aboutsummaryrefslogtreecommitdiff
path: root/NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp
diff options
context:
space:
mode:
authorMarijn Tamis <[email protected]>2018-05-03 18:22:48 +0200
committerMarijn Tamis <[email protected]>2018-05-03 18:22:48 +0200
commitca32c59a58d37c1822e185a2d5f3d0d3e8943593 (patch)
treeb06b9eec03f34344ef8fc31aa147b2714d3962ee /NvCloth/samples/SampleBase/utils/ClothMeshGenerator.cpp
parentForced rename of platform folders in cmake dir. Git didn't pick this up before. (diff)
downloadnvcloth-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.cpp217
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)
{