aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/PhysX/src/NpShape.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/NpShape.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/NpShape.cpp')
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpShape.cpp851
1 files changed, 851 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysX/src/NpShape.cpp b/PhysX_3.4/Source/PhysX/src/NpShape.cpp
new file mode 100644
index 00000000..eafbd852
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpShape.cpp
@@ -0,0 +1,851 @@
+// 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 "GuConvexMesh.h"
+#include "GuTriangleMesh.h"
+#include "ScbNpDeps.h"
+#include "GuBounds.h"
+
+using namespace physx;
+using namespace Sq;
+
+namespace physx
+{
+ extern bool gUnifiedHeightfieldCollision;
+}
+
+static PX_FORCE_INLINE void updatePvdProperties(const Scb::Shape& shape)
+{
+#if PX_SUPPORT_PVD
+ Scb::Scene* scbScene = shape.getScbSceneForAPI();
+ if(scbScene)
+ scbScene->getScenePvdClient().updatePvdProperties(&shape);
+#else
+ PX_UNUSED(shape);
+#endif
+}
+
+NpShape::NpShape(const PxGeometry& geometry, PxShapeFlags shapeFlags, const PxU16* materialIndices, PxU16 materialCount, bool isExclusive)
+: PxShape (PxConcreteType::eSHAPE, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+, mActor (NULL)
+, mShape (geometry, shapeFlags, materialIndices, materialCount, isExclusive)
+, mName (NULL)
+, mExclusiveAndActorCount (isExclusive ? EXCLUSIVE_MASK : 0)
+{
+ PX_ASSERT(mShape.getScShape().getPxShape() == static_cast<PxShape*>(this));
+
+ PxShape::userData = NULL;
+
+ incMeshRefCount();
+}
+
+NpShape::~NpShape()
+{
+ decMeshRefCount();
+
+ PxU32 nbMaterials = mShape.getNbMaterials();
+ for (PxU32 i=0; i < nbMaterials; i++)
+ {
+ NpMaterial* mat = static_cast<NpMaterial*>(mShape.getMaterial(i));
+ mat->decRefCount();
+ }
+}
+
+void NpShape::onRefCountZero()
+{
+ NpFactory::getInstance().onShapeRelease(this);
+ // see NpShape.h for ref counting semantics for shapes
+ NpDestroy(getScbShape());
+}
+
+// PX_SERIALIZATION
+
+NpShape::NpShape(PxBaseFlags baseFlags) : PxShape(baseFlags), mShape(PxEmpty)
+{
+ mExclusiveAndActorCount &= EXCLUSIVE_MASK;
+}
+
+void NpShape::exportExtraData(PxSerializationContext& stream)
+{
+ getScbShape().getScShape().exportExtraData(stream);
+ stream.writeName(mName);
+}
+
+void NpShape::importExtraData(PxDeserializationContext& context)
+{
+ getScbShape().getScShape().importExtraData(context);
+ context.readName(mName);
+}
+
+void NpShape::requires(PxProcessPxBaseCallback& c)
+{
+ //meshes
+ PxBase* mesh = NULL;
+ switch(mShape.getGeometryType())
+ {
+ case PxGeometryType::eCONVEXMESH:
+ mesh = static_cast<const PxConvexMeshGeometry&>(mShape.getGeometry()).convexMesh;
+ break;
+ case PxGeometryType::eHEIGHTFIELD:
+ mesh = static_cast<const PxHeightFieldGeometry&>(mShape.getGeometry()).heightField;
+ break;
+ case PxGeometryType::eTRIANGLEMESH:
+ mesh = static_cast<const PxTriangleMeshGeometry&>(mShape.getGeometry()).triangleMesh;
+ break;
+ case PxGeometryType::eSPHERE:
+ case PxGeometryType::ePLANE:
+ case PxGeometryType::eCAPSULE:
+ case PxGeometryType::eBOX:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ break;
+ }
+
+ if(mesh)
+ c.process(*mesh);
+
+ //material
+ PxU32 nbMaterials = mShape.getNbMaterials();
+ for (PxU32 i=0; i < nbMaterials; i++)
+ {
+ NpMaterial* mat = static_cast<NpMaterial*>(mShape.getMaterial(i));
+ c.process(*mat);
+ }
+}
+
+void NpShape::resolveReferences(PxDeserializationContext& context)
+{
+ // getMaterials() only works after material indices have been patched.
+ // in order to get to the new material indices, we need access to the new materials.
+ // this only leaves us with the option of acquiring the material through the context given an old material index (we do have the mapping)
+ {
+ PxU32 nbIndices = mShape.getScShape().getNbMaterialIndices();
+ const PxU16* indices = mShape.getScShape().getMaterialIndices();
+
+ for (PxU32 i=0; i < nbIndices; i++)
+ {
+ PxBase* base = context.resolveReference(PX_SERIAL_REF_KIND_MATERIAL_IDX, size_t(indices[i]));
+ PX_ASSERT(base && base->is<PxMaterial>());
+
+ NpMaterial& material = *static_cast<NpMaterial*>(base);
+ getScbShape().getScShape().resolveMaterialReference(i, PxU16(material.getHandle()));
+ }
+ }
+
+ context.translatePxBase(mActor);
+
+ getScbShape().getScShape().resolveReferences(context);
+
+
+ incMeshRefCount();
+
+ // Increment materials' refcounts in a second pass. Works better in case of failure above.
+ PxU32 nbMaterials = mShape.getNbMaterials();
+ for (PxU32 i=0; i < nbMaterials; i++)
+ {
+ NpMaterial* mat = static_cast<NpMaterial*>(mShape.getMaterial(i));
+ mat->incRefCount();
+ }
+}
+
+NpShape* NpShape::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpShape* obj = new (address) NpShape(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpShape);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+void NpShape::acquireReference()
+{
+ incRefCount();
+}
+
+void NpShape::release()
+{
+ PX_CHECK_AND_RETURN(getRefCount() > 1 || getActorCount() == 0, "PxShape::release: last reference to a shape released while still attached to an actor!");
+ NP_WRITE_CHECK(getOwnerScene());
+ releaseInternal();
+}
+
+void NpShape::releaseInternal()
+{
+ decRefCount();
+}
+
+Sc::RigidCore& NpShape::getScRigidObjectExclusive() const
+{
+ const PxType actorType = mActor->getConcreteType();
+
+ if (actorType == PxConcreteType::eRIGID_DYNAMIC)
+ return static_cast<NpRigidDynamic&>(*mActor).getScbBodyFast().getScBody();
+ else if (actorType == PxConcreteType::eARTICULATION_LINK)
+ return static_cast<NpArticulationLink&>(*mActor).getScbBodyFast().getScBody();
+ else
+ return static_cast<NpRigidStatic&>(*mActor).getScbRigidStaticFast().getScStatic();
+}
+
+PxGeometryType::Enum NpShape::getGeometryType() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getGeometryType();
+}
+
+void NpShape::setGeometry(const PxGeometry& g)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setGeometry: shared shapes attached to actors are not writable.");
+ PX_SIMD_GUARD;
+
+ // PT: fixes US2117
+ if(g.getType() != getGeometryTypeFast())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxShape::setGeometry(): Invalid geometry type. Changing the type of the shape is not supported.");
+ return;
+ }
+
+#if PX_CHECKED
+ bool isValid = false;
+ switch(g.getType())
+ {
+ case PxGeometryType::eSPHERE:
+ isValid = static_cast<const PxSphereGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::ePLANE:
+ isValid = static_cast<const PxPlaneGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eCAPSULE:
+ isValid = static_cast<const PxCapsuleGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eBOX:
+ isValid = static_cast<const PxBoxGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eCONVEXMESH:
+ isValid = static_cast<const PxConvexMeshGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eTRIANGLEMESH:
+ isValid = static_cast<const PxTriangleMeshGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eHEIGHTFIELD:
+ isValid = static_cast<const PxHeightFieldGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ break;
+ }
+
+ if(!isValid)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxShape::setGeometry(): Invalid geometry!");
+ return;
+ }
+#endif
+
+ decMeshRefCount();
+
+ mShape.setGeometry(g);
+
+ incMeshRefCount();
+
+ if((mShape.getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE) && mActor)
+ {
+ PX_ASSERT(mActor);
+
+ NpScene* scene = NpActor::getOwnerScene(*mActor);
+ NpShapeManager* shapeManager = NpActor::getShapeManager(*mActor);
+ if(scene)
+ {
+ const PrunerData sqData = shapeManager->findSceneQueryData(*this);
+ scene->getSceneQueryManagerFast().markForUpdate(sqData);
+ }
+
+ // invalidate the pruning structure if the actor bounds changed
+ if (shapeManager->getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxShape::setGeometry: Shape is a part of pruning structure, pruning structure is now invalid!");
+ shapeManager->getPruningStructure()->invalidate(mActor);
+ }
+ }
+}
+
+PxGeometryHolder NpShape::getGeometry() const
+{
+ PX_COMPILE_TIME_ASSERT(sizeof(Gu::GeometryUnion)>=sizeof(PxGeometryHolder));
+ return reinterpret_cast<const PxGeometryHolder&>(mShape.getGeometry());
+}
+
+template<class T>
+static PX_FORCE_INLINE bool getGeometryT(const NpShape* npShape, PxGeometryType::Enum type, T& geom)
+{
+ NP_READ_CHECK(npShape->getOwnerScene());
+
+ if(npShape->getGeometryTypeFast() != type)
+ return false;
+
+ geom = static_cast<const T&>(npShape->getScbShape().getGeometry());
+ return true;
+}
+
+bool NpShape::getBoxGeometry(PxBoxGeometry& g) const { return getGeometryT(this, PxGeometryType::eBOX, g); }
+bool NpShape::getSphereGeometry(PxSphereGeometry& g) const { return getGeometryT(this, PxGeometryType::eSPHERE, g); }
+bool NpShape::getCapsuleGeometry(PxCapsuleGeometry& g) const { return getGeometryT(this, PxGeometryType::eCAPSULE, g); }
+bool NpShape::getPlaneGeometry(PxPlaneGeometry& g) const { return getGeometryT(this, PxGeometryType::ePLANE, g); }
+bool NpShape::getConvexMeshGeometry(PxConvexMeshGeometry& g) const { return getGeometryT(this, PxGeometryType::eCONVEXMESH, g); }
+bool NpShape::getTriangleMeshGeometry(PxTriangleMeshGeometry& g) const { return getGeometryT(this, PxGeometryType::eTRIANGLEMESH, g); }
+bool NpShape::getHeightFieldGeometry(PxHeightFieldGeometry& g) const { return getGeometryT(this, PxGeometryType::eHEIGHTFIELD, g); }
+
+PxRigidActor* NpShape::getActor() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mActor;
+}
+
+void NpShape::setLocalPose(const PxTransform& newShape2Actor)
+{
+ PX_CHECK_AND_RETURN(newShape2Actor.isSane(), "PxShape::setLocalPose: pose is not valid.");
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setLocalPose: shared shapes attached to actors are not writable.");
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mShape.setShape2Actor(newShape2Actor.getNormalized());
+
+ if(mShape.getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE && mActor)
+ {
+ NpScene* scene = NpActor::getAPIScene(*mActor);
+ NpShapeManager* shapeManager = NpActor::getShapeManager(*mActor);
+ if(scene)
+ {
+ const PrunerData sqData = shapeManager->findSceneQueryData(*this);
+ scene->getSceneQueryManagerFast().markForUpdate(sqData);
+ }
+
+ // invalidate the pruning structure if the actor bounds changed
+ if (shapeManager->getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxShape::setLocalPose: Shape is a part of pruning structure, pruning structure is now invalid!");
+ shapeManager->getPruningStructure()->invalidate(mActor);
+ }
+ }
+}
+
+PxTransform NpShape::getLocalPose() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getShape2Actor();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpShape::setSimulationFilterData(const PxFilterData& data)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setSimulationFilterData: shared shapes attached to actors are not writable.");
+ mShape.setSimulationFilterData(data);
+}
+
+PxFilterData NpShape::getSimulationFilterData() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mShape.getSimulationFilterData();
+}
+
+void NpShape::setQueryFilterData(const PxFilterData& data)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setQueryFilterData: shared shapes attached to actors are not writable.");
+
+ mShape.getScShape().setQueryFilterData(data); // PT: this one doesn't need double-buffering
+
+ updatePvdProperties(mShape);
+}
+
+PxFilterData NpShape::getQueryFilterData() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return getQueryFilterDataFast();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpShape::setMaterials(PxMaterial*const* materials, PxU16 materialCount)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setMaterials: shared shapes attached to actors are not writable.");
+
+#if PX_CHECKED
+ if (!NpShape::checkMaterialSetup(mShape.getGeometry(), "PxShape::setMaterials()", materials, materialCount))
+ return;
+#endif
+
+ PxU32 oldMaterialCount = mShape.getNbMaterials();
+ PX_ALLOCA(oldMaterials, PxMaterial*, oldMaterialCount);
+ PxU32 tmp = mShape.getMaterials(oldMaterials, oldMaterialCount);
+ PX_ASSERT(tmp == oldMaterialCount);
+ PX_UNUSED(tmp);
+
+ if (mShape.setMaterials(materials, materialCount))
+ {
+ for(PxU32 i=0; i < materialCount; i++)
+ static_cast<NpMaterial*>(materials[i])->incRefCount();
+
+ for(PxU32 i=0; i < oldMaterialCount; i++)
+ static_cast<NpMaterial*>(oldMaterials[i])->decRefCount();
+ }
+}
+
+PxU16 NpShape::getNbMaterials() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getNbMaterials();
+}
+
+PxU32 NpShape::getMaterials(PxMaterial** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getMaterials(userBuffer, bufferSize, startIndex);
+}
+
+PxMaterial* NpShape::getMaterialFromInternalFaceIndex(PxU32 faceIndex) const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ bool isHf = (getGeometryType() == PxGeometryType::eHEIGHTFIELD);
+ bool isMesh = (getGeometryType() == PxGeometryType::eTRIANGLEMESH);
+ if( faceIndex == 0xFFFFffff && (isHf || isMesh) )
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxShape::getMaterialFromInternalFaceIndex received 0xFFFFffff as input - returning NULL.");
+ return NULL;
+ }
+
+ PxMaterialTableIndex hitMatTableId = 0;
+
+ if(isHf)
+ {
+ PxHeightFieldGeometry hfGeom;
+ getHeightFieldGeometry(hfGeom);
+
+ hitMatTableId = hfGeom.heightField->getTriangleMaterialIndex(faceIndex);
+ }
+ else if(isMesh)
+ {
+ PxTriangleMeshGeometry triGeo;
+ getTriangleMeshGeometry(triGeo);
+
+ Gu::TriangleMesh* tm = static_cast<Gu::TriangleMesh*>(triGeo.triangleMesh);
+ if(tm->hasPerTriangleMaterials())
+ hitMatTableId = triGeo.triangleMesh->getTriangleMaterialIndex(faceIndex);
+ }
+
+ return getMaterial(hitMatTableId);
+}
+
+void NpShape::setContactOffset(PxReal contactOffset)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+
+ PX_CHECK_AND_RETURN(PxIsFinite(contactOffset), "PxShape::setContactOffset: invalid float");
+ PX_CHECK_AND_RETURN((contactOffset >= 0.0f && contactOffset > mShape.getRestOffset()), "PxShape::setContactOffset: contactOffset should be positive, and greater than restOffset!");
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setContactOffset: shared shapes attached to actors are not writable.");
+
+ mShape.setContactOffset(contactOffset);
+}
+
+PxReal NpShape::getContactOffset() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getContactOffset();
+}
+
+void NpShape::setRestOffset(PxReal restOffset)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(PxIsFinite(restOffset), "PxShape::setRestOffset: invalid float");
+ PX_CHECK_AND_RETURN((restOffset < mShape.getContactOffset()), "PxShape::setRestOffset: restOffset should be less than contactOffset!");
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setRestOffset: shared shapes attached to actors are not writable.");
+
+ mShape.setRestOffset(restOffset);
+}
+
+PxReal NpShape::getRestOffset() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getRestOffset();
+}
+
+void NpShape::setFlagsInternal(PxShapeFlags inFlags)
+{
+ const bool hasMeshTypeGeom = mShape.getGeometryType() == PxGeometryType::eTRIANGLEMESH || mShape.getGeometryType() == PxGeometryType::eHEIGHTFIELD;
+
+ if(hasMeshTypeGeom && (inFlags & PxShapeFlag::eTRIGGER_SHAPE))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxShape::setFlag(s): triangle mesh and heightfield triggers are not supported!");
+ return;
+ }
+
+ if((inFlags & PxShapeFlag::eSIMULATION_SHAPE) && (inFlags & PxShapeFlag::eTRIGGER_SHAPE))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxShape::setFlag(s): shapes cannot simultaneously be trigger shapes and simulation shapes.");
+ return;
+ }
+
+ const PxShapeFlags oldFlags = mShape.getFlags();
+
+ const bool oldIsSimShape = oldFlags & PxShapeFlag::eSIMULATION_SHAPE;
+ const bool isSimShape = inFlags & PxShapeFlag::eSIMULATION_SHAPE;
+
+ if(mActor)
+ {
+ const PxType type = mActor->getConcreteType();
+
+ // PT: US5732 - support kinematic meshes
+ bool isKinematic = false;
+ if(type==PxConcreteType::eRIGID_DYNAMIC)
+ {
+ PxRigidDynamic* rigidDynamic = static_cast<PxRigidDynamic*>(mActor);
+ isKinematic = rigidDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC;
+ }
+
+ if((type != PxConcreteType::eRIGID_STATIC) && !isKinematic && isSimShape && !oldIsSimShape && (hasMeshTypeGeom || mShape.getGeometryType() == PxGeometryType::ePLANE))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxShape::setFlag(s): triangle mesh, heightfield and plane shapes can only be simulation shapes if part of a PxRigidStatic!");
+ return;
+ }
+ }
+
+ const bool oldHasSceneQuery = oldFlags & PxShapeFlag::eSCENE_QUERY_SHAPE;
+ const bool hasSceneQuery = inFlags & PxShapeFlag::eSCENE_QUERY_SHAPE;
+
+ mShape.setFlags(inFlags);
+
+ if(oldHasSceneQuery != hasSceneQuery && mActor)
+ {
+ NpScene* npScene = getAPIScene();
+ NpShapeManager* shapeManager = NpActor::getShapeManager(*mActor);
+ if(npScene)
+ {
+ if(hasSceneQuery)
+ shapeManager->setupSceneQuery(npScene->getSceneQueryManagerFast(), *mActor, *this);
+ else
+ shapeManager->teardownSceneQuery(npScene->getSceneQueryManagerFast(), *this);
+ }
+
+ // invalidate the pruning structure if the actor bounds changed
+ if(shapeManager->getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxShape::setFlag: Shape is a part of pruning structure, pruning structure is now invalid!");
+ shapeManager->getPruningStructure()->invalidate(mActor);
+ }
+ }
+}
+
+void NpShape::setFlag(PxShapeFlag::Enum flag, bool value)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setFlag: shared shapes attached to actors are not writable.");
+ PX_SIMD_GUARD;
+
+ PxShapeFlags shapeFlags = mShape.getFlags();
+ shapeFlags = value ? shapeFlags | flag : shapeFlags & ~flag;
+
+ setFlagsInternal(shapeFlags);
+}
+
+void NpShape::setFlags( PxShapeFlags inFlags )
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_SIMD_GUARD;
+
+ setFlagsInternal(inFlags);
+}
+
+PxShapeFlags NpShape::getFlags() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mShape.getFlags();
+}
+
+bool NpShape::isExclusive() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return (mExclusiveAndActorCount & EXCLUSIVE_MASK) != 0;
+}
+
+void NpShape::onActorAttach(PxRigidActor& actor)
+{
+ incRefCount();
+ if(isExclusiveFast())
+ mActor = &actor;
+ Ps::atomicIncrement(&mExclusiveAndActorCount);
+}
+
+void NpShape::onActorDetach()
+{
+ PX_ASSERT(getActorCount() > 0);
+ Ps::atomicDecrement(&mExclusiveAndActorCount);
+ if(isExclusiveFast())
+ mActor = NULL;
+ decRefCount();
+}
+
+void NpShape::setName(const char* debugName)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setName: shared shapes attached to actors are not writable.");
+
+ mName = debugName;
+
+ updatePvdProperties(mShape);
+}
+
+const char* NpShape::getName() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mName;
+}
+
+NpScene* NpShape::getOwnerScene() const
+{
+ return mActor ? NpActor::getOwnerScene(*mActor) : NULL;
+}
+
+NpScene* NpShape::getAPIScene() const
+{
+ // gets called when we update SQ structures due to a write - in which case there must be an actor
+ PX_ASSERT(mActor);
+ return NpActor::getAPIScene(*mActor);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace physx
+{
+Sc::RigidCore* NpShapeGetScRigidObjectFromScbSLOW(const Scb::Shape &scb)
+{
+ const NpShape* np = getNpShape(&scb);
+ return np->NpShape::getActor() ? &np->getScRigidObjectExclusive() : NULL;
+}
+
+size_t NpShapeGetScPtrOffset()
+{
+ const size_t offset = size_t(&(reinterpret_cast<NpShape*>(0)->getScbShape().getScShape()));
+ return offset;
+}
+
+void NpShapeIncRefCount(Scb::Shape& scb)
+{
+ NpShape* np = const_cast<NpShape*>(getNpShape(&scb));
+ np->incRefCount();
+}
+
+void NpShapeDecRefCount(Scb::Shape& scb)
+{
+ NpShape* np = const_cast<NpShape*>(getNpShape(&scb));
+ np->decRefCount();
+}
+}
+
+// see NpConvexMesh.h, NpHeightField.h, NpTriangleMesh.h for details on how ref counting works
+// for meshes
+Cm::RefCountable* NpShape::getMeshRefCountable()
+{
+ switch(mShape.getGeometryType())
+ {
+ case PxGeometryType::eCONVEXMESH:
+ return static_cast<Gu::ConvexMesh*>(
+ static_cast<const PxConvexMeshGeometry&>(mShape.getGeometry()).convexMesh);
+
+ case PxGeometryType::eHEIGHTFIELD:
+ return static_cast<Gu::HeightField*>(
+ static_cast<const PxHeightFieldGeometry&>(mShape.getGeometry()).heightField);
+
+ case PxGeometryType::eTRIANGLEMESH:
+ return static_cast<Gu::TriangleMesh*>(
+ static_cast<const PxTriangleMeshGeometry&>(mShape.getGeometry()).triangleMesh);
+
+ case PxGeometryType::eSPHERE:
+ case PxGeometryType::ePLANE:
+ case PxGeometryType::eCAPSULE:
+ case PxGeometryType::eBOX:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ break;
+ }
+ return NULL;
+}
+
+bool NpShape::isWritable()
+{
+ // a shape is writable if it's exclusive, or it's not connected to any actors (which is true if the ref count is 1 and the user ref is not released.)
+ return isExclusiveFast() || (getRefCount()==1 && (mBaseFlags & PxBaseFlag::eIS_RELEASABLE));
+}
+
+void NpShape::incMeshRefCount()
+{
+ Cm::RefCountable* npMesh = getMeshRefCountable();
+ if(npMesh)
+ npMesh->incRefCount();
+}
+
+void NpShape::decMeshRefCount()
+{
+ Cm::RefCountable* npMesh = getMeshRefCountable();
+ if(npMesh)
+ npMesh->decRefCount();
+}
+
+bool NpShape::checkMaterialSetup(const PxGeometry& geom, const char* errorMsgPrefix, PxMaterial*const* materials, PxU16 materialCount)
+{
+ for(PxU32 i=0; i<materialCount; ++i)
+ {
+ if(!materials[i])
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "material pointer %d is NULL!", i);
+ return false;
+ }
+ }
+
+ // check that simple shapes don't get assigned multiple materials
+ if (materialCount > 1 && (geom.getType() != PxGeometryType::eHEIGHTFIELD) && (geom.getType() != PxGeometryType::eTRIANGLEMESH))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "%s: multiple materials defined for single material geometry!", errorMsgPrefix);
+ return false;
+ }
+
+ // verify we provide all materials required
+ if (materialCount > 1 && (geom.getType() == PxGeometryType::eTRIANGLEMESH))
+ {
+ const PxTriangleMeshGeometry& meshGeom = static_cast<const PxTriangleMeshGeometry&>(geom);
+ const PxTriangleMesh& mesh = *meshGeom.triangleMesh;
+ if(mesh.getTriangleMaterialIndex(0) != 0xffff)
+ {
+ for(PxU32 i = 0; i < mesh.getNbTriangles(); i++)
+ {
+ const PxMaterialTableIndex meshMaterialIndex = mesh.getTriangleMaterialIndex(i);
+ if(meshMaterialIndex >= materialCount)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "%s: PxTriangleMesh material indices reference more materials than provided!", errorMsgPrefix);
+ break;
+ }
+ }
+ }
+ }
+ if (materialCount > 1 && (geom.getType() == PxGeometryType::eHEIGHTFIELD))
+ {
+ const PxHeightFieldGeometry& meshGeom = static_cast<const PxHeightFieldGeometry&>(geom);
+ const PxHeightField& mesh = *meshGeom.heightField;
+ if(mesh.getTriangleMaterialIndex(0) != 0xffff)
+ {
+ const PxU32 nbTris = (mesh.getNbColumns() - 1)*(mesh.getNbColumns() - 1)*2;
+ for(PxU32 i = 0; i < nbTris; i++)
+ {
+ const PxMaterialTableIndex meshMaterialIndex = mesh.getTriangleMaterialIndex(i);
+ if(meshMaterialIndex >= materialCount)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "%s: PxHeightField material indices reference more materials than provided!", errorMsgPrefix);
+ break;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+#include "GuDebug.h"
+
+void NpShape::visualize(Cm::RenderOutput& out, const PxRigidActor& actor)
+{
+ NpScene* npScene = NpActor::getOwnerScene(actor);
+ PX_ASSERT(npScene);
+
+ const PxReal scale = npScene->getVisualizationParameter(PxVisualizationParameter::eSCALE);
+ if(!scale) return;
+
+ const PxTransform absPose = actor.getGlobalPose() * mShape.getShape2Actor();
+
+ if(npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_AABBS))
+ out << PxU32(PxDebugColor::eARGB_YELLOW) << PxMat44(PxIdentity) << Cm::DebugBox(Gu::computeBounds(mShape.getGeometry(), absPose, !gUnifiedHeightfieldCollision));
+
+ const PxReal collisionAxes = scale * npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_AXES);
+ if(collisionAxes != 0.0f)
+ out << PxMat44(absPose) << Cm::DebugBasis(PxVec3(collisionAxes), 0xcf0000, 0x00cf00, 0x0000cf);
+
+ if( npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_SHAPES) ||
+ npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_FNORMALS) ||
+ npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_EDGES))
+ {
+ const PxBounds3& cullbox = npScene->getVisualizationCullingBox();
+
+ const PxReal fscale = scale * npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_FNORMALS);
+
+ // Pack bool params into bit mask.
+ PxU64 mask = 0;
+
+ #define SET_MASK(mask, param) (mask |= (PxU64(!!npScene->getVisualizationParameter(param))) << param)
+
+ SET_MASK(mask, PxVisualizationParameter::eCULL_BOX);
+ SET_MASK(mask, PxVisualizationParameter::eCOLLISION_FNORMALS);
+ SET_MASK(mask, PxVisualizationParameter::eCOLLISION_EDGES);
+ SET_MASK(mask, PxVisualizationParameter::eCOLLISION_SHAPES);
+
+ Sc::ShapeCore& shape = mShape.getScShape();
+ const PxU32 numMaterials = shape.getNbMaterialIndices();
+ Gu::Debug::visualize(getGeometryFast().getGeometry(), out, absPose, cullbox, mask, fscale, numMaterials);
+ }
+}
+
+#endif // PX_ENABLE_DEBUG_VISUALIZATION