1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
|
class Tearing : public Scene
{
public:
Tearing(const char* name) : Scene(name) {}
~Tearing()
{
NvFlexExtDestroyTearingCloth(mCloth);
}
void Initialize()
{
Mesh* mesh = ImportMesh(GetFilePathByPlatform("../../data/irregular_plane.obj").c_str());
mesh->Transform(RotationMatrix(kPi, Vec3(0.0f, 1.0f, 0.0f))*RotationMatrix(kPi*0.5f, Vec3(1.0f, 0.0f, 0.0f))*ScaleMatrix(2.0f));
Vec3 lower, upper;
mesh->GetBounds(lower, upper);
float radius = 0.065f;
int phase = NvFlexMakePhase(0, eNvFlexPhaseSelfCollide | eNvFlexPhaseSelfCollideFilter);
for (size_t i = 0; i < mesh->GetNumVertices(); ++i)
{
Vec3 p = Vec3(mesh->m_positions[i]);
float invMass = 1.0f;
if (p.y == upper.y)
invMass = 0.0f;
p += Vec3(0.0f, 1.5f, 0.0f);
g_buffers->positions.push_back(Vec4(p.x, p.y, p.z, invMass));
g_buffers->velocities.push_back(0.0f);
g_buffers->phases.push_back(phase);
}
g_numExtraParticles = 1000;
mCloth = NvFlexExtCreateTearingClothFromMesh((float*)&g_buffers->positions[0], int(g_buffers->positions.size()), int(g_buffers->positions.size()) + g_numExtraParticles, (int*)&mesh->m_indices[0], mesh->GetNumFaces(), 0.8f, 0.8f, 0.0f);
g_buffers->triangles.assign((int*)&mesh->m_indices[0], mesh->m_indices.size());
g_buffers->triangleNormals.resize(mesh->GetNumFaces(), Vec3(0.0f, 0.0f, 1.0f));
g_buffers->springIndices.assign(mCloth->springIndices, mCloth->numSprings * 2);
g_buffers->springStiffness.assign(mCloth->springCoefficients, mCloth->numSprings);
g_buffers->springLengths.assign(mCloth->springRestLengths, mCloth->numSprings);
g_params.radius = radius;
g_params.dynamicFriction = 0.025f;
g_params.dissipation = 0.0f;
g_params.numIterations = 16;
g_params.particleCollisionMargin = g_params.radius*0.05f;
g_params.relaxationFactor = 1.0f;
g_params.drag = 0.03f;
g_params.relaxationMode = eNvFlexRelaxationGlobal;
g_params.relaxationFactor = 0.35f;
g_numSubsteps = 2;
g_pause = false;
// draw options
g_drawPoints = false;
}
void Update()
{
g_params.wind[0] = 0.1f;
g_params.wind[1] = 0.1f;
g_params.wind[2] = -0.2f;
g_windStrength = 6.0f;
const float maxStrain = 3.0f;
const int maxCopies = 2048;
const int maxEdits = 2048;
NvFlexExtTearingParticleClone particleCopies[maxCopies];
int numParticleCopies;
NvFlexExtTearingMeshEdit triangleEdits[maxEdits];
int numTriangleEdits;
// update asset's copy of the particles
memcpy(mCloth->particles, &g_buffers->positions[0], sizeof(Vec4)*g_buffers->positions.size());
NvFlexExtTearClothMesh(mCloth, maxStrain, 4, particleCopies, &numParticleCopies, maxCopies, triangleEdits, &numTriangleEdits, maxEdits);
// copy particles
for (int i = 0; i < numParticleCopies; ++i)
{
const int srcIndex = particleCopies[i].srcIndex;
const int destIndex = particleCopies[i].destIndex;
g_buffers->positions[destIndex] = Vec4(Vec3(g_buffers->positions[srcIndex]), 1.0f); // override mass because picked particle has inf. mass
g_buffers->restPositions[destIndex] = g_buffers->restPositions[srcIndex];
g_buffers->velocities[destIndex] = g_buffers->velocities[srcIndex];
g_buffers->phases[destIndex] = g_buffers->phases[srcIndex];
g_buffers->activeIndices.push_back(destIndex);
}
// apply triangle modifications to index buffer
for (int i = 0; i < numTriangleEdits; ++i)
{
const int index = triangleEdits[i].triIndex;
const int newValue = triangleEdits[i].newParticleIndex;
g_buffers->triangles[index] = newValue;
}
mCloth->numParticles += numParticleCopies;
// update constraints
g_buffers->springIndices.assign(mCloth->springIndices, mCloth->numSprings * 2);
g_buffers->springStiffness.assign(mCloth->springCoefficients, mCloth->numSprings);
g_buffers->springLengths.assign(mCloth->springRestLengths, mCloth->numSprings);
}
virtual void Sync()
{
// update solver data not already updated in the main loop
NvFlexSetSprings(g_solver, g_buffers->springIndices.buffer, g_buffers->springLengths.buffer, g_buffers->springStiffness.buffer, g_buffers->springLengths.size());
NvFlexSetDynamicTriangles(g_solver, g_buffers->triangles.buffer, g_buffers->triangleNormals.buffer, g_buffers->triangles.size() / 3);
NvFlexSetRestParticles(g_solver, g_buffers->restPositions.buffer, NULL);
}
NvFlexExtAsset* mCloth;
};
|