void DeformableMesh::generateConstraintsFromTriangles() { PxU32 numTriangles = mPrimitives.size() / 3; DeformableTriEdge e; Ps::Array<DeformableTriEdge> edges PX_DEBUG_EXP("defoMeshEdges"); edges.reserve(numTriangles * 3); const PxU32 *i0 = mPrimitives.begin(); for (PxU32 i = 0; i < numTriangles; i++, i0 += 3) { const PxU32 *i1 = i0+1; const PxU32 *i2 = i0+2; e.set(mVertexToParticleMap[*i0], mVertexToParticleMap[*i1], mVertexToParticleMap[*i2], i); edges.pushBack(e); e.set(mVertexToParticleMap[*i1], mVertexToParticleMap[*i2], mVertexToParticleMap[*i0], i); edges.pushBack(e); e.set(mVertexToParticleMap[*i2], mVertexToParticleMap[*i0], mVertexToParticleMap[*i1], i); edges.pushBack(e); } quickSortEdges(edges, 0, edges.size()-1); DeformableConstraint constraint; constraint.particleId[4] = -1; // only used when torn constraint.particleId[5] = -1; // only used when torn for(PxU32 i=0; i<edges.size(); ) { const DeformableTriEdge &e0 = edges[i]; PxU32 p0 = constraint.particleId[0] = e0.particleId[0]; PxU32 p1 = constraint.particleId[1] = e0.particleId[1]; PxVec3 d0 = mWeldedVertices[p1] - mWeldedVertices[p0]; constraint.stretchingRestLength = d0.magnitude(); constraint.particleId[2] = e0.third; constraint.particleId[3] = -1; // for border edges -> no bending possible constraint.bendingRestLength = 0.0f; constraint.flags = 0; if (++i < edges.size()) { const DeformableTriEdge &e1 = edges[i]; if (e0 == e1) { constraint.particleId[2] = e0.third; constraint.particleId[3] = e1.third; PxVec3 d1 = mWeldedVertices[e1.third] - mWeldedVertices[e0.third]; constraint.bendingRestLength = d1.magnitude(); } while (i < edges.size() && edges[i] == e0) ++i; } mConstraints.pushBack(constraint); } }
void DeformableMesh::generateConstraintsFromTetrahedra() { PxU32 edgeIndices[6][2] = { {0,1}, {0,2}, {0,3}, {1,2}, {1,3}, {2,3} }; PxU32 *tetIndices; // - tetrahedra are assumed to be unique (thus no parent code here) PxU32 numTetrahedra = mPrimitives.size() / 4; DeformableTetraEdge e; Ps::Array<DeformableTetraEdge> edges PX_DEBUG_EXP("defoMeshEdges2"); edges.reserve(numTetrahedra * 6); tetIndices = mPrimitives.begin(); PxU32 i, j; for (i = 0; i < numTetrahedra; i++, tetIndices += 4) { for(j = 0; j < 6; j++) { PxU32 e0 = mVertexToParticleMap[tetIndices[edgeIndices[j][0]]]; PxU32 e1 = mVertexToParticleMap[tetIndices[edgeIndices[j][1]]]; e.set(e0, e1, i); edges.pushBack(e); } } quickSortTetraEdges(edges, 0, edges.size()-1); mConstraints.resize(numTetrahedra); DeformableConstraint constraint; DeformableTetraEdge *tetEdges[6]; tetIndices = mPrimitives.begin(); bool warningIssued = false; for (i = 0; i < numTetrahedra; i++, tetIndices += 4) { for (j = 0; j < 6; j++) { PxU32 e0 = mVertexToParticleMap[tetIndices[edgeIndices[j][0]]]; PxU32 e1 = mVertexToParticleMap[tetIndices[edgeIndices[j][1]]]; DeformableTetraEdge goalEdge; goalEdge.set(e0, e1, i); tetEdges[j] = binarySearchTetraEdge(edges, goalEdge); } for (j = 0; j < 4; j++) constraint.particleId[j] = mVertexToParticleMap[tetIndices[j]]; PxVec3 groundArea = (mWeldedVertices[tetIndices[1]] - mWeldedVertices[tetIndices[0]]).cross(mWeldedVertices[tetIndices[2]] - mWeldedVertices[tetIndices[0]]); constraint.restVolume = groundArea.dot(mWeldedVertices[tetIndices[3]] - mWeldedVertices[tetIndices[0]]); constraint.flags = 0; if (!warningIssued && constraint.restVolume < 0.0f) { Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "Soft body mesh tetrahedron %d has illegal winding order.", i); warningIssued = true; } for (j = 0; j < 6; j++) { PxU32 e0 = mVertexToParticleMap[tetIndices[edgeIndices[j][0]]]; PxU32 e1 = mVertexToParticleMap[tetIndices[edgeIndices[j][1]]]; PxVec3 edgeVec = mWeldedVertices[e1] - mWeldedVertices[e0]; if(tetEdges[j]) { PX_ASSERT(tetEdges[j]->tetrahedron == i); constraint.restEdgeLengths[j] = edgeVec.magnitude(); } else constraint.restEdgeLengths[j] = -edgeVec.magnitude(); } mConstraints[i] = constraint; } }