aboutsummaryrefslogtreecommitdiff
path: root/extensions/flexExtContainer.cpp
diff options
context:
space:
mode:
authorMiles Macklin <[email protected]>2018-03-19 15:10:24 +1300
committerMiles Macklin <[email protected]>2018-03-19 15:10:24 +1300
commit8ee05c79ae1748ef132a12e4fb0af284899faec6 (patch)
tree82bd5aa1892e28ce7886b6cfeafe66a47ff38e67 /extensions/flexExtContainer.cpp
parentFlex 1.2 (beta 2) (diff)
downloadflex-8ee05c79ae1748ef132a12e4fb0af284899faec6.tar.xz
flex-8ee05c79ae1748ef132a12e4fb0af284899faec6.zip
Flex 1.2.0 release
Diffstat (limited to 'extensions/flexExtContainer.cpp')
-rw-r--r--extensions/flexExtContainer.cpp173
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();
+}
+