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/particles/NpParticleBaseTemplate.h | |
| 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/particles/NpParticleBaseTemplate.h')
| -rw-r--r-- | PhysX_3.4/Source/PhysX/src/particles/NpParticleBaseTemplate.h | 925 |
1 files changed, 925 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysX/src/particles/NpParticleBaseTemplate.h b/PhysX_3.4/Source/PhysX/src/particles/NpParticleBaseTemplate.h new file mode 100644 index 00000000..001d3cbd --- /dev/null +++ b/PhysX_3.4/Source/PhysX/src/particles/NpParticleBaseTemplate.h @@ -0,0 +1,925 @@ +// 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. + + +#ifndef PX_PHYSICS_NP_PARTICLESYSTEM_TEMPLATE +#define PX_PHYSICS_NP_PARTICLESYSTEM_TEMPLATE + +#include "PxPhysXConfig.h" + +#if PX_USE_PARTICLE_SYSTEM_API + +#include "NpActorTemplate.h" +#include "PxParticleSystem.h" +#include "ScbParticleSystem.h" +#include "NpWriteCheck.h" +#include "NpReadCheck.h" +#include "PtParticleData.h" +#include "NpScene.h" + +#if PX_SUPPORT_GPU_PHYSX +#include "PxParticleDeviceExclusive.h" +#endif + +namespace physx +{ + +template<class APIClass, class LeafClass> +class NpParticleBaseTemplate : public NpActorTemplate<APIClass> +{ +public: +// PX_SERIALIZATION + NpParticleBaseTemplate(PxBaseFlags baseFlags) : NpActorTemplate<APIClass>(baseFlags), mParticleSystem(PxEmpty) {} +//~PX_SERIALIZATION + NpParticleBaseTemplate<APIClass, LeafClass>(PxType, PxBaseFlags, const PxActorType::Enum&, PxU32, bool); + virtual ~NpParticleBaseTemplate(); + + //--------------------------------------------------------------------------------- + // PxParticleSystemActor implementation + //--------------------------------------------------------------------------------- + virtual void release(); + + virtual PxActorType::Enum getType() const { return PxActorType::ePARTICLE_SYSTEM; } + + virtual bool createParticles(const PxParticleCreationData& creationData); + virtual void releaseParticles(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer); + virtual void releaseParticles(); + virtual void setPositions(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, + const PxStrideIterator<const PxVec3>& positionBuffer); + virtual void setVelocities(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, + const PxStrideIterator<const PxVec3>& velocityBuffer); + virtual void setRestOffsets(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, + const PxStrideIterator<const PxF32>& restOffsetBuffer); + virtual void addForces(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, + const PxStrideIterator<const PxVec3>& forceBuffer, PxForceMode::Enum forceMode); + virtual PxParticleReadData* lockParticleReadData(PxDataAccessFlags flags); + virtual PxParticleReadData* lockParticleReadData(); + + virtual PxReal getDamping() const; + virtual void setDamping(PxReal); + virtual PxVec3 getExternalAcceleration() const; + virtual void setExternalAcceleration(const PxVec3&); + + virtual PxReal getParticleMass() const; + virtual void setParticleMass(PxReal); + virtual PxReal getRestitution() const; + virtual void setRestitution(PxReal); + virtual PxReal getDynamicFriction() const; + virtual void setDynamicFriction(PxReal); + virtual PxReal getStaticFriction() const; + virtual void setStaticFriction(PxReal); + + virtual void setSimulationFilterData(const PxFilterData& data); + virtual PxFilterData getSimulationFilterData() const; + virtual void resetFiltering(); + + virtual void setParticleBaseFlag(PxParticleBaseFlag::Enum flag, bool value); + virtual PxParticleBaseFlags getParticleBaseFlags() const; + + virtual PxParticleReadDataFlags getParticleReadDataFlags() const; + virtual void setParticleReadDataFlag(PxParticleReadDataFlag::Enum, bool); + + virtual PxU32 getMaxParticles() const; + + virtual PxReal getMaxMotionDistance() const; + virtual void setMaxMotionDistance(PxReal); + virtual PxReal getRestOffset() const; + virtual void setRestOffset(PxReal); + virtual PxReal getContactOffset() const; + virtual void setContactOffset(PxReal); + virtual PxReal getGridSize() const; + virtual void setGridSize(PxReal); + + virtual void getProjectionPlane(PxVec3& normal, PxReal& d) const; + virtual void setProjectionPlane(const PxVec3& normal, PxReal d); + + virtual PxBounds3 getWorldBounds(float inflation=1.01f) const; + + typedef NpActorTemplate<APIClass> ActorTemplateClass; + + //--------------------------------------------------------------------------------- + // Miscellaneous + //--------------------------------------------------------------------------------- + PX_INLINE Scb::Actor& getScbActor() const { return const_cast<Scb::ParticleSystem&>(mParticleSystem); } + + PX_INLINE const Scb::ParticleSystem& getScbParticleSystem() const { return mParticleSystem; } + PX_INLINE Scb::ParticleSystem& getScbParticleSystem() { return mParticleSystem; } + PX_INLINE NpScene* getNpScene() const { return NpActor::getAPIScene(*this); } + +#if PX_SUPPORT_GPU_PHYSX + // Helper for reporting error conditions. + class PxParticleDeviceExclusiveAccess* getDeviceExclusiveAccessGpu(const char* callerName) const; + + void enableDeviceExclusiveModeGpu(); + bool isDeviceExclusiveModeEnabledGpu() const; + void getReadWriteCudaBuffersGpu(struct PxCudaReadWriteParticleBuffers& buffers) const; + void setValidParticleRangeGpu(PxU32 validParticleRange); + void setDeviceExclusiveModeFlagsGpu(PxU32 flags); + PxBaseTask* getLaunchTaskGpu() const; + void addLaunchTaskDependentGpu(class physx::PxBaseTask& dependent); + size_t getCudaStreamGpu() const; +#endif + +private: + bool checkAllocatedIndices(PxU32 numIndices, const PxStrideIterator<const PxU32>& indices); + bool checkFreeIndices(PxU32 numIndices, const PxStrideIterator<const PxU32>& indices); + +//private: +public: // PT: sorry, needs to be accessible to serialization macro + Scb::ParticleSystem mParticleSystem; +}; + + +template<class APIClass, class LeafClass> +NpParticleBaseTemplate<APIClass, LeafClass>::NpParticleBaseTemplate(PxType concreteType, PxBaseFlags baseFlags, const PxActorType::Enum& actorType, PxU32 maxParticles, bool perParticleRestOffset) +: ActorTemplateClass(concreteType, baseFlags, NULL, NULL) +, mParticleSystem(actorType, maxParticles, perParticleRestOffset) +{ + // don't ref Scb actor here, it hasn't been assigned yet +} + + +template<class APIClass, class LeafClass> +NpParticleBaseTemplate<APIClass, LeafClass>::~NpParticleBaseTemplate() +{ +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::release() +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + NpPhysics::getInstance().notifyDeletionListenersUserRelease(this, this->userData); + +// PX_AGGREGATE + ActorTemplateClass::release(); // PT: added for PxAggregate +//~PX_AGGREGATE + + NpScene* npScene = NpActor::getAPIScene(*this); + if (npScene) + { + npScene->removeFromParticleBaseList(*this); + npScene->getScene().removeParticleSystem(static_cast<LeafClass&>(*this).getScbParticleSystem(), true); + } + mParticleSystem.destroy(); +} + +#if PX_CHECKED +namespace +{ + bool checkUniqueIndices(PxU32 numIndices, const PxStrideIterator<const PxU32>& indices) + { + Cm::BitMap bitmap; + PxU32 i = 0; + for (; i != numIndices; ++i) + { + PxU32 index = indices[i]; + if (bitmap.boundedTest(index)) + break; + bitmap.growAndSet(index); + } + + if (i != numIndices) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "PxParticleBase::releaseParticles(): indexBuffer contains duplicate particle index %d.", indices[i]); + return false; + } + return true; + } + + bool checkVectors(PxU32 numVectors, const PxStrideIterator<const PxVec3>& vectors) + { + for (PxU32 i = 0; i < numVectors; ++i) + { + if(!vectors[i].isFinite()) + return false; + } + return true; + } + + bool checkRestOffsets(PxU32 numParticles, const PxStrideIterator<const PxF32>& restOffsetBuffer, PxF32 restOffset) + { + for (PxU32 i = 0; i < numParticles; ++i) + { + if (restOffsetBuffer[i] < 0.0f || restOffsetBuffer[i] > restOffset) + return false; + } + return true; + } + + bool checkRestOffset(Pt::ParticleData& standaloneData, PxF32 restOffset) + { + const PxF32* restOffsetBuffer = standaloneData.getRestOffsetBuffer(); + PxU32 numParticles = standaloneData.getMaxParticles(); + for (PxU32 i = 0; i < numParticles; ++i) + { + if (restOffsetBuffer[i] > restOffset) + return false; + } + return true; + } +} +#endif // PX_CHECKED + +//----------------------------------------------------------------------------// + +template<class APIClass, class LeafClass> +bool NpParticleBaseTemplate<APIClass, LeafClass>::checkAllocatedIndices(PxU32 numIndices, const PxStrideIterator<const PxU32>& indices) +{ + const Cm::BitMap& map = mParticleSystem.getParticleMap(); + PxU32 maxParticles = getMaxParticles(); + + for (PxU32 i = 0; i < numIndices; ++i) + { + PxU32 index = indices[i]; + + if (index >= maxParticles) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "Operation on particle index %d not in valid range [0, %d]", index, getMaxParticles() - 1); + return false; + } + + if (!map.boundedTest(index)) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "Operation on invalid particle with index %d", index); + return false; + } + } + return true; +} + +//----------------------------------------------------------------------------// + +template<class APIClass, class LeafClass> +bool NpParticleBaseTemplate<APIClass, LeafClass>::checkFreeIndices(PxU32 numIndices, const PxStrideIterator<const PxU32>& indices) +{ + const Cm::BitMap& map = mParticleSystem.getParticleMap(); + PxU32 maxParticles = getMaxParticles(); + + for (PxU32 i = 0; i < numIndices; ++i) + { + PxU32 index = indices[i]; + + if (index >= maxParticles) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "Provided particle index %d is not in valid range [0, %d]", index, getMaxParticles() - 1); + return false; + } + + if (map.boundedTest(index)) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, + "Provided particle index %d is already in use", index); + return false; + } + } + return true; +} + +//----------------------------------------------------------------------------// + +template<class APIClass, class LeafClass> +bool NpParticleBaseTemplate<APIClass, LeafClass>::createParticles(const PxParticleCreationData& creationData) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PX_CHECK_AND_RETURN_NULL(creationData.isValid(), "PxParticleCreationData submitted with PxParticleBase::createParticles() invalid."); + if (creationData.numParticles == 0) + return true; + + bool supportsPerParticleRestOffset = getScbParticleSystem().getFlags() & PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET; + bool perParticleRestOffset = creationData.restOffsetBuffer.ptr() != NULL; + + PX_UNUSED(supportsPerParticleRestOffset); + PX_UNUSED(perParticleRestOffset); + + PX_CHECK_AND_RETURN_NULL(!perParticleRestOffset || supportsPerParticleRestOffset, "PxParticleCreationData.restOffsetBuffer set but PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET not set.") + PX_CHECK_AND_RETURN_NULL(!supportsPerParticleRestOffset || perParticleRestOffset, "PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET set, but PxParticleCreationData.restOffsetBuffer not set.") + +#if PX_CHECKED + PX_CHECK_AND_RETURN_NULL(checkFreeIndices(creationData.numParticles, creationData.indexBuffer), "PxParticleBase::createParticles: failed"); + PX_CHECK_AND_RETURN_NULL(checkUniqueIndices(creationData.numParticles, creationData.indexBuffer), "PxParticleBase::createParticles: failed"); + + if (perParticleRestOffset) + PX_CHECK_AND_RETURN_NULL(checkRestOffsets(creationData.numParticles, creationData.restOffsetBuffer, getScbParticleSystem().getRestOffset()), + "PxParticleCreationData.restOffsetBuffer: offsets must be in range [0.0f, restOffset]."); + + PX_CHECK_AND_RETURN_NULL(checkVectors(creationData.numParticles, creationData.positionBuffer), "PxParticleBase::createParticles: position vectors shoule be finite"); + + bool perParticleVelocity = creationData.velocityBuffer.ptr() != NULL; + if(perParticleVelocity) + { + PX_CHECK_AND_RETURN_NULL(checkVectors(creationData.numParticles, creationData.velocityBuffer), "PxParticleBase::createParticles: velocity vectors shoule be finite"); + } +#endif + + return getScbParticleSystem().createParticles(creationData); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::releaseParticles(PxU32 numParticles, const PxStrideIterator<const PxU32>& indices) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + if (numParticles == 0) + return; + +#if PX_CHECKED + PX_CHECK_AND_RETURN(indices.ptr() && indices.stride() != 0, "PxParticleBase::releaseParticles: invalid index buffer"); + PX_CHECK_AND_RETURN(checkAllocatedIndices(numParticles, indices), "PxParticleBase::releaseParticles: failed"); + PX_CHECK_AND_RETURN(checkUniqueIndices(numParticles, indices), "PxParticleBase::releaseParticles: failed"); +#endif + + getScbParticleSystem().releaseParticles(numParticles, indices); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::releaseParticles() +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + getScbParticleSystem().releaseParticles(); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setPositions(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, + const PxStrideIterator<const PxVec3>& positionBuffer) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + if (numParticles == 0) + return; + + PX_CHECK_AND_RETURN(indexBuffer.ptr() && indexBuffer.stride() != 0, "PxParticleBase::setPositions: invalid index buffer"); + PX_CHECK_AND_RETURN(positionBuffer.ptr(), "PxParticleBase::setPositions: invalid position buffer"); + +#if PX_CHECKED + PX_CHECK_AND_RETURN(checkAllocatedIndices(numParticles, indexBuffer), "PxParticleBase::setPositions: failed"); + PX_CHECK_AND_RETURN(checkVectors(numParticles, positionBuffer), "PxParticleBase::setPositions: position vectors shoule be finite"); +#endif + + getScbParticleSystem().setPositions(numParticles, indexBuffer, positionBuffer); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setVelocities(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, + const PxStrideIterator<const PxVec3>& velocityBuffer) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + if (numParticles == 0) + return; + + PX_CHECK_AND_RETURN(indexBuffer.ptr() && indexBuffer.stride() != 0, "PxParticleBase::setVelocities: invalid index buffer"); + PX_CHECK_AND_RETURN(velocityBuffer.ptr(), "PxParticleBase::setVelocities: invalid velocity buffer"); + +#if PX_CHECKED + PX_CHECK_AND_RETURN(checkAllocatedIndices(numParticles, indexBuffer), "PxParticleBase::setVelocities: failed"); + PX_CHECK_AND_RETURN(checkVectors(numParticles, velocityBuffer), "PxParticleBase::setVelocities: velocity vectors shoule be finite"); +#endif + getScbParticleSystem().setVelocities(numParticles, indexBuffer, velocityBuffer); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setRestOffsets(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, + const PxStrideIterator<const PxF32>& restOffsetBuffer) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + if (numParticles == 0) + return; + + PX_CHECK_AND_RETURN(indexBuffer.ptr() && indexBuffer.stride() != 0, "PxParticleBase::setRestOffsets: invalid index buffer"); + PX_CHECK_AND_RETURN(restOffsetBuffer.ptr(), "PxParticleBase::restOffsets: invalid restOffset buffer"); + + PX_CHECK_AND_RETURN(getScbParticleSystem().getFlags() & PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET, "PxParticleBase::setRestOffsets: PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET not set"); + +#if PX_CHECKED + PX_CHECK_AND_RETURN(checkAllocatedIndices(numParticles, indexBuffer), "PxParticleBase::setRestOffsets: failed"); + PX_CHECK_AND_RETURN(checkRestOffsets(numParticles, restOffsetBuffer, getScbParticleSystem().getRestOffset()), + "PxParticleBase::restOffsets: offsets must be in range [0.0f, restOffset]."); +#endif + getScbParticleSystem().setRestOffsets(numParticles, indexBuffer, restOffsetBuffer); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::addForces(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, + const PxStrideIterator<const PxVec3>& forceBuffer, PxForceMode::Enum forceMode) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + if (!getNpScene()) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, + "Attempt to add forces on particle system which isn't assigned to any scene."); + return; + } + + if (numParticles == 0) + return; + + PX_CHECK_AND_RETURN(indexBuffer.ptr() && indexBuffer.stride() != 0, "PxParticleBase::addForces: invalid index buffer"); + PX_CHECK_AND_RETURN(forceBuffer.ptr(), "PxParticleBase::addForces: invalid force buffer"); + +#if PX_CHECKED + PX_CHECK_AND_RETURN(checkAllocatedIndices(numParticles, indexBuffer), "PxParticleBase::addForces: failed"); + PX_CHECK_AND_RETURN(checkVectors(numParticles, forceBuffer), "PxParticleBase::addForces: force vectors shoule be finite"); +#endif + + getScbParticleSystem().addForces(numParticles, indexBuffer, forceBuffer, forceMode); +} + +template<class APIClass, class LeafClass> +PxParticleReadData* NpParticleBaseTemplate<APIClass, LeafClass>::lockParticleReadData(PxDataAccessFlags flags) +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().lockParticleReadData(flags); +} + +template<class APIClass, class LeafClass> +PxParticleReadData* NpParticleBaseTemplate<APIClass, LeafClass>::lockParticleReadData() +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().lockParticleReadData(PxDataAccessFlag::eREADABLE); +} + + +template<class APIClass, class LeafClass> +PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getDamping() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getDamping(); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setDamping(PxReal d) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(d >= 0.0f,"Damping is not allowed to be negative, PxParticleBase::setDamping() ignored."); + getScbParticleSystem().setDamping(d); +} + + +template<class APIClass, class LeafClass> +PxVec3 NpParticleBaseTemplate<APIClass, LeafClass>::getExternalAcceleration() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getExternalAcceleration(); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setExternalAcceleration(const PxVec3& a) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + getScbParticleSystem().setExternalAcceleration(a); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::getProjectionPlane(PxVec3& normal, PxReal& d) const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + PxPlane p = getScbParticleSystem().getProjectionPlane(); + normal = p.n; + d = p.d; +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setProjectionPlane(const PxVec3& normal, PxReal d) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(!normal.isZero(),"Plane normal needs to be non zero, PxParticleBase::setProjectionPlane() ignored."); + + PxPlane p(normal, d); + getScbParticleSystem().setProjectionPlane(p); +} + + +template<class APIClass, class LeafClass> +PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getParticleMass() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getParticleMass(); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setParticleMass(PxReal m) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(m > 0.0f, "ParticleMass needs to be positive, PxParticleBase::setParticleMass() ignored."); + getScbParticleSystem().setParticleMass(m); +} + + +template<class APIClass, class LeafClass> +PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getRestitution() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getRestitution(); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setRestitution(PxReal r) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(r >= 0.0f && r <= 1.0f,"Restitution needs to be in [0,1], PxParticleBase::setRestitution() ignored."); + getScbParticleSystem().setRestitution(r); +} + + +template<class APIClass, class LeafClass> +PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getDynamicFriction() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getDynamicFriction(); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setDynamicFriction(PxReal a) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(a >= 0.0f && a <= 1.0f,"Dynamic Friction needs to be in [0,1], PxParticleBase::setDynamicFriction() ignored."); + getScbParticleSystem().setDynamicFriction(a); +} + + +template<class APIClass, class LeafClass> +PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getStaticFriction() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getStaticFriction(); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setStaticFriction(PxReal a) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(a >= 0.0f,"Static Friction needs to be positive, PxParticleBase::setStaticFriction() ignored."); + getScbParticleSystem().setStaticFriction(a); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setSimulationFilterData(const PxFilterData& data) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + getScbParticleSystem().setSimulationFilterData(data); +} + + +template<class APIClass, class LeafClass> +PxFilterData NpParticleBaseTemplate<APIClass, LeafClass>::getSimulationFilterData() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getSimulationFilterData(); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::resetFiltering() +{ + physx::shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_INFO, __FILE__, __LINE__, "PxParticleBase::resetFiltering: This method has been deprecated!"); + + NpScene* scene = NpActor::getOwnerScene(*this); + if (scene) + scene->resetFiltering(*this); +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setParticleBaseFlag(PxParticleBaseFlag::Enum flag, bool value) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + // flags that are generally immutable + if (flag == PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET flag is not modifiable. Operation ignored."); + return; + } + + PxParticleBaseFlags flags = getScbParticleSystem().getFlags(); + if(value) + flags |= flag; + else + flags &= ~flag; + + getScbParticleSystem().setFlags(flags); + + if (getNpScene()) + getNpScene()->updatePhysXIndicator(); +} + + +template<class APIClass, class LeafClass> +PxParticleBaseFlags NpParticleBaseTemplate<APIClass, LeafClass>::getParticleBaseFlags() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getFlags(); +} + +template<class APIClass, class LeafClass> +PxParticleReadDataFlags NpParticleBaseTemplate<APIClass, LeafClass>::getParticleReadDataFlags() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getParticleReadDataFlags(); +} + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setParticleReadDataFlag(PxParticleReadDataFlag::Enum flag, bool value) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"PxParticleReadDataFlag immutable when the particle system is part of a scene."); + PxParticleReadDataFlags flags = getScbParticleSystem().getParticleReadDataFlags(); + + PX_CHECK_AND_RETURN(!(flag == PxParticleReadDataFlag::eREST_OFFSET_BUFFER && value) + || (getScbParticleSystem().getFlags() & PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET), + "PxParticleReadDataFlag::eREST_OFFSET_BUFFER not supported without specifying per particle rest offsets on calling " + "PxPhysics::createParticleSystem or PxPhysics::createParticleFluid."); + + if(value) + flags |= flag; + else + flags &= ~flag; + + getScbParticleSystem().setParticleReadDataFlags(flags); +} + +template<class APIClass, class LeafClass> +PxU32 NpParticleBaseTemplate<APIClass, LeafClass>::getMaxParticles() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getMaxParticles(); +} + + +template<class APIClass, class LeafClass> +PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getMaxMotionDistance() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getMaxMotionDistance(); +} + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setMaxMotionDistance(PxReal d) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(d >= 0.0f,"MaxMotionDistance needs to be positive, PxParticleBase::setMaxMotionDistance() ignored."); + PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"MaxMotionDistance immutable when the particle system is part of a scene."); + getScbParticleSystem().setMaxMotionDistance(d); +} + +template<class APIClass, class LeafClass> +PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getRestOffset() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getRestOffset(); +} + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setRestOffset(PxReal r) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(r >= 0.0f,"RestOffset needs to be positive, PxParticleBase::setRestOffset() ignored."); + PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"RestOffset immutable when the particle system is part of a scene."); +#if PX_CHECKED + if(getParticleBaseFlags() & PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET) + { + Pt::ParticleData* standaloneData = getScbParticleSystem().getScParticleSystem().obtainStandaloneData(); + PX_ASSERT(standaloneData); + bool pass = checkRestOffset(*standaloneData, r); + getScbParticleSystem().getScParticleSystem().returnStandaloneData(standaloneData); + PX_CHECK_AND_RETURN(pass, "PxParticleBase::restOffset: offset must be larger than each perParticle restOffset."); + } +#endif + getScbParticleSystem().setRestOffset(r); +} + +template<class APIClass, class LeafClass> +PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getContactOffset() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getContactOffset(); +} + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setContactOffset(PxReal c) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(c >= 0.0f,"ContactOffset needs to be positive, PxParticleBase::setContactOffset() ignored."); + PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"ContactOffset immutable when the particle system is part of a scene."); + getScbParticleSystem().setContactOffset(c); +} + +template<class APIClass, class LeafClass> +PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getGridSize() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + return getScbParticleSystem().getGridSize(); +} + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setGridSize(PxReal g) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + PX_CHECK_AND_RETURN(g >= 0.0f,"GridSize needs to be positive, PxParticleBase::setGridSize() ignored."); + PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"GridSize immutable when the particle system is part of a scene."); + getScbParticleSystem().setGridSize(g); +} + +template<class APIClass, class LeafClass> +PxBounds3 NpParticleBaseTemplate<APIClass, LeafClass>::getWorldBounds(float inflation) const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + const PxBounds3 bounds = getScbParticleSystem().getWorldBounds(); + PX_ASSERT(bounds.isValid()); + + // PT: unfortunately we can't just scale the min/max vectors, we need to go through center/extents. + const PxVec3 center = bounds.getCenter(); + const PxVec3 inflatedExtents = bounds.getExtents() * inflation; + return PxBounds3::centerExtents(center, inflatedExtents); +} + + +#if PX_SUPPORT_GPU_PHYSX + +template<class APIClass, class LeafClass> +PxParticleDeviceExclusiveAccess* NpParticleBaseTemplate<APIClass, LeafClass>::getDeviceExclusiveAccessGpu(const char* callerName) const +{ + PxParticleDeviceExclusiveAccess* access = NULL; + if (getNpScene() && (getParticleBaseFlags() & PxParticleBaseFlag::eGPU)) + { + access = getScbParticleSystem().getDeviceExclusiveAccessGpu(); + } + + if (!access) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, + "%s is only allowed to be called if the particle system is in device exclusive mode. " + "Please refer to PxParticleDeviceExclusive::enable and PxParticleDeviceExclusive::isEnabled.", callerName); + } + + return access; +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::enableDeviceExclusiveModeGpu() +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + if (!getNpScene()) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxParticleDeviceExclusive::enable is not allowed to be called if the particle system is not in a scene."); + return; + } + + if (!(getParticleBaseFlags() & PxParticleBaseFlag::eGPU)) + { + Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxParticleDeviceExclusive::enable is not allowed for non PxParticleBaseFlag::eGPU particle systems."); + return; + } + + getScbParticleSystem().enableDeviceExclusiveModeGpu(); +} + + +template<class APIClass, class LeafClass> +bool NpParticleBaseTemplate<APIClass, LeafClass>::isDeviceExclusiveModeEnabledGpu() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + if (!getNpScene() || !(getParticleBaseFlags() & PxParticleBaseFlag::eGPU)) + { + return false; + } + + return getScbParticleSystem().getDeviceExclusiveAccessGpu() != NULL; +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::getReadWriteCudaBuffersGpu(PxCudaReadWriteParticleBuffers& buffers) const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::getReadWriteCudaBuffers"); + if (access) + { + access->getReadWriteCudaBuffers(buffers); + } +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setValidParticleRangeGpu(PxU32 validParticleRange) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::setValidParticleRange"); + if (access) + { + access->setValidParticleRange(validParticleRange); + } +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::setDeviceExclusiveModeFlagsGpu(PxU32 flags) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::setFlags"); + if (access) + { + access->setFlags(flags); + } +} + + +template<class APIClass, class LeafClass> +physx::PxBaseTask* NpParticleBaseTemplate<APIClass, LeafClass>::getLaunchTaskGpu() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::getLaunchTask"); + if (access) + { + return access->getLaunchTask(); + } + return NULL; +} + + +template<class APIClass, class LeafClass> +void NpParticleBaseTemplate<APIClass, LeafClass>::addLaunchTaskDependentGpu(class physx::PxBaseTask& dependent) +{ + NP_WRITE_CHECK(NpActor::getOwnerScene(*this)); + + PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::addLaunchTaskDependent"); + if (access) + { + access->addLaunchTaskDependent(dependent); + } +} + + +template<class APIClass, class LeafClass> +size_t NpParticleBaseTemplate<APIClass, LeafClass>::getCudaStreamGpu() const +{ + NP_READ_CHECK(NpActor::getOwnerScene(*this)); + + PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::getCudaStream"); + if (access) + { + return access->getCudaStream(); + } + return 0; +} + + +#endif +} + +#endif // PX_USE_PARTICLE_SYSTEM_API + +#endif |