aboutsummaryrefslogtreecommitdiff
path: root/NvCloth/src/cuda
diff options
context:
space:
mode:
Diffstat (limited to 'NvCloth/src/cuda')
-rw-r--r--NvCloth/src/cuda/CuCloth.cpp135
-rw-r--r--NvCloth/src/cuda/CuCloth.h77
-rw-r--r--NvCloth/src/cuda/CuClothClone.cpp9
-rw-r--r--NvCloth/src/cuda/CuFactory.cpp17
-rw-r--r--NvCloth/src/cuda/CuFactory.h2
-rw-r--r--NvCloth/src/cuda/CuSolver.cpp16
-rw-r--r--NvCloth/src/cuda/CuSolver.h6
7 files changed, 124 insertions, 138 deletions
diff --git a/NvCloth/src/cuda/CuCloth.cpp b/NvCloth/src/cuda/CuCloth.cpp
index 93b2370..3e6175b 100644
--- a/NvCloth/src/cuda/CuCloth.cpp
+++ b/NvCloth/src/cuda/CuCloth.cpp
@@ -37,7 +37,6 @@
#include "../TripletScheduler.h"
#include "../ClothBase.h"
#include <foundation/PxMat44.h>
-#include <PsFoundation.h>
using namespace physx;
@@ -215,7 +214,7 @@ uint32_t cloth::CuCloth::getSharedMemorySize() const
return phaseConfigSize + sizeof(float) * (continuousCollisionSize + std::max(selfCollisionSize, discreteCollisionSize));
}
-void cloth::CuCloth::setPhaseConfig(Range<const PhaseConfig> configs)
+void cloth::CuCloth::setPhaseConfigInternal(Range<const PhaseConfig> configs)
{
mHostPhaseConfigs.assign(configs.begin(), configs.end());
@@ -317,69 +316,60 @@ namespace nv
namespace cloth
{
-// ClothImpl<CuCloth>::clone() implemented in CuClothClone.cpp
+// CuCloth::clone() implemented in CuClothClone.cpp
-template <>
-uint32_t ClothImpl<CuCloth>::getNumParticles() const
+uint32_t CuCloth::getNumParticles() const
{
- return mCloth.mNumParticles;
+ return mNumParticles;
}
-template <>
-void ClothImpl<CuCloth>::lockParticles() const
+void CuCloth::lockParticles() const
{
- const_cast<CuCloth&>(mCloth).syncHostParticles();
+ const_cast<CuCloth&>(*this).syncHostParticles();
}
-template <>
-void ClothImpl<CuCloth>::unlockParticles() const
+void CuCloth::unlockParticles() const
{
}
-template <>
-MappedRange<PxVec4> ClothImpl<CuCloth>::getCurrentParticles()
+MappedRange<PxVec4> CuCloth::getCurrentParticles()
{
- mCloth.wakeUp();
+ wakeUp();
lockParticles();
- mCloth.mDeviceParticlesDirty = true;
- return getMappedParticles(mCloth.mParticlesHostCopy.begin());
+ mDeviceParticlesDirty = true;
+ return getMappedParticles(mParticlesHostCopy.begin());
}
-template <>
-MappedRange<const PxVec4> ClothImpl<CuCloth>::getCurrentParticles() const
+MappedRange<const PxVec4> CuCloth::getCurrentParticles() const
{
lockParticles();
- return getMappedParticles(mCloth.mParticlesHostCopy.begin());
+ return getMappedParticles(mParticlesHostCopy.begin());
}
-template <>
-MappedRange<PxVec4> ClothImpl<CuCloth>::getPreviousParticles()
+MappedRange<PxVec4> CuCloth::getPreviousParticles()
{
- mCloth.wakeUp();
+ wakeUp();
lockParticles();
- mCloth.mDeviceParticlesDirty = true;
- return getMappedParticles(mCloth.mParticlesHostCopy.begin() + mCloth.mNumParticles);
+ mDeviceParticlesDirty = true;
+ return getMappedParticles(mParticlesHostCopy.begin() + mNumParticles);
}
-template <>
-MappedRange<const PxVec4> ClothImpl<CuCloth>::getPreviousParticles() const
+MappedRange<const PxVec4> CuCloth::getPreviousParticles() const
{
lockParticles();
- return getMappedParticles(mCloth.mParticlesHostCopy.begin() + mCloth.mNumParticles);
+ return getMappedParticles(mParticlesHostCopy.begin() + mNumParticles);
}
-template <>
-GpuParticles ClothImpl<CuCloth>::getGpuParticles()
+GpuParticles CuCloth::getGpuParticles()
{
- mCloth.syncDeviceParticles();
- mCloth.mHostParticlesDirty = true;
- PxVec4* particles = mCloth.mParticles.begin().get();
- GpuParticles result = { particles, particles + mCloth.mNumParticles, 0 };
+ syncDeviceParticles();
+ mHostParticlesDirty = true;
+ PxVec4* particles = mParticles.begin().get();
+ GpuParticles result = { particles, particles + mNumParticles, 0 };
return result;
}
-template <>
-void ClothImpl<CuCloth>::setPhaseConfig(Range<const PhaseConfig> configs)
+void CuCloth::setPhaseConfig(Range<const PhaseConfig> configs)
{
Vector<PhaseConfig>::Type transformedConfigs;
transformedConfigs.reserve(configs.size());
@@ -389,56 +379,52 @@ void ClothImpl<CuCloth>::setPhaseConfig(Range<const PhaseConfig> configs)
if (configs.front().mStiffness > 0.0f)
transformedConfigs.pushBack(transform(configs.front()));
- mCloth.setPhaseConfig(Range<const PhaseConfig>(transformedConfigs.begin(), transformedConfigs.end()));
- mCloth.notifyChanged();
- mCloth.wakeUp();
+ setPhaseConfigInternal(Range<const PhaseConfig>(transformedConfigs.begin(), transformedConfigs.end()));
+ notifyChanged();
+ wakeUp();
}
-template <>
-void ClothImpl<CuCloth>::setSelfCollisionIndices(Range<const uint32_t> indices)
+void CuCloth::setSelfCollisionIndices(Range<const uint32_t> indices)
{
- ContextLockType lock(mCloth.mFactory);
- mCloth.mSelfCollisionIndices.assign(indices.begin(), indices.end());
- mCloth.mSelfCollisionIndicesHost.assign(indices.begin(), indices.end());
- mCloth.notifyChanged();
- mCloth.wakeUp();
+ ContextLockType lock(mFactory);
+ mSelfCollisionIndices.assign(indices.begin(), indices.end());
+ mSelfCollisionIndicesHost.assign(indices.begin(), indices.end());
+ notifyChanged();
+ wakeUp();
}
-template <>
-uint32_t ClothImpl<CuCloth>::getNumVirtualParticles() const
+uint32_t CuCloth::getNumVirtualParticles() const
{
- return uint32_t(mCloth.mVirtualParticleIndices.size());
+ return uint32_t(mVirtualParticleIndices.size());
}
-template <>
-Range<PxVec4> ClothImpl<CuCloth>::getParticleAccelerations()
+Range<PxVec4> CuCloth::getParticleAccelerations()
{
- if (mCloth.mParticleAccelerations.empty())
+ if (mParticleAccelerations.empty())
{
- CuContextLock contextLock(mCloth.mFactory);
- mCloth.mParticleAccelerations.resize(mCloth.mNumParticles);
+ CuContextLock contextLock(mFactory);
+ mParticleAccelerations.resize(mNumParticles);
}
- if (!mCloth.mParticleAccelerationsHostCopy.capacity())
+ if (!mParticleAccelerationsHostCopy.capacity())
{
- CuContextLock contextLock(mCloth.mFactory);
- mCloth.mParticleAccelerationsHostCopy.reserve(mCloth.mNumParticles);
+ CuContextLock contextLock(mFactory);
+ mParticleAccelerationsHostCopy.reserve(mNumParticles);
}
- mCloth.mParticleAccelerationsHostCopy.resizeUninitialized(mCloth.mNumParticles);
+ mParticleAccelerationsHostCopy.resizeUninitialized(mNumParticles);
- mCloth.wakeUp();
+ wakeUp();
- PxVec4* data = mCloth.mParticleAccelerationsHostCopy.begin();
- return Range<PxVec4>(data, mCloth.mParticleAccelerationsHostCopy.end());
+ PxVec4* data = mParticleAccelerationsHostCopy.begin();
+ return Range<PxVec4>(data, mParticleAccelerationsHostCopy.end());
}
-template <>
-void ClothImpl<CuCloth>::clearParticleAccelerations()
+void CuCloth::clearParticleAccelerations()
{
- CuContextLock contextLock(mCloth.mFactory);
- CuDeviceVector<PxVec4>(mCloth.mFactory.mContext).swap(mCloth.mParticleAccelerations);
- CuHostVector<PxVec4, CU_MEMHOSTALLOC_DEVICEMAP>::Type().swap(mCloth.mParticleAccelerationsHostCopy);
- mCloth.wakeUp();
+ CuContextLock contextLock(mFactory);
+ CuDeviceVector<PxVec4>(mFactory.mContext).swap(mParticleAccelerations);
+ CuHostVector<PxVec4, CU_MEMHOSTALLOC_DEVICEMAP>::Type().swap(mParticleAccelerationsHostCopy);
+ wakeUp();
}
namespace
@@ -469,12 +455,11 @@ namespace
}
}
-template <>
-void ClothImpl<CuCloth>::setVirtualParticles(Range<const uint32_t[4]> indices, Range<const PxVec3> weights)
+void CuCloth::setVirtualParticles(Range<const uint32_t[4]> indices, Range<const PxVec3> weights)
{
// shuffle indices to form independent SIMD sets
TripletScheduler scheduler(indices);
- scheduler.warp(mCloth.mNumParticles, 32);
+ scheduler.warp(mNumParticles, 32);
// convert to 16bit indices
Vector<Vec4us>::Type hostIndices;
@@ -497,15 +482,15 @@ void ClothImpl<CuCloth>::setVirtualParticles(Range<const uint32_t[4]> indices, R
hostWeights.pushBack(PxVec4( w.x, w.y, w.z, scale ));
}
- CuContextLock contextLock(mCloth.mFactory);
+ CuContextLock contextLock(mFactory);
// todo: 'swap' these to force reallocation?
- mCloth.mVirtualParticleIndices = hostIndices;
- mCloth.mVirtualParticleSetSizes = scheduler.mSetSizes;
- mCloth.mVirtualParticleWeights = hostWeights;
+ mVirtualParticleIndices = hostIndices;
+ mVirtualParticleSetSizes = scheduler.mSetSizes;
+ mVirtualParticleWeights = hostWeights;
- mCloth.notifyChanged();
- mCloth.wakeUp();
+ notifyChanged();
+ wakeUp();
}
} // namespace cloth
diff --git a/NvCloth/src/cuda/CuCloth.h b/NvCloth/src/cuda/CuCloth.h
index 1f86343..8dc3082 100644
--- a/NvCloth/src/cuda/CuCloth.h
+++ b/NvCloth/src/cuda/CuCloth.h
@@ -43,6 +43,8 @@
#include <foundation/PxVec3.h>
#include <foundation/PxTransform.h>
#include "NvCloth/Allocator.h"
+#include "ClothImpl.h"
+#include "CuFactory.h"
namespace nv
{
@@ -50,7 +52,6 @@ namespace cloth
{
class CuFabric;
-class CuFactory;
struct CuClothData;
struct CuConstraints
@@ -74,7 +75,18 @@ struct CuConstraints
CuHostVector<physx::PxVec4, CU_MEMHOSTALLOC_DEVICEMAP>::Type mHostCopy;
};
-class CuCloth : protected CuContextLock
+class CuCloth;
+
+template<>
+class ClothTraits<CuCloth>
+{
+public:
+ typedef CuFactory FactoryType;
+ typedef CuFabric FabricType;
+ typedef CuContextLock ContextLockType;
+};
+
+class CuCloth : protected CuContextLock, public ClothImpl<CuCloth>
{
CuCloth(); // not implemented
@@ -94,14 +106,24 @@ class CuCloth : protected CuContextLock
~CuCloth(); // not virtual on purpose
public:
- bool isSleeping() const
- {
- return mSleepPassCounter >= mSleepAfterCount;
- }
- void wakeUp()
- {
- mSleepPassCounter = 0;
- }
+ virtual Cloth* clone(Factory& factory) const;
+ uint32_t getNumParticles() const;
+
+ void lockParticles() const;
+ void unlockParticles() const;
+
+ MappedRange<physx::PxVec4> getCurrentParticles();
+ MappedRange<const physx::PxVec4> getCurrentParticles() const;
+ MappedRange<physx::PxVec4> getPreviousParticles();
+ MappedRange<const physx::PxVec4> getPreviousParticles() const;
+ GpuParticles getGpuParticles();
+ void setPhaseConfig(Range<const PhaseConfig> configs);
+
+ void setSelfCollisionIndices(Range<const uint32_t> indices);
+ uint32_t getNumVirtualParticles() const;
+ Range<physx::PxVec4> getParticleAccelerations();
+ void clearParticleAccelerations();
+ void setVirtualParticles(Range<const uint32_t[4]> indices, Range<const physx::PxVec3> weights);
void notifyChanged();
@@ -109,7 +131,7 @@ class CuCloth : protected CuContextLock
uint32_t getSharedMemorySize() const; // without particle data
// expects transformed configs, doesn't call notifyChanged()
- void setPhaseConfig(Range<const PhaseConfig>);
+ void setPhaseConfigInternal(Range<const PhaseConfig>);
Range<physx::PxVec4> push(CuConstraints&);
void clear(CuConstraints&);
@@ -133,27 +155,6 @@ class CuCloth : protected CuContextLock
bool mDeviceParticlesDirty;
bool mHostParticlesDirty;
- physx::PxVec3 mParticleBoundsCenter;
- physx::PxVec3 mParticleBoundsHalfExtent;
-
- physx::PxVec3 mGravity;
- physx::PxVec3 mLogDamping;
- physx::PxVec3 mLinearLogDrag;
- physx::PxVec3 mAngularLogDrag;
- physx::PxVec3 mLinearInertia;
- physx::PxVec3 mAngularInertia;
- physx::PxVec3 mCentrifugalInertia;
- float mSolverFrequency;
- float mStiffnessFrequency;
-
- physx::PxTransform mTargetMotion;
- physx::PxTransform mCurrentMotion;
- physx::PxVec3 mLinearVelocity;
- physx::PxVec3 mAngularVelocity;
-
- float mPrevIterDt;
- MovingAverage mIterDtAvg;
-
CuDeviceVector<CuPhaseConfig> mPhaseConfigs; // transformed!
Vector<PhaseConfig>::Type mHostPhaseConfigs; // transformed!
@@ -174,11 +175,6 @@ class CuCloth : protected CuContextLock
CuDeviceVector<physx::PxVec4> mParticleAccelerations;
CuHostVector<physx::PxVec4, CU_MEMHOSTALLOC_DEVICEMAP>::Type mParticleAccelerationsHostCopy;
- // wind
- physx::PxVec3 mWind;
- float mDragLogCoefficient;
- float mLiftLogCoefficient;
-
// collision stuff
CuHostVector<IndexPair, CU_MEMHOSTALLOC_DEVICEMAP>::Type mCapsuleIndices;
CuHostVector<physx::PxVec4, CU_MEMHOSTALLOC_DEVICEMAP>::Type mStartCollisionSpheres;
@@ -208,13 +204,6 @@ class CuCloth : protected CuContextLock
// 4 (position) + 2 (key) per particle + cellStart (8322)
CuDeviceVector<float> mSelfCollisionData;
- // sleeping (see SwCloth for comments)
- uint32_t mSleepTestInterval;
- uint32_t mSleepAfterCount;
- float mSleepThreshold;
- uint32_t mSleepPassCounter;
- uint32_t mSleepTestCounter;
-
uint32_t mSharedMemorySize;
void* mUserData;
diff --git a/NvCloth/src/cuda/CuClothClone.cpp b/NvCloth/src/cuda/CuClothClone.cpp
index df43c66..5dba4ec 100644
--- a/NvCloth/src/cuda/CuClothClone.cpp
+++ b/NvCloth/src/cuda/CuClothClone.cpp
@@ -56,11 +56,10 @@ Range<const uint32_t> getSelfCollisionIndices(const CuCloth& cloth)
return makeRange(cloth.mSelfCollisionIndicesHost);
}
-template <>
-Cloth* ClothImpl<CuCloth>::clone(Factory& factory) const
+Cloth* CuCloth::clone(Factory& factory) const
{
- if (&mCloth.mFactory == &factory)
- return NV_CLOTH_NEW(ClothImpl<CuCloth>)(factory, *this); // copy construct directly
+ if (&mFactory == &factory)
+ return NV_CLOTH_NEW(CuCloth)(mFactory, *this); // copy construct directly
switch(factory.getPlatform())
{
@@ -77,7 +76,7 @@ Cloth* ClothImpl<CuCloth>::clone(Factory& factory) const
Cloth* CuFactory::clone(const Cloth& cloth)
{
if (cloth.getFactory().getPlatform() == Platform::CPU)
- return convertCloth(*this, static_cast<const SwClothImpl&>(cloth));
+ return convertCloth(*this, static_cast<const SwCloth&>(cloth));
return cloth.clone(*this);
}
diff --git a/NvCloth/src/cuda/CuFactory.cpp b/NvCloth/src/cuda/CuFactory.cpp
index 460cebc..397262c 100644
--- a/NvCloth/src/cuda/CuFactory.cpp
+++ b/NvCloth/src/cuda/CuFactory.cpp
@@ -35,7 +35,6 @@
#include "CuCheckSuccess.h"
#include "CuContextLock.h"
#include <cuda.h>
-#include <PsFoundation.h>
#include "CuSolverKernelBlob.h"
#if PX_VC
@@ -155,7 +154,7 @@ cloth::Fabric* cloth::CuFactory::createFabric(uint32_t numParticles, Range<const
cloth::Cloth* cloth::CuFactory::createCloth(Range<const PxVec4> particles, Fabric& fabric)
{
- return NV_CLOTH_NEW(CuClothImpl)(*this, fabric, particles);
+ return NV_CLOTH_NEW(CuCloth)(*this, static_cast<CuFabric&>(fabric), particles);
}
cloth::Solver* cloth::CuFactory::createSolver()
@@ -255,7 +254,7 @@ void cloth::CuFactory::extractCollisionData(const Cloth& cloth, Range<PxVec4> sp
{
NV_CLOTH_ASSERT(&cloth.getFactory() == this);
- const CuCloth& cuCloth = static_cast<const CuClothImpl&>(cloth).mCloth;
+ const CuCloth& cuCloth = static_cast<const CuCloth&>(cloth);
NV_CLOTH_ASSERT(spheres.empty() || spheres.size() == cuCloth.mStartCollisionSpheres.size());
NV_CLOTH_ASSERT(capsules.empty() || capsules.size() == cuCloth.mCapsuleIndices.size() * 2);
@@ -287,7 +286,7 @@ void cloth::CuFactory::extractMotionConstraints(const Cloth& cloth, Range<PxVec4
{
NV_CLOTH_ASSERT(&cloth.getFactory() == this);
- const CuCloth& cuCloth = static_cast<const CuClothImpl&>(cloth).mCloth;
+ const CuCloth& cuCloth = static_cast<const CuCloth&>(cloth);
if (cuCloth.mMotionConstraints.mHostCopy.size())
{
@@ -314,7 +313,7 @@ void cloth::CuFactory::extractSeparationConstraints(const Cloth& cloth, Range<Px
{
NV_CLOTH_ASSERT(&cloth.getFactory() == this);
- const CuCloth& cuCloth = static_cast<const CuClothImpl&>(cloth).mCloth;
+ const CuCloth& cuCloth = static_cast<const CuCloth&>(cloth);
if (cuCloth.mSeparationConstraints.mHostCopy.size())
{
@@ -341,7 +340,7 @@ void cloth::CuFactory::extractParticleAccelerations(const Cloth& cloth, Range<Px
{
NV_CLOTH_ASSERT(&cloth.getFactory() == this);
- const CuCloth& cuCloth = static_cast<const CuClothImpl&>(cloth).mCloth;
+ const CuCloth& cuCloth = static_cast<const CuCloth&>(cloth);
if (cuCloth.mParticleAccelerationsHostCopy.size())
{
@@ -359,7 +358,7 @@ void cloth::CuFactory::extractVirtualParticles(const Cloth& cloth, Range<uint32_
CuContextLock contextLock(*this);
- const CuCloth& cuCloth = static_cast<const CuClothImpl&>(cloth).mCloth;
+ const CuCloth& cuCloth = static_cast<const CuCloth&>(cloth);
if (destWeights.size() > 0)
{
@@ -400,7 +399,7 @@ void cloth::CuFactory::extractVirtualParticles(const Cloth& cloth, Range<uint32_
void cloth::CuFactory::extractSelfCollisionIndices(const Cloth& cloth, Range<uint32_t> destIndices) const
{
- const CuCloth& cuCloth = static_cast<const CuClothImpl&>(cloth).mCloth;
+ const CuCloth& cuCloth = static_cast<const CuCloth&>(cloth);
NV_CLOTH_ASSERT(destIndices.size() == cuCloth.mSelfCollisionIndices.size());
copyToHost(cuCloth.mSelfCollisionIndices.begin().get(), cuCloth.mSelfCollisionIndices.end().get(),
destIndices.begin());
@@ -408,7 +407,7 @@ void cloth::CuFactory::extractSelfCollisionIndices(const Cloth& cloth, Range<uin
void cloth::CuFactory::extractRestPositions(const Cloth& cloth, Range<PxVec4> destRestPositions) const
{
- const CuCloth& cuCloth = static_cast<const CuClothImpl&>(cloth).mCloth;
+ const CuCloth& cuCloth = static_cast<const CuCloth&>(cloth);
NV_CLOTH_ASSERT(destRestPositions.size() == cuCloth.mRestPositions.size());
copyToHost(cuCloth.mRestPositions.begin().get(), cuCloth.mRestPositions.end().get(), destRestPositions.begin());
}
diff --git a/NvCloth/src/cuda/CuFactory.h b/NvCloth/src/cuda/CuFactory.h
index 81799ec..3ff5752 100644
--- a/NvCloth/src/cuda/CuFactory.h
+++ b/NvCloth/src/cuda/CuFactory.h
@@ -52,7 +52,7 @@ class CuFactory : public Factory
public:
typedef CuFabric FabricType;
- typedef ClothImpl<CuCloth> ImplType;
+ typedef CuCloth ClothType;
CuFactory(CUcontext);
virtual ~CuFactory();
diff --git a/NvCloth/src/cuda/CuSolver.cpp b/NvCloth/src/cuda/CuSolver.cpp
index 7927a42..f0e328f 100644
--- a/NvCloth/src/cuda/CuSolver.cpp
+++ b/NvCloth/src/cuda/CuSolver.cpp
@@ -326,7 +326,7 @@ struct ClothSimCostGreater
void cloth::CuSolver::addCloth(Cloth* cloth)
{
- CuCloth& cuCloth = static_cast<CuClothImpl&>(*cloth).mCloth;
+ CuCloth& cuCloth = *static_cast<CuCloth*>(cloth);
NV_CLOTH_ASSERT(mCloths.find(&cuCloth) == mCloths.end());
@@ -348,7 +348,7 @@ void cloth::CuSolver::addCloth(Cloth* cloth)
void cloth::CuSolver::removeCloth(Cloth* cloth)
{
- CuCloth& cuCloth = static_cast<CuClothImpl&>(*cloth).mCloth;
+ CuCloth& cuCloth = static_cast<CuCloth&>(*cloth);
ClothVector::Iterator begin = mCloths.begin(), end = mCloths.end();
ClothVector::Iterator it = mCloths.find(&cuCloth);
@@ -364,6 +364,18 @@ void cloth::CuSolver::removeCloth(Cloth* cloth)
mClothDataDirty = true;
}
+int cloth::CuSolver::getNumCloths() const
+{
+ return mCloths.size();
+}
+cloth::Cloth * const * cloth::CuSolver::getClothList() const
+{
+ if(getNumCloths())
+ return reinterpret_cast<Cloth* const*>(&mCloths[0]);
+ else
+ return nullptr;
+}
+
bool cloth::CuSolver::beginSimulation(float dt)
{
if (mCloths.empty())
diff --git a/NvCloth/src/cuda/CuSolver.h b/NvCloth/src/cuda/CuSolver.h
index 8e256a7..0406e00 100644
--- a/NvCloth/src/cuda/CuSolver.h
+++ b/NvCloth/src/cuda/CuSolver.h
@@ -57,8 +57,10 @@ public:
CuSolver(CuFactory&);
~CuSolver();
- virtual void addCloth(Cloth*);
- virtual void removeCloth(Cloth*);
+ virtual void addCloth(Cloth*) override;
+ virtual void removeCloth(Cloth*) override;
+ virtual int getNumCloths() const override;
+ virtual Cloth * const * getClothList() const override;
// functions executing the simulation work.
virtual bool beginSimulation(float dt);