diff options
Diffstat (limited to 'PhysX_3.4/Source/LowLevelCloth/src/ClothImpl.h')
| -rw-r--r-- | PhysX_3.4/Source/LowLevelCloth/src/ClothImpl.h | 1302 |
1 files changed, 1302 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/LowLevelCloth/src/ClothImpl.h b/PhysX_3.4/Source/LowLevelCloth/src/ClothImpl.h new file mode 100644 index 00000000..2cc491c5 --- /dev/null +++ b/PhysX_3.4/Source/LowLevelCloth/src/ClothImpl.h @@ -0,0 +1,1302 @@ +// 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) 2008-2016 NVIDIA Corporation. All rights reserved. +// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved. +// Copyright (c) 2001-2004 NovodeX AG. All rights reserved. + +#pragma once + +#include "Cloth.h" +#include "Fabric.h" +#include "Allocator.h" +#include "PsMathUtils.h" + +namespace physx +{ +namespace cloth +{ + +// SwCloth or CuCloth aggregate implementing the Cloth interface +// Member specializations are implemented in Sw/CuCloth.cpp +template <typename T> +class ClothImpl : public UserAllocated, public Cloth +{ + ClothImpl(const ClothImpl&); + + public: + ClothImpl& operator=(const ClothImpl&); + + typedef T ClothType; + typedef typename ClothType::FactoryType FactoryType; + typedef typename ClothType::FabricType FabricType; + typedef typename ClothType::ContextLockType ContextLockType; + + ClothImpl(Factory&, Fabric&, Range<const PxVec4>); + ClothImpl(Factory&, const ClothImpl&); + + virtual Cloth* clone(Factory& factory) const; + + virtual Fabric& getFabric() const; + virtual Factory& getFactory() const; + + virtual uint32_t getNumParticles() const; + virtual void lockParticles() const; + virtual void unlockParticles() const; + virtual MappedRange<PxVec4> getCurrentParticles(); + virtual MappedRange<const PxVec4> getCurrentParticles() const; + virtual MappedRange<PxVec4> getPreviousParticles(); + virtual MappedRange<const PxVec4> getPreviousParticles() const; + virtual GpuParticles getGpuParticles(); + + virtual void setTranslation(const PxVec3& trans); + virtual void setRotation(const PxQuat& rot); + + virtual const PxVec3& getTranslation() const; + virtual const PxQuat& getRotation() const; + + virtual void clearInertia(); + + virtual void teleport(const PxVec3& delta); + + virtual float getPreviousIterationDt() const; + virtual void setGravity(const PxVec3& gravity); + virtual PxVec3 getGravity() const; + virtual void setDamping(const PxVec3& damping); + virtual PxVec3 getDamping() const; + virtual void setLinearDrag(const PxVec3& drag); + virtual PxVec3 getLinearDrag() const; + virtual void setAngularDrag(const PxVec3& drag); + virtual PxVec3 getAngularDrag() const; + virtual void setLinearInertia(const PxVec3& inertia); + virtual PxVec3 getLinearInertia() const; + virtual void setAngularInertia(const PxVec3& inertia); + virtual PxVec3 getAngularInertia() const; + virtual void setCentrifugalInertia(const PxVec3& inertia); + virtual PxVec3 getCentrifugalInertia() const; + + virtual void setSolverFrequency(float frequency); + virtual float getSolverFrequency() const; + + virtual void setStiffnessFrequency(float frequency); + virtual float getStiffnessFrequency() const; + + virtual void setAcceleationFilterWidth(uint32_t); + virtual uint32_t getAccelerationFilterWidth() const; + + virtual void setPhaseConfig(Range<const PhaseConfig> configs); + + virtual void setSpheres(Range<const PxVec4>, uint32_t first, uint32_t last); + virtual uint32_t getNumSpheres() const; + + virtual void setCapsules(Range<const uint32_t>, uint32_t first, uint32_t last); + virtual uint32_t getNumCapsules() const; + + virtual void setPlanes(Range<const PxVec4>, uint32_t first, uint32_t last); + virtual uint32_t getNumPlanes() const; + + virtual void setConvexes(Range<const uint32_t>, uint32_t first, uint32_t last); + virtual uint32_t getNumConvexes() const; + + virtual void setTriangles(Range<const PxVec3>, uint32_t first, uint32_t last); + virtual void setTriangles(Range<const PxVec3>, Range<const PxVec3>, uint32_t first); + virtual uint32_t getNumTriangles() const; + + virtual bool isContinuousCollisionEnabled() const; + virtual void enableContinuousCollision(bool); + + virtual float getCollisionMassScale() const; + virtual void setCollisionMassScale(float); + virtual void setFriction(float friction); + virtual float getFriction() const; + + virtual void setVirtualParticles(Range<const uint32_t[4]>, Range<const PxVec3>); + virtual uint32_t getNumVirtualParticles() const; + virtual uint32_t getNumVirtualParticleWeights() const; + + virtual void setTetherConstraintScale(float scale); + virtual float getTetherConstraintScale() const; + virtual void setTetherConstraintStiffness(float stiffness); + virtual float getTetherConstraintStiffness() const; + + virtual Range<PxVec4> getMotionConstraints(); + virtual void clearMotionConstraints(); + virtual uint32_t getNumMotionConstraints() const; + virtual void setMotionConstraintScaleBias(float scale, float bias); + virtual float getMotionConstraintScale() const; + virtual float getMotionConstraintBias() const; + virtual void setMotionConstraintStiffness(float stiffness); + virtual float getMotionConstraintStiffness() const; + + virtual Range<PxVec4> getSeparationConstraints(); + virtual void clearSeparationConstraints(); + virtual uint32_t getNumSeparationConstraints() const; + + virtual void clearInterpolation(); + + virtual Range<PxVec4> getParticleAccelerations(); + virtual void clearParticleAccelerations(); + virtual uint32_t getNumParticleAccelerations() const; + + virtual void setWindVelocity(PxVec3); + virtual PxVec3 getWindVelocity() const; + virtual void setDragCoefficient(float); + virtual float getDragCoefficient() const; + virtual void setLiftCoefficient(float); + virtual float getLiftCoefficient() const; + + virtual void setSelfCollisionDistance(float); + virtual float getSelfCollisionDistance() const; + virtual void setSelfCollisionStiffness(float); + virtual float getSelfCollisionStiffness() const; + + virtual void setSelfCollisionIndices(Range<const uint32_t>); + virtual uint32_t getNumSelfCollisionIndices() const; + + virtual void setRestPositions(Range<const PxVec4>); + virtual uint32_t getNumRestPositions() const; + + virtual const PxVec3& getBoundingBoxCenter() const; + virtual const PxVec3& getBoundingBoxScale() const; + + virtual void setSleepThreshold(float); + virtual float getSleepThreshold() const; + virtual void setSleepTestInterval(uint32_t); + virtual uint32_t getSleepTestInterval() const; + virtual void setSleepAfterCount(uint32_t); + virtual uint32_t getSleepAfterCount() const; + virtual uint32_t getSleepPassCount() const; + virtual bool isAsleep() const; + virtual void putToSleep(); + virtual void wakeUp(); + + virtual void setUserData(void*); + virtual void* getUserData() const; + + // helper function + template <typename U> + MappedRange<U> getMappedParticles(U* data) const; + + ClothType mCloth; +}; + +class SwCloth; +typedef ClothImpl<SwCloth> SwClothImpl; + +class CuCloth; +typedef ClothImpl<CuCloth> CuClothImpl; + +class DxCloth; +typedef ClothImpl<DxCloth> DxClothImpl; + +template <typename T> +ClothImpl<T>::ClothImpl(Factory& factory, Fabric& fabric, Range<const PxVec4> particles) +: mCloth(static_cast<FactoryType&>(factory), static_cast<FabricType&>(fabric), particles) +{ + // fabric and cloth need to be created by the same factory + PX_ASSERT(&fabric.getFactory() == &factory); +} + +template <typename T> +ClothImpl<T>::ClothImpl(Factory& factory, const ClothImpl& impl) +: mCloth(static_cast<FactoryType&>(factory), impl.mCloth) +{ +} + +template <typename T> +inline Fabric& ClothImpl<T>::getFabric() const +{ + return mCloth.mFabric; +} + +template <typename T> +inline Factory& ClothImpl<T>::getFactory() const +{ + return mCloth.mFactory; +} + +template <typename T> +inline void ClothImpl<T>::setTranslation(const PxVec3& trans) +{ + PxVec3 t = reinterpret_cast<const PxVec3&>(trans); + if(t == mCloth.mTargetMotion.p) + return; + + mCloth.mTargetMotion.p = t; + mCloth.wakeUp(); +} + +template <typename T> +inline void ClothImpl<T>::setRotation(const PxQuat& q) +{ + if((q - mCloth.mTargetMotion.q).magnitudeSquared() == 0.0f) + return; + + mCloth.mTargetMotion.q = q; + mCloth.wakeUp(); +} + +template <typename T> +inline const PxVec3& ClothImpl<T>::getTranslation() const +{ + return mCloth.mTargetMotion.p; +} + +template <typename T> +inline const PxQuat& ClothImpl<T>::getRotation() const +{ + return mCloth.mTargetMotion.q; +} + +template <typename T> +inline void ClothImpl<T>::clearInertia() +{ + mCloth.mCurrentMotion = mCloth.mTargetMotion; + mCloth.mLinearVelocity = PxVec3(0.0f); + mCloth.mAngularVelocity = PxVec3(0.0f); + + mCloth.wakeUp(); +} + +// Fixed 4505:local function has been removed +template <typename T> +inline void ClothImpl<T>::teleport(const PxVec3& delta) +{ + mCloth.mCurrentMotion.p += delta; + mCloth.mTargetMotion.p += delta; +} + +template <typename T> +inline float ClothImpl<T>::getPreviousIterationDt() const +{ + return mCloth.mPrevIterDt; +} + +template <typename T> +inline void ClothImpl<T>::setGravity(const PxVec3& gravity) +{ + PxVec3 value = gravity; + if(value == mCloth.mGravity) + return; + + mCloth.mGravity = value; + mCloth.wakeUp(); +} + +template <typename T> +inline PxVec3 ClothImpl<T>::getGravity() const +{ + return mCloth.mGravity; +} + +inline float safeLog2(float x) +{ + return x ? shdfnd::log2(x) : -FLT_MAX_EXP; +} + +inline PxVec3 safeLog2(const PxVec3& v) +{ + return PxVec3(safeLog2(v.x), safeLog2(v.y), safeLog2(v.z)); +} + +inline float safeExp2(float x) +{ + if(x <= -FLT_MAX_EXP) + return 0.0f; + else + return shdfnd::exp2(x); +} + +inline PxVec3 safeExp2(const PxVec3& v) +{ + return PxVec3(safeExp2(v.x), safeExp2(v.y), safeExp2(v.z)); +} + +template <typename T> +inline void ClothImpl<T>::setDamping(const PxVec3& damping) +{ + PxVec3 value = safeLog2(PxVec3(1.f) - damping); + if(value == mCloth.mLogDamping) + return; + + mCloth.mLogDamping = value; + mCloth.wakeUp(); +} + +template <typename T> +inline PxVec3 ClothImpl<T>::getDamping() const +{ + return PxVec3(1.f) - safeExp2(mCloth.mLogDamping); +} + +template <typename T> +inline void ClothImpl<T>::setLinearDrag(const PxVec3& drag) +{ + PxVec3 value = safeLog2(PxVec3(1.f) - drag); + if(value == mCloth.mLinearLogDrag) + return; + + mCloth.mLinearLogDrag = value; + mCloth.wakeUp(); +} + +template <typename T> +inline PxVec3 ClothImpl<T>::getLinearDrag() const +{ + return PxVec3(1.f) - safeExp2(mCloth.mLinearLogDrag); +} + +template <typename T> +inline void ClothImpl<T>::setAngularDrag(const PxVec3& drag) +{ + PxVec3 value = safeLog2(PxVec3(1.f) - drag); + if(value == mCloth.mAngularLogDrag) + return; + + mCloth.mAngularLogDrag = value; + mCloth.wakeUp(); +} + +template <typename T> +inline PxVec3 ClothImpl<T>::getAngularDrag() const +{ + return PxVec3(1.f) - safeExp2(mCloth.mAngularLogDrag); +} + +template <typename T> +inline void ClothImpl<T>::setLinearInertia(const PxVec3& inertia) +{ + PxVec3 value = inertia; + if(value == mCloth.mLinearInertia) + return; + + mCloth.mLinearInertia = value; + mCloth.wakeUp(); +} + +template <typename T> +inline PxVec3 ClothImpl<T>::getLinearInertia() const +{ + return mCloth.mLinearInertia; +} + +template <typename T> +inline void ClothImpl<T>::setAngularInertia(const PxVec3& inertia) +{ + PxVec3 value = inertia; + if(value == mCloth.mAngularInertia) + return; + + mCloth.mAngularInertia = value; + mCloth.wakeUp(); +} + +template <typename T> +inline PxVec3 ClothImpl<T>::getAngularInertia() const +{ + return mCloth.mAngularInertia; +} + +template <typename T> +inline void ClothImpl<T>::setCentrifugalInertia(const PxVec3& inertia) +{ + PxVec3 value = inertia; + if(value == mCloth.mCentrifugalInertia) + return; + + mCloth.mCentrifugalInertia = value; + mCloth.wakeUp(); +} + +template <typename T> +inline PxVec3 ClothImpl<T>::getCentrifugalInertia() const +{ + return mCloth.mCentrifugalInertia; +} + +template <typename T> +inline void ClothImpl<T>::setSolverFrequency(float frequency) +{ + if(frequency == mCloth.mSolverFrequency) + return; + + mCloth.mSolverFrequency = frequency; + mCloth.mIterDtAvg.reset(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getSolverFrequency() const +{ + return mCloth.mSolverFrequency; +} + +template <typename T> +inline void ClothImpl<T>::setStiffnessFrequency(float frequency) +{ + if(frequency == mCloth.mStiffnessFrequency) + return; + + mCloth.mStiffnessFrequency = frequency; + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getStiffnessFrequency() const +{ + return mCloth.mStiffnessFrequency; +} + +template <typename T> +inline void ClothImpl<T>::setAcceleationFilterWidth(uint32_t n) +{ + mCloth.mIterDtAvg.resize(n); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getAccelerationFilterWidth() const +{ + return mCloth.mIterDtAvg.size(); +} + +// move a subarray +template <typename Iter> +void move(Iter it, uint32_t first, uint32_t last, uint32_t result) +{ + if(result > first) + { + result += last - first; + while(first < last) + it[--result] = it[--last]; + } + else + { + while(first < last) + it[result++] = it[first++]; + } +} + +// update capsule index +inline bool updateIndex(uint32_t& index, uint32_t first, int32_t delta) +{ + return index >= first && int32_t(index += delta) < int32_t(first); +} + +template <typename T> +inline void ClothImpl<T>::setSpheres(Range<const PxVec4> spheres, uint32_t first, uint32_t last) +{ + uint32_t oldSize = uint32_t(mCloth.mStartCollisionSpheres.size()); + uint32_t newSize = uint32_t(spheres.size()) + oldSize - last + first; + + PX_ASSERT(newSize <= 32); + PX_ASSERT(first <= oldSize); + PX_ASSERT(last <= oldSize); + +#if PX_DEBUG + for(const PxVec4* it = spheres.begin(); it < spheres.end(); ++it) + PX_ASSERT(it->w >= 0.0f); +#endif + + if(!oldSize && !newSize) + return; + + if(!oldSize) + { + ContextLockType contextLock(mCloth.mFactory); + mCloth.mStartCollisionSpheres.assign(spheres.begin(), spheres.end()); + mCloth.notifyChanged(); + } + else + { + if(PxMax(oldSize, newSize) > + PxMin(mCloth.mStartCollisionSpheres.capacity(), mCloth.mTargetCollisionSpheres.capacity())) + { + ContextLockType contextLock(mCloth.mFactory); + mCloth.mStartCollisionSpheres.reserve(newSize); + mCloth.mTargetCollisionSpheres.reserve(PxMax(oldSize, newSize)); + } + + typename T::MappedVec4fVectorType start = mCloth.mStartCollisionSpheres; + typename T::MappedVec4fVectorType target = mCloth.mTargetCollisionSpheres; + + // fill target from start + for(uint32_t i = target.size(); i < oldSize; ++i) + target.pushBack(start[i]); + + // resize to larger of oldSize and newSize + start.resize(PxMax(oldSize, newSize), PxVec4(0.0f)); + target.resize(PxMax(oldSize, newSize), PxVec4(0.0f)); + + if(int32_t delta = int32_t(newSize - oldSize)) + { + // move past-range elements to new place + move(start.begin(), last, oldSize, last + delta); + move(target.begin(), last, oldSize, last + delta); + + // fill new elements from spheres + for(uint32_t i = last; i < last + delta; ++i) + start[i] = spheres[i - first]; + + // adjust capsule indices + typename T::MappedIndexVectorType indices = mCloth.mCapsuleIndices; + Vector<IndexPair>::Type::Iterator cIt, cEnd = indices.end(); + for(cIt = indices.begin(); cIt != cEnd;) + { + bool removed = false; + removed |= updateIndex(cIt->first, last + PxMin(0, delta), int32_t(delta)); + removed |= updateIndex(cIt->second, last + PxMin(0, delta), int32_t(delta)); + if(!removed) + ++cIt; + else + { + indices.replaceWithLast(cIt); + cEnd = indices.end(); + } + } + + start.resize(newSize); + target.resize(newSize); + + mCloth.notifyChanged(); + } + + // fill target elements with spheres + for(uint32_t i = 0; i < spheres.size(); ++i) + target[first + i] = spheres[i]; + } + + mCloth.wakeUp(); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumSpheres() const +{ + return uint32_t(mCloth.mStartCollisionSpheres.size()); +} + +// Fixed 4505:local function has been removed +template <typename T> +inline void ClothImpl<T>::setCapsules(Range<const uint32_t> capsules, uint32_t first, uint32_t last) +{ + uint32_t oldSize = mCloth.mCapsuleIndices.size(); + uint32_t newSize = uint32_t(capsules.size() / 2) + oldSize - last + first; + + PX_ASSERT(newSize <= 32); + PX_ASSERT(first <= oldSize); + PX_ASSERT(last <= oldSize); + + const IndexPair* srcIndices = reinterpret_cast<const IndexPair*>(capsules.begin()); + + if(mCloth.mCapsuleIndices.capacity() < newSize) + { + ContextLockType contextLock(mCloth.mFactory); + mCloth.mCapsuleIndices.reserve(newSize); + } + + // resize to larger of oldSize and newSize + mCloth.mCapsuleIndices.resize(PxMax(oldSize, newSize)); + + typename T::MappedIndexVectorType dstIndices = mCloth.mCapsuleIndices; + + if(uint32_t delta = newSize - oldSize) + { + // move past-range elements to new place + move(dstIndices.begin(), last, oldSize, last + delta); + + // fill new elements from capsules + for(uint32_t i = last; i < last + delta; ++i) + dstIndices[i] = srcIndices[i - first]; + + dstIndices.resize(newSize); + mCloth.notifyChanged(); + } + + // fill existing elements from capsules + for(uint32_t i = first; i < last; ++i) + dstIndices[i] = srcIndices[i - first]; + + mCloth.wakeUp(); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumCapsules() const +{ + return uint32_t(mCloth.mCapsuleIndices.size()); +} + +template <typename T> +inline void ClothImpl<T>::setPlanes(Range<const PxVec4> planes, uint32_t first, uint32_t last) +{ + uint32_t oldSize = uint32_t(mCloth.mStartCollisionPlanes.size()); + uint32_t newSize = uint32_t(planes.size()) + oldSize - last + first; + + PX_ASSERT(newSize <= 32); + PX_ASSERT(first <= oldSize); + PX_ASSERT(last <= oldSize); + + if(!oldSize && !newSize) + return; + + if(!oldSize) + { + ContextLockType contextLock(mCloth.mFactory); + mCloth.mStartCollisionPlanes.assign(planes.begin(), planes.end()); + mCloth.notifyChanged(); + } + else + { + if(PxMax(oldSize, newSize) > + PxMin(mCloth.mStartCollisionPlanes.capacity(), mCloth.mTargetCollisionPlanes.capacity())) + { + ContextLockType contextLock(mCloth.mFactory); + mCloth.mStartCollisionPlanes.reserve(newSize); + mCloth.mTargetCollisionPlanes.reserve(PxMax(oldSize, newSize)); + } + + // fill target from start + for(uint32_t i = mCloth.mTargetCollisionPlanes.size(); i < oldSize; ++i) + mCloth.mTargetCollisionPlanes.pushBack(mCloth.mStartCollisionPlanes[i]); + + // resize to larger of oldSize and newSize + mCloth.mStartCollisionPlanes.resize(PxMax(oldSize, newSize), PxZero); + mCloth.mTargetCollisionPlanes.resize(PxMax(oldSize, newSize), PxZero); + + if(int32_t delta = int32_t(newSize - oldSize)) + { + // move past-range elements to new place + move(mCloth.mStartCollisionPlanes.begin(), last, oldSize, last + delta); + move(mCloth.mTargetCollisionPlanes.begin(), last, oldSize, last + delta); + + // fill new elements from planes + for(uint32_t i = last; i < last + delta; ++i) + mCloth.mStartCollisionPlanes[i] = planes[i - first]; + + // adjust convex indices + uint32_t mask = (uint32_t(1) << (last + PxMin(delta, 0))) - 1; + Vector<uint32_t>::Type::Iterator cIt, cEnd = mCloth.mConvexMasks.end(); + for(cIt = mCloth.mConvexMasks.begin(); cIt != cEnd;) + { + uint32_t convex = (*cIt & mask); + if(delta < 0) + convex |= *cIt >> -delta & ~mask; + else + convex |= (*cIt & ~mask) << delta; + if(convex) + *cIt++ = convex; + else + { + mCloth.mConvexMasks.replaceWithLast(cIt); + cEnd = mCloth.mConvexMasks.end(); + } + } + + mCloth.mStartCollisionPlanes.resize(newSize); + mCloth.mTargetCollisionPlanes.resize(newSize); + + mCloth.notifyChanged(); + } + + // fill target elements with planes + for(uint32_t i = 0; i < planes.size(); ++i) + mCloth.mTargetCollisionPlanes[first + i] = planes[i]; + } + + mCloth.wakeUp(); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumPlanes() const +{ + return uint32_t(mCloth.mStartCollisionPlanes.size()); +} + +template <typename T> +inline void ClothImpl<T>::setConvexes(Range<const uint32_t> convexes, uint32_t first, uint32_t last) +{ + uint32_t oldSize = mCloth.mConvexMasks.size(); + uint32_t newSize = uint32_t(convexes.size()) + oldSize - last + first; + + PX_ASSERT(newSize <= 32); + PX_ASSERT(first <= oldSize); + PX_ASSERT(last <= oldSize); + + if(mCloth.mConvexMasks.capacity() < newSize) + { + ContextLockType contextLock(mCloth.mFactory); + mCloth.mConvexMasks.reserve(newSize); + } + + // resize to larger of oldSize and newSize + mCloth.mConvexMasks.resize(PxMax(oldSize, newSize)); + + if(uint32_t delta = newSize - oldSize) + { + // move past-range elements to new place + move(mCloth.mConvexMasks.begin(), last, oldSize, last + delta); + + // fill new elements from capsules + for(uint32_t i = last; i < last + delta; ++i) + mCloth.mConvexMasks[i] = convexes[i - first]; + + mCloth.mConvexMasks.resize(newSize); + mCloth.notifyChanged(); + } + + mCloth.wakeUp(); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumConvexes() const +{ + return uint32_t(mCloth.mConvexMasks.size()); +} + +template <typename T> +inline void ClothImpl<T>::setTriangles(Range<const PxVec3> triangles, uint32_t first, uint32_t last) +{ + // convert from triangle to vertex count + first *= 3; + last *= 3; + + triangles = mCloth.clampTriangleCount(triangles, last - first); + PX_ASSERT(0 == triangles.size() % 3); + + uint32_t oldSize = uint32_t(mCloth.mStartCollisionTriangles.size()); + uint32_t newSize = uint32_t(triangles.size()) + oldSize - last + first; + + PX_ASSERT(first <= oldSize); + PX_ASSERT(last <= oldSize); + + if(!oldSize && !newSize) + return; + + if(!oldSize) + { + ContextLockType contextLock(mCloth.mFactory); + mCloth.mStartCollisionTriangles.assign(triangles.begin(), triangles.end()); + mCloth.notifyChanged(); + } + else + { + if(PxMax(oldSize, newSize) > + PxMin(mCloth.mStartCollisionTriangles.capacity(), mCloth.mTargetCollisionTriangles.capacity())) + { + ContextLockType contextLock(mCloth.mFactory); + mCloth.mStartCollisionTriangles.reserve(newSize); + mCloth.mTargetCollisionTriangles.reserve(PxMax(oldSize, newSize)); + } + + // fill target from start + for(uint32_t i = mCloth.mTargetCollisionTriangles.size(); i < oldSize; ++i) + mCloth.mTargetCollisionTriangles.pushBack(mCloth.mStartCollisionTriangles[i]); + + // resize to larger of oldSize and newSize + mCloth.mStartCollisionTriangles.resize(PxMax(oldSize, newSize)); + mCloth.mTargetCollisionTriangles.resize(PxMax(oldSize, newSize)); + + if(uint32_t delta = newSize - oldSize) + { + // move past-range elements to new place + move(mCloth.mStartCollisionTriangles.begin(), last, oldSize, last + delta); + move(mCloth.mTargetCollisionTriangles.begin(), last, oldSize, last + delta); + + // fill new elements from triangles + for(uint32_t i = last; i < last + delta; ++i) + mCloth.mStartCollisionTriangles[i] = triangles[i - first]; + + mCloth.mStartCollisionTriangles.resize(newSize); + mCloth.mTargetCollisionTriangles.resize(newSize); + + mCloth.notifyChanged(); + } + + // fill target elements with triangles + for(uint32_t i = 0; i < triangles.size(); ++i) + mCloth.mTargetCollisionTriangles[first + i] = triangles[i]; + } + + mCloth.wakeUp(); +} + +template <typename T> +inline void ClothImpl<T>::setTriangles(Range<const PxVec3> startTriangles, Range<const PxVec3> targetTriangles, + uint32_t first) +{ + PX_ASSERT(startTriangles.size() == targetTriangles.size()); + + // convert from triangle to vertex count + first *= 3; + + uint32_t last = uint32_t(mCloth.mStartCollisionTriangles.size()); + + startTriangles = mCloth.clampTriangleCount(startTriangles, last - first); + targetTriangles = mCloth.clampTriangleCount(targetTriangles, last - first); + + uint32_t oldSize = uint32_t(mCloth.mStartCollisionTriangles.size()); + uint32_t newSize = uint32_t(startTriangles.size()) + oldSize - last + first; + + PX_ASSERT(first <= oldSize); + PX_ASSERT(last == oldSize); // this path only supports replacing the tail + + if(!oldSize && !newSize) + return; + + if(newSize > PxMin(mCloth.mStartCollisionTriangles.capacity(), mCloth.mTargetCollisionTriangles.capacity())) + { + ContextLockType contextLock(mCloth.mFactory); + mCloth.mStartCollisionTriangles.reserve(newSize); + mCloth.mTargetCollisionTriangles.reserve(newSize); + } + + uint32_t retainSize = oldSize - last + first; + mCloth.mStartCollisionTriangles.resize(retainSize); + mCloth.mTargetCollisionTriangles.resize(retainSize); + + for(uint32_t i = 0, n = startTriangles.size(); i < n; ++i) + { + mCloth.mStartCollisionTriangles.pushBack(startTriangles[i]); + mCloth.mTargetCollisionTriangles.pushBack(targetTriangles[i]); + } + + if(newSize - oldSize) + mCloth.notifyChanged(); + + mCloth.wakeUp(); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumTriangles() const +{ + return uint32_t(mCloth.mStartCollisionTriangles.size()) / 3; +} + +template <typename T> +inline bool ClothImpl<T>::isContinuousCollisionEnabled() const +{ + return mCloth.mEnableContinuousCollision; +} + +template <typename T> +inline void ClothImpl<T>::enableContinuousCollision(bool enable) +{ + if(enable == mCloth.mEnableContinuousCollision) + return; + + mCloth.mEnableContinuousCollision = enable; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getCollisionMassScale() const +{ + return mCloth.mCollisionMassScale; +} + +template <typename T> +inline void ClothImpl<T>::setCollisionMassScale(float scale) +{ + if(scale == mCloth.mCollisionMassScale) + return; + + mCloth.mCollisionMassScale = scale; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline void ClothImpl<T>::setFriction(float friction) +{ + mCloth.mFriction = friction; + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getFriction() const +{ + return mCloth.mFriction; +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumVirtualParticleWeights() const +{ + return uint32_t(mCloth.mVirtualParticleWeights.size()); +} + +template <typename T> +inline void ClothImpl<T>::setTetherConstraintScale(float scale) +{ + if(scale == mCloth.mTetherConstraintScale) + return; + + mCloth.mTetherConstraintScale = scale; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getTetherConstraintScale() const +{ + return mCloth.mTetherConstraintScale; +} + +template <typename T> +inline void ClothImpl<T>::setTetherConstraintStiffness(float stiffness) +{ + float value = safeLog2(1 - stiffness); + if(value == mCloth.mTetherConstraintLogStiffness) + return; + + mCloth.mTetherConstraintLogStiffness = value; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getTetherConstraintStiffness() const +{ + return 1 - safeExp2(mCloth.mTetherConstraintLogStiffness); +} + +template <typename T> +inline Range<PxVec4> ClothImpl<T>::getMotionConstraints() +{ + mCloth.wakeUp(); + return mCloth.push(mCloth.mMotionConstraints); +} + +template <typename T> +inline void ClothImpl<T>::clearMotionConstraints() +{ + mCloth.clear(mCloth.mMotionConstraints); + mCloth.wakeUp(); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumMotionConstraints() const +{ + return uint32_t(mCloth.mMotionConstraints.mStart.size()); +} + +template <typename T> +inline void ClothImpl<T>::setMotionConstraintScaleBias(float scale, float bias) +{ + if(scale == mCloth.mMotionConstraintScale && bias == mCloth.mMotionConstraintBias) + return; + + mCloth.mMotionConstraintScale = scale; + mCloth.mMotionConstraintBias = bias; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getMotionConstraintScale() const +{ + return mCloth.mMotionConstraintScale; +} + +template <typename T> +inline float ClothImpl<T>::getMotionConstraintBias() const +{ + return mCloth.mMotionConstraintBias; +} + +template <typename T> +inline void ClothImpl<T>::setMotionConstraintStiffness(float stiffness) +{ + float value = safeLog2(1 - stiffness); + if(value == mCloth.mMotionConstraintLogStiffness) + return; + + mCloth.mMotionConstraintLogStiffness = value; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getMotionConstraintStiffness() const +{ + return 1 - safeExp2(mCloth.mMotionConstraintLogStiffness); +} + +template <typename T> +inline Range<PxVec4> ClothImpl<T>::getSeparationConstraints() +{ + mCloth.wakeUp(); + return mCloth.push(mCloth.mSeparationConstraints); +} + +template <typename T> +inline void ClothImpl<T>::clearSeparationConstraints() +{ + mCloth.clear(mCloth.mSeparationConstraints); + mCloth.wakeUp(); +} + +template <typename T> +inline void ClothImpl<T>::clearInterpolation() +{ + if(!mCloth.mTargetCollisionSpheres.empty()) + { + physx::shdfnd::swap(mCloth.mStartCollisionSpheres, mCloth.mTargetCollisionSpheres); + mCloth.mTargetCollisionSpheres.resize(0); + } + mCloth.mMotionConstraints.pop(); + mCloth.mSeparationConstraints.pop(); + mCloth.wakeUp(); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumSeparationConstraints() const +{ + return uint32_t(mCloth.mSeparationConstraints.mStart.size()); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumParticleAccelerations() const +{ + return uint32_t(mCloth.mParticleAccelerations.size()); +} + +template <typename T> +inline void ClothImpl<T>::setWindVelocity(PxVec3 wind) +{ + if(wind == mCloth.mWind) + return; + + mCloth.mWind = wind; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline PxVec3 ClothImpl<T>::getWindVelocity() const +{ + return mCloth.mWind; +} + +template <typename T> +inline void ClothImpl<T>::setDragCoefficient(float coefficient) +{ + float value = safeLog2(1 - coefficient); + if(value == mCloth.mDragLogCoefficient) + return; + + mCloth.mDragLogCoefficient = value; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getDragCoefficient() const +{ + return 1 - safeExp2(mCloth.mDragLogCoefficient); +} + +template <typename T> +inline void ClothImpl<T>::setLiftCoefficient(float coefficient) +{ + float value = safeLog2(1 - coefficient); + if(value == mCloth.mLiftLogCoefficient) + return; + + mCloth.mLiftLogCoefficient = value; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getLiftCoefficient() const +{ + return 1 - safeExp2(mCloth.mLiftLogCoefficient); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumSelfCollisionIndices() const +{ + return uint32_t(mCloth.mSelfCollisionIndices.size()); +} + +// Fixed 4505:local function has been removed +template <typename T> +inline void ClothImpl<T>::setRestPositions(Range<const PxVec4> restPositions) +{ + PX_ASSERT(restPositions.empty() || restPositions.size() == getNumParticles()); + ContextLockType contextLock(mCloth.mFactory); + mCloth.mRestPositions.assign(restPositions.begin(), restPositions.end()); + mCloth.wakeUp(); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getNumRestPositions() const +{ + return uint32_t(mCloth.mRestPositions.size()); +} + +template <typename T> +inline void ClothImpl<T>::setSelfCollisionDistance(float distance) +{ + if(distance == mCloth.mSelfCollisionDistance) + return; + + mCloth.mSelfCollisionDistance = distance; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getSelfCollisionDistance() const +{ + return mCloth.mSelfCollisionDistance; +} + +template <typename T> +inline void ClothImpl<T>::setSelfCollisionStiffness(float stiffness) +{ + float value = safeLog2(1 - stiffness); + if(value == mCloth.mSelfCollisionLogStiffness) + return; + + mCloth.mSelfCollisionLogStiffness = value; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getSelfCollisionStiffness() const +{ + return 1 - safeExp2(mCloth.mSelfCollisionLogStiffness); +} + +template <typename T> +inline const PxVec3& ClothImpl<T>::getBoundingBoxCenter() const +{ + return mCloth.mParticleBoundsCenter; +} + +template <typename T> +inline const PxVec3& ClothImpl<T>::getBoundingBoxScale() const +{ + return mCloth.mParticleBoundsHalfExtent; +} + +template <typename T> +inline void ClothImpl<T>::setSleepThreshold(float threshold) +{ + if(threshold == mCloth.mSleepThreshold) + return; + + mCloth.mSleepThreshold = threshold; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline float ClothImpl<T>::getSleepThreshold() const +{ + return mCloth.mSleepThreshold; +} + +template <typename T> +inline void ClothImpl<T>::setSleepTestInterval(uint32_t interval) +{ + if(interval == mCloth.mSleepTestInterval) + return; + + mCloth.mSleepTestInterval = interval; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getSleepTestInterval() const +{ + return mCloth.mSleepTestInterval; +} + +template <typename T> +inline void ClothImpl<T>::setSleepAfterCount(uint32_t afterCount) +{ + if(afterCount == mCloth.mSleepAfterCount) + return; + + mCloth.mSleepAfterCount = afterCount; + mCloth.notifyChanged(); + mCloth.wakeUp(); +} + +template <typename T> +inline uint32_t ClothImpl<T>::getSleepAfterCount() const +{ + return mCloth.mSleepAfterCount; +} + +template <typename T> +inline uint32_t ClothImpl<T>::getSleepPassCount() const +{ + return mCloth.mSleepPassCounter; +} + +template <typename T> +inline bool ClothImpl<T>::isAsleep() const +{ + return mCloth.isSleeping(); +} + +template <typename T> +inline void ClothImpl<T>::putToSleep() +{ + mCloth.mSleepPassCounter = mCloth.mSleepAfterCount; +} + +template <typename T> +inline void ClothImpl<T>::wakeUp() +{ + mCloth.wakeUp(); +} + +template <typename T> +inline void ClothImpl<T>::setUserData(void* data) +{ + mCloth.mUserData = data; +} + +template <typename T> +inline void* ClothImpl<T>::getUserData() const +{ + return mCloth.mUserData; +} + +template <typename T> +template <typename U> +inline MappedRange<U> ClothImpl<T>::getMappedParticles(U* data) const +{ + return MappedRange<U>(data, data + getNumParticles(), *this, &Cloth::lockParticles, &Cloth::unlockParticles); +} + +} // namespace cloth + +} // namespace physx |