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/SimulationController/src/particles | |
| 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/SimulationController/src/particles')
7 files changed, 2328 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/SimulationController/src/particles/ScParticleBodyInteraction.cpp b/PhysX_3.4/Source/SimulationController/src/particles/ScParticleBodyInteraction.cpp new file mode 100644 index 00000000..fc8e6723 --- /dev/null +++ b/PhysX_3.4/Source/SimulationController/src/particles/ScParticleBodyInteraction.cpp @@ -0,0 +1,112 @@ +// 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 "ScParticleBodyInteraction.h" +#if PX_USE_PARTICLE_SYSTEM_API + +#include "ScParticleSystemSim.h" +#include "ScScene.h" +#include "PxsContext.h" +#include "ScParticleSystemCore.h" +#include "ScBodySim.h" +#include "ScNPhaseCore.h" + +using namespace physx; + + +Sc::ParticleElementRbElementInteraction::ParticleElementRbElementInteraction(ParticlePacketShape &particleShape, ShapeSim& rbShape, ActorElementPair& actorElementPair, const PxU32 ccdPass) : + ElementSimInteraction (particleShape, rbShape, InteractionType::ePARTICLE_BODY, InteractionFlag::eFILTERABLE | InteractionFlag::eELEMENT_ELEMENT), + mActorElementPair (actorElementPair), + mPacketShapeIndex (PX_INVALID_PACKET_SHAPE_INDEX), + mIsActiveForLowLevel (false) +{ + registerInActors(); + + getScene().getNPhaseCore()->registerInteraction(this); + + mPacketShapeIndex = getParticleShape().addPacketShapeInteraction(this); + + if (!isDisabled()) + activateForLowLevel(ccdPass); // Collision with rigid body +} + + +Sc::ParticleElementRbElementInteraction::~ParticleElementRbElementInteraction() +{ + unregisterFromActors(); + getScene().getNPhaseCore()->unregisterInteraction(this); +} + + +void Sc::ParticleElementRbElementInteraction::destroy(bool isDyingRb, const PxU32 ccdPass) +{ + ParticlePacketShape& ps = getParticleShape(); + + if (mIsActiveForLowLevel) + deactivateForLowLevel(isDyingRb, ccdPass); + + const PxU16 idx = mPacketShapeIndex; + ps.removePacketShapeInteraction(idx); + if (idx < ps.getInteractionsCount()) + ps.getPacketShapeInteraction(idx)->setPacketShapeIndex(idx); + mPacketShapeIndex = PX_INVALID_PACKET_SHAPE_INDEX; +} + + +bool Sc::ParticleElementRbElementInteraction::onActivate(void*) +{ + return false; +} + + +bool Sc::ParticleElementRbElementInteraction::onDeactivate(PxU32) +{ + return true; +} + + +void Sc::ParticleElementRbElementInteraction::activateForLowLevel(const PxU32 ccdPass) +{ + //update active cm count and update transform hash/mirroring + getParticleShape().getParticleSystem().addInteraction(getParticleShape(), getRbShape(), ccdPass); + mIsActiveForLowLevel = true; +} + + +void Sc::ParticleElementRbElementInteraction::deactivateForLowLevel(bool isDyingRb, const PxU32 ccdPass) +{ + //update active cm count and update transform hash/mirroring + getParticleShape().getParticleSystem().removeInteraction(getParticleShape(), getRbShape(), isDyingRb, ccdPass); + mIsActiveForLowLevel = false; +} + + + +#endif // PX_USE_PARTICLE_SYSTEM_API diff --git a/PhysX_3.4/Source/SimulationController/src/particles/ScParticleBodyInteraction.h b/PhysX_3.4/Source/SimulationController/src/particles/ScParticleBodyInteraction.h new file mode 100644 index 00000000..78738d02 --- /dev/null +++ b/PhysX_3.4/Source/SimulationController/src/particles/ScParticleBodyInteraction.h @@ -0,0 +1,152 @@ +// 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_SCP_PARTICLEBODYINTERACTION +#define PX_PHYSICS_SCP_PARTICLEBODYINTERACTION + +#include "CmPhysXCommon.h" +#include "PxPhysXConfig.h" +#if PX_USE_PARTICLE_SYSTEM_API + +#include "ScElementSimInteraction.h" +#include "ScActorElementPair.h" +#include "ScParticlePacketShape.h" +#include "ScShapeSim.h" + + +#define PX_INVALID_PACKET_SHAPE_INDEX 0xffff + + +namespace physx +{ +namespace Sc +{ + + class ParticleElementRbElementInteraction : public ElementSimInteraction + { + public: + + // The ccdPass parameter is needed to avoid concurrent interaction updates while the gpu particle pipeline is running. + ParticleElementRbElementInteraction(ParticlePacketShape &particleShape, ShapeSim& rbShape, ActorElementPair& actorElementPair, const PxU32 ccdPass); + virtual ~ParticleElementRbElementInteraction(); + PX_INLINE void* operator new(size_t s, void* memory); + + void destroy(bool isDyingRb, const PxU32 ccdPass); + + //---------- Interaction ---------- + protected: + virtual bool onActivate(void*); + virtual bool onDeactivate(PxU32 infoFlag); + //----------------------------------- + + public: + //----- ElementSimInteraction ------ + virtual bool isLastFilterInteraction() const { return (mActorElementPair.getRefCount() == 1); } + //---------------------------------- + + PX_INLINE ParticlePacketShape& getParticleShape() const; + PX_INLINE ShapeSim& getRbShape() const; + + PX_INLINE void onRbShapeChange(); + + PX_FORCE_INLINE ActorElementPair* getActorElementPair() const { return &mActorElementPair; } + PX_FORCE_INLINE bool isDisabled() const { return (getActorElementPair()->isSuppressed() || isRbTrigger()); } + + PX_INLINE void setPacketShapeIndex(PxU16 idx); + + PX_INLINE void checkLowLevelActivationState(); + + private: + ParticleElementRbElementInteraction& operator=(const ParticleElementRbElementInteraction&); + void activateForLowLevel(const PxU32 ccdPass); + void deactivateForLowLevel(bool isDyingRb, const PxU32 ccdPass); + static void operator delete(void*) {} + + PX_FORCE_INLINE PxU32 isRbTrigger() const { return (getRbShape().getFlags() & PxShapeFlag::eTRIGGER_SHAPE); } + + + ActorElementPair& mActorElementPair; + PxU16 mPacketShapeIndex; + bool mIsActiveForLowLevel; + }; + +} // namespace Sc + +PX_INLINE void* Sc::ParticleElementRbElementInteraction::operator new(size_t, void* memory) +{ + return memory; +} + + +PX_INLINE Sc::ParticlePacketShape& Sc::ParticleElementRbElementInteraction::getParticleShape() const +{ + PX_ASSERT(getElement0().getElementType() == ElementType::ePARTICLE_PACKET); + return static_cast<ParticlePacketShape&>(getElement0()); +} + + +PX_INLINE Sc::ShapeSim& Sc::ParticleElementRbElementInteraction::getRbShape() const +{ + PX_ASSERT(getElement1().getElementType() == ElementType::eSHAPE); + PX_ASSERT(static_cast<ShapeSim&>(getElement1()).getActor().isDynamicRigid() || (static_cast<ShapeSim&>(getElement1()).getActor().getActorType() == PxActorType::eRIGID_STATIC)); + return static_cast<ShapeSim&>(getElement1()); +} + +PX_INLINE void Sc::ParticleElementRbElementInteraction::checkLowLevelActivationState() +{ + if (!isDisabled() && !mIsActiveForLowLevel) + { + // The interaction is now valid --> Create low level contact manager + activateForLowLevel(false); + } + else if (isDisabled() && mIsActiveForLowLevel) + { + // The interaction is not valid anymore --> Release low level contact manager + deactivateForLowLevel(false, false); + } +} + +PX_INLINE void Sc::ParticleElementRbElementInteraction::onRbShapeChange() +{ + getParticleShape().getParticleSystem().onRbShapeChange(getParticleShape(), getRbShape()); +} + +PX_INLINE void Sc::ParticleElementRbElementInteraction::setPacketShapeIndex(PxU16 idx) +{ + PX_ASSERT(idx != PX_INVALID_PACKET_SHAPE_INDEX); + mPacketShapeIndex = idx; +} + + +} + +#endif // PX_USE_PARTICLE_SYSTEM_API + +#endif diff --git a/PhysX_3.4/Source/SimulationController/src/particles/ScParticlePacketShape.cpp b/PhysX_3.4/Source/SimulationController/src/particles/ScParticlePacketShape.cpp new file mode 100644 index 00000000..8dd86f0a --- /dev/null +++ b/PhysX_3.4/Source/SimulationController/src/particles/ScParticlePacketShape.cpp @@ -0,0 +1,191 @@ +// 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 "ScParticlePacketShape.h" +#if PX_USE_PARTICLE_SYSTEM_API + +#include "ScParticleBodyInteraction.h" +#include "ScNPhaseCore.h" +#include "ScScene.h" +#include "PtParticleSystemSim.h" +#include "ScParticleSystemCore.h" +#include "ScSimStats.h" +#include "ScSqBoundsManager.h" +#include "ScScene.h" +#include "PxsContext.h" + +using namespace physx; + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +Sc::ParticlePacketShape::ParticlePacketShape(ParticleSystemSim& particleSystem, PxU32 index, Pt::ParticleShape* llParticleShape) : + ElementSim(particleSystem, ElementType::ePARTICLE_PACKET), + mLLParticleShape(llParticleShape) +{ + // Initialize LL shape. + PX_ASSERT(mLLParticleShape); + mLLParticleShape->setUserDataV(this); + + setIndex(index); + + // Add particle actor element to broadphase + createLowLevelVolume(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +Sc::ParticlePacketShape::~ParticlePacketShape() +{ + getParticleSystem().unlinkParticleShape(this); // Let the particle system remove this shape from the list. + + // Remove particle actor element from broadphase and cleanup interactions + destroyLowLevelVolume(); + + // Destroy LowLevel shape + if (mLLParticleShape) + { + mLLParticleShape->destroyV(); + mLLParticleShape = 0; + } + + PX_ASSERT(mInteractions.size()==0); + mInteractions.releaseMem(*this); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Sc::ParticlePacketShape::computeWorldBounds(PxBounds3& b) const +{ + b = getBounds(); + PX_ASSERT(b.isFinite()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Sc::ParticlePacketShape::getFilterInfo(PxFilterObjectAttributes& filterAttr, PxFilterData& filterData) const +{ + filterAttr = 0; + if (getParticleSystem().getInternalFlags() & Pt::InternalParticleSystemFlag::eSPH) + ElementSim::setFilterObjectAttributeType(filterAttr, PxFilterObjectType::ePARTICLE_FLUID); + else + ElementSim::setFilterObjectAttributeType(filterAttr, PxFilterObjectType::ePARTICLE_SYSTEM); + + filterData = getParticleSystem().getSimulationFilterData(); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +Sc::ParticleSystemSim& Sc::ParticlePacketShape::getParticleSystem() const +{ + return static_cast<ParticleSystemSim&>(getActor()); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Sc::ParticlePacketShape::setInteractionsDirty(InteractionDirtyFlag::Enum flag) +{ + ParticleElementRbElementInteraction** interactions = getInteractions(); + PxU32 nbInteractions = getInteractionsCount(); + + while(nbInteractions--) + { + ParticleElementRbElementInteraction* interaction = *interactions++; + + PX_ASSERT(interaction->readInteractionFlag(InteractionFlag::eFILTERABLE)); + PX_ASSERT(interaction->readInteractionFlag(InteractionFlag::eELEMENT_ELEMENT)); + + interaction->setDirty(flag); + } +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +// PT: TODO: refactor with Sc::ActorSim::reallocInteractions +void Sc::ParticlePacketShape::reallocInteractions(Sc::ParticleElementRbElementInteraction**& mem, PxU16& capacity, PxU16 size, PxU16 requiredMinCapacity) +{ + ParticleElementRbElementInteraction** newMem; + PxU16 newCapacity; + + if(requiredMinCapacity==0) + { + newCapacity = 0; + newMem = 0; + } + else if(requiredMinCapacity<=INLINE_INTERACTION_CAPACITY) + { + newCapacity = INLINE_INTERACTION_CAPACITY; + newMem = mInlineInteractionMem; + } + else + { + const PxU32 desiredCapacity = Ps::nextPowerOfTwo(PxU32(requiredMinCapacity-1)); + PX_ASSERT(desiredCapacity<=65536); + + const PxU32 limit = 0xffff; + newCapacity = Ps::to16(PxMin(limit, desiredCapacity)); + newMem = reinterpret_cast<ParticleElementRbElementInteraction**>(getScene().allocatePointerBlock(newCapacity)); + } + + PX_ASSERT(newCapacity >= requiredMinCapacity && requiredMinCapacity>=size); + + PxMemCopy(newMem, mem, size*sizeof(ParticleElementRbElementInteraction*)); + + if(mem && mem!=mInlineInteractionMem) + getScene().deallocatePointerBlock(reinterpret_cast<void**>(mem), capacity); + + capacity = newCapacity; + mem = newMem; +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Sc::ParticlePacketShape::createLowLevelVolume() +{ + PX_ASSERT(getBounds().isFinite()); + + getScene().getBoundsArray().setBounds(getBounds(), getElementID()); + addToAABBMgr(0, Bp::FilterGroup::ePARTICLES, false); +} + +/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// + +void Sc::ParticlePacketShape::destroyLowLevelVolume() +{ + if (!isInBroadPhase()) + return; + + Sc::Scene& scene = getScene(); + PxsContactManagerOutputIterator outputs = scene.getLowLevelContext()->getNphaseImplementationContext()->getContactManagerOutputs(); + + scene.getNPhaseCore()->onVolumeRemoved(this, 0, outputs, scene.getPublicFlags() & PxSceneFlag::eADAPTIVE_FORCE); + removeFromAABBMgr(); +} + +#endif // PX_USE_PARTICLE_SYSTEM_API diff --git a/PhysX_3.4/Source/SimulationController/src/particles/ScParticlePacketShape.h b/PhysX_3.4/Source/SimulationController/src/particles/ScParticlePacketShape.h new file mode 100644 index 00000000..a212d649 --- /dev/null +++ b/PhysX_3.4/Source/SimulationController/src/particles/ScParticlePacketShape.h @@ -0,0 +1,126 @@ +// 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_PARTICLESHAPE +#define PX_PHYSICS_PARTICLESHAPE + +#include "CmPhysXCommon.h" +#include "PxPhysXConfig.h" +#if PX_USE_PARTICLE_SYSTEM_API + +#include "ScElementSim.h" +#include "ScParticleSystemSim.h" +#include "PtParticleShape.h" + +namespace physx +{ +namespace Sc +{ + class ParticleElementRbElementInteraction; + + + /** + A collision detection primitive for particle systems. + */ + class ParticlePacketShape : public ElementSim + { + public: + ParticlePacketShape(ParticleSystemSim& particleSystem, PxU32 uid, Pt::ParticleShape* llParticleShape); + ~ParticlePacketShape(); + + // ElementSim implementation + virtual void getFilterInfo(PxFilterObjectAttributes& filterAttr, PxFilterData& filterData) const; + // ~ElementSim + + virtual void createLowLevelVolume(); + virtual void destroyLowLevelVolume(); + + public: + void setIndex(PxU32 index) { PX_ASSERT(index < ((1 << 16) - 1)); mIndex = static_cast<PxU16>(index); } + PX_FORCE_INLINE PxU16 getIndex() const { return mIndex; } + + PX_FORCE_INLINE PxBounds3 getBounds() const { return mLLParticleShape->getBoundsV(); } + + class ParticleSystemSim& getParticleSystem() const; + + void computeWorldBounds(PxBounds3&) const; + + PX_FORCE_INLINE ParticleElementRbElementInteraction** getInteractions() const { return mInteractions.begin(); } + PX_FORCE_INLINE PxU32 getInteractionsCount() const { return mInteractions.size(); } + + PX_FORCE_INLINE Pt::ParticleShape* getLowLevelParticleShape() const { return mLLParticleShape; } + + void setInteractionsDirty(InteractionDirtyFlag::Enum flag); + + PX_INLINE PxU16 addPacketShapeInteraction(ParticleElementRbElementInteraction* interaction); + PX_INLINE void removePacketShapeInteraction(PxU16 id); + PX_INLINE ParticleElementRbElementInteraction* getPacketShapeInteraction(PxU16 id) const; + + private: + void reallocInteractions(ParticleElementRbElementInteraction**& mem, PxU16& capacity, PxU16 size, PxU16 requiredMinCapacity); + + + static const PxU32 INLINE_INTERACTION_CAPACITY = 4; + ParticleElementRbElementInteraction* mInlineInteractionMem[INLINE_INTERACTION_CAPACITY]; + + Cm::OwnedArray<ParticleElementRbElementInteraction*, ParticlePacketShape, PxU16, &ParticlePacketShape::reallocInteractions> + mInteractions; + + Pt::ParticleShape* mLLParticleShape; // Low level handle of particle packet + PxU16 mIndex; + }; + +} // namespace Sc + + +//These are called from interaction creation/destruction +PX_INLINE PxU16 Sc::ParticlePacketShape::addPacketShapeInteraction(ParticleElementRbElementInteraction* interaction) +{ + mInteractions.pushBack(interaction, *this); + return PxU16(mInteractions.size()-1); +} + +PX_INLINE void Sc::ParticlePacketShape::removePacketShapeInteraction(PxU16 id) +{ + mInteractions.replaceWithLast(id); +} + +PX_INLINE Sc::ParticleElementRbElementInteraction* Sc::ParticlePacketShape::getPacketShapeInteraction(PxU16 id) const +{ + PX_ASSERT(id<mInteractions.size()); + return mInteractions[id]; +} + + +} + +#endif // PX_USE_PARTICLE_SYSTEM_API + +#endif diff --git a/PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemCore.cpp b/PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemCore.cpp new file mode 100644 index 00000000..e7e18e3b --- /dev/null +++ b/PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemCore.cpp @@ -0,0 +1,705 @@ +// 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 "ScParticleSystemCore.h" +#if PX_USE_PARTICLE_SYSTEM_API + +#include "ScParticleSystemSim.h" +#include "ScPhysics.h" + +#include "PsBitUtils.h" +#include "PsMathUtils.h" + +#include "PxParticleReadData.h" +#include "PtParticleData.h" + +using namespace physx; + +//----------------------------------------------------------------------------// + +#if PX_SUPPORT_GPU_PHYSX +namespace physx +{ + struct PxCudaReadWriteParticleBuffers; +} +#endif + +//----------------------------------------------------------------------------// + +PxU32 computePacketSizeMultLog2(PxReal packetSize, PxReal cellSize) +{ + PX_FPU_GUARD; // unknown osx issue with ceil function (throwing fp exception), printf makes it go away. + const PxU32 mult = PxU32(Ps::ceil(packetSize / cellSize)); + PxU32 multPow2 = Ps::nextPowerOfTwo(mult-1); + multPow2 = PxMax(PxU32(4), multPow2); + return Ps::ilog2(multPow2); +} + +//----------------------------------------------------------------------------// + +Sc::ParticleSystemCore::ParticleSystemCore(const PxActorType::Enum& actorType, PxU32 maxParticles, bool perParticleRestOffset) : + ActorCore(actorType, PxActorFlag::eVISUALIZATION, PX_DEFAULT_CLIENT, 0, 0), + mStandaloneData(0), + mParticleMass(0.001f) +{ + // set simulation parameters + mSimulationFilterData.setToDefault(); + setExternalAcceleration(PxVec3(0)); + + mLLParameter.particleReadDataFlags = PxParticleReadDataFlag::ePOSITION_BUFFER | PxParticleReadDataFlag::eFLAGS_BUFFER;//desc.particleReadDataFlags; + mLLParameter.flags = PxParticleBaseFlag::eENABLED | + PxParticleBaseFlag::eCOLLISION_WITH_DYNAMIC_ACTORS | + PxParticleBaseFlag::ePER_PARTICLE_COLLISION_CACHE_HINT; + if(perParticleRestOffset) + mLLParameter.flags |= PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET; + + bool isFluid = actorType != PxActorType::ePARTICLE_SYSTEM; + + if (isFluid) + { + PX_ASSERT(actorType == PxActorType::ePARTICLE_FLUID); + + mLLParameter.flags |= Pt::InternalParticleSystemFlag::eSPH; + mLLParameter.restParticleDistance = 0.02f; + mLLParameter.kernelRadiusMultiplier = SPH_KERNEL_RADIUS_MULT; + mLLParameter.packetSizeMultiplierLog2 = computePacketSizeMultLog2(0.6f/*gridSize*/, mLLParameter.restParticleDistance*SPH_KERNEL_RADIUS_MULT); + mLLParameter.stiffness = 20.0f; + mLLParameter.viscosity = 6.0f; + mLLParameter.restDensity = SPH_REST_DENSITY; + } + else + { + mLLParameter.restParticleDistance = 0.06f; + mLLParameter.kernelRadiusMultiplier = 1.0f; + mLLParameter.packetSizeMultiplierLog2 = computePacketSizeMultLog2(0.6f/*gridSize*/, mLLParameter.restParticleDistance); + mLLParameter.stiffness = 0.0f; + mLLParameter.viscosity = 0.0f; + mLLParameter.restDensity = 0.0f; + } + + mLLParameter.maxMotionDistance = 0.06f; + mLLParameter.restOffset = 0.004f; + mLLParameter.contactOffset = 0.008f; + mLLParameter.damping = 0.0f; + mLLParameter.noiseCounter = 0; + + // Simon: This is a bit hacky. We should have better support for non sph in LL + mLLParameter.restitution = 0.5f; + mLLParameter.dynamicFriction = 0.05f; + mLLParameter.staticFriction = 0.0f; + + mLLParameter.projectionPlane = PxPlane(PxVec3(0.0f, 0.0f, 1.0f), 0.0f); + + // Create the low level standalone core + maxParticles = PxMin(maxParticles, MAX_PARTICLES_PER_PARTICLE_SYSTEM); + mStandaloneData = Pt::ParticleData::create(maxParticles, perParticleRestOffset); + if(perParticleRestOffset) + { + PxF32* restOffsetBuf = mStandaloneData->getRestOffsetBuffer(); + for(PxU32 i = 0; i < maxParticles; i++) + *restOffsetBuf++ = 0.f; + } +} + +//----------------------------------------------------------------------------// + +Sc::ParticleSystemCore::~ParticleSystemCore() +{ + PX_ASSERT(getSim() == NULL); + + if (mStandaloneData) + mStandaloneData->release(); +} + +//----------------------------------------------------------------------------// + +// PX_SERIALIZATION +void Sc::ParticleSystemCore::exportExtraData(PxSerializationContext& stream) +{ + if (mStandaloneData) + { + mStandaloneData->exportData(stream); + } + else + { + //sschirm, this could be made faster and more memory friendly for non-gpu fluids. do we care? + //if so, we would need to push this functionality into lowlevel and write platform dependent code. + //for faster gpu export, we would need to push the export into the gpu dll. + Pt::ParticleSystemStateDataDesc particles; + getParticleState().getParticlesV(particles, true, false); + Pt::ParticleData* tmp = Pt::ParticleData::create(particles, getParticleState().getWorldBoundsV()); + tmp->exportData(stream); + tmp->release(); + } +} + +void Sc::ParticleSystemCore::importExtraData(PxDeserializationContext& context) +{ + PX_ASSERT(!getSim()); + mStandaloneData = Pt::ParticleData::create(context); +} +//~PX_SERIALIZATION + +//----------------------------------------------------------------------------// + +Sc::ParticleSystemSim* Sc::ParticleSystemCore::getSim() const +{ + return static_cast<ParticleSystemSim*>(Sc::ActorCore::getSim()); +} + +//----------------------------------------------------------------------------// + +Pt::ParticleSystemState& Sc::ParticleSystemCore::getParticleState() +{ + return getSim() ? getSim()->getParticleState() : *mStandaloneData; +} + +//----------------------------------------------------------------------------// + +const Pt::ParticleSystemState& Sc::ParticleSystemCore::getParticleState() const +{ + return getSim() ? getSim()->getParticleState() : *mStandaloneData; +} + +//----------------------------------------------------------------------------// + +Pt::ParticleData* Sc::ParticleSystemCore::obtainStandaloneData() +{ + PX_ASSERT(mStandaloneData); + Pt::ParticleData* tmp = mStandaloneData; + mStandaloneData = NULL; + return tmp; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::returnStandaloneData(Pt::ParticleData* particleData) +{ + PX_ASSERT(particleData && !mStandaloneData); + mStandaloneData = particleData; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::onOriginShift(const PxVec3& shift) +{ + // hard to come up with a use case for this but we do it for the sake of consistency + PxReal delta = mLLParameter.projectionPlane.n.dot(shift); + mLLParameter.projectionPlane.d += delta; + + PX_ASSERT(mStandaloneData); + mStandaloneData->onOriginShift(shift); +} + +//----------------------------------------------------------------------------// + +PxParticleBase* Sc::ParticleSystemCore::getPxParticleBase() +{ + if (getActorCoreType() == PxActorType::ePARTICLE_SYSTEM) + return gOffsetTable.convertScParticleSystem2Px(this); + else + return gOffsetTable.convertScParticleSystem2PxParticleFluid(this); +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getStiffness() const +{ + return mLLParameter.stiffness; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setStiffness(PxReal t) +{ + mLLParameter.stiffness = t; +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getViscosity() const +{ + return mLLParameter.viscosity; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setViscosity(PxReal t) +{ + mLLParameter.viscosity = t; +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getDamping() const +{ + return mLLParameter.damping; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setDamping(PxReal t) +{ + mLLParameter.damping = t; +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getParticleMass() const +{ + return mParticleMass; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setParticleMass(PxReal mass) +{ + mParticleMass = mass; +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getRestitution() const +{ + return mLLParameter.restitution; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setRestitution(PxReal t) +{ + mLLParameter.restitution = t; +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getDynamicFriction() const +{ + return mLLParameter.dynamicFriction; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setDynamicFriction(PxReal t) +{ + mLLParameter.dynamicFriction = t; +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getStaticFriction() const +{ + return mLLParameter.staticFriction; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setStaticFriction(PxReal t) +{ + mLLParameter.staticFriction = t; +} + +//----------------------------------------------------------------------------// + +const PxFilterData& Sc::ParticleSystemCore::getSimulationFilterData() const +{ + return mSimulationFilterData; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setSimulationFilterData(const PxFilterData& data) +{ + mSimulationFilterData = data; + + if (getSim()) + getSim()->scheduleRefiltering(); + // If no sim object then we have no particle packets anyway and nothing to worry about +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::resetFiltering() +{ + if (getSim()) + getSim()->resetFiltering(); + // If no sim object then we have no particle packets anyway and nothing to worry about +} + +//----------------------------------------------------------------------------// + +PxParticleBaseFlags Sc::ParticleSystemCore::getFlags() const +{ + return PxParticleBaseFlags(PxU16(mLLParameter.flags)); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setFlags(PxParticleBaseFlags flags) +{ + if (getSim()) + { + // flags that are immutable while in scene + PxParticleBaseFlags sceneImmutableFlags = + PxParticleBaseFlag::eGPU | + PxParticleBaseFlag::eCOLLISION_TWOWAY | + PxParticleBaseFlag::eCOLLISION_WITH_DYNAMIC_ACTORS | + PxParticleBaseFlag::ePER_PARTICLE_COLLISION_CACHE_HINT; + + if (flags & sceneImmutableFlags) + { + Sc::Scene* scene = &getSim()->getScene(); + scene->removeParticleSystem(*this, false); + setInternalFlags(flags); + scene->addParticleSystem(*this); + } + else + { + setInternalFlags(flags); + } + getSim()->setFlags(flags); + } + else + { + setInternalFlags(flags); + } +} + +//----------------------------------------------------------------------------// + +PxU32 Sc::ParticleSystemCore::getInternalFlags() const +{ + return mLLParameter.flags; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setInternalFlags(PxParticleBaseFlags flags) +{ + mLLParameter.flags = (mLLParameter.flags & 0xffff0000) | PxU32(flags); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::notifyCpuFallback() +{ + setInternalFlags(getFlags() & ~PxParticleBaseFlag::eGPU); +} + +//----------------------------------------------------------------------------// + +PxParticleReadDataFlags Sc::ParticleSystemCore::getParticleReadDataFlags() const +{ + return mLLParameter.particleReadDataFlags; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setParticleReadDataFlags(PxParticleReadDataFlags flags) +{ + mLLParameter.particleReadDataFlags = flags; +} + +//----------------------------------------------------------------------------// + +PxU32 Sc::ParticleSystemCore::getMaxParticles() const +{ + return getParticleState().getMaxParticlesV(); +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getMaxMotionDistance() const +{ + return mLLParameter.maxMotionDistance; +} + +//---------------------------------------------------------------------------// +void Sc::ParticleSystemCore::setMaxMotionDistance(PxReal distance) +{ + PX_ASSERT(!getSim()); + mLLParameter.maxMotionDistance = distance; +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getRestOffset() const +{ + return mLLParameter.restOffset; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setRestOffset(PxReal restOffset) +{ + PX_ASSERT(!getSim()); + mLLParameter.restOffset = restOffset; +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getContactOffset() const +{ + return mLLParameter.contactOffset; +} + +//---------------------------------------------------------------------------// +void Sc::ParticleSystemCore::setContactOffset(PxReal contactOffset) +{ + PX_ASSERT(!getSim()); + mLLParameter.contactOffset = contactOffset; +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getRestParticleDistance() const +{ + return mLLParameter.restParticleDistance; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setRestParticleDistance(PxReal restParticleDistance) +{ + PX_ASSERT(!getSim()); + PxReal gridSize = getGridSize(); + mLLParameter.restParticleDistance = restParticleDistance; + setGridSize(gridSize); +} + +//----------------------------------------------------------------------------// + +PxReal Sc::ParticleSystemCore::getGridSize() const +{ + const PxReal cellSize = mLLParameter.kernelRadiusMultiplier * mLLParameter.restParticleDistance; + const PxU32 packetMult = PxU32(1 << mLLParameter.packetSizeMultiplierLog2); + return packetMult * cellSize; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setGridSize(PxReal gridSize) +{ + PX_ASSERT(!getSim()); + const PxReal cellSize = mLLParameter.kernelRadiusMultiplier * mLLParameter.restParticleDistance; + mLLParameter.packetSizeMultiplierLog2 = computePacketSizeMultLog2(gridSize, cellSize); +} + +//----------------------------------------------------------------------------// + +/** +Create new particles in the LL and the user particle data. +*/ +bool Sc::ParticleSystemCore::createParticles(const PxParticleCreationData& creationData) +{ + PX_ASSERT(creationData.numParticles > 0); + PX_ASSERT(creationData.numParticles <= (getParticleState().getMaxParticlesV() - getParticleCount())); + + // add particles to lowlevel + return getParticleState().addParticlesV(creationData); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::releaseParticles(PxU32 nbIndices, const PxStrideIterator<const PxU32>& indices) +{ + PX_ASSERT(indices.ptr()); + getParticleState().removeParticlesV(nbIndices, indices); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::releaseParticles() +{ + getParticleState().removeParticlesV(); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setPositions(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, const PxStrideIterator<const PxVec3>& positionBuffer) +{ + PX_ASSERT(numParticles > 0 && indexBuffer.ptr() && positionBuffer.ptr()); + getParticleState().setPositionsV(numParticles, indexBuffer, positionBuffer); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setVelocities(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, const PxStrideIterator<const PxVec3>& velocityBuffer) +{ + PX_ASSERT(numParticles > 0 && indexBuffer.ptr() && velocityBuffer.ptr()); + getParticleState().setVelocitiesV(numParticles, indexBuffer, velocityBuffer); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setRestOffsets(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer, const PxStrideIterator<const PxF32>& restOffsetBuffer) +{ + PX_ASSERT(numParticles > 0 && indexBuffer.ptr() && restOffsetBuffer.ptr()); + getParticleState().setRestOffsetsV(numParticles, indexBuffer, restOffsetBuffer); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::addDeltaVelocities(const Cm::BitMap& bufferMap, const PxVec3* buffer, PxReal multiplier) +{ + getParticleState().addDeltaVelocitiesV(bufferMap, buffer, multiplier); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::getParticleReadData(PxParticleFluidReadData& readData) const +{ + bool wantDeviceData = readData.getDataAccessFlags()&PxDataAccessFlag::eDEVICE; + + Pt::ParticleSystemStateDataDesc particles; + getParticleState().getParticlesV(particles, false, wantDeviceData); + PX_ASSERT(particles.maxParticles >= particles.numParticles); + PX_ASSERT(particles.maxParticles >= particles.validParticleRange); + + readData.nbValidParticles = particles.numParticles; + readData.validParticleRange = particles.validParticleRange; + readData.validParticleBitmap = particles.bitMap ? particles.bitMap->getWords() : NULL; + + readData.positionBuffer = PxStrideIterator<const PxVec3>(); + readData.velocityBuffer = PxStrideIterator<const PxVec3>(); + readData.restOffsetBuffer = PxStrideIterator<const PxF32>(); + readData.flagsBuffer = PxStrideIterator<const PxParticleFlags>(); + readData.collisionNormalBuffer = PxStrideIterator<const PxVec3>(); + readData.collisionVelocityBuffer = PxStrideIterator<const PxVec3>(); + readData.densityBuffer = PxStrideIterator<const PxReal>(); + + if (readData.validParticleRange > 0) + { + if (mLLParameter.particleReadDataFlags & PxParticleReadDataFlag::ePOSITION_BUFFER) + readData.positionBuffer = particles.positions; + + if (mLLParameter.particleReadDataFlags & PxParticleReadDataFlag::eVELOCITY_BUFFER) + readData.velocityBuffer = particles.velocities; + + if (mLLParameter.particleReadDataFlags & PxParticleReadDataFlag::eREST_OFFSET_BUFFER) + readData.restOffsetBuffer = particles.restOffsets; + + if (mLLParameter.particleReadDataFlags & PxParticleReadDataFlag::eFLAGS_BUFFER) + readData.flagsBuffer = PxStrideIterator<const PxParticleFlags>(reinterpret_cast<const PxParticleFlags*>(particles.flags.ptr()), particles.flags.stride()); + + Sc::ParticleSystemSim* sim = getSim(); + if (sim) + { + Pt::ParticleSystemSimDataDesc simParticleData; + sim->getSimParticleData(simParticleData, wantDeviceData); + + if (mLLParameter.particleReadDataFlags & PxParticleReadDataFlag::eCOLLISION_NORMAL_BUFFER) + readData.collisionNormalBuffer = simParticleData.collisionNormals; + + if (mLLParameter.particleReadDataFlags & PxParticleReadDataFlag::eCOLLISION_VELOCITY_BUFFER) + readData.collisionVelocityBuffer = simParticleData.collisionVelocities; + + if (mLLParameter.particleReadDataFlags & PxParticleReadDataFlag::eDENSITY_BUFFER) + readData.densityBuffer = simParticleData.densities; + } + } +} + +//----------------------------------------------------------------------------// + +const Cm::BitMap& Sc::ParticleSystemCore::getParticleMap() const +{ + Pt::ParticleSystemStateDataDesc particles; + getParticleState().getParticlesV(particles, false, false); + return *particles.bitMap; +} + +//----------------------------------------------------------------------------// + +PxU32 Sc::ParticleSystemCore::getParticleCount() const +{ + return getParticleState().getParticleCountV(); +} + +//----------------------------------------------------------------------------// + +PxBounds3 Sc::ParticleSystemCore::getWorldBounds() const +{ + return getParticleState().getWorldBoundsV(); +} + +//----------------------------------------------------------------------------// + +const PxVec3& Sc::ParticleSystemCore::getExternalAcceleration() const +{ + return mExternalAcceleration; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setExternalAcceleration(const PxVec3& v) +{ + mExternalAcceleration = v; +} + +//----------------------------------------------------------------------------// + +const PxPlane& Sc::ParticleSystemCore::getProjectionPlane() const +{ + return mLLParameter.projectionPlane; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemCore::setProjectionPlane(const PxPlane& plane) +{ + mLLParameter.projectionPlane = plane; +} + +//----------------------------------------------------------------------------// + +#if PX_SUPPORT_GPU_PHYSX + +void Sc::ParticleSystemCore::enableDeviceExclusiveModeGpu() +{ + PX_ASSERT(getSim()); + getSim()->enableDeviceExclusiveModeGpu(); +} + +PxParticleDeviceExclusiveAccess* Sc::ParticleSystemCore::getDeviceExclusiveAccessGpu() const +{ + PX_ASSERT(getSim()); + return getSim()->getDeviceExclusiveAccessGpu(); +} + +bool Sc::ParticleSystemCore::isGpu() const +{ + return getSim() && getSim()->isGpu(); +} +#endif + +//----------------------------------------------------------------------------// + +#endif // PX_USE_PARTICLE_SYSTEM_API diff --git a/PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemSim.cpp b/PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemSim.cpp new file mode 100644 index 00000000..7ebf1fde --- /dev/null +++ b/PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemSim.cpp @@ -0,0 +1,868 @@ +// 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 "ScParticleSystemSim.h" +#if PX_USE_PARTICLE_SYSTEM_API + +#include "foundation/PxProfiler.h" +#include "ScParticlePacketShape.h" +#include "ScParticleBodyInteraction.h" +#include "ScParticleSystemCore.h" +#include "ScPhysics.h" +#include "ScNPhaseCore.h" +#include "ScBodySim.h" +#include "ScStaticSim.h" +#include "PxParticleReadData.h" +#include "PtParticleSystemSim.h" +#include "PtParticleContactManagerStream.h" +#include "PtContext.h" + +using namespace physx; + +//----------------------------------------------------------------------------// + +Sc::ParticleSystemSim::ParticleSystemSim(Scene& scene, ParticleSystemCore& core) +: ActorSim(scene, core) +, mParticlePacketShapePool(PX_DEBUG_EXP("ParticlePacketShapePool")) +, mParticlePacketShapes(PX_DEBUG_EXP("ParticleSysPacketShapes")) +, mInteractionCount(0) +, mCollisionInputPrepTask(this, "ScParticleSystemSim.prepareCollisionInput") +{ + // Set size of interaction list + ActorSim::setInteractionCountHint(32); + + Pt::Context* llContext = getScene().getParticleContext(); + Pt::ParticleData* particleData = core.obtainStandaloneData(); + PX_ASSERT(particleData); + + bool useGpu = getCore().getFlags() & PxParticleBaseFlag::eGPU; + mLLSim = llContext->addParticleSystem(particleData, core.getLowLevelParameter(), useGpu); + + //CPU fall back + if (!mLLSim && useGpu) + { + Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "GPU particle system creation failed. Falling back to CPU implementation."); + mLLSim = llContext->addParticleSystem(particleData, core.getLowLevelParameter(), false); + getCore().notifyCpuFallback(); + } + + if (mLLSim) + { + if (getCore().getFlags() & PxParticleBaseFlag::eENABLED) + { + mLLSim->setSimulatedV(true); + } + } + else + { + core.setSim(NULL); + core.returnStandaloneData(particleData); + } +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::release(bool releaseParticleData) +{ + releaseParticlePacketShapes(); + + if (mLLSim) //might be not the case if low level sim creation failed. + { + Pt::Context* llContext = getScene().getParticleContext(); + + Pt::ParticleData* particleData = llContext->removeParticleSystem(mLLSim, !releaseParticleData); + if (!releaseParticleData) + { + PX_ASSERT(particleData); + getCore().returnStandaloneData(particleData); + } + getCore().setSim(NULL); + } + delete this; +} + +//----------------------------------------------------------------------------// + +Sc::ParticleSystemCore& Sc::ParticleSystemSim::getCore() const +{ + return static_cast<ParticleSystemCore&>(Sc::ActorSim::getActorCore()); +} + +//----------------------------------------------------------------------------// + +#if PX_SUPPORT_GPU_PHYSX + +void Sc::ParticleSystemSim::enableDeviceExclusiveModeGpu() +{ + PX_ASSERT(mLLSim); + mLLSim->enableDeviceExclusiveModeGpuV(); +} + +PxParticleDeviceExclusiveAccess* Sc::ParticleSystemSim::getDeviceExclusiveAccessGpu() const +{ + PX_ASSERT(mLLSim); + return mLLSim->getDeviceExclusiveAccessGpuV(); +} + +#endif + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::unlinkParticleShape(ParticlePacketShape* particleShape) +{ + // Remove the specified particle shape from the shape list + PX_ASSERT(particleShape); + PX_ASSERT(mParticlePacketShapes.size() > 0); + PxU32 index = particleShape->getIndex(); + PX_ASSERT(mParticlePacketShapes[index] == particleShape); + mParticlePacketShapes.back()->setIndex(index); + mParticlePacketShapes.replaceWithLast(index); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::releaseParticlePacketShapes() +{ + PxU32 shapesCount = mParticlePacketShapes.size(); + for(PxU32 i=0; i < shapesCount; i++) + { + ParticlePacketShape* fs = mParticlePacketShapes.back(); + mParticlePacketShapePool.destroy(fs); // The shape will remove itself from the particle shape list + } +} + +//----------------------------------------------------------------------------// + +PxU32 Sc::ParticleSystemSim::getInternalFlags() const +{ + return getCore().getInternalFlags(); +} + +//----------------------------------------------------------------------------// + +PxFilterData Sc::ParticleSystemSim::getSimulationFilterData() const +{ + return getCore().getSimulationFilterData(); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::scheduleRefiltering() +{ + // Schedule a refiltering + for (PxU32 i=0; i < mParticlePacketShapes.size(); i++) + { + mParticlePacketShapes[i]->setInteractionsDirty(InteractionDirtyFlag::eFILTER_STATE); + } +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::resetFiltering() +{ + // Remove all shapes from broadphase and add again + const PxU32 size = mParticlePacketShapes.size(); + for (PxU32 i=0; i<size; i++) + { + mParticlePacketShapes[i]->destroyLowLevelVolume(); + mParticlePacketShapes[i]->createLowLevelVolume(); + } +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::setFlags(PxU32 flags) +{ + if ((getCore().getFlags() & PxParticleBaseFlag::eENABLED) && !(flags & PxParticleBaseFlag::eENABLED)) + { + mLLSim->setSimulatedV(true); + } + else if (!(getCore().getFlags() & PxParticleBaseFlag::eENABLED) && (flags & PxParticleBaseFlag::eENABLED)) + { + mLLSim->setSimulatedV(false); + } +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::getSimParticleData(Pt::ParticleSystemSimDataDesc& simParticleData, bool devicePtr) const +{ + PX_ASSERT(mLLSim); + mLLSim->getSimParticleDataV(simParticleData, devicePtr); +} + +//----------------------------------------------------------------------------// + +Pt::ParticleSystemState& Sc::ParticleSystemSim::getParticleState() +{ + PX_ASSERT(mLLSim); + return mLLSim->getParticleStateV(); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::addInteraction(const ParticlePacketShape& particleShape, const ShapeSim& shape, const PxU32 ccdPass) +{ + PX_ASSERT(mLLSim); + const PxsShapeCore& shapeCore = shape.getCore().getCore(); + bool isDynamic = shape.actorIsDynamic(); + PxsRigidCore& rigidCore = shape.getPxsRigidCore(); + if(isDynamic) + getScene().getParticleContext()->getBodyTransformVaultFast().addBody(static_cast<PxsBodyCore&>(rigidCore)); + + mLLSim->addInteractionV(*particleShape.getLowLevelParticleShape(), size_t(&shapeCore), size_t(&rigidCore), isDynamic, (ccdPass > 0)); + mInteractionCount++; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::removeInteraction(const ParticlePacketShape& particleShape, const ShapeSim& shape, bool isDyingRb, const PxU32 ccdPass) +{ + PX_ASSERT(mLLSim); + const PxsShapeCore& shapeCore = shape.getCore().getCore(); + bool isDynamic = shape.actorIsDynamic(); + PxsRigidCore& rigidCore = shape.getPxsRigidCore(); + if(isDynamic) + getScene().getParticleContext()->getBodyTransformVaultFast().removeBody(static_cast<PxsBodyCore&>(rigidCore)); + + mLLSim->removeInteractionV(*particleShape.getLowLevelParticleShape(), size_t(&shapeCore), size_t(&rigidCore), isDynamic, isDyingRb, (ccdPass > 0)); + mInteractionCount--; +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::onRbShapeChange(const ParticlePacketShape& particleShape, const ShapeSim& shape) +{ + PX_ASSERT(mLLSim); + mLLSim->onRbShapeChangeV(*particleShape.getLowLevelParticleShape(), size_t(&shape.getCore().getCore())); +} + +//----------------------------------------------------------------------------// + +PX_FORCE_INLINE void addImpulseAtPos(PxsBodyCore& bodyCore, const PxVec3& impulse, const PxVec3& worldPos) +{ + const PxTransform& pose = bodyCore.body2World; + PxVec3 torque = (worldPos - pose.p).cross(impulse); + + bodyCore.linearVelocity += impulse * bodyCore.inverseMass; + bodyCore.angularVelocity += pose.q.rotate(bodyCore.inverseInertia.multiply(pose.q.rotateInv(torque))); +} + +//----------------------------------------------------------------------------// + +/** +currently, it may be that shape id's from removed shapes are reported. +Try to catch these and ignore them in order to avoid artefacts. +*/ +void Sc::ParticleSystemSim::updateRigidBodies() +{ + if (!(getCore().getFlags() & PxParticleBaseFlag::eCOLLISION_TWOWAY) + || !(getCore().getFlags() & PxParticleBaseFlag::eCOLLISION_WITH_DYNAMIC_ACTORS)) + return; + + PxReal particleMass = getCore().getParticleMass(); + + //Particle data might not even be available if count is zero. + if (getParticleState().getParticleCountV() == 0) + return; + + Pt::ParticleSystemStateDataDesc particlesCore; + getParticleState().getParticlesV(particlesCore, false, false); + + if (particlesCore.validParticleRange == 0) + return; + + PX_ASSERT(particlesCore.bitMap); + PX_ASSERT(particlesCore.flags.ptr()); + PX_ASSERT(particlesCore.positions.ptr()); + + Pt::ParticleSystemSimDataDesc particlesSim; + getSimParticleData(particlesSim, false); + PX_ASSERT(particlesSim.twoWayImpluses.ptr()); + PX_ASSERT(particlesSim.twoWayBodies.ptr()); + + Cm::BitMap::Iterator it(*particlesCore.bitMap); + for (PxU32 p = it.getNext(); p != Cm::BitMap::Iterator::DONE; p = it.getNext()) + { + if (!particlesSim.twoWayBodies[p]) + continue; + + Pt::ParticleFlags flags = particlesCore.flags[p]; + PX_ASSERT(flags.api & PxParticleFlag::eCOLLISION_WITH_DYNAMIC); + + PxsBodyCore& body = *reinterpret_cast<PxsBodyCore*>(particlesSim.twoWayBodies[p]); + BodyCore& scBody = BodyCore::getCore(body); + + if (scBody.getCore().inverseMass == 0.0f) // kinematic + continue; + + PxDominanceGroupPair cdom = getScene().getDominanceGroupPair(getCore().getDominanceGroup(), scBody.getDominanceGroup()); + + if (cdom.dominance0 == 0.0f) + continue; + + if (cdom.dominance1 == 0.0f) + PX_WARN_ONCE("Dominance: unsupport particle dominance is 1.0 and rigid body dominance is 0.0"); + + if (flags.api & PxParticleFlag::eCOLLISION_WITH_DRAIN) + continue; + + const PxVec3& position = particlesCore.positions[p]; + const PxVec3& impulse = particlesSim.twoWayImpluses[p]; + PX_ASSERT(impulse.isFinite()); + + if (!impulse.isZero()) + { + PX_ASSERT(scBody.getSim()); + scBody.getSim()->internalWakeUp(); + addImpulseAtPos(scBody.getCore(), impulse*particleMass, position); + } + } +} + +//----------------------------------------------------------------------------// + +/* particle update has the following structure: + * + * The update process for the particle array in low level is to process the active + * particle buffer by removing the deleted particles and moving particles from + * the top of the array to fill the spaces, then to append the new particles to + * the array. Using this knowledge we synchronize the IndexMap on the host. + * + * TODO: there's an obvious optimization here: replacing deleted particles in place with + * new particles, and then just processing remaining deletes and adds. + */ +void Sc::ParticleSystemSim::startStep() +{ + PX_PROFILE_ZONE("ParticleSim.startStep",0); + + PxVec3 externalAcceleration = getCore().getExternalAcceleration(); + if ((getCore().getActorFlags() & PxActorFlag::eDISABLE_GRAVITY) == false) + externalAcceleration += getScene().getGravity(); + + mLLSim->setExternalAccelerationV(externalAcceleration); + + // Set simulation time step + mLLSim->setSimulationTimeStepV(static_cast<PxReal>(getScene().getDt())); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::addParticlePacket(Pt::ParticleShape* llParticleShape) +{ + PX_ASSERT(llParticleShape); + + PxU32 index = mParticlePacketShapes.size(); + Sc::ParticlePacketShape* particleShape = mParticlePacketShapePool.construct(*this, index, llParticleShape); + + if (particleShape) + { + mParticlePacketShapes.pushBack(particleShape); // Add shape to list. + } + else + { + llParticleShape->destroyV(); + } +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::removeParticlePacket(const Pt::ParticleShape * llParticleShape) +{ + // Find corresponding particle packet shape. + void* data = llParticleShape->getUserDataV(); + PX_ASSERT(data); + ParticlePacketShape* particleShape = reinterpret_cast<ParticlePacketShape*>(data); + // Cleanup shape. The shape will remove itself from particle shape list. + mParticlePacketShapePool.destroy(particleShape); +} + +//----------------------------------------------------------------------------// + +/** +- Create / delete / update particle shapes. + +Only call this function when the packet/shapes update task for the particle system has successful finished +and after the whole particle pipeline has finished. +*/ +void Sc::ParticleSystemSim::processShapesUpdate() +{ + PX_PROFILE_ZONE("ParticleSim.shapesUpdateProcessing",0); + + Pt::ParticleShapeUpdateResults updateResults; + mLLSim->getShapesUpdateV(updateResults); + + // + // Process particle shape update results + // + + for(PxU32 i=0; i < updateResults.destroyedShapeCount; i++) + { + // Delete particle packet + PX_ASSERT(updateResults.destroyedShapes[i]); + removeParticlePacket(updateResults.destroyedShapes[i]); + } + + for(PxU32 i=0; i < updateResults.createdShapeCount; i++) + { + // Create new particle packet + PX_ASSERT(updateResults.createdShapes[i]); + addParticlePacket(updateResults.createdShapes[i]); + } +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::endStep() +{ + PX_PROFILE_ZONE("ParticleSim.endStep",0); + + // applies int buffered interaction updates that where produced asynchronously to gpu execution. + // this has to go before processShapesUpdate, since that will update interactions as well + mLLSim->flushBufferedInteractionUpdatesV(); + + // some lowlevel implementations (gpu) got an update at the end of the step. + processShapesUpdate(); + + // 2-way interaction + updateRigidBodies(); +} + +//----------------------------------------------------------------------------// + +#if PX_ENABLE_DEBUG_VISUALIZATION + +/** +Render particle system state before simulation starts. CollisionNormals are a product of of simulate and not available here. +*/ +void Sc::ParticleSystemSim::visualizeStartStep(Cm::RenderOutput& out) +{ + if (!(getCore().getActorFlags() & PxActorFlag::eVISUALIZATION)) + return; + + //all particle visualization in world space! + out << PxTransform(PxIdentity); + + if (getScene().getVisualizationParameter(PxVisualizationParameter::ePARTICLE_SYSTEM_BOUNDS) > 0.0f) + visualizeParticlesBounds(out); + + visualizeParticles(out); + + if (getScene().getVisualizationParameter(PxVisualizationParameter::ePARTICLE_SYSTEM_GRID) > 0.0f) + visualizeSpatialGrid(out); + + if (getScene().getVisualizationParameter(PxVisualizationParameter::ePARTICLE_SYSTEM_BROADPHASE_BOUNDS) > 0.0f) + visualizeBroadPhaseBounds(out); + + if(0) // MS: Might be helpful for debugging + visualizeInteractions(out); +} + +/** +Render particle system data that is available after simulation and not up to date after the application made updates (CollisionNormals). +*/ +void Sc::ParticleSystemSim::visualizeEndStep(Cm::RenderOutput& out) +{ + if (!(getCore().getActorFlags() & PxActorFlag::eVISUALIZATION)) + return; + + //all particle visualization in world space! + out << PxTransform(PxIdentity); + + visualizeCollisionNormals(out); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::visualizeParticlesBounds(Cm::RenderOutput& out) +{ + PxBounds3 bounds = getParticleState().getWorldBoundsV(); + out << PxU32(PxDebugColor::eARGB_RED) << Cm::DebugBox(bounds); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::visualizeSpatialGrid(Cm::RenderOutput& out) +{ + PxReal packetSize = getCore().getGridSize(); + + for (PxU32 i = 0; i < mParticlePacketShapes.size(); i++) + { + ParticlePacketShape* particleShape = mParticlePacketShapes[i]; + + PxBounds3 bounds = particleShape->getBounds(); + PxVec3 centerGridSpace = bounds.getCenter() / packetSize; + + for (PxU32 d = 0; d < 3; d++) + bounds.minimum[d] = Ps::floor(centerGridSpace[d]) * packetSize; + for (PxU32 d = 0; d < 3; d++) + bounds.maximum[d] = Ps::ceil(centerGridSpace[d]) * packetSize; + + out << PxU32(PxDebugColor::eARGB_BLUE) << Cm::DebugBox(bounds); + } +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::visualizeBroadPhaseBounds(Cm::RenderOutput& out) +{ + for (PxU32 i = 0; i < mParticlePacketShapes.size(); i++) + { + ParticlePacketShape* particleShape = mParticlePacketShapes[i]; + PxBounds3 bounds = particleShape->getBounds(); + out << PxU32(PxDebugColor::eARGB_BLUE) << Cm::DebugBox(bounds); + } +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::visualizeParticles(Cm::RenderOutput& out) +{ + PxReal timestep = getScene().getDt(); + + Pt::ParticleSystemStateDataDesc particlesCore; + getParticleState().getParticlesV(particlesCore, false, false); + + if (particlesCore.numParticles == 0) + return; + + PX_ASSERT(particlesCore.bitMap); + + bool arePositionsReadeable = getCore().getParticleReadDataFlags() & PxParticleReadDataFlag::ePOSITION_BUFFER; + bool areVelocitiesReadeable = getCore().getParticleReadDataFlags() & PxParticleReadDataFlag::eVELOCITY_BUFFER; + + if (getScene().getVisualizationParameter(PxVisualizationParameter::ePARTICLE_SYSTEM_MAX_MOTION_DISTANCE) > 0.0f) + { + if (arePositionsReadeable) + { + PxReal radius = getCore().getMaxMotionDistance(); + + PxQuat q0(0.0f, 0.0f, 0.0f, 1.0f ); + PxQuat q1(0.0f, PxSqrt(0.5f), 0.0f, PxSqrt(0.5f) ); + PxQuat q2(0.5f, 0.5f, 0.5f, 0.5f ); + + Cm::BitMap::Iterator it(*particlesCore.bitMap); + for (PxU32 p = it.getNext(); p != Cm::BitMap::Iterator::DONE; p = it.getNext()) + { + const PxVec3& position = particlesCore.positions[p]; + + if (areVelocitiesReadeable && particlesCore.velocities[p].magnitude()*timestep >= radius*0.99f) + out << PxU32(PxDebugColor::eARGB_RED); + else + out << PxU32(PxDebugColor::eARGB_GREEN); + + out << PxTransform(position, q0) << Cm::DebugCircle(12, radius); + out << PxTransform(position, q1) << Cm::DebugCircle(12, radius); + out << PxTransform(position, q2) << Cm::DebugCircle(12, radius); + } + } + else + { + PX_WARN_ONCE( + "PxVisualizationParameter::ePARTICLE_SYSTEM_MAX_MOTION_DISTANCE cannot be rendered without specifying PxParticleReadDataFlag::ePOSITION_BUFFER"); + } + } + + if (getScene().getVisualizationParameter(PxVisualizationParameter::ePARTICLE_SYSTEM_POSITION) > 0.0f) + { + if (arePositionsReadeable) + { + PxReal rad = getScene().getVisualizationParameter(PxVisualizationParameter::ePARTICLE_SYSTEM_POSITION) * getScene().getVisualizationScale()*0.5f; + PxVec3 a(0,0,rad); + PxVec3 b(0,rad,0); + PxVec3 c(rad,0,0); + + out << PxU32(PxDebugColor::eARGB_BLUE) << Cm::RenderOutput::LINES << PxMat44(PxIdentity); + + Cm::BitMap::Iterator it(*particlesCore.bitMap); + for (PxU32 p = it.getNext(); p != Cm::BitMap::Iterator::DONE; p = it.getNext()) + { + const PxVec3& position = particlesCore.positions[p]; + out << position + a << position - a; + out << position + b << position - b; + out << position + c << position - c; + } + } + else + { + PX_WARN_ONCE( + "PxVisualizationParameter::ePARTICLE_SYSTEM_POSITION cannot be rendered without specifying \ + PxParticleReadDataFlag::ePOSITION_BUFFER"); + } + } + + if (getScene().getVisualizationParameter(PxVisualizationParameter::ePARTICLE_SYSTEM_VELOCITY) > 0.0f) + { + if (arePositionsReadeable && areVelocitiesReadeable) + { + PxReal scale = getScene().getVisualizationParameter(PxVisualizationParameter::ePARTICLE_SYSTEM_VELOCITY) * getScene().getVisualizationScale(); + + out << PxU32(PxDebugColor::eARGB_RED) << PxMat44(PxIdentity); + + Cm::BitMap::Iterator it(*particlesCore.bitMap); + for (PxU32 p = it.getNext(); p != Cm::BitMap::Iterator::DONE; p = it.getNext()) + { + out << Cm::DebugArrow(particlesCore.positions[p], particlesCore.velocities[p] * timestep, scale); + } + } + else + { + PX_WARN_ONCE( + "PxVisualizationParameter::ePARTICLE_SYSTEM_VELOCITY cannot be rendered without specifying \ + PxParticleReadDataFlag::ePOSITION_BUFFER and PxParticleReadDataFlag::eVELOCITY_BUFFER"); + } + } +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::visualizeCollisionNormals(Cm::RenderOutput& out) +{ + Pt::ParticleSystemStateDataDesc particlesCore; + getParticleState().getParticlesV(particlesCore, false, false); + + if (particlesCore.numParticles == 0) + return; + + PX_ASSERT(particlesCore.bitMap); + + bool arePositionsReadeable = getCore().getParticleReadDataFlags() & PxParticleReadDataFlag::ePOSITION_BUFFER; + bool areCollisionNormalsReadeable = getCore().getParticleReadDataFlags() & PxParticleReadDataFlag::eCOLLISION_NORMAL_BUFFER; + + if (getScene().getVisualizationParameter(PxVisualizationParameter::ePARTICLE_SYSTEM_COLLISION_NORMAL) > 0.0f) + { + if (arePositionsReadeable && areCollisionNormalsReadeable) + { + Pt::ParticleSystemSimDataDesc particlesSim; + getSimParticleData(particlesSim, false); + + PxReal scale = getScene().getVisualizationParameter(PxVisualizationParameter::ePARTICLE_SYSTEM_COLLISION_NORMAL) * getScene().getVisualizationScale(); + + out << PxU32(PxDebugColor::eARGB_GREEN) << PxMat44(PxIdentity); + + if(particlesSim.collisionNormals.ptr()) + { + Cm::BitMap::Iterator it(*particlesCore.bitMap); + for (PxU32 p = it.getNext(); p != Cm::BitMap::Iterator::DONE; p = it.getNext()) + { + if (!particlesSim.collisionNormals[p].isZero()) + { + const PxVec3& position = particlesCore.positions[p]; + const PxVec3& normal = particlesSim.collisionNormals[p]; + out << Cm::DebugArrow(position, normal*scale, 0.1f*scale); + } + } + } + } + else + { + PX_WARN_ONCE( + "PxVisualizationParameter::ePARTICLE_SYSTEM_COLLISION_NORMAL cannot be rendered without specifying \ + PxParticleReadDataFlag::ePOSITION_BUFFER and PxParticleReadDataFlag::eCOLLISION_NORMAL_BUFFER"); + } + } +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::visualizeInteractions(Cm::RenderOutput& out) +{ + out << PxU32(PxDebugColor::eARGB_GREEN) << Cm::RenderOutput::LINES; + for(PxU32 i=0; i < mParticlePacketShapes.size(); i++) + { + ParticlePacketShape* particleShape = mParticlePacketShapes[i]; + + ParticleElementRbElementInteraction** interactions = particleShape->getInteractions(); + PxU32 nbInteractions = particleShape->getInteractionsCount(); + + while(nbInteractions--) + { + ParticleElementRbElementInteraction* interaction = *interactions++; + + PX_ASSERT(interaction->getType() == InteractionType::ePARTICLE_BODY); + + const PxBounds3 bounds = particleShape->getBounds(); + + PX_ALIGN(16, PxTransform absPos); + interaction->getRbShape().getAbsPoseAligned(&absPos); + + out << bounds.getCenter() << absPos.p; + } + } +} + +//----------------------------------------------------------------------------// + +PxBaseTask& Sc::ParticleSystemSim::scheduleShapeGeneration(Pt::Context& context, const Ps::Array<ParticleSystemSim*>& particleSystems, PxBaseTask& continuation) +{ + Ps::Array<Pt::ParticleSystemSim*, Ps::TempAllocator> llParticleSystems(particleSystems.size()); + Ps::Array<Pt::ParticleShapesUpdateInput, Ps::TempAllocator> llInputs(particleSystems.size()); + + for (PxU32 i = 0; i < particleSystems.size(); ++i) + { + PX_ASSERT(particleSystems[i]->getScene().getParticleContext() == &context); + particleSystems[i]->createShapeUpdateInput(llInputs[i]); + llParticleSystems[i] = particleSystems[i]->mLLSim; + } + + return context.scheduleShapeGeneration(llParticleSystems.begin(), llInputs.begin(), particleSystems.size(), continuation); +} + +//----------------------------------------------------------------------------// + +PxBaseTask& Sc::ParticleSystemSim::scheduleDynamicsCpu(Pt::Context& context, const Ps::Array<ParticleSystemSim*>& particleSystems, PxBaseTask& continuation) +{ + Ps::Array<Pt::ParticleSystemSim*, Ps::TempAllocator> llParticleSystems(particleSystems.size()); + + for (PxU32 i = 0; i < particleSystems.size(); ++i) + { + PX_ASSERT(particleSystems[i]->getScene().getParticleContext() == &context); + llParticleSystems[i] = particleSystems[i]->mLLSim; + } + + return context.scheduleDynamicsCpu(llParticleSystems.begin(), particleSystems.size(), continuation); +} + +//----------------------------------------------------------------------------// + +PxBaseTask& Sc::ParticleSystemSim::scheduleCollisionPrep(Pt::Context& context, const Ps::Array<ParticleSystemSim*>& particleSystems, PxBaseTask& continuation) +{ + Ps::Array<Pt::ParticleSystemSim*, Ps::TempAllocator> llParticleSystems(particleSystems.size()); + Ps::Array<PxLightCpuTask*, Ps::TempAllocator> inputPrepTasks(particleSystems.size()); + + for (PxU32 i = 0; i < particleSystems.size(); ++i) + { + PX_ASSERT(particleSystems[i]->getScene().getParticleContext() == &context); + inputPrepTasks[i] = &particleSystems[i]->mCollisionInputPrepTask; + llParticleSystems[i] = particleSystems[i]->mLLSim; + } + + return context.scheduleCollisionPrep(llParticleSystems.begin(), inputPrepTasks.begin(), inputPrepTasks.size(), continuation); +} + +//----------------------------------------------------------------------------// + +PxBaseTask& Sc::ParticleSystemSim::scheduleCollisionCpu(Pt::Context& context, const Ps::Array<ParticleSystemSim*>& particleSystems, PxBaseTask& continuation) +{ + Ps::Array<Pt::ParticleSystemSim*, Ps::TempAllocator> llParticleSystems(particleSystems.size()); + + for (PxU32 i = 0; i < particleSystems.size(); ++i) + { + PX_ASSERT(particleSystems[i]->getScene().getParticleContext() == &context); + llParticleSystems[i] = particleSystems[i]->mLLSim; + } + + return context.scheduleCollisionCpu(llParticleSystems.begin(), particleSystems.size(), continuation); +} + +//----------------------------------------------------------------------------// + +PxBaseTask& Sc::ParticleSystemSim::schedulePipelineGpu(Pt::Context& context, const Ps::Array<ParticleSystemSim*>& particleSystems, PxBaseTask& continuation) +{ + Ps::Array<Pt::ParticleSystemSim*, Ps::TempAllocator> llParticleSystems(particleSystems.size()); + for (PxU32 i = 0; i < particleSystems.size(); ++i) + { + PX_ASSERT(particleSystems[i]->getScene().getParticleContext() == &context); + llParticleSystems[i] = particleSystems[i]->mLLSim; + } + + return context.schedulePipelineGpu(llParticleSystems.begin(), particleSystems.size(), continuation); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::createShapeUpdateInput(Pt::ParticleShapesUpdateInput& input) +{ + Pt::ParticleShape** llShapes = NULL; + if (mParticlePacketShapes.size() > 0) + { + //note: this buffer needs to be deallocated in LL + llShapes = reinterpret_cast<Pt::ParticleShape**>(PX_ALLOC_TEMP(mParticlePacketShapes.size()*sizeof(Pt::ParticleShape*), "Pt::ParticleShape*")); + for (PxU32 i = 0; i < mParticlePacketShapes.size(); ++i) + llShapes[i] = mParticlePacketShapes[i]->getLowLevelParticleShape(); + } + + input.shapes = llShapes; + input.shapeCount = mParticlePacketShapes.size(); +} + +//----------------------------------------------------------------------------// + +void Sc::ParticleSystemSim::prepareCollisionInput(PxBaseTask* /*continuation*/) +{ + PxU32 numParticleShapes = mParticlePacketShapes.size(); + PxU32 numInteractionsTest = 0; + + //note: this buffer needs to be deallocated in LL + PxU32 cmStreamSize = Pt::ParticleContactManagerStreamWriter::getStreamSize(numParticleShapes, mInteractionCount); + PxU8* cmStream = reinterpret_cast<PxU8*>(PX_ALLOC_TEMP(cmStreamSize, "ParticleContactManagerStream")); + + Pt::ParticleContactManagerStreamWriter swriter(cmStream, numParticleShapes, mInteractionCount); + + for (PxU32 s = 0; s < mParticlePacketShapes.size(); ++s) + { + const Sc::ParticlePacketShape& particleShape = *mParticlePacketShapes[s]; + swriter.addParticleShape(particleShape.getLowLevelParticleShape()); + + //count number of interactions... could be cached + ParticleElementRbElementInteraction*const* interactions = particleShape.getInteractions(); + PxU32 nbInteractions = particleShape.getInteractionsCount(); + while(nbInteractions--) + { + PX_ASSERT((*interactions)->getType() == InteractionType::ePARTICLE_BODY); + const Sc::ParticleElementRbElementInteraction& cm = *(*interactions++); + + if (!cm.isDisabled()) + { + PX_ASSERT(cm.getElement1().getElementType() == ElementType::eSHAPE); + const Sc::ShapeSim& shapeSim = cm.getRbShape(); + bool isDynamic = shapeSim.actorIsDynamic(); + const RigidSim& rigidSim = shapeSim.getRbSim(); + PxsRigidCore& rigidCore = static_cast<BodyCore&>(rigidSim.getActorCore()).getCore(); + const PxTransform* w2sOld = isDynamic ? getScene().getParticleContext()->getBodyTransformVaultFast().getTransform(static_cast<const PxsBodyCore&>(rigidCore)) : NULL; + swriter.addContactManager(&rigidCore, &shapeSim.getCore().getCore(), w2sOld, (shapeSim.getFlags() & PxShapeFlag::ePARTICLE_DRAIN) != 0, isDynamic); + numInteractionsTest++; + } + } + } + PX_ASSERT(numInteractionsTest == mInteractionCount); + + //passes ownership to low level object + Pt::ParticleCollisionUpdateInput input; + input.contactManagerStream = cmStream; + mLLSim->passCollisionInputV(input); +} + +//----------------------------------------------------------------------------// + +#endif // PX_ENABLE_DEBUG_VISUALIZATION + + +#endif // PX_USE_PARTICLE_SYSTEM_API diff --git a/PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemSim.h b/PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemSim.h new file mode 100644 index 00000000..c020ca18 --- /dev/null +++ b/PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemSim.h @@ -0,0 +1,174 @@ +// 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_SCP_PARTICLE_SYSTEM_SIM +#define PX_PHYSICS_SCP_PARTICLE_SYSTEM_SIM + +#include "CmPhysXCommon.h" +#include "PxPhysXConfig.h" +#if PX_USE_PARTICLE_SYSTEM_API + +#include "ScScene.h" +#include "ScActorSim.h" +#include "ScRigidSim.h" +#include "PsPool.h" + +#include "ScParticlePacketShape.h" +#include "PtParticleSystemSim.h" + +namespace physx +{ + +#if PX_SUPPORT_GPU_PHYSX +class PxParticleDeviceExclusiveAccess; +#endif + +namespace Pt +{ + class Context; + class ParticleSystemSim; + class ParticleShape; + class ParticleSystemState; + struct ParticleSystemSimDataDesc; + struct ParticleShapesUpdateInput; + struct ParticleCollisionUpdateInput; +} + +namespace Sc +{ + class ParticleSystemCore; + class ShapeSim; + class ParticlePacketShape; + +#define PX_PARTICLE_SYSTEM_DEBUG_RENDERING 1 + + class ParticleSystemSim : public ActorSim + { + public: + + ParticleSystemSim(Scene&, ParticleSystemCore&); + + void release(bool releaseStateBuffers); + + PxFilterData getSimulationFilterData() const; + void scheduleRefiltering(); + void resetFiltering(); + + void setFlags(PxU32 flags); + PxU32 getInternalFlags() const; + + void getSimParticleData(Pt::ParticleSystemSimDataDesc& simParticleData, bool devicePtr) const; + Pt::ParticleSystemState& getParticleState(); + + void addInteraction(const ParticlePacketShape& particleShape, const ShapeSim& shape, const PxU32 ccdPass); + void removeInteraction(const ParticlePacketShape& particleShape, const ShapeSim& shape, bool isDyingRb, const PxU32 ccdPass); + void onRbShapeChange(const ParticlePacketShape& particleShape, const ShapeSim& shape); + + void processShapesUpdate(); +#if PX_SUPPORT_GPU_PHYSX + Ps::IntBool isGpu() const { return mLLSim->isGpuV(); } +#endif + // batched updates + static PxBaseTask& scheduleShapeGeneration(Pt::Context& context, const Ps::Array<ParticleSystemSim*>& particleSystems, PxBaseTask& continuation); + static PxBaseTask& scheduleDynamicsCpu(Pt::Context& context, const Ps::Array<ParticleSystemSim*>& particleSystems, PxBaseTask& continuation); + static PxBaseTask& scheduleCollisionPrep(Pt::Context& context, const Ps::Array<ParticleSystemSim*>& particleSystems, PxBaseTask& continuation); + static PxBaseTask& scheduleCollisionCpu(Pt::Context& context, const Ps::Array<ParticleSystemSim*>& particleSystems, PxBaseTask& continuation); + static PxBaseTask& schedulePipelineGpu(Pt::Context& context, const Ps::Array<ParticleSystemSim*>& particleSystems, PxBaseTask& continuation); + + //--------------------------------------------------------------------------------- + // Actor implementation + //--------------------------------------------------------------------------------- + public: + // non-DDI methods: + + // Core functionality + void startStep(); + void endStep(); + + void unlinkParticleShape(ParticlePacketShape* particleShape); + + ParticleSystemCore& getCore() const; + +#if PX_SUPPORT_GPU_PHYSX + void enableDeviceExclusiveModeGpu(); + PxParticleDeviceExclusiveAccess* + getDeviceExclusiveAccessGpu() const; +#endif + + private: + ~ParticleSystemSim() {} + + void createShapeUpdateInput(Pt::ParticleShapesUpdateInput& input); + void createCollisionUpdateInput(Pt::ParticleCollisionUpdateInput& input); + void updateRigidBodies(); + void prepareCollisionInput(PxBaseTask* continuation); + + // ParticleSystem packet handling + void releaseParticlePacketShapes(); + PX_INLINE void addParticlePacket(Pt::ParticleShape* llParticleShape); + PX_INLINE void removeParticlePacket(const Pt::ParticleShape * llParticleShape); + + +#if PX_ENABLE_DEBUG_VISUALIZATION + public: + void visualizeStartStep(Cm::RenderOutput& out); + void visualizeEndStep(Cm::RenderOutput& out); + + private: + void visualizeParticlesBounds(Cm::RenderOutput& out); + void visualizeParticles(Cm::RenderOutput& out); + void visualizeCollisionNormals(Cm::RenderOutput& out); + void visualizeSpatialGrid(Cm::RenderOutput& out); + void visualizeBroadPhaseBounds(Cm::RenderOutput& out); + void visualizeInteractions(Cm::RenderOutput& out); // MS: Might be helpful for debugging +#endif // PX_ENABLE_DEBUG_VISUALIZATION + + + private: + Pt::ParticleSystemSim* mLLSim; + + // Array of particle packet shapes + Ps::Pool<ParticlePacketShape> mParticlePacketShapePool; + Ps::Array<ParticlePacketShape*> mParticlePacketShapes; + + // Count interactions for sizing the contact manager stream + PxU32 mInteractionCount; + + typedef Cm::DelegateTask<Sc::ParticleSystemSim, &Sc::ParticleSystemSim::prepareCollisionInput> CollisionInputPrepTask; + CollisionInputPrepTask mCollisionInputPrepTask; + }; + +} // namespace Sc + +} + +#endif // PX_USE_PARTICLE_SYSTEM_API + +#endif |