Projekt_Grafika/dependencies/physx-4.1/source/physx/src/NpFactory.cpp

857 lines
28 KiB
C++

//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions
// are met:
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above copyright
// notice, this list of conditions and the following disclaimer in the
// documentation and/or other materials provided with the distribution.
// * Neither the name of NVIDIA CORPORATION nor the names of its
// contributors may be used to endorse or promote products derived
// from this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//
// Copyright (c) 2008-2019 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"
#include "NpConnector.h"
#include "NpPtrTableStorageManager.h"
#include "CmCollection.h"
#include "NpArticulationReducedCoordinate.h"
#include "NpArticulationJointReducedCoordinate.h"
using namespace physx;
NpFactory::NpFactory()
: GuMeshFactory()
, mConnectorArrayPool(PX_DEBUG_EXP("connectorArrayPool"))
, mPtrTableStorageManager(PX_NEW(NpPtrTableStorageManager))
, mMaterialPool(PX_DEBUG_EXP("MaterialPool"))
#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 invalidating 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();
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;
///////////////////////////////////////////////////////////////////////////////
template <class T0, class T1>
static void addToTracking(T1& set, T0* element, Ps::Mutex& mutex, bool lock)
{
if(!element)
return;
if(lock)
mutex.lock();
set.insert(element);
if(lock)
mutex.unlock();
}
/////////////////////////////////////////////////////////////////////////////// Actors
void NpFactory::addRigidStatic(PxRigidStatic* npActor, bool lock)
{
addToTracking(mActorTracking, npActor, mTrackingMutex, lock);
}
void NpFactory::addRigidDynamic(PxRigidDynamic* npBody, bool lock)
{
addToTracking(mActorTracking, npBody, mTrackingMutex, lock);
}
void NpFactory::addShape(PxShape* shape, bool lock)
{
addToTracking(mShapeTracking, shape, mTrackingMutex, lock);
}
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(PxArticulationBase* npArticulation, bool lock)
{
addToTracking(mArticulationTracking, npArticulation, mTrackingMutex, lock);
}
namespace
{
PxArticulationBase* createArticulation()
{
NpArticulation* npArticulation = NpFactory::getInstance().createNpArticulation();
if (!npArticulation)
Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Articulation initialization failed: returned NULL.");
return npArticulation;
}
PxArticulationBase* createArticulationRC()
{
NpArticulationReducedCoordinate* npArticulation = NpFactory::getInstance().createNpArticulationRC();
if (!npArticulation)
Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Articulation initialization failed: returned NULL.");
return npArticulation;
}
NpArticulationLink* createArticulationLink(PxArticulationBase&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);
PxArticulationJointBase* npArticulationJoint = root.createArticulationJoint(*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 PxArticulationBase* (*sCreateArticulationFn)() = 0;
static PxArticulationBase* (*sCreateArticulationRCFn)() = 0;
static NpArticulationLink* (*sCreateArticulationLinkFn)(PxArticulationBase&, NpArticulationLink* parent, const PxTransform& pose) = 0;
}
void NpFactory::registerArticulations()
{
sCreateArticulationFn = &::createArticulation;
sCreateArticulationLinkFn = &::createArticulationLink;
}
void NpFactory::registerArticulationRCs()
{
sCreateArticulationRCFn = &::createArticulationRC;
sCreateArticulationLinkFn = &::createArticulationLink;
}
void NpFactory::releaseArticulationToPool(PxArticulationBase& articulation)
{
PX_ASSERT(articulation.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
if (articulation.getConcreteType() == PxConcreteType::eARTICULATION)
{
Ps::Mutex::ScopedLock lock(mArticulationPoolLock);
mArticulationPool.destroy(static_cast<NpArticulation*>(&articulation));
}
else
{
PX_ASSERT(articulation.getConcreteType() == PxConcreteType::eARTICULATION_REDUCED_COORDINATE);
Ps::Mutex::ScopedLock lock(mArticulationRCPoolLock);
mArticulationRCPool.destroy(static_cast<NpArticulationReducedCoordinate*>(&articulation));
}
}
NpArticulation* NpFactory::createNpArticulation()
{
Ps::Mutex::ScopedLock lock(mArticulationPoolLock);
return mArticulationPool.construct();
}
PxArticulation* NpFactory::createArticulation()
{
if(!sCreateArticulationFn)
{
Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
"Articulations not registered: returned NULL.");
return NULL;
}
PxArticulationBase* npArticulation = (*sCreateArticulationFn)();
if(npArticulation)
addArticulation(npArticulation);
return static_cast<PxArticulation*>(npArticulation);
}
PxArticulationReducedCoordinate* NpFactory::createArticulationRC()
{
if (!sCreateArticulationRCFn)
{
Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
"Articulations not registered: returned NULL.");
return NULL;
}
PxArticulationBase* npArticulation = (*sCreateArticulationRCFn)();
if (npArticulation)
addArticulation(npArticulation);
return static_cast<PxArticulationReducedCoordinate*>(npArticulation);
}
NpArticulationReducedCoordinate* NpFactory::createNpArticulationRC()
{
Ps::Mutex::ScopedLock lock(mArticulationRCPoolLock);
return mArticulationRCPool.construct();
}
void NpFactory::onArticulationRelease(PxArticulationBase* a)
{
Ps::Mutex::ScopedLock lock(mTrackingMutex);
mArticulationTracking.erase(a);
}
NpArticulationLink* NpFactory::createNpArticulationLink(PxArticulationBase&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(PxArticulationBase& 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);
}
NpArticulationJointReducedCoordinate* NpFactory::createNpArticulationJointRC(NpArticulationLink& parent, const PxTransform& parentFrame, NpArticulationLink& child, const PxTransform& childFrame)
{
NpArticulationJointReducedCoordinate* npArticulationJoint;
{
Ps::Mutex::ScopedLock lock(mArticulationJointRCPoolLock);
npArticulationJoint = mArticulationRCJointPool.construct(parent, parentFrame, child, childFrame);
}
return npArticulationJoint;
}
void NpFactory::releaseArticulationJointRCToPool(NpArticulationJointReducedCoordinate& articulationJoint)
{
PX_ASSERT(articulationJoint.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
Ps::Mutex::ScopedLock lock(mArticulationJointRCPoolLock);
mArticulationRCJointPool.destroy(&articulationJoint);
}
/////////////////////////////////////////////////////////////////////////////// constraint
void NpFactory::addConstraint(PxConstraint* npConstraint, bool lock)
{
addToTracking(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
void NpFactory::addAggregate(PxAggregate* npAggregate, bool lock)
{
addToTracking(mAggregateTracking, npAggregate, mTrackingMutex, lock);
}
PxAggregate* NpFactory::createAggregate(PxU32 maxActors, bool selfCollisions)
{
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);
}
///////////////////////////////////////////////////////////////////////////////
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 materialData;
materialData.staticFriction = staticFriction;
materialData.dynamicFriction = dynamicFriction;
materialData.restitution = restitution;
NpMaterial* npMaterial;
{
Ps::Mutex::ScopedLock lock(mMaterialPoolLock);
npMaterial = mMaterialPool.construct(materialData);
}
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] = 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
{
// PT: TODO: isn't there a lock missing here? See usage in MeshFactory
return mShapeTracking.size();
}
PxU32 NpFactory::getShapes(PxShape** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
{
// PT: TODO: isn't there a lock missing here? See usage in MeshFactory
return Cm::getArrayOfPointers(userBuffer, bufferSize, startIndex, mShapeTracking.getEntries(), mShapeTracking.size());
}
///////////////////////////////////////////////////////////////////////////////
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);
}
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);
}
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::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_REDUCED_COORDINATE)
{
NpArticulationReducedCoordinate* np = static_cast<NpArticulationReducedCoordinate*>(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_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);
}
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)
{
PxArticulationJointBase* np = scb.getScArticulationJoint().getRoot();
if (np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
{
if (np->getConcreteType() == PxConcreteType::eARTICULATION_JOINT)
{
NpFactory::getInstance().releaseArticulationJointToPool(*static_cast<NpArticulationJoint*>(np));
}
else
{
PX_ASSERT(np->getConcreteType() == PxConcreteType::eARTICULATION_JOINT_REDUCED_COORDINATE);
NpFactory::getInstance().releaseArticulationJointRCToPool(*static_cast<NpArticulationJointReducedCoordinate*>(np));
}
}
else
np->~PxArticulationJointBase();
NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, NULL);
}
static void NpDestroyArticulation(Scb::Articulation& scb)
{
PxArticulationBase* artic = const_cast<PxArticulationBase*>(static_cast<const PxArticulationBase*>(getNpArticulation(&scb)));
void* ud = artic->PxArticulationBase::userData;
if (artic->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
NpFactory::getInstance().releaseArticulationToPool(*artic);
else
artic->~PxArticulationBase();
NpPhysics::getInstance().notifyDeletionListenersMemRelease(artic, 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);
}
namespace physx
{
void NpDestroy(Scb::Base& base)
{
switch(base.getScbType())
{
case ScbType::eSHAPE_EXCLUSIVE:
case ScbType::eSHAPE_SHARED: { NpDestroyShape(static_cast<Scb::Shape&>(base)); }break;
case ScbType::eBODY: { NpDestroyRigidDynamic(static_cast<Scb::Body&>(base)); }break;
case ScbType::eBODY_FROM_ARTICULATION_LINK: { NpDestroyArticulationLink(static_cast<Scb::Body&>(base)); }break;
case ScbType::eRIGID_STATIC: { NpDestroyRigidActor(static_cast<Scb::RigidStatic&>(base)); }break;
case ScbType::eCONSTRAINT: { NpDestroyConstraint(static_cast<Scb::Constraint&>(base)); }break;
case ScbType::eARTICULATION: { NpDestroyArticulation(static_cast<Scb::Articulation&>(base)); }break;
case ScbType::eARTICULATION_JOINT: { NpDestroyArticulationJoint(static_cast<Scb::ArticulationJoint&>(base)); }break;
case ScbType::eAGGREGATE: { NpDestroyAggregate(static_cast<Scb::Aggregate&>(base)); }break;
case ScbType::eUNDEFINED:
case ScbType::eTYPE_COUNT:
PX_ALWAYS_ASSERT_MESSAGE("NpDestroy: missing type!");
break;
}
}
}