aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/PhysX/src/NpFactory.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/PhysX/src/NpFactory.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/PhysX/src/NpFactory.cpp')
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpFactory.cpp1256
1 files changed, 1256 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysX/src/NpFactory.cpp b/PhysX_3.4/Source/PhysX/src/NpFactory.cpp
new file mode 100644
index 00000000..bd026191
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpFactory.cpp
@@ -0,0 +1,1256 @@
+// 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.
+
+
+#include "NpCast.h"
+#include "NpFactory.h"
+#include "NpPhysics.h"
+#include "ScPhysics.h"
+#include "ScbScene.h"
+#include "ScbActor.h"
+#include "GuHeightField.h"
+#include "GuTriangleMesh.h"
+#include "GuConvexMesh.h"
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ #include "NpParticleSystem.h"
+#endif
+
+#if PX_USE_CLOTH_API
+ #include "NpClothFabric.h"
+ #include "PxClothCollisionData.h"
+#endif
+
+#include "NpConnector.h"
+#include "NpPtrTableStorageManager.h"
+#include "CmCollection.h"
+
+using namespace physx;
+
+NpFactory::NpFactory()
+: GuMeshFactory()
+, mConnectorArrayPool(PX_DEBUG_EXP("connectorArrayPool"))
+, mPtrTableStorageManager(PX_NEW(NpPtrTableStorageManager))
+, mMaterialPool(PX_DEBUG_EXP("MaterialPool"))
+#if PX_USE_CLOTH_API
+ , mClothFabricArray(PX_DEBUG_EXP("clothFabricArray"))
+#endif
+#if PX_SUPPORT_PVD
+ , mNpFactoryListener(NULL)
+#endif
+{
+}
+
+namespace
+{
+ template <typename T> void releaseAll(Ps::HashSet<T*>& container)
+ {
+ // a bit tricky: release will call the factory back to remove the object from
+ // the tracking array, immediately evaluating the iterator. Reconstructing the
+ // iterator per delete can be expensive. So, we use a temporary object.
+ //
+ // a coalesced hash would be efficient too, but we only ever iterate over it
+ // here so it's not worth the 2x remove penalty over the normal hash.
+
+ Ps::Array<T*, Ps::ReflectionAllocator<T*> > tmp;
+ tmp.reserve(container.size());
+ for(typename Ps::HashSet<T*>::Iterator iter = container.getIterator(); !iter.done(); ++iter)
+ tmp.pushBack(*iter);
+
+ PX_ASSERT(tmp.size() == container.size());
+ for(PxU32 i=0;i<tmp.size();i++)
+ tmp[i]->release();
+ }
+}
+
+
+
+NpFactory::~NpFactory()
+{
+ PX_DELETE(mPtrTableStorageManager);
+}
+
+
+void NpFactory::release()
+{
+ releaseAll(mAggregateTracking);
+ releaseAll(mConstraintTracking);
+ releaseAll(mArticulationTracking);
+ releaseAll(mActorTracking);
+ while(mShapeTracking.size())
+ static_cast<NpShape*>(mShapeTracking.getEntries()[0])->releaseInternal();
+
+#if PX_USE_CLOTH_API
+ while(mClothFabricArray.size())
+ {
+ mClothFabricArray[0]->release();
+ }
+#endif
+
+ GuMeshFactory::release(); // deletes the class
+}
+
+void NpFactory::createInstance()
+{
+ PX_ASSERT(!mInstance);
+ mInstance = PX_NEW(NpFactory)();
+}
+
+
+void NpFactory::destroyInstance()
+{
+ PX_ASSERT(mInstance);
+ mInstance->release();
+ mInstance = NULL;
+}
+
+
+NpFactory* NpFactory::mInstance = NULL;
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+ template <typename T> void addToTracking(Ps::HashSet<T*>& set, T* element, Ps::Mutex& mutex, bool lock=true)
+ {
+ if(!element)
+ return;
+
+ if(lock)
+ mutex.lock();
+
+ set.insert(element);
+
+ if(lock)
+ mutex.unlock();
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////// Actors
+
+void NpFactory::addRigidStatic(PxRigidStatic* npActor, bool lock)
+{
+ addToTracking<PxActor>(mActorTracking, npActor, mTrackingMutex, lock);
+}
+
+void NpFactory::addRigidDynamic(PxRigidDynamic* npBody, bool lock)
+{
+ addToTracking<PxActor>(mActorTracking, npBody, mTrackingMutex, lock);
+}
+
+void NpFactory::addShape(PxShape* shape, bool lock)
+{
+ // this uses a coalesced hash set rather than a normal hash set so that we can iterate over it efficiently
+ if(!shape)
+ return;
+
+ if(lock)
+ mTrackingMutex.lock();
+
+ mShapeTracking.insert(shape);
+
+ if(lock)
+ mTrackingMutex.unlock();
+}
+
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+namespace
+{
+ NpParticleSystem* createParticleSystem(PxU32 maxParticles, bool perParticleRestOffset)
+ {
+ return NpFactory::getInstance().createNpParticleSystem(maxParticles, perParticleRestOffset);
+ }
+
+ NpParticleFluid* createParticleFluid(PxU32 maxParticles, bool perParticleRestOffset)
+ {
+ return NpFactory::getInstance().createNpParticleFluid(maxParticles, perParticleRestOffset);
+ }
+
+ // pointers to function above, initialized during subsystem registration
+ NpParticleSystem* (*sCreateParticleSystemFn)(PxU32 maxParticles, bool perParticleRestOffset) = 0;
+ NpParticleFluid* (*sCreateParticleFluidFn)(PxU32 maxParticles, bool perParticleRestOffset) = 0;
+}
+
+void NpFactory::registerParticles()
+{
+ sCreateParticleSystemFn = &::createParticleSystem;
+ sCreateParticleFluidFn = &::createParticleFluid;
+}
+
+void NpFactory::addParticleSystem(PxParticleSystem* ps, bool lock)
+{
+ addToTracking<PxActor>(mActorTracking, ps, mTrackingMutex, lock);
+}
+
+void NpFactory::addParticleFluid(PxParticleFluid* fluid, bool lock)
+{
+ addToTracking<PxActor>(mActorTracking, fluid, mTrackingMutex, lock);
+}
+
+NpParticleSystem* NpFactory::createNpParticleSystem(PxU32 maxParticles, bool perParticleRestOffset)
+{
+ NpParticleSystem* npParticleSystem;
+ {
+ Ps::Mutex::ScopedLock lock(mParticleSystemPoolLock);
+ npParticleSystem = mParticleSystemPool.construct(maxParticles, perParticleRestOffset);
+ }
+ return npParticleSystem;
+}
+
+void NpFactory::releaseParticleSystemToPool(NpParticleSystem& particleSystem)
+{
+ PX_ASSERT(particleSystem.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mParticleSystemPoolLock);
+ mParticleSystemPool.destroy(&particleSystem);
+}
+
+NpParticleFluid* NpFactory::createNpParticleFluid(PxU32 maxParticles, bool perParticleRestOffset)
+{
+ NpParticleFluid* npParticleFluid;
+ {
+ Ps::Mutex::ScopedLock lock(mParticleFluidPoolLock);
+ npParticleFluid = mParticleFluidPool.construct(maxParticles, perParticleRestOffset);
+ }
+ return npParticleFluid;
+}
+
+void NpFactory::releaseParticleFluidToPool(NpParticleFluid& particleFluid)
+{
+ PX_ASSERT(particleFluid.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mParticleFluidPoolLock);
+ mParticleFluidPool.destroy(&particleFluid);
+}
+
+PxParticleFluid* NpFactory::createParticleFluid(PxU32 maxParticles, bool perParticleRestOffset)
+{
+ if (!sCreateParticleFluidFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle fluid creation failed. Use PxRegisterParticles to register particle module: returned NULL.");
+ return NULL;
+ }
+
+ PxParticleFluid* fluid = sCreateParticleFluidFn(maxParticles, perParticleRestOffset);
+ if (!fluid)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Particle fluid initialization failed: returned NULL.");
+ return NULL;
+ }
+
+ addParticleFluid(fluid);
+ return fluid;
+}
+
+PxParticleSystem* NpFactory::createParticleSystem(PxU32 maxParticles, bool perParticleRestOffset)
+{
+ if (!sCreateParticleSystemFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle system creation failed. Use PxRegisterParticles to register particle module: returned NULL.");
+ return NULL;
+ }
+
+ PxParticleSystem* ps = sCreateParticleSystemFn(maxParticles, perParticleRestOffset);
+ if (!ps)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Particle system initialization failed: returned NULL.");
+ return NULL;
+ }
+
+ addParticleSystem(ps);
+ return ps;
+}
+
+#endif
+
+
+#if PX_USE_CLOTH_API
+
+namespace
+{
+ NpCloth* createCloth(const PxTransform& globalPose, PxClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags)
+ {
+ return NpFactory::getInstance().createNpCloth(globalPose, static_cast<NpClothFabric&>(fabric), particles, flags);
+ }
+
+ NpClothFabric* createClothFabric(PxInputStream& stream)
+ {
+ NpClothFabric* fabric = NpFactory::getInstance().createNpClothFabric();
+ if(fabric)
+ {
+ if(fabric->load(stream))
+ return fabric;
+ fabric->decRefCount();
+ }
+ return NULL;
+ }
+
+ NpClothFabric* createClothFabric(const PxClothFabricDesc& desc)
+ {
+ NpClothFabric* fabric = NpFactory::getInstance().createNpClothFabric();
+ if(fabric)
+ {
+ if(fabric->load(desc))
+ return fabric;
+ fabric->decRefCount();
+ }
+ return NULL;
+ }
+
+ // pointers to functions above, initialized during subsystem registration
+ NpCloth* (*sCreateClothFn)(const PxTransform&, PxClothFabric&, const PxClothParticle*, PxClothFlags) = 0;
+ NpClothFabric* (*sCreateClothFabricFromStreamFn)(PxInputStream&) = 0;
+ NpClothFabric* (*sCreateClothFabricFromDescFn)(const PxClothFabricDesc&) = 0;
+}
+
+void NpFactory::registerCloth()
+{
+ sCreateClothFn = &::createCloth;
+ sCreateClothFabricFromStreamFn = &::createClothFabric;
+ sCreateClothFabricFromDescFn = &::createClothFabric;
+
+ Sc::Physics::getInstance().registerCloth();
+}
+
+void NpFactory::addCloth(PxCloth* cloth, bool lock)
+{
+ addToTracking<PxActor>(mActorTracking, cloth, mTrackingMutex, lock);
+}
+
+NpCloth* NpFactory::createNpCloth(const PxTransform& globalPose, PxClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags)
+{
+ NpCloth* npCloth;
+ {
+ Ps::Mutex::ScopedLock lock(mClothPoolLock);
+ npCloth = mClothPool.construct(globalPose, static_cast<NpClothFabric&>(fabric), particles, flags);
+ }
+ return npCloth;
+}
+
+void NpFactory::releaseClothToPool(NpCloth& cloth)
+{
+ PX_ASSERT(cloth.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mClothPoolLock);
+ mClothPool.destroy(&cloth);
+}
+
+NpClothFabric* NpFactory::createNpClothFabric()
+{
+ NpClothFabric* npClothFabric;
+ {
+ Ps::Mutex::ScopedLock lock(mClothFabricPoolLock);
+ npClothFabric = mClothFabricPool.construct();
+ }
+ return npClothFabric;
+}
+
+void NpFactory::releaseClothFabricToPool(NpClothFabric& clothFabric)
+{
+ PX_ASSERT(clothFabric.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mClothFabricPoolLock);
+ mClothFabricPool.destroy(&clothFabric);
+}
+
+void NpFactory::addClothFabric(NpClothFabric* cf, bool lock)
+{
+ if(lock)
+ {
+ Ps::Mutex::ScopedLock lock_(mTrackingMutex);
+ if(!mClothFabricArray.size())
+ mClothFabricArray.reserve(64);
+
+ mClothFabricArray.pushBack(cf);
+ }
+ else
+ {
+ if(!mClothFabricArray.size())
+ mClothFabricArray.reserve(64);
+
+ mClothFabricArray.pushBack(cf);
+ }
+}
+
+PxClothFabric* NpFactory::createClothFabric(PxInputStream& stream)
+{
+ if(!sCreateClothFabricFromStreamFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Cloth not registered: returned NULL.");
+ return NULL;
+ }
+
+ NpClothFabric* result = (*sCreateClothFabricFromStreamFn)(stream);
+
+ if(result)
+ addClothFabric(result);
+
+ return result;
+}
+
+PxClothFabric* NpFactory::createClothFabric(const PxClothFabricDesc& desc)
+{
+ if(!sCreateClothFabricFromDescFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Cloth not registered: returned NULL.");
+ return NULL;
+ }
+
+ NpClothFabric* result = (*sCreateClothFabricFromDescFn)(desc);
+
+ if(result)
+ addClothFabric(result);
+
+ return result;
+}
+
+bool NpFactory::removeClothFabric(PxClothFabric& cf)
+{
+ NpClothFabric* npClothFabric = &static_cast<NpClothFabric&>(cf);
+
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+
+ // remove the cloth fabric from the array
+ for(PxU32 i=0; i<mClothFabricArray.size(); i++)
+ {
+ if(mClothFabricArray[i]==npClothFabric)
+ {
+ mClothFabricArray.replaceWithLast(i);
+#if PX_SUPPORT_PVD
+ if(mNpFactoryListener)
+ mNpFactoryListener->onNpFactoryBufferRelease(cf);
+#endif
+ return true;
+ }
+ }
+ return false;
+}
+
+PxU32 NpFactory::getNbClothFabrics() const
+{
+ return mClothFabricArray.size();
+}
+
+PxU32 NpFactory::getClothFabrics(PxClothFabric** userBuffer, PxU32 bufferSize) const
+{
+ const PxU32 size = mClothFabricArray.size();
+
+ const PxU32 writeCount = PxMin(size, bufferSize);
+ for(PxU32 i=0; i<writeCount; i++)
+ userBuffer[i] = mClothFabricArray[i];
+
+ return writeCount;
+}
+
+PxCloth* NpFactory::createCloth(const PxTransform& globalPose, PxClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags)
+{
+ PX_CHECK_AND_RETURN_NULL(globalPose.isValid(),"globalPose is not valid. createCloth returns NULL.");
+ PX_CHECK_AND_RETURN_NULL((particles != NULL) && fabric.getNbParticles(), "No particles supplied. createCloth returns NULL.");
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN_NULL(NpCloth::checkParticles(fabric.getNbParticles(), particles), "PxPhysics::createCloth: particle values must be finite and inverse weight must not be negative");
+#endif
+
+ if(!sCreateClothFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Cloth not registered: returned NULL.");
+ return NULL;
+ }
+
+ // create the internal cloth object
+ NpCloth* npCloth = (*sCreateClothFn)(globalPose, fabric, particles, flags);
+ if (npCloth)
+ {
+ addToTracking<PxActor>(mActorTracking, npCloth, mTrackingMutex);
+ return npCloth;
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Cloth initialization failed: returned NULL.");
+ return NULL;
+ }
+}
+#endif
+
+void NpFactory::onActorRelease(PxActor* a)
+{
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+ mActorTracking.erase(a);
+}
+
+void NpFactory::onShapeRelease(PxShape* a)
+{
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+ mShapeTracking.erase(a);
+}
+
+
+void NpFactory::addArticulation(PxArticulation* npArticulation, bool lock)
+{
+ addToTracking<PxArticulation>(mArticulationTracking, npArticulation, mTrackingMutex, lock);
+}
+
+namespace
+{
+ NpArticulation* createArticulation()
+ {
+ NpArticulation* npArticulation = NpFactory::getInstance().createNpArticulation();
+ if (!npArticulation)
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Articulation initialization failed: returned NULL.");
+
+ return npArticulation;
+ }
+
+ NpArticulationLink* createArticulationLink(NpArticulation&root, NpArticulationLink* parent, const PxTransform& pose)
+ {
+ PX_CHECK_AND_RETURN_NULL(pose.isValid(),"Supplied PxArticulation pose is not valid. Articulation link creation method returns NULL.");
+ PX_CHECK_AND_RETURN_NULL((!parent || (&parent->getRoot() == &root)), "specified parent link is not part of the destination articulation. Articulation link creation method returns NULL.");
+
+ NpArticulationLink* npArticulationLink = NpFactory::getInstance().createNpArticulationLink(root, parent, pose);
+ if (!npArticulationLink)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Articulation link initialization failed: returned NULL.");
+ return NULL;
+ }
+
+ if (parent)
+ {
+ PxTransform parentPose = parent->getCMassLocalPose().transformInv(pose);
+ PxTransform childPose = PxTransform(PxIdentity);
+
+ NpArticulationJoint* npArticulationJoint = NpFactory::getInstance().createNpArticulationJoint(*parent, parentPose, *npArticulationLink, childPose);
+ if (!npArticulationJoint)
+ {
+ PX_DELETE(npArticulationLink);
+
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Articulation link initialization failed due to joint creation failure: returned NULL.");
+ return NULL;
+ }
+
+ npArticulationLink->setInboundJoint(*npArticulationJoint);
+ }
+
+ return npArticulationLink;
+ }
+
+ // pointers to functions above, initialized during subsystem registration
+ static NpArticulation* (*sCreateArticulationFn)() = 0;
+ static NpArticulationLink* (*sCreateArticulationLinkFn)(NpArticulation&, NpArticulationLink* parent, const PxTransform& pose) = 0;
+}
+
+void NpFactory::registerArticulations()
+{
+ sCreateArticulationFn = &::createArticulation;
+ sCreateArticulationLinkFn = &::createArticulationLink;
+}
+
+NpArticulation* NpFactory::createNpArticulation()
+{
+ NpArticulation* npArticulation;
+ {
+ Ps::Mutex::ScopedLock lock(mArticulationPoolLock);
+ npArticulation = mArticulationPool.construct();
+ }
+ return npArticulation;
+}
+
+void NpFactory::releaseArticulationToPool(NpArticulation& articulation)
+{
+ PX_ASSERT(articulation.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mArticulationPoolLock);
+ mArticulationPool.destroy(&articulation);
+}
+
+PxArticulation* NpFactory::createArticulation()
+{
+ if(!sCreateArticulationFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Articulations not registered: returned NULL.");
+ return NULL;
+ }
+
+ NpArticulation* npArticulation = (*sCreateArticulationFn)();
+ if(npArticulation)
+ addArticulation(npArticulation);
+
+ return npArticulation;
+}
+
+void NpFactory::onArticulationRelease(PxArticulation* a)
+{
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+ mArticulationTracking.erase(a);
+}
+
+NpArticulationLink* NpFactory::createNpArticulationLink(NpArticulation&root, NpArticulationLink* parent, const PxTransform& pose)
+{
+ NpArticulationLink* npArticulationLink;
+ {
+ Ps::Mutex::ScopedLock lock(mArticulationLinkPoolLock);
+ npArticulationLink = mArticulationLinkPool.construct(pose, root, parent);
+ }
+ return npArticulationLink;
+}
+
+void NpFactory::releaseArticulationLinkToPool(NpArticulationLink& articulationLink)
+{
+ PX_ASSERT(articulationLink.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mArticulationLinkPoolLock);
+ mArticulationLinkPool.destroy(&articulationLink);
+}
+
+PxArticulationLink* NpFactory::createArticulationLink(NpArticulation& root, NpArticulationLink* parent, const PxTransform& pose)
+{
+ if(!sCreateArticulationLinkFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Articulations not registered: returned NULL.");
+ return NULL;
+ }
+
+ return (*sCreateArticulationLinkFn)(root, parent, pose);
+}
+
+NpArticulationJoint* NpFactory::createNpArticulationJoint(NpArticulationLink& parent, const PxTransform& parentFrame, NpArticulationLink& child, const PxTransform& childFrame)
+{
+ NpArticulationJoint* npArticulationJoint;
+ {
+ Ps::Mutex::ScopedLock lock(mArticulationJointPoolLock);
+ npArticulationJoint = mArticulationJointPool.construct(parent, parentFrame, child, childFrame);
+ }
+ return npArticulationJoint;
+}
+
+void NpFactory::releaseArticulationJointToPool(NpArticulationJoint& articulationJoint)
+{
+ PX_ASSERT(articulationJoint.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mArticulationJointPoolLock);
+ mArticulationJointPool.destroy(&articulationJoint);
+}
+
+/////////////////////////////////////////////////////////////////////////////// constraint
+
+void NpFactory::addConstraint(PxConstraint* npConstraint, bool lock)
+{
+ addToTracking<PxConstraint>(mConstraintTracking, npConstraint, mTrackingMutex, lock);
+}
+
+PxConstraint* NpFactory::createConstraint(PxRigidActor* actor0, PxRigidActor* actor1, PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize)
+{
+ PX_CHECK_AND_RETURN_NULL((actor0 && !actor0->is<PxRigidStatic>()) || (actor1 && !actor1->is<PxRigidStatic>()), "createConstraint: At least one actor must be dynamic or an articulation link");
+
+ NpConstraint* npConstraint;
+ {
+ Ps::Mutex::ScopedLock lock(mConstraintPoolLock);
+ npConstraint = mConstraintPool.construct(actor0, actor1, connector, shaders, dataSize);
+ }
+ addConstraint(npConstraint);
+ return npConstraint;
+}
+
+void NpFactory::releaseConstraintToPool(NpConstraint& constraint)
+{
+ PX_ASSERT(constraint.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mConstraintPoolLock);
+ mConstraintPool.destroy(&constraint);
+}
+
+void NpFactory::onConstraintRelease(PxConstraint* c)
+{
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+ mConstraintTracking.erase(c);
+}
+
+/////////////////////////////////////////////////////////////////////////////// aggregate
+
+// PX_AGGREGATE
+void NpFactory::addAggregate(PxAggregate* npAggregate, bool lock)
+{
+ addToTracking<PxAggregate>(mAggregateTracking, npAggregate, mTrackingMutex, lock);
+}
+
+PxAggregate* NpFactory::createAggregate(PxU32 maxActors, bool selfCollisions)
+{
+ PX_CHECK_AND_RETURN_NULL(maxActors<=128, "maxActors limited to 128. createAggregate method returns NULL.");
+
+ NpAggregate* npAggregate;
+
+ {
+ Ps::Mutex::ScopedLock lock(mAggregatePoolLock);
+ npAggregate = mAggregatePool.construct(maxActors, selfCollisions);
+ }
+
+ addAggregate(npAggregate);
+ return npAggregate;
+}
+
+void NpFactory::releaseAggregateToPool(NpAggregate& aggregate)
+{
+ PX_ASSERT(aggregate.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mAggregatePoolLock);
+ mAggregatePool.destroy(&aggregate);
+}
+
+void NpFactory::onAggregateRelease(PxAggregate* a)
+{
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+ mAggregateTracking.erase(a);
+}
+//~PX_AGGREGATE
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxMaterial* NpFactory::createMaterial(PxReal staticFriction, PxReal dynamicFriction, PxReal restitution)
+{
+ PX_CHECK_AND_RETURN_NULL(dynamicFriction >= 0.0f, "createMaterial: dynamicFriction must be >= 0.");
+ PX_CHECK_AND_RETURN_NULL(staticFriction >= 0.0f, "createMaterial: staticFriction must be >= 0.");
+ PX_CHECK_AND_RETURN_NULL(restitution >= 0.0f || restitution <= 1.0f, "createMaterial: restitution must be between 0 and 1.");
+
+ Sc::MaterialData data;
+ data.staticFriction = staticFriction;
+ data.dynamicFriction = dynamicFriction;
+ data.restitution = restitution;
+
+ NpMaterial* npMaterial;
+ {
+ Ps::Mutex::ScopedLock lock(mMaterialPoolLock);
+ npMaterial = mMaterialPool.construct(data);
+ }
+ return npMaterial;
+}
+
+void NpFactory::releaseMaterialToPool(NpMaterial& material)
+{
+ PX_ASSERT(material.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mMaterialPoolLock);
+ mMaterialPool.destroy(&material);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+NpConnectorArray* NpFactory::acquireConnectorArray()
+{
+ Ps::MutexT<>::ScopedLock l(mConnectorArrayPoolLock);
+ return mConnectorArrayPool.construct();
+}
+
+void NpFactory::releaseConnectorArray(NpConnectorArray* array)
+{
+ Ps::MutexT<>::ScopedLock l(mConnectorArrayPoolLock);
+ mConnectorArrayPool.destroy(array);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+NpShape* NpFactory::createShape(const PxGeometry& geometry,
+ PxShapeFlags shapeFlags,
+ PxMaterial*const* materials,
+ PxU16 materialCount,
+ bool isExclusive)
+{
+ switch(geometry.getType())
+ {
+ case PxGeometryType::eBOX:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxBoxGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eSPHERE:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxSphereGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eCAPSULE:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxCapsuleGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eCONVEXMESH:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxConvexMeshGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::ePLANE:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxPlaneGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eHEIGHTFIELD:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxHeightFieldGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eTRIANGLEMESH:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxTriangleMeshGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ PX_ASSERT(0);
+ }
+
+ //
+ // Check for invalid material table setups
+ //
+
+#if PX_CHECKED
+ if (!NpShape::checkMaterialSetup(geometry, "Shape creation", materials, materialCount))
+ return NULL;
+#endif
+
+ Ps::InlineArray<PxU16, 4> materialIndices("NpFactory::TmpMaterialIndexBuffer");
+ materialIndices.resize(materialCount);
+ if (materialCount == 1)
+ {
+ materialIndices[0] = Ps::to16((static_cast<NpMaterial*>(materials[0]))->getHandle());
+ }
+ else
+ {
+ NpMaterial::getMaterialIndices(materials, materialIndices.begin(), materialCount);
+ }
+
+ NpShape* npShape;
+ {
+ Ps::Mutex::ScopedLock lock(mShapePoolLock);
+ PxU16* mi = materialIndices.begin(); // required to placate pool constructor arg passing
+ npShape = mShapePool.construct(geometry, shapeFlags, mi, materialCount, isExclusive);
+ }
+
+ if(!npShape)
+ return NULL;
+
+ for (PxU32 i=0; i < materialCount; i++)
+ static_cast<NpMaterial*>(npShape->getMaterial(i))->incRefCount();
+
+ addShape(npShape);
+
+ return npShape;
+}
+
+void NpFactory::releaseShapeToPool(NpShape& shape)
+{
+ PX_ASSERT(shape.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mShapePoolLock);
+ mShapePool.destroy(&shape);
+}
+
+
+
+PxU32 NpFactory::getNbShapes() const
+{
+ return mShapeTracking.size();
+}
+
+PxU32 NpFactory::getShapes(PxShape** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ if(mShapeTracking.size()<startIndex)
+ return 0;
+ PxU32 count = PxMax(bufferSize, mShapeTracking.size()-startIndex);
+ PxShape*const *shapes = mShapeTracking.getEntries();
+ for(PxU32 i=0;i<count;i++)
+ userBuffer[i] = shapes[startIndex+i];
+ return count;
+}
+
+
+PxRigidStatic* NpFactory::createRigidStatic(const PxTransform& pose)
+{
+ PX_CHECK_AND_RETURN_NULL(pose.isValid(), "pose is not valid. createRigidStatic returns NULL.");
+
+ NpRigidStatic* npActor;
+
+ {
+ Ps::Mutex::ScopedLock lock(mRigidStaticPoolLock);
+ npActor = mRigidStaticPool.construct(pose);
+ }
+
+ addRigidStatic(npActor);
+ return npActor;
+}
+
+void NpFactory::releaseRigidStaticToPool(NpRigidStatic& rigidStatic)
+{
+ PX_ASSERT(rigidStatic.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mRigidStaticPoolLock);
+ mRigidStaticPool.destroy(&rigidStatic);
+}
+
+PxRigidDynamic* NpFactory::createRigidDynamic(const PxTransform& pose)
+{
+ PX_CHECK_AND_RETURN_NULL(pose.isValid(), "pose is not valid. createRigidDynamic returns NULL.");
+
+ NpRigidDynamic* npBody;
+ {
+ Ps::Mutex::ScopedLock lock(mRigidDynamicPoolLock);
+ npBody = mRigidDynamicPool.construct(pose);
+ }
+ addRigidDynamic(npBody);
+ return npBody;
+}
+
+
+void NpFactory::releaseRigidDynamicToPool(NpRigidDynamic& rigidDynamic)
+{
+ PX_ASSERT(rigidDynamic.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mRigidDynamicPoolLock);
+ mRigidDynamicPool.destroy(&rigidDynamic);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PT: this function is here to minimize the amount of locks when deserializing a collection
+void NpFactory::addCollection(const Cm::Collection& collection)
+{
+
+ PxU32 nb = collection.getNbObjects();
+ const Ps::Pair<PxBase* const, PxSerialObjectId>* entries = collection.internalGetObjects();
+ // PT: we take the lock only once, here
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+
+ for(PxU32 i=0;i<nb;i++)
+ {
+ PxBase* s = entries[i].first;
+ const PxType serialType = s->getConcreteType();
+//////////////////////////
+ if(serialType==PxConcreteType::eHEIGHTFIELD)
+ {
+ Gu::HeightField* gu = static_cast<Gu::HeightField*>(s);
+ gu->setMeshFactory(this);
+ addHeightField(gu, false);
+ }
+ else if(serialType==PxConcreteType::eCONVEX_MESH)
+ {
+ Gu::ConvexMesh* gu = static_cast<Gu::ConvexMesh*>(s);
+ gu->setMeshFactory(this);
+ addConvexMesh(gu, false);
+ }
+ else if(serialType==PxConcreteType::eTRIANGLE_MESH_BVH33 || serialType==PxConcreteType::eTRIANGLE_MESH_BVH34)
+ {
+ Gu::TriangleMesh* gu = static_cast<Gu::TriangleMesh*>(s);
+ gu->setMeshFactory(this);
+ addTriangleMesh(gu, false);
+ }
+//////////////////////////
+#if PX_USE_CLOTH_API
+ else if (serialType==PxConcreteType::eCLOTH_FABRIC)
+ {
+ NpClothFabric* np = static_cast<NpClothFabric*>(s);
+ // PT: TODO: investigate why cloth don't need a "setMeshFactory" call here
+ addClothFabric(np, false);
+ }
+#endif
+ else if(serialType==PxConcreteType::eRIGID_DYNAMIC)
+ {
+ NpRigidDynamic* np = static_cast<NpRigidDynamic*>(s);
+ addRigidDynamic(np, false);
+ }
+ else if(serialType==PxConcreteType::eRIGID_STATIC)
+ {
+ NpRigidStatic* np = static_cast<NpRigidStatic*>(s);
+ addRigidStatic(np, false);
+ }
+ else if(serialType==PxConcreteType::eSHAPE)
+ {
+ NpShape* np = static_cast<NpShape*>(s);
+ addShape(np, false);
+ }
+ else if(serialType==PxConcreteType::eMATERIAL)
+ {
+ }
+ else if(serialType==PxConcreteType::eCONSTRAINT)
+ {
+ NpConstraint* np = static_cast<NpConstraint*>(s);
+ addConstraint(np, false);
+ }
+#if PX_USE_CLOTH_API
+ else if (serialType==PxConcreteType::eCLOTH)
+ {
+ NpCloth* np = static_cast<NpCloth*>(s);
+ addCloth(np, false);
+ }
+#endif
+#if PX_USE_PARTICLE_SYSTEM_API
+ else if(serialType==PxConcreteType::ePARTICLE_SYSTEM)
+ {
+ NpParticleSystem* np = static_cast<NpParticleSystem*>(s);
+ addParticleSystem(np, false);
+ }
+ else if(serialType==PxConcreteType::ePARTICLE_FLUID)
+ {
+ NpParticleFluid* np = static_cast<NpParticleFluid*>(s);
+ addParticleFluid(np, false);
+ }
+#endif
+ else if(serialType==PxConcreteType::eAGGREGATE)
+ {
+ NpAggregate* np = static_cast<NpAggregate*>(s);
+ addAggregate(np, false);
+
+ // PT: TODO: double-check this.... is it correct?
+ for(PxU32 j=0;j<np->getCurrentSizeFast();j++)
+ {
+ PxBase* actor = np->getActorFast(j);
+ const PxType serialType1 = actor->getConcreteType();
+
+ if(serialType1==PxConcreteType::eRIGID_STATIC)
+ addRigidStatic(static_cast<NpRigidStatic*>(actor), false);
+ else if(serialType1==PxConcreteType::eRIGID_DYNAMIC)
+ addRigidDynamic(static_cast<NpRigidDynamic*>(actor), false);
+ else if(serialType1==PxConcreteType::ePARTICLE_SYSTEM)
+ {}
+ else if(serialType1==PxConcreteType::ePARTICLE_FLUID)
+ {}
+ else if(serialType1==PxConcreteType::eARTICULATION_LINK)
+ {}
+ else PX_ASSERT(0);
+ }
+ }
+ else if(serialType==PxConcreteType::eARTICULATION)
+ {
+ NpArticulation* np = static_cast<NpArticulation*>(s);
+ addArticulation(np, false);
+ }
+ else if(serialType==PxConcreteType::eARTICULATION_LINK)
+ {
+// NpArticulationLink* np = static_cast<NpArticulationLink*>(s);
+ }
+ else if(serialType==PxConcreteType::eARTICULATION_JOINT)
+ {
+// NpArticulationJoint* np = static_cast<NpArticulationJoint*>(s);
+ }
+ else
+ {
+// assert(0);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_SUPPORT_GPU_PHYSX
+void NpFactory::notifyReleaseTriangleMesh(const PxTriangleMesh& tm)
+{
+ NpPhysics::getInstance().getNpPhysicsGpu().releaseTriangleMeshMirror(tm);
+}
+
+void NpFactory::notifyReleaseHeightField(const PxHeightField& hf)
+{
+ NpPhysics::getInstance().getNpPhysicsGpu().releaseHeightFieldMirror(hf);
+}
+
+void NpFactory::notifyReleaseConvexMesh(const PxConvexMesh& cm)
+{
+ NpPhysics::getInstance().getNpPhysicsGpu().releaseConvexMeshMirror(cm);
+}
+#endif
+
+#if PX_SUPPORT_PVD
+void NpFactory::setNpFactoryListener( NpFactoryListener& inListener)
+{
+ mNpFactoryListener = &inListener;
+ addFactoryListener(inListener);
+}
+#endif
+///////////////////////////////////////////////////////////////////////////////
+
+// these calls are issued from the Scb layer when buffered deletes are issued.
+// TODO: we should really push these down as a virtual interface that is part of Scb's reqs
+// to eliminate this link-time dep.
+
+
+static void NpDestroyRigidActor(Scb::RigidStatic& scb)
+{
+ NpRigidStatic* np = const_cast<NpRigidStatic*>(getNpRigidStatic(&scb));
+
+ void* ud = np->userData;
+
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseRigidStaticToPool(*np);
+ else
+ np->~NpRigidStatic();
+
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+
+static void NpDestroyRigidDynamic(Scb::Body& scb)
+{
+ NpRigidDynamic* np = const_cast<NpRigidDynamic*>(getNpRigidDynamic(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseRigidDynamicToPool(*np);
+ else
+ np->~NpRigidDynamic();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+
+#if PX_USE_PARTICLE_SYSTEM_API
+static void NpDestroyParticleSystem(Scb::ParticleSystem& scb)
+{
+ if(scb.getActorType() == PxActorType::ePARTICLE_SYSTEM)
+ {
+ NpParticleSystem* np = const_cast<NpParticleSystem*>(getNpParticleSystem(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseParticleSystemToPool(*np);
+ else
+ np->~NpParticleSystem();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+ }
+ else
+ {
+ NpParticleFluid* np = const_cast<NpParticleFluid*>(getNpParticleFluid(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseParticleFluidToPool(*np);
+ else
+ np->~NpParticleFluid();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+ }
+}
+#endif
+
+static void NpDestroyArticulationLink(Scb::Body& scb)
+{
+ NpArticulationLink* np = const_cast<NpArticulationLink*>(getNpArticulationLink(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseArticulationLinkToPool(*np);
+ else
+ np->~NpArticulationLink();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+
+static void NpDestroyArticulationJoint(Scb::ArticulationJoint& scb)
+{
+ NpArticulationJoint* np = const_cast<NpArticulationJoint*>(getNpArticulationJoint(&scb));
+
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseArticulationJointToPool(*np);
+ else
+ np->~NpArticulationJoint();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, NULL);
+}
+
+static void NpDestroyArticulation(Scb::Articulation& scb)
+{
+ NpArticulation* np = const_cast<NpArticulation*>(getNpArticulation(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseArticulationToPool(*np);
+ else
+ np->~NpArticulation();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+
+static void NpDestroyAggregate(Scb::Aggregate& scb)
+{
+ NpAggregate* np = const_cast<NpAggregate*>(getNpAggregate(&scb));
+
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseAggregateToPool(*np);
+ else
+ np->~NpAggregate();
+
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, NULL);
+}
+
+static void NpDestroyShape(Scb::Shape& scb)
+{
+ NpShape* np = const_cast<NpShape*>(getNpShape(&scb));
+
+ void* ud = np->userData;
+
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseShapeToPool(*np);
+ else
+ np->~NpShape();
+
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+
+static void NpDestroyConstraint(Scb::Constraint& scb)
+{
+ const size_t offset = size_t(&(reinterpret_cast<NpConstraint*>(0)->getScbConstraint()));
+ NpConstraint* np = reinterpret_cast<NpConstraint*>(reinterpret_cast<char*>(&scb)-offset);
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseConstraintToPool(*np);
+ else
+ np->~NpConstraint();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, NULL);
+}
+
+#if PX_USE_CLOTH_API
+static void NpDestroyCloth(Scb::Cloth& scb)
+{
+ NpCloth* np = const_cast<NpCloth*>(getNpCloth(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseClothToPool(*np);
+ else
+ np->~NpCloth();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+#endif
+
+namespace physx
+{
+ void NpDestroy(Scb::Base& base)
+ {
+ switch(base.getScbType())
+ {
+ case ScbType::SHAPE_EXCLUSIVE:
+ case ScbType::SHAPE_SHARED: { NpDestroyShape(static_cast<Scb::Shape&>(base)); }break;
+ case ScbType::BODY: { NpDestroyRigidDynamic(static_cast<Scb::Body&>(base)); }break;
+ case ScbType::BODY_FROM_ARTICULATION_LINK: { NpDestroyArticulationLink(static_cast<Scb::Body&>(base)); }break;
+ case ScbType::RIGID_STATIC: { NpDestroyRigidActor(static_cast<Scb::RigidStatic&>(base)); }break;
+ case ScbType::CONSTRAINT: { NpDestroyConstraint(static_cast<Scb::Constraint&>(base)); }break;
+#if PX_USE_PARTICLE_SYSTEM_API
+ case ScbType::PARTICLE_SYSTEM: { NpDestroyParticleSystem(static_cast<Scb::ParticleSystem&>(base)); }break;
+#endif
+ case ScbType::ARTICULATION: { NpDestroyArticulation(static_cast<Scb::Articulation&>(base)); }break;
+ case ScbType::ARTICULATION_JOINT: { NpDestroyArticulationJoint(static_cast<Scb::ArticulationJoint&>(base)); }break;
+ case ScbType::AGGREGATE: { NpDestroyAggregate(static_cast<Scb::Aggregate&>(base)); }break;
+#if PX_USE_CLOTH_API
+ case ScbType::CLOTH: { NpDestroyCloth(static_cast<Scb::Cloth&>(base)); }break;
+#endif
+ case ScbType::UNDEFINED:
+ case ScbType::TYPE_COUNT:
+ PX_ALWAYS_ASSERT_MESSAGE("NpDestroy: missing type!");
+ break;
+ }
+ }
+}
+