diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/PhysX/src/NpShape.cpp | |
| download | physx-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.cpp | 851 |
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 |