|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#include <vector> |
|
|
#include <limits> |
|
|
#include <algorithm> |
|
|
|
|
|
#include "../core/core.h" |
|
|
#include "../core/maths.h" |
|
|
|
|
|
#include "../include/NvFlex.h" |
|
|
#include "../include/NvFlexExt.h" |
|
|
|
|
|
class Bitmap |
|
|
{ |
|
|
public: |
|
|
|
|
|
typedef unsigned int Word; |
|
|
|
|
|
static const int kWordSize = sizeof(Word)*8; |
|
|
|
|
|
Bitmap(int numBits) : mBits((numBits+kWordSize-1)/kWordSize) |
|
|
{ |
|
|
} |
|
|
|
|
|
inline void Set(int bit) |
|
|
{ |
|
|
const int wordIndex = bit/kWordSize; |
|
|
const int bitIndex = bit&(kWordSize-1); |
|
|
|
|
|
const Word word = mBits[wordIndex]; |
|
|
|
|
|
mBits[wordIndex] = word|(1<<bitIndex); |
|
|
} |
|
|
|
|
|
inline void Reset(int bit) |
|
|
{ |
|
|
const int wordIndex = bit/kWordSize; |
|
|
const int bitIndex = bit&(kWordSize-1); |
|
|
|
|
|
const Word word = mBits[wordIndex]; |
|
|
|
|
|
mBits[wordIndex] = word&~(1<<bitIndex); |
|
|
} |
|
|
|
|
|
inline bool IsSet(int bit) |
|
|
{ |
|
|
const int wordIndex = bit/kWordSize; |
|
|
const int bitIndex = bit&(kWordSize-1); |
|
|
|
|
|
const Word word = mBits[wordIndex]; |
|
|
|
|
|
return (word & (1<<bitIndex)) != 0; |
|
|
} |
|
|
|
|
|
private: |
|
|
|
|
|
std::vector<Word> mBits; |
|
|
}; |
|
|
|
|
|
|
|
|
struct NvFlexExtContainer |
|
|
{ |
|
|
int mMaxParticles; |
|
|
|
|
|
NvFlexSolver* mSolver; |
|
|
NvFlexLibrary* mFlexLib; |
|
|
|
|
|
|
|
|
NvFlexVector<int> mActiveList; |
|
|
|
|
|
std::vector<int> mFreeList; |
|
|
std::vector<NvFlexExtInstance*> mInstances; |
|
|
|
|
|
std::vector<NvFlexExtSoftJoint*> mSoftJoints; |
|
|
|
|
|
|
|
|
NvFlexVector<Vec4> mParticles; |
|
|
NvFlexVector<Vec4> mParticlesRest; |
|
|
NvFlexVector<Vec3> mVelocities; |
|
|
NvFlexVector<int> mPhases; |
|
|
NvFlexVector<Vec4> mNormals; |
|
|
|
|
|
|
|
|
NvFlexVector<int> mShapeOffsets; |
|
|
NvFlexVector<int> mShapeIndices; |
|
|
NvFlexVector<float> mShapeCoefficients; |
|
|
NvFlexVector<float> mShapePlasticThresholds; |
|
|
NvFlexVector<float> mShapePlasticCreeps; |
|
|
NvFlexVector<Quat> mShapeRotations; |
|
|
NvFlexVector<Vec3> mShapeTranslations; |
|
|
NvFlexVector<Vec3> mShapeRestPositions; |
|
|
|
|
|
|
|
|
NvFlexVector<int> mSpringIndices; |
|
|
NvFlexVector<float> mSpringLengths; |
|
|
NvFlexVector<float> mSpringCoefficients; |
|
|
|
|
|
|
|
|
NvFlexVector<int> mTriangleIndices; |
|
|
NvFlexVector<Vec3> mTriangleNormals; |
|
|
|
|
|
NvFlexVector<int> mInflatableStarts; |
|
|
NvFlexVector<int> mInflatableCounts; |
|
|
NvFlexVector<float> mInflatableRestVolumes; |
|
|
NvFlexVector<float> mInflatableCoefficients; |
|
|
NvFlexVector<float> mInflatableOverPressures; |
|
|
|
|
|
|
|
|
NvFlexVector<Vec3> mBoundsLower; |
|
|
NvFlexVector<Vec3> mBoundsUpper; |
|
|
|
|
|
|
|
|
bool mNeedsCompact; |
|
|
|
|
|
bool mNeedsActiveListRebuild; |
|
|
|
|
|
NvFlexExtContainer(NvFlexLibrary* l) : |
|
|
mMaxParticles(0), mSolver(NULL), mFlexLib(l), |
|
|
mActiveList(l),mParticles(l),mParticlesRest(l),mVelocities(l), |
|
|
mPhases(l),mNormals(l),mShapeOffsets(l),mShapeIndices(l), |
|
|
mShapeCoefficients(l),mShapePlasticThresholds(l), |
|
|
mShapePlasticCreeps(l),mShapeRotations(l),mShapeTranslations(l), |
|
|
mShapeRestPositions(l),mSpringIndices(l),mSpringLengths(l), |
|
|
mSpringCoefficients(l),mTriangleIndices(l),mTriangleNormals(l), |
|
|
mInflatableStarts(l),mInflatableCounts(l),mInflatableRestVolumes(l), |
|
|
mInflatableCoefficients(l),mInflatableOverPressures(l), mBoundsLower(l), mBoundsUpper(l), |
|
|
mNeedsCompact(false), mNeedsActiveListRebuild(false) |
|
|
{} |
|
|
}; |
|
|
|
|
|
|
|
|
|
|
|
namespace |
|
|
{ |
|
|
|
|
|
|
|
|
void CompactObjects(NvFlexExtContainer* c) |
|
|
{ |
|
|
int totalNumSprings = 0; |
|
|
int totalNumTris = 0; |
|
|
int totalNumShapes = 0; |
|
|
int totalNumShapeIndices = 0; |
|
|
|
|
|
bool plasticDeformation = false; |
|
|
|
|
|
|
|
|
for (size_t i = 0; i < c->mInstances.size(); ++i) |
|
|
{ |
|
|
NvFlexExtInstance* inst = c->mInstances[i]; |
|
|
|
|
|
const NvFlexExtAsset* asset = inst->asset; |
|
|
|
|
|
|
|
|
inst->triangleIndex = totalNumTris; |
|
|
|
|
|
totalNumSprings += asset->numSprings; |
|
|
totalNumTris += asset->numTriangles; |
|
|
|
|
|
totalNumShapeIndices += asset->numShapeIndices; |
|
|
totalNumShapes += asset->numShapes; |
|
|
|
|
|
if (asset->shapePlasticThresholds && asset->shapePlasticCreeps) |
|
|
{ |
|
|
plasticDeformation = true; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
for (size_t i = 0; i < c->mSoftJoints.size(); ++i) |
|
|
{ |
|
|
const NvFlexExtSoftJoint* joint = c->mSoftJoints[i]; |
|
|
|
|
|
totalNumShapeIndices += joint->numParticles; |
|
|
++totalNumShapes; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c->mSpringIndices.map(); |
|
|
c->mSpringLengths.map(); |
|
|
c->mSpringCoefficients.map(); |
|
|
|
|
|
|
|
|
c->mTriangleIndices.map(); |
|
|
c->mTriangleNormals.map(); |
|
|
|
|
|
|
|
|
c->mInflatableStarts.map(); |
|
|
c->mInflatableCounts.map(); |
|
|
c->mInflatableRestVolumes.map(); |
|
|
c->mInflatableCoefficients.map(); |
|
|
c->mInflatableOverPressures.map(); |
|
|
|
|
|
|
|
|
c->mShapeIndices.map(); |
|
|
c->mShapeRestPositions.map(); |
|
|
c->mShapeOffsets.map(); |
|
|
c->mShapeCoefficients.map(); |
|
|
|
|
|
c->mShapePlasticThresholds.map(); |
|
|
c->mShapePlasticCreeps.map(); |
|
|
|
|
|
c->mShapeTranslations.map(); |
|
|
c->mShapeRotations.map(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c->mSpringIndices.resize(totalNumSprings * 2); |
|
|
c->mSpringLengths.resize(totalNumSprings); |
|
|
c->mSpringCoefficients.resize(totalNumSprings); |
|
|
|
|
|
|
|
|
c->mTriangleIndices.resize(totalNumTris * 3); |
|
|
c->mTriangleNormals.resize(totalNumTris); |
|
|
|
|
|
|
|
|
c->mInflatableStarts.resize(0); |
|
|
c->mInflatableCounts.resize(0); |
|
|
c->mInflatableRestVolumes.resize(0); |
|
|
c->mInflatableCoefficients.resize(0); |
|
|
c->mInflatableOverPressures.resize(0); |
|
|
|
|
|
|
|
|
c->mShapeIndices.resize(totalNumShapeIndices); |
|
|
c->mShapeRestPositions.resize(totalNumShapeIndices); |
|
|
c->mShapeOffsets.resize(1 + totalNumShapes); |
|
|
c->mShapeCoefficients.resize(totalNumShapes); |
|
|
|
|
|
if (plasticDeformation) |
|
|
{ |
|
|
c->mShapePlasticThresholds.resize(totalNumShapes); |
|
|
c->mShapePlasticCreeps.resize(totalNumShapes); |
|
|
} |
|
|
else |
|
|
{ |
|
|
c->mShapePlasticThresholds.resize(0); |
|
|
c->mShapePlasticCreeps.resize(0); |
|
|
} |
|
|
|
|
|
c->mShapeTranslations.resize(totalNumShapes); |
|
|
c->mShapeRotations.resize(totalNumShapes); |
|
|
|
|
|
int* __restrict dstSpringIndices = (totalNumSprings) ? &c->mSpringIndices[0] : NULL; |
|
|
float* __restrict dstSpringLengths = (totalNumSprings) ? &c->mSpringLengths[0] : NULL; |
|
|
float* __restrict dstSpringCoefficients = (totalNumSprings) ? &c->mSpringCoefficients[0] : NULL; |
|
|
|
|
|
int* __restrict dstTriangleIndices = (totalNumTris) ? &c->mTriangleIndices[0] : NULL; |
|
|
|
|
|
int* __restrict dstShapeIndices = (totalNumShapeIndices) ? &c->mShapeIndices[0] : NULL; |
|
|
Vec3* __restrict dstShapeRestPositions = (totalNumShapeIndices) ? &c->mShapeRestPositions[0] : NULL; |
|
|
int* __restrict dstShapeOffsets = (totalNumShapes) ? &c->mShapeOffsets[0] : NULL; |
|
|
float* __restrict dstShapeCoefficients = (totalNumShapes) ? &c->mShapeCoefficients[0] : NULL; |
|
|
float* __restrict dstShapePlasticThresholds = NULL; |
|
|
float* __restrict dstShapePlasticCreeps = NULL; |
|
|
if (plasticDeformation) |
|
|
{ |
|
|
dstShapePlasticThresholds = (totalNumShapes) ? &c->mShapePlasticThresholds[0] : NULL; |
|
|
dstShapePlasticCreeps = (totalNumShapes) ? &c->mShapePlasticCreeps[0] : NULL; |
|
|
} |
|
|
Vec3* __restrict dstShapeTranslations = (totalNumShapes) ? &c->mShapeTranslations[0] : NULL; |
|
|
Quat* __restrict dstShapeRotations = (totalNumShapes) ? &c->mShapeRotations[0] : NULL; |
|
|
|
|
|
|
|
|
if (totalNumShapes != 0) |
|
|
{ |
|
|
*dstShapeOffsets = 0; |
|
|
++dstShapeOffsets; |
|
|
} |
|
|
|
|
|
int shapeIndexOffset = 0; |
|
|
int shapeIndex = 0; |
|
|
|
|
|
|
|
|
for (size_t i = 0; i < c->mInstances.size(); ++i) |
|
|
{ |
|
|
NvFlexExtInstance* inst = c->mInstances[i]; |
|
|
|
|
|
const NvFlexExtAsset* asset = inst->asset; |
|
|
|
|
|
|
|
|
const int* __restrict remap = &inst->particleIndices[0]; |
|
|
|
|
|
|
|
|
int numSprings = asset->numSprings; |
|
|
const int numSpringIndices = asset->numSprings * 2; |
|
|
const int* __restrict srcSpringIndices = asset->springIndices; |
|
|
|
|
|
for (int i = 0; i < numSpringIndices; ++i) |
|
|
{ |
|
|
*dstSpringIndices = remap[*srcSpringIndices]; |
|
|
|
|
|
++dstSpringIndices; |
|
|
++srcSpringIndices; |
|
|
} |
|
|
|
|
|
memcpy(dstSpringLengths, asset->springRestLengths, numSprings*sizeof(float)); |
|
|
memcpy(dstSpringCoefficients, asset->springCoefficients, numSprings*sizeof(float)); |
|
|
|
|
|
dstSpringLengths += numSprings; |
|
|
dstSpringCoefficients += numSprings; |
|
|
|
|
|
|
|
|
if (asset->numShapes) |
|
|
{ |
|
|
const int indexOffset = shapeIndexOffset; |
|
|
|
|
|
|
|
|
inst->shapeIndex = shapeIndex; |
|
|
|
|
|
int shapeStart = 0; |
|
|
|
|
|
for (int s=0; s < asset->numShapes; ++s) |
|
|
{ |
|
|
dstShapeOffsets[shapeIndex] = asset->shapeOffsets[s] + indexOffset; |
|
|
dstShapeCoefficients[shapeIndex] = asset->shapeCoefficients[s]; |
|
|
if (plasticDeformation) |
|
|
{ |
|
|
if (asset->shapePlasticThresholds) |
|
|
dstShapePlasticThresholds[shapeIndex] = asset->shapePlasticThresholds[s]; |
|
|
else |
|
|
dstShapePlasticThresholds[shapeIndex] = 0.0f; |
|
|
|
|
|
if (asset->shapePlasticCreeps) |
|
|
dstShapePlasticCreeps[shapeIndex] = asset->shapePlasticCreeps[s]; |
|
|
else |
|
|
dstShapePlasticCreeps[shapeIndex] = 0.0f; |
|
|
} |
|
|
dstShapeTranslations[shapeIndex] = Vec3(&inst->shapeTranslations[s*3]); |
|
|
dstShapeRotations[shapeIndex] = Quat(&inst->shapeRotations[s*4]); |
|
|
|
|
|
++shapeIndex; |
|
|
|
|
|
const int shapeEnd = asset->shapeOffsets[s]; |
|
|
|
|
|
for (int i=shapeStart; i < shapeEnd; ++i) |
|
|
{ |
|
|
const int currentParticle = asset->shapeIndices[i]; |
|
|
|
|
|
|
|
|
dstShapeRestPositions[shapeIndexOffset] = Vec3(&asset->particles[currentParticle*4]) - Vec3(&asset->shapeCenters[s*3]); |
|
|
dstShapeIndices[shapeIndexOffset] = remap[asset->shapeIndices[i]]; |
|
|
|
|
|
++shapeIndexOffset; |
|
|
} |
|
|
|
|
|
shapeStart = shapeEnd; |
|
|
} |
|
|
} |
|
|
|
|
|
if (asset->numTriangles) |
|
|
{ |
|
|
|
|
|
const int numTriIndices = asset->numTriangles * 3; |
|
|
const int* __restrict srcTriIndices = asset->triangleIndices; |
|
|
|
|
|
for (int i = 0; i < numTriIndices; ++i) |
|
|
{ |
|
|
*dstTriangleIndices = remap[*srcTriIndices]; |
|
|
|
|
|
++dstTriangleIndices; |
|
|
++srcTriIndices; |
|
|
} |
|
|
|
|
|
if (asset->inflatable) |
|
|
{ |
|
|
c->mInflatableStarts.push_back(inst->triangleIndex); |
|
|
c->mInflatableCounts.push_back(asset->numTriangles); |
|
|
c->mInflatableRestVolumes.push_back(asset->inflatableVolume); |
|
|
c->mInflatableCoefficients.push_back(asset->inflatableStiffness); |
|
|
c->mInflatableOverPressures.push_back(asset->inflatablePressure); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
for (size_t i = 0; i < c->mSoftJoints.size(); ++i) |
|
|
{ |
|
|
NvFlexExtSoftJoint* joint = c->mSoftJoints[i]; |
|
|
const int numJointParticles = joint->numParticles; |
|
|
|
|
|
|
|
|
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; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
c->mSpringIndices.unmap(); |
|
|
c->mSpringLengths.unmap(); |
|
|
c->mSpringCoefficients.unmap(); |
|
|
|
|
|
|
|
|
c->mTriangleIndices.unmap(); |
|
|
c->mTriangleNormals.unmap(); |
|
|
|
|
|
|
|
|
c->mInflatableStarts.unmap(); |
|
|
c->mInflatableCounts.unmap(); |
|
|
c->mInflatableRestVolumes.unmap(); |
|
|
c->mInflatableCoefficients.unmap(); |
|
|
c->mInflatableOverPressures.unmap(); |
|
|
|
|
|
|
|
|
c->mShapeIndices.unmap(); |
|
|
c->mShapeRestPositions.unmap(); |
|
|
c->mShapeOffsets.unmap(); |
|
|
c->mShapeCoefficients.unmap(); |
|
|
|
|
|
c->mShapePlasticThresholds.unmap(); |
|
|
c->mShapePlasticCreeps.unmap(); |
|
|
|
|
|
c->mShapeTranslations.unmap(); |
|
|
c->mShapeRotations.unmap(); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (c->mSpringLengths.size()) |
|
|
NvFlexSetSprings(c->mSolver, c->mSpringIndices.buffer, c->mSpringLengths.buffer, c->mSpringCoefficients.buffer, int(c->mSpringLengths.size())); |
|
|
else |
|
|
NvFlexSetSprings(c->mSolver, NULL, NULL, NULL, 0); |
|
|
|
|
|
|
|
|
if (c->mShapeCoefficients.size()) |
|
|
{ |
|
|
NvFlexSetRigids(c->mSolver, c->mShapeOffsets.buffer, c->mShapeIndices.buffer, c->mShapeRestPositions.buffer, NULL, c->mShapeCoefficients.buffer, c->mShapePlasticThresholds.buffer, c->mShapePlasticCreeps.buffer, c->mShapeRotations.buffer, c->mShapeTranslations.buffer, int(c->mShapeCoefficients.size()), c->mShapeIndices.size()); |
|
|
} |
|
|
else |
|
|
{ |
|
|
c->mShapeRotations.resize(0); |
|
|
c->mShapeTranslations.resize(0); |
|
|
|
|
|
NvFlexSetRigids(c->mSolver, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, 0, 0); |
|
|
} |
|
|
|
|
|
|
|
|
if (c->mTriangleIndices.size()) |
|
|
NvFlexSetDynamicTriangles(c->mSolver, c->mTriangleIndices.buffer, NULL, int(c->mTriangleIndices.size()/3)); |
|
|
else |
|
|
NvFlexSetDynamicTriangles(c->mSolver, NULL, NULL, 0); |
|
|
|
|
|
|
|
|
if (c->mInflatableCounts.size()) |
|
|
NvFlexSetInflatables(c->mSolver, c->mInflatableStarts.buffer, c->mInflatableCounts.buffer, c->mInflatableRestVolumes.buffer, c->mInflatableOverPressures.buffer, c->mInflatableCoefficients.buffer, int(c->mInflatableCounts.size())); |
|
|
else |
|
|
NvFlexSetInflatables(c->mSolver, NULL, NULL, NULL, NULL, NULL, 0); |
|
|
|
|
|
c->mNeedsCompact = false; |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
NvFlexExtContainer* NvFlexExtCreateContainer(NvFlexLibrary* flexLib, NvFlexSolver* solver, int maxParticles) |
|
|
{ |
|
|
NvFlexExtContainer* c = new NvFlexExtContainer(flexLib); |
|
|
|
|
|
c->mSolver = solver; |
|
|
c->mFlexLib = flexLib; |
|
|
c->mMaxParticles = maxParticles; |
|
|
|
|
|
|
|
|
c->mFreeList.resize(maxParticles); |
|
|
for (int i=0; i < maxParticles; ++i) |
|
|
c->mFreeList[i] = i; |
|
|
|
|
|
c->mActiveList.init(maxParticles); |
|
|
c->mParticles.init(maxParticles); |
|
|
c->mParticlesRest.init(maxParticles); |
|
|
c->mVelocities.init(maxParticles); |
|
|
c->mPhases.init(maxParticles); |
|
|
c->mNormals.init(maxParticles); |
|
|
|
|
|
|
|
|
|
|
|
NvFlexAcquireContext(flexLib); |
|
|
|
|
|
c->mBoundsLower.init(1); |
|
|
c->mBoundsUpper.init(1); |
|
|
|
|
|
NvFlexRestoreContext(flexLib); |
|
|
|
|
|
c->mNeedsCompact = false; |
|
|
|
|
|
return c; |
|
|
} |
|
|
|
|
|
void NvFlexExtDestroyContainer(NvFlexExtContainer* c) |
|
|
{ |
|
|
|
|
|
NvFlexLibrary* lib = c->mFlexLib; |
|
|
|
|
|
NvFlexAcquireContext(lib); |
|
|
|
|
|
delete c; |
|
|
|
|
|
NvFlexRestoreContext(lib); |
|
|
|
|
|
} |
|
|
|
|
|
int NvFlexExtAllocParticles(NvFlexExtContainer* c, int n, int* indices) |
|
|
{ |
|
|
const int numToAlloc = Min(int(c->mFreeList.size()), n); |
|
|
const int start = int(c->mFreeList.size())-numToAlloc; |
|
|
|
|
|
if (numToAlloc) |
|
|
{ |
|
|
memcpy(indices, &c->mFreeList[start], numToAlloc*sizeof(int)); |
|
|
c->mFreeList.resize(start); |
|
|
} |
|
|
|
|
|
c->mNeedsActiveListRebuild = true; |
|
|
|
|
|
return numToAlloc; |
|
|
} |
|
|
|
|
|
void NvFlexExtFreeParticles(NvFlexExtContainer* c, int n, const int* indices) |
|
|
{ |
|
|
#if _DEBUG |
|
|
for (int i=0; i < n; ++i) |
|
|
{ |
|
|
|
|
|
assert(indices[i] >= 0 && indices[i] < int(c->mFreeList.capacity())); |
|
|
|
|
|
|
|
|
assert(std::find(c->mFreeList.begin(), c->mFreeList.end(), indices[i]) == c->mFreeList.end()); |
|
|
} |
|
|
#endif |
|
|
|
|
|
c->mFreeList.insert(c->mFreeList.end(), indices, indices+n); |
|
|
|
|
|
c->mNeedsActiveListRebuild = true; |
|
|
} |
|
|
|
|
|
int NvFlexExtGetActiveList(NvFlexExtContainer* c, int* indices) |
|
|
{ |
|
|
int count = 0; |
|
|
|
|
|
Bitmap inactive(c->mMaxParticles); |
|
|
|
|
|
|
|
|
for (size_t i=0; i < c->mFreeList.size(); ++i) |
|
|
{ |
|
|
|
|
|
assert(!inactive.IsSet(c->mFreeList[i])); |
|
|
|
|
|
inactive.Set(c->mFreeList[i]); |
|
|
} |
|
|
|
|
|
|
|
|
for (int i=0; i < c->mMaxParticles; ++i) |
|
|
if (inactive.IsSet(i) == false) |
|
|
indices[count++] = i; |
|
|
|
|
|
return count; |
|
|
} |
|
|
|
|
|
NvFlexExtParticleData NvFlexExtMapParticleData(NvFlexExtContainer* c) |
|
|
{ |
|
|
NvFlexExtParticleData data; |
|
|
|
|
|
c->mParticles.map(); |
|
|
c->mParticlesRest.map(); |
|
|
c->mVelocities.map(); |
|
|
c->mPhases.map(); |
|
|
c->mNormals.map(); |
|
|
|
|
|
c->mBoundsLower.map(); |
|
|
c->mBoundsUpper.map(); |
|
|
|
|
|
if (c->mParticles.size()) |
|
|
data.particles = (float*)&c->mParticles[0]; |
|
|
|
|
|
if (c->mParticlesRest.size()) |
|
|
data.restParticles = (float*)&c->mParticlesRest[0]; |
|
|
|
|
|
if (c->mVelocities.size()) |
|
|
data.velocities = (float*)&c->mVelocities[0]; |
|
|
|
|
|
if (c->mPhases.size()) |
|
|
data.phases = (int*)&c->mPhases[0]; |
|
|
|
|
|
if (c->mNormals.size()) |
|
|
data.normals = (float*)&c->mNormals[0]; |
|
|
|
|
|
data.lower = c->mBoundsLower[0]; |
|
|
data.upper = c->mBoundsUpper[0]; |
|
|
|
|
|
return data; |
|
|
} |
|
|
|
|
|
void NvFlexExtUnmapParticleData(NvFlexExtContainer*c) |
|
|
{ |
|
|
c->mParticles.unmap(); |
|
|
c->mParticlesRest.unmap(); |
|
|
c->mVelocities.unmap(); |
|
|
c->mPhases.unmap(); |
|
|
c->mNormals.unmap(); |
|
|
|
|
|
c->mBoundsLower.unmap(); |
|
|
c->mBoundsUpper.unmap(); |
|
|
} |
|
|
|
|
|
NvFlexExtTriangleData NvFlexExtMapTriangleData(NvFlexExtContainer* c) |
|
|
{ |
|
|
NvFlexExtTriangleData data; |
|
|
|
|
|
c->mTriangleIndices.map(); |
|
|
c->mTriangleNormals.map(); |
|
|
|
|
|
if (c->mTriangleIndices.size()) |
|
|
data.indices = &c->mTriangleIndices[0]; |
|
|
|
|
|
if (c->mTriangleNormals.size()) |
|
|
data.normals = (float*)&c->mTriangleNormals[0]; |
|
|
|
|
|
return data; |
|
|
} |
|
|
|
|
|
void NvFlexExtUnmapTriangleData(NvFlexExtContainer* c) |
|
|
{ |
|
|
c->mTriangleIndices.unmap(); |
|
|
c->mTriangleNormals.unmap(); |
|
|
} |
|
|
|
|
|
NvFlexExtShapeData NvFlexExtMapShapeData(NvFlexExtContainer* c) |
|
|
{ |
|
|
NvFlexExtShapeData data; |
|
|
|
|
|
c->mShapeRotations.map(); |
|
|
c->mShapeTranslations.map(); |
|
|
|
|
|
if (c->mShapeRotations.size()) |
|
|
data.rotations = (float*)&c->mShapeRotations[0]; |
|
|
|
|
|
if (c->mShapeTranslations.size()) |
|
|
data.positions = (float*)&c->mShapeTranslations[0]; |
|
|
|
|
|
return data; |
|
|
} |
|
|
|
|
|
void NvFlexExtUnmapShapeData(NvFlexExtContainer* c) |
|
|
{ |
|
|
c->mShapeRotations.unmap(); |
|
|
c->mShapeTranslations.unmap(); |
|
|
} |
|
|
|
|
|
|
|
|
NvFlexExtInstance* NvFlexExtCreateInstance(NvFlexExtContainer* c, NvFlexExtParticleData* particleData, const NvFlexExtAsset* asset, const float* transform, float vx, float vy, float vz, int phase, float invMassScale) |
|
|
{ |
|
|
const int numParticles = asset->numParticles; |
|
|
|
|
|
|
|
|
if (int(c->mFreeList.size()) < numParticles) |
|
|
return NULL; |
|
|
|
|
|
NvFlexExtInstance* inst = new NvFlexExtInstance(); |
|
|
|
|
|
inst->asset = asset; |
|
|
inst->triangleIndex = -1; |
|
|
inst->shapeIndex = -1; |
|
|
inst->inflatableIndex = -1; |
|
|
inst->userData = NULL; |
|
|
inst->numParticles = numParticles; |
|
|
|
|
|
assert(inst->numParticles <= asset->maxParticles); |
|
|
|
|
|
|
|
|
inst->particleIndices = new int[asset->maxParticles]; |
|
|
int n = NvFlexExtAllocParticles(c, numParticles, &inst->particleIndices[0]); |
|
|
assert(n == numParticles); |
|
|
(void)n; |
|
|
|
|
|
c->mInstances.push_back(inst); |
|
|
|
|
|
const Matrix44 xform(transform); |
|
|
|
|
|
for (int i=0; i < numParticles; ++i) |
|
|
{ |
|
|
const int index = inst->particleIndices[i]; |
|
|
|
|
|
|
|
|
((Vec4*)(particleData->particles))[index] = xform*Vec4(Vec3(&asset->particles[i*4]), 1.0f); |
|
|
((Vec4*)(particleData->particles))[index].w = asset->particles[i*4+3]*invMassScale; |
|
|
((Vec4*)(particleData->restParticles))[index] = Vec4(&asset->particles[i*4]); |
|
|
|
|
|
((Vec3*)(particleData->velocities))[index] = Vec3(vx, vy, vz); |
|
|
((int*)(particleData->phases))[index] = phase; |
|
|
((Vec4*)(particleData->normals))[index] = Vec4(0.0f); |
|
|
} |
|
|
|
|
|
const int numShapes = asset->numShapes; |
|
|
|
|
|
|
|
|
Vec3* shapeTranslations = new Vec3[numShapes]; |
|
|
Quat* shapeRotations = new Quat[numShapes]; |
|
|
|
|
|
Quat rotation = Quat(Matrix33(xform.GetAxis(0), xform.GetAxis(1), xform.GetAxis(2))); |
|
|
|
|
|
for (int i=0; i < numShapes; ++i) |
|
|
{ |
|
|
shapeTranslations[i] = Vec3(xform*Vec4(asset->shapeCenters[i*3+0], asset->shapeCenters[i*3+1], asset->shapeCenters[i*3+2], 1.0)); |
|
|
shapeRotations[i] = rotation; |
|
|
} |
|
|
|
|
|
inst->shapeTranslations = (float*)shapeTranslations; |
|
|
inst->shapeRotations = (float*)shapeRotations; |
|
|
|
|
|
|
|
|
c->mNeedsCompact = true; |
|
|
c->mNeedsActiveListRebuild = true; |
|
|
|
|
|
return inst; |
|
|
} |
|
|
|
|
|
void NvFlexExtDestroyInstance(NvFlexExtContainer* c, const NvFlexExtInstance* inst) |
|
|
{ |
|
|
NvFlexExtFreeParticles(c, inst->numParticles, &inst->particleIndices[0]); |
|
|
delete[] inst->particleIndices; |
|
|
|
|
|
delete[] inst->shapeRotations; |
|
|
delete[] inst->shapeTranslations; |
|
|
|
|
|
|
|
|
std::vector<NvFlexExtInstance*>::iterator iter = std::find(c->mInstances.begin(), c->mInstances.end(), inst); |
|
|
assert(iter != c->mInstances.end()); |
|
|
c->mInstances.erase(iter); |
|
|
|
|
|
c->mNeedsCompact = true; |
|
|
c->mNeedsActiveListRebuild = true; |
|
|
|
|
|
delete inst; |
|
|
} |
|
|
|
|
|
void NvFlexExtTickContainer(NvFlexExtContainer* c, float dt, int substeps, bool enableTiming) |
|
|
{ |
|
|
|
|
|
NvFlexExtPushToDevice(c); |
|
|
|
|
|
|
|
|
NvFlexUpdateSolver(c->mSolver, dt, substeps, enableTiming); |
|
|
|
|
|
|
|
|
NvFlexExtPullFromDevice(c); |
|
|
} |
|
|
|
|
|
void NvFlexExtNotifyAssetChanged(NvFlexExtContainer* c, const NvFlexExtAsset* asset) |
|
|
{ |
|
|
c->mNeedsCompact = true; |
|
|
} |
|
|
|
|
|
void NvFlexExtPushToDevice(NvFlexExtContainer* c) |
|
|
{ |
|
|
if (c->mNeedsActiveListRebuild) |
|
|
{ |
|
|
|
|
|
c->mActiveList.map(); |
|
|
int n = NvFlexExtGetActiveList(c, &c->mActiveList[0]); |
|
|
c->mActiveList.unmap(); |
|
|
|
|
|
NvFlexSetActive(c->mSolver, c->mActiveList.buffer, NULL); |
|
|
NvFlexSetActiveCount(c->mSolver, n); |
|
|
|
|
|
c->mNeedsActiveListRebuild = false; |
|
|
} |
|
|
|
|
|
|
|
|
NvFlexSetParticles(c->mSolver, c->mParticles.buffer, NULL); |
|
|
NvFlexSetRestParticles(c->mSolver, c->mParticlesRest.buffer, NULL); |
|
|
|
|
|
NvFlexSetVelocities(c->mSolver, c->mVelocities.buffer, NULL); |
|
|
NvFlexSetPhases(c->mSolver, c->mPhases.buffer, NULL); |
|
|
NvFlexSetNormals(c->mSolver, c->mNormals.buffer, NULL); |
|
|
|
|
|
if (c->mNeedsCompact) |
|
|
CompactObjects(c); |
|
|
} |
|
|
|
|
|
void NvFlexExtPullFromDevice(NvFlexExtContainer* c) |
|
|
{ |
|
|
|
|
|
NvFlexGetParticles(c->mSolver, c->mParticles.buffer, NULL); |
|
|
NvFlexGetVelocities(c->mSolver, c->mVelocities.buffer, NULL); |
|
|
NvFlexGetPhases(c->mSolver, c->mPhases.buffer, NULL); |
|
|
NvFlexGetNormals(c->mSolver, c->mNormals.buffer, NULL); |
|
|
NvFlexGetBounds(c->mSolver, c->mBoundsLower.buffer, c->mBoundsUpper.buffer); |
|
|
|
|
|
|
|
|
if (c->mShapeCoefficients.size()) |
|
|
NvFlexGetRigids(c->mSolver, NULL, NULL, NULL, NULL, NULL, NULL, NULL, c->mShapeRotations.buffer, c->mShapeTranslations.buffer); |
|
|
} |
|
|
|
|
|
void NvFlexExtUpdateInstances(NvFlexExtContainer* c) |
|
|
{ |
|
|
c->mShapeTranslations.map(); |
|
|
c->mShapeRotations.map(); |
|
|
|
|
|
for (int i=0; i < int(c->mInstances.size()); ++i) |
|
|
{ |
|
|
NvFlexExtInstance* inst = c->mInstances[i]; |
|
|
|
|
|
|
|
|
const int numShapes = inst->asset->numShapes; |
|
|
const int shapeStart = inst->shapeIndex; |
|
|
|
|
|
if (shapeStart == -1) |
|
|
continue; |
|
|
|
|
|
for (int s=0; s < numShapes; ++s) |
|
|
{ |
|
|
((Vec3*)inst->shapeTranslations)[s] = c->mShapeTranslations[shapeStart + s]; |
|
|
((Quat*)inst->shapeRotations)[s] = c->mShapeRotations[shapeStart + s]; |
|
|
} |
|
|
} |
|
|
|
|
|
for (int i = 0; i < int(c->mSoftJoints.size()); ++i) |
|
|
{ |
|
|
NvFlexExtSoftJoint* joint = c->mSoftJoints[i]; |
|
|
|
|
|
const int shapeStart = joint->shapeIndex; |
|
|
|
|
|
|
|
|
if (!joint->initialized) |
|
|
{ |
|
|
|
|
|
|
|
|
|
|
|
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]]; |
|
|
|
|
|
|
|
|
com += Vec3(particlePosition) - shapeOffset; |
|
|
} |
|
|
com /= float(joint->numParticles); |
|
|
|
|
|
|
|
|
com += shapeOffset; |
|
|
|
|
|
|
|
|
joint->shapeTranslations[0] = com.x; |
|
|
joint->shapeTranslations[1] = com.y; |
|
|
joint->shapeTranslations[2] = com.z; |
|
|
|
|
|
joint->initialized = true; |
|
|
} |
|
|
else |
|
|
{ |
|
|
joint->shapeTranslations[0] = c->mShapeTranslations[shapeStart].x; |
|
|
joint->shapeTranslations[1] = c->mShapeTranslations[shapeStart].y; |
|
|
joint->shapeTranslations[2] = c->mShapeTranslations[shapeStart].z; |
|
|
} |
|
|
|
|
|
|
|
|
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(); |
|
|
} |
|
|
|
|
|
void NvFlexExtDestroyAsset(NvFlexExtAsset* asset) |
|
|
{ |
|
|
delete[] asset->particles; |
|
|
delete[] asset->springIndices; |
|
|
delete[] asset->springCoefficients; |
|
|
delete[] asset->springRestLengths; |
|
|
delete[] asset->triangleIndices; |
|
|
delete[] asset->shapeIndices; |
|
|
delete[] asset->shapeOffsets; |
|
|
delete[] asset->shapeCenters; |
|
|
delete[] asset->shapeCoefficients; |
|
|
delete[] asset->shapePlasticThresholds; |
|
|
delete[] asset->shapePlasticCreeps; |
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
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; |
|
|
|
|
|
c->mSoftJoints.push_back(joint); |
|
|
|
|
|
|
|
|
c->mNeedsCompact = true; |
|
|
|
|
|
return joint; |
|
|
} |
|
|
|
|
|
void NvFlexExtDestroySoftJoint(NvFlexExtContainer* c, NvFlexExtSoftJoint* joint) |
|
|
{ |
|
|
delete[] joint->particleIndices; |
|
|
delete[] joint->particleLocalPositions; |
|
|
|
|
|
|
|
|
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) |
|
|
{ |
|
|
|
|
|
Matrix44 LocalFromOld = AffineInverse(TranslationMatrix(Point3(joint->shapeTranslations))*RotationMatrix(joint->shapeRotations)); |
|
|
Matrix44 NewFromLocal = TranslationMatrix(Point3(newPosition))*RotationMatrix(newRotation); |
|
|
Matrix44 transform = NewFromLocal*LocalFromOld; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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); |
|
|
|
|
|
|
|
|
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]; |
|
|
|
|
|
|
|
|
|
|
|
c->mParticles.unmap(); |
|
|
} |
|
|
|
|
|
|
|
|
|