aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/SimulationController/src/particles
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/SimulationController/src/particles
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/SimulationController/src/particles')
-rw-r--r--PhysX_3.4/Source/SimulationController/src/particles/ScParticleBodyInteraction.cpp112
-rw-r--r--PhysX_3.4/Source/SimulationController/src/particles/ScParticleBodyInteraction.h152
-rw-r--r--PhysX_3.4/Source/SimulationController/src/particles/ScParticlePacketShape.cpp191
-rw-r--r--PhysX_3.4/Source/SimulationController/src/particles/ScParticlePacketShape.h126
-rw-r--r--PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemCore.cpp705
-rw-r--r--PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemSim.cpp868
-rw-r--r--PhysX_3.4/Source/SimulationController/src/particles/ScParticleSystemSim.h174
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