diff options
| author | Miles Macklin <[email protected]> | 2017-03-10 14:51:31 +1300 |
|---|---|---|
| committer | Miles Macklin <[email protected]> | 2017-03-10 14:51:31 +1300 |
| commit | ad3d90fafe5ee79964bdfe1f1e0704c3ffcdfd5f (patch) | |
| tree | 4cc6f3288363889d7342f7f8407c0251e6904819 /extensions/flexExtContainer.cpp | |
| download | flex-ad3d90fafe5ee79964bdfe1f1e0704c3ffcdfd5f.tar.xz flex-ad3d90fafe5ee79964bdfe1f1e0704c3ffcdfd5f.zip | |
Initial 1.1.0 binary release
Diffstat (limited to 'extensions/flexExtContainer.cpp')
| -rw-r--r-- | extensions/flexExtContainer.cpp | 807 |
1 files changed, 807 insertions, 0 deletions
diff --git a/extensions/flexExtContainer.cpp b/extensions/flexExtContainer.cpp new file mode 100644 index 0000000..92cb958 --- /dev/null +++ b/extensions/flexExtContainer.cpp @@ -0,0 +1,807 @@ +// This code contains NVIDIA Confidential Information and is disclosed to you +// under a form of NVIDIA software license agreement provided separately to you. +// +// Notice +// NVIDIA Corporation and its licensors retain all intellectual property and +// proprietary rights in and to this software and related documentation and +// any modifications thereto. Any use, reproduction, disclosure, or +// distribution of this software and related documentation without an express +// license agreement from NVIDIA Corporation is strictly prohibited. +// +// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES +// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO +// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT, +// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE. +// +// Information and code furnished is believed to be accurate and reliable. +// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such +// information or for any infringement of patents or other rights of third parties that may +// result from its use. No license is granted by implication or otherwise under any patent +// or patent rights of NVIDIA Corporation. Details are subject to change without notice. +// This code supersedes and replaces all information previously supplied. +// NVIDIA Corporation products are not authorized for use as critical +// components in life support devices or systems without express written approval of +// NVIDIA Corporation. +// +// Copyright (c) 2013-2017 NVIDIA Corporation. All rights reserved. + +#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; + + // first n indices + NvFlexVector<int> mActiveList; + + std::vector<int> mFreeList; + std::vector<NvFlexExtInstance*> mInstances; + + // particles + NvFlexVector<Vec4> mParticles; + NvFlexVector<Vec4> mParticlesRest; + NvFlexVector<Vec3> mVelocities; + NvFlexVector<int> mPhases; + NvFlexVector<Vec4> mNormals; + + // shapes + NvFlexVector<int> mShapeOffsets; + NvFlexVector<int> mShapeIndices; + NvFlexVector<float> mShapeCoefficients; + NvFlexVector<Quat> mShapeRotations; + NvFlexVector<Vec3> mShapeTranslations; + NvFlexVector<Vec3> mShapeRestPositions; + + // springs + NvFlexVector<int> mSpringIndices; + NvFlexVector<float> mSpringLengths; + NvFlexVector<float> mSpringCoefficients; + + // cloth + NvFlexVector<int> mTriangleIndices; + NvFlexVector<Vec3> mTriangleNormals; + + NvFlexVector<int> mInflatableStarts; + NvFlexVector<int> mInflatableCounts; + NvFlexVector<float> mInflatableRestVolumes; + NvFlexVector<float> mInflatableCoefficients; + NvFlexVector<float> mInflatableOverPressures; + + // bounds (CPU), stored in a vector to ensure transfers can happen asynchronously + NvFlexVector<Vec3> mBoundsLower; + NvFlexVector<Vec3> mBoundsUpper; + + // needs compact + bool mNeedsCompact; + // needs to update active list + 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),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 +{ + +// compacts all constraints into linear arrays +void CompactObjects(NvFlexExtContainer* c) +{ + int totalNumSprings = 0; + int totalNumTris = 0; + int totalNumShapes = 0; + int totalNumShapeIndices = 0; + + // pre-calculate array sizes + for (size_t i = 0; i < c->mInstances.size(); ++i) + { + NvFlexExtInstance* inst = c->mInstances[i]; + + const NvFlexExtAsset* asset = inst->asset; + + // index into the triangle array for this instance + inst->triangleIndex = totalNumTris; + + totalNumSprings += asset->numSprings; + totalNumTris += asset->numTriangles; + + totalNumShapeIndices += asset->numShapeIndices; + totalNumShapes += asset->numShapes; + } + + //---------------------- + // map buffers + + // springs + c->mSpringIndices.map(); + c->mSpringLengths.map(); + c->mSpringCoefficients.map(); + + // cloth + c->mTriangleIndices.map(); + c->mTriangleNormals.map(); + + // inflatables + c->mInflatableStarts.map(); + c->mInflatableCounts.map(); + c->mInflatableRestVolumes.map(); + c->mInflatableCoefficients.map(); + c->mInflatableOverPressures.map(); + + // shapes + c->mShapeIndices.map(); + c->mShapeRestPositions.map(); + c->mShapeOffsets.map(); + c->mShapeCoefficients.map(); + + c->mShapeTranslations.map(); + c->mShapeRotations.map(); + + //---------------------- + // resize buffers + + // springs + c->mSpringIndices.resize(totalNumSprings * 2); + c->mSpringLengths.resize(totalNumSprings); + c->mSpringCoefficients.resize(totalNumSprings); + + // cloth + c->mTriangleIndices.resize(totalNumTris * 3); + c->mTriangleNormals.resize(totalNumTris); + + // inflatables + c->mInflatableStarts.resize(0); + c->mInflatableCounts.resize(0); + c->mInflatableRestVolumes.resize(0); + c->mInflatableCoefficients.resize(0); + c->mInflatableOverPressures.resize(0); + + // shapes + c->mShapeIndices.resize(totalNumShapeIndices); + c->mShapeRestPositions.resize(totalNumShapeIndices); + c->mShapeOffsets.resize(1 + totalNumShapes); + c->mShapeCoefficients.resize(totalNumShapes); + + 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; + Vec3* __restrict dstShapeTranslations = (totalNumShapes) ? &c->mShapeTranslations[0] : NULL; + Quat* __restrict dstShapeRotations = (totalNumShapes) ? &c->mShapeRotations[0] : NULL; + + // push leading zero if necessary + if (totalNumShapes != 0) + { + *dstShapeOffsets = 0; + ++dstShapeOffsets; + } + + int shapeIndexOffset = 0; + int shapeIndex = 0; + + // go through each instance and update springs, shapes, etc + for (size_t i = 0; i < c->mInstances.size(); ++i) + { + NvFlexExtInstance* inst = c->mInstances[i]; + + const NvFlexExtAsset* asset = inst->asset; + + // map indices from the asset to the instance + const int* __restrict remap = &inst->particleIndices[0]; + + // flatten spring data + 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; + + // shapes + if (asset->numShapes) + { + const int indexOffset = shapeIndexOffset; + + // store start index into shape array + 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]; + 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 firstParticle = asset->shapeIndices[0]; + const int currentParticle = asset->shapeIndices[i]; + + // remap indices and create local space positions for each shape + // To make this calculation more robust, subtract the position of the first particle from both, the positions of the current + // particle and the shapeCenter. Without this one would subtract two very similar floating point values, which can lead to ghost forces. + dstShapeRestPositions[shapeIndexOffset] = (Vec3(&asset->particles[currentParticle*4]) - Vec3(&asset->particles[firstParticle])) + - (Vec3(&asset->shapeCenters[s*3]) - Vec3(&asset->particles[firstParticle])); + + dstShapeIndices[shapeIndexOffset] = remap[asset->shapeIndices[i]]; + + ++shapeIndexOffset; + } + + shapeStart = shapeEnd; + } + } + + if (asset->numTriangles) + { + // triangles + 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); + } + } + } + + + //---------------------- + // unmap buffers + + // springs + c->mSpringIndices.unmap(); + c->mSpringLengths.unmap(); + c->mSpringCoefficients.unmap(); + + // cloth + c->mTriangleIndices.unmap(); + c->mTriangleNormals.unmap(); + + // inflatables + c->mInflatableStarts.unmap(); + c->mInflatableCounts.unmap(); + c->mInflatableRestVolumes.unmap(); + c->mInflatableCoefficients.unmap(); + c->mInflatableOverPressures.unmap(); + + // shapes + c->mShapeIndices.unmap(); + c->mShapeRestPositions.unmap(); + c->mShapeOffsets.unmap(); + c->mShapeCoefficients.unmap(); + + c->mShapeTranslations.unmap(); + c->mShapeRotations.unmap(); + + // ---------------------- + // Flex update + + // springs + 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); + + // shapes + if (c->mShapeCoefficients.size()) + { + NvFlexSetRigids(c->mSolver, c->mShapeOffsets.buffer, c->mShapeIndices.buffer, c->mShapeRestPositions.buffer, NULL, c->mShapeCoefficients.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, 0, 0); + } + + // triangles + if (c->mTriangleIndices.size()) + NvFlexSetDynamicTriangles(c->mSolver, c->mTriangleIndices.buffer, NULL, int(c->mTriangleIndices.size()/3)); + else + NvFlexSetDynamicTriangles(c->mSolver, NULL, NULL, 0); + + // inflatables + 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; + +} + +} // anonymous namespace + + +NvFlexExtContainer* NvFlexExtCreateContainer(NvFlexLibrary* flexLib, NvFlexSolver* solver, int maxParticles) +{ + NvFlexExtContainer* c = new NvFlexExtContainer(flexLib); + + c->mSolver = solver; + c->mFlexLib = flexLib; + c->mMaxParticles = maxParticles; + + // initialize free list + 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); + + + // ensure we have the corerct CUDA context set + NvFlexAcquireContext(flexLib); + + c->mBoundsLower.init(1); + c->mBoundsUpper.init(1); + + NvFlexRestoreContext(flexLib); + + c->mNeedsCompact = false; + + return c; +} + +void NvFlexExtDestroyContainer(NvFlexExtContainer* c) +{ + // ensure we have the corerct CUDA context set + 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) + { + // check valid values + assert(indices[i] >= 0 && indices[i] < int(c->mFreeList.capacity())); + + // check for double delete + 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); + + // create bitmap + for (size_t i=0; i < c->mFreeList.size(); ++i) + { + // if this fires then somehow a duplicate has ended up in the free list (double delete) + assert(!inactive.IsSet(c->mFreeList[i])); + + inactive.Set(c->mFreeList[i]); + } + + // iterate bitmap to find active elements + 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; + + // check if asset will fit + 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); + + // allocate particles for instance + 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]; + + // add transformed particles to the locked particle data + ((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; + + // allocate memory for shape transforms + 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; + + // mark container as dirty + 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; + + // TODO: O(N) remove + 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) +{ + // update the device + NvFlexExtPushToDevice(c); + + // update solver + NvFlexUpdateSolver(c->mSolver, dt, substeps, enableTiming); + + // update host + NvFlexExtPullFromDevice(c); +} + +void NvFlexExtNotifyAssetChanged(NvFlexExtContainer* c, const NvFlexExtAsset* asset) +{ + c->mNeedsCompact = true; +} + +void NvFlexExtPushToDevice(NvFlexExtContainer* c) +{ + if (c->mNeedsActiveListRebuild) + { + // update active list + c->mActiveList.map(); + int n = NvFlexExtGetActiveList(c, &c->mActiveList[0]); + c->mActiveList.unmap(); + + NvFlexSetActive(c->mSolver, c->mActiveList.buffer, n); + + c->mNeedsActiveListRebuild = false; + } + + // push any changes to solver + NvFlexSetParticles(c->mSolver, c->mParticles.buffer, int(c->mParticles.size())); + NvFlexSetRestParticles(c->mSolver, c->mParticlesRest.buffer, int(c->mParticlesRest.size())); + + NvFlexSetVelocities(c->mSolver, c->mVelocities.buffer, int(c->mVelocities.size())); + NvFlexSetPhases(c->mSolver, c->mPhases.buffer, int(c->mPhases.size())); + NvFlexSetNormals(c->mSolver, c->mNormals.buffer, int(c->mNormals.size())); + + if (c->mNeedsCompact) + CompactObjects(c); +} + +void NvFlexExtPullFromDevice(NvFlexExtContainer* c) +{ + + // read back particle data + NvFlexGetParticles(c->mSolver, c->mParticles.buffer, int(c->mParticles.size())); + NvFlexGetVelocities(c->mSolver, c->mVelocities.buffer, int(c->mVelocities.size())); + NvFlexGetPhases(c->mSolver, c->mPhases.buffer, int(c->mPhases.size())); + NvFlexGetNormals(c->mSolver, c->mNormals.buffer, int(c->mNormals.size())); + NvFlexGetBounds(c->mSolver, c->mBoundsLower.buffer, c->mBoundsUpper.buffer); + + // read back shape transforms + if (c->mShapeCoefficients.size()) + NvFlexGetRigidTransforms(c->mSolver, 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]; + + // copy data back to per-instance memory from the container's memory + 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]; + } + } + + 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; +} + + |