diff options
| author | Miles Macklin <[email protected]> | 2018-03-19 15:10:24 +1300 |
|---|---|---|
| committer | Miles Macklin <[email protected]> | 2018-03-19 15:10:24 +1300 |
| commit | 8ee05c79ae1748ef132a12e4fb0af284899faec6 (patch) | |
| tree | 82bd5aa1892e28ce7886b6cfeafe66a47ff38e67 /extensions/flexExtContainer.cpp | |
| parent | Flex 1.2 (beta 2) (diff) | |
| download | flex-8ee05c79ae1748ef132a12e4fb0af284899faec6.tar.xz flex-8ee05c79ae1748ef132a12e4fb0af284899faec6.zip | |
Flex 1.2.0 release
Diffstat (limited to 'extensions/flexExtContainer.cpp')
| -rw-r--r-- | extensions/flexExtContainer.cpp | 173 |
1 files changed, 173 insertions, 0 deletions
diff --git a/extensions/flexExtContainer.cpp b/extensions/flexExtContainer.cpp index 60d0230..b96f73c 100644 --- a/extensions/flexExtContainer.cpp +++ b/extensions/flexExtContainer.cpp @@ -96,6 +96,8 @@ struct NvFlexExtContainer std::vector<int> mFreeList; std::vector<NvFlexExtInstance*> mInstances; + std::vector<NvFlexExtSoftJoint*> mSoftJoints; + // particles NvFlexVector<Vec4> mParticles; NvFlexVector<Vec4> mParticlesRest; @@ -188,6 +190,15 @@ void CompactObjects(NvFlexExtContainer* c) } } + // each joint corresponds to one shape matching constraint + for (size_t i = 0; i < c->mSoftJoints.size(); ++i) + { + const NvFlexExtSoftJoint* joint = c->mSoftJoints[i]; + + totalNumShapeIndices += joint->numParticles; + ++totalNumShapes; + } + //---------------------- // map buffers @@ -391,6 +402,33 @@ void CompactObjects(NvFlexExtContainer* c) } + // go through each joint and add shape matching constraint to the solver + for (size_t i = 0; i < c->mSoftJoints.size(); ++i) + { + NvFlexExtSoftJoint* joint = c->mSoftJoints[i]; + const int numJointParticles = joint->numParticles; + + // store start index into shape array + joint->shapeIndex = shapeIndex; + + const int offset = dstShapeOffsets[shapeIndex - 1]; + dstShapeOffsets[shapeIndex] = offset + numJointParticles; + + for (int i = 0; i < numJointParticles; ++i) + { + dstShapeIndices[shapeIndexOffset] = joint->particleIndices[i]; + dstShapeRestPositions[shapeIndexOffset] = Vec3(joint->particleLocalPositions[3 * i + 0], joint->particleLocalPositions[3 * i + 1], joint->particleLocalPositions[3 * i + 2]); + + ++shapeIndexOffset; + } + + dstShapeTranslations[shapeIndex] = Vec3(joint->shapeTranslations); + dstShapeRotations[shapeIndex] = Quat(joint->shapeRotations); + dstShapeCoefficients[shapeIndex] = joint->stiffness; + + ++shapeIndex; + } + //---------------------- // unmap buffers @@ -825,6 +863,60 @@ void NvFlexExtUpdateInstances(NvFlexExtContainer* c) } } + for (int i = 0; i < int(c->mSoftJoints.size()); ++i) + { + NvFlexExtSoftJoint* joint = c->mSoftJoints[i]; + + const int shapeStart = joint->shapeIndex; + + // Here we compute the COM only once instead of in NvFlexExtCreateSoftJoint() to avoid buffer mapping issue + if (!joint->initialized) + { + // Calculate the center of mass of the new shape matching constraint given a set of joint particles and its indices + // To improve the accuracy of the result, first transform the particlePosition to relative coordinates (by finding the mean and subtracting that from all positions) + // Note: If this is not done, one might see ghost forces if the mean of the particlePosition is far from the origin. + Vec3 shapeOffset(0.0f); + for (int i = 0; i < joint->numParticles; ++i) + { + const Vec4 particlePosition = c->mParticles[joint->particleIndices[i]]; + shapeOffset += Vec3(particlePosition); + } + shapeOffset /= float(joint->numParticles); + + Vec3 com; + for (int i = 0; i < joint->numParticles; ++i) + { + const Vec4 particlePosition = c->mParticles[joint->particleIndices[i]]; + + // By subtracting shapeOffset the calculation is done in relative coordinates + com += Vec3(particlePosition) - shapeOffset; + } + com /= float(joint->numParticles); + + // Add the shapeOffset to switch back to absolute coordinates + com += shapeOffset; + + // update per-joint shapeTranslations and copy to the container's memory + joint->shapeTranslations[0] = com.x; + joint->shapeTranslations[1] = com.y; + joint->shapeTranslations[2] = com.z; + + joint->initialized = true; // Complete joint initilization process + } + else + { + joint->shapeTranslations[0] = c->mShapeTranslations[shapeStart].x; + joint->shapeTranslations[1] = c->mShapeTranslations[shapeStart].y; + joint->shapeTranslations[2] = c->mShapeTranslations[shapeStart].z; + } + + // copy data back to per-joint memory from the container's memory + joint->shapeRotations[0] = c->mShapeRotations[shapeStart].x; + joint->shapeRotations[1] = c->mShapeRotations[shapeStart].y; + joint->shapeRotations[2] = c->mShapeRotations[shapeStart].z; + joint->shapeRotations[3] = c->mShapeRotations[shapeStart].w; + } + c->mShapeTranslations.unmap(); c->mShapeRotations.unmap(); } @@ -846,4 +938,85 @@ void NvFlexExtDestroyAsset(NvFlexExtAsset* asset) delete asset; } +NvFlexExtSoftJoint* NvFlexExtCreateSoftJoint(NvFlexExtContainer* c, const int* particleIndices, const float* particleLocalPositions, const int numJointParticles, const float stiffness) +{ + NvFlexExtSoftJoint* joint = new NvFlexExtSoftJoint(); + + joint->particleIndices = new int[numJointParticles]; + memcpy(joint->particleIndices, particleIndices, sizeof(int) * numJointParticles); + + joint->particleLocalPositions = new float[3 * numJointParticles]; + memcpy(joint->particleLocalPositions, particleLocalPositions, 3 * sizeof(float)*numJointParticles); + + // initialize with Quat() + joint->shapeRotations[0] = Quat().x; + joint->shapeRotations[1] = Quat().y; + joint->shapeRotations[2] = Quat().z; + joint->shapeRotations[3] = Quat().w; + + joint->numParticles = numJointParticles; + joint->stiffness = stiffness; + joint->initialized = false; // Initialization will be fully completed in NvFlexExtUpdateInstances() + + c->mSoftJoints.push_back(joint); + + // mark container as dirty + c->mNeedsCompact = true; + + return joint; +} + +void NvFlexExtDestroySoftJoint(NvFlexExtContainer* c, NvFlexExtSoftJoint* joint) +{ + delete[] joint->particleIndices; + delete[] joint->particleLocalPositions; + + // TODO: O(N) remove + std::vector<NvFlexExtSoftJoint*>::iterator iter = std::find(c->mSoftJoints.begin(), c->mSoftJoints.end(), joint); + assert(iter != c->mSoftJoints.end()); + c->mSoftJoints.erase(iter); + + c->mNeedsCompact = true; + + delete joint; +} + +void NvFlexExtSoftJointSetTransform(NvFlexExtContainer* c, NvFlexExtSoftJoint* joint, const float* newPosition, const float* newRotation) +{ + // calculate transform from old position to new position + Matrix44 LocalFromOld = AffineInverse(TranslationMatrix(Point3(joint->shapeTranslations))*RotationMatrix(joint->shapeRotations)); + Matrix44 NewFromLocal = TranslationMatrix(Point3(newPosition))*RotationMatrix(newRotation); + Matrix44 transform = NewFromLocal*LocalFromOld; + + // transform soft joint particles to new location + + //---------------------- + // map buffers + c->mParticles.map(); + + for (int i = 0; i < joint->numParticles; ++i) + { + const Vec3 particlePosition = Vec3(c->mParticles[joint->particleIndices[i]]); + Vec4 particleNewPostion = transform * Vec4(particlePosition, 1.0f); + + // update soft joint particles + c->mParticles[joint->particleIndices[i]].x = particleNewPostion.x; + c->mParticles[joint->particleIndices[i]].y = particleNewPostion.y; + c->mParticles[joint->particleIndices[i]].z = particleNewPostion.z; + } + + joint->shapeTranslations[0] = newPosition[0]; + joint->shapeTranslations[1] = newPosition[1]; + joint->shapeTranslations[2] = newPosition[2]; + + joint->shapeRotations[0] = newRotation[0]; + joint->shapeRotations[1] = newRotation[1]; + joint->shapeRotations[2] = newRotation[2]; + joint->shapeRotations[3] = newRotation[3]; + + //---------------------- + // unmap buffers + c->mParticles.unmap(); +} + |