diff options
| author | Marijn Tamis <[email protected]> | 2018-05-03 18:22:48 +0200 |
|---|---|---|
| committer | Marijn Tamis <[email protected]> | 2018-05-03 18:22:48 +0200 |
| commit | ca32c59a58d37c1822e185a2d5f3d0d3e8943593 (patch) | |
| tree | b06b9eec03f34344ef8fc31aa147b2714d3962ee /NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp | |
| parent | Forced rename of platform folders in cmake dir. Git didn't pick this up before. (diff) | |
| download | nvcloth-ca32c59a58d37c1822e185a2d5f3d0d3e8943593.tar.xz nvcloth-ca32c59a58d37c1822e185a2d5f3d0d3e8943593.zip | |
NvCloth 1.1.4 Release. (24070740)
Diffstat (limited to 'NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp')
| -rw-r--r-- | NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp | 217 |
1 files changed, 203 insertions, 14 deletions
diff --git a/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp b/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp index 495ba15..a0c0d3a 100644 --- a/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp +++ b/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp @@ -10,6 +10,25 @@ #include "ClothMeshGenerator.h" +#include "PsMathUtils.h" + +#include <fstream> +#include <iterator> +#include <algorithm> +#include <assert.h> + +namespace +{ + template<typename T> + std::vector<T> readValuesFromFile(const std::string& path) + { + std::ifstream inputFile(path); + std::vector<T> data{ std::istream_iterator<T>{inputFile}, { } }; + return std::move(data); + } +} // end of anonymous namespace + + void ClothMeshData::Clear() { mVertices.clear(); @@ -34,8 +53,6 @@ GeneratePlaneCloth(x,y,2,2) generates: */ -// Submesh submesh; - Clear(); mVertices.resize((segmentsX + 1) * (segmentsY + 1)); mInvMasses.resize((segmentsX + 1) * (segmentsY + 1)); @@ -144,6 +161,90 @@ GeneratePlaneCloth(x,y,2,2) generates: } } +void ClothMeshData::GenerateCylinderWave(float radiusTop, float radiusBottom, float height, float frequency, float ampitudeTop, float ampitudeBottom, int segmentsX, int segmentsY, physx::PxMat44 transform, bool attachTop, bool attachBottom, bool createQuads, int missingXsegments) +{ + Clear(); + int particleXsegments = segmentsX - std::max(0, missingXsegments - 1); + int triangleXsegments = segmentsX - missingXsegments; + assert(missingXsegments < segmentsX); + mVertices.resize((particleXsegments + 0) * (segmentsY + 1)); + mInvMasses.resize((particleXsegments + 0) * (segmentsY + 1)); + mTriangles.resize(triangleXsegments * segmentsY * 2); + if (createQuads) + mQuads.resize(triangleXsegments * segmentsY); + + mMesh.vertices.resize(mVertices.size()); + mMesh.indices.resize(3 * mTriangles.size()); + + float slopeX; + float slopeY; + { + float y = height; + float x = radiusBottom - radiusTop; + float l = sqrtf(x*x + y*y); + slopeY = x / l; + slopeX = y / l; + } + + // Vertices + for (int y = 0; y < segmentsY + 1; y++) + { + float h = height - (float)y / (float)segmentsY * height - 0.5f*height; + float ynorm = (float)y / (float)(segmentsY - 1); + float w = ynorm; + float r = radiusBottom * w + (1.0f - w) * radiusTop; + for (int x = 0; x < particleXsegments; x++) + { + float theta = (float)x / (float)segmentsX * physx::PxTwoPi; + float rw = r + cosf(frequency*theta)*(ampitudeBottom * w + (1.0f - w) * ampitudeTop); + mVertices[x + y * particleXsegments] = transform.transform(physx::PxVec3(sinf(theta)*rw, h, cosf(theta)*rw)); + mInvMasses[x + y * particleXsegments] = (y == 0 && attachTop || y == segmentsY && attachBottom) ? 0.0f : 1.0f; + + mMesh.vertices[x + y * particleXsegments].position = mVertices[x + y * particleXsegments]; + mMesh.vertices[x + y * particleXsegments].uv = physx::PxVec2((float)x / (float)particleXsegments, (float)y / (float)segmentsY); + // Not the correct normal, but we recalculate it anyway when updating the cloth mesh + mMesh.vertices[x + y * particleXsegments].normal = physx::PxVec3(cosf(theta)*slopeX, slopeY, -sinf(theta)*slopeX); + } + } + + if (createQuads) + { + // Quads + for (int y = 0; y < segmentsY; y++) + { + for (int x = 0; x < triangleXsegments; x++) + { + mQuads[(x + y * triangleXsegments)] = Quad((uint32_t)(x + 0) + (y + 0) * (particleXsegments), + (uint32_t)((x + 1) % particleXsegments) + (y + 0) * (particleXsegments), + (uint32_t)((x + 1) % particleXsegments) + (y + 1) * (particleXsegments), + (uint32_t)((x + 0) % particleXsegments) + (y + 1) * (particleXsegments)); + } + } + } + + // Triangles + for (int y = 0; y < segmentsY; y++) + { + for (int x = 0; x < triangleXsegments; x++) + { + mTriangles[(x + y * triangleXsegments) * 2 + 0] = Triangle((uint32_t)((x + 1) % particleXsegments) + (y + 1) * (particleXsegments), + (uint32_t)((x + 1) % particleXsegments) + (y + 0) * (particleXsegments), + (uint32_t)(x + 0) + (y + 0) * (particleXsegments)); + + mTriangles[(x + y * triangleXsegments) * 2 + 1] = Triangle((uint32_t)((x + 0) % particleXsegments) + (y + 1) * (particleXsegments), + (uint32_t)((x + 1) % particleXsegments) + (y + 1) * (particleXsegments), + (uint32_t)(x + 0) + (y + 0) * (particleXsegments)); + } + } + + for (int i = 0; i < (int)mTriangles.size(); i++) + { + mMesh.indices[3 * i + 0] = mTriangles[i].a; + mMesh.indices[3 * i + 1] = mTriangles[i].b; + mMesh.indices[3 * i + 2] = mTriangles[i].c; + } +} + void ClothMeshData::AttachClothPlaneByAngles(int segmentsX, int segmentsY, bool attachByWidth) { for (int y = 0; y < segmentsY + 1; y++) @@ -161,6 +262,105 @@ void ClothMeshData::AttachClothPlaneBySide(int segmentsX, int segmentsY, bool at mInvMasses[x + y * (segmentsX + 1)] = 0.0f; } +void ClothMeshData::AttachClothUsingTopVertices(float thresholdY) +{ + int topVertexIndex = -1; + physx::PxVec3 topVertex(-1e30f, -1e30f, -1e30f); + + for (int i = 0; i < (int)mVertices.size(); ++i) + { + if (mVertices[i].y > topVertex.y) + { + topVertex = mVertices[i]; + topVertexIndex = i; + } + } + NV_CLOTH_ASSERT(topVertexIndex >= 0); + + for (int i = 0; i < (int)mVertices.size(); ++i) + { + if (topVertex.y - mVertices[i].y < thresholdY) + { + mInvMasses[i] = 0.0f; + } + } +} + +bool ClothMeshData::ReadClothFromFile(const std::string& verticesPath, const std::string& indicesPath, physx::PxMat44 transform) +{ + std::vector<float> verticesXYZ = readValuesFromFile<float>(verticesPath); + std::vector<uint32_t> indices = readValuesFromFile<uint32_t>(indicesPath); + + if(verticesXYZ.size() < 3*3 || indices.size() < 3) + return false; + + return InitializeFromData<float,uint32_t>(ToBoundedData(verticesXYZ), ToBoundedData(indices), transform); +} + +template<typename PositionType, typename IndexType> +bool ClothMeshData::InitializeFromData(nv::cloth::BoundedData positions, nv::cloth::BoundedData indices, physx::PxMat44 transform) +{ + if(positions.count < 3 || indices.count < 3) + return false; + + NV_CLOTH_ASSERT(sizeof(PositionType) != physx::PxVec3 || positions.count % 3 == 0); + NV_CLOTH_ASSERT(indices.count % 3 == 0); + + auto numVertices = (sizeof(PositionType) == sizeof(physx::PxVec3)) ? positions.count : positions.count / 3; + const auto numTriangles = indices.count / 3; + + Clear(); + mVertices.resize(numVertices); + mInvMasses.resize(numVertices); + mTriangles.resize(numTriangles); + + // Quads not supported yet + //mQuads.resize(numTriangles / 2); + + mMesh.vertices.resize(mVertices.size()); + mMesh.indices.resize(3 * mTriangles.size()); + + for(int i = 0; i < (int)numVertices; ++i) + { + physx::PxVec3 pos; + if(sizeof(PositionType) == sizeof(physx::PxVec3)) + pos = positions.at<physx::PxVec3>(i); + else + pos = physx::PxVec3(positions.at<float>(i * 3), positions.at<float>(i * 3 + 1), positions.at<float>(i * 3 + 2)); + + pos = transform.transform(pos); + + mVertices[i] = pos; + mInvMasses[i] = 1.0f; + + mMesh.vertices[i].position = pos; + mMesh.vertices[i].normal = transform.transform(physx::PxVec3(0.f, 1.f, 0.f)); // TODO + mMesh.vertices[i].uv = physx::PxVec2(0.0f, 0.0f); // TODO + } + + for(int i = 0; i < (int)numTriangles; ++i) + { + mTriangles[i] = Triangle( + indices.at<IndexType>(i * 3), + indices.at<IndexType>(i * 3 + 1), + indices.at<IndexType>(i * 3 + 2) + ); + } + + for(int i = 0; i < (int)numTriangles; i++) + { + mMesh.indices[3 * i + 0] = mTriangles[i].a; + mMesh.indices[3 * i + 1] = mTriangles[i].b; + mMesh.indices[3 * i + 2] = mTriangles[i].c; + } + + return true; +} +template bool ClothMeshData::InitializeFromData<float,uint16_t>(nv::cloth::BoundedData positions, nv::cloth::BoundedData indices, physx::PxMat44 transform); +template bool ClothMeshData::InitializeFromData<float,uint32_t>(nv::cloth::BoundedData positions, nv::cloth::BoundedData indices, physx::PxMat44 transform); +template bool ClothMeshData::InitializeFromData<physx::PxVec3,uint16_t>(nv::cloth::BoundedData positions, nv::cloth::BoundedData indices, physx::PxMat44 transform); +template bool ClothMeshData::InitializeFromData<physx::PxVec3,uint32_t>(nv::cloth::BoundedData positions, nv::cloth::BoundedData indices, physx::PxMat44 transform); + void ClothMeshData::SetInvMasses(float invMass) { // Doesn't modify attached vertices @@ -178,17 +378,6 @@ void ClothMeshData::SetInvMassesFromDensity(float density) mInvMasses[i] = 1.f / density; } -template <typename T> -nv::cloth::BoundedData ToBoundedData(T& vector) -{ - nv::cloth::BoundedData d; - d.data = &vector[0]; - d.stride = sizeof(vector[0]); - d.count = (physx::PxU32)vector.size(); - - return d; -} - nv::cloth::ClothMeshDesc ClothMeshData::GetClothMeshDesc() { nv::cloth::ClothMeshDesc d; @@ -218,7 +407,7 @@ void ClothMeshData::Merge(const ClothMeshData& other) mUvs.insert(mUvs.end(), other.mUvs.begin(), other.mUvs.end()); mInvMasses.insert(mInvMasses.end(), other.mInvMasses.begin(), other.mInvMasses.end()); - mMesh.vertices.insert(mMesh.vertices.end(), mMesh.vertices.begin(), mMesh.vertices.end()); + mMesh.vertices.insert(mMesh.vertices.end(), other.mMesh.vertices.begin(), other.mMesh.vertices.end()); for(const auto& t : other.mTriangles) { |