aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/PhysX/src/buffering
diff options
context:
space:
mode:
Diffstat (limited to 'PhysX_3.4/Source/PhysX/src/buffering')
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbActor.cpp84
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbActor.h186
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbAggregate.cpp152
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbAggregate.h249
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbArticulation.h353
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbArticulationJoint.h283
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbBase.cpp48
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbBase.h333
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbBody.h1068
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbCloth.cpp60
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbCloth.h1195
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbConstraint.h332
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbDefs.h140
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbMetaData.cpp203
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbNpDeps.h77
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbParticleSystem.cpp311
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbParticleSystem.h484
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbRigidObject.h530
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbRigidStatic.h155
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbScene.cpp1514
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbScene.h939
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbSceneBuffer.h164
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbScenePvdClient.cpp1240
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbScenePvdClient.h223
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbShape.cpp146
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbShape.h452
-rw-r--r--PhysX_3.4/Source/PhysX/src/buffering/ScbType.h61
27 files changed, 10982 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbActor.cpp b/PhysX_3.4/Source/PhysX/src/buffering/ScbActor.cpp
new file mode 100644
index 00000000..9c91235a
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbActor.cpp
@@ -0,0 +1,84 @@
+// 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 "ScbBase.h"
+
+using namespace physx;
+using namespace Scb;
+
+using namespace physx;
+using namespace Scb;
+
+#include "ScbActor.h"
+#include "ScbRigidStatic.h"
+#include "ScbBody.h"
+#include "ScbParticleSystem.h"
+#include "ScbCloth.h"
+
+namespace physx
+{
+namespace Scb
+{
+
+Actor::Offsets::Offsets()
+{
+ size_t staticOffset = reinterpret_cast<size_t>(&(reinterpret_cast<Scb::RigidStatic*>(0)->getScStatic()));
+ size_t bodyOffset = reinterpret_cast<size_t>(&(reinterpret_cast<Scb::Body*>(0)->getScBody()));
+
+ scToScb[PxActorType::eRIGID_STATIC] = staticOffset;
+ scToScb[PxActorType::eRIGID_DYNAMIC] = bodyOffset;
+ scToScb[PxActorType::eARTICULATION_LINK] = bodyOffset;
+
+ scbToSc[ScbType::RIGID_STATIC] = staticOffset;
+ scbToSc[ScbType::BODY] = bodyOffset;
+ scbToSc[ScbType::BODY_FROM_ARTICULATION_LINK] = bodyOffset;
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ size_t particleOffset = reinterpret_cast<size_t>(&(reinterpret_cast<Scb::ParticleSystem*>(0)->getScParticleSystem()));
+ scToScb[PxActorType::ePARTICLE_FLUID] = particleOffset;
+ scToScb[PxActorType::ePARTICLE_SYSTEM] = particleOffset;
+ scbToSc[ScbType::PARTICLE_SYSTEM] = particleOffset;
+#endif
+
+#if PX_USE_CLOTH_API
+ size_t clothOffset = reinterpret_cast<size_t>(&(reinterpret_cast<Scb::Cloth*>(0)->getScCloth()));
+ scToScb[PxActorType::eCLOTH] = clothOffset;
+ scbToSc[ScbType::CLOTH] = clothOffset;
+#endif
+
+
+}
+
+
+
+
+const Actor::Offsets Actor::sOffsets;
+}
+}
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbActor.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbActor.h
new file mode 100644
index 00000000..364972b1
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbActor.h
@@ -0,0 +1,186 @@
+// 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_SCB_FSACTOR
+#define PX_PHYSICS_SCB_FSACTOR
+
+#include "ScActorCore.h"
+#include "PsUtilities.h"
+#include "ScbBase.h"
+#include "ScbDefs.h"
+
+#include "PxClient.h"
+
+namespace physx
+{
+namespace Scb
+{
+struct ActorBuffer
+{
+ template <PxU32 I, PxU32 Dummy> struct Fns {};
+ typedef Sc::ActorCore Core;
+ typedef ActorBuffer Buf;
+
+ SCB_REGULAR_ATTRIBUTE (0, PxActorFlags, ActorFlags)
+ SCB_REGULAR_ATTRIBUTE (1, PxDominanceGroup, DominanceGroup)
+ SCB_REGULAR_ATTRIBUTE (2, PxActorClientBehaviorFlags, ClientBehaviorFlags)
+
+ enum { AttrCount = 3 };
+
+protected:
+ ~ActorBuffer(){}
+};
+
+
+class Actor : public Base
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+
+ typedef ActorBuffer Buf;
+ typedef Sc::ActorCore Core;
+
+public:
+// PX_SERIALIZATION
+ Actor(const PxEMPTY) : Base(PxEmpty) {}
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+
+ PX_INLINE Actor() {}
+
+ //---------------------------------------------------------------------------------
+ // Wrapper for Sc::Actor interface
+ //---------------------------------------------------------------------------------
+ PX_INLINE PxActorFlags getActorFlags() const { return read<Buf::BF_ActorFlags>(); }
+ PX_INLINE void setActorFlags(PxActorFlags v);
+
+ PX_INLINE PxDominanceGroup getDominanceGroup() const { return read<Buf::BF_DominanceGroup>(); }
+ PX_INLINE void setDominanceGroup(PxDominanceGroup v) { write<Buf::BF_DominanceGroup>(v); }
+
+ PX_INLINE PxActorClientBehaviorFlags getClientBehaviorFlags() const { return read<Buf::BF_ClientBehaviorFlags>(); }
+ PX_INLINE void setClientBehaviorFlags(PxActorClientBehaviorFlags v){ write<Buf::BF_ClientBehaviorFlags>(v); }
+
+ PX_INLINE void setOwnerClient( PxClientID inId );
+ PX_INLINE PxClientID getOwnerClient() const { return getActorCore().getOwnerClient(); } //immutable, so this should be fine.
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+
+ PX_FORCE_INLINE const Core& getActorCore() const { return *reinterpret_cast<const Core*>(reinterpret_cast<size_t>(this) + sOffsets.scbToSc[getScbType()]); }
+ PX_FORCE_INLINE Core& getActorCore() { return *reinterpret_cast<Core*>(reinterpret_cast<size_t>(this) + sOffsets.scbToSc[getScbType()]); }
+
+ PX_FORCE_INLINE static const Actor& fromSc(const Core& a) { return *reinterpret_cast<const Actor*>(reinterpret_cast<size_t>(&a) - sOffsets.scToScb[a.getActorCoreType()]); }
+ PX_FORCE_INLINE static Actor& fromSc(Core &a) { return *reinterpret_cast<Actor*>(reinterpret_cast<size_t>(&a) - sOffsets.scToScb[a.getActorCoreType()]); }
+
+ PX_FORCE_INLINE PxActorType::Enum getActorType() const { return getActorCore().getActorCoreType(); }
+
+protected:
+ PX_INLINE void syncState();
+
+ //---------------------------------------------------------------------------------
+ // Infrastructure for regular attributes
+ //---------------------------------------------------------------------------------
+
+ struct Access: public BufferedAccess<Buf, Core, Actor> {};
+ template<PxU32 f> PX_FORCE_INLINE typename Buf::Fns<f,0>::Arg read() const { return Access::read<Buf::Fns<f,0> >(*this, getActorCore()); }
+ template<PxU32 f> PX_FORCE_INLINE void write(typename Buf::Fns<f,0>::Arg v) { Access::write<Buf::Fns<f,0> >(*this, getActorCore(), v); }
+ template<PxU32 f> PX_FORCE_INLINE void flush(Core& core, const Buf& buf) { Access::flush<Buf::Fns<f,0> >(*this, core, buf); }
+
+protected:
+ ~Actor() {}
+
+ struct Offsets
+ {
+ size_t scToScb[PxActorType::eACTOR_COUNT];
+ size_t scbToSc[ScbType::TYPE_COUNT];
+ Offsets();
+ };
+ static const Offsets sOffsets;
+};
+
+
+PX_INLINE void Actor::setActorFlags(PxActorFlags v)
+{
+#if PX_CHECKED
+ PxActorFlags aFlags = getActorFlags();
+ PxActorType::Enum aType = getActorType();
+ if ((!aFlags.isSet(PxActorFlag::eDISABLE_SIMULATION)) && v.isSet(PxActorFlag::eDISABLE_SIMULATION) &&
+ (aType != PxActorType::eRIGID_DYNAMIC) && (aType != PxActorType::eRIGID_STATIC))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxActor::setActorFlag: PxActorFlag::eDISABLE_SIMULATION is only supported by PxRigidDynamic and PxRigidStatic objects.");
+ }
+#endif
+
+ write<Buf::BF_ActorFlags>(v);
+}
+
+PX_INLINE void Actor::setOwnerClient( PxClientID inId )
+{
+ //This call is only valid if we aren't in a scene.
+ //Thus we can't be buffering yet
+ if (!isBuffering())
+ {
+ getActorCore().setOwnerClient( inId );
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Attempt to set the client id when an actor is buffering");
+ }
+}
+
+PX_INLINE void Actor::syncState()
+{
+ //this should be called from syncState() of derived classes
+
+ const PxU32 flags = getBufferFlags();
+ if (flags & (Buf::BF_ActorFlags|Buf::BF_DominanceGroup|Buf::BF_ClientBehaviorFlags))
+ {
+ Core& core = getActorCore();
+ Buf& buffer = *reinterpret_cast<Buf*>(getStream());
+
+ flush<Buf::BF_ActorFlags>(core, buffer);
+ flush<Buf::BF_DominanceGroup>(core, buffer);
+ flush<Buf::BF_ClientBehaviorFlags>(core, buffer);
+ }
+}
+
+} // namespace Scb
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbAggregate.cpp b/PhysX_3.4/Source/PhysX/src/buffering/ScbAggregate.cpp
new file mode 100644
index 00000000..22a26abd
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbAggregate.cpp
@@ -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.
+
+
+#include "ScbAggregate.h"
+#include "ScbActor.h"
+
+using namespace physx;
+
+
+void Scb::Aggregate::addActor(Scb::Actor& actor)
+{
+ const ControlState::Enum state = getControlState();
+
+ if(!isBufferingSpecial(state))
+ {
+ actor.getActorCore().setAggregateID(mAggregateID);
+ PvdAttachActorToAggregate( this, &actor );
+ PvdUpdateProperties( this );
+ }
+ else if ((state != ControlState::eREMOVE_PENDING)) // If the aggregate is pending for deletion, adding/removing an actor should not be double buffered because the aggregateID must not be set for the actors
+ {
+ // if available, search in list of removed actors to cover the remove-add case
+ Scb::AggregateBuffer* PX_RESTRICT bufferedData = getBufferedData();
+ if (bufferedData->removeBufferIdx != 0xffffffff)
+ {
+ Scb::Actor** removeBuffer = getScbScene()->getActorBuffer(bufferedData->removeBufferIdx);
+ for(PxU32 i=0; i < bufferedData->removeCount; i++)
+ {
+ if (removeBuffer[i] == &actor)
+ {
+ removeBuffer[i] = removeBuffer[bufferedData->removeCount - 1];
+ PX_ASSERT(bufferedData->removeCount > 0);
+ bufferedData->removeCount--;
+ break;
+ }
+ }
+ }
+
+ Scb::Actor** actorBuffer;
+ if (bufferedData->addBufferIdx == 0xffffffff)
+ {
+ actorBuffer = getScbScene()->allocActorBuffer(mMaxNbActors, bufferedData->addBufferIdx);
+ }
+ else
+ {
+ actorBuffer = getScbScene()->getActorBuffer(bufferedData->addBufferIdx);
+ }
+
+ PX_ASSERT(bufferedData->addCount < mMaxNbActors);
+ actorBuffer[bufferedData->addCount] = &actor;
+ bufferedData->addCount++;
+
+ if (state != ControlState::eINSERT_PENDING)
+ markUpdated(BF_ADD_ACTOR);
+ else
+ {
+ // Not a great solution but aggregates are special in the sense that even in the pending insert case, data needs to be double buffered
+ // (see isBufferingSpecial() for details)
+ setBufferFlag(BF_ADD_ACTOR);
+ }
+ }
+}
+
+
+void Scb::Aggregate::removeActor(Scb::Actor& actor, bool reinsert)
+{
+ const ControlState::Enum state = getControlState();
+ const ControlState::Enum actorState = actor.getControlState();
+
+ if(!isBufferingSpecial(state))
+ {
+ Sc::ActorCore& ac = actor.getActorCore();
+ ac.setAggregateID(PX_INVALID_U32);
+
+ if(getScbSceneForAPI() && reinsert)
+ {
+ ac.reinsertShapes();
+ }
+ }
+ else if ((state != ControlState::eREMOVE_PENDING))
+ {
+ // if available, search in list of added actors to cover the add-remove case
+ Scb::AggregateBuffer* PX_RESTRICT bufferedData = getBufferedData();
+ if (bufferedData->addBufferIdx != 0xffffffff)
+ {
+ Scb::Actor** addBuffer = getScbScene()->getActorBuffer(bufferedData->addBufferIdx);
+ for(PxU32 i=0; i < bufferedData->addCount; i++)
+ {
+ if (addBuffer[i] == &actor)
+ {
+ addBuffer[i] = addBuffer[bufferedData->addCount - 1];
+ PX_ASSERT(bufferedData->addCount > 0);
+ bufferedData->addCount--;
+ return; // It's fine to abort here because the aggregateID has not been set yet
+ }
+ }
+ }
+
+ Scb::Actor** actorBuffer;
+ if (bufferedData->removeBufferIdx == 0xffffffff)
+ {
+ actorBuffer = getScbScene()->allocActorBuffer(mMaxNbActors, bufferedData->removeBufferIdx);
+ }
+ else
+ {
+ actorBuffer = getScbScene()->getActorBuffer(bufferedData->removeBufferIdx);
+ }
+
+ PX_ASSERT(bufferedData->removeCount < mMaxNbActors);
+ actorBuffer[bufferedData->removeCount] = &actor;
+ bufferedData->removeCount++;
+
+ markUpdated(BF_REMOVE_ACTOR);
+ }
+
+ //Update pvd status if not buffer OR the actor release while aggregate is already in scene
+ if(!isBufferingSpecial(state)
+ || ((actorState == ControlState::eIN_SCENE || actorState == ControlState::eREMOVE_PENDING )
+ && state != ControlState::eINSERT_PENDING
+ && !reinsert))
+ {
+ PvdDetachActorFromAggregate( this, &actor );
+ PvdUpdateProperties( this );
+ }
+}
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbAggregate.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbAggregate.h
new file mode 100644
index 00000000..55911d22
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbAggregate.h
@@ -0,0 +1,249 @@
+// 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_SCB_AGGREGATE
+#define PX_PHYSICS_SCB_AGGREGATE
+
+#include "CmPhysXCommon.h"
+#include "PxAggregate.h"
+#include "ScbActor.h"
+#include "ScbAggregate.h"
+#include "ScbBase.h"
+
+// PX_SERIALIZATION
+#include "PxSerialFramework.h"
+//~PX_SERIALIZATION
+
+namespace physx
+{
+namespace Scb
+{
+
+class Actor;
+
+struct AggregateBuffer
+{
+ AggregateBuffer() : addBufferIdx(0xffffffff), addCount(0), removeBufferIdx(0xffffffff), removeCount(0) {}
+
+ PxU32 addBufferIdx;
+ PxU32 addCount;
+ PxU32 removeBufferIdx;
+ PxU32 removeCount;
+};
+
+
+class Aggregate : public Base
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+private:
+ enum BufferFlag
+ {
+ BF_ADD_ACTOR = (1 << 0),
+ BF_REMOVE_ACTOR = (1 << 1)
+ };
+
+public:
+
+// PX_SERIALIZATION
+ Aggregate(const PxEMPTY) : Base(PxEmpty) {}
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ PX_INLINE Aggregate(PxAggregate* px, PxU32 maxActors, bool selfCollision);
+ PX_INLINE ~Aggregate();
+
+ void addActor(Scb::Actor&);
+ void removeActor(Scb::Actor& actor, bool reinsert);
+
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+ PX_INLINE void syncState(Scb::Scene& scene);
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ PX_FORCE_INLINE PxU32 getMaxActorCount() const { return mMaxNbActors; }
+ PX_FORCE_INLINE bool getSelfCollide() const { return mSelfCollide; }
+ PX_FORCE_INLINE PxU32 getAggregateID() const { return mAggregateID; }
+ PX_FORCE_INLINE void setAggregateID(PxU32 cid) { mAggregateID = cid; }
+
+ PX_FORCE_INLINE bool isBufferingSpecial(ControlState::Enum state) const;
+
+ PxAggregate* mPxAggregate; // Back pointer
+private:
+ PxU32 mAggregateID;
+ PxU32 mMaxNbActors;
+ bool mSelfCollide;
+
+ PX_FORCE_INLINE const Scb::AggregateBuffer* getBufferedData() const { return reinterpret_cast<const Scb::AggregateBuffer*>(getStream()); }
+ PX_FORCE_INLINE Scb::AggregateBuffer* getBufferedData() { return reinterpret_cast<Scb::AggregateBuffer*>(getStream()); }
+};
+
+
+PX_INLINE Aggregate::Aggregate(PxAggregate* px, PxU32 maxActors, bool selfCollision) :
+ mPxAggregate (px),
+ mAggregateID (PX_INVALID_U32),
+ mMaxNbActors (maxActors),
+ mSelfCollide (selfCollision)
+{
+ setScbType(ScbType::AGGREGATE);
+}
+
+
+PX_INLINE Aggregate::~Aggregate()
+{
+}
+
+PX_FORCE_INLINE bool Aggregate::isBufferingSpecial(ControlState::Enum state) const
+{
+ // A special version of the buffer check is needed for aggregates because it is not fine for adding/removing
+ // an actor to be not double buffered if the aggregate is pending for insertion.
+ // For example: Adding an actor can not be processed if the aggregate is pending for insertion because the aggregateID
+ // is not yet available (an there is no Sc::Aggregate object to store the actors)
+
+ Scb::Scene* scbScene = getScbSceneForAPI();
+ return state == ControlState::eREMOVE_PENDING || // pending remove not possible if not buffered
+ (scbScene && scbScene->isPhysicsBuffering());
+}
+
+//--------------------------------------------------------------
+//
+// PVD Events
+//
+//--------------------------------------------------------------
+
+namespace
+{
+#if PX_SUPPORT_PVD
+ PX_FORCE_INLINE void PvdAttachActorToAggregate(Scb::Aggregate* pAggregate, Scb::Actor* pScbActor)
+ {
+ Scb::Scene* scbScene = pAggregate->getScbSceneForAPI();
+ if( scbScene/* && scbScene->getScenePvdClient().isInstanceValid(pAggregate)*/)
+ {
+ scbScene->getScenePvdClient().attachAggregateActor( pAggregate, pScbActor );
+ }
+ }
+
+ PX_FORCE_INLINE void PvdDetachActorFromAggregate(Scb::Aggregate* pAggregate, Scb::Actor* pScbActor)
+ {
+ Scb::Scene* scbScene = pAggregate->getScbSceneForAPI();
+ if( scbScene/*&& scbScene->getScenePvdClient().isInstanceValid(pAggregate)*/)
+ {
+ scbScene->getScenePvdClient().detachAggregateActor( pAggregate, pScbActor );
+ }
+ }
+
+ PX_FORCE_INLINE void PvdUpdateProperties(Scb::Aggregate* pAggregate)
+ {
+ Scb::Scene* scbScene = pAggregate->getScbSceneForAPI();
+ if( scbScene /*&& scbScene->getScenePvdClient().isInstanceValid(pAggregate)*/)
+ {
+ scbScene->getScenePvdClient().updatePvdProperties( pAggregate );
+ }
+ }
+#else
+#define PvdAttachActorToAggregate(aggregate, scbActor) {}
+#define PvdDetachActorFromAggregate(aggregate, scbActor) {}
+#define PvdUpdateProperties(aggregate) {}
+#endif
+}
+
+//--------------------------------------------------------------
+//
+// Data synchronization
+//
+//--------------------------------------------------------------
+
+PX_INLINE void Aggregate::syncState(Scb::Scene& scene)
+{
+ PxU32 flags = getBufferFlags();
+
+ enum AggregateSyncDirtyType
+ {
+ DIRTY_NONE = 0,
+ DIRTY_ADD_ACTOR = 1<<0,
+ DIRTY_REMOVE_ACTOR = 1<<1
+ };
+
+ PxU32 dirtyType = DIRTY_NONE;
+
+ if (flags)
+ {
+ const Scb::AggregateBuffer* PX_RESTRICT bufferedData = getBufferedData();
+
+ if (flags & BF_ADD_ACTOR)
+ {
+ dirtyType |= DIRTY_ADD_ACTOR;
+
+ Scb::Actor* const* actorBuffer = scene.getActorBuffer(bufferedData->addBufferIdx);
+
+ PX_ASSERT(mAggregateID != PX_INVALID_U32);
+ for(PxU32 i=0; i < bufferedData->addCount; i++)
+ {
+ actorBuffer[i]->getActorCore().setAggregateID(mAggregateID);
+ PvdAttachActorToAggregate( this, actorBuffer[i] );
+ }
+ }
+
+ if (flags & BF_REMOVE_ACTOR)
+ {
+ dirtyType |= DIRTY_REMOVE_ACTOR;
+ Scb::Actor* const* actorBuffer = scene.getActorBuffer(bufferedData->removeBufferIdx);
+
+ for(PxU32 i=0; i < bufferedData->removeCount; i++)
+ {
+ const ControlState::Enum state = actorBuffer[i]->getControlState();
+
+ Sc::ActorCore& ac = actorBuffer[i]->getActorCore();
+ ac.setAggregateID(PX_INVALID_U32);
+ if(state != ControlState::eREMOVE_PENDING)
+ PvdDetachActorFromAggregate( this, actorBuffer[i] );
+ if (state == ControlState::eINSERT_PENDING || state == ControlState::eIN_SCENE)
+ ac.reinsertShapes();
+ }
+ }
+
+ if(dirtyType != DIRTY_NONE)
+ PvdUpdateProperties( this );
+ }
+
+ postSyncState();
+}
+
+}// namespace Scb
+}// namespace physx
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbArticulation.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbArticulation.h
new file mode 100644
index 00000000..424cf34b
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbArticulation.h
@@ -0,0 +1,353 @@
+// 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_SCB_ARTICULATION
+#define PX_PHYSICS_SCB_ARTICULATION
+
+#include "ScArticulationCore.h"
+#include "ScbBase.h"
+#include "ScbDefs.h"
+
+namespace physx
+{
+
+namespace Scb
+{
+
+struct ArticulationBuffer
+{
+ template <PxU32 I, PxU32 Dummy> struct Fns {};
+ typedef Sc::ArticulationCore Core;
+ typedef ArticulationBuffer Buf;
+
+ SCB_REGULAR_ATTRIBUTE(0, PxU32, InternalDriveIterations)
+ SCB_REGULAR_ATTRIBUTE(1, PxU32, ExternalDriveIterations)
+ SCB_REGULAR_ATTRIBUTE(2, PxU32, MaxProjectionIterations)
+ SCB_REGULAR_ATTRIBUTE(3, PxReal, SeparationTolerance)
+ SCB_REGULAR_ATTRIBUTE(4, PxReal, SleepThreshold)
+ SCB_REGULAR_ATTRIBUTE(5, PxU16, SolverIterationCounts)
+ SCB_REGULAR_ATTRIBUTE(6, PxReal, FreezeThreshold)
+
+ enum { BF_WakeCounter = 1<<7 };
+ enum { BF_PutToSleep = 1<<8 };
+ enum { BF_WakeUp = 1<<9 };
+
+};
+
+class Articulation : public Base
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+
+ typedef ArticulationBuffer Buf;
+ typedef Sc::ArticulationCore Core;
+
+// PX_SERIALIZATION
+public:
+ Articulation(const PxEMPTY) : Base(PxEmpty), mArticulation(PxEmpty), mBufferedIsSleeping(1) {}
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+
+private:
+
+public:
+ PX_INLINE Articulation();
+ PX_INLINE ~Articulation() {}
+
+ //---------------------------------------------------------------------------------
+ // Wrapper for Sc::Articulation interface
+ //---------------------------------------------------------------------------------
+
+ PX_INLINE PxU32 getInternalDriveIterations() const { return read<Buf::BF_InternalDriveIterations>(); }
+ PX_INLINE void setInternalDriveIterations(const PxU32 v) { write<Buf::BF_InternalDriveIterations>(v); }
+
+ PX_INLINE PxU32 getExternalDriveIterations() const { return read<Buf::BF_ExternalDriveIterations>(); }
+ PX_INLINE void setExternalDriveIterations(const PxU32 v) { write<Buf::BF_ExternalDriveIterations>(v); }
+
+ PX_INLINE PxU32 getMaxProjectionIterations() const { return read<Buf::BF_MaxProjectionIterations>(); }
+ PX_INLINE void setMaxProjectionIterations(const PxU32 v) { write<Buf::BF_MaxProjectionIterations>(v); }
+
+ PX_INLINE PxU16 getSolverIterationCounts() const { return read<Buf::BF_SolverIterationCounts>(); }
+ PX_INLINE void setSolverIterationCounts(PxU16 v) { write<Buf::BF_SolverIterationCounts>(v); }
+
+ PX_INLINE PxReal getSeparationTolerance() const { return read<Buf::BF_SeparationTolerance>(); }
+ PX_INLINE void setSeparationTolerance(const PxReal v) { write<Buf::BF_SeparationTolerance>(v); }
+
+ PX_INLINE PxReal getSleepThreshold() const { return read<Buf::BF_SleepThreshold>(); }
+ PX_INLINE void setSleepThreshold(const PxReal v) { write<Buf::BF_SleepThreshold>(v); }
+
+ PX_INLINE PxReal getFreezeThreshold() const { return read<Buf::BF_SleepThreshold>(); }
+ PX_INLINE void setFreezeThreshold(const PxReal v) { write<Buf::BF_SleepThreshold>(v); }
+
+ PX_INLINE PxReal getWakeCounter() const { return mBufferedWakeCounter; }
+ PX_INLINE void setWakeCounter(const PxReal v);
+
+ PX_FORCE_INLINE void wakeUp();
+ PX_FORCE_INLINE void putToSleep();
+ PX_FORCE_INLINE bool isSleeping() const { return (mBufferedIsSleeping != 0); }
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+ PX_INLINE void syncState();
+
+ PX_FORCE_INLINE const Sc::ArticulationCore& getScArticulation() const { return mArticulation; } // Only use if you know what you're doing!
+ PX_FORCE_INLINE Sc::ArticulationCore& getScArticulation() { return mArticulation; } // Only use if you know what you're doing!
+
+ PX_FORCE_INLINE static Articulation& fromSc(Core &a) { return *reinterpret_cast<Articulation*>(reinterpret_cast<PxU8*>(&a)-getScOffset()); }
+ PX_FORCE_INLINE static const Articulation& fromSc(const Core &a) { return *reinterpret_cast<const Articulation*>(reinterpret_cast<const PxU8*>(&a)-getScOffset()); }
+ static size_t getScOffset()
+ {
+ return reinterpret_cast<size_t>(&reinterpret_cast<Articulation*>(0)->mArticulation);
+ }
+
+ PX_FORCE_INLINE void wakeUpInternal(PxReal wakeCounter);
+
+ PX_FORCE_INLINE void initBufferedState();
+ PX_FORCE_INLINE void clearBufferedState();
+ PX_FORCE_INLINE void clearBufferedSleepStateChange();
+
+private:
+ Sc::ArticulationCore mArticulation;
+ PxReal mBufferedWakeCounter;
+ PxU8 mBufferedIsSleeping;
+
+ PX_FORCE_INLINE const Buf* getArticulationBuffer() const { return reinterpret_cast<const Buf*>(getStream()); }
+ PX_FORCE_INLINE Buf* getArticulationBuffer() { return reinterpret_cast<Buf*>(getStream()); }
+
+
+ //---------------------------------------------------------------------------------
+ // Infrastructure for regular attributes
+ //---------------------------------------------------------------------------------
+
+ struct Access: public BufferedAccess<Buf, Core, Articulation> {};
+ template<PxU32 f> PX_FORCE_INLINE typename Buf::Fns<f,0>::Arg read() const { return Access::read<Buf::Fns<f,0> >(*this, mArticulation); }
+ template<PxU32 f> PX_FORCE_INLINE void write(typename Buf::Fns<f,0>::Arg v) { Access::write<Buf::Fns<f,0> >(*this, mArticulation, v); }
+ template<PxU32 f> PX_FORCE_INLINE void flush(const Buf& buf) { Access::flush<Buf::Fns<f,0> >(*this, mArticulation, buf); }
+
+};
+
+
+Articulation::Articulation()
+{
+ setScbType(ScbType::ARTICULATION);
+ mBufferedWakeCounter = getScArticulation().getWakeCounter();
+ mBufferedIsSleeping = 1; // this is the specified value for free standing objects
+}
+
+
+PX_INLINE void Articulation::setWakeCounter(PxReal counter)
+{
+ mBufferedWakeCounter = counter;
+
+ if (!isBuffering())
+ {
+ if (getScbScene() && (counter > 0.0f))
+ mBufferedIsSleeping = 0;
+
+ getScArticulation().setWakeCounter(counter);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ if (counter > 0.0f)
+ {
+ mBufferedIsSleeping = 0;
+ markUpdated(Buf::BF_WakeUp | Buf::BF_WakeCounter);
+ resetBufferFlag(Buf::BF_PutToSleep);
+ }
+ else
+ markUpdated(Buf::BF_WakeCounter);
+ }
+}
+
+
+PX_FORCE_INLINE void Articulation::wakeUp()
+{
+ Scene* scene = getScbScene();
+ PX_ASSERT(scene); // only allowed for an object in a scene
+
+ wakeUpInternal(scene->getWakeCounterResetValue());
+}
+
+
+PX_FORCE_INLINE void Articulation::wakeUpInternal(PxReal wakeCounter)
+{
+ PX_ASSERT(getScbScene());
+
+ mBufferedWakeCounter = wakeCounter;
+
+ mBufferedIsSleeping = 0;
+ if (!isBuffering())
+ {
+ getScArticulation().wakeUp(wakeCounter);
+ }
+ else
+ {
+ markUpdated(Buf::BF_WakeUp | Buf::BF_WakeCounter);
+ resetBufferFlag(Buf::BF_PutToSleep);
+ }
+}
+
+
+PX_FORCE_INLINE void Articulation::putToSleep()
+{
+ mBufferedWakeCounter = 0.0f;
+
+ mBufferedIsSleeping = 1;
+ if (!isBuffering())
+ {
+ getScArticulation().putToSleep();
+ }
+ else
+ {
+ markUpdated(Buf::BF_PutToSleep | Buf::BF_WakeCounter);
+ resetBufferFlag(Buf::BF_WakeUp);
+ }
+}
+
+
+PX_FORCE_INLINE void Articulation::initBufferedState()
+{
+ PX_ASSERT(mBufferedIsSleeping); // this method is only meant to get called when an object is added to the scene
+
+ if (getWakeCounter() == 0.0f)
+ mBufferedIsSleeping = 1;
+ else
+ mBufferedIsSleeping = 0;
+ // note: to really know whether the articulation is awake/asleep on insertion, we need to go through every link and check whether any of them has
+ // a parameter setup that keeps it alive. However, the links get added after the articulation, so we do not test those here. After the links
+ // are added, an additional check will wake the articulation up if necessary.
+}
+
+
+PX_FORCE_INLINE void Articulation::clearBufferedState()
+{
+ mBufferedIsSleeping = 1; // the expected state when an object gets removed from the scene
+}
+
+
+PX_FORCE_INLINE void Articulation::clearBufferedSleepStateChange()
+{
+ resetBufferFlag(Buf::BF_WakeUp | Buf::BF_PutToSleep);
+}
+
+//--------------------------------------------------------------
+//
+// Data synchronization
+//
+//--------------------------------------------------------------
+
+PX_INLINE void Articulation::syncState()
+{
+ // see comments in Body::syncState
+ PX_ASSERT( (getControlState() != ControlState::eREMOVE_PENDING) ||
+ (mBufferedIsSleeping && (!isBuffered(Buf::BF_WakeUp | Buf::BF_PutToSleep))) );
+
+ PxU32 flags = getBufferFlags();
+
+ //----
+
+ if ((flags & Buf::BF_WakeCounter) == 0)
+ mBufferedWakeCounter = getScArticulation().getWakeCounter();
+ else if (!(flags & (Buf::BF_WakeUp | Buf::BF_PutToSleep))) // if there has been at least one buffered sleep state transition, then there is no use in adjusting the wake counter separately because it will
+ // get done in the sleep state update.
+ {
+ PX_ASSERT(mBufferedWakeCounter == 0.0f); // a wake counter change is always connected to a sleep state change, except one case: if setWakeCounter(0.0f) was called
+
+ getScArticulation().setWakeCounter(mBufferedWakeCounter);
+ }
+
+ //----
+
+ bool isSimObjectSleeping = getScArticulation().isSleeping();
+ if ((flags & (Buf::BF_WakeUp | Buf::BF_PutToSleep)) == 0)
+ {
+ if (getControlState() != ControlState::eREMOVE_PENDING) // we do not want the simulation sleep state to take effect if the object was removed (free standing objects have buffered state sleeping)
+ mBufferedIsSleeping = PxU8(isSimObjectSleeping);
+ else
+ PX_ASSERT(mBufferedIsSleeping); // this must get set immediately at remove
+ }
+ else
+ {
+ PX_ASSERT(flags & Buf::BF_WakeCounter); // sleep state transitions always mark the wake counter dirty
+ PX_ASSERT(getControlState() != ControlState::eREMOVE_PENDING); // removing an object should clear pending wakeUp/putToSleep operations since the state for a free standing object gets set according to specification.
+
+ if (flags & Buf::BF_PutToSleep)
+ {
+ PX_ASSERT(mBufferedIsSleeping);
+ PX_ASSERT(!(flags & Buf::BF_WakeUp));
+ PX_ASSERT(mBufferedWakeCounter == 0.0f);
+ getScArticulation().putToSleep();
+ }
+ else
+ {
+ PX_ASSERT(!mBufferedIsSleeping);
+ PX_ASSERT(flags & Buf::BF_WakeUp);
+
+ getScArticulation().wakeUp(mBufferedWakeCounter);
+ }
+ }
+
+ //----
+
+ if(flags&~(Buf::BF_WakeCounter|Buf::BF_WakeUp|Buf::BF_PutToSleep)) // Optimization to avoid all the if-statements below if possible
+ {
+ const Buf* PX_RESTRICT buffer = getArticulationBuffer();
+
+ flush<Buf::BF_ExternalDriveIterations>(*buffer);
+ flush<Buf::BF_InternalDriveIterations>(*buffer);
+ flush<Buf::BF_MaxProjectionIterations>(*buffer);
+ flush<Buf::BF_SeparationTolerance>(*buffer);
+ flush<Buf::BF_SleepThreshold>(*buffer);
+ flush<Buf::BF_SolverIterationCounts>(*buffer);
+ flush<Buf::BF_FreezeThreshold>(*buffer);
+ }
+
+ // --------------
+ // postconditions
+ //
+ PX_ASSERT((getControlState() != ControlState::eREMOVE_PENDING) || mBufferedIsSleeping); // nothing in this method should change this
+ //
+ // postconditions
+ // --------------
+
+ postSyncState();
+}
+
+} // namespace Scb
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbArticulationJoint.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbArticulationJoint.h
new file mode 100644
index 00000000..04a49f1c
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbArticulationJoint.h
@@ -0,0 +1,283 @@
+// 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_SCB_ARTICULATION_JOINT
+#define PX_PHYSICS_SCB_ARTICULATION_JOINT
+
+#include "ScArticulationJointCore.h"
+#include "ScbBody.h"
+#include "ScbBase.h"
+#include "ScbDefs.h"
+
+namespace physx
+{
+namespace Scb
+{
+
+struct ArticulationJointBuffer
+{
+ template <PxU32 I, PxU32 Dummy> struct Fns {};
+ typedef Sc::ArticulationJointCore Core;
+ typedef ArticulationJointBuffer Buf;
+
+ SCB_REGULAR_ATTRIBUTE(0, PxTransform, ParentPose)
+ SCB_REGULAR_ATTRIBUTE(1, PxTransform, ChildPose)
+ SCB_REGULAR_ATTRIBUTE(2, PxQuat, TargetOrientation)
+ SCB_REGULAR_ATTRIBUTE(3, PxVec3, TargetVelocity)
+ SCB_REGULAR_ATTRIBUTE(4, PxReal, Stiffness)
+ SCB_REGULAR_ATTRIBUTE(5, PxReal, Damping)
+ SCB_REGULAR_ATTRIBUTE(6, PxReal, InternalCompliance)
+ SCB_REGULAR_ATTRIBUTE(7, PxReal, ExternalCompliance)
+ SCB_REGULAR_ATTRIBUTE(8, PxReal, SwingLimitContactDistance)
+ SCB_REGULAR_ATTRIBUTE(9, bool, SwingLimitEnabled)
+ SCB_REGULAR_ATTRIBUTE(10, PxReal, TangentialStiffness)
+ SCB_REGULAR_ATTRIBUTE(11, PxReal, TangentialDamping)
+ SCB_REGULAR_ATTRIBUTE(12, PxReal, TwistLimitContactDistance)
+ SCB_REGULAR_ATTRIBUTE(13, bool, TwistLimitEnabled)
+ SCB_REGULAR_ATTRIBUTE(14, PxArticulationJointDriveType::Enum, DriveType)
+
+ enum { BF_SwingLimit = 1<<15 };
+ enum { BF_TwistLimit = 1<<16 };
+
+ PxReal mSwingLimitY;
+ PxReal mSwingLimitZ;
+ PxReal mTwistLimitLower;
+ PxReal mTwistLimitUpper;
+};
+
+class ArticulationJoint : public Base
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+
+ typedef ArticulationJointBuffer Buf;
+ typedef Sc::ArticulationJointCore Core;
+
+public:
+// PX_SERIALIZATION
+ ArticulationJoint(const PxEMPTY) : Base(PxEmpty), mJoint(PxEmpty) {}
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+
+ PX_INLINE ArticulationJoint(const PxTransform& parentFrame,
+ const PxTransform& childFrame);
+ PX_INLINE ~ArticulationJoint();
+
+ //---------------------------------------------------------------------------------
+ // Wrapper for Sc::ArticulationJoint interface
+ //---------------------------------------------------------------------------------
+
+ PX_INLINE PxTransform getParentPose() const { return read<Buf::BF_ParentPose>(); }
+ PX_INLINE void setParentPose(const PxTransform& v) { write<Buf::BF_ParentPose>(v); }
+
+ PX_INLINE PxTransform getChildPose() const { return read<Buf::BF_ChildPose>(); }
+ PX_INLINE void setChildPose(const PxTransform& v) { write<Buf::BF_ChildPose>(v); }
+
+ PX_INLINE PxQuat getTargetOrientation() const { return read<Buf::BF_TargetOrientation>(); }
+ PX_INLINE void setTargetOrientation(const PxQuat& v) { write<Buf::BF_TargetOrientation>(v); }
+
+ PX_INLINE PxVec3 getTargetVelocity() const { return read<Buf::BF_TargetVelocity>(); }
+ PX_INLINE void setTargetVelocity(const PxVec3& v) { write<Buf::BF_TargetVelocity>(v); }
+
+ PX_INLINE PxReal getStiffness() const { return read<Buf::BF_Stiffness>(); }
+ PX_INLINE void setStiffness(PxReal v) { write<Buf::BF_Stiffness>(v); }
+
+ PX_INLINE PxReal getDamping() const { return read<Buf::BF_Damping>(); }
+ PX_INLINE void setDamping(PxReal v) { write<Buf::BF_Damping>(v); }
+
+ PX_INLINE PxReal getInternalCompliance() const { return read<Buf::BF_InternalCompliance>(); }
+ PX_INLINE void setInternalCompliance(PxReal v) { write<Buf::BF_InternalCompliance>(v); }
+
+ PX_INLINE PxReal getExternalCompliance() const { return read<Buf::BF_ExternalCompliance>(); }
+ PX_INLINE void setExternalCompliance(PxReal v) { write<Buf::BF_ExternalCompliance>(v); }
+
+ PX_INLINE PxReal getTangentialStiffness() const { return read<Buf::BF_TangentialStiffness>(); }
+ PX_INLINE void setTangentialStiffness(PxReal v) { write<Buf::BF_TangentialStiffness>(v); }
+
+ PX_INLINE PxReal getTangentialDamping() const { return read<Buf::BF_TangentialDamping>(); }
+ PX_INLINE void setTangentialDamping(PxReal v) { write<Buf::BF_TangentialDamping>(v); }
+
+ PX_INLINE PxReal getSwingLimitContactDistance() const { return read<Buf::BF_SwingLimitContactDistance>(); }
+ PX_INLINE void setSwingLimitContactDistance(PxReal v) { write<Buf::BF_SwingLimitContactDistance>(v); }
+
+ PX_INLINE PxReal getTwistLimitContactDistance() const { return read<Buf::BF_TwistLimitContactDistance>(); }
+ PX_INLINE void setTwistLimitContactDistance(PxReal v) { write<Buf::BF_TwistLimitContactDistance>(v); }
+
+ PX_INLINE PxArticulationJointDriveType::Enum
+ getDriveType() const { return read<Buf::BF_DriveType>(); }
+ PX_INLINE void setDriveType(PxArticulationJointDriveType::Enum v)
+ { write<Buf::BF_DriveType>(v); }
+
+ PX_INLINE bool getSwingLimitEnabled() const { return read<Buf::BF_SwingLimitEnabled>(); }
+ PX_INLINE void setSwingLimitEnabled(bool v) { write<Buf::BF_SwingLimitEnabled>(v); }
+
+ PX_INLINE bool getTwistLimitEnabled() const { return read<Buf::BF_TwistLimitEnabled>(); }
+ PX_INLINE void setTwistLimitEnabled(bool v) { write<Buf::BF_TwistLimitEnabled>(v); }
+
+ PX_INLINE void getSwingLimit(PxReal& yLimit, PxReal& zLimit) const;
+ PX_INLINE void setSwingLimit(PxReal yLimit, PxReal zLimit);
+
+ PX_INLINE void getTwistLimit(PxReal &lower, PxReal &upper) const;
+ PX_INLINE void setTwistLimit(PxReal lower, PxReal upper);
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+ PX_INLINE void syncState();
+
+ PX_FORCE_INLINE const Core& getScArticulationJoint() const { return mJoint; } // Only use if you know what you're doing!
+ PX_FORCE_INLINE Core& getScArticulationJoint() { return mJoint; } // Only use if you know what you're doing!
+
+private:
+ Core mJoint;
+
+ PX_FORCE_INLINE const Buf* getBuffer() const { return reinterpret_cast<const Buf*>(getStream()); }
+ PX_FORCE_INLINE Buf* getBuffer() { return reinterpret_cast<Buf*>(getStream()); }
+
+ //---------------------------------------------------------------------------------
+ // Infrastructure for regular attributes
+ //---------------------------------------------------------------------------------
+
+ struct Access: public BufferedAccess<Buf, Core, ArticulationJoint> {};
+ template<PxU32 f> PX_FORCE_INLINE typename Buf::Fns<f,0>::Arg read() const { return Access::read<Buf::Fns<f,0> >(*this, mJoint); }
+ template<PxU32 f> PX_FORCE_INLINE void write(typename Buf::Fns<f,0>::Arg v) { Access::write<Buf::Fns<f,0> >(*this, mJoint, v); }
+ template<PxU32 f> PX_FORCE_INLINE void flush(const Buf& buf) { Access::flush<Buf::Fns<f,0> >(*this, mJoint, buf); }
+};
+
+
+ArticulationJoint::ArticulationJoint(const PxTransform& parentFrame,
+ const PxTransform& childFrame) :
+ mJoint(parentFrame, childFrame)
+{
+ setScbType(ScbType::ARTICULATION_JOINT);
+}
+
+
+ArticulationJoint::~ArticulationJoint()
+{
+}
+
+PX_INLINE void ArticulationJoint::getSwingLimit(PxReal &yLimit, PxReal &zLimit) const
+{
+ if (isBuffered(Buf::BF_SwingLimit))
+ {
+ yLimit = getBuffer()->mSwingLimitY;
+ zLimit = getBuffer()->mSwingLimitZ;
+ }
+ else
+ getScArticulationJoint().getSwingLimit(yLimit, zLimit);
+}
+
+
+PX_INLINE void ArticulationJoint::setSwingLimit(PxReal yLimit, PxReal zLimit)
+{
+ if (!isBuffering())
+ getScArticulationJoint().setSwingLimit(yLimit, zLimit);
+ else
+ {
+ getBuffer()->mSwingLimitY = yLimit;
+ getBuffer()->mSwingLimitZ = zLimit;
+ markUpdated(Buf::BF_SwingLimit);
+ }
+}
+
+
+PX_INLINE void ArticulationJoint::getTwistLimit(PxReal &lower, PxReal &upper) const
+{
+ if (isBuffered(Buf::BF_TwistLimit))
+ {
+ lower = getBuffer()->mTwistLimitLower;
+ upper = getBuffer()->mTwistLimitUpper;
+ }
+ else
+ mJoint.getTwistLimit(lower, upper);
+}
+
+
+PX_INLINE void ArticulationJoint::setTwistLimit(PxReal lower, PxReal upper)
+{
+ if (!isBuffering())
+ mJoint.setTwistLimit(lower, upper);
+ else
+ {
+ getBuffer()->mTwistLimitLower = lower;
+ getBuffer()->mTwistLimitUpper = upper;
+ markUpdated(Buf::BF_TwistLimit);
+ }
+}
+
+
+//--------------------------------------------------------------
+//
+// Data synchronization
+//
+//--------------------------------------------------------------
+
+PX_INLINE void ArticulationJoint::syncState()
+{
+ PxU32 flags = getBufferFlags();
+ if(flags) // Optimization to avoid all the if-statements below if possible
+ {
+ const Buf& buffer = *getBuffer();
+
+ flush<Buf::BF_ParentPose>(buffer);
+ flush<Buf::BF_ChildPose>(buffer);
+ flush<Buf::BF_TargetOrientation>(buffer);
+ flush<Buf::BF_TargetVelocity>(buffer);
+ flush<Buf::BF_Stiffness>(buffer);
+ flush<Buf::BF_Damping>(buffer);
+ flush<Buf::BF_InternalCompliance>(buffer);
+ flush<Buf::BF_ExternalCompliance>(buffer);
+ flush<Buf::BF_SwingLimitContactDistance>(buffer);
+ flush<Buf::BF_SwingLimitEnabled>(buffer);
+ flush<Buf::BF_TwistLimitContactDistance>(buffer);
+ flush<Buf::BF_TwistLimitEnabled>(buffer);
+ flush<Buf::BF_TangentialStiffness>(buffer);
+ flush<Buf::BF_TangentialDamping>(buffer);
+
+ if (isBuffered(Buf::BF_SwingLimit))
+ getScArticulationJoint().setSwingLimit( buffer.mSwingLimitY, buffer.mSwingLimitZ);
+
+ if (isBuffered(Buf::BF_TwistLimit))
+ getScArticulationJoint().setTwistLimit( buffer.mTwistLimitLower, buffer.mTwistLimitUpper);
+ }
+
+ postSyncState();
+}
+
+} // namespace Scb
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbBase.cpp b/PhysX_3.4/Source/PhysX/src/buffering/ScbBase.cpp
new file mode 100644
index 00000000..fb23dad6
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbBase.cpp
@@ -0,0 +1,48 @@
+// 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 "ScbBase.h"
+#include "ScbNpDeps.h"
+
+using namespace physx;
+using namespace Scb;
+
+void Base::destroy()
+{
+ if(!isBuffering())
+ NpDestroy(*this);
+ else
+ {
+ // Schedule for destroy
+ PX_ASSERT(!(getControlFlags() & ControlFlag::eIS_RELEASED));
+ PX_ASSERT(getControlState() == ControlState::eREMOVE_PENDING);
+ setControlFlag(ControlFlag::eIS_RELEASED);
+ }
+}
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbBase.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbBase.h
new file mode 100644
index 00000000..15fb0f75
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbBase.h
@@ -0,0 +1,333 @@
+// 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_SCB_BASE
+#define PX_PHYSICS_SCB_BASE
+
+#include "CmPhysXCommon.h"
+#include "ScbScene.h"
+
+namespace physx
+{
+
+#if PX_SUPPORT_PVD
+ // PT: updatePvdProperties() is overloaded and the compiler needs to know 'this' type to do the right thing.
+ // Thus we can't just move this as an inlined Base function.
+ #define UPDATE_PVD_PROPERTIES_OBJECT() { \
+ Scb::Scene* scene_ = getScbSceneForAPI(); \
+ if(scene_ && !insertPending() ) \
+ scene_->getScenePvdClient().updatePvdProperties(this); }
+#else
+ #define UPDATE_PVD_PROPERTIES_OBJECT() {}
+#endif
+
+namespace Scb
+{
+ struct ControlState
+ {
+ enum Enum
+ {
+ /**
+ \brief The object is not in the scene.
+
+ The object has not been added to a scene yet. This is the default when an object gets created.
+
+ In this state...
+ \li ...user changes get written to Core directly.
+ \li ...the object can not be in the list of dirty objects.
+ \li ...the object can not be marked as eIS_UPDATED or eIS_RELEASED.
+ */
+ eNOT_IN_SCENE = 0,
+
+ /**
+ \brief The object waits to get inserted into the scene internally.
+
+ The object has been added to the scene while the simulation is running and is waiting to get fully registered in all layers.
+
+ In this state...
+ \li ...user changes get written to Core directly (since the object has not yet registered in the inner layers, hence, will not get accessed internally).
+ \li ...the object is in the list of dirty objects.
+ \li ...the object can not be marked as eIS_UPDATED or eIS_RELEASED.
+ */
+ eINSERT_PENDING = 1,
+
+ /**
+ \brief The object is registered in the scene internally.
+
+ The object has been added to the scene and is fully registered in all layers.
+
+ In this state...
+ \li ...user changes get written to a buffer object and get synced with Core at a sync point.
+ \li ...the object can be in the list of dirty objects.
+ \li ...the object can be marked as eIS_UPDATED but not eIS_RELEASED.
+ */
+ eIN_SCENE = 2,
+
+ /**
+ \brief The object waits to get removed from the scene internally.
+
+ The object is in the scene and fully registered in all layers but has been removed while the simulation is running and is now
+ waiting to get unregistered from all layers.
+
+ In this state...
+ \li ...user changes get written to a buffer object and get synced with Core at a sync point.
+ \li ...the object is in the list of dirty objects.
+ \li ...the object can be marked as eIS_UPDATED or eIS_RELEASED.
+ */
+ eREMOVE_PENDING = 3
+ };
+ };
+
+ struct ControlFlag
+ {
+ enum Enum
+ {
+ /**
+ \brief An object property/state has been changed.
+
+ A property/state of the object has been changed and needs to get synced to Core. Insertion & removal don't count.
+ */
+ eIS_UPDATED = 1,
+
+ /**
+ \brief The object has been released.
+
+ The object has not just been removed from the scene it has been released as well. The object will get destroyed after the sync has been completed.
+ */
+ eIS_RELEASED = 2
+ };
+ };
+
+
+ /**
+ \brief Base class for objects that should support buffering.
+
+ This class has members to track the buffering related object state and mark which properties have been changed and need to get synced at sync points.
+ */
+ class Base
+ {
+ //= ATTENTION! =====================================================================================
+ // Changing the data layout of this class breaks the binary serialization format. See comments for
+ // PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+ // function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+ // accordingly.
+ //==================================================================================================
+
+ protected:
+// No-copy
+ Base(const Base& c);
+ Base& operator=(const Base& c);
+ public:
+
+// PX_SERIALIZATION
+ Base(const PxEMPTY) :
+ mScene (NULL),
+ mStreamPtr(NULL)
+ {
+ resetAllBufferFlags();
+ resetControl(ControlState::eNOT_IN_SCENE);
+ }
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ Base() :
+ mScene (NULL),
+ mStreamPtr (NULL)
+ {
+ setScbType(ScbType::UNDEFINED);
+ resetControl(ControlState::eNOT_IN_SCENE);
+ resetAllBufferFlags();
+ }
+
+ PX_INLINE bool isBuffering() const
+ {
+ const ControlState::Enum state = getControlState();
+ return state == ControlState::eREMOVE_PENDING || // pending remove not possible if not buffered
+ (state == ControlState::eIN_SCENE && mScene->isPhysicsBuffering());
+ }
+
+
+ PX_FORCE_INLINE Ps::IntBool insertPending() const { return getControlState() == ControlState::eINSERT_PENDING; }
+ PX_FORCE_INLINE ScbType::Enum getScbType() const { return ScbType::Enum((mControlState&eTYPE_MASK)>>eTYPE_SHIFT); }
+ PX_FORCE_INLINE void setScbType(ScbType::Enum type) { mControlState = (mControlState&~eTYPE_MASK)|(type<<eTYPE_SHIFT); }
+
+ // the scene value field set if the object is either inserted, in simulation, or waiting for removal. If any of these things
+ // is true, it can't be added to a different scene
+
+ PX_FORCE_INLINE void setScbScene(Scb::Scene* scene)
+ {
+ mScene = scene;
+ }
+
+ PX_FORCE_INLINE Scb::Scene* getScbScene() const
+ {
+ return mScene;
+ }
+
+ /**
+ \brief Get scene pointer from a users perspective.
+
+ When the user removes an object from the scene while the simulation is running, the scene pointer does not get set to NULL immediately. This will only happen
+ at the next sync point. However, from an API point of view, a NULL pointer is expected after a removal. This method provides the correct answer in such a case.
+
+ \return The scene pointer as it should be visible from the users perspective.
+ */
+ PX_FORCE_INLINE Scb::Scene* getScbSceneForAPI() const
+ {
+ ControlState::Enum state = getControlState();
+ return state == ControlState::eINSERT_PENDING || state == ControlState::eIN_SCENE ? mScene : NULL;
+ }
+
+ PX_FORCE_INLINE void resetScbScene() { mScene = NULL; }
+
+ PX_FORCE_INLINE bool hasUpdates() const { return getControlFlags() & ControlFlag::eIS_UPDATED; }
+ PX_FORCE_INLINE PxU32 getControlFlags() const { return (mControlState&eCONTROLFLAG_MASK)>>eCONTROLFLAG_SHIFT; }
+ PX_FORCE_INLINE void setControlFlag(ControlFlag::Enum f) { mControlState |= (f<<eCONTROLFLAG_SHIFT); }
+ PX_FORCE_INLINE void resetControlFlag(ControlFlag::Enum f) { mControlState &=~(f<<eCONTROLFLAG_SHIFT); }
+
+ PX_FORCE_INLINE ControlState::Enum getControlState() const { return ControlState::Enum((mControlState&PxU32(eCONTROLSTATE_MASK))>>eCONTROLSTATE_SHIFT);}
+ PX_FORCE_INLINE void setControlState(ControlState::Enum s) { mControlState = (mControlState&~eCONTROLSTATE_MASK)|(s<<eCONTROLSTATE_SHIFT); }
+ PX_FORCE_INLINE void resetControl(ControlState::Enum s) { mControlState = (mControlState&~eCONTROL_MASK) | (s<<eCONTROLSTATE_SHIFT); }
+
+ PX_FORCE_INLINE void scheduleForUpdate() { mScene->scheduleForUpdate(*this); }
+
+ /**
+ \brief Destroys the object.
+
+ If the simulation is not running, this will release the object, else it will just mark the object as eIS_RELEASED and thus it will get deleted
+ when the next sync point is reached. This method expects that the object has been removed from the scene first (or waits for removal).
+ */
+ void destroy();
+
+ /**
+ \brief Test if a property has been changed by the user.
+
+ \param[in] flag The flag of the property to test for. Has to be within the bounds of eBUFFERFLAG_MASK.
+ \return Positive value if the property has been changed by the user.
+ */
+ PX_FORCE_INLINE Ps::IntBool isBuffered(PxU32 flag) const
+ {
+ PX_ASSERT((flag & eBUFFERFLAG_MASK) == flag);
+ return Ps::IntBool(mControlState & flag);
+ }
+
+ PX_FORCE_INLINE PxU8* getStream() { return mStreamPtr ? mStreamPtr : mStreamPtr = mScene->getStream(getScbType()); }
+ PX_FORCE_INLINE const PxU8* getStream() const { PX_ASSERT(mStreamPtr); return mStreamPtr; }
+
+ /**
+ \brief Helper method to trigger object tracking after a property change.
+
+ This method will flag the marked property as changed and will add the object to the list of updated objects if it is not
+ registered already.
+
+ \param[in] flag The flag of the changed property. Has to be within the bounds of eBUFFERFLAG_MASK.
+ */
+ PX_FORCE_INLINE void markUpdated(PxU32 flag)
+ {
+ PX_ASSERT((flag & eBUFFERFLAG_MASK) == flag);
+ scheduleForUpdate();
+ mControlState |= flag;
+ }
+
+ protected:
+ ~Base(){}
+
+ PX_FORCE_INLINE PxU32 getBufferFlags() const { return mControlState & eBUFFERFLAG_MASK; }
+ PX_FORCE_INLINE void setBufferFlag(PxU32 flag) { PX_ASSERT((flag & eBUFFERFLAG_MASK) == flag); mControlState |= flag; }
+ PX_FORCE_INLINE void resetBufferFlag(PxU32 flag) { PX_ASSERT((flag & eBUFFERFLAG_MASK) == flag); mControlState &= ~flag; }
+ PX_FORCE_INLINE void resetAllBufferFlags() { mControlState &=~eBUFFERFLAG_MASK; }
+
+
+ /**
+ \brief Cleanup method after the object has been synced.
+
+ Every buffering object should implement a syncState() method where the buffered user changes get synced with Core. Call this method at the end of the
+ syncState() method to clear all buffer flags and references.
+ */
+ PX_FORCE_INLINE void postSyncState()
+ {
+ // DS: this can get called even when mScene == NULL, by removeAggregate (see AggregateFreeStandingCreateDelete test)
+ // TODO(dsequeira): investigate that when the dust settles on shape refactoring
+ PX_ASSERT(getControlState()!=ControlState::eNOT_IN_SCENE || mScene == NULL);
+ PX_ASSERT(getScbType()!=ScbType::UNDEFINED);
+
+ mStreamPtr = NULL;
+ resetAllBufferFlags();
+ }
+
+ private:
+ enum { eBUFFERFLAG_MASK = (1<<24) - 1,
+ eTYPE_MASK = 15<<24,
+ eCONTROLFLAG_MASK = 3<<28,
+ eCONTROLSTATE_MASK = 3<<30,
+ eCONTROL_MASK = 15<<28};
+
+ enum { eTYPE_SHIFT = 24,
+ eCONTROLFLAG_SHIFT = 28,
+ eCONTROLSTATE_SHIFT = 30};
+
+ /**
+ \brief Scene pointer.
+
+ The scene pointer get set as soon as the user adds an object to the scene. However, it does not get cleared until the object has been
+ removed from the scene internally, i.e., removing an object while the simulation is running will not set this pointer to NULL immediately.
+ */
+ Scb::Scene* mScene;
+
+ /**
+ \brief Mix of buffering related states/flags.
+
+ highest lowest
+ | 2 | 2 | 4 | 24 |
+ | ControlState | ControlFlag | ScbType | buffer attribute flags |
+
+ The buffer attribute flags mark which of the properties have been updated. The specific implementation of this class defines those flags.
+ */
+ PxU32 mControlState;
+
+ /**
+ \brief Data buffer to store property/state changes temporarily.
+
+ Pointer to a temporary struct where user changes made while the simulation is running are buffered. The structure is currently as large as necessary to hold all
+ properties of a buffered object. Even if only a single property of an object gets changed, the whole structure is assigned. The motivation for this was to keep
+ the implementation complexity low based on the assumption that users will not change all objects in a scene every frame. The temporary buffer gets assigned on demand
+ and is returned to pools after the data has been synced to Core. The pointer is then set to NULL again.
+ This kind of buffer can not be used for properties that get written by the simulation (for example, pose, velocity, sleep state). Those need to be permanently buffered
+ in the specific implementation of this class, else the user might get an inconsistent picture of the scene object state.
+
+ @see postSyncState()
+ */
+ PxU8* mStreamPtr;
+ };
+
+} // namespace Scb
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbBody.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbBody.h
new file mode 100644
index 00000000..00ce9f52
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbBody.h
@@ -0,0 +1,1068 @@
+// 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_SCB_BODY
+#define PX_PHYSICS_SCB_BODY
+
+#include "ScBodyCore.h"
+
+#include "ScbRigidObject.h"
+#include "CmUtils.h"
+#include "PsUtilities.h"
+#include "PxRigidDynamic.h"
+#include "ScbDefs.h"
+#include "GuSIMDHelpers.h"
+
+namespace physx
+{
+namespace Scb
+{
+#if PX_VC
+ #pragma warning(push)
+ #pragma warning( disable : 4324 ) // Padding was added at the end of a structure because of a __declspec(align) value.
+#endif
+
+struct BodyBuffer : public RigidObjectBuffer //once RigidObject has its own buffered elements, derive from that instead
+{
+ template <PxU32 I, PxU32 Dummy> struct Fns {}; // TODO: make the base class traits visible
+ typedef Sc::BodyCore Core;
+ typedef BodyBuffer Buf;
+
+ // regular attributes
+ SCB_REGULAR_ATTRIBUTE(0, PxReal, InverseMass)
+ SCB_REGULAR_ATTRIBUTE(1, PxVec3, InverseInertia)
+ SCB_REGULAR_ATTRIBUTE(2, PxReal, LinearDamping)
+ SCB_REGULAR_ATTRIBUTE(3, PxReal, AngularDamping)
+ SCB_REGULAR_ATTRIBUTE(4, PxReal, MaxAngVelSq)
+ SCB_REGULAR_ATTRIBUTE(5, PxReal, SleepThreshold)
+ SCB_REGULAR_ATTRIBUTE(6, PxReal, CCDAdvanceCoefficient)
+ SCB_REGULAR_ATTRIBUTE(7, PxReal, ContactReportThreshold)
+ SCB_REGULAR_ATTRIBUTE(8, PxU16, SolverIterationCounts)
+ SCB_REGULAR_ATTRIBUTE_ALIGNED(9,PxTransform, Body2Actor, 16)
+ SCB_REGULAR_ATTRIBUTE(10, PxReal, MaxPenetrationBias)
+ SCB_REGULAR_ATTRIBUTE(11, PxReal, FreezeThreshold)
+ SCB_REGULAR_ATTRIBUTE(12, PxReal, MaxContactImpulse)
+ SCB_REGULAR_ATTRIBUTE(13, PxRigidDynamicLockFlags, RigidDynamicLockFlags)
+
+ // irregular attributes
+
+ PX_ALIGN(16, PxTransform) mKinematicTarget;
+ PxVec3 mLinAcceleration;
+ PxVec3 mAngAcceleration;
+ PxVec3 mLinDeltaVelocity;
+ PxVec3 mAngDeltaVelocity;
+
+ PxRigidBodyFlags mRigidBodyFlags;
+ PxRigidDynamicLockFlags mRigidDynamicFlags;
+
+ enum
+ {
+ BF_RigidBodyFlags = 1<<14,
+ BF_KinematicTarget = 1<<15,
+ BF_AccelerationLinear = 1<<16,
+ BF_AccelerationAngular = 1<<17,
+ BF_Acceleration = BF_AccelerationLinear|BF_AccelerationAngular,
+ BF_DeltaVelocityLinear = 1<<18,
+ BF_DeltaVelocityAngular = 1<<19,
+ BF_DeltaVelocity = BF_DeltaVelocityLinear|BF_DeltaVelocityAngular,
+ BF_Body2World = 1<<20,
+ BF_Body2World_CoM = 1<<21, // the body pose was adjusted because of a center of mass change only
+ BF_LinearVelocity = 1<<22,
+ BF_AngularVelocity = 1<<23,
+ BF_WakeCounter = 1<<24,
+ BF_PutToSleep = 1<<25,
+ BF_WakeUp = 1<<26,
+ BF_ClearAccelerationLinear = 1<<27,
+ BF_ClearAccelerationAngular = 1<<28,
+ BF_ClearAcceleration = BF_ClearAccelerationLinear|BF_ClearAccelerationAngular,
+ BF_ClearDeltaVelocityLinear = 1<<29,
+ BF_ClearDeltaVelocityAngular= 1<<30,
+ BF_ClearDeltaVelocity = BF_ClearDeltaVelocityLinear|BF_ClearDeltaVelocityAngular
+ };
+
+ BodyBuffer(): mLinAcceleration(0), mAngAcceleration(0), mLinDeltaVelocity(0), mAngDeltaVelocity(0) {}
+};
+
+
+#if PX_VC
+ #pragma warning(pop)
+#endif
+
+class Body : public Scb::RigidObject
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+
+ typedef BodyBuffer Buf;
+ typedef Sc::BodyCore Core;
+
+public:
+// PX_SERIALIZATION
+ Body(const PxEMPTY) : Scb::RigidObject(PxEmpty), mBodyCore(PxEmpty), mBufferedIsSleeping(1) { PX_ASSERT(mBodyBufferFlags == 0); }
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ PX_INLINE Body(PxActorType::Enum type, const PxTransform& bodyPose);
+ PX_INLINE ~Body() {}
+
+ //---------------------------------------------------------------------------------
+ // Wrapper for Sc::BodyCore interface
+ //---------------------------------------------------------------------------------
+
+
+ PX_FORCE_INLINE const PxTransform& getBody2World() const { return mBufferedBody2World; } // PT: important: keep returning an address here (else update prefetch in SceneQueryManager::addShapes)
+ PX_INLINE void setBody2World(const PxTransform& p, bool asPartOfBody2ActorChange);
+
+ PX_FORCE_INLINE const PxVec3& getLinearVelocity() const { return mBufferedLinVelocity; }
+ PX_INLINE void setLinearVelocity(const PxVec3& v);
+ PX_FORCE_INLINE const PxVec3& getAngularVelocity() const { return mBufferedAngVelocity; }
+ PX_INLINE void setAngularVelocity(const PxVec3& v);
+
+ PX_FORCE_INLINE void wakeUp();
+ PX_FORCE_INLINE void putToSleep();
+ PX_FORCE_INLINE PxReal getWakeCounter() const { return mBufferedWakeCounter; }
+ PX_INLINE void setWakeCounter(PxReal w);
+ PX_FORCE_INLINE bool isSleeping() const { return (mBufferedIsSleeping != 0); }
+
+ PX_INLINE const PxTransform& getBody2Actor() const { return read<Buf::BF_Body2Actor>(); }
+ PX_INLINE void setBody2Actor(const PxTransform& m) { write<Buf::BF_Body2Actor>(m); }
+
+ PX_INLINE PxReal getInverseMass() const { return read<Buf::BF_InverseMass>(); }
+ PX_INLINE void setInverseMass(PxReal m) { write<Buf::BF_InverseMass>(m); }
+
+ PX_INLINE PxVec3 getInverseInertia() const { return read<Buf::BF_InverseInertia>(); }
+ PX_INLINE void setInverseInertia(const PxVec3& i) { write<Buf::BF_InverseInertia>(i); }
+
+ PX_INLINE PxReal getLinearDamping() const { return read<Buf::BF_LinearDamping>(); }
+ PX_INLINE void setLinearDamping(PxReal d) { write<Buf::BF_LinearDamping>(d); }
+
+ PX_INLINE PxReal getAngularDamping() const { return read<Buf::BF_AngularDamping>(); }
+ PX_INLINE void setAngularDamping(PxReal d) { write<Buf::BF_AngularDamping>(d); }
+
+ PX_INLINE PxRigidBodyFlags getFlags() const { return (isBuffered(Buf::BF_RigidBodyFlags)) ? getBodyBuffer()->mRigidBodyFlags : mBodyCore.getFlags(); }
+ PX_INLINE void setFlags(PxRigidBodyFlags f);
+
+ PX_INLINE PxRigidDynamicLockFlags getLockFlags() const { return read<Buf::BF_RigidDynamicLockFlags>(); }
+ PX_INLINE void setLockFlags(PxRigidDynamicLockFlags f) { write<Buf::BF_RigidDynamicLockFlags>(f); }
+
+ PX_INLINE PxReal getSleepThreshold() const { return read<Buf::BF_SleepThreshold>(); }
+ PX_INLINE void setSleepThreshold(PxReal t) { write<Buf::BF_SleepThreshold>(t); }
+
+ PX_INLINE PxReal getFreezeThreshold() const { return read<Buf::BF_FreezeThreshold>(); }
+ PX_INLINE void setFreezeThreshold(PxReal t) { write<Buf::BF_FreezeThreshold>(t); }
+
+ PX_INLINE PxReal getMaxPenetrationBias() const { return read<Buf::BF_MaxPenetrationBias>(); }
+ PX_INLINE void setMaxPenetrationBias(PxReal t) { write<Buf::BF_MaxPenetrationBias>(t); }
+
+ PX_INLINE PxReal getMaxAngVelSq() const { return read<Buf::BF_MaxAngVelSq>(); }
+ PX_INLINE void setMaxAngVelSq(PxReal v) { write<Buf::BF_MaxAngVelSq>(v); }
+
+ PX_INLINE PxU16 getSolverIterationCounts() const { return Ps::to16(read<Buf::BF_SolverIterationCounts>()); }
+ PX_INLINE void setSolverIterationCounts(PxU16 c) { write<Buf::BF_SolverIterationCounts>(c); }
+
+ PX_INLINE PxReal getContactReportThreshold() const { return read<Buf::BF_ContactReportThreshold>(); }
+ PX_INLINE void setContactReportThreshold(PxReal t) { write<Buf::BF_ContactReportThreshold>(t); }
+
+ PX_INLINE PxReal getMaxContactImpulse() const { return read<Buf::BF_MaxContactImpulse>(); }
+ PX_INLINE void setMaxContactImpulse(PxReal t) { write<Buf::BF_MaxContactImpulse>(t); }
+
+ PX_INLINE void addSpatialAcceleration(const PxVec3* linAcc, const PxVec3* angAcc);
+ PX_INLINE void clearSpatialAcceleration(bool force, bool torque);
+ PX_INLINE void addSpatialVelocity(const PxVec3* linVelDelta, const PxVec3* angVelDelta);
+ PX_INLINE void clearSpatialVelocity(bool force, bool torque);
+
+ PX_INLINE bool getKinematicTarget(PxTransform& p) const;
+ PX_INLINE void setKinematicTarget(const PxTransform& p);
+
+ PX_INLINE void setMinCCDAdvanceCoefficient(PxReal minCCDAdvanceCoefficient){write<Buf::BF_CCDAdvanceCoefficient>(minCCDAdvanceCoefficient);}
+ PX_INLINE PxReal getMinCCDAdvanceCoefficient() const { return read<Buf::BF_CCDAdvanceCoefficient>();}
+
+ PX_FORCE_INLINE void onOriginShift(const PxVec3& shift);
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+ PX_INLINE void syncState();
+ PX_INLINE void syncCollisionWriteThroughState();
+
+ static size_t getScOffset()
+ {
+ return reinterpret_cast<size_t>(&reinterpret_cast<Body*>(0)->mBodyCore);
+ }
+
+ /**
+ \brief Shadowed method of #Scb::Base::markUpdated() to store the buffered property flags in a separate location (ran out of flag space)
+ */
+ PX_FORCE_INLINE void markUpdated(PxU32 flag);
+
+ /**
+ \brief Shadowed method of #Scb::Base::isBuffered() to check the buffered property flags (ran out of flag space)
+ */
+ PX_FORCE_INLINE Ps::IntBool isBuffered(PxU32 flag) const;
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+public:
+ PX_FORCE_INLINE const Sc::BodyCore& getScBody() const { return mBodyCore; } // Only use if you know what you're doing!
+ PX_FORCE_INLINE Sc::BodyCore& getScBody() { return mBodyCore; } // Only use if you know what you're doing!
+
+ PX_FORCE_INLINE static const Body& fromSc(const Core& a) { return static_cast<const Body&>(Actor::fromSc(a)); }
+ PX_FORCE_INLINE static Body& fromSc(Core &a) { return static_cast<Body&>(Actor::fromSc(a)); }
+
+ PX_FORCE_INLINE bool hasKinematicTarget() const;
+ PX_FORCE_INLINE void clearSimStateDataForPendingInsert();
+ PX_FORCE_INLINE void transitionSimStateDataForPendingInsert();
+
+ PX_INLINE PxMat33 getGlobalInertiaTensorInverse() const;
+
+ PX_FORCE_INLINE bool checkSleepReadinessBesidesWakeCounter();
+ PX_FORCE_INLINE void initBufferedState();
+ PX_FORCE_INLINE void clearBufferedState();
+ PX_FORCE_INLINE void clearBufferedSleepStateChange();
+
+ PX_INLINE void wakeUpInternal(PxReal wakeCounter);
+ PX_INLINE void putToSleepInternal();
+
+ PX_FORCE_INLINE void switchBodyToNoSim();
+
+private:
+ Sc::BodyCore mBodyCore;
+ //---------------------------------------------------------------------------------
+ // Permanently buffered data (simulation written data)
+ //---------------------------------------------------------------------------------
+ PxTransform mBufferedBody2World;
+ PxVec3 mBufferedLinVelocity;
+ PxVec3 mBufferedAngVelocity;
+ PxReal mBufferedWakeCounter;
+ PxU32 mBufferedIsSleeping; // Note: If the object is not in a scene this value must be true, i.e., positive
+ // Don't need 4 bytes but otherwise there is padding here anyway.
+ PxU32 mBodyBufferFlags; // Stores the buffered property flags since there is not enough space in usual location in Scb::Base.
+
+ PX_FORCE_INLINE const Buf* getBodyBuffer() const { return reinterpret_cast<const Buf*>(getStream()); }
+ PX_FORCE_INLINE Buf* getBodyBuffer() { return reinterpret_cast<Buf*>(getStream()); }
+
+ PX_INLINE void accumulate(PxVec3& linear, PxVec3& angular, PxU32 linearFlag, PxU32 angularFlag, const PxVec3* linIncrement, const PxVec3* angIncrement)
+ {
+ PxU32 flag = 0;
+ if(linIncrement)
+ {
+ linear += *linIncrement;
+ flag |= linearFlag;
+ }
+
+ if(angIncrement)
+ {
+ angular += *angIncrement;
+ flag |= angularFlag;
+ }
+
+ markUpdated(flag);
+ }
+
+ PX_INLINE void resetAccumulator(PxVec3& linear, PxVec3& angular, PxU32 linearFlag, PxU32 angularFlag, PxU32 raisedFlagLinear, PxU32 raisedFlagAngular, bool force, bool torque)
+ {
+ PxU32 flags = mBodyBufferFlags;
+ PxU32 raisedFlags = 0;
+ if(force)
+ {
+ linear = PxVec3(0.0f);
+ flags &= ~linearFlag;
+ raisedFlags |= raisedFlagLinear;
+ }
+
+ if(torque)
+ {
+ angular = PxVec3(0.0f);
+ flags &= ~angularFlag;
+ raisedFlags |= raisedFlagAngular;
+ }
+
+ //This is for the split sim logic to support write-through spatial accelerations. It is for the condition where a spatial acceleration has been applied prior to
+ //collide(). However, a clear spatial acceleration command is raised by the user between collide() and fetchCollision(), we need to raised this
+ //flag to clear the previous applied spatial acceleration in the unbuffered state so that this spatial acceleration can be cleared correctly in fetchCollision().
+ flags |= raisedFlags;
+ mBodyBufferFlags = flags;
+ scheduleForUpdate();
+ }
+
+ PX_FORCE_INLINE void setBufferedParamsForAsleep() // use this in the non-buffered case to set the buffered properties
+ {
+ mBufferedIsSleeping = 1;
+ mBufferedWakeCounter = 0.0f;
+ mBufferedLinVelocity = PxVec3(0.0f);
+ mBufferedAngVelocity = PxVec3(0.0f);
+ // no need to clear forces since that will be the job of the corresponding core/sim methods
+ }
+
+ PX_FORCE_INLINE void setBufferedParamsForAwake(PxReal wakeCounter) // use this in the non-buffered case to set the buffered properties
+ {
+ mBufferedIsSleeping = 0;
+ mBufferedWakeCounter = wakeCounter;
+ }
+
+ //---------------------------------------------------------------------------------
+ // Infrastructure for regular attributes
+ //---------------------------------------------------------------------------------
+
+ struct Access: public BufferedAccess<Buf, Core, Body, Body> {};
+
+ template<PxU32 f> PX_FORCE_INLINE typename Buf::Fns<f,0>::Arg read() const { return Access::read<Buf::Fns<f,0> >(*this, mBodyCore); }
+ template<PxU32 f> PX_FORCE_INLINE void write(typename Buf::Fns<f,0>::Arg v) { Access::write<Buf::Fns<f,0> >(*this, mBodyCore, v); }
+ template<PxU32 f> PX_FORCE_INLINE void flush(const Buf& buf) { Access::flush<Buf::Fns<f,0> >(*this, mBodyCore, buf); }
+
+};
+
+
+PX_INLINE Body::Body(PxActorType::Enum type, const PxTransform& bodyPose) : mBodyCore(type, bodyPose)
+{
+ setScbType(ScbType::BODY);
+
+ mBufferedBody2World = mBodyCore.getBody2World();
+ mBufferedLinVelocity = mBodyCore.getLinearVelocity();
+ mBufferedAngVelocity = mBodyCore.getAngularVelocity();
+ mBufferedWakeCounter = mBodyCore.getWakeCounter();
+ mBufferedIsSleeping = 1; // this is the specified value for free standing objects
+ mBodyBufferFlags = 0;
+}
+
+PX_INLINE void Body::setBody2World(const PxTransform& p, bool asPartOfBody2ActorChange)
+{
+ mBufferedBody2World = p;
+
+ if (!isBuffering())
+ {
+ mBodyCore.setBody2World(p);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ if (!asPartOfBody2ActorChange)
+ {
+ // call was triggered by a setGlobalPose(). This means the simulated body pose will get
+ // overwritten by the user value, so we do not need to adjust it.
+
+ mBodyBufferFlags &= ~Buf::BF_Body2World_CoM;
+ }
+ else if (!(mBodyBufferFlags & Buf::BF_Body2World))
+ {
+ // there has been no setGlobalPose() on the body yet and the center of mass changes.
+ // This case needs special treatment because the simulation results for such a body will be based on
+ // the old center of mass but need to get translated to the new center of mass.
+
+ mBodyBufferFlags |= Buf::BF_Body2World_CoM;
+ }
+
+ markUpdated(Buf::BF_Body2World);
+ }
+}
+
+PX_INLINE void Body::setLinearVelocity(const PxVec3& v)
+{
+ mBufferedLinVelocity = v;
+
+ if (!isBuffering())
+ {
+ mBodyCore.setLinearVelocity(v);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ markUpdated(Buf::BF_LinearVelocity);
+}
+
+PX_INLINE void Body::setAngularVelocity(const PxVec3& v)
+{
+ mBufferedAngVelocity = v;
+
+ if (!isBuffering())
+ {
+ mBodyCore.setAngularVelocity(v);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ markUpdated(Buf::BF_AngularVelocity);
+}
+
+
+PX_INLINE void Body::wakeUpInternal(PxReal wakeCounter)
+{
+ PX_ASSERT(getScbScene());
+
+ if (!isBuffering())
+ {
+ setBufferedParamsForAwake(wakeCounter);
+ mBodyCore.wakeUp(wakeCounter);
+ }
+ else
+ {
+ mBufferedIsSleeping = 0;
+ mBufferedWakeCounter = wakeCounter;
+ markUpdated(Buf::BF_WakeUp | Buf::BF_WakeCounter);
+ mBodyBufferFlags &= ~Buf::BF_PutToSleep;
+ }
+}
+
+PX_FORCE_INLINE void Body::wakeUp()
+{
+ PX_ASSERT(!(getFlags() & PxRigidBodyFlag::eKINEMATIC));
+ Scene* scene = getScbScene();
+ PX_ASSERT(scene); // only allowed for an object in a scene
+
+ wakeUpInternal(scene->getWakeCounterResetValue());
+}
+
+
+PX_INLINE void Body::putToSleepInternal()
+{
+ if (!isBuffering())
+ {
+ setBufferedParamsForAsleep();
+ mBodyCore.putToSleep();
+ }
+ else
+ {
+ mBufferedIsSleeping = 1;
+ mBufferedWakeCounter = 0.0f;
+ // it is necessary to set the velocities as a buffered operation (not just adjust the buffered velocities) because
+ // a putToSleep can be followed by a wakeUp in which case only the wakeUp will get processed on sync, however, the velocities
+ // still need to get set to 0.
+ setLinearVelocity(PxVec3(0.0f));
+ setAngularVelocity(PxVec3(0.0f));
+ mBodyBufferFlags &= ~(Buf::BF_Acceleration | Buf::BF_DeltaVelocity | Buf::BF_KinematicTarget);
+
+ markUpdated(Buf::BF_PutToSleep | Buf::BF_WakeCounter);
+ mBodyBufferFlags &= ~Buf::BF_WakeUp;
+ }
+}
+
+
+PX_FORCE_INLINE void Body::putToSleep()
+{
+ PX_ASSERT(!(getFlags() & PxRigidBodyFlag::eKINEMATIC));
+
+ putToSleepInternal();
+}
+
+
+PX_INLINE void Body::setWakeCounter(PxReal w)
+{
+ PX_ASSERT(!(getFlags() & PxRigidBodyFlag::eKINEMATIC));
+
+ mBufferedWakeCounter = w;
+
+ if (!isBuffering())
+ {
+ if (getScbScene() && (w > 0.0f))
+ mBufferedIsSleeping = 0;
+
+ mBodyCore.setWakeCounter(w);
+
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ if (w > 0.0f)
+ wakeUpInternal(w);
+ else
+ markUpdated(Buf::BF_WakeCounter);
+ }
+}
+
+
+PX_INLINE void Body::setFlags(PxRigidBodyFlags f)
+{
+ PxU32 wasKinematic = getFlags() & PxRigidBodyFlag::eKINEMATIC;
+ PxU32 isKinematic = f & PxRigidBodyFlag::eKINEMATIC;
+ bool switchToKinematic = ((!wasKinematic) && isKinematic);
+ bool switchToDynamic = (wasKinematic && (!isKinematic));
+
+ if (!isBuffering())
+ {
+ if (switchToKinematic)
+ setBufferedParamsForAsleep();
+
+ mBodyCore.setFlags(getScbScene() ? getScbScene()->getScScene().getSimStateDataPool() : NULL, f);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ if (switchToKinematic)
+ putToSleepInternal();
+ else if (switchToDynamic)
+ mBodyBufferFlags &= ~Buf::BF_KinematicTarget;
+
+ getBodyBuffer()->mRigidBodyFlags = f;
+ markUpdated(Buf::BF_RigidBodyFlags);
+ }
+}
+
+
+PX_INLINE void Body::addSpatialAcceleration(const PxVec3* linAcc, const PxVec3* angAcc)
+{
+ if (!isBuffering())
+ {
+ mBodyCore.addSpatialAcceleration(getScbScene()->getScScene().getSimStateDataPool(), linAcc, angAcc);
+ //Spatial acceleration isn't sent to PVD.
+ }
+ else
+ {
+ Buf* b = getBodyBuffer();
+ accumulate(b->mLinAcceleration, b->mAngAcceleration, Buf::BF_AccelerationLinear, Buf::BF_AccelerationAngular, linAcc, angAcc);
+ }
+}
+
+
+PX_INLINE void Body::clearSpatialAcceleration(bool force, bool torque)
+{
+ if (!isBuffering())
+ {
+ mBodyCore.clearSpatialAcceleration(force, torque);
+ //Spatial acceleration isn't sent to PVD.
+ }
+ else
+ {
+ Buf* b = getBodyBuffer();
+ resetAccumulator(b->mLinAcceleration, b->mAngAcceleration, Buf::BF_AccelerationLinear, Buf::BF_AccelerationAngular, Buf::BF_ClearAccelerationLinear, Buf::BF_ClearAccelerationAngular, force, torque);
+ }
+}
+
+
+PX_INLINE void Body::addSpatialVelocity(const PxVec3* linVelDelta, const PxVec3* angVelDelta)
+{
+ if (!isBuffering())
+ {
+ mBodyCore.addSpatialVelocity(getScbScene()->getScScene().getSimStateDataPool(), linVelDelta, angVelDelta);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ Buf* b = getBodyBuffer();
+ accumulate(b->mLinDeltaVelocity, b->mAngDeltaVelocity, Buf::BF_DeltaVelocityLinear, Buf::BF_DeltaVelocityAngular, linVelDelta, angVelDelta);
+ }
+}
+
+
+PX_INLINE void Body::clearSpatialVelocity(bool force, bool torque)
+{
+ if (!isBuffering())
+ {
+ mBodyCore.clearSpatialVelocity(force, torque);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ Buf* b = getBodyBuffer();
+ resetAccumulator(b->mLinDeltaVelocity, b->mAngDeltaVelocity, Buf::BF_DeltaVelocityLinear, Buf::BF_DeltaVelocityAngular, Buf::BF_ClearDeltaVelocityLinear, Buf::BF_ClearDeltaVelocityAngular, force, torque);
+ }
+}
+
+
+PX_INLINE bool Body::getKinematicTarget(PxTransform& p) const
+{
+ if (isBuffered(Buf::BF_KinematicTarget))
+ {
+ p = getBodyBuffer()->mKinematicTarget;
+ return true;
+ }
+ else if (getControlState() != ControlState::eREMOVE_PENDING)
+ return mBodyCore.getKinematicTarget(p);
+ else
+ return false;
+}
+
+
+PX_INLINE void Body::setKinematicTarget(const PxTransform& p)
+{
+ Scene* scene = getScbScene();
+ PX_ASSERT(scene); // only allowed for an object in a scene
+ PxReal wakeCounterResetValue = scene->getWakeCounterResetValue();
+
+ if (!isBuffering())
+ {
+ mBodyCore.setKinematicTarget(scene->getScScene().getSimStateDataPool(), p, wakeCounterResetValue);
+ setBufferedParamsForAwake(wakeCounterResetValue);
+
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ PX_ASSERT((mBodyBufferFlags & (Buf::BF_DeltaVelocity|Buf::BF_Acceleration)) == 0); // switching to kinematic should do that.
+ getBodyBuffer()->mKinematicTarget = p;
+ markUpdated(Buf::BF_KinematicTarget);
+
+ wakeUpInternal(wakeCounterResetValue);
+ }
+#if PX_SUPPORT_PVD
+ if(getControlState() == ControlState::eIN_SCENE)
+ {
+ scene->getScenePvdClient().updateKinematicTarget(this, p);
+ }
+#endif
+}
+
+
+PX_FORCE_INLINE void Body::onOriginShift(const PxVec3& shift)
+{
+ mBufferedBody2World.p -= shift;
+ mBodyCore.onOriginShift(shift);
+}
+
+
+
+//--------------------------------------------------------------
+//
+// Miscellaneous
+//
+//--------------------------------------------------------------
+
+PX_FORCE_INLINE bool Body::hasKinematicTarget() const
+{
+ return
+ (
+ isBuffered(BodyBuffer::BF_KinematicTarget) || mBodyCore.getHasValidKinematicTarget()
+ );
+}
+
+
+PX_FORCE_INLINE void Body::clearSimStateDataForPendingInsert()
+{
+ Sc::BodyCore& core = getScBody();
+ if (insertPending())
+ {
+ // not-so-nice-code to cover the following cases:
+ // - user adds a kinematic to the scene, sets a target and removes the kinematic from scene again (all while the sim is running)
+ // - same as above but instead of removing the kinematic it gets switched to dynamic
+ // - user adds a dynamic to the scene, sets a target and removes the dynamic from scene again (all while the sim is running)
+
+ if(core.getSimStateData(true))
+ core.tearDownSimStateData(getScbScene()->getScScene().getSimStateDataPool(), true);
+ else if(core.getSimStateData(false))
+ core.tearDownSimStateData(getScbScene()->getScScene().getSimStateDataPool(), false);
+ }
+}
+
+
+PX_FORCE_INLINE void Body::transitionSimStateDataForPendingInsert()
+{
+ Sc::BodyCore& core = getScBody();
+ if (insertPending())
+ {
+ // not-so-nice-code to cover the following case:
+ // - user adds a dynamic, adds force, then switches to kinematic (all while the sim is running)
+
+ if(core.getSimStateData(false))
+ {
+ core.setupSimStateData(getScbScene()->getScScene().getSimStateDataPool(), true); // note: this won't allocate the memory twice
+ }
+ }
+}
+
+
+PX_INLINE PxMat33 Body::getGlobalInertiaTensorInverse() const
+{
+ PxMat33 inverseInertiaWorldSpace;
+ Cm::transformInertiaTensor(getInverseInertia(), Gu::PxMat33Padded(getBody2World().q), inverseInertiaWorldSpace);
+ return inverseInertiaWorldSpace;
+}
+
+
+PX_FORCE_INLINE bool Body::checkSleepReadinessBesidesWakeCounter()
+{
+ return (getLinearVelocity().isZero() && getAngularVelocity().isZero());
+ // no need to test for pending force updates yet since currently this is not supported on scene insertion
+}
+
+
+PX_FORCE_INLINE void Body::initBufferedState()
+{
+ PX_ASSERT(mBufferedIsSleeping); // this method is only meant to get called when an object is added to the scene
+
+ if ((getWakeCounter() == 0.0f) && checkSleepReadinessBesidesWakeCounter())
+ mBufferedIsSleeping = 1;
+ else
+ mBufferedIsSleeping = 0;
+}
+
+
+PX_FORCE_INLINE void Body::clearBufferedState()
+{
+ if (!(getFlags() & PxRigidBodyFlag::eKINEMATIC))
+ {
+ mBufferedIsSleeping = 1; // the expected state when an object gets removed from the scene.
+ mBodyBufferFlags &= ~(Buf::BF_Acceleration | Buf::BF_DeltaVelocity);
+ }
+ else
+ {
+ // make sure the buffered properties for a kinematic that is not in a scene are set according to the specification
+
+ // necessary to use the putToSleep method because buffered re-insertion case needs to be covered as well. Currently, re-insertion
+ // just clears the remove operation. This would prevent the core object parameters to get updated. Thus the operations need
+ // to be buffered and putToSleepInternal takes care of that.
+ putToSleepInternal();
+ }
+
+ RigidObject::clearBufferedState();
+}
+
+
+PX_FORCE_INLINE void Body::clearBufferedSleepStateChange()
+{
+ mBodyBufferFlags &= ~(Buf::BF_WakeUp | Buf::BF_PutToSleep);
+}
+
+
+PX_FORCE_INLINE void Body::switchBodyToNoSim()
+{
+ Scb::Scene* scene = getScbScene();
+
+ switchToNoSim(true);
+
+ if ((!scene) || (!getScbScene()->isPhysicsBuffering()))
+ {
+ setBufferedParamsForAsleep();
+ getScBody().putToSleep();
+ }
+ else
+ putToSleepInternal();
+
+ if (scene)
+ clearSimStateDataForPendingInsert();
+}
+
+
+//--------------------------------------------------------------
+//
+// Data synchronization
+//
+//--------------------------------------------------------------
+
+PX_FORCE_INLINE void Body::markUpdated(PxU32 flag)
+{
+ scheduleForUpdate();
+ mBodyBufferFlags |= flag;
+}
+
+PX_FORCE_INLINE Ps::IntBool Body::isBuffered(PxU32 flag) const
+{
+ return Ps::IntBool(mBodyBufferFlags & flag);
+}
+
+PX_INLINE void Body::syncCollisionWriteThroughState()
+{
+ PxU32 bufferFlags = mBodyBufferFlags;
+
+ //----
+ if ((bufferFlags & Buf::BF_LinearVelocity) == 0)
+ mBufferedLinVelocity = mBodyCore.getLinearVelocity();
+ else
+ {
+ PX_ASSERT( (mBufferedIsSleeping && mBufferedLinVelocity.isZero()) ||
+ (!mBufferedIsSleeping) ||
+ (getControlState() == ControlState::eREMOVE_PENDING));
+ PX_ASSERT( mBufferedLinVelocity.isZero() ||
+ ((!mBufferedLinVelocity.isZero()) && (!mBufferedIsSleeping)) ||
+ (getControlState() == ControlState::eREMOVE_PENDING));
+
+ mBodyCore.setLinearVelocity(mBufferedLinVelocity);
+ //clear the flag
+ bufferFlags &= ~Buf::BF_LinearVelocity;
+ }
+
+ //----
+
+ if ((bufferFlags & Buf::BF_AngularVelocity) == 0)
+ mBufferedAngVelocity = mBodyCore.getAngularVelocity();
+ else
+ {
+ PX_ASSERT( (mBufferedIsSleeping && mBufferedAngVelocity.isZero()) ||
+ (!mBufferedIsSleeping) ||
+ (getControlState() == ControlState::eREMOVE_PENDING));
+ PX_ASSERT( mBufferedAngVelocity.isZero() ||
+ ((!mBufferedAngVelocity.isZero()) && (!mBufferedIsSleeping)) ||
+ (getControlState() == ControlState::eREMOVE_PENDING));
+
+ mBodyCore.setAngularVelocity(mBufferedAngVelocity);
+ //clear the flag
+ bufferFlags &= ~Buf::BF_AngularVelocity;
+ }
+
+ //----
+
+ if (bufferFlags & Buf::BF_KinematicTarget)
+ {
+ //don't apply kinematic target unless the actor is kinematic already. setKinematicTarget is write-through properties for split sim but setRigidBodyFlag transition from rigid body to kinematic isn't write-through
+ if(mBodyCore.getFlags() & PxRigidBodyFlag::eKINEMATIC)
+ {
+ Buf& buffer = *getBodyBuffer();
+ PX_ASSERT(mBufferedWakeCounter > 0.0f); // that is the expected behavior
+
+ mBodyCore.setKinematicTarget(getScbScene()->getScScene().getSimStateDataPool(), buffer.mKinematicTarget, mBufferedWakeCounter);
+ //clear the flag
+ bufferFlags &= ~Buf::BF_KinematicTarget;
+ }
+ }
+
+ //----
+ //in case user call addForce(), collide(), clearForce(), which we need to clear the acclearation in the low-level
+ if(bufferFlags & Buf::BF_ClearAcceleration)
+ {
+ PX_ASSERT(!(mBodyCore.getFlags() & PxRigidBodyFlag::eKINEMATIC));
+ PX_ASSERT(!mBufferedIsSleeping);
+ mBodyCore.clearSpatialAcceleration((bufferFlags & Buf::BF_ClearAccelerationLinear)!=0, (bufferFlags & Buf::BF_ClearAccelerationAngular)!=0);
+
+ //clear the flag, we don't clear the buffered acceleration, because the user might call addForce() again after calling clearForce()
+ bufferFlags &= ~Buf::BF_ClearAcceleration;
+ }
+
+ //----
+
+ //apply addForce/clearForce, addTorque/clearTorque
+ if(bufferFlags & Buf::BF_Acceleration)
+ {
+ Buf& buffer = *getBodyBuffer();
+ PX_ASSERT(!(mBodyCore.getFlags() & PxRigidBodyFlag::eKINEMATIC));
+ PX_ASSERT(!mBufferedIsSleeping || (buffer.mLinAcceleration.isZero() && buffer.mAngAcceleration.isZero()));
+ mBodyCore.addSpatialAcceleration(getScbScene()->getScScene().getSimStateDataPool(), &buffer.mLinAcceleration, &buffer.mAngAcceleration);
+
+ //clear the flag
+ bufferFlags &= ~Buf::BF_Acceleration;
+ buffer.mLinAcceleration = PxVec3(0.0f);
+ buffer.mAngAcceleration = PxVec3(0.0f);
+ }
+
+ //----
+
+ if(bufferFlags & Buf::BF_ClearDeltaVelocity)
+ {
+ PX_ASSERT(!(mBodyCore.getFlags() & PxRigidBodyFlag::eKINEMATIC));
+ PX_ASSERT(!mBufferedIsSleeping );
+ mBodyCore.clearSpatialVelocity((bufferFlags & Buf::BF_ClearDeltaVelocityLinear)!=0, (bufferFlags & Buf::BF_ClearDeltaVelocityAngular)!=0);
+
+ //clear the flag, we don't clear the buffered velocity, because the user might call addForce() again after calling clearForce()
+ bufferFlags &= ~Buf::BF_ClearDeltaVelocity;
+ }
+
+ //----
+
+ if(bufferFlags & Buf::BF_DeltaVelocity)
+ {
+ Buf& buffer = *getBodyBuffer();
+ PX_ASSERT(!(mBodyCore.getFlags() & PxRigidBodyFlag::eKINEMATIC));
+ PX_ASSERT(!mBufferedIsSleeping || (buffer.mLinDeltaVelocity.isZero() && buffer.mAngDeltaVelocity.isZero()));
+ mBodyCore.addSpatialVelocity(getScbScene()->getScScene().getSimStateDataPool(), &buffer.mLinDeltaVelocity, &buffer.mAngDeltaVelocity);
+
+ //clear the flag
+ bufferFlags &= ~Buf::BF_DeltaVelocity;
+ buffer.mLinDeltaVelocity = PxVec3(0.0f);
+ buffer.mAngDeltaVelocity = PxVec3(0.0f);
+ }
+
+ //----
+
+ if ((bufferFlags & Buf::BF_WakeCounter) == 0)
+ mBufferedWakeCounter = mBodyCore.getWakeCounter();
+ else if (!(bufferFlags & (Buf::BF_WakeUp | Buf::BF_PutToSleep))) // if there has been at least one buffered sleep state transition, then there is no use in adjusting the wake counter separately because it will
+ // get done in the sleep state update.
+ {
+ PX_ASSERT((getControlState() == ControlState::eREMOVE_PENDING) || (mBufferedWakeCounter == 0.0f)); // a wake counter change is always connected to a sleep state change, except if setWakeCounter(0.0f) was called or an object gets removed from the scene after it was woken up.
+
+ mBodyCore.setWakeCounter(mBufferedWakeCounter);
+
+ bufferFlags &= ~Buf::BF_WakeCounter;
+ }
+ else if(bufferFlags & Buf::BF_WakeUp)
+ {
+ Buf& buffer = *getBodyBuffer();
+ //Because in the split sim, transition from rigid body to kinematic isn't a write through properties. However, when the user call setKinematicTarget, the SDK wake up the actor so we want to avoid waking up the
+ //actor if the actor is transitioning from rigid body to kinematic or vice versa.
+ PxRigidBodyFlags changeFlags= mBodyCore.getFlags() ^ buffer.mRigidBodyFlags;
+ if(!((bufferFlags & Buf::BF_RigidBodyFlags) && (changeFlags & PxRigidBodyFlag::eKINEMATIC)))
+ {
+ PX_ASSERT(bufferFlags & Buf::BF_WakeCounter); // sleep state transitions always mark the wake counter dirty
+ PX_ASSERT(getControlState() != ControlState::eREMOVE_PENDING); // removing an object should clear pending wakeUp/putToSleep operations since the state for a free standing object gets set according to specification.
+
+ // The sleep state ends up with the proper result that reflects the order of the original buffered operations because...
+ // - every operation that affects the sleep state makes a buffered call to wakeUp/putToSleep, hence, the buffered sleep transition
+ // will always reflect the latest change
+ // - a user triggered sleep state transition (wakeUp/putToSleep) always adjusts the affected properties (velocity, force, wake counter...) through separate
+ // buffered calls, hence, those properties will get adjusted to the correct values in the end
+ // - sleep state sync runs after all calls that have side effects on the sleep state.
+ //
+ PX_ASSERT(!mBufferedIsSleeping);
+ PX_ASSERT(bufferFlags & Buf::BF_WakeUp);
+
+ // can not assert for any values here since it is possible, for example, to end up waking something up with a 0 wakeCounter here (as a consequence of a buffered wakeUp() followed by a setWakeCounter(0))
+
+ mBodyCore.wakeUp(mBufferedWakeCounter);
+
+ bufferFlags &= ~(Buf::BF_WakeUp | Buf::BF_WakeCounter);
+ }
+ }
+
+ //----
+
+ mBodyBufferFlags = bufferFlags;
+}
+
+PX_INLINE void Body::syncState()
+{
+ // if the body was removed from the scene, we expect...
+ // ...it to be marked as sleeping (that is the specification)
+ // ...no pending sleep state change (because wakeUp/putTosleep is illegal for a free standing object and we clear such operations if pending).
+ // Note: a sleep state change might have happened before the removal but the corresponding wake counter change is then covered through the BF_WakeCounter dirty flag.
+ PX_ASSERT( (getControlState() != ControlState::eREMOVE_PENDING) ||
+ (mBufferedIsSleeping && (!isBuffered(Buf::BF_WakeUp | Buf::BF_PutToSleep))) );
+
+
+ //
+ // IMPORTANT: Since we ran out of space for buffered property flags, the Scb::Body property related flags are stored in mBodyBufferFlags.
+ // To get the buffer flags from the base classes, use getBufferFlags()
+ //
+ const PxU32 bufferFlags = mBodyBufferFlags;
+ const PxU32 baseBufferFlags = getBufferFlags();
+
+ if ((bufferFlags & Buf::BF_Body2World) == 0)
+ mBufferedBody2World = mBodyCore.getBody2World();
+ else if ((bufferFlags & Buf::BF_Body2World_CoM) == 0)
+ mBodyCore.setBody2World(mBufferedBody2World);
+ else
+ {
+ // IMPORTANT: Do this before adjusting body2Actor
+ PX_ASSERT(bufferFlags & Buf::BF_Body2Actor);
+ Buf& buffer = *getBodyBuffer();
+ const PxTransform newBody2oldBody = mBodyCore.getBody2Actor().transformInv(buffer.mBody2Actor);
+
+ PxTransform b2w = mBodyCore.getBody2World();
+ b2w = b2w.transform(newBody2oldBody); // translate simulation result from old CoM to new CoM
+
+ mBufferedBody2World = b2w;
+ mBodyCore.setBody2World(b2w);
+ }
+
+ //----
+
+ if (baseBufferFlags & Buf::BF_ActorFlags)
+ syncNoSimSwitch(*getBodyBuffer(), mBodyCore, true);
+
+ //----
+
+ if(bufferFlags & ~( Buf::BF_WakeCounter|Buf::BF_Body2World|Buf::BF_LinearVelocity|Buf::BF_AngularVelocity
+ |Buf::BF_WakeUp|Buf::BF_PutToSleep)) // Optimization to avoid all the if-statements below if possible
+ {
+ Buf& buffer = *getBodyBuffer();
+
+ flush<Buf::BF_InverseMass>(buffer);
+ flush<Buf::BF_InverseInertia>(buffer);
+ flush<Buf::BF_LinearDamping>(buffer);
+ flush<Buf::BF_AngularDamping>(buffer);
+ flush<Buf::BF_MaxAngVelSq>(buffer);
+ flush<Buf::BF_SleepThreshold>(buffer);
+ flush<Buf::BF_SolverIterationCounts>(buffer);
+ flush<Buf::BF_ContactReportThreshold>(buffer);
+ flush<Buf::BF_Body2Actor>(buffer);
+ flush<Buf::BF_FreezeThreshold>(buffer);
+ flush<Buf::BF_MaxPenetrationBias>(buffer);
+ flush<Buf::BF_MaxContactImpulse>(buffer);
+ if (bufferFlags & Buf::BF_RigidBodyFlags)
+ {
+ mBodyCore.setFlags(getScbScene()->getScScene().getSimStateDataPool(), buffer.mRigidBodyFlags);
+ }
+ }
+
+
+ //This method sync all the write through properties in collision and is called in fetchCollision()
+ syncCollisionWriteThroughState();
+
+ //----
+
+ bool isSimObjectSleeping = mBodyCore.isSleeping();
+ if ((bufferFlags & (Buf::BF_PutToSleep)) == 0)
+ {
+ if (getControlState() != ControlState::eREMOVE_PENDING) // we do not want to sync the simulation sleep state if the object was removed (free standing objects have buffered state sleeping)
+ mBufferedIsSleeping = PxU32(isSimObjectSleeping);
+ else
+ PX_ASSERT(mBufferedIsSleeping); // this must get set immediately at remove
+ }
+ else
+ {
+ PX_ASSERT(bufferFlags & Buf::BF_WakeCounter); // sleep state transitions always mark the wake counter dirty
+ PX_ASSERT(getControlState() != ControlState::eREMOVE_PENDING); // removing an object should clear pending wakeUp/putToSleep operations since the state for a free standing object gets set according to specification.
+
+ // The sleep state ends up with the proper result that reflects the order of the original buffered operations because...
+ // - every operation that affects the sleep state makes a buffered call to wakeUp/putToSleep, hence, the buffered sleep transition
+ // will always reflect the latest change
+ // - a user triggered sleep state transition (wakeUp/putToSleep) always adjusts the affected properties (velocity, force, wake counter...) through separate
+ // buffered calls, hence, those properties will get adjusted to the correct values in the end
+ // - sleep state sync runs after all calls that have side effects on the sleep state.
+ //
+
+ PX_ASSERT(mBufferedIsSleeping);
+ PX_ASSERT(!(bufferFlags & Buf::BF_WakeUp));
+ PX_ASSERT(mBufferedWakeCounter == 0.0f);
+ PX_ASSERT(mBufferedLinVelocity.isZero());
+ PX_ASSERT(mBufferedAngVelocity.isZero());
+ PX_ASSERT(!(bufferFlags & Buf::BF_Acceleration));
+ PX_ASSERT(!(bufferFlags & Buf::BF_DeltaVelocity));
+
+ mBodyCore.putToSleep();
+ }
+
+ // PT: we must call this even when there's no buffered data
+ RigidObject::syncState();
+
+ // --------------
+ // postconditions
+ //
+ PX_ASSERT((getControlState() != ControlState::eREMOVE_PENDING) || mBufferedIsSleeping); // nothing in this method should change this
+#ifdef _DEBUG
+ // make sure that for a removed kinematic, the buffered params hold the values as defined in our specification
+ if ((mBodyCore.getFlags() & PxRigidBodyFlag::eKINEMATIC) && (getControlState() == ControlState::eREMOVE_PENDING))
+ {
+ PX_ASSERT(mBufferedLinVelocity.isZero());
+ PX_ASSERT(mBufferedAngVelocity.isZero());
+ PX_ASSERT(mBufferedWakeCounter == 0.0f);
+ }
+#endif
+ //
+ // postconditions
+ // --------------
+
+ postSyncState();
+ mBodyBufferFlags = 0;
+}
+
+} // namespace Scb
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbCloth.cpp b/PhysX_3.4/Source/PhysX/src/buffering/ScbCloth.cpp
new file mode 100644
index 00000000..ecee8baa
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbCloth.cpp
@@ -0,0 +1,60 @@
+// 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 "PxPhysXConfig.h"
+
+#if PX_USE_CLOTH_API
+
+#include "ScbCloth.h"
+
+using namespace physx;
+
+Scb::Cloth::Cloth(const PxTransform& globalPose, Sc::ClothFabricCore& fabric, const PxClothParticle* particles, PxClothFlags flags) :
+ mCloth(globalPose, fabric, particles, flags)
+{
+ setScbType(ScbType::CLOTH);
+}
+
+
+Scb::Cloth::~Cloth()
+{
+}
+
+
+void Scb::Cloth::syncState()
+{
+ if (getBufferFlags()) // Optimization to avoid all the if-statements below if possible
+ {
+ Actor::syncState();
+ }
+
+ postSyncState();
+}
+
+#endif // PX_USE_CLOTH_API
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbCloth.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbCloth.h
new file mode 100644
index 00000000..238df91f
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbCloth.h
@@ -0,0 +1,1195 @@
+// 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_SCB_CLOTH
+#define PX_PHYSICS_SCB_CLOTH
+
+#include "PxPhysXConfig.h"
+
+#if PX_USE_CLOTH_API
+
+#include "ScbActor.h"
+
+#include "ScClothCore.h"
+#include "NpClothParticleData.h"
+
+namespace physx
+{
+
+struct PxClothCollisionSphere;
+
+namespace Scb
+{
+
+class Cloth : public Scb::Actor
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+
+public:
+// PX_SERIALIZATION
+ Cloth(const PxEMPTY) : Scb::Actor(PxEmpty), mCloth(PxEmpty) {}
+ void exportExtraData(PxSerializationContext& stream) { mCloth.exportExtraData(stream); }
+ void importExtraData(PxDeserializationContext &context) { mCloth.importExtraData(context); }
+ void resolveReferences(Sc::ClothFabricCore& fabric) { mCloth.resolveReferences(fabric); }
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ Cloth(const PxTransform& globalPose, Sc::ClothFabricCore& fabric, const PxClothParticle* particles, PxClothFlags flags);
+ ~Cloth();
+
+ //---------------------------------------------------------------------------------
+ // Wrapper for Sc::ClothCore interface
+ //---------------------------------------------------------------------------------
+
+ PX_INLINE Sc::ClothFabricCore* getFabric() const;
+ PX_INLINE void resetFabric();
+
+ PX_INLINE void setParticles(const PxClothParticle* currentParticles, const PxClothParticle* previousParticles);
+ PX_INLINE PxU32 getNbParticles() const;
+
+ PX_INLINE void setMotionConstraints(const PxClothParticleMotionConstraint* motionConstraints);
+ PX_INLINE bool getMotionConstraints(PxClothParticleMotionConstraint* motionConstraintsBuffer) const;
+ PX_INLINE PxU32 getNbMotionConstraints() const;
+
+ PX_INLINE PxClothMotionConstraintConfig getMotionConstraintConfig() const;
+ PX_INLINE void setMotionConstraintConfig(const PxClothMotionConstraintConfig& config);
+
+ PX_INLINE void setSeparationConstraints(const PxClothParticleSeparationConstraint* separationConstraints);
+ PX_INLINE bool getSeparationConstraints(PxClothParticleSeparationConstraint* separationConstraintsBuffer) const;
+ PX_INLINE PxU32 getNbSeparationConstraints() const;
+
+ PX_INLINE void clearInterpolation();
+
+ PX_INLINE void setParticleAccelerations(const PxVec4* particleAccelerations);
+ PX_INLINE bool getParticleAccelerations(PxVec4* particleAccelerationsBuffer) const;
+ PX_INLINE PxU32 getNbParticleAccelerations() const;
+
+ PX_INLINE void addCollisionSphere(const PxClothCollisionSphere& sphere);
+ PX_INLINE void removeCollisionSphere(PxU32 index);
+ PX_INLINE void setCollisionSpheres(const PxClothCollisionSphere* spheresBuffer, PxU32 count);
+ PX_INLINE PxU32 getNbCollisionSpheres() const;
+
+ PX_INLINE void getCollisionData(PxClothCollisionSphere* spheresBuffer, PxU32* capsulesBuffer,
+ PxClothCollisionPlane* planesBuffer, PxU32* convexesBuffer, PxClothCollisionTriangle* trianglesBuffer) const;
+
+ PX_INLINE void addCollisionCapsule(PxU32 first, PxU32 second);
+ PX_INLINE void removeCollisionCapsule(PxU32 index);
+ PX_INLINE PxU32 getNbCollisionCapsules() const;
+
+ PX_INLINE void addCollisionTriangle(const PxClothCollisionTriangle& triangle);
+ PX_INLINE void removeCollisionTriangle(PxU32 index);
+ PX_INLINE void setCollisionTriangles(const PxClothCollisionTriangle* trianglesBuffer, PxU32 count);
+ PX_INLINE PxU32 getNbCollisionTriangles() const;
+
+ PX_INLINE void addCollisionPlane(const PxClothCollisionPlane& plane);
+ PX_INLINE void removeCollisionPlane(PxU32 index);
+ PX_INLINE void setCollisionPlanes(const PxClothCollisionPlane* planesBuffer, PxU32 count);
+ PX_INLINE PxU32 getNbCollisionPlanes() const;
+
+ PX_INLINE void addCollisionConvex(PxU32 mask);
+ PX_INLINE void removeCollisionConvex(PxU32 index);
+ PX_INLINE PxU32 getNbCollisionConvexes() const;
+
+ PX_INLINE void setVirtualParticles(PxU32 numParticles, const PxU32* indices, PxU32 numWeights, const PxVec3* weights);
+
+ PX_INLINE PxU32 getNbVirtualParticles() const;
+ PX_INLINE void getVirtualParticles(PxU32* indicesBuffer) const;
+
+ PX_INLINE PxU32 getNbVirtualParticleWeights() const;
+ PX_INLINE void getVirtualParticleWeights(PxVec3* weightsBuffer) const;
+
+ PX_INLINE PxTransform getGlobalPose() const;
+ PX_INLINE void setGlobalPose(const PxTransform& pose);
+
+ PX_INLINE void setTargetPose(const PxTransform& pose);
+
+ PX_INLINE PxVec3 getExternalAcceleration() const;
+ PX_INLINE void setExternalAcceleration(PxVec3 acceleration);
+
+ PX_INLINE PxVec3 getLinearInertiaScale() const;
+ PX_INLINE void setLinearInertiaScale(PxVec3 scale);
+ PX_INLINE PxVec3 getAngularInertiaScale() const;
+ PX_INLINE void setAngularInertiaScale(PxVec3 scale);
+ PX_INLINE PxVec3 getCentrifugalInertiaScale() const;
+ PX_INLINE void setCentrifugalInertiaScale(PxVec3 scale);
+
+ PX_INLINE PxVec3 getDampingCoefficient() const;
+ PX_INLINE void setDampingCoefficient(PxVec3 dampingCoefficient);
+
+ PX_INLINE PxReal getFrictionCoefficient() const;
+ PX_INLINE void setFrictionCoefficient(PxReal frictionCoefficient);
+
+ PX_INLINE PxVec3 getLinearDragCoefficient() const;
+ PX_INLINE void setLinearDragCoefficient(PxVec3 dragCoefficient);
+ PX_INLINE PxVec3 getAngularDragCoefficient() const;
+ PX_INLINE void setAngularDragCoefficient(PxVec3 dragCoefficient);
+
+ PX_INLINE PxReal getCollisionMassScale() const;
+ PX_INLINE void setCollisionMassScale(PxReal scalingCoefficient);
+
+ PX_INLINE void setSelfCollisionDistance(PxReal distance);
+ PX_INLINE PxReal getSelfCollisionDistance() const;
+ PX_INLINE void setSelfCollisionStiffness(PxReal stiffness);
+ PX_INLINE PxReal getSelfCollisionStiffness() const;
+
+ PX_INLINE void setSelfCollisionIndices(const PxU32* indices, PxU32 nbIndices);
+ PX_INLINE bool getSelfCollisionIndices(PxU32* indices) const;
+ PX_INLINE PxU32 getNbSelfCollisionIndices() const;
+
+ PX_INLINE void setRestPositions(const PxVec4* restPositions);
+ PX_INLINE bool getRestPositions(PxVec4* restPositions) const;
+ PX_INLINE PxU32 getNbRestPositions() const;
+
+ PX_INLINE PxReal getSolverFrequency() const;
+ PX_INLINE void setSolverFrequency(PxReal);
+
+ PX_INLINE PxReal getStiffnessFrequency() const;
+ PX_INLINE void setStiffnessFrequency(PxReal);
+
+ PX_INLINE void setStretchConfig(PxClothFabricPhaseType::Enum type, const PxClothStretchConfig& config);
+ PX_INLINE void setTetherConfig(const PxClothTetherConfig& config);
+
+ PX_INLINE PxClothStretchConfig getStretchConfig(PxClothFabricPhaseType::Enum type) const;
+ PX_INLINE PxClothTetherConfig getTetherConfig() const;
+
+ PX_INLINE PxClothFlags getClothFlags() const;
+ PX_INLINE void setClothFlags(PxClothFlags flags);
+
+ PX_INLINE PxVec3 getWindVelocity() const;
+ PX_INLINE void setWindVelocity(PxVec3);
+ PX_INLINE PxReal getDragCoefficient() const;
+ PX_INLINE void setDragCoefficient(PxReal);
+ PX_INLINE PxReal getLiftCoefficient() const;
+ PX_INLINE void setLiftCoefficient(PxReal);
+
+ PX_INLINE bool isSleeping() const;
+ PX_INLINE PxReal getSleepLinearVelocity() const;
+ PX_INLINE void setSleepLinearVelocity(PxReal threshold);
+ PX_INLINE void setWakeCounter(PxReal wakeCounterValue);
+ PX_INLINE PxReal getWakeCounter() const;
+ PX_INLINE void wakeUp();
+ PX_INLINE void putToSleep();
+
+ PX_INLINE void getParticleData(NpClothParticleData&);
+
+ PX_INLINE PxReal getPreviousTimeStep() const;
+
+ PX_INLINE PxBounds3 getWorldBounds() const;
+
+ PX_INLINE void setSimulationFilterData(const PxFilterData& data);
+ PX_INLINE PxFilterData getSimulationFilterData() const;
+
+ PX_INLINE void setContactOffset(PxReal);
+ PX_INLINE PxReal getContactOffset() const;
+ PX_INLINE void setRestOffset(PxReal);
+ PX_INLINE PxReal getRestOffset() const;
+
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+
+ // Synchronously called with fetchResults.
+ void syncState();
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ PX_FORCE_INLINE const Sc::ClothCore& getScCloth() const { return mCloth; } // Only use if you know what you're doing!
+ PX_FORCE_INLINE Sc::ClothCore& getScCloth() { return mCloth; } // Only use if you know what you're doing!
+
+ static size_t getScOffset()
+ {
+ return reinterpret_cast<size_t>(&reinterpret_cast<Cloth*>(0)->mCloth);
+ }
+
+private:
+ Sc::ClothCore mCloth;
+};
+
+
+PX_INLINE Sc::ClothFabricCore* Cloth::getFabric() const
+{
+ return mCloth.getFabric();
+}
+
+PX_INLINE void Cloth::resetFabric()
+{
+ return mCloth.resetFabric();
+}
+
+PX_INLINE void Cloth::setParticles(const PxClothParticle* currentParticles, const PxClothParticle* previousParticles)
+{
+ if (!isBuffering())
+ mCloth.setParticles(currentParticles, previousParticles);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setParticles() not allowed while simulation is running.");
+}
+
+PX_INLINE PxU32 Cloth::getNbParticles() const
+{
+ return mCloth.getNbParticles();
+}
+
+PX_INLINE void Cloth::setMotionConstraints(const PxClothParticleMotionConstraint* motionConstraints)
+{
+ if (!isBuffering())
+ mCloth.setMotionConstraints(motionConstraints);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setMotionConstraints() not allowed while simulation is running.");
+}
+
+
+PX_INLINE bool Cloth::getMotionConstraints(PxClothParticleMotionConstraint* motionConstraintsBuffer) const
+{
+ if (!isBuffering())
+ return mCloth.getMotionConstraints(motionConstraintsBuffer);
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getMotionConstraints() not allowed while simulation is running.");
+ return false;
+ }
+}
+
+PX_INLINE PxU32 Cloth::getNbMotionConstraints() const
+{
+ return mCloth.getNbMotionConstraints();
+}
+
+PX_INLINE PxClothMotionConstraintConfig Cloth::getMotionConstraintConfig() const
+{
+ if (!isBuffering())
+ return mCloth.getMotionConstraintConfig();
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getMotionConstraintScaleBias() not allowed while simulation is running.");
+
+ return PxClothMotionConstraintConfig();
+}
+
+
+PX_INLINE void Cloth::setMotionConstraintConfig(const PxClothMotionConstraintConfig& config)
+{
+ if (!isBuffering())
+ mCloth.setMotionConstraintConfig(config);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setMotionConstraintConfig() not allowed while simulation is running.");
+}
+
+PX_INLINE void Cloth::setSeparationConstraints(const PxClothParticleSeparationConstraint* separationConstraints)
+{
+ if (!isBuffering())
+ mCloth.setSeparationConstraints(separationConstraints);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setSeparationConstraints() not allowed while simulation is running.");
+}
+
+
+PX_INLINE bool Cloth::getSeparationConstraints(PxClothParticleSeparationConstraint* separationConstraintsBuffer) const
+{
+ if (!isBuffering())
+ return mCloth.getSeparationConstraints(separationConstraintsBuffer);
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getSeparationConstraints() not allowed while simulation is running.");
+ return false;
+ }
+}
+
+PX_INLINE PxU32 Cloth::getNbSeparationConstraints() const
+{
+ return mCloth.getNbSeparationConstraints();
+}
+
+PX_INLINE void Cloth::clearInterpolation()
+{
+ return mCloth.clearInterpolation();
+}
+
+PX_INLINE void Cloth::setParticleAccelerations(const PxVec4* particleAccelerations)
+{
+ if (!isBuffering())
+ mCloth.setParticleAccelerations(particleAccelerations);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setParticleAccelerations() not allowed while simulation is running.");
+}
+
+
+PX_INLINE bool Cloth::getParticleAccelerations(PxVec4* particleAccelerationsBuffer) const
+{
+ if (!isBuffering())
+ return mCloth.getParticleAccelerations(particleAccelerationsBuffer);
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getParticleAccelerations() not allowed while simulation is running.");
+ return false;
+ }
+}
+
+PX_INLINE PxU32 Cloth::getNbParticleAccelerations() const
+{
+ return mCloth.getNbParticleAccelerations();
+}
+
+PX_INLINE void Cloth::addCollisionSphere(const PxClothCollisionSphere& sphere)
+{
+ if (!isBuffering())
+ mCloth.addCollisionSphere(sphere);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::addCollisionSphere() not allowed while simulation is running.");
+}
+PX_INLINE void Cloth::removeCollisionSphere(PxU32 index)
+{
+ if (!isBuffering())
+ mCloth.removeCollisionSphere(index);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::removeCollisionSphere() not allowed while simulation is running.");
+}
+PX_INLINE void Cloth::setCollisionSpheres(const PxClothCollisionSphere* spheresBuffer, PxU32 count)
+{
+ if (!isBuffering())
+ mCloth.setCollisionSpheres(spheresBuffer, count);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setCollisionSpheres() not allowed while simulation is running.");
+}
+PX_INLINE PxU32 Cloth::getNbCollisionSpheres() const
+{
+ if (!isBuffering())
+ return mCloth.getNbCollisionSpheres();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getNbCollisionSpheres() not allowed while simulation is running.");
+ return 0;
+ }
+}
+
+PX_INLINE void Cloth::getCollisionData( PxClothCollisionSphere* spheresBuffer, PxU32* capsulesBuffer,
+ PxClothCollisionPlane* planesBuffer, PxU32* convexesBuffer, PxClothCollisionTriangle* trianglesBuffer ) const
+{
+ if (!isBuffering())
+ mCloth.getCollisionData(spheresBuffer, capsulesBuffer, planesBuffer, convexesBuffer, trianglesBuffer);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getCollisionData() not allowed while simulation is running.");
+}
+
+
+PX_INLINE void Cloth::addCollisionCapsule(PxU32 first, PxU32 second)
+{
+ if (!isBuffering())
+ mCloth.addCollisionCapsule(first, second);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::addCollisionCapsule() not allowed while simulation is running.");
+}
+PX_INLINE void Cloth::removeCollisionCapsule(PxU32 index)
+{
+ if (!isBuffering())
+ mCloth.removeCollisionCapsule(index);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::removeCollisionCapsule() not allowed while simulation is running.");
+}
+PX_INLINE PxU32 Cloth::getNbCollisionCapsules() const
+{
+ if (!isBuffering())
+ return mCloth.getNbCollisionCapsules();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getNbCollisionCapsules() not allowed while simulation is running.");
+ return 0;
+ }
+}
+
+PX_INLINE void Cloth::addCollisionTriangle(const PxClothCollisionTriangle& triangle)
+{
+ if (!isBuffering())
+ mCloth.addCollisionTriangle(triangle);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::addCollisionTriangle() not allowed while simulation is running.");
+}
+PX_INLINE void Cloth::removeCollisionTriangle(PxU32 index)
+{
+ if (!isBuffering())
+ mCloth.removeCollisionTriangle(index);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::removeCollisionTriangle() not allowed while simulation is running.");
+}
+PX_INLINE void Cloth::setCollisionTriangles(const PxClothCollisionTriangle* trianglesBuffer, PxU32 count)
+{
+ if (!isBuffering())
+ mCloth.setCollisionTriangles(trianglesBuffer, count);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setCollisionTriangles() not allowed while simulation is running.");
+}
+PX_INLINE PxU32 Cloth::getNbCollisionTriangles() const
+{
+ if (!isBuffering())
+ return mCloth.getNbCollisionTriangles();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getNbCollisionTriangles() not allowed while simulation is running.");
+ return 0;
+ }
+}
+
+PX_INLINE void Cloth::addCollisionPlane(const PxClothCollisionPlane& plane)
+{
+ if (!isBuffering())
+ mCloth.addCollisionPlane(plane);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::addCollisionPlane() not allowed while simulation is running.");
+}
+PX_INLINE void Cloth::removeCollisionPlane(PxU32 index)
+{
+ if (!isBuffering())
+ mCloth.removeCollisionPlane(index);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::removeCollisionPlane() not allowed while simulation is running.");
+}
+PX_INLINE void Cloth::setCollisionPlanes(const PxClothCollisionPlane* planesBuffer, PxU32 count)
+{
+ if (!isBuffering())
+ mCloth.setCollisionPlanes(planesBuffer, count);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setCollisionPlanes() not allowed while simulation is running.");
+}
+PX_INLINE PxU32 Cloth::getNbCollisionPlanes() const
+{
+ if (!isBuffering())
+ return mCloth.getNbCollisionPlanes();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getNbCollisionPlanes() not allowed while simulation is running.");
+ return 0;
+ }
+}
+
+PX_INLINE void Cloth::addCollisionConvex(PxU32 mask)
+{
+ if (!isBuffering())
+ mCloth.addCollisionConvex(mask);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::addCollisionConvex() not allowed while simulation is running.");
+}
+PX_INLINE void Cloth::removeCollisionConvex(PxU32 index)
+{
+ if (!isBuffering())
+ mCloth.removeCollisionConvex(index);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::removeCollisionConvex() not allowed while simulation is running.");
+}
+PX_INLINE PxU32 Cloth::getNbCollisionConvexes() const
+{
+ if (!isBuffering())
+ return mCloth.getNbCollisionConvexes();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getNbCollisionConvexes() not allowed while simulation is running.");
+ return 0;
+ }
+}
+
+
+PX_INLINE void Cloth::setVirtualParticles(PxU32 numParticles, const PxU32* indices, PxU32 numWeights, const PxVec3* weights)
+{
+ if (!isBuffering())
+ mCloth.setVirtualParticles(numParticles, indices, numWeights, weights);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setVirtualParticles() not allowed while simulation is running.");
+}
+
+
+PX_INLINE PxU32 Cloth::getNbVirtualParticles() const
+{
+ if (!isBuffering())
+ return mCloth.getNbVirtualParticles();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getNbVirtualParticles() not allowed while simulation is running.");
+ return 0;
+ }
+}
+
+
+PX_INLINE void Cloth::getVirtualParticles(PxU32* indicesBuffer) const
+{
+ if (!isBuffering())
+ mCloth.getVirtualParticles(indicesBuffer);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getVirtualParticles() not allowed while simulation is running.");
+}
+
+
+PX_INLINE PxU32 Cloth::getNbVirtualParticleWeights() const
+{
+ if (!isBuffering())
+ return mCloth.getNbVirtualParticleWeights();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getNbVirtualParticleWeights() not allowed while simulation is running.");
+ return 0;
+ }
+}
+
+
+PX_INLINE void Cloth::getVirtualParticleWeights(PxVec3* weightsBuffer) const
+{
+ if (!isBuffering())
+ mCloth.getVirtualParticleWeights(weightsBuffer);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getVirtualParticleWeights() not allowed while simulation is running.");
+}
+
+
+PX_INLINE PxTransform Cloth::getGlobalPose() const
+{
+ if (!isBuffering())
+ return mCloth.getGlobalPose();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getGlobalPose() not allowed while simulation is running.");
+ return PxTransform(PxIdentity);
+ }
+}
+
+
+PX_INLINE void Cloth::setGlobalPose(const PxTransform& pose)
+{
+ if (!isBuffering())
+ mCloth.setGlobalPose(pose);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setGlobalPose() not allowed while simulation is running.");
+}
+
+
+PX_INLINE void Cloth::setTargetPose(const PxTransform& pose)
+{
+ if (!isBuffering())
+ mCloth.setTargetPose(pose);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setTargetPose() not allowed while simulation is running.");
+}
+
+
+PX_INLINE PxVec3 Cloth::getExternalAcceleration() const
+{
+ if (!isBuffering())
+ return mCloth.getExternalAcceleration();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getExternalAcceleration() not allowed while simulation is running.");
+ return PxVec3(0.0f);
+ }
+}
+
+
+PX_INLINE void Cloth::setExternalAcceleration(PxVec3 acceleration)
+{
+ if (!isBuffering())
+ mCloth.setExternalAcceleration(acceleration);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setExternalAcceleration() not allowed while simulation is running.");
+}
+
+PX_INLINE PxVec3 Cloth::getLinearInertiaScale() const
+{
+ if (!isBuffering())
+ return mCloth.getLinearInertiaScale();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getLinearInertiaScale() not allowed while simulation is running.");
+ return PxVec3(0.0f);
+ }
+}
+
+
+PX_INLINE void Cloth::setLinearInertiaScale(PxVec3 scale)
+{
+ if (!isBuffering())
+ mCloth.setLinearInertiaScale(scale);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setLinearInertiaScale() not allowed while simulation is running.");
+}
+
+PX_INLINE PxVec3 Cloth::getAngularInertiaScale() const
+{
+ if (!isBuffering())
+ return mCloth.getAngularInertiaScale();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getAngularInertiaScale() not allowed while simulation is running.");
+ return PxVec3(0.0f);
+ }
+}
+
+
+PX_INLINE void Cloth::setAngularInertiaScale(PxVec3 scale)
+{
+ if (!isBuffering())
+ mCloth.setAngularInertiaScale(scale);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setAngularInertiaScale() not allowed while simulation is running.");
+}
+
+PX_INLINE PxVec3 Cloth::getCentrifugalInertiaScale() const
+{
+ if (!isBuffering())
+ return mCloth.getCentrifugalInertiaScale();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getCentrifugalInertiaScale() not allowed while simulation is running.");
+ return PxVec3(0.0f);
+ }
+}
+
+
+PX_INLINE void Cloth::setCentrifugalInertiaScale(PxVec3 scale)
+{
+ if (!isBuffering())
+ mCloth.setCentrifugalInertiaScale(scale);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setCentrifugalInertiaScale() not allowed while simulation is running.");
+}
+
+PX_INLINE PxVec3 Cloth::getDampingCoefficient() const
+{
+ if (!isBuffering())
+ return mCloth.getDampingCoefficient();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getDampingCoefficient() not allowed while simulation is running.");
+ return PxVec3(0.0f);
+ }
+}
+
+
+PX_INLINE void Cloth::setDampingCoefficient(PxVec3 dampingCoefficient)
+{
+ if (!isBuffering())
+ mCloth.setDampingCoefficient(dampingCoefficient);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setDampingCoefficient() not allowed while simulation is running.");
+}
+
+PX_INLINE PxReal Cloth::getFrictionCoefficient() const
+{
+ if (!isBuffering())
+ return mCloth.getFrictionCoefficient();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getFrictionCoefficient() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+
+
+PX_INLINE void Cloth::setFrictionCoefficient(PxReal frictionCoefficient)
+{
+ if (!isBuffering())
+ mCloth.setFrictionCoefficient(frictionCoefficient);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setFrictionCoefficient() not allowed while simulation is running.");
+}
+
+PX_INLINE PxVec3 Cloth::getLinearDragCoefficient() const
+{
+ if (!isBuffering())
+ return mCloth.getLinearDragCoefficient();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getLinearDragCoefficient() not allowed while simulation is running.");
+ return PxVec3(0.0f);
+ }
+}
+
+
+PX_INLINE void Cloth::setLinearDragCoefficient(PxVec3 dampingCoefficient)
+{
+ if (!isBuffering())
+ mCloth.setLinearDragCoefficient(dampingCoefficient);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setLinearDragCoefficient() not allowed while simulation is running.");
+}
+
+PX_INLINE PxVec3 Cloth::getAngularDragCoefficient() const
+{
+ if (!isBuffering())
+ return mCloth.getAngularDragCoefficient();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getAngularDragCoefficient() not allowed while simulation is running.");
+ return PxVec3(0.0f);
+ }
+}
+
+
+PX_INLINE void Cloth::setAngularDragCoefficient(PxVec3 dampingCoefficient)
+{
+ if (!isBuffering())
+ mCloth.setAngularDragCoefficient(dampingCoefficient);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setAngularDragCoefficient() not allowed while simulation is running.");
+}
+
+PX_INLINE PxReal Cloth::getCollisionMassScale() const
+{
+ if (!isBuffering())
+ return mCloth.getCollisionMassScale();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getCollisionMassScale() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+PX_INLINE void Cloth::setCollisionMassScale(PxReal scalingCoefficient)
+{
+ if (!isBuffering())
+ mCloth.setCollisionMassScale(scalingCoefficient);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setCollisionMassScale() not allowed while simulation is running.");
+}
+
+PX_INLINE PxReal Cloth::getSelfCollisionDistance() const
+{
+ if (!isBuffering())
+ return mCloth.getSelfCollisionDistance();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getSelfCollisionDistance() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+PX_INLINE void Cloth::setSelfCollisionDistance(PxReal distance)
+{
+ if (!isBuffering())
+ mCloth.setSelfCollisionDistance(distance);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setSelfCollisionDistance() not allowed while simulation is running.");
+}
+PX_INLINE PxReal Cloth::getSelfCollisionStiffness() const
+{
+ if (!isBuffering())
+ return mCloth.getSelfCollisionStiffness();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getSelfCollisionStiffness() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+PX_INLINE void Cloth::setSelfCollisionStiffness(PxReal stiffness)
+{
+ if (!isBuffering())
+ mCloth.setSelfCollisionStiffness(stiffness);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setSelfCollisionStiffness() not allowed while simulation is running.");
+}
+
+PX_INLINE void Cloth::setSelfCollisionIndices(const PxU32* indices, PxU32 nbIndices)
+{
+ if (!isBuffering())
+ mCloth.setSelfCollisionIndices(indices, nbIndices);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setSelfCollisionIndices() not allowed while simulation is running.");
+}
+
+PX_INLINE bool Cloth::getSelfCollisionIndices(PxU32* indices) const
+{
+ if (!isBuffering())
+ return mCloth.getSelfCollisionIndices(indices);
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getSelfCollisionIndices() not allowed while simulation is running.");
+ return false;
+ }
+}
+
+PX_INLINE PxU32 Cloth::getNbSelfCollisionIndices() const
+{
+ return mCloth.getNbSelfCollisionIndices();
+}
+
+
+PX_INLINE void Cloth::setRestPositions(const PxVec4* restPositions)
+{
+ if (!isBuffering())
+ mCloth.setRestPositions(restPositions);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setRestPositions() not allowed while simulation is running.");
+}
+
+PX_INLINE bool Cloth::getRestPositions(PxVec4* restPositions) const
+{
+ if (!isBuffering())
+ return mCloth.getRestPositions(restPositions);
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getRestPositions() not allowed while simulation is running.");
+ return false;
+ }
+}
+
+PX_INLINE PxU32 Cloth::getNbRestPositions() const
+{
+ return mCloth.getNbRestPositions();
+}
+
+PX_INLINE PxReal Cloth::getSolverFrequency() const
+{
+ if (!isBuffering())
+ return mCloth.getSolverFrequency();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getSolverFrequency() not allowed while simulation is running.");
+ return 60.0f;
+ }
+}
+
+
+PX_INLINE void Cloth::setSolverFrequency(PxReal solverFreq)
+{
+ if (!isBuffering())
+ mCloth.setSolverFrequency(solverFreq);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setSolverFrequency() not allowed while simulation is running.");
+}
+
+PX_INLINE PxReal Cloth::getStiffnessFrequency() const
+{
+ if (!isBuffering())
+ return mCloth.getStiffnessFrequency();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getStiffnessFrequency() not allowed while simulation is running.");
+ return 60.0f;
+ }
+}
+
+
+PX_INLINE void Cloth::setStiffnessFrequency(PxReal solverFreq)
+{
+ if (!isBuffering())
+ mCloth.setStiffnessFrequency(solverFreq);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setStiffnessFrequency() not allowed while simulation is running.");
+}
+
+
+PX_INLINE void Cloth::setStretchConfig(PxClothFabricPhaseType::Enum type, const PxClothStretchConfig& config)
+{
+ if (!isBuffering())
+ mCloth.setStretchConfig(type, config);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setStretchConfig() not allowed while simulation is running.");
+}
+
+PX_INLINE void Cloth::setTetherConfig(const PxClothTetherConfig& config)
+{
+ if (!isBuffering())
+ mCloth.setTetherConfig(config);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setTetherConfig() not allowed while simulation is running.");
+}
+
+PX_INLINE PxClothStretchConfig Cloth::getStretchConfig(PxClothFabricPhaseType::Enum type) const
+{
+ if (!isBuffering())
+ return mCloth.getStretchConfig(type);
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getStretchConfig() not allowed while simulation is running.");
+ return PxClothStretchConfig();
+ }
+}
+
+PX_INLINE PxClothTetherConfig Cloth::getTetherConfig() const
+{
+ if (!isBuffering())
+ return mCloth.getTetherConfig();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getTetherConfig() not allowed while simulation is running.");
+ return PxClothTetherConfig();
+ }
+}
+
+PX_INLINE PxClothFlags Cloth::getClothFlags() const
+{
+ if (!isBuffering())
+ return mCloth.getClothFlags();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getClothFlags() not allowed while simulation is running.");
+ return PxClothFlags(0);
+ }
+}
+
+
+PX_INLINE void Cloth::setClothFlags(PxClothFlags flags)
+{
+ if (!isBuffering())
+ mCloth.setClothFlags(flags);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setClothFlag() not allowed while simulation is running.");
+}
+
+PX_INLINE PxVec3 Cloth::getWindVelocity() const
+{
+ if (!isBuffering())
+ return mCloth.getWindVelocity();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getWindVelocity() not allowed while simulation is running.");
+ return PxVec3(0.0f);
+ }
+}
+
+PX_INLINE void Cloth::setWindVelocity(PxVec3 wind)
+{
+ if (!isBuffering())
+ mCloth.setWindVelocity(wind);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setWindVelocity() not allowed while simulation is running.");
+}
+
+PX_INLINE PxReal Cloth::getDragCoefficient() const
+{
+ if (!isBuffering())
+ return mCloth.getDragCoefficient();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getDragCoefficient() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+
+PX_INLINE void Cloth::setDragCoefficient(PxReal value)
+{
+ if (!isBuffering())
+ mCloth.setDragCoefficient(value);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setDragCoefficient() not allowed while simulation is running.");
+}
+
+PX_INLINE PxReal Cloth::getLiftCoefficient() const
+{
+ if (!isBuffering())
+ return mCloth.getLiftCoefficient();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getLiftCoefficient() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+
+PX_INLINE void Cloth::setLiftCoefficient(PxReal value)
+{
+ if (!isBuffering())
+ mCloth.setLiftCoefficient(value);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setLiftCoefficient() not allowed while simulation is running.");
+}
+
+
+PX_INLINE bool Cloth::isSleeping() const
+{
+ if (!isBuffering())
+ return mCloth.isSleeping();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::isSleeping() not allowed while simulation is running.");
+ return false;
+ }
+}
+
+
+PX_INLINE PxReal Cloth::getSleepLinearVelocity() const
+{
+ if (!isBuffering())
+ return mCloth.getSleepLinearVelocity();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getSleepLinearVelocity() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+
+
+PX_INLINE void Cloth::setSleepLinearVelocity(PxReal threshold)
+{
+ if (!isBuffering())
+ mCloth.setSleepLinearVelocity(threshold);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setSleepLinearVelocity() not allowed while simulation is running.");
+}
+
+
+PX_INLINE void Cloth::setWakeCounter(PxReal wakeCounterValue)
+{
+ if (!isBuffering())
+ mCloth.setWakeCounter(wakeCounterValue);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setWakeCounter() not allowed while simulation is running.");
+}
+
+
+PX_INLINE PxReal Cloth::getWakeCounter() const
+{
+ if (!isBuffering())
+ return mCloth.getWakeCounter();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getWakeCounter() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+
+
+PX_INLINE void Cloth::wakeUp()
+{
+ Scene* scene = getScbScene();
+ PX_ASSERT(scene); // only allowed for an object in a scene
+
+ if (!isBuffering())
+ mCloth.wakeUp(scene->getWakeCounterResetValue());
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::wakeUp() not allowed while simulation is running.");
+}
+
+
+PX_INLINE void Cloth::putToSleep()
+{
+ if (!isBuffering())
+ mCloth.putToSleep();
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::putToSleep() not allowed while simulation is running.");
+}
+
+
+PX_INLINE void Cloth::getParticleData(NpClothParticleData& particleData)
+{
+ if (!isBuffering())
+ return getScCloth().getParticleData(particleData);
+
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Call to PxCloth::lockParticleData() not allowed while simulation is running.");
+
+ particleData.particles = 0;
+ particleData.previousParticles = 0;
+}
+
+
+PxReal Cloth::getPreviousTimeStep() const
+{
+ if (!isBuffering())
+ return mCloth.getPreviousTimeStep();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getPreviousTimeStep() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+
+
+PX_INLINE PxBounds3 Cloth::getWorldBounds() const
+{
+ if (!isBuffering())
+ return mCloth.getWorldBounds();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getWorldBounds() not allowed while simulation is running.");
+ return PxBounds3::empty();
+ }
+}
+
+PX_INLINE void Cloth::setSimulationFilterData(const PxFilterData& data)
+{
+ if (!isBuffering())
+ mCloth.setSimulationFilterData(data);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setSimulationFilterData() not allowed while simulation is running.");
+}
+
+PX_INLINE PxFilterData Cloth::getSimulationFilterData() const
+{
+ if (!isBuffering())
+ return mCloth.getSimulationFilterData();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getSimulationFilterData() not allowed while simulation is running.");
+ return PxFilterData();
+ }
+}
+
+PX_INLINE void Cloth::setContactOffset(PxReal offset)
+{
+ if (!isBuffering())
+ mCloth.setContactOffset(offset);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setContactOffset() not allowed while simulation is running.");
+}
+
+PX_INLINE PxReal Cloth::getContactOffset() const
+{
+ if (!isBuffering())
+ return mCloth.getContactOffset();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getContactOffset() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+
+PX_INLINE void Cloth::setRestOffset(PxReal offset)
+{
+ if (!isBuffering())
+ mCloth.setRestOffset(offset);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::setRestOffset() not allowed while simulation is running.");
+}
+
+PX_INLINE PxReal Cloth::getRestOffset() const
+{
+ if (!isBuffering())
+ return mCloth.getRestOffset();
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Call to PxCloth::getRestOffset() not allowed while simulation is running.");
+ return 0.0f;
+ }
+}
+
+} // namespace Scb
+
+}
+
+#endif // PX_USE_CLOTH_API
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbConstraint.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbConstraint.h
new file mode 100644
index 00000000..d4661e2d
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbConstraint.h
@@ -0,0 +1,332 @@
+// 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_SCB_CONSTRAINTSHADER
+#define PX_PHYSICS_SCB_CONSTRAINTSHADER
+
+#include "CmPhysXCommon.h"
+#include "../../../SimulationController/include/ScConstraintCore.h"
+
+#include "ScbBody.h"
+
+namespace physx
+{
+
+namespace Sc
+{
+ class RigidCore;
+}
+
+namespace Scb
+{
+
+struct ConstraintBuffer
+{
+public:
+ Sc::RigidCore* rigids[2];
+ PxReal linBreakForce;
+ PxReal angBreakForce;
+ PxConstraintFlags flags;
+ PxReal minResponseThreshold;
+};
+
+enum ConstraintBufferFlag
+{
+ BF_BODIES = (1 << 0),
+ BF_BREAK_IMPULSE = (1 << 1),
+ BF_FLAGS = (1 << 2),
+ BF_MIN_RESPONSE_THRESHOLD = (1 << 3),
+
+ BF_LAST_BUFFER_BIT = BF_FLAGS
+};
+
+class Constraint : public Base, public Ps::UserAllocated
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+
+public:
+
+ typedef ConstraintBuffer Buf;
+ typedef Sc::ConstraintCore Core;
+
+// PX_SERIALIZATION
+ Constraint(const PxEMPTY) : Base(PxEmpty), mConstraint(PxEmpty) {}
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ PX_INLINE Constraint(PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize);
+ PX_INLINE ~Constraint() {}
+
+ //---------------------------------------------------------------------------------
+ // Wrapper for Sc::ConstraintCore interface
+ //---------------------------------------------------------------------------------
+
+ PX_INLINE PxConstraint* getPxConstraint() const;
+ PX_INLINE PxConstraintConnector* getPxConnector() const;
+
+ PX_INLINE void setFlags(PxConstraintFlags f);
+ PX_INLINE PxConstraintFlags getFlags() const;
+
+ PX_INLINE void setBodies(Scb::RigidObject* r0, Scb::RigidObject* r1);
+
+ PX_INLINE void getForce(PxVec3& force, PxVec3& torque) const;
+
+ PX_INLINE void setBreakForce(PxReal linear, PxReal angular);
+ PX_INLINE void getBreakForce(PxReal& linear, PxReal& angular) const;
+
+ PX_INLINE void setMinResponseThreshold(PxReal threshold);
+ PX_INLINE PxReal getMinResponseThreshold() const;
+
+ PX_INLINE bool updateConstants(void* addr);
+
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+ PX_INLINE void prepareForActorRemoval();
+ PX_INLINE void syncState();
+
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ PX_FORCE_INLINE const Core& getScConstraint() const { return mConstraint; } // Only use if you know what you're doing!
+ PX_FORCE_INLINE Core& getScConstraint() { return mConstraint; } // Only use if you know what you're doing!
+
+ PX_FORCE_INLINE static Constraint& fromSc(Core &a) { return *reinterpret_cast<Constraint*>(reinterpret_cast<PxU8*>(&a)-getScOffset()); }
+ PX_FORCE_INLINE static const Constraint& fromSc(const Core &a) { return *reinterpret_cast<const Constraint*>(reinterpret_cast<const PxU8*>(&a)-getScOffset()); }
+
+
+ static size_t getScOffset()
+ {
+ return reinterpret_cast<size_t>(&reinterpret_cast<Constraint*>(0)->mConstraint);
+ }
+
+private:
+ Core mConstraint;
+
+ //---------------------------------------------------------------------------------
+ // Permanently buffered data (simulation written data)
+ //---------------------------------------------------------------------------------
+ PxVec3 mBufferedForce;
+ PxVec3 mBufferedTorque;
+ PxConstraintFlags mBrokenFlag;
+
+ PX_FORCE_INLINE const Buf* getBufferedData() const { return reinterpret_cast<const Buf*>(getStream()); }
+ PX_FORCE_INLINE Buf* getBufferedData() { return reinterpret_cast<Buf*>(getStream()); }
+};
+
+} // namespace Scb
+
+PX_INLINE Scb::Constraint::Constraint(PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize) :
+ mConstraint(connector, shaders, dataSize),
+ mBufferedForce(0.0f),
+ mBufferedTorque(0.0f),
+ mBrokenFlag(0)
+{
+ setScbType(ScbType::CONSTRAINT);
+}
+
+PX_INLINE PxConstraintConnector* Scb::Constraint::getPxConnector() const
+{
+ return mConstraint.getPxConnector();
+}
+
+PX_INLINE void Scb::Constraint::setFlags(PxConstraintFlags f)
+{
+ if (!isBuffering())
+ {
+ mConstraint.setFlags(f);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ getBufferedData()->flags = f;
+ markUpdated(BF_FLAGS);
+ }
+}
+
+PX_INLINE PxConstraintFlags Scb::Constraint::getFlags() const
+{
+ return isBuffered(BF_FLAGS) ? getBufferedData()->flags & (~(PxConstraintFlag::eBROKEN | PxConstraintFlag::eGPU_COMPATIBLE) | mBrokenFlag)
+ : mConstraint.getFlags() & (~(PxConstraintFlag::eBROKEN | PxConstraintFlag::eGPU_COMPATIBLE) | mBrokenFlag);
+}
+
+
+PX_INLINE void Scb::Constraint::setBodies(Scb::RigidObject* r0, Scb::RigidObject* r1)
+{
+ Sc::RigidCore* scR0 = r0 ? &r0->getScRigidCore() : NULL;
+ Sc::RigidCore* scR1 = r1 ? &r1->getScRigidCore() : NULL;
+
+ if (!isBuffering())
+ {
+ mConstraint.prepareForSetBodies();
+ mConstraint.setBodies(scR0, scR1);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ Buf* PX_RESTRICT bufferedData = getBufferedData();
+ bufferedData->rigids[0] = scR0;
+ bufferedData->rigids[1] = scR1;
+ markUpdated(BF_BODIES);
+ }
+
+ mBufferedForce = PxVec3(0);
+ mBufferedTorque = PxVec3(0);
+}
+
+
+
+PX_INLINE void Scb::Constraint::getForce(PxVec3& force, PxVec3& torque) const
+{
+ force = mBufferedForce;
+ torque = mBufferedTorque;
+}
+
+
+PX_INLINE void Scb::Constraint::setBreakForce(PxReal linear, PxReal angular)
+{
+ if (!isBuffering())
+ {
+ mConstraint.setBreakForce(linear, angular);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ Buf* PX_RESTRICT bufferedData = getBufferedData();
+ bufferedData->linBreakForce = linear;
+ bufferedData->angBreakForce = angular;
+ markUpdated(BF_BREAK_IMPULSE);
+ }
+}
+
+
+PX_INLINE void Scb::Constraint::getBreakForce(PxReal& linear, PxReal& angular) const
+{
+ if (isBuffered(BF_BREAK_IMPULSE))
+ {
+ const Buf* PX_RESTRICT bufferedData = getBufferedData();
+ linear = bufferedData->linBreakForce;
+ angular = bufferedData->angBreakForce;
+ }
+ else
+ mConstraint.getBreakForce(linear, angular);
+}
+
+
+PX_INLINE void Scb::Constraint::setMinResponseThreshold(PxReal threshold)
+{
+ if (!isBuffering())
+ {
+ mConstraint.setMinResponseThreshold(threshold);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ Buf* PX_RESTRICT bufferedData = getBufferedData();
+ bufferedData->minResponseThreshold = threshold;
+ markUpdated(BF_MIN_RESPONSE_THRESHOLD);
+ }
+}
+
+
+PX_INLINE PxReal Scb::Constraint::getMinResponseThreshold() const
+{
+ if (isBuffered(BF_MIN_RESPONSE_THRESHOLD))
+ {
+ const Buf* PX_RESTRICT bufferedData = getBufferedData();
+ return bufferedData->minResponseThreshold;
+ }
+ else
+ return mConstraint.getMinResponseThreshold();
+}
+
+
+
+PX_INLINE bool Scb::Constraint::updateConstants(void* addr)
+{
+ PX_ASSERT(!getScbScene()->isPhysicsBuffering());
+
+ return mConstraint.updateConstants(addr);
+}
+
+
+//--------------------------------------------------------------
+//
+// Data synchronization
+//
+//--------------------------------------------------------------
+
+PX_INLINE void Scb::Constraint::prepareForActorRemoval()
+{
+ // when the bodies of a constraint have been changed during buffering, it's possible the
+ // attached actor is going to get deleted. Sc expects that all interactions with that actor
+ // will have been removed, so we give the Sc::Constraint a chance to ensure that before
+ // the actors go away.
+ if(getBufferFlags() & BF_BODIES)
+ mConstraint.prepareForSetBodies();
+}
+
+PX_INLINE void Scb::Constraint::syncState()
+{
+ //!!! Force has to be synced every frame (might want to have a list of active constraint shaders?)
+ mConstraint.getForce(mBufferedForce, mBufferedTorque);
+
+ mBrokenFlag = mConstraint.getFlags() & PxConstraintFlag::eBROKEN;
+
+ PxU32 flags = getBufferFlags();
+ if(flags)
+ {
+ const Buf* PX_RESTRICT bufferedData = getBufferedData();
+
+ if(flags & BF_BODIES)
+ mConstraint.setBodies(bufferedData->rigids[0], bufferedData->rigids[1]);
+
+ if(flags & BF_BREAK_IMPULSE)
+ mConstraint.setBreakForce(bufferedData->linBreakForce, bufferedData->angBreakForce);
+
+ if(flags & BF_MIN_RESPONSE_THRESHOLD)
+ mConstraint.setMinResponseThreshold(bufferedData->minResponseThreshold);
+
+ if(flags & BF_FLAGS)
+ mConstraint.setFlags(bufferedData->flags | mBrokenFlag);
+ }
+
+ postSyncState();
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbDefs.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbDefs.h
new file mode 100644
index 00000000..bd3fd4cd
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbDefs.h
@@ -0,0 +1,140 @@
+// 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_SCB_DEFS
+#define PX_PHYSICS_SCB_DEFS
+
+#include "ScbBase.h"
+
+// a Regular attribute of type T is one for which
+// * the SC method takes a single argument of type ArgType<T> (defined below)
+// * Scb either passes that argument through, or dumps it in a buffer to flush later.
+// * PVD is notified when the variable changes
+//
+// For each such, we can define static methods to read and write the core and buffered variables,
+// and capture the buffering logic in the BufferedAccess class.
+//
+// The dummy arg is necessary here because ISO permits partial specialization of member templates
+// but not full specialization.
+//
+// putting just accessors and mutators here allows us to change the behavior just by varying the
+// BufferAccess template (e.g. to compile without buffering), and also to size-reduce that template
+// by passing function pointers if necessary
+
+#define SCB_REGULAR_ATTRIBUTE(_val, _type, _name) \
+enum { BF_##_name = 1<<(_val) }; \
+_type m##_name; \
+template<PxU32 Dummy> struct Fns<1<<(_val),Dummy> \
+{ \
+ typedef typename ArgType<_type>::Type Arg; \
+ enum { flag = 1<<(_val) }; \
+ static PX_FORCE_INLINE Arg getBuffered(const Buf& buf) { return Arg(buf.m##_name);} \
+ static PX_FORCE_INLINE void setBuffered(Buf& buf, Arg v) { buf.m##_name = v;} \
+ static PX_FORCE_INLINE Arg getCore(const Core& core) { return Arg(core.get##_name());} \
+ static PX_FORCE_INLINE void setCore(Core& core, Arg v) { core.set##_name(v);} \
+};
+
+#define SCB_REGULAR_ATTRIBUTE_ALIGNED(_val, _type, _name, _alignment) \
+enum { BF_##_name = 1<<(_val) }; \
+PX_ALIGN(_alignment, _type) m##_name; \
+template<PxU32 Dummy> struct Fns<1<<(_val),Dummy> \
+{ \
+ typedef typename ArgType<_type>::Type Arg; \
+ enum { flag = 1<<(_val) }; \
+ static PX_FORCE_INLINE Arg getBuffered(const Buf& buf) { return buf.m##_name;} \
+ static PX_FORCE_INLINE void setBuffered(Buf& buf, Arg v) { buf.m##_name = v;} \
+ static PX_FORCE_INLINE Arg getCore(const Core& core) { return core.get##_name();} \
+ static PX_FORCE_INLINE void setCore(Core& core, Arg v) { core.set##_name(v);} \
+};
+
+
+
+namespace physx
+{
+
+namespace Scb
+{
+class Scene;
+
+template<typename T> struct ArgType { typedef T Type; };
+template<> struct ArgType<PxVec3> { typedef const PxVec3& Type; };
+template<> struct ArgType<PxTransform> { typedef const PxTransform& Type; };
+template<> struct ArgType<PxQuat> { typedef const PxQuat& Type; };
+template<> struct ArgType<PxPlane> { typedef const PxPlane& Type; };
+template<> struct ArgType<PxFilterData> { typedef const PxFilterData& Type; };
+
+// TODO: should be able to size-reduce this if necessary by just generating one set per
+// arg type instead of one per arg, by passing function pointers to the accessors/mutators/flag
+// instead of instancing per type.
+
+template<class Buf, class Core, class ScbClass, class BaseClass=Scb::Base> // BaseClass: introduced to have Scb::Body use custom location for storing buffered property flags
+struct BufferedAccess
+{
+ template<typename Fns>
+ static PX_FORCE_INLINE typename Fns::Arg read(const BaseClass& base, const Core& core)
+ {
+ return base.isBuffered(Fns::flag) ? Fns::getBuffered(*reinterpret_cast<const Buf*>(base.getStream()))
+ : Fns::getCore(core);
+ }
+
+ template<typename Fns>
+ static PX_FORCE_INLINE void write(BaseClass& base, Core& core, typename Fns::Arg v)
+ {
+ if (!base.isBuffering())
+ {
+ Fns::setCore(core, v);
+#if PX_SUPPORT_PVD
+ if(base.getControlState() == ControlState::eIN_SCENE)
+ {
+ Scb::Scene* scene = base.getScbScene();
+ PX_ASSERT(scene);
+ scene->getScenePvdClient().updatePvdProperties(static_cast<ScbClass*>(&base));
+ }
+#endif
+ }
+ else
+ {
+ Fns::setBuffered(*reinterpret_cast<Buf*>(base.getStream()), v);
+ base.markUpdated(Fns::flag);
+ }
+ }
+
+ template<typename Fns>
+ static PX_FORCE_INLINE void flush(const BaseClass& base, Core& core, const Buf& buf)
+ {
+ if(base.isBuffered(Fns::flag))
+ Fns::setCore(core, Fns::getBuffered(buf));
+ }
+};
+
+}
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbMetaData.cpp b/PhysX_3.4/Source/PhysX/src/buffering/ScbMetaData.cpp
new file mode 100644
index 00000000..fea9a5f3
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbMetaData.cpp
@@ -0,0 +1,203 @@
+// 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 "foundation/PxIO.h"
+#include "ScbShape.h"
+#include "ScbBody.h"
+#include "ScbRigidStatic.h"
+#include "ScbConstraint.h"
+#include "ScbArticulation.h"
+#include "ScbArticulationJoint.h"
+#include "ScbAggregate.h"
+#include "ScbCloth.h"
+#include "ScbParticleSystem.h"
+
+using namespace physx;
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Base::getBinaryMetaData(PxOutputStream& stream)
+{
+ // 28 => 12 bytes
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, ScbType::Enum, PxU32)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::Base)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Base, Scb::Scene, mScene, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Base, PxU32, mControlState, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Base, PxU8*, mStreamPtr, PxMetaDataFlag::ePTR)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Shape::getBinaryMetaData(PxOutputStream& stream)
+{
+ // 176 => 160 bytes
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::Shape)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::Shape, Scb::Base)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Shape, ShapeCore, mShape, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Actor::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::Actor)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::Actor, Scb::Base)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::RigidObject::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::RigidObject)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::RigidObject, Scb::Actor)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Body::getBinaryMetaData(PxOutputStream& stream)
+{
+ // 240 => 224 bytes
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::Body)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::Body, Scb::RigidObject)
+
+#ifdef EXPLICIT_PADDING_METADATA
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Body, PxU32, mPaddingScbBody1, PxMetaDataFlag::ePADDING)
+#endif
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Body, Sc::BodyCore, mBodyCore, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Body, PxTransform, mBufferedBody2World, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Body, PxVec3, mBufferedLinVelocity, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Body, PxVec3, mBufferedAngVelocity, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Body, PxReal, mBufferedWakeCounter, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Body, PxU32, mBufferedIsSleeping, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Body, PxU32, mBodyBufferFlags, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::RigidStatic::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::RigidStatic)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::RigidStatic, Scb::RigidObject)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::RigidStatic, Sc::StaticCore, mStatic, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Articulation::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::Articulation)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::Articulation, Scb::Base)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Articulation, ArticulationCore, mArticulation, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Articulation, PxReal, mBufferedWakeCounter, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Articulation, PxU8, mBufferedIsSleeping, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::ArticulationJoint::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::ArticulationJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::ArticulationJoint, Scb::Base)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::ArticulationJoint, ArticulationJointCore, mJoint, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Constraint::getBinaryMetaData(PxOutputStream& stream)
+{
+ // 120 => 108 bytes
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::Constraint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::Constraint, Scb::Base)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Constraint, ConstraintCore, mConstraint, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Constraint, PxVec3, mBufferedForce, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Constraint, PxVec3, mBufferedTorque, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Constraint, PxConstraintFlags, mBrokenFlag, 0)
+#ifdef EXPLICIT_PADDING_METADATA
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Constraint, PxU16, mPaddingFromBrokenFlags, PxMetaDataFlag::ePADDING)
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Aggregate::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::Aggregate)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::Aggregate, Scb::Base)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Aggregate, PxAggregate,mPxAggregate, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Aggregate, PxU32, mAggregateID, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Aggregate, PxU32, mMaxNbActors, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Aggregate, bool, mSelfCollide, 0)
+
+#ifdef EXPLICIT_PADDING_METADATA
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, Scb::Aggregate, bool, mPaddingFromBool, PxMetaDataFlag::ePADDING)
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_USE_CLOTH_API
+void Scb::Cloth::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::Cloth)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::Cloth, Scb::Actor)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::Cloth, Sc::ClothCore, mCloth, 0)
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_USE_PARTICLE_SYSTEM_API
+void Scb::ParticleSystem::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, ForceUpdates)
+ PX_DEF_BIN_METADATA_ITEM(stream, ForceUpdates, BitMap, map, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, ForceUpdates, PxVec3, values, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, ForceUpdates, bool, hasUpdates, 0)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, Scb::ParticleSystem)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, Scb::ParticleSystem, Scb::Actor)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::ParticleSystem, Sc::ParticleSystemCore, mParticleSystem, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::ParticleSystem, NpParticleFluidReadData, mReadParticleFluidData, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::ParticleSystem, ForceUpdates, mForceUpdatesAcc, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Scb::ParticleSystem, ForceUpdates, mForceUpdatesVel, 0)
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbNpDeps.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbNpDeps.h
new file mode 100644
index 00000000..37517dc8
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbNpDeps.h
@@ -0,0 +1,77 @@
+// 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_SCB_NPDEPS
+#define PX_PHYSICS_SCB_NPDEPS
+
+namespace physx
+{
+
+// The Scb layer needs to delete the owning Np objects, but we don't want to include the Np headers
+// necessary to find their addresses. So we use link-level dependencies instead.
+
+namespace Scb
+{
+ class Base;
+ class Shape;
+ class RigidObject;
+ class Constraint;
+ class Scene;
+ class ArticulationJoint;
+ class Articulation;
+ class RigidStatic;
+ class Body;
+}
+
+namespace Sc
+{
+ class RigidCore;
+}
+
+class PxScene;
+
+extern void NpDestroy(Scb::Base&);
+
+// we want to get the pointer to the rigid object that owns a shape, and the two actor pointers for a constraint, so that we don't
+// duplicate the scene graph in Scb
+
+extern PxU32 NpRigidStaticGetShapes(Scb::RigidStatic& rigid, void* const *&shapes);
+extern PxU32 NpRigidDynamicGetShapes(Scb::Body& body, void* const *&shapes);
+extern size_t NpShapeGetScPtrOffset();
+extern void NpShapeIncRefCount(Scb::Shape& shape);
+extern void NpShapeDecRefCount(Scb::Shape& shape);
+
+extern Sc::RigidCore* NpShapeGetScRigidObjectFromScbSLOW(const Scb::Shape &);
+extern void NpConstraintGetRigidObjectsFromScb(const Scb::Constraint&, Scb::RigidObject*&, Scb::RigidObject*&);
+extern void NpArticulationJointGetBodiesFromScb(Scb::ArticulationJoint&, Scb::Body*&, Scb::Body*&);
+extern Scb::Body* NpArticulationGetRootFromScb(Scb::Articulation&);
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbParticleSystem.cpp b/PhysX_3.4/Source/PhysX/src/buffering/ScbParticleSystem.cpp
new file mode 100644
index 00000000..078f3a24
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbParticleSystem.cpp
@@ -0,0 +1,311 @@
+// 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 "PxPhysXConfig.h"
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+#include "ScbParticleSystem.h"
+
+using namespace physx;
+
+//----------------------------------------------------------------------------//
+
+// lazy allocate. doesn't reset hasUpdates
+void Scb::ParticleSystem::ForceUpdates::initialize(PxU32 maxParticles)
+{
+ PX_ASSERT((map == NULL) == (values == NULL));
+ if (values)
+ return;
+
+ values = reinterpret_cast<PxVec3*>(PX_ALLOC(maxParticles*sizeof(PxVec3), "PxVec3"));
+ map = PX_NEW(Cm::BitMap)();
+ map->resizeAndClear(maxParticles);
+}
+
+//----------------------------------------------------------------------------//
+
+void Scb::ParticleSystem::ForceUpdates::destroy()
+{
+ PX_ASSERT((map == NULL) == (values == NULL));
+
+ if (map)
+ {
+ PX_DELETE(map);
+ map = NULL;
+ PX_FREE(values);
+ values = NULL;
+ }
+ hasUpdates = false;
+}
+
+//----------------------------------------------------------------------------//
+
+Scb::ParticleSystem::ParticleSystem(const PxActorType::Enum& actorType, PxU32 maxParticles, bool perParticleRestOffset)
+: mParticleSystem(actorType, maxParticles, perParticleRestOffset)
+, mReadParticleFluidData(NULL)
+{
+ setScbType(ScbType::PARTICLE_SYSTEM);
+}
+
+//----------------------------------------------------------------------------//
+
+Scb::ParticleSystem::~ParticleSystem()
+{
+ if (mReadParticleFluidData)
+ PX_DELETE_AND_RESET(mReadParticleFluidData);
+}
+
+//----------------------------------------------------------------------------//
+
+bool Scb::ParticleSystem::createParticles(const PxParticleCreationData& creationData)
+{
+ if (isBuffering())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle operations are not allowed while simulation is running.");
+ return false;
+ }
+ else
+ {
+ LOCK_PARTICLE_USER_BUFFERS("PxParticleBase::createParticles()")
+
+ bool ret = mParticleSystem.createParticles(creationData);
+
+ return ret;
+ }
+}
+
+//----------------------------------------------------------------------------//
+
+void Scb::ParticleSystem::releaseParticles(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer)
+{
+ LOCK_PARTICLE_USER_BUFFERS("PxParticleBase::releaseParticles()")
+
+ if (numParticles == 0)
+ return;
+
+ if (isBuffering())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle operations are not allowed while simulation is running.");
+ return;
+ }
+ else
+ {
+ mParticleSystem.releaseParticles(numParticles, indexBuffer);
+ }
+
+ if (mForceUpdatesAcc.hasUpdates)
+ for (PxU32 i=0; i < numParticles; i++)
+ mForceUpdatesAcc.clear(indexBuffer[i]);
+
+ if (mForceUpdatesVel.hasUpdates)
+ for (PxU32 i=0; i < numParticles; i++)
+ mForceUpdatesVel.clear(indexBuffer[i]);
+}
+
+//----------------------------------------------------------------------------//
+
+void Scb::ParticleSystem::releaseParticles()
+{
+ LOCK_PARTICLE_USER_BUFFERS("PxParticleBase::releaseParticles()")
+
+ if (isBuffering())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle operations are not allowed while simulation is running.");
+ return;
+ }
+ else
+ {
+ mParticleSystem.releaseParticles();
+ }
+
+ mForceUpdatesAcc.clear();
+ mForceUpdatesVel.clear();
+}
+
+//----------------------------------------------------------------------------//
+
+void Scb::ParticleSystem::setPositions(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& positionBuffer)
+{
+ LOCK_PARTICLE_USER_BUFFERS("PxParticleBase::setPositions()")
+
+ if (isBuffering())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle operations are not allowed while simulation is running.");
+ return;
+ }
+ else
+ {
+ mParticleSystem.setPositions(numParticles, indexBuffer, positionBuffer);
+ }
+}
+
+//----------------------------------------------------------------------------//
+
+void Scb::ParticleSystem::setVelocities(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& velocityBuffer)
+{
+ LOCK_PARTICLE_USER_BUFFERS("PxParticleBase::setVelocities()")
+
+ if (isBuffering())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle operations are not allowed while simulation is running.");
+ return;
+ }
+ else
+ {
+ mParticleSystem.setVelocities(numParticles, indexBuffer, velocityBuffer);
+ }
+}
+
+//----------------------------------------------------------------------------//
+
+void Scb::ParticleSystem::setRestOffsets(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxF32>& restOffsetBuffer)
+{
+ LOCK_PARTICLE_USER_BUFFERS("PxParticleBase::setRestOffsets()")
+
+ if (isBuffering())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle operations are not allowed while simulation is running.");
+ return;
+ }
+ else
+ {
+ mParticleSystem.setRestOffsets(numParticles, indexBuffer, restOffsetBuffer);
+ }
+}
+
+//----------------------------------------------------------------------------//
+
+void Scb::ParticleSystem::addForces(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& forceBuffer, PxForceMode::Enum forceMode)
+{
+ if (isBuffering())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle operations are not allowed while simulation is running.");
+ return;
+ }
+
+ PX_ASSERT(numParticles > 0);
+ PX_ASSERT(indexBuffer.ptr() && indexBuffer.stride() > 0);
+
+ PxReal particleMass = getParticleMass();
+ bool isAcceleration = false;
+ PxReal unitMult = 0.0;
+ switch(forceMode)
+ {
+ case PxForceMode::eFORCE: //!< parameter has unit of mass * distance/ time^2, i.e. a force
+ unitMult = 1.0f / particleMass;
+ isAcceleration = true;
+ break;
+ case PxForceMode::eIMPULSE: //!< parameter has unit of mass * distance /time
+ unitMult = 1.0f / particleMass;
+ isAcceleration = false;
+ break;
+ case PxForceMode::eVELOCITY_CHANGE: //!< parameter has unit of distance / time, i.e. the effect is mass independent: a velocity change.
+ unitMult = 1.0f;
+ isAcceleration = false;
+ break;
+ case PxForceMode::eACCELERATION: //!< parameter has unit of distance/ time^2, i.e. an acceleration. It gets treated just like a force except the mass is not divided out before integration.
+ unitMult = 1.0f;
+ isAcceleration = true;
+ break;
+ }
+
+ ForceUpdates& forceUpdates = isAcceleration ? mForceUpdatesAcc : mForceUpdatesVel;
+ forceUpdates.initialize(mParticleSystem.getMaxParticles());
+
+ for (PxU32 i=0; i < numParticles; i++)
+ forceUpdates.add(indexBuffer[i], forceBuffer[i] * unitMult);
+}
+
+//----------------------------------------------------------------------------//
+
+void Scb::ParticleSystem::submitForceUpdates(PxReal timeStep)
+{
+ LOCK_PARTICLE_USER_BUFFERS("PxParticleBase: Apply forces")
+
+ if (mForceUpdatesAcc.hasUpdates)
+ {
+ mParticleSystem.addDeltaVelocities(*mForceUpdatesAcc.map, mForceUpdatesAcc.values, timeStep);
+ mForceUpdatesAcc.clear();
+ }
+
+ if (mForceUpdatesVel.hasUpdates)
+ {
+ mParticleSystem.addDeltaVelocities(*mForceUpdatesVel.map, mForceUpdatesVel.values, 1.0f);
+ mForceUpdatesVel.clear();
+ }
+}
+
+//----------------------------------------------------------------------------//
+
+void Scb::ParticleSystem::syncState()
+{
+ LOCK_PARTICLE_USER_BUFFERS("PxScene::fetchResults()")
+
+ PxU32 flags = getBufferFlags();
+ if (flags) // Optimization to avoid all the if-statements below if possible
+ {
+ const Buf& buffer = *getParticleSystemBuffer();
+
+ flush<Buf::BF_Stiffness>(buffer);
+ flush<Buf::BF_Viscosity>(buffer);
+ flush<Buf::BF_Damping>(buffer);
+ flush<Buf::BF_ExternalAcceleration>(buffer);
+ flush<Buf::BF_ProjectionPlane>(buffer);
+ flush<Buf::BF_ParticleMass>(buffer);
+ flush<Buf::BF_Restitution>(buffer);
+ flush<Buf::BF_DynamicFriction>(buffer);
+ flush<Buf::BF_StaticFriction>(buffer);
+
+ if (flags & Buf::BF_ResetFiltering)
+ mParticleSystem.resetFiltering();
+
+ flush<Buf::BF_SimulationFilterData>(buffer);
+ flush<Buf::BF_Flags>(buffer);
+
+ Actor::syncState();
+ }
+
+ postSyncState();
+}
+
+//----------------------------------------------------------------------------//
+
+#endif // PX_USE_PARTICLE_SYSTEM_API
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbParticleSystem.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbParticleSystem.h
new file mode 100644
index 00000000..a0d720d1
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbParticleSystem.h
@@ -0,0 +1,484 @@
+// 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_SCB_PARTICLE_SYSTEM
+#define PX_PHYSICS_SCB_PARTICLE_SYSTEM
+
+#include "PxPhysXConfig.h"
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+#include "ScParticleSystemCore.h"
+
+#include "ScbActor.h"
+
+#include "NpPhysics.h"
+#include "NpParticleFluidReadData.h"
+
+namespace physx
+{
+
+struct PxCudaReadWriteParticleBuffers;
+
+namespace Scb
+{
+
+struct ParticleSystemBuffer : public Scb::ActorBuffer
+{
+ template <PxU32 I, PxU32 Dummy> struct Fns {}; // TODO : make the base class traits visible
+ typedef Sc::ParticleSystemCore Core;
+ typedef ParticleSystemBuffer Buf;
+ enum { BF_Base = ActorBuffer::AttrCount };
+
+ // Regular attributes
+
+ SCB_REGULAR_ATTRIBUTE(BF_Base+2, PxReal, Stiffness)
+ SCB_REGULAR_ATTRIBUTE(BF_Base+3, PxReal, Viscosity)
+ SCB_REGULAR_ATTRIBUTE(BF_Base+4, PxReal, Damping)
+ SCB_REGULAR_ATTRIBUTE(BF_Base+5, PxVec3, ExternalAcceleration)
+ SCB_REGULAR_ATTRIBUTE(BF_Base+6, PxPlane, ProjectionPlane)
+ SCB_REGULAR_ATTRIBUTE(BF_Base+7, PxReal, ParticleMass)
+ SCB_REGULAR_ATTRIBUTE(BF_Base+8, PxReal, Restitution)
+ SCB_REGULAR_ATTRIBUTE(BF_Base+9, PxReal, DynamicFriction)
+ SCB_REGULAR_ATTRIBUTE(BF_Base+10, PxReal, StaticFriction)
+ SCB_REGULAR_ATTRIBUTE(BF_Base+11, PxFilterData, SimulationFilterData)
+ SCB_REGULAR_ATTRIBUTE(BF_Base+12, PxParticleBaseFlags, Flags)
+
+ enum { BF_ResetFiltering = 1<<(BF_Base+13) };
+
+};
+
+
+class DebugIndexPool;
+
+class ParticleSystem : public Scb::Actor
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+
+ typedef Sc::ParticleSystemCore Core;
+ typedef ParticleSystemBuffer Buf;
+
+ struct UserBufferLock
+ {
+ UserBufferLock(NpParticleFluidReadData* db, const char* callerName) : dataBuffer(db) { if (dataBuffer) { dataBuffer->lock(callerName); } }
+ ~UserBufferLock() { if (dataBuffer) { dataBuffer->unlock(); } }
+
+ NpParticleFluidReadData* dataBuffer;
+ private:
+ UserBufferLock& operator=(const UserBufferLock&);
+ };
+
+#define LOCK_PARTICLE_USER_BUFFERS(callerName) UserBufferLock userBufferLock(mReadParticleFluidData, callerName);
+
+ struct ForceUpdates
+ {
+ ForceUpdates() : map(NULL), values(NULL), hasUpdates(false) {}
+ void initialize(PxU32 maxParticles);
+ void destroy();
+
+ PX_INLINE void add(PxU32 index, const PxVec3& value)
+ {
+ hasUpdates = true;
+ if (!map->test(index))
+ {
+ map->set(index);
+ values[index] = value;
+ return;
+ }
+ values[index] += value;
+ }
+
+ PX_INLINE void clear(PxU32 index)
+ {
+ PX_ASSERT(map);
+ map->reset(index);
+ }
+
+ PX_INLINE void clear()
+ {
+ if (!hasUpdates)
+ return;
+
+ PX_ASSERT(map);
+ map->clear();
+ hasUpdates = false;
+ }
+
+ Cm::BitMap* map; // can we make this an instance?
+ PxVec3* values;
+ bool hasUpdates;
+ };
+
+public:
+// PX_SERIALIZATION
+ ParticleSystem(const PxEMPTY) : Scb::Actor(PxEmpty), mParticleSystem(PxEmpty) { mReadParticleFluidData = NULL; }
+ void exportExtraData(PxSerializationContext& stream) { mParticleSystem.exportExtraData(stream); }
+ void importExtraData(PxDeserializationContext& context) { mParticleSystem.importExtraData(context); }
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ ParticleSystem(const PxActorType::Enum&, PxU32, bool);
+ ~ParticleSystem();
+
+ //---------------------------------------------------------------------------------
+ // Wrapper for Sc::ParticleSystemCore interface
+ //---------------------------------------------------------------------------------
+ PX_INLINE PxParticleBase* getPxParticleSystem();
+
+ PX_INLINE void removeFromScene();
+
+ bool createParticles(const PxParticleCreationData& creationData);
+ void releaseParticles(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer);
+ void releaseParticles();
+ void setPositions(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& positionBuffer);
+ void setVelocities(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& velocitiesBuffer);
+ void setRestOffsets(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxF32>& restOffsetBuffer);
+ void addForces(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& forceBuffer, PxForceMode::Enum forceMode);
+
+ PX_INLINE PxParticleReadData* lockParticleReadData(PxDataAccessFlags flags);
+
+ PX_INLINE PxU32 getSimulationMethod() const;
+
+ PX_INLINE PxReal getStiffness() const { return read<Buf::BF_Stiffness>(); }
+ PX_INLINE void setStiffness(PxReal v) { write<Buf::BF_Stiffness>(v); }
+
+ PX_INLINE PxReal getViscosity() const { return read<Buf::BF_Viscosity>(); }
+ PX_INLINE void setViscosity(PxReal v) { write<Buf::BF_Viscosity>(v); }
+
+ PX_INLINE PxReal getDamping() const { return read<Buf::BF_Damping>(); }
+ PX_INLINE void setDamping(PxReal v) { write<Buf::BF_Damping>(v); }
+
+ PX_INLINE PxVec3 getExternalAcceleration() const { return read<Buf::BF_ExternalAcceleration>(); }
+ PX_INLINE void setExternalAcceleration(const PxVec3& v) { write<Buf::BF_ExternalAcceleration>(v); }
+
+ PX_INLINE PxPlane getProjectionPlane() const { return read<Buf::BF_ProjectionPlane>(); }
+ PX_INLINE void setProjectionPlane(const PxPlane& v) { write<Buf::BF_ProjectionPlane>(v); }
+
+ PX_INLINE PxReal getParticleMass() const { return read<Buf::BF_ParticleMass>(); }
+ PX_INLINE void setParticleMass(PxReal v) { write<Buf::BF_ParticleMass>(v); }
+
+ PX_INLINE PxReal getRestitution() const { return read<Buf::BF_Restitution>(); }
+ PX_INLINE void setRestitution(PxReal v) { write<Buf::BF_Restitution>(v); }
+
+ PX_INLINE PxReal getDynamicFriction() const { return read<Buf::BF_DynamicFriction>(); }
+ PX_INLINE void setDynamicFriction(PxReal v) { write<Buf::BF_DynamicFriction>(v);}
+
+ PX_INLINE PxReal getStaticFriction() const { return read<Buf::BF_StaticFriction>(); }
+ PX_INLINE void setStaticFriction(PxReal v) { write<Buf::BF_StaticFriction>(v); }
+
+ PX_INLINE PxParticleBaseFlags getFlags() const { return read<Buf::BF_Flags>();}
+ PX_INLINE void setFlags(PxParticleBaseFlags v) { write<Buf::BF_Flags>(v); }
+
+ PX_INLINE PxFilterData getSimulationFilterData() const { return read<Buf::BF_SimulationFilterData>(); }
+ PX_INLINE void setSimulationFilterData(const PxFilterData& v) { write<Buf::BF_SimulationFilterData>(v); }
+
+ PX_INLINE void resetFiltering();
+
+ PX_INLINE PxParticleReadDataFlags getParticleReadDataFlags() const;
+ PX_INLINE void setParticleReadDataFlags(PxParticleReadDataFlags);
+
+
+ PX_INLINE PxU32 getParticleCount() const;
+ PX_INLINE const Cm::BitMap& getParticleMap() const;
+
+ PX_INLINE PxU32 getMaxParticles() const;
+
+ PX_INLINE PxReal getMaxMotionDistance() const;
+ PX_INLINE void setMaxMotionDistance(PxReal);
+ PX_INLINE PxReal getRestOffset() const;
+ PX_INLINE void setRestOffset(PxReal);
+ PX_INLINE PxReal getContactOffset() const;
+ PX_INLINE void setContactOffset(PxReal);
+ PX_INLINE PxReal getRestParticleDistance() const;
+ PX_INLINE void setRestParticleDistance(PxReal);
+ PX_INLINE PxReal getGridSize() const;
+ PX_INLINE void setGridSize(PxReal);
+
+ PX_INLINE PxBounds3 getWorldBounds() const;
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+
+ // Synchronously called when the scene starts to be simulated.
+ void submitForceUpdates(PxReal timeStep);
+
+ // Synchronously called with fetchResults.
+ void syncState();
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ PX_FORCE_INLINE const Core& getScParticleSystem() const { return mParticleSystem; } // Only use if you know what you're doing!
+ PX_FORCE_INLINE Core& getScParticleSystem() { return mParticleSystem; } // Only use if you know what you're doing!
+
+ PX_FORCE_INLINE static const ParticleSystem&fromSc(const Core& a) { return static_cast<const ParticleSystem&>(Actor::fromSc(a)); }
+ PX_FORCE_INLINE static ParticleSystem& fromSc(Core &a) {
+
+ Scb::Actor& actor = Actor::fromSc(a);
+ ParticleSystem& ps = static_cast<ParticleSystem&>(actor);
+ PX_UNUSED(ps);
+
+ return static_cast<ParticleSystem&>(Actor::fromSc(a));
+
+ }
+
+ static size_t getScOffset()
+ {
+ return reinterpret_cast<size_t>(&reinterpret_cast<ParticleSystem*>(0)->mParticleSystem);
+ }
+
+#if PX_SUPPORT_GPU_PHYSX
+ PX_INLINE void enableDeviceExclusiveModeGpu();
+ PX_INLINE PxParticleDeviceExclusiveAccess* getDeviceExclusiveAccessGpu() const;
+#endif
+
+private:
+ Core mParticleSystem;
+
+ NpParticleFluidReadData* mReadParticleFluidData;
+
+
+ ForceUpdates mForceUpdatesAcc;
+ ForceUpdates mForceUpdatesVel;
+
+ PX_FORCE_INLINE const Scb::ParticleSystemBuffer* getParticleSystemBuffer() const { return reinterpret_cast<const Scb::ParticleSystemBuffer*>(getStream()); }
+ PX_FORCE_INLINE Scb::ParticleSystemBuffer* getParticleSystemBuffer() { return reinterpret_cast<Scb::ParticleSystemBuffer*>(getStream()); }
+
+ //---------------------------------------------------------------------------------
+ // Infrastructure for regular attributes
+ //---------------------------------------------------------------------------------
+
+ struct Access: public BufferedAccess<Buf, Core, ParticleSystem> {};
+ template<PxU32 f> PX_FORCE_INLINE typename Buf::Fns<f,0>::Arg read() const { return Access::read<Buf::Fns<f, 0> >(*this, mParticleSystem); }
+ template<PxU32 f> PX_FORCE_INLINE void write(typename Buf::Fns<f,0>::Arg v) { Access::write<Buf::Fns<f, 0> >(*this, mParticleSystem, v); }
+ template<PxU32 f> PX_FORCE_INLINE void flush(const Buf& buf) { Access::flush<Buf::Fns<f, 0> >(*this, mParticleSystem, buf); }
+};
+
+PX_INLINE PxParticleBase* ParticleSystem::getPxParticleSystem()
+{
+ return getScParticleSystem().getPxParticleBase();
+}
+
+
+PX_INLINE void ParticleSystem::removeFromScene()
+{
+ PX_ASSERT(!isBuffering() || getControlState()==ControlState::eREMOVE_PENDING);
+
+ mForceUpdatesAcc.destroy();
+ mForceUpdatesVel.destroy();
+}
+
+
+PX_INLINE PxParticleReadData* ParticleSystem::lockParticleReadData(PxDataAccessFlags flags)
+{
+ // Don't use the macro here since releasing the lock should not be done automatically but by the user
+ if (isBuffering())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Particle data read not allowed while simulation is running.");
+ return NULL;
+ }
+
+ if (!mReadParticleFluidData)
+ {
+ mReadParticleFluidData = PX_NEW(NpParticleFluidReadData)();
+ }
+
+ mReadParticleFluidData->lock("PxParticleBase::lockParticleReadData()");
+ mReadParticleFluidData->setDataAccessFlags(flags);
+ getScParticleSystem().getParticleReadData(*mReadParticleFluidData);
+ return mReadParticleFluidData;
+}
+
+
+
+
+PX_INLINE void ParticleSystem::resetFiltering()
+{
+ if (!isBuffering())
+ {
+ getScParticleSystem().resetFiltering();
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+ else
+ {
+ markUpdated(Buf::BF_ResetFiltering);
+ }
+}
+
+
+
+PX_INLINE PxParticleReadDataFlags ParticleSystem::getParticleReadDataFlags() const
+{
+ return getScParticleSystem().getParticleReadDataFlags();
+}
+
+PX_INLINE void ParticleSystem::setParticleReadDataFlags(PxParticleReadDataFlags flags)
+{
+ if (!isBuffering())
+ {
+ getScParticleSystem().setParticleReadDataFlags(flags);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+}
+
+PX_INLINE PxU32 ParticleSystem::getParticleCount() const
+{
+ return getScParticleSystem().getParticleCount();
+}
+
+PX_INLINE const Cm::BitMap& ParticleSystem::getParticleMap() const
+{
+ return getScParticleSystem().getParticleMap();
+}
+
+PX_INLINE PxU32 ParticleSystem::getMaxParticles() const
+{
+ return getScParticleSystem().getMaxParticles();
+}
+
+
+PX_INLINE PxReal ParticleSystem::getMaxMotionDistance() const
+{
+ return getScParticleSystem().getMaxMotionDistance();
+}
+
+PX_INLINE void ParticleSystem::setMaxMotionDistance(PxReal distance)
+{
+ if (!isBuffering())
+ {
+ getScParticleSystem().setMaxMotionDistance(distance);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+}
+
+PX_INLINE PxReal ParticleSystem::getRestOffset() const
+{
+ return getScParticleSystem().getRestOffset();
+}
+
+
+PX_INLINE void ParticleSystem::setRestOffset(PxReal restOffset)
+{
+ if (!isBuffering())
+ {
+ getScParticleSystem().setRestOffset(restOffset);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+}
+
+PX_INLINE PxReal ParticleSystem::getContactOffset() const
+{
+ return getScParticleSystem().getContactOffset();
+}
+
+PX_INLINE void ParticleSystem::setContactOffset(PxReal contactOffset)
+{
+ if (!isBuffering())
+ {
+ getScParticleSystem().setContactOffset(contactOffset);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+}
+
+PX_INLINE PxReal ParticleSystem::getRestParticleDistance() const
+{
+ return getScParticleSystem().getRestParticleDistance();
+}
+
+PX_INLINE void ParticleSystem::setRestParticleDistance(PxReal restParticleDistance)
+{
+ if (!isBuffering())
+ {
+ getScParticleSystem().setRestParticleDistance(restParticleDistance);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+}
+
+
+PX_INLINE PxReal ParticleSystem::getGridSize() const
+{
+ return getScParticleSystem().getGridSize();
+}
+
+PX_INLINE void ParticleSystem::setGridSize(PxReal gridSize)
+{
+ if (!isBuffering())
+ {
+ getScParticleSystem().setGridSize(gridSize);
+ UPDATE_PVD_PROPERTIES_OBJECT()
+ }
+}
+
+PX_INLINE PxBounds3 ParticleSystem::getWorldBounds() const
+{
+ if (isBuffering())
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxActor::getWorldBounds(): Can't access particle world bounds during simulation without enabling bulk buffering.");
+ return PxBounds3();
+ }
+
+ return getScParticleSystem().getWorldBounds();
+}
+
+#if PX_SUPPORT_GPU_PHYSX
+
+PX_INLINE void ParticleSystem::enableDeviceExclusiveModeGpu()
+{
+ getScParticleSystem().enableDeviceExclusiveModeGpu();
+}
+
+PX_INLINE PxParticleDeviceExclusiveAccess* ParticleSystem::getDeviceExclusiveAccessGpu() const
+{
+ if (getFlags() & PxParticleBaseFlag::eGPU)
+ {
+ return getScParticleSystem().getDeviceExclusiveAccessGpu();
+ }
+ return NULL;
+}
+
+#endif
+
+} // namespace Scb
+
+}
+
+#endif // PX_USE_PARTICLE_SYSTEM_API
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbRigidObject.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbRigidObject.h
new file mode 100644
index 00000000..e1ea7a43
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbRigidObject.h
@@ -0,0 +1,530 @@
+// 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_SCB_RIGID_OBJECT
+#define PX_PHYSICS_SCB_RIGID_OBJECT
+
+#include "../../SimulationController/include/ScRigidCore.h"
+#include "ScbScene.h"
+#include "ScbActor.h"
+#include "ScbShape.h"
+#include "PsInlineArray.h"
+
+namespace physx
+{
+
+// base class for dynamic and static rigid objects, so that shapes can have something to refer to
+
+namespace Scb
+{
+
+struct RemovedShape
+{
+ RemovedShape() : mShape(NULL), mWakeTouching(0) {}
+ RemovedShape(Scb::Shape* s, PxU8 wakeTouching) : mShape(s), mWakeTouching(wakeTouching) {}
+
+ PX_FORCE_INLINE bool operator == (const RemovedShape& other) const
+ {
+ return (mShape == other.mShape);
+ }
+
+ PX_FORCE_INLINE bool operator != (const RemovedShape& other) const
+ {
+ return (mShape != other.mShape);
+ }
+
+ Scb::Shape* mShape;
+ PxU8 mWakeTouching;
+};
+
+
+struct RigidObjectBuffer : public ActorBuffer //once RigidObject has its own buffered elements, derive from that instead
+{
+ RigidObjectBuffer(): mResetFilterShape(0), mResetFilterShapeCount(0) {}
+
+ // TODO(dsequeira): ideally we would use an allocator that allocates from the buffered memory stream
+ Ps::InlineArray<Scb::Shape*, 4> mAddedShapes;
+ Ps::InlineArray<Scb::RemovedShape, 4> mRemovedShapes;
+ union
+ {
+ PxU32 mResetFilterShapesIdx;
+ Scb::Shape* mResetFilterShape;
+ };
+ PxU32 mResetFilterShapeCount;
+
+ enum { BF_Base = ActorBuffer::AttrCount };
+
+ enum
+ {
+ BF_Shapes = 1<<BF_Base,
+ BF_WakeTouching = 1<<(BF_Base+1),
+ BF_ResetFiltering = 1<<(BF_Base+2)
+ };
+
+ enum { AttrCount = ActorBuffer::AttrCount+3 };
+};
+
+
+class RigidObject : public Scb::Actor
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+
+ typedef RigidObjectBuffer Buf;
+ typedef Sc::RigidCore Core;
+
+public:
+// PX_SERIALIZATION
+ RigidObject() {}
+ RigidObject(const PxEMPTY) : Scb::Actor(PxEmpty) {}
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+
+ //---------------------------------------------------------------------------------
+ // Wrapper for Sc::RigidCore interface
+ //---------------------------------------------------------------------------------
+
+ PX_INLINE void resetFiltering(Scb::Shape*const* shapes, PxU32 shapeCount);
+
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+
+ // the fetchResults order is to process removes, do callbacks, and then do the other synchronization. So we need to split sync'ing of
+ // adds and removes
+ // Note: The array of removed shapes must be reset here to avoid memory leaks: even if the control state means we don't process the
+ // array of removed shapes, we still need to clear the array.
+ PX_INLINE void processShapeRemoves()
+ {
+ if(getBufferFlags() & Buf::BF_Shapes)
+ {
+ RigidObjectBuffer* b = getBuffer();
+
+ if(getControlState() == ControlState::eIN_SCENE)
+ {
+#if PX_SUPPORT_PVD
+ PxActor& pxActor = *getScRigidCore().getPxActor();
+#endif
+ for(PxU32 i=0;i<b->mRemovedShapes.size();i++)
+ {
+ RemovedShape& rs = b->mRemovedShapes[i];
+ Shape& shape = *rs.mShape;
+ shape.setControlStateIfExclusive(NULL, Scb::ControlState::eNOT_IN_SCENE);
+
+ Sc::RigidCore& rc = getScRigidCore();
+ Scb::Scene* scene = getScbScene();
+#if PX_SUPPORT_PVD
+ scene->getScenePvdClient().releasePvdInstance(&shape, pxActor);
+#endif
+ if (!isSimDisabledInternally())
+ {
+ rc.removeShapeFromScene(shape.getScShape(), (rs.mWakeTouching != 0));
+
+ shape.checkUpdateOnRemove<true>(scene);
+
+ NpShapeDecRefCount(shape);
+ }
+ }
+ }
+
+ // The array of removed shapes must be reset to avoid memory leaks.
+ b->mRemovedShapes.reset();
+ }
+ }
+
+ PX_INLINE void syncState()
+ {
+ PxU32 bufferFlags = getBufferFlags();
+
+ if (bufferFlags & Buf::BF_ResetFiltering)
+ {
+ PX_ASSERT(getControlState() != ControlState::eREMOVE_PENDING); // removing the actor should have cleared BF_ResetFiltering
+
+ Scb::Scene* scene = getScbScene();
+ Sc::RigidCore& scCore = getScRigidCore();
+ RigidObjectBuffer* b = getBuffer();
+ Scb::Shape* const* shapes = (b->mResetFilterShapeCount == 1) ? &b->mResetFilterShape : scene->getShapeBuffer(b->mResetFilterShapesIdx);
+ for(PxU32 i=0; i < b->mResetFilterShapeCount; i++)
+ {
+ Sc::ShapeCore& scShape = shapes[i]->getScShape();
+
+ // do not process the call if the shape will not be a broadphase shape any longer
+ if (shapes[i]->getFlags() & (PxShapeFlag::eSIMULATION_SHAPE | PxShapeFlag::eTRIGGER_SHAPE))
+ scCore.onShapeChange(scShape, Sc::ShapeChangeNotifyFlag::eRESET_FILTERING, PxShapeFlags());
+ }
+ }
+
+ if(bufferFlags & Buf::BF_Shapes)
+ {
+ RigidObjectBuffer* b = getBuffer();
+ ControlState::Enum cs = getControlState();
+#if PX_SUPPORT_PVD
+ PxActor& pxActor = *getScRigidCore().getPxActor();
+#endif
+ for(PxU32 i=0;i<b->mAddedShapes.size();i++)
+ {
+ Shape& shape = *b->mAddedShapes[i];
+
+ // it can happen that a shape gets attached while the sim is running but then the actor is removed from the scene,
+ // so we need to distinguish those two cases
+ if (cs != ControlState::eREMOVE_PENDING)
+ {
+ shape.setControlStateIfExclusive(getScbScene(), Scb::ControlState::eIN_SCENE);
+
+ if (!(getActorFlags() & PxActorFlag::eDISABLE_SIMULATION)) // important to use the buffered flags since we want the new state.
+ {
+ getScRigidCore().addShapeToScene(shape.getScShape());
+ NpShapeIncRefCount(shape);
+ }
+#if PX_SUPPORT_PVD
+ getScbScene()->getScenePvdClient().createPvdInstance(&shape, pxActor);
+#endif
+ }
+ else
+ shape.setControlStateIfExclusive(getScbScene(), Scb::ControlState::eNOT_IN_SCENE);
+ }
+
+ // reset the arrays, because destructors don't run on buffers
+ b->mAddedShapes.reset();
+ }
+
+ Actor::syncState();
+ }
+
+ PX_FORCE_INLINE void scheduleForWakeTouching() { PX_ASSERT(getScbScene() && getScbScene()->isPhysicsBuffering()); setBufferFlag(RigidObjectBuffer::BF_WakeTouching); }
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+public:
+ PX_INLINE const Sc::RigidCore& getScRigidCore() const { return static_cast<const Sc::RigidCore&>(getActorCore()); } // Only use if you know what you're doing!
+ PX_INLINE Sc::RigidCore& getScRigidCore() { return static_cast<Sc::RigidCore&>(getActorCore()); } // Only use if you know what you're doing!
+
+ PX_INLINE void setShapeStateIfExclusive(Scb::Shape& shape, ControlState::Enum cs, Scb::Scene& scene)
+ {
+ if(shape.isExclusive())
+ {
+ shape.setScbScene(&scene);
+ shape.setControlState(cs);
+ }
+ }
+
+ PX_INLINE void onShapeAttach(Scb::Shape& shape)
+ {
+ // there are two things to do here: add the shape to the sim (if unbuffered) or set it up for
+ // * if unbuffered, add the shape to the sim and PVD and increment its refcount, else set it up for buffered insertion,
+ // * if the shape is exclusive, set its Scb control state appropriately.
+
+ ControlState::Enum cs = getControlState();
+ if(cs==ControlState::eNOT_IN_SCENE)
+ return;
+
+ Scene* scbScene = getScbScene();
+ if(!scbScene->isPhysicsBuffering())
+ {
+ if (!(getActorFlags() & PxActorFlag::eDISABLE_SIMULATION))
+ {
+ NpShapeIncRefCount(shape);
+ getScRigidCore().addShapeToScene(shape.getScShape());
+ }
+
+#if PX_SUPPORT_PVD
+ getScbScene()->getScenePvdClient().createPvdInstance(&shape, *getScRigidCore().getPxActor());
+#endif
+ shape.setControlStateIfExclusive(scbScene, ControlState::eIN_SCENE);
+ return;
+ }
+ else if (cs == ControlState::eINSERT_PENDING)
+ {
+ shape.setControlStateIfExclusive(scbScene, ControlState::eINSERT_PENDING);
+ return;
+ }
+
+ RigidObjectBuffer* b = getBuffer();
+ if(!b->mRemovedShapes.findAndReplaceWithLast(RemovedShape(&shape, 0)))
+ b->mAddedShapes.pushBack(&shape);
+ markUpdated(Buf::BF_Shapes);
+
+ shape.setControlStateIfExclusive(scbScene, ControlState::eINSERT_PENDING);
+ }
+
+
+ PX_INLINE void onShapeDetach(Scb::Shape& shape, bool wakeOnLostTouch, bool toBeReleased)
+ {
+ // see comments in onShapeAttach
+ ControlState::Enum cs = getControlState();
+ if(cs==ControlState::eNOT_IN_SCENE)
+ return;
+
+ Scene* scbScene = getScbScene();
+ if(!scbScene->isPhysicsBuffering())
+ {
+#if PX_SUPPORT_PVD
+ scbScene->getScenePvdClient().releasePvdInstance(&shape, *getScRigidCore().getPxActor());
+#endif
+ if (!(getActorFlags() & PxActorFlag::eDISABLE_SIMULATION))
+ {
+ getScRigidCore().removeShapeFromScene(shape.getScShape(), wakeOnLostTouch);
+ NpShapeDecRefCount(shape);
+ }
+
+ shape.setControlStateIfExclusive(NULL, ControlState::eNOT_IN_SCENE);
+ return;
+ }
+ else if (cs == ControlState::eINSERT_PENDING)
+ {
+ shape.setControlStateIfExclusive(NULL, ControlState::eNOT_IN_SCENE);
+ return;
+ }
+
+ RigidObjectBuffer* b = getBuffer();
+
+ // remove from the resetFiltering list
+ PxU32 bufferFlags = getBufferFlags();
+ if (bufferFlags & Buf::BF_ResetFiltering)
+ {
+ if (b->mResetFilterShapeCount == 1)
+ {
+ if (b->mResetFilterShape == &shape)
+ {
+ b->mResetFilterShapeCount = 0;
+ b->mResetFilterShape = 0;
+ resetBufferFlag(Buf::BF_ResetFiltering);
+ }
+ }
+ else
+ {
+ Scb::Shape** shapes = scbScene->getShapeBuffer(b->mResetFilterShapesIdx);
+ PxU32 idx = 0;
+ PxU32 lastIdx = b->mResetFilterShapeCount;
+ for(PxU32 k=0; k < b->mResetFilterShapeCount; k++) // need to iterate over whole list, same shape can be in there multiple times
+ {
+ if (shapes[idx] != &shape)
+ idx++;
+ else
+ {
+ lastIdx--;
+ shapes[idx] = shapes[lastIdx];
+ }
+ }
+ b->mResetFilterShapeCount = idx;
+ if (idx == 0)
+ {
+ b->mResetFilterShape = 0;
+ resetBufferFlag(Buf::BF_ResetFiltering);
+ }
+ else if (idx == 1)
+ b->mResetFilterShape = shapes[0];
+ }
+ }
+
+ if(b->mAddedShapes.findAndReplaceWithLast(&shape))
+ shape.setControlStateIfExclusive(scbScene, ControlState::eIN_SCENE);
+ else
+ {
+ if (!isSimDisabledInternally())
+ {
+ b->mRemovedShapes.pushBack(RemovedShape(&shape, PxU8(wakeOnLostTouch ? 1 : 0)));
+ }
+ else
+ {
+ PX_ASSERT(scbScene);
+ PX_ASSERT(scbScene->isPhysicsBuffering());
+ if (toBeReleased)
+ {
+ shape.checkUpdateOnRemove<false>(scbScene);
+#if PX_SUPPORT_PVD
+ scbScene->getScenePvdClient().releasePvdInstance(&shape, *getScRigidCore().getPxActor());
+#endif
+ }
+ else
+ b->mRemovedShapes.pushBack(RemovedShape(&shape, 0));
+ }
+ shape.setControlStateIfExclusive(scbScene, ControlState::eREMOVE_PENDING);
+ }
+ markUpdated(Buf::BF_Shapes);
+ }
+
+ PX_INLINE bool isAddedShape(Scb::Shape&); // check whether the specified shape is pending for insertion. Only call this method if you know that there are pending shape adds/removes.
+
+ PX_FORCE_INLINE void switchToNoSim(bool isDynamic);
+ PX_FORCE_INLINE void switchFromNoSim(bool isDynamic);
+ PX_FORCE_INLINE void syncNoSimSwitch(const Buf& buf, Sc::RigidCore& rc, bool isDynamic);
+
+ // IMPORTANT: This is the non-buffered state, for the case where it is important to know what the current internal state is.
+ // Reading is fine even if the sim is running because actor flags are read-only internally.
+ PX_FORCE_INLINE bool isSimDisabledInternally() const { return getScRigidCore().getActorFlags().isSet(PxActorFlag::eDISABLE_SIMULATION); }
+
+ PX_FORCE_INLINE void clearBufferedState() { resetBufferFlag(Buf::BF_ResetFiltering); }
+
+ PX_FORCE_INLINE static const RigidObject& fromSc(const Sc::RigidCore& a) { return static_cast<const RigidObject&>(Actor::fromSc(a)); }
+ PX_FORCE_INLINE static RigidObject& fromSc(Sc::RigidCore &a) { return static_cast<RigidObject&>(Actor::fromSc(a)); }
+protected:
+ ~RigidObject() {}
+private:
+ Buf* getBuffer() { return reinterpret_cast<Buf*>(getStream()); }
+
+ PX_FORCE_INLINE void copyResetFilterShapes(Scb::Shape** shapePtrs, Scb::Shape*const* oldShapes, PxU32 oldShapeCount, Scb::Shape*const* newShapes, PxU32 newShapeCount);
+};
+
+
+PX_INLINE void RigidObject::resetFiltering(Scb::Shape*const* shapes, PxU32 shapeCount)
+{
+ PX_ASSERT(!(getActorFlags() & PxActorFlag::eDISABLE_SIMULATION));
+
+ if(!isBuffering())
+ {
+ for(PxU32 i=0; i < shapeCount; i++)
+ getScRigidCore().onShapeChange(shapes[i]->getScShape(), Sc::ShapeChangeNotifyFlag::eRESET_FILTERING, PxShapeFlags());
+ }
+ else
+ {
+ RigidObjectBuffer* b = getBuffer();
+
+ if (b->mResetFilterShapeCount == 0)
+ {
+ if (shapeCount == 1)
+ {
+ b->mResetFilterShape = shapes[0];
+ b->mResetFilterShapeCount = 1;
+ markUpdated(Buf::BF_ResetFiltering);
+ }
+ else
+ {
+ PxU32 bufferIdx;
+ Scb::Shape** shapePtrs = getScbScene()->allocShapeBuffer(shapeCount, bufferIdx);
+ if (shapePtrs)
+ {
+ for(PxU32 i=0; i < shapeCount; i++)
+ shapePtrs[i] = shapes[i];
+ b->mResetFilterShapesIdx = bufferIdx;
+ b->mResetFilterShapeCount = shapeCount;
+ markUpdated(Buf::BF_ResetFiltering);
+ }
+ }
+ }
+ else
+ {
+ PxU32 newCount = b->mResetFilterShapeCount + shapeCount;
+ PxU32 bufferIdx;
+ Scb::Shape** shapePtrs = getScbScene()->allocShapeBuffer(newCount, bufferIdx);
+ if (shapePtrs)
+ {
+ if (b->mResetFilterShapeCount == 1)
+ copyResetFilterShapes(shapePtrs, &b->mResetFilterShape, 1, shapes, shapeCount);
+ else
+ copyResetFilterShapes(shapePtrs, getScbScene()->getShapeBuffer(b->mResetFilterShapesIdx), b->mResetFilterShapeCount, shapes, shapeCount);
+ b->mResetFilterShapesIdx = bufferIdx;
+ b->mResetFilterShapeCount = newCount;
+ markUpdated(Buf::BF_ResetFiltering);
+ }
+ }
+ }
+}
+
+
+PX_INLINE bool RigidObject::isAddedShape(Scb::Shape& shape)
+{
+ PX_ASSERT(isBuffered(Buf::BF_Shapes));
+
+ if (shape.isExclusive())
+ {
+ return (shape.getControlState() == Scb::ControlState::eINSERT_PENDING);
+ }
+ else
+ {
+ // For shared shapes it is not clear from the shape alone whether it has been added while the simulation was running.
+
+ RigidObjectBuffer* buf = getBuffer();
+ PX_ASSERT(buf);
+ const PxU32 addedShapeCount = buf->mAddedShapes.size();
+ for(PxU32 k=0; k < addedShapeCount; k++)
+ {
+ if (&shape == buf->mAddedShapes[k])
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+}
+
+
+PX_FORCE_INLINE void RigidObject::switchToNoSim(bool isDynamic)
+{
+ Scb::Scene* scene = getScbScene();
+
+ if (scene && (!scene->isPhysicsBuffering()))
+ scene->switchRigidToNoSim(*this, isDynamic);
+}
+
+
+PX_FORCE_INLINE void RigidObject::switchFromNoSim(bool isDynamic)
+{
+ Scb::Scene* scene = getScbScene();
+
+ if (scene && (!scene->isPhysicsBuffering()))
+ scene->switchRigidFromNoSim(*this, isDynamic);
+}
+
+
+PX_FORCE_INLINE void RigidObject::syncNoSimSwitch(const Buf& buf, Sc::RigidCore& rc, bool isDynamic)
+{
+ PxActorFlags oldFlags = rc.getActorFlags();
+ bool oldNoSim = oldFlags.isSet(PxActorFlag::eDISABLE_SIMULATION);
+ bool newNoSim = buf.mActorFlags.isSet(PxActorFlag::eDISABLE_SIMULATION);
+
+ if (oldNoSim && (!newNoSim))
+ getScbScene()->switchRigidFromNoSim(*this, isDynamic);
+ else if ((!oldNoSim) && newNoSim)
+ getScbScene()->switchRigidToNoSim(*this, isDynamic);
+}
+
+
+PX_FORCE_INLINE void RigidObject::copyResetFilterShapes(Scb::Shape** shapePtrs, Scb::Shape*const* oldShapes, PxU32 oldShapeCount, Scb::Shape*const* newShapes, PxU32 newShapeCount)
+{
+ for(PxU32 i=0; i < oldShapeCount; i++)
+ shapePtrs[i] = oldShapes[i];
+ for(PxU32 i=0; i < newShapeCount; i++)
+ shapePtrs[i+oldShapeCount] = newShapes[i];
+}
+
+
+} // namespace Scb
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbRigidStatic.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbRigidStatic.h
new file mode 100644
index 00000000..d783f203
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbRigidStatic.h
@@ -0,0 +1,155 @@
+// 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_SCB_RIGID_STATIC
+#define PX_PHYSICS_SCB_RIGID_STATIC
+
+#include "ScStaticCore.h"
+#include "ScbScene.h"
+#include "ScbActor.h"
+#include "ScbRigidObject.h"
+
+namespace physx
+{
+
+namespace Scb
+{
+
+#if PX_VC
+ #pragma warning(push)
+ #pragma warning( disable : 4324 ) // Padding was added at the end of a structure because of a __declspec(align) value.
+#endif
+
+struct RigidStaticBuffer : public RigidObjectBuffer
+{
+ template <PxU32 I, PxU32 Dummy> struct Fns {}; // TODO: make the base class traits visible
+ typedef Sc::StaticCore Core;
+ typedef RigidStaticBuffer Buf;
+
+ // regular attributes
+ enum { BF_Base = RigidObjectBuffer::AttrCount };
+ SCB_REGULAR_ATTRIBUTE_ALIGNED(BF_Base, PxTransform, Actor2World, 16)
+};
+
+#if PX_VC
+ #pragma warning(pop)
+#endif
+
+
+class RigidStatic : public Scb::RigidObject
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+
+ typedef RigidStaticBuffer Buf;
+ typedef Sc::StaticCore Core;
+
+public:
+// PX_SERIALIZATION
+ RigidStatic(const PxEMPTY) : Scb::RigidObject(PxEmpty), mStatic(PxEmpty) {}
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ PX_INLINE RigidStatic(const PxTransform& actor2World);
+ PX_INLINE ~RigidStatic() {}
+
+ PX_INLINE const PxTransform& getActor2World() const { return read<Buf::BF_Actor2World>(); }
+ PX_INLINE void setActor2World(const PxTransform& m) { write<Buf::BF_Actor2World>(m); }
+
+ PX_FORCE_INLINE void onOriginShift(const PxVec3& shift) { mStatic.onOriginShift(shift); }
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+ PX_INLINE void syncState();
+
+ static size_t getScOffset()
+ {
+ return reinterpret_cast<size_t>(&reinterpret_cast<RigidStatic*>(0)->mStatic);
+ }
+
+ PX_FORCE_INLINE Sc::StaticCore& getScStatic() { return mStatic; }
+
+ PX_FORCE_INLINE void initBufferedState() {}
+
+private:
+ Sc::StaticCore mStatic;
+
+ PX_FORCE_INLINE const Buf* getRigidActorBuffer() const { return reinterpret_cast<const Buf*>(getStream()); }
+ PX_FORCE_INLINE Buf* getRigidActorBuffer() { return reinterpret_cast<Buf*>(getStream()); }
+
+ //---------------------------------------------------------------------------------
+ // Infrastructure for regular attributes
+ //---------------------------------------------------------------------------------
+
+ struct Access: public BufferedAccess<Buf, Core, RigidStatic> {};
+
+ template<PxU32 f> PX_FORCE_INLINE typename Buf::Fns<f,0>::Arg read() const { return Access::read<Buf::Fns<f,0> >(*this, mStatic); }
+ template<PxU32 f> PX_FORCE_INLINE void write(typename Buf::Fns<f,0>::Arg v) { Access::write<Buf::Fns<f,0> >(*this, mStatic, v); }
+ template<PxU32 f> PX_FORCE_INLINE void flush(const Buf& buf) { Access::flush<Buf::Fns<f,0> >(*this, mStatic, buf); }
+
+};
+
+RigidStatic::RigidStatic(const PxTransform& actor2World) :
+ mStatic(actor2World)
+{
+ setScbType(ScbType::RIGID_STATIC);
+}
+
+
+//--------------------------------------------------------------
+//
+// Data synchronization
+//
+//--------------------------------------------------------------
+
+PX_INLINE void RigidStatic::syncState()
+{
+ PxU32 bufferFlags = getBufferFlags();
+
+ if (bufferFlags & Buf::BF_ActorFlags)
+ syncNoSimSwitch(*getRigidActorBuffer(), mStatic, false);
+
+ RigidObject::syncState();
+
+ if (bufferFlags & Buf::BF_Actor2World)
+ flush<Buf::BF_Actor2World>(*getRigidActorBuffer());
+
+ postSyncState();
+}
+
+} // namespace Scb
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbScene.cpp b/PhysX_3.4/Source/PhysX/src/buffering/ScbScene.cpp
new file mode 100644
index 00000000..0d0ac638
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbScene.cpp
@@ -0,0 +1,1514 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "NpCast.h"
+#include "ScbScene.h"
+#include "ScbRigidStatic.h"
+#include "ScbBody.h"
+#include "ScbShape.h"
+#include "ScbConstraint.h"
+#include "ScbParticleSystem.h"
+#include "ScbArticulation.h"
+#include "ScbArticulationJoint.h"
+#include "ScbCloth.h"
+#include "ScbNpDeps.h"
+#include "ScbAggregate.h"
+
+#include "PsFoundation.h"
+#include "PxArticulation.h"
+
+namespace physx
+{
+ class NpMaterial;
+}
+
+using namespace physx;
+
+// constants to make boolean template parameters more readable
+static const bool tSimRunning = true;
+static const bool tAdd = true;
+static const bool tDynamic = true;
+static const bool tNonSimObject = true;
+static const bool tSyncOnRemove = true;
+static const bool tWakeOnLostTouchCheck = true;
+
+void Scb::ObjectTracker::scheduleForInsert(Scb::Base& element)
+{
+ ControlState::Enum state = element.getControlState();
+ PxU32 flags = element.getControlFlags();
+ PX_ASSERT(!(flags & ControlFlag::eIS_RELEASED));
+ PX_ASSERT(state == ControlState::eNOT_IN_SCENE || state == ControlState::eREMOVE_PENDING);
+
+ if(state == ControlState::eREMOVE_PENDING)
+ {
+ element.setControlState(ControlState::eIN_SCENE);
+ if(!(flags & ControlFlag::eIS_UPDATED))
+ remove(element);
+ }
+ else
+ {
+ PX_ASSERT(!(flags & ControlFlag::eIS_UPDATED));
+ element.setControlState(ControlState::eINSERT_PENDING);
+ insert(element);
+ }
+}
+
+void Scb::ObjectTracker::scheduleForRemove(Scb::Base& element)
+{
+ ControlState::Enum state = element.getControlState();
+ PxU32 flags = element.getControlFlags();
+
+ PX_ASSERT(!(flags & ControlFlag::eIS_RELEASED));
+
+ if(state == ControlState::eINSERT_PENDING)
+ {
+ // if it's inserted this frame, just remove it - it can't be dirty
+ //ML: this assert wont' work because buffered insert raises this flag. We have a unit test which called TEST_F(ObserverTest, OnRelease) to verify it
+ //PX_ASSERT(!(flags & ControlFlag::eIS_UPDATED));
+ element.setControlState(ControlState::eNOT_IN_SCENE);
+ remove(element);
+ }
+ else if(state == ControlState::eIN_SCENE)
+ {
+ element.setControlState(ControlState::eREMOVE_PENDING);
+ if(!(flags & ControlFlag::eIS_UPDATED))
+ insert(element);
+ }
+ else
+ {
+ PX_ALWAYS_ASSERT_MESSAGE("Trying to remove element not in scene.");
+ }
+}
+
+void Scb::ObjectTracker::scheduleForUpdate(Scb::Base& element)
+{
+ ControlState::Enum state = element.getControlState();
+ PxU32 flags = element.getControlFlags();
+
+ PX_ASSERT(!(flags & ControlFlag::eIS_RELEASED));
+ PX_ASSERT(state == ControlState::eIN_SCENE || state == ControlState::eREMOVE_PENDING || state == ControlState::eINSERT_PENDING);
+
+ if(!(flags & ControlFlag::eIS_UPDATED))
+ {
+ element.setControlFlag(ControlFlag::eIS_UPDATED);
+ if(state == ControlState::eIN_SCENE)
+ insert(element);
+ }
+}
+
+void Scb::ObjectTracker::clear()
+{
+ Scb::Base *const * elements = mBuffered.getEntries();
+ for(PxU32 i=0;i<mBuffered.size();i++)
+ {
+ ControlState::Enum state = elements[i]->getControlState();
+ PxU32 flags = elements[i]->getControlFlags();
+
+ if(state == ControlState::eIN_SCENE || state == ControlState::eINSERT_PENDING)
+ elements[i]->resetControl(ControlState::eIN_SCENE);
+ else
+ {
+ elements[i]->resetControl(ControlState::eNOT_IN_SCENE);
+ elements[i]->resetScbScene();
+ }
+
+ if(flags & ControlFlag::eIS_RELEASED)
+ NpDestroy(*elements[i]);
+ }
+ mBuffered.clear();
+}
+
+void Scb::ObjectTracker::insert(Scb::Base& element)
+{
+ PX_ASSERT(!mBuffered.contains(&element));
+ mBuffered.insert(&element);
+}
+
+void Scb::ObjectTracker::remove(Scb::Base& element)
+{
+ mBuffered.erase(&element);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+template <bool TSimRunning, bool TAdd, bool TIsDynamic, bool TIsNonSimObject, class T>
+PX_FORCE_INLINE static void addOrRemoveRigidObject(Sc::Scene& s, T& rigidObject, bool wakeOnLostTouch, PxBounds3* uninflatedBounds);
+
+template <typename T>struct ScSceneFns {};
+
+template<> struct ScSceneFns<Scb::Articulation>
+{
+ static PX_FORCE_INLINE void insert(Sc::Scene& s, Scb::Articulation& v, PxBounds3*)
+ {
+ Scb::Body* b = NpArticulationGetRootFromScb(v);
+ s.addArticulation(v.getScArticulation(), b->getScBody());
+ }
+ static PX_FORCE_INLINE void remove(Sc::Scene& s, Scb::Articulation& v, bool wakeOnLostTouch)
+ {
+ PX_UNUSED(wakeOnLostTouch);
+
+ v.clearBufferedSleepStateChange(); // see comment in remove code of Scb::Body
+
+ s.removeArticulation(v.getScArticulation());
+ }
+};
+
+template<> struct ScSceneFns<Scb::ArticulationJoint>
+{
+ static PX_FORCE_INLINE void insert(Sc::Scene& s, Scb::ArticulationJoint& v, PxBounds3*)
+ {
+ Scb::Body* scb0, * scb1;
+ NpArticulationJointGetBodiesFromScb(v, scb0, scb1);
+ s.addArticulationJoint(v.getScArticulationJoint(), scb0->getScBody(), scb1->getScBody());
+ }
+ static PX_FORCE_INLINE void remove(Sc::Scene& s, Scb::ArticulationJoint& v, bool wakeOnLostTouch) { PX_UNUSED(wakeOnLostTouch); s.removeArticulationJoint(v.getScArticulationJoint()); }
+};
+
+template<> struct ScSceneFns<Scb::Constraint>
+{
+ static PX_FORCE_INLINE void insert(Sc::Scene& s, Scb::Constraint& v, PxBounds3*)
+ {
+ Scb::RigidObject* scb0, * scb1;
+ NpConstraintGetRigidObjectsFromScb(v, scb0, scb1);
+
+ PX_ASSERT((!scb0) || (!(scb0->getActorFlags() & PxActorFlag::eDISABLE_SIMULATION)));
+ PX_ASSERT((!scb1) || (!(scb1->getActorFlags() & PxActorFlag::eDISABLE_SIMULATION)));
+
+ s.addConstraint(v.getScConstraint(), scb0 ? &scb0->getScRigidCore() : NULL, scb1 ? &scb1->getScRigidCore() : NULL);
+ }
+ static PX_FORCE_INLINE void remove(Sc::Scene& s, Scb::Constraint& v, bool wakeOnLostTouch)
+ {
+ PX_UNUSED(wakeOnLostTouch);
+ s.removeConstraint(v.getScConstraint());
+ }
+};
+
+template<> struct ScSceneFns<Scb::RigidStatic>
+{
+ static PX_FORCE_INLINE void insert(Sc::Scene& s, Scb::RigidStatic& v, PxBounds3* uninflatedBounds)
+ {
+ // important to use the buffered flags because for a pending insert those describe the end state the
+ // user expects.
+
+ if (!(v.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION))
+ addOrRemoveRigidObject<!tSimRunning, tAdd, !tDynamic, !tNonSimObject>(s, v, false, uninflatedBounds);
+ else
+ addOrRemoveRigidObject<!tSimRunning, tAdd, !tDynamic, tNonSimObject>(s, v, false, uninflatedBounds);
+ }
+ static PX_FORCE_INLINE void remove(Sc::Scene& s, Scb::RigidStatic& v, bool wakeOnLostTouch)
+ {
+ // important to use the original flags because for a pending removal those describe the original state that needs
+ // to get cleaned up.
+
+ if (!v.isSimDisabledInternally())
+ addOrRemoveRigidObject<!tSimRunning, !tAdd, !tDynamic, !tNonSimObject>(s, v, wakeOnLostTouch, NULL);
+ else
+ addOrRemoveRigidObject<!tSimRunning, !tAdd, !tDynamic, tNonSimObject>(s, v, false, NULL);
+ }
+};
+
+template<> struct ScSceneFns<Scb::Body>
+{
+ static PX_FORCE_INLINE void insert(Sc::Scene& s, Scb::Body& v, PxBounds3* uninflatedBounds)
+ {
+ // see comments in rigid static case
+ if (!(v.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION))
+ addOrRemoveRigidObject<!tSimRunning, tAdd, tDynamic, !tNonSimObject>(s, v, false, uninflatedBounds);
+ else
+ addOrRemoveRigidObject<!tSimRunning, tAdd, tDynamic, tNonSimObject>(s, v, false, uninflatedBounds);
+ }
+ static PX_FORCE_INLINE void remove(Sc::Scene& s, Scb::Body& v, bool wakeOnLostTouch)
+ {
+ // strictly speaking, the following is only necessary for pending removes but it does not have a
+ // functional side effect if applied all the time.
+ // When an object gets removed from the scene, pending wakeUp/putToSleep events should be ignored because
+ // the internal sleep state for a free standing object is specified as sleeping. All the other parameter changes
+ // that go along with a sleep state change should still get processed though (zero vel, zero wake counter on
+ // putToSleep for example). Those are not affected because they are tracked through buffered updates
+ // of the velocity and wake counter.
+ // The clearing happens here because only here we are sure that the object does get removed for real. At earlier
+ // stages someone might remove and then re-insert and object and for such cases it is important to keep the
+ // sleep state change buffered.
+ v.clearBufferedSleepStateChange();
+
+ // see comments in rigid static case
+ if (!v.isSimDisabledInternally())
+ addOrRemoveRigidObject<!tSimRunning, !tAdd, tDynamic, !tNonSimObject>(s, v, wakeOnLostTouch, NULL);
+ else
+ addOrRemoveRigidObject<!tSimRunning, !tAdd, tDynamic, tNonSimObject>(s, v, false, NULL);
+ }
+};
+
+#if PX_USE_PARTICLE_SYSTEM_API
+template<> struct ScSceneFns<Scb::ParticleSystem>
+{
+ static PX_FORCE_INLINE void insert(Sc::Scene& s, Scb::ParticleSystem& v, PxBounds3*) { s.addParticleSystem(v.getScParticleSystem()); }
+ static PX_FORCE_INLINE void remove(Sc::Scene& s, Scb::ParticleSystem& v, bool wakeOnLostTouch) { PX_UNUSED(wakeOnLostTouch); s.removeParticleSystem(v.getScParticleSystem(), (v.getControlFlags() & Scb::ControlFlag::eIS_RELEASED) != 0); }
+};
+#endif
+
+#if PX_USE_CLOTH_API
+template<> struct ScSceneFns<Scb::Cloth>
+{
+// static PX_FORCE_INLINE void insert(Sc::Scene& s, Scb::Cloth& v) { s.addRigidObject(v.getScCloth()); }
+ static PX_FORCE_INLINE void remove(Sc::Scene& s, Scb::Cloth& v, bool wakeOnLostTouch) { PX_UNUSED(wakeOnLostTouch); s.removeCloth(v.getScCloth()); }
+};
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+#if PX_SUPPORT_PVD
+template<typename T> struct PvdFns
+{
+ // PT: in the following functions, checkPvdDebugFlag() is done by the callers to save time when functions are called from a loop.
+
+ static void createInstance(Scb::Scene& scene, Vd::ScbScenePvdClient& d, T* v)
+ {
+ PX_PROFILE_ZONE("PVD.createPVDInstance", scene.getContextId());
+ PX_UNUSED(scene);
+ d.createPvdInstance(v);
+ }
+
+ static void updateInstance(Scb::Scene& scene, Vd::ScbScenePvdClient& d, T* v)
+ {
+ PX_UNUSED(scene);
+ if(((v->getControlFlags() & Scb::ControlFlag::eIS_RELEASED) == 0) && (v->getControlState() != Scb::ControlState::eREMOVE_PENDING))
+ {
+ PX_PROFILE_ZONE("PVD.updatePVDProperties", scene.getContextId());
+ d.updatePvdProperties(v);
+ }
+ }
+
+ static void releaseInstance(Scb::Scene& scene, Vd::ScbScenePvdClient& d, T* v)
+ {
+ PX_UNUSED(scene);
+ PX_PROFILE_ZONE("PVD.releasePVDInstance", scene.getContextId());
+ d.releasePvdInstance(v);
+ }
+};
+
+ #define CREATE_PVD_INSTANCE(obj) \
+ { \
+ if(mScenePvdClient.checkPvdDebugFlag()) \
+ { \
+ PX_PROFILE_ZONE("PVD.createPVDInstance", getContextId());\
+ mScenePvdClient.createPvdInstance(obj); \
+ } \
+ }
+ #define RELEASE_PVD_INSTANCE(obj) \
+ { \
+ if(mScenePvdClient.checkPvdDebugFlag()) \
+ { \
+ PX_PROFILE_ZONE("PVD.releasePVDInstance", getContextId());\
+ mScenePvdClient.releasePvdInstance(obj); \
+ } \
+ }
+ #define UPDATE_PVD_PROPERTIES(obj) \
+ { \
+ if(mScenePvdClient.checkPvdDebugFlag()) \
+ { \
+ PX_PROFILE_ZONE("PVD.updatePVDProperties", getContextId());\
+ mScenePvdClient.updatePvdProperties(obj); \
+ } \
+ }
+ #define PVD_ORIGIN_SHIFT(shift) \
+ { \
+ if(mScenePvdClient.checkPvdDebugFlag()) \
+ { \
+ PX_PROFILE_ZONE("PVD.originShift", getContextId());\
+ mScenePvdClient.originShift(shift); \
+ } \
+ }
+#else
+ #define CREATE_PVD_INSTANCE(obj) {}
+ #define RELEASE_PVD_INSTANCE(obj) {}
+ #define UPDATE_PVD_PROPERTIES(obj) {}
+ #define PVD_ORIGIN_SHIFT(shift){}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+Scb::Scene::Scene(const PxSceneDesc& desc, PxU64 contextID) :
+ mScene (desc, contextID),
+ mSimulationRunning (false),
+ mIsBuffering (false),
+ mStream (16384),
+ mShapeMaterialBuffer (PX_DEBUG_EXP("shapeMaterialBuffer")),
+ mShapePtrBuffer (PX_DEBUG_EXP("shapePtrBuffer")),
+ mActorPtrBuffer (PX_DEBUG_EXP("actorPtrBuffer")),
+#if PX_SUPPORT_PVD
+ mScenePvdClient (*this),
+#endif
+ mWakeCounterResetValue (desc.wakeCounterResetValue),
+ mBufferFlags (0)
+{
+}
+
+void Scb::Scene::release()
+{
+#if PX_SUPPORT_PVD
+ mScenePvdClient.releasePvdInstance();
+#endif
+ mScene.release();
+ mShapeMaterialBuffer.clear();
+ mShapePtrBuffer.clear();
+ mActorPtrBuffer.clear();
+ mStream.clear();
+}
+
+// PT: TODO: inline this
+PxScene* Scb::Scene::getPxScene()
+{
+ return const_cast<NpScene*>(getNpScene(this));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+template<typename T>
+void Scb::Scene::add(T& v, ObjectTracker &tracker, PxBounds3* uninflatedBounds)
+{
+ v.setScbScene(this);
+
+ if (!mIsBuffering)
+ {
+ v.resetControl(ControlState::eIN_SCENE);
+ ScSceneFns<T>::insert(mScene, v, uninflatedBounds);
+#if PX_SUPPORT_PVD
+ if(mScenePvdClient.checkPvdDebugFlag())
+ PvdFns<T>::createInstance(*this, mScenePvdClient, &v);
+#endif
+ }
+ else
+ tracker.scheduleForInsert(v);
+}
+
+template<typename T>
+void Scb::Scene::remove(T& v, ObjectTracker &tracker, bool wakeOnLostTouch)
+{
+ if (!mIsBuffering)
+ {
+ ScSceneFns<T>::remove(mScene, v, wakeOnLostTouch);
+#if PX_SUPPORT_PVD
+ if(mScenePvdClient.checkPvdDebugFlag())
+ PvdFns<T>::releaseInstance(*this, mScenePvdClient, &v);
+#endif
+ v.resetControl(ControlState::eNOT_IN_SCENE);
+ v.setScbScene(NULL);
+ }
+ else
+ {
+ tracker.scheduleForRemove(v);
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+template<bool TIsDynamic, class T>
+void Scb::Scene::addRigidNoSim(T& v, ObjectTracker &tracker)
+{
+ PX_ASSERT(v.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION);
+ v.setScbScene(this);
+
+ if (!mIsBuffering)
+ {
+ v.resetControl(ControlState::eIN_SCENE);
+#if PX_SUPPORT_PVD
+ if(mScenePvdClient.checkPvdDebugFlag())
+ PvdFns<T>::createInstance(*this, mScenePvdClient, &v);
+#endif
+ addOrRemoveRigidObject<!tSimRunning, tAdd, TIsDynamic, tNonSimObject>(mScene, v, false, NULL);
+ }
+ else
+ {
+ tracker.scheduleForInsert(v);
+ addOrRemoveRigidObject<tSimRunning, tAdd, TIsDynamic, tNonSimObject>(mScene, v, false, NULL);
+ }
+}
+
+
+template<bool TIsDynamic, class T>
+void Scb::Scene::removeRigidNoSim(T& v, ObjectTracker &tracker)
+{
+ PX_ASSERT(v.isSimDisabledInternally());
+
+ if (!mIsBuffering)
+ {
+ addOrRemoveRigidObject<!tSimRunning, !tAdd, TIsDynamic, tNonSimObject>(mScene, v, false, NULL);
+#if PX_SUPPORT_PVD
+ if(mScenePvdClient.checkPvdDebugFlag())
+ PvdFns<T>::releaseInstance(*this, mScenePvdClient, &v);
+#endif
+ v.resetControl(ControlState::eNOT_IN_SCENE);
+ v.setScbScene(NULL);
+ }
+ else
+ {
+ tracker.scheduleForRemove(v);
+ addOrRemoveRigidObject<tSimRunning, !tAdd, TIsDynamic, tNonSimObject>(mScene, v, false, NULL);
+ }
+}
+
+
+void Scb::Scene::switchRigidToNoSim(Scb::RigidObject& r, bool isDynamic)
+{
+ PX_ASSERT(!mIsBuffering);
+
+ // when a simulation objects has a pending remove and then gets switched to a non-simulation object,
+ // we must not process the code below. On sync the object will get removed before this call.
+ if (r.getControlState() == ControlState::eIN_SCENE)
+ {
+ size_t ptrOffset = -Scb::Shape::getScOffset();
+ Ps::InlineArray<const Sc::ShapeCore*, 64> scShapes;
+
+ if (isDynamic)
+ mScene.removeBody(static_cast<Sc::BodyCore&>(r.getScRigidCore()), scShapes, true);
+ else
+ mScene.removeStatic(static_cast<Sc::StaticCore&>(r.getScRigidCore()), scShapes, true);
+
+ // not in simulation anymore -> decrement shape ref-counts
+ void* const* shapes = reinterpret_cast<void*const*>(const_cast<Sc::ShapeCore*const*>(scShapes.begin()));
+ for(PxU32 i=0; i < scShapes.size(); i++)
+ {
+ Scb::Shape& scbShape = *Ps::pointerOffset<Scb::Shape*>(shapes[i], ptrdiff_t(ptrOffset));
+ NpShapeDecRefCount(scbShape);
+ }
+ }
+}
+
+
+void Scb::Scene::switchRigidFromNoSim(Scb::RigidObject& r, bool isDynamic)
+{
+ PX_ASSERT(!mIsBuffering);
+
+ // when a non-simulation objects has a pending remove and then gets switched to a simulation object,
+ // we must not process the code below. On sync the object will get removed before this call.
+ if (r.getControlState() == ControlState::eIN_SCENE)
+ {
+ void* const* shapes;
+ size_t shapePtrOffset = NpShapeGetScPtrOffset();
+ size_t ptrOffset = shapePtrOffset - Scb::Shape::getScOffset();
+
+ PxU32 nbShapes;
+ if (isDynamic)
+ {
+ nbShapes = NpRigidDynamicGetShapes(static_cast<Scb::Body&>(r), shapes);
+ mScene.addBody(static_cast<Sc::BodyCore&>(r.getScRigidCore()), shapes, nbShapes, shapePtrOffset, NULL);
+ }
+ else
+ {
+ nbShapes = NpRigidStaticGetShapes(static_cast<Scb::RigidStatic&>(r), shapes);
+ mScene.addStatic(static_cast<Sc::StaticCore&>(r.getScRigidCore()), shapes, nbShapes, shapePtrOffset, NULL);
+ }
+
+ // add to simulation -> increment shape ref-counts
+ for(PxU32 i=0; i < nbShapes; i++)
+ {
+ Scb::Shape& scbShape = *Ps::pointerOffset<Scb::Shape*>(shapes[i], ptrdiff_t(ptrOffset));
+ NpShapeIncRefCount(scbShape);
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PT: TODO:
+// - consider making these templates not scene member functions
+
+template<bool TIsDynamic, class T>
+PX_FORCE_INLINE void Scb::Scene::addActorT(T& actor, Scb::ObjectTracker& tracker, bool noSim, PxBounds3* uninflatedBounds)
+{
+ PX_PROFILE_ZONE("API.addActorToSim", getContextId());
+ if(!noSim)
+ {
+ add<T>(actor, tracker, uninflatedBounds);
+ actor.initBufferedState();
+
+ // copy buffer control state from rigid object to shapes and set scene
+ if(mIsBuffering)
+ addOrRemoveRigidObject<tSimRunning, tAdd, TIsDynamic, !tNonSimObject>(mScene, actor, false, NULL);
+ }
+ else
+ {
+ addRigidNoSim<TIsDynamic>(actor, tracker);
+ actor.initBufferedState();
+ }
+}
+
+void Scb::Scene::addActor(Scb::RigidStatic& rigidStatic, bool noSim, PxBounds3* uninflatedBounds)
+{
+ addActorT<false>(rigidStatic, mRigidStaticManager, noSim, uninflatedBounds);
+}
+
+void Scb::Scene::addActor(Scb::Body& body, bool noSim, PxBounds3* uninflatedBounds)
+{
+ addActorT<true>(body, mBodyManager, noSim, uninflatedBounds);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Scene::removeActor(Scb::RigidStatic& rigidStatic, bool wakeOnLostTouch, bool noSim)
+{
+ PX_PROFILE_ZONE("API.removeActorFromSim", getContextId());
+ if (!noSim)
+ {
+ remove<Scb::RigidStatic>(rigidStatic, mRigidStaticManager, wakeOnLostTouch);
+
+ // copy buffer control state from rigid object to shapes and set scene
+ if (mIsBuffering)
+ {
+ if (wakeOnLostTouch)
+ rigidStatic.scheduleForWakeTouching();
+ addOrRemoveRigidObject<tSimRunning, !tAdd, !tDynamic, !tNonSimObject>(mScene, rigidStatic, wakeOnLostTouch, NULL);
+ }
+ }
+ else
+ {
+ removeRigidNoSim<!tDynamic>(rigidStatic, mRigidStaticManager);
+ }
+
+ rigidStatic.clearBufferedState();
+}
+
+void Scb::Scene::removeActor(Scb::Body& body, bool wakeOnLostTouch, bool noSim)
+{
+ PX_PROFILE_ZONE("API.removeActorFromSim", getContextId());
+ if (!noSim)
+ {
+ body.clearSimStateDataForPendingInsert();
+
+ remove<Scb::Body>(body, mBodyManager, wakeOnLostTouch);
+ body.clearBufferedState();
+
+ // copy buffer control state from rigid object to shapes and set scene
+ if (mIsBuffering)
+ {
+ if (wakeOnLostTouch)
+ body.scheduleForWakeTouching();
+ addOrRemoveRigidObject<tSimRunning, !tAdd, tDynamic, !tNonSimObject>(mScene, body, wakeOnLostTouch, NULL);
+ }
+ }
+ else
+ {
+ removeRigidNoSim<tDynamic>(body, mBodyManager);
+
+ // note: "noSim" refers to the internal state here. The following asserts only apply if the bufferd state has not switched to "sim".
+ PX_ASSERT(!(body.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION) || body.isSleeping());
+ PX_ASSERT(!(body.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION) || !body.isBuffered(BodyBuffer::BF_KinematicTarget | BodyBuffer::BF_Acceleration | BodyBuffer::BF_DeltaVelocity));
+ // What about velocity, wakeCounter, ...?
+ // Those are not allowed on a no-sim object, however, they might still be necessary due to complex buffering scenarios:
+ // Imagine the following operation flow (all buffered):
+ // - dynamic sim object awake with velocities
+ // - switch to no-sim -> needs to clear velocities, wake counter, put to sleep, ...
+ // - switch back to sim -> the velocities, wake counter, ... still need to get cleared and it needs to be asleep (that would be the non-buffered behavior of the operations)
+
+ body.clearBufferedState(); // this also covers the buffered case where a noSim object gets switched to a sim object, followed by a wakeUp() call and then a remove.
+ // If we checked whether the buffered object is still a noSim object then only body.RigidObject::clearBufferedState() would be necessary.
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Scene::addConstraint(Scb::Constraint& constraint)
+{
+ add<Scb::Constraint>(constraint, mConstraintManager, NULL);
+}
+
+void Scb::Scene::removeConstraint(Scb::Constraint& constraint)
+{
+ if (!mIsBuffering)
+ {
+ mScene.removeConstraint(constraint.getScConstraint());
+
+ // Release pvd constraint immediately since delayed removal with already released ext::joints does not work, can't call callback.
+ if(constraint.getControlState() != ControlState::eINSERT_PENDING)
+ RELEASE_PVD_INSTANCE(&constraint)
+
+ constraint.resetControl(ControlState::eNOT_IN_SCENE);
+ constraint.setScbScene(NULL);
+ }
+ else
+ {
+ mConstraintManager.scheduleForRemove(constraint);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Scene::addArticulation(Scb::Articulation& articulation)
+{
+ add<Scb::Articulation>(articulation, mArticulationManager, NULL);
+ articulation.initBufferedState();
+}
+
+void Scb::Scene::removeArticulation(Scb::Articulation& articulation)
+{
+ remove<Scb::Articulation>(articulation, mArticulationManager);
+ articulation.clearBufferedState();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Scene::addArticulationJoint(Scb::ArticulationJoint& joint)
+{
+ add<Scb::ArticulationJoint>(joint, mArticulationJointManager, NULL);
+}
+
+void Scb::Scene::removeArticulationJoint(Scb::ArticulationJoint& joint)
+{
+ remove<Scb::ArticulationJoint>(joint, mArticulationJointManager);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Scene::addAggregate(Scb::Aggregate& agg)
+{
+ agg.setScbScene(this);
+
+ if (!mIsBuffering)
+ {
+ PxU32 aggregateID = mScene.createAggregate(agg.mPxAggregate, agg.getSelfCollide());
+ agg.setAggregateID(aggregateID);
+ agg.resetControl(ControlState::eIN_SCENE);
+#if PX_SUPPORT_PVD
+ //Sending pvd events after all aggregates's actors are inserted into scene
+ mScenePvdClient.createPvdInstance(&agg);
+#endif
+ }
+ else
+ mAggregateManager.scheduleForInsert(agg);
+}
+
+
+void Scb::Scene::removeAggregate(Scb::Aggregate& agg)
+{
+ if (!mIsBuffering)
+ {
+ mScene.deleteAggregate(agg.getAggregateID());
+ agg.resetControl(ControlState::eNOT_IN_SCENE);
+ agg.setScbScene(NULL);
+#if PX_SUPPORT_PVD
+ mScenePvdClient.releasePvdInstance(&agg);
+#endif
+ }
+ else
+ {
+ mAggregateManager.scheduleForRemove(agg);
+ }
+}
+
+
+void Scb::Scene::addMaterial(const Sc::MaterialCore& material)
+{
+ Ps::Mutex::ScopedLock lock(mSceneMaterialBufferLock);
+
+ mSceneMaterialBuffer.pushBack(MaterialEvent(material.getMaterialIndex(), MATERIAL_ADD));
+
+ CREATE_PVD_INSTANCE(&material)
+}
+
+void Scb::Scene::updateMaterial(const Sc::MaterialCore& material)
+{
+ Ps::Mutex::ScopedLock lock(mSceneMaterialBufferLock);
+
+ mSceneMaterialBuffer.pushBack(MaterialEvent(material.getMaterialIndex(), MATERIAL_UPDATE));
+
+ UPDATE_PVD_PROPERTIES(&material)
+}
+
+void Scb::Scene::removeMaterial(const Sc::MaterialCore& material)
+{
+ if(material.getMaterialIndex() == MATERIAL_INVALID_HANDLE)
+ return;
+
+ Ps::Mutex::ScopedLock lock(mSceneMaterialBufferLock);
+
+ mSceneMaterialBuffer.pushBack(MaterialEvent(material.getMaterialIndex(), MATERIAL_REMOVE));
+
+ RELEASE_PVD_INSTANCE(&material);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_USE_PARTICLE_SYSTEM_API
+void Scb::Scene::addParticleSystem(Scb::ParticleSystem& ps)
+{
+ add<Scb::ParticleSystem>(ps, mParticleSystemManager, NULL);
+}
+
+void Scb::Scene::removeParticleSystem(Scb::ParticleSystem& ps, bool isRelease)
+{
+ if (!mIsBuffering)
+ {
+ RELEASE_PVD_INSTANCE(&ps)
+ ps.removeFromScene();
+ mScene.removeParticleSystem(ps.getScParticleSystem(), isRelease);
+ ps.resetControl(ControlState::eNOT_IN_SCENE);
+ ps.setScbScene(NULL);
+ }
+ else
+ {
+ mParticleSystemManager.scheduleForRemove(ps);
+ }
+}
+#endif
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_USE_CLOTH_API
+void Scb::Scene::addCloth(Scb::Cloth& cl)
+{
+ cl.setScbScene(this);
+
+ if (!mIsBuffering)
+ {
+ if (mScene.addCloth(cl.getScCloth()))
+ {
+ cl.resetControl(ControlState::eIN_SCENE);
+ CREATE_PVD_INSTANCE(&cl)
+ }
+ else
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Adding cloth to the scene failed!");
+ }
+ else
+ mClothManager.scheduleForInsert(cl);
+}
+
+void Scb::Scene::removeCloth(Scb::Cloth& cl)
+{
+ if (!mIsBuffering)
+ {
+ RELEASE_PVD_INSTANCE(&cl)
+ mScene.removeCloth(cl.getScCloth());
+ cl.resetControl(ControlState::eNOT_IN_SCENE);
+ cl.setScbScene(NULL);
+ }
+ else
+ {
+ mClothManager.scheduleForRemove(cl);
+ }
+}
+#endif // PX_USE_CLOTH_API
+
+///////////////////////////////////////////////////////////////////////////////
+
+void Scb::Scene::updateLowLevelMaterial(NpMaterial** masterMaterial)
+{
+ Ps::Mutex::ScopedLock lock(mSceneMaterialBufferLock);
+
+ //sync all the material events
+ PxsMaterialManager& manager = mScene.getMaterialManager();
+ for(PxU32 i=0; i< mSceneMaterialBuffer.size(); ++i)
+ {
+ const MaterialEvent& event = mSceneMaterialBuffer[i];
+ const NpMaterial* masMat = masterMaterial[event.mHandle];
+ switch(event.mType)
+ {
+ case MATERIAL_ADD:
+ if(masMat)
+ {
+ Sc::MaterialCore* materialCore = &masterMaterial[event.mHandle]->getScMaterial();
+ manager.setMaterial(materialCore);
+ mScene.registerMaterialInNP(*materialCore);
+ }
+ break;
+ case MATERIAL_UPDATE:
+ if(masMat)
+ {
+ Sc::MaterialCore* materialCore = &masterMaterial[event.mHandle]->getScMaterial();
+ manager.updateMaterial(materialCore);
+ mScene.updateMaterialInNP(*materialCore);
+ }
+ break;
+ case MATERIAL_REMOVE:
+ if (event.mHandle < manager.getMaxSize()) // materials might get added and then removed again immediately. However, the add does not get processed (see case MATERIAL_ADD above),
+ { // so the remove might end up reading out of bounds memory unless checked.
+ PxsMaterialCore* materialCore = manager.getMaterial(event.mHandle);
+ mScene.unregisterMaterialInNP(*materialCore);
+ manager.removeMaterial(materialCore);
+ }
+ break;
+ };
+ }
+
+ mSceneMaterialBuffer.resize(0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+#if PX_USE_PARTICLE_SYSTEM_API
+void Scb::Scene::preSimulateUpdateAppThread(PxReal timeStep)
+{
+ // Submit applied forces to particle systems
+ PxU32 nbParticleSystems = mScene.getNbParticleSystems();
+ Sc::ParticleSystemCore* const* particleSystems = mScene.getParticleSystems();
+ for(PxU32 i=0; i < nbParticleSystems; i++)
+ Scb::ParticleSystem::fromSc(*particleSystems[i]).submitForceUpdates(timeStep);
+}
+#endif
+
+//--------------------------------------------------------------
+//
+// Data synchronization
+//
+//--------------------------------------------------------------
+void Scb::Scene::syncState()
+{
+ //process client creation -- must be done before BF_CLIENT_BEHAVIOR_FLAGS processing in the below block:
+ while (mBufferedData.numClientsCreated)
+ {
+ mScene.createClient();
+ mBufferedData.numClientsCreated--;
+ }
+
+ if (mBufferFlags)
+ {
+ if (isBuffered(BF_GRAVITY))
+ mScene.setGravity(mBufferedData.gravity);
+
+ if(isBuffered(BF_BOUNCETHRESHOLDVELOCITY))
+ mScene.setBounceThresholdVelocity(mBufferedData.bounceThresholdVelocity);
+
+ if (isBuffered(BF_FLAGS))
+ mScene.setPublicFlags(mBufferedData.flags);
+
+ if (isBuffered(BF_DOMINANCE_PAIRS))
+ mBufferedData.syncDominancePairs(mScene);
+
+ if (isBuffered(BF_SOLVER_BATCH_SIZE))
+ mScene.setSolverBatchSize(mBufferedData.solverBatchSize);
+
+ if (isBuffered(BF_CLIENT_BEHAVIOR_FLAGS))
+ {
+ for (PxU32 i = 0; i < mBufferedData.clientBehaviorFlags.size(); i++)
+ {
+ if (mBufferedData.clientBehaviorFlags[i] != PxClientBehaviorFlag_eNOT_BUFFERED) //not PxClientBehaviorFlag_eNOT_BUFFERED means it was written.
+ {
+ mScene.setClientBehaviorFlags(PxClientID(i), mBufferedData.clientBehaviorFlags[i]);
+ mBufferedData.clientBehaviorFlags[i] = PxClientBehaviorFlag_eNOT_BUFFERED;
+ }
+
+ }
+ }
+
+ if (isBuffered(BF_VISUALIZATION))
+ {
+ for(PxU32 i=0; i < PxVisualizationParameter::eNUM_VALUES; i++)
+ {
+ if (mBufferedData.visualizationParamChanged[i])
+ {
+ mScene.setVisualizationParameter(static_cast<PxVisualizationParameter::Enum>(i), mBufferedData.visualizationParam[i]);
+ }
+ }
+ }
+
+#if PX_SUPPORT_PVD
+ if(mScenePvdClient.checkPvdDebugFlag())
+ mScenePvdClient.updatePvdProperties();
+#endif
+ }
+
+
+ mBufferFlags = 0;
+ mBufferedData.clearDominanceBuffer();
+ mBufferedData.clearVisualizationParams();
+}
+
+template<typename T>
+void Scb::Scene::processUserUpdates(ObjectTracker &tracker)
+{
+#if PX_SUPPORT_PVD
+ bool isPvdValid = mScenePvdClient.checkPvdDebugFlag();
+#endif
+ Base*const * buffered = tracker.getBuffered();
+ for(PxU32 i=0; i < tracker.getBufferedCount(); i++)
+ {
+ T& v = *static_cast<T*>(buffered[i]);
+ if (v.getControlState() == ControlState::eINSERT_PENDING)
+ {
+ ScSceneFns<T>::insert(mScene, v, NULL);
+#if PX_SUPPORT_PVD
+ if(isPvdValid)
+ PvdFns<T>::createInstance(*this, mScenePvdClient, &v);
+#endif
+ }
+ else if(v.getControlFlags() & ControlFlag::eIS_UPDATED)
+ {
+ v.syncState();
+#if PX_SUPPORT_PVD
+ if(isPvdValid)
+ PvdFns<T>::updateInstance(*this, mScenePvdClient, &v);
+#endif
+ }
+ }
+}
+
+template<typename T, typename S>
+void Scb::Scene::processSimUpdates(S*const * scObjects, PxU32 nbObjects)
+{
+#if PX_SUPPORT_PVD
+ bool isPvdValid = mScenePvdClient.checkPvdDebugFlag();
+#endif
+ for(PxU32 i=0;i<nbObjects;i++)
+ {
+ T& v = T::fromSc(*scObjects[i]);
+
+ if(!(v.getControlFlags() & ControlFlag::eIS_UPDATED)) // else the data will be synced further below
+ {
+ v.syncState();
+#if PX_SUPPORT_PVD
+ if(isPvdValid)
+ PvdFns<T>::updateInstance(*this, mScenePvdClient, &v);
+#endif
+ }
+ }
+}
+
+#define ENABLE_PVD_ORIGINSHIFT_EVENT
+void Scb::Scene::shiftOrigin(const PxVec3& shift)
+{
+ PX_ASSERT(!isPhysicsBuffering());
+ mScene.shiftOrigin(shift);
+
+#ifdef ENABLE_PVD_ORIGINSHIFT_EVENT
+ PVD_ORIGIN_SHIFT(shift);
+#endif
+}
+
+void Scb::Scene::syncWriteThroughProperties()
+{
+ mStream.lock();
+
+ Base*const * buffered = mBodyManager.getBuffered();
+ PxU32 count = mBodyManager.getBufferedCount();
+ for(PxU32 i=0; i < count; i++)
+ {
+ Scb::Body& bufferedBody = *static_cast<Scb::Body*>(buffered[i]);
+ bufferedBody.syncCollisionWriteThroughState();
+ }
+
+ mStream.unlock();
+}
+
+void Scb::Scene::syncEntireScene(PxU32* error)
+{
+ PX_PROFILE_ZONE("Sim.syncState", getContextId());
+ if (error)
+ *error = mScene.getErrorState();
+
+ mStream.lock();
+ syncState();
+ //
+ // Process aggregates (needs to be done before adding actors because the actor's aggregateID needs to get set)
+ //
+
+ for(PxU32 i=0; i < mAggregateManager.getBufferedCount(); i++)
+ {
+ Aggregate* a = static_cast<Aggregate*>(mAggregateManager.getBuffered()[i]);
+ if (a->getControlState() == ControlState::eINSERT_PENDING)
+ {
+ PxU32 aggregateID = mScene.createAggregate(a->mPxAggregate, a->getSelfCollide());
+ a->setAggregateID(aggregateID);
+#if PX_SUPPORT_PVD
+ mScenePvdClient.createPvdInstance(a);
+#endif
+ a->syncState(*this); // Necessary to set the aggregate ID for all actors of the aggregate
+ }
+ else if(a->getControlFlags() & ControlFlag::eIS_UPDATED)
+ {
+ a->syncState(*this);
+ }
+ }
+ mAggregateManager.clear();
+ mActorPtrBuffer.clear();
+
+
+ // rigid statics
+ processUserUpdates<Scb::RigidStatic>(mRigidStaticManager);
+ mRigidStaticManager.clear();
+
+
+ // rigid dynamics and articulation links
+ //
+ // 1) Sync simulation changed data
+ {
+ Sc::BodyCore*const* activeBodies = mScene.getActiveBodiesArray();
+ PxU32 nbActiveBodies = mScene.getNumActiveBodies();
+ while(nbActiveBodies--)
+ {
+ Sc::BodyCore* bodyCore = *activeBodies++;
+ Scb::Body& bufferedBody = Scb::Body::fromSc(*bodyCore);
+ if (!(bufferedBody.getControlFlags() & ControlFlag::eIS_UPDATED)) // Else the data will be synced further below
+ bufferedBody.syncState();
+ }
+ }
+
+ // 2) Sync data of rigid dynamics which were put to sleep by the simulation
+
+ PxU32 nbSleepingBodies;
+ Sc::BodyCore* const* sleepingBodies = mScene.getSleepBodiesArray(nbSleepingBodies);
+ processSimUpdates<Scb::Body, Sc::BodyCore>(sleepingBodies, nbSleepingBodies);
+
+ // user updates
+ processUserUpdates<Scb::Body>(mBodyManager);
+ mBodyManager.clear();
+ mShapePtrBuffer.clear();
+
+
+ // rigid body shapes
+ //
+ // IMPORTANT: This has to run after the material update
+ //
+ // Sync user changed data. Inserts and removes are handled in actor sync
+ for(PxU32 i=0; i < mShapeManager.getBufferedCount(); i++)
+ {
+ Scb::Shape* s = static_cast<Scb::Shape*>(mShapeManager.getBuffered()[i]);
+
+ if(s->getControlFlags() & ControlFlag::eIS_UPDATED)
+ {
+ s->syncState();
+ UPDATE_PVD_PROPERTIES(s)
+ }
+ }
+
+ mShapeManager.clear();
+ mShapeMaterialBuffer.clear();
+
+ // constraints (get break force and broken status from sim)
+
+ processSimUpdates<Scb::Constraint, Sc::ConstraintCore>(mScene.getConstraints(), mScene.getNbConstraints());
+ processUserUpdates<Scb::Constraint>(mConstraintManager);
+ mConstraintManager.clear();
+
+
+ // articulations (get sleep state from sim)
+
+ processSimUpdates<Scb::Articulation, Sc::ArticulationCore>(mScene.getArticulations(), mScene.getNbArticulations());
+ processUserUpdates<Scb::Articulation>(mArticulationManager);
+ mArticulationManager.clear();
+
+
+ // Process articulation joints
+
+ processUserUpdates<Scb::ArticulationJoint>(mArticulationJointManager);
+ mArticulationJointManager.clear();
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ //
+ // Process particle systems
+ //
+ // 1) Sync simulation changed data
+
+ PxU32 nbParticleSystems = mScene.getNbParticleSystems();
+ Sc::ParticleSystemCore* const* particleSystems = mScene.getParticleSystems();
+ for(PxU32 i=0; i < nbParticleSystems; i++)
+ {
+ Scb::ParticleSystem& scbParticleSystem = Scb::ParticleSystem::fromSc(*particleSystems[i]);
+ scbParticleSystem.syncState();
+ if(scbParticleSystem.hasUpdates())
+ UPDATE_PVD_PROPERTIES(&scbParticleSystem)
+ }
+
+ // 2) Sync user changed data
+ for(PxU32 i=0; i < mParticleSystemManager.getBufferedCount(); i++)
+ {
+ ParticleSystem* p = static_cast<ParticleSystem*>(mParticleSystemManager.getBuffered()[i]);
+
+ //special handling to release bulk buffer data
+ if (p->getControlState() == ControlState::eREMOVE_PENDING)
+ p->removeFromScene();
+
+ else if (p->getControlState() == ControlState::eINSERT_PENDING)
+ {
+ mScene.addParticleSystem(p->getScParticleSystem());
+ CREATE_PVD_INSTANCE(p)
+ }
+ }
+ mParticleSystemManager.clear();
+#endif
+
+#if PX_USE_CLOTH_API
+ //
+ // Process cloth
+ //
+ // Pending insert & sync user changed data
+
+ for(PxU32 i=0; i < mClothManager.getBufferedCount(); i++)
+ {
+ Cloth* cl = static_cast<Cloth*>(mClothManager.getBuffered()[i]);
+ if (cl->getControlState() == ControlState::eINSERT_PENDING)
+ {
+ if (mScene.addCloth(cl->getScCloth()))
+ {
+ CREATE_PVD_INSTANCE(cl)
+ }
+ else
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Adding cloth to the scene failed!");
+ }
+ // no need yet
+ //else if(cl->getControlFlags() & ControlFlag::eIS_UPDATED)
+ //{
+ // cl->syncState();
+ // UPDATE_PVD_PROPERTIES(pvdConnected, cl)
+ //}
+ }
+ mClothManager.clear();
+#endif // PX_USE_CLOTH_API
+
+ mStream.clearNotThreadSafe();
+ mStream.unlock();
+}
+
+
+
+template<typename T, bool syncOnRemove, bool wakeOnLostTouchCheck>
+void Scb::Scene::processRemoves(ObjectTracker& tracker)
+{
+#if PX_SUPPORT_PVD
+ bool isPvdValid = mScenePvdClient.checkPvdDebugFlag();
+#endif
+ typedef ScSceneFns<T> Fns;
+ for(PxU32 i=0; i < tracker.getBufferedCount(); i++)
+ {
+ T* v = static_cast<T*>(tracker.getBuffered()[i]);
+ if(v->getControlState() == ControlState::eREMOVE_PENDING)
+ {
+ bool wakeOnLostTouch = false;
+ if (wakeOnLostTouchCheck)
+ {
+ PX_ASSERT( (v->getScbType() == ScbType::BODY) ||
+ (v->getScbType() == ScbType::BODY_FROM_ARTICULATION_LINK) ||
+ (v->getScbType() == ScbType::RIGID_STATIC) );
+ wakeOnLostTouch = (v->Base::isBuffered(RigidObjectBuffer::BF_WakeTouching) != 0); // important to use Scb::Base::isBuffered() because Scb::Body, for example, has a shadowed implementation of this method
+ }
+
+ Fns::remove(mScene, *v, wakeOnLostTouch);
+
+ // if no object param has been updated, the state sync still needs to be processed to write simulation results
+ // back to the permanently buffered params.
+ if (syncOnRemove && !(v->getControlFlags() & ControlFlag::eIS_UPDATED))
+ v->syncState();
+#if PX_SUPPORT_PVD
+ if(isPvdValid)
+ PvdFns<T>::releaseInstance(*this, mScenePvdClient, v);
+#endif
+ }
+ }
+}
+
+template<typename T>
+void Scb::Scene::processShapeRemoves(ObjectTracker& tracker)
+{
+ for(PxU32 i=0; i < tracker.getBufferedCount(); i++)
+ {
+ T* v = static_cast<T*>(tracker.getBuffered()[i]);
+ v->processShapeRemoves();
+ }
+}
+
+void Scb::Scene::processPendingRemove()
+{
+ processShapeRemoves<Scb::RigidStatic>(mRigidStaticManager);
+ processShapeRemoves<Scb::Body>(mBodyManager);
+
+ processRemoves<Scb::Constraint, tSyncOnRemove, !tWakeOnLostTouchCheck>(mConstraintManager);
+
+ Scb::Base *const * buffered = mConstraintManager.getBuffered();
+ for(PxU32 i=0; i < mConstraintManager.getBufferedCount(); i++)
+ {
+ Scb::Constraint* constraint = static_cast<Scb::Constraint*>(buffered[i]);
+
+ if(constraint->getControlFlags() & ControlFlag::eIS_UPDATED)
+ constraint->prepareForActorRemoval(); // see comments in Scb::Constraint
+ }
+
+ processRemoves<Scb::ArticulationJoint, !tSyncOnRemove, !tWakeOnLostTouchCheck> (mArticulationJointManager);
+ processRemoves<Scb::RigidStatic, !tSyncOnRemove, tWakeOnLostTouchCheck> (mRigidStaticManager);
+ processRemoves<Scb::Body, tSyncOnRemove, tWakeOnLostTouchCheck> (mBodyManager);
+ processRemoves<Scb::Articulation, tSyncOnRemove, !tWakeOnLostTouchCheck> (mArticulationManager);
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ processRemoves<Scb::ParticleSystem, !tSyncOnRemove, !tWakeOnLostTouchCheck> (mParticleSystemManager);
+#endif
+
+#if PX_USE_CLOTH_API
+ processRemoves<Scb::Cloth, !tSyncOnRemove, !tWakeOnLostTouchCheck> (mClothManager);
+#endif
+
+ // Do after actors have been removed (coumpound can only be removed after all its elements are gone)
+ for(PxU32 i=0; i < mAggregateManager.getBufferedCount(); i++)
+ {
+ Aggregate* a = static_cast<Aggregate*>(mAggregateManager.getBuffered()[i]);
+
+ if(a->getControlState() == ControlState::eREMOVE_PENDING)
+ {
+ a->syncState(*this); // Clears the aggregate ID for all actors of the aggregate
+ mScene.deleteAggregate(a->getAggregateID());
+
+#if PX_SUPPORT_PVD
+ mScenePvdClient.releasePvdInstance(a);
+#endif
+ }
+ }
+
+
+}
+
+void Scb::Scene::scheduleForUpdate(Scb::Base& object)
+{
+ switch(object.getScbType())
+ {
+ case ScbType::SHAPE_EXCLUSIVE:
+ case ScbType::SHAPE_SHARED: { mShapeManager.scheduleForUpdate(object); }break;
+ case ScbType::BODY: { mBodyManager.scheduleForUpdate(object); }break;
+ case ScbType::BODY_FROM_ARTICULATION_LINK: { mBodyManager.scheduleForUpdate(object); }break;
+ case ScbType::RIGID_STATIC: { mRigidStaticManager.scheduleForUpdate(object); }break;
+ case ScbType::CONSTRAINT: { mConstraintManager.scheduleForUpdate(object); }break;
+#if PX_USE_PARTICLE_SYSTEM_API
+ case ScbType::PARTICLE_SYSTEM: { mParticleSystemManager.scheduleForUpdate(object); }break;
+#endif
+ case ScbType::ARTICULATION: { mArticulationManager.scheduleForUpdate(object); }break;
+ case ScbType::ARTICULATION_JOINT: { mArticulationJointManager.scheduleForUpdate(object); }break;
+ case ScbType::AGGREGATE: { mAggregateManager.scheduleForUpdate(object); }break;
+#if PX_USE_CLOTH_API
+ case ScbType::CLOTH: { mClothManager.scheduleForUpdate(object); }break;
+#endif
+ case ScbType::UNDEFINED:
+ case ScbType::TYPE_COUNT:
+ PX_ALWAYS_ASSERT_MESSAGE( "scheduleForUpdate: missing type!");
+ break;
+ }
+}
+
+PxU8* Scb::Scene::getStream(ScbType::Enum type)
+{
+ PxU8* memory = NULL;
+ switch(type)
+ {
+ case ScbType::SHAPE_EXCLUSIVE:
+ case ScbType::SHAPE_SHARED: { memory = reinterpret_cast<PxU8*>(mStream.allocateNotThreadSafe(sizeof(Scb::ShapeBuffer))); new (memory) Scb::ShapeBuffer; }break;
+ case ScbType::BODY: { memory = reinterpret_cast<PxU8*>(mStream.allocateNotThreadSafe(sizeof(Scb::BodyBuffer))); new (memory) Scb::BodyBuffer; }break;
+ case ScbType::BODY_FROM_ARTICULATION_LINK: { memory = reinterpret_cast<PxU8*>(mStream.allocateNotThreadSafe(sizeof(Scb::BodyBuffer))); new (memory) Scb::BodyBuffer; }break;
+ case ScbType::RIGID_STATIC: { memory = reinterpret_cast<PxU8*>(mStream.allocateNotThreadSafe(sizeof(Scb::RigidStaticBuffer))); new (memory) Scb::RigidStaticBuffer; }break;
+ case ScbType::CONSTRAINT: { memory = reinterpret_cast<PxU8*>(mStream.allocateNotThreadSafe(sizeof(Scb::ConstraintBuffer))); new (memory) Scb::ConstraintBuffer; }break;
+#if PX_USE_PARTICLE_SYSTEM_API
+ case ScbType::PARTICLE_SYSTEM: { memory = reinterpret_cast<PxU8*>(mStream.allocateNotThreadSafe(sizeof(Scb::ParticleSystemBuffer))); new (memory) Scb::ParticleSystemBuffer; }break;
+#endif
+ case ScbType::ARTICULATION: { memory = reinterpret_cast<PxU8*>(mStream.allocateNotThreadSafe(sizeof(Scb::ArticulationBuffer))); new (memory) Scb::ArticulationBuffer; }break;
+ case ScbType::ARTICULATION_JOINT: { memory = reinterpret_cast<PxU8*>(mStream.allocateNotThreadSafe(sizeof(Scb::ArticulationJointBuffer))); new (memory) Scb::ArticulationJointBuffer; }break;
+ case ScbType::AGGREGATE: { memory = reinterpret_cast<PxU8*>(mStream.allocateNotThreadSafe(sizeof(Scb::AggregateBuffer))); new (memory) Scb::AggregateBuffer; }break;
+
+#if PX_USE_CLOTH_API
+ case ScbType::CLOTH:
+#endif
+ case ScbType::UNDEFINED:
+ case ScbType::TYPE_COUNT:
+ PX_ALWAYS_ASSERT_MESSAGE("getStream: missing type!");
+ return NULL;
+ }
+ return memory;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxBroadPhaseType::Enum Scb::Scene::getBroadPhaseType() const
+{
+ return mScene.getBroadPhaseType();
+}
+
+bool Scb::Scene::getBroadPhaseCaps(PxBroadPhaseCaps& caps) const
+{
+ return mScene.getBroadPhaseCaps(caps);
+}
+
+PxU32 Scb::Scene::getNbBroadPhaseRegions() const
+{
+ return mScene.getNbBroadPhaseRegions();
+}
+
+PxU32 Scb::Scene::getBroadPhaseRegions(PxBroadPhaseRegionInfo* userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ return mScene.getBroadPhaseRegions(userBuffer, bufferSize, startIndex);
+}
+
+PxU32 Scb::Scene::addBroadPhaseRegion(const PxBroadPhaseRegion& region, bool populateRegion)
+{
+ if(!isPhysicsBuffering())
+ return mScene.addBroadPhaseRegion(region, populateRegion);
+ else
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::addBroadPhaseRegion() not allowed while simulation is running. Call will be ignored.");
+ return 0xffffffff;
+}
+
+bool Scb::Scene::removeBroadPhaseRegion(PxU32 handle)
+{
+ if(!isPhysicsBuffering())
+ return mScene.removeBroadPhaseRegion(handle);
+ else
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::removeBroadPhaseRegion() not allowed while simulation is running. Call will be ignored.");
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+//
+// To avoid duplication of a lot of similar code, the following templated method was introduced. Its main purpose is to
+// take care of all the operations related to adding/removing a rigid object to/from the scene. Depending on the type
+// of rigid object and the simulation state, there are slight changes to the code flow necessary. Among the operations are:
+//
+// - Add/remove rigid object to/from scene
+// - Add/remove shapes from PVD
+// - Adjust buffer control state of shapes
+// - Adjust ref-count of shapes
+//
+template <bool TSimRunning, bool TAdd, bool TIsDynamic, bool TIsNonSimObject, class T>
+PX_FORCE_INLINE static void addOrRemoveRigidObject(Sc::Scene& s, T& rigidObject, bool wakeOnLostTouch, PxBounds3* uninflatedBounds)
+{
+ PX_ASSERT(TIsDynamic || (rigidObject.getScbType() == ScbType::RIGID_STATIC));
+ if (TSimRunning && TIsNonSimObject && TAdd)
+ PX_ASSERT(rigidObject.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION);
+ if (TSimRunning && TIsNonSimObject&& !TAdd)
+ PX_ASSERT(rigidObject.isSimDisabledInternally());
+ if (!TSimRunning && TIsNonSimObject)
+ PX_ASSERT(rigidObject.isSimDisabledInternally()); // when the simulation flag gets cleared on an object with pending removal, only the core flag knows that internally it is still a non-simulation object.
+ PX_ASSERT(!uninflatedBounds || (TAdd && !TSimRunning && !TIsNonSimObject));
+
+ Ps::InlineArray<const Sc::ShapeCore*, 64> localShapes;
+ Ps::InlineArray<const Sc::ShapeCore*, 64>& scShapes = s.getBatchRemove() ? s.getBatchRemove()->removedShapes : localShapes;
+
+ PxActor* pxActor = NULL;
+ void* const* shapes;
+ PxU32 nbShapes;
+ size_t shapePtrOffset = NpShapeGetScPtrOffset();
+
+ Scb::Body& dynamicObject = reinterpret_cast<Scb::Body&>(rigidObject);
+ Scb::RigidStatic& staticObject = reinterpret_cast<Scb::RigidStatic&>(rigidObject);
+
+ if (!TSimRunning)
+ {
+ if (TIsDynamic)
+ pxActor = dynamicObject.getScBody().getPxActor();
+ else
+ pxActor = staticObject.getScStatic().getPxActor();
+ }
+ PX_UNUSED(pxActor);
+ size_t ptrOffset;
+ if (TAdd || TSimRunning || TIsNonSimObject)
+ {
+ // Np buffers are still valid when the object gets removed while the sim is running.
+ // Furthermore, for non-simulation objects, there exists no shape buffer in the simulation controller
+ // and we need to fetch from Np all the time.
+
+ ptrOffset = shapePtrOffset - Scb::Shape::getScOffset();
+
+ if (TIsDynamic)
+ nbShapes = NpRigidDynamicGetShapes(dynamicObject, shapes);
+ else
+ nbShapes = NpRigidStaticGetShapes(staticObject, shapes);
+ }
+
+ if ((!TSimRunning) && (!TIsNonSimObject))
+ {
+ if (TAdd)
+ {
+ if (TIsDynamic)
+ s.addBody(dynamicObject.getScBody(), shapes, nbShapes, shapePtrOffset, uninflatedBounds);
+ else
+ s.addStatic(staticObject.getScStatic(), shapes, nbShapes, shapePtrOffset, uninflatedBounds);
+ }
+ else
+ {
+ ptrOffset = -Scb::Shape::getScOffset();
+
+ if (TIsDynamic)
+ s.removeBody(dynamicObject.getScBody(), scShapes, wakeOnLostTouch);
+ else
+ s.removeStatic(staticObject.getScStatic(), scShapes, wakeOnLostTouch);
+
+ shapes = reinterpret_cast<void*const*>(const_cast<Sc::ShapeCore*const*>(scShapes.begin()));
+ nbShapes = scShapes.size();
+ }
+ }
+
+ Scb::Scene* scbScene = rigidObject.getScbScene();
+ Scb::Scene* shapeScenePtr = scbScene;
+ Scb::ControlState::Enum controlState = rigidObject.getControlState();
+
+ if (!TSimRunning)
+ {
+ // hacky: in the non-buffered case the rigid objects might not have been updated properly at this point, so it's done explicitly.
+
+ if (TAdd)
+ {
+ PX_ASSERT(shapeScenePtr == scbScene);
+ controlState = Scb::ControlState::eIN_SCENE;
+ }
+ else
+ {
+ shapeScenePtr = NULL;
+ controlState = Scb::ControlState::eNOT_IN_SCENE;
+ }
+ }
+
+ for(PxU32 i=0; i < nbShapes; i++)
+ {
+ Scb::Shape& scbShape = *Ps::pointerOffset<Scb::Shape*>(shapes[i], ptrdiff_t(ptrOffset));
+
+ if (!TSimRunning)
+ {
+ PX_ASSERT(pxActor);
+ PX_ASSERT(scbScene);
+
+ if (TAdd)
+ {
+ scbShape.setControlStateIfExclusive(shapeScenePtr, controlState);
+
+ if (!TIsNonSimObject)
+ NpShapeIncRefCount(scbShape); // simulation increases the refcount to avoid that shapes get destroyed while the sim is running
+
+#if PX_SUPPORT_PVD
+ scbScene->getScenePvdClient().createPvdInstance(&scbShape, *pxActor);
+#endif
+ }
+ else
+ {
+ scbShape.checkUpdateOnRemove<true>(scbScene);
+
+#if PX_SUPPORT_PVD
+ scbScene->getScenePvdClient().releasePvdInstance(&scbShape, *pxActor);
+#endif
+ scbShape.setControlStateIfExclusive(shapeScenePtr, controlState);
+
+ if (!TIsNonSimObject)
+ NpShapeDecRefCount(scbShape); // see comment in the "TAdd" section above
+ }
+ }
+ else
+ scbShape.setControlStateIfExclusive(shapeScenePtr, controlState);
+ }
+}
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbScene.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbScene.h
new file mode 100644
index 00000000..3a3ae43d
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbScene.h
@@ -0,0 +1,939 @@
+// 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_SCB_SCENE
+#define PX_PHYSICS_SCB_SCENE
+
+#include "ScScene.h"
+
+#include "ScbSceneBuffer.h"
+#include "ScbType.h"
+#include "PsFoundation.h"
+#include "PsMutex.h"
+#include "PsHashSet.h"
+
+#if PX_SUPPORT_PVD
+#include "PxPhysics.h"
+#include "ScbScenePvdClient.h"
+#endif
+
+namespace physx
+{
+
+class NpMaterial;
+
+namespace Sc
+{
+ class BodyDesc;
+}
+
+namespace Scb
+{
+ class Base;
+ class RigidObject;
+ class RigidStatic;
+ class Body;
+ class Actor;
+ class Shape;
+ class Constraint;
+ class Material;
+ class ParticleSystem;
+ class Articulation;
+ class ArticulationJoint;
+ class Aggregate;
+ class Cloth;
+
+ struct ShapeBuffer;
+
+ /**
+ \brief Helper class to track inserted/removed/updated buffering objects.
+ */
+ class ObjectTracker
+ {
+ public:
+ ObjectTracker() {}
+
+ /**
+ \brief An object has been inserted while the simulation was running -> track it for insertion at sync point
+ */
+ void scheduleForInsert(Base& element);
+
+ /**
+ \brief An object has been removed while the simulation was running -> track it for removal at sync point
+ */
+ void scheduleForRemove(Base& element);
+
+ /**
+ \brief An object has been changed while the simulation was running -> track it for update at sync point
+ */
+ void scheduleForUpdate(Base& element);
+
+ /**
+ \brief Get the list of dirty objects that require processing at a sync point.
+ */
+ Base*const * getBuffered() { return mBuffered.getEntries(); }
+
+ /**
+ \brief Get number of dirty objects that require processing at a sync point.
+ */
+ PxU32 getBufferedCount() const { return mBuffered.size(); }
+
+ /**
+ \brief Cleanup dirty objects after sync point.
+
+ \li Transition pending insertion objects from eINSERT_PENDING to eIN_SCENE.
+ \li Transition pending removal objects from eREMOVE_PENDING to eNOT_IN_SCENE.
+ \li Destroy objects marked as eIS_RELEASED.
+ \li Clear dirty list.
+ */
+ void clear();
+
+ void insert(Base& element);
+ void remove(Base& element);
+
+ private:
+ Ps::CoalescedHashSet<Base*> mBuffered;
+ };
+
+ typedef ObjectTracker ShapeManager;
+ typedef ObjectTracker RigidStaticManager;
+ typedef ObjectTracker BodyManager;
+ typedef ObjectTracker ParticleSystemManager;
+ typedef ObjectTracker ArticulationManager;
+ typedef ObjectTracker ConstraintManager;
+ typedef ObjectTracker ArticulationJointManager;
+ typedef ObjectTracker AggregateManager;
+ typedef ObjectTracker ClothManager;
+
+ enum MATERIAL_EVENT
+ {
+ MATERIAL_ADD,
+ MATERIAL_UPDATE,
+ MATERIAL_REMOVE
+ };
+
+ class MaterialEvent
+ {
+ public:
+ PX_FORCE_INLINE MaterialEvent(PxU32 handle, MATERIAL_EVENT type) : mHandle(handle), mType(type) {}
+ PX_FORCE_INLINE MaterialEvent() {}
+
+ PxU32 mHandle;//handle to the master material table
+ MATERIAL_EVENT mType;
+ };
+
+ class Scene : public Ps::UserAllocated
+ {
+ PX_NOCOPY(Scene)
+ public:
+ enum BufferFlag
+ {
+ BF_GRAVITY = (1 << 0),
+ BF_BOUNCETHRESHOLDVELOCITY = (1 << 1),
+ BF_FLAGS = (1 << 2),
+ BF_DOMINANCE_PAIRS = (1 << 3),
+ BF_SOLVER_BATCH_SIZE = (1 << 4),
+ BF_CLIENT_BEHAVIOR_FLAGS = (1 << 5),
+ BF_VISUALIZATION = (1 << 6),
+ BF_SCENE_PARAMS = (1 << 7)
+
+ };
+
+ public:
+ Scene(const PxSceneDesc& desc, PxU64 contextID);
+ ~Scene() {} //use release() plz.
+
+ //---------------------------------------------------------------------------------
+ // Wrapper for Sc::Scene interface
+ //---------------------------------------------------------------------------------
+ void release();
+
+ PxScene* getPxScene();
+
+ PX_INLINE void setGravity(const PxVec3& gravity);
+ PX_INLINE PxVec3 getGravity() const;
+
+ PX_INLINE void setBounceThresholdVelocity(const PxReal t);
+ PX_INLINE PxReal getBounceThresholdVelocity() const;
+
+ PX_INLINE void setFlags(PxSceneFlags flags);
+ PX_INLINE PxSceneFlags getFlags() const;
+
+ PX_INLINE void setFrictionType(PxFrictionType::Enum);
+ PX_INLINE PxFrictionType::Enum getFrictionType() const;
+
+ void addActor(Scb::RigidStatic&, bool noSim, PxBounds3* uninflatedBounds);
+ void removeActor(Scb::RigidStatic&, bool wakeOnLostTouch, bool noSim);
+
+ void addActor(Scb::Body&, bool noSim, PxBounds3* uninflatedBounds);
+ void removeActor(Scb::Body&, bool wakeOnLostTouch, bool noSim);
+
+ void addConstraint(Scb::Constraint&);
+ void removeConstraint(Scb::Constraint&);
+
+ void addArticulation(Scb::Articulation&);
+ void removeArticulation(Scb::Articulation&);
+
+ void addArticulationJoint(Scb::ArticulationJoint&);
+ void removeArticulationJoint(Scb::ArticulationJoint&);
+
+ void addAggregate(Scb::Aggregate&);
+ void removeAggregate(Scb::Aggregate&);
+
+ #if PX_USE_PARTICLE_SYSTEM_API
+ void addParticleSystem(Scb::ParticleSystem&);
+ void removeParticleSystem(Scb::ParticleSystem&, bool isRelease);
+ #endif
+
+ #if PX_USE_CLOTH_API
+ void addCloth(Scb::Cloth&);
+ void removeCloth(Scb::Cloth&);
+ #endif
+
+ void addMaterial(const Sc::MaterialCore& mat);
+ void updateMaterial(const Sc::MaterialCore& mat);
+ void removeMaterial(const Sc::MaterialCore& mat);
+ void updateLowLevelMaterial(NpMaterial** masterMaterials);
+ // These methods are only to be called at fetchResults!
+ PX_INLINE PxU32 getNumActiveBodies() const;
+ PX_INLINE Sc::BodyCore* const* getActiveBodiesArray() const;
+ PX_INLINE PxSimulationEventCallback* getSimulationEventCallback(PxClientID client) const;
+ PX_INLINE void setSimulationEventCallback(PxSimulationEventCallback* callback, PxClientID client);
+ PX_INLINE PxContactModifyCallback* getContactModifyCallback() const;
+ PX_INLINE void setContactModifyCallback(PxContactModifyCallback* callback);
+ PX_INLINE PxCCDContactModifyCallback* getCCDContactModifyCallback() const;
+ PX_INLINE void setCCDContactModifyCallback(PxCCDContactModifyCallback* callback);
+ PX_INLINE PxU32 getCCDMaxPasses() const;
+ PX_INLINE void setCCDMaxPasses(PxU32 ccdMaxPasses);
+ PX_INLINE void setBroadPhaseCallback(PxBroadPhaseCallback* callback, PxClientID client);
+ PX_INLINE PxBroadPhaseCallback* getBroadPhaseCallback(PxClientID client) const;
+ PxBroadPhaseType::Enum getBroadPhaseType() const;
+ bool getBroadPhaseCaps(PxBroadPhaseCaps& caps) const;
+ PxU32 getNbBroadPhaseRegions() const;
+ PxU32 getBroadPhaseRegions(PxBroadPhaseRegionInfo* userBuffer, PxU32 bufferSize, PxU32 startIndex) const;
+ PxU32 addBroadPhaseRegion(const PxBroadPhaseRegion& region, bool populateRegion);
+ bool removeBroadPhaseRegion(PxU32 handle);
+
+ // Collision filtering
+ PX_INLINE void setFilterShaderData(const void* data, PxU32 dataSize);
+ PX_INLINE const void* getFilterShaderData() const;
+ PX_INLINE PxU32 getFilterShaderDataSize() const;
+ PX_INLINE PxSimulationFilterShader getFilterShader() const;
+ PX_INLINE PxSimulationFilterCallback* getFilterCallback() const;
+
+ // Groups
+ PX_INLINE void setDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2, const PxDominanceGroupPair& dominance);
+ PX_INLINE PxDominanceGroupPair getDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2) const;
+
+ PX_INLINE void setSolverBatchSize(PxU32 solverBatchSize);
+ PX_INLINE PxU32 getSolverBatchSize() const;
+
+ PX_INLINE void simulate(PxReal timeStep, PxBaseTask* continuation);
+ PX_INLINE void collide(PxReal timeStep, PxBaseTask* continuation);
+ PX_INLINE void advance(PxReal timeStep, PxBaseTask* continuation);
+ PX_INLINE void endSimulation();
+ PX_INLINE void flush(bool sendPendingReports);
+ PX_INLINE void fireBrokenConstraintCallbacks() { mScene.fireBrokenConstraintCallbacks(); }
+ PX_INLINE void fireTriggerCallbacks() { mScene.fireTriggerCallbacks(); }
+ PX_INLINE void fireQueuedContactCallbacks() { mScene.fireQueuedContactCallbacks(false); }
+ PX_INLINE const Ps::Array<PxContactPairHeader>&
+ getQueuedContactPairHeaders() { return mScene.getQueuedContactPairHeaders(); }
+ PX_FORCE_INLINE void postCallbacksPreSync() { mScene.postCallbacksPreSync(); } //cleanup tasks after the pre-sync callbacks have fired
+
+
+ PX_INLINE void fireCallBacksPostSync() { mScene.fireCallbacksPostSync(); } //callbacks that are fired on the core side, after the buffers get synced
+ PX_INLINE void postReportsCleanup();
+
+ PX_INLINE const PxSceneLimits& getLimits() const;
+ PX_INLINE void setLimits(const PxSceneLimits& limits);
+
+ PX_INLINE void getStats(PxSimulationStatistics& stats) const;
+
+ PX_DEPRECATED PX_INLINE void buildActiveTransforms(); // build the list of active transforms
+ PX_DEPRECATED PX_INLINE PxActiveTransform* getActiveTransforms(PxU32& nbTransformsOut, PxClientID client);
+
+ PX_INLINE void buildActiveActors(); // build the list of active actors
+ PX_INLINE PxActor** getActiveActors(PxU32& nbActorsOut, PxClientID client);
+
+ PX_INLINE PxClientID createClient();
+ PX_INLINE void setClientBehaviorFlags(PxClientID client, PxClientBehaviorFlags clientBehaviorFlags);
+ PX_INLINE PxClientBehaviorFlags getClientBehaviorFlags(PxClientID client) const;
+
+#if PX_USE_CLOTH_API
+ PX_INLINE void setClothInterCollisionDistance(PxF32 distance);
+ PX_INLINE PxF32 getClothInterCollisionDistance() const;
+ PX_INLINE void setClothInterCollisionStiffness(PxF32 stiffness);
+ PX_INLINE PxF32 getClothInterCollisionStiffness() const;
+ PX_INLINE void setClothInterCollisionNbIterations(PxU32 nbIterations);
+ PX_INLINE PxU32 getClothInterCollisionNbIterations() const;
+#endif
+
+ PX_INLINE void setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value);
+ PX_INLINE PxReal getVisualizationParameter(PxVisualizationParameter::Enum param) const;
+
+ PX_INLINE void setVisualizationCullingBox(const PxBounds3& box);
+ PX_INLINE const PxBounds3& getVisualizationCullingBox() const;
+
+ void shiftOrigin(const PxVec3& shift);
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+ public:
+ void syncWriteThroughProperties();
+ void syncEntireScene(PxU32* error);
+ void processPendingRemove();
+
+ PX_FORCE_INLINE PxU16* allocShapeMaterialBuffer(PxU32 count, PxU32& startIdx) { return allocArrayBuffer(mShapeMaterialBuffer, count, startIdx); }
+ PX_FORCE_INLINE const PxU16* getShapeMaterialBuffer(PxU32 startIdx) const { return &mShapeMaterialBuffer[startIdx]; }
+ PX_FORCE_INLINE Scb::Shape** allocShapeBuffer(PxU32 count, PxU32& startIdx) { return allocArrayBuffer(mShapePtrBuffer, count, startIdx); }
+ PX_FORCE_INLINE Scb::Shape** getShapeBuffer(PxU32 startIdx) { return &mShapePtrBuffer[startIdx]; }
+ PX_FORCE_INLINE Scb::Actor** allocActorBuffer(PxU32 count, PxU32& startIdx) { return allocArrayBuffer(mActorPtrBuffer, count, startIdx); }
+ PX_FORCE_INLINE Scb::Actor** getActorBuffer(PxU32 startIdx) { return &mActorPtrBuffer[startIdx]; }
+
+ void scheduleForUpdate(Scb::Base& object);
+ PxU8* getStream(ScbType::Enum type);
+
+ PX_FORCE_INLINE void removeShapeFromPendingUpdateList(Scb::Base& shape) { mShapeManager.remove(shape); }
+
+ PX_FORCE_INLINE const Sc::Scene& getScScene() const { return mScene; }
+ PX_FORCE_INLINE Sc::Scene& getScScene() { return mScene; }
+ PX_FORCE_INLINE void prepareOutOfBoundsCallbacks() { mScene.prepareOutOfBoundsCallbacks(); }
+
+ private:
+ void syncState();
+ PX_FORCE_INLINE Ps::IntBool isBuffered(BufferFlag f) const { return Ps::IntBool(mBufferFlags& f); }
+ PX_FORCE_INLINE void markUpdated(BufferFlag f) { mBufferFlags |= f; }
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ public:
+
+ PX_FORCE_INLINE bool isPhysicsBuffering() const { return mIsBuffering; }
+ PX_FORCE_INLINE void setPhysicsBuffering(bool buffering) { mIsBuffering = buffering; }
+
+ PX_FORCE_INLINE Sc::SimulationStage::Enum getSimulationStage() const { return mScene.getSimulationStage(); }
+ PX_FORCE_INLINE void setSimulationStage(Sc::SimulationStage::Enum stage) { mScene.setSimulationStage(stage); }
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ void preSimulateUpdateAppThread(PxReal timeStep); // Data updates that need to be handled in the application thread before the simulation potentially switches // to its own thread.
+#endif
+
+ PX_FORCE_INLINE bool isValid() const { return mScene.isValid(); }
+
+ PX_FORCE_INLINE PxReal getWakeCounterResetValue() const { return mWakeCounterResetValue; }
+
+ void switchRigidToNoSim(Scb::RigidObject&, bool isDynamic);
+ void switchRigidFromNoSim(Scb::RigidObject&, bool isDynamic);
+
+ static size_t getScOffset() { return reinterpret_cast<size_t>(&reinterpret_cast<Scene*>(0)->mScene); }
+
+#if PX_SUPPORT_PVD
+ PX_FORCE_INLINE Vd::ScbScenePvdClient& getScenePvdClient() { return mScenePvdClient; }
+ PX_FORCE_INLINE const Vd::ScbScenePvdClient& getScenePvdClient() const { return mScenePvdClient; }
+#endif
+
+ PX_FORCE_INLINE PxU64 getContextId() const { return mScene.getContextId(); }
+
+ private:
+ void addShapeInternal(Scb::Shape&);
+ void addShapesInternal(PxU32 nbShapes, PxShape** PX_RESTRICT shapes, size_t scbOffset, PxActor** PX_RESTRICT owners, PxU32 offsetNpToCore, bool isDynamic);
+
+ template<typename T> T* allocArrayBuffer(Ps::Array<T>& buffer, PxU32 count, PxU32& startIdx);
+
+ private:
+
+ template<bool TIsDynamic, class T>
+ PX_FORCE_INLINE void addActorT(T& actor, ObjectTracker& tracker, bool noSim, PxBounds3* uninflatedBounds);
+
+ template<typename T> void add(T& v, ObjectTracker &tracker, PxBounds3* uninflatedBounds);
+ template<typename T> void remove(T& v, ObjectTracker &tracker, bool wakeOnLostTouch = false);
+ template<bool TIsDynamic, typename T> void addRigidNoSim(T& v, ObjectTracker &tracker);
+ template<bool TIsDynamic, typename T> void removeRigidNoSim(T& v, ObjectTracker &tracker);
+ template<typename T, typename S> void processSimUpdates(S*const * scObjects, PxU32 nbObjects);
+ template<typename T> void processUserUpdates(ObjectTracker& tracker);
+ template<typename T, bool syncOnRemove, bool wakeOnLostTouchCheck> void processRemoves(ObjectTracker& tracker);
+ template<typename T> void processShapeRemoves(ObjectTracker& tracker);
+
+ Sc::Scene mScene;
+
+ Ps::Array<MaterialEvent> mSceneMaterialBuffer;
+ Ps::Mutex mSceneMaterialBufferLock;
+
+ bool mSimulationRunning;
+ bool mIsBuffering;
+
+ Cm::FlushPool mStream; // Pool for temporarily buffering user changes on objects
+ ShapeManager mShapeManager;
+ Ps::Array<PxU16> mShapeMaterialBuffer; // Buffered setMaterial() call might need to track list of materials (for multi material shapes)
+ Ps::Array<Scb::Shape*> mShapePtrBuffer; // List of shape pointers to track buffered calls to resetFiltering(), for example
+ Ps::Array<Scb::Actor*> mActorPtrBuffer;
+ RigidStaticManager mRigidStaticManager;
+ BodyManager mBodyManager;
+#if PX_USE_PARTICLE_SYSTEM_API
+ ParticleSystemManager mParticleSystemManager;
+#endif
+ ConstraintManager mConstraintManager;
+ ArticulationManager mArticulationManager;
+ ArticulationJointManager mArticulationJointManager;
+ AggregateManager mAggregateManager;
+#if PX_USE_CLOTH_API
+ ClothManager mClothManager;
+#endif
+#if PX_SUPPORT_PVD
+ Vd::ScbScenePvdClient mScenePvdClient;
+#endif
+
+ PX_FORCE_INLINE void updatePvdProperties()
+ {
+#if PX_SUPPORT_PVD
+ // PT: TODO: shouldn't we test PxPvdInstrumentationFlag::eDEBUG here?
+ if(mScenePvdClient.isConnected())
+ mScenePvdClient.updatePvdProperties();
+#endif
+ }
+
+ PxReal mWakeCounterResetValue;
+
+ // note: If deletion of rigid objects is done before the sync of the simulation data then we
+ // might wanna consider having a separate list for deleted rigid objects (for performance
+ // reasons)
+
+ //---------------------------------------------------------------------------------
+ // On demand buffered data (simulation read-only data)
+ //---------------------------------------------------------------------------------
+ Scb::SceneBuffer mBufferedData;
+ PxU32 mBufferFlags;
+ };
+
+} // namespace Scb
+
+
+template<typename T>
+T* Scb::Scene::allocArrayBuffer(Ps::Array<T>& buffer, PxU32 count, PxU32& startIdx)
+{
+ PxU32 oldSize = buffer.size();
+ buffer.resize(oldSize + count);
+ startIdx = oldSize;
+ return &buffer[oldSize];
+}
+
+PX_INLINE void Scb::Scene::setGravity(const PxVec3& gravity)
+{
+ if (!isPhysicsBuffering())
+ {
+ mScene.setGravity(gravity);
+ updatePvdProperties();
+ }
+ else
+ {
+ mBufferedData.gravity = gravity;
+ markUpdated(BF_GRAVITY);
+ }
+}
+
+PX_INLINE PxVec3 Scb::Scene::getGravity() const
+{
+ if (isBuffered(BF_GRAVITY))
+ return mBufferedData.gravity;
+ else
+ return mScene.getGravity();
+}
+
+void Scb::Scene::setBounceThresholdVelocity(const PxReal t)
+{
+ if (!isPhysicsBuffering())
+ {
+ mScene.setBounceThresholdVelocity(t);
+ updatePvdProperties();
+ }
+ else
+ {
+ mBufferedData.bounceThresholdVelocity = t;
+ markUpdated(BF_BOUNCETHRESHOLDVELOCITY);
+ }
+}
+
+PxReal Scb::Scene::getBounceThresholdVelocity() const
+{
+ if (isBuffered(BF_BOUNCETHRESHOLDVELOCITY))
+ return mBufferedData.bounceThresholdVelocity;
+ else
+ return mScene.getBounceThresholdVelocity();
+}
+
+PX_INLINE void Scb::Scene::setFrictionType(PxFrictionType::Enum frictionType)
+{
+ mScene.setFrictionType(frictionType);
+}
+
+PX_INLINE PxFrictionType::Enum Scb::Scene::getFrictionType() const
+{
+ return mScene.getFrictionType();
+}
+
+
+PX_INLINE void Scb::Scene::setFlags(PxSceneFlags flags)
+{
+ if (!isPhysicsBuffering())
+ {
+ mScene.setPublicFlags(flags);
+ const bool pcm = (flags & PxSceneFlag::eENABLE_PCM);
+ mScene.setPCM(pcm);
+ const bool contactCache = !(flags & PxSceneFlag::eDISABLE_CONTACT_CACHE);
+ mScene.setContactCache(contactCache);
+ updatePvdProperties();
+ }
+ else
+ {
+ mBufferedData.flags = flags;
+ markUpdated(BF_FLAGS);
+ }
+}
+
+
+PX_INLINE PxSceneFlags Scb::Scene::getFlags() const
+{
+ if (isBuffered(BF_FLAGS))
+ return mBufferedData.flags;
+ else
+ return mScene.getPublicFlags();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PX_INLINE PxSimulationEventCallback* Scb::Scene::getSimulationEventCallback(PxClientID client) const
+{
+ return mScene.getSimulationEventCallback(client);
+}
+
+PX_INLINE void Scb::Scene::setSimulationEventCallback(PxSimulationEventCallback* callback, PxClientID client)
+{
+ if(!isPhysicsBuffering())
+ mScene.setSimulationEventCallback(callback, client);
+ else
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::setSimulationEventCallback() not allowed while simulation is running. Call will be ignored.");
+}
+
+PX_INLINE PxContactModifyCallback* Scb::Scene::getContactModifyCallback() const
+{
+ return mScene.getContactModifyCallback();
+}
+
+PX_INLINE void Scb::Scene::setContactModifyCallback(PxContactModifyCallback* callback)
+{
+ if(!isPhysicsBuffering())
+ mScene.setContactModifyCallback(callback);
+ else
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::setContactModifyCallback() not allowed while simulation is running. Call will be ignored.");
+}
+
+PX_INLINE PxCCDContactModifyCallback* Scb::Scene::getCCDContactModifyCallback() const
+{
+ return mScene.getCCDContactModifyCallback();
+}
+
+PX_INLINE void Scb::Scene::setCCDContactModifyCallback(PxCCDContactModifyCallback* callback)
+{
+ if(!isPhysicsBuffering())
+ mScene.setCCDContactModifyCallback(callback);
+ else
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::setCCDContactModifyCallback() not allowed while simulation is running. Call will be ignored.");
+}
+
+PX_INLINE PxU32 Scb::Scene::getCCDMaxPasses() const
+{
+ return mScene.getCCDMaxPasses();
+}
+
+PX_INLINE void Scb::Scene::setCCDMaxPasses(PxU32 ccdMaxPasses)
+{
+ if(!isPhysicsBuffering())
+ mScene.setCCDMaxPasses(ccdMaxPasses);
+ else
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::setCCDMaxPasses() not allowed while simulation is running. Call will be ignored.");
+}
+
+PX_INLINE PxBroadPhaseCallback* Scb::Scene::getBroadPhaseCallback(PxClientID client) const
+{
+ return mScene.getBroadPhaseCallback(client);
+}
+
+PX_INLINE void Scb::Scene::setBroadPhaseCallback(PxBroadPhaseCallback* callback, PxClientID client)
+{
+ if(!isPhysicsBuffering())
+ mScene.setBroadPhaseCallback(callback, client);
+ else
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::setBroadPhaseCallback() not allowed while simulation is running. Call will be ignored.");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PX_INLINE void Scb::Scene::setFilterShaderData(const void* data, PxU32 dataSize)
+{
+ if(!isPhysicsBuffering())
+ mScene.setFilterShaderData(data, dataSize);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::setFilterShaderData() not allowed while simulation is running. Call will be ignored.");
+}
+
+
+PX_INLINE const void* Scb::Scene::getFilterShaderData() const
+{
+ return mScene.getFilterShaderDataFast();
+}
+
+
+PX_INLINE PxU32 Scb::Scene::getFilterShaderDataSize() const
+{
+ return mScene.getFilterShaderDataSizeFast();
+}
+
+
+PX_INLINE PxSimulationFilterShader Scb::Scene::getFilterShader() const
+{
+ return mScene.getFilterShaderFast();
+}
+
+
+PX_INLINE PxSimulationFilterCallback* Scb::Scene::getFilterCallback() const
+{
+ return mScene.getFilterCallbackFast();
+}
+
+
+PX_INLINE void Scb::Scene::simulate(PxReal timeStep, PxBaseTask* continuation)
+{
+ mScene.simulate(timeStep, continuation);
+}
+
+PX_INLINE void Scb::Scene::advance(PxReal timeStep, PxBaseTask* continuation)
+{
+ mScene.advance(timeStep, continuation);
+}
+
+PX_INLINE void Scb::Scene::collide(PxReal timeStep, PxBaseTask* continuation)
+{
+ mScene.collide(timeStep, continuation);
+}
+
+PX_INLINE void Scb::Scene::endSimulation()
+{
+ mScene.endSimulation();
+}
+
+
+PX_INLINE void Scb::Scene::flush(bool sendPendingReports)
+{
+ PX_ASSERT(!isPhysicsBuffering());
+
+ mShapeMaterialBuffer.reset();
+ mShapePtrBuffer.reset();
+ mActorPtrBuffer.reset();
+
+ //!!! TODO: Clear all buffers used for double buffering changes (see ObjectTracker::mBufferPool)
+
+ mScene.flush(sendPendingReports);
+}
+
+
+PX_INLINE void Scb::Scene::postReportsCleanup()
+{
+ PX_ASSERT(!isPhysicsBuffering());
+ mScene.postReportsCleanup();
+}
+
+
+PX_INLINE const PxSceneLimits& Scb::Scene::getLimits() const
+{
+ return mScene.getLimits();
+}
+
+PX_INLINE void Scb::Scene::setLimits(const PxSceneLimits& limits)
+{
+ mScene.setLimits(limits);
+}
+
+PX_INLINE void Scb::Scene::setDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2, const PxDominanceGroupPair& dominance)
+{
+ if (!isPhysicsBuffering())
+ {
+ mScene.setDominanceGroupPair(group1, group2, dominance);
+ updatePvdProperties();
+ }
+ else
+ {
+ mBufferedData.setDominancePair(group1, group2, dominance);
+ markUpdated(BF_DOMINANCE_PAIRS);
+ }
+}
+
+
+PX_INLINE PxDominanceGroupPair Scb::Scene::getDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2) const
+{
+ if (isBuffered(BF_DOMINANCE_PAIRS))
+ {
+ PxDominanceGroupPair dominance(0, 0);
+ if (mBufferedData.getDominancePair(group1, group2, dominance))
+ return dominance;
+ }
+
+ return mScene.getDominanceGroupPair(group1, group2);
+}
+
+
+PX_INLINE void Scb::Scene::setSolverBatchSize(PxU32 solverBatchSize)
+{
+ if (!isPhysicsBuffering())
+ {
+ mScene.setSolverBatchSize(solverBatchSize);
+ updatePvdProperties();
+ }
+ else
+ {
+ mBufferedData.solverBatchSize = solverBatchSize;
+ markUpdated(BF_SOLVER_BATCH_SIZE);
+ }
+}
+
+PX_INLINE PxU32 Scb::Scene::getSolverBatchSize() const
+{
+ if (isBuffered(BF_SOLVER_BATCH_SIZE))
+ return mBufferedData.solverBatchSize;
+ else
+ return mScene.getSolverBatchSize();
+}
+
+
+PX_INLINE void Scb::Scene::getStats(PxSimulationStatistics& stats) const
+{
+ PX_ASSERT(!isPhysicsBuffering());
+
+ mScene.getStats(stats);
+}
+
+
+PX_DEPRECATED PX_INLINE void Scb::Scene::buildActiveTransforms()
+{
+ PX_ASSERT(!isPhysicsBuffering());
+
+ mScene.buildActiveTransforms();
+}
+
+
+PX_DEPRECATED PX_INLINE PxActiveTransform* Scb::Scene::getActiveTransforms(PxU32& nbTransformsOut, PxClientID client)
+{
+ if (!isPhysicsBuffering())
+ {
+ return mScene.getActiveTransforms(nbTransformsOut, client);
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::getActiveTransforms() not allowed while simulation is running. Call will be ignored.");
+ nbTransformsOut = 0;
+ return NULL;
+ }
+}
+
+PX_INLINE void Scb::Scene::buildActiveActors()
+{
+ PX_ASSERT(!isPhysicsBuffering());
+
+ mScene.buildActiveActors();
+}
+
+PX_INLINE PxActor** Scb::Scene::getActiveActors(PxU32& nbActorsOut, PxClientID client)
+{
+ if (!isPhysicsBuffering())
+ {
+ return mScene.getActiveActors(nbActorsOut, client);
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::getActiveActors() not allowed while simulation is running. Call will be ignored.");
+ nbActorsOut = 0;
+ return NULL;
+ }
+}
+
+
+PX_INLINE PxClientID Scb::Scene::createClient()
+{
+ mBufferedData.clientBehaviorFlags.pushBack(PxClientBehaviorFlag_eNOT_BUFFERED); //PxClientBehaviorFlag_eNOT_BUFFERED means its not storing anything. Do this either way to make sure this buffer is big enough for behavior bit set/gets later.
+
+ if (!isPhysicsBuffering())
+ {
+ PxClientID i = mScene.createClient();
+ PX_ASSERT(mBufferedData.clientBehaviorFlags.size()-1 == i);
+ return i;
+ }
+ else
+ {
+ mBufferedData.numClientsCreated++;
+ return PxClientID(mBufferedData.clientBehaviorFlags.size()-1); //mScene.createClient();
+ }
+}
+
+PX_INLINE void Scb::Scene::setClientBehaviorFlags(PxClientID client, PxClientBehaviorFlags clientBehaviorFlags)
+{
+ if (!isPhysicsBuffering())
+ {
+ mScene.setClientBehaviorFlags(client, clientBehaviorFlags);
+ updatePvdProperties();
+ }
+ else
+ {
+ PX_ASSERT(mBufferedData.clientBehaviorFlags.size() > client);
+ mBufferedData.clientBehaviorFlags[client] = clientBehaviorFlags;
+ markUpdated(BF_CLIENT_BEHAVIOR_FLAGS);
+ }
+}
+
+PX_INLINE PxClientBehaviorFlags Scb::Scene::getClientBehaviorFlags(PxClientID client) const
+{
+ PX_ASSERT(mBufferedData.clientBehaviorFlags.size() > client);
+ if (isBuffered(BF_CLIENT_BEHAVIOR_FLAGS) && (mBufferedData.clientBehaviorFlags[client] != PxClientBehaviorFlag_eNOT_BUFFERED))
+ return mBufferedData.clientBehaviorFlags[client];
+ else
+ return mScene.getClientBehaviorFlags(client);
+}
+
+#if PX_USE_CLOTH_API
+
+PX_INLINE void Scb::Scene::setClothInterCollisionDistance(PxF32 distance)
+{
+ if (!isPhysicsBuffering())
+ {
+ mScene.setClothInterCollisionDistance(distance);
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::setClothInterCollisionDistance() not allowed while simulation is running. Call will be ignored.");
+ }
+}
+
+PX_INLINE PxF32 Scb::Scene::getClothInterCollisionDistance() const
+{
+ return mScene.getClothInterCollisionDistance();
+}
+
+PX_INLINE void Scb::Scene::setClothInterCollisionStiffness(PxF32 stiffness)
+{
+ if (!isPhysicsBuffering())
+ {
+ mScene.setClothInterCollisionStiffness(stiffness);
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::setClothInterCollisionStiffness() not allowed while simulation is running. Call will be ignored.");
+ }
+}
+
+PX_INLINE PxF32 Scb::Scene::getClothInterCollisionStiffness() const
+{
+ return mScene.getClothInterCollisionStiffness();
+}
+
+PX_INLINE void Scb::Scene::setClothInterCollisionNbIterations(PxU32 nbIterations)
+{
+ if (!isPhysicsBuffering())
+ {
+ mScene.setClothInterCollisionNbIterations(nbIterations);
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::setClothInterCollisionNbIterations() not allowed while simulation is running. Call will be ignored.");
+ }
+}
+
+PX_INLINE PxU32 Scb::Scene::getClothInterCollisionNbIterations() const
+{
+ return mScene.getClothInterCollisionNbIterations();
+}
+
+#endif
+
+
+PX_INLINE void Scb::Scene::setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value)
+{
+ if (!isPhysicsBuffering())
+ mScene.setVisualizationParameter(param, value);
+ else
+ {
+ PX_ASSERT(param < PxVisualizationParameter::eNUM_VALUES);
+ mBufferedData.visualizationParamChanged[param] = 1;
+ mBufferedData.visualizationParam[param] = value;
+ markUpdated(BF_VISUALIZATION);
+ }
+}
+
+PX_INLINE PxReal Scb::Scene::getVisualizationParameter(PxVisualizationParameter::Enum param) const
+{
+ PX_ASSERT(param < PxVisualizationParameter::eNUM_VALUES);
+
+ if (isBuffered(BF_VISUALIZATION) && mBufferedData.visualizationParamChanged[param])
+ return mBufferedData.visualizationParam[param];
+ else
+ return mScene.getVisualizationParameter(param);
+}
+
+PX_INLINE void Scb::Scene::setVisualizationCullingBox(const PxBounds3& box)
+{
+ if (!isPhysicsBuffering())
+ mScene.setVisualizationCullingBox(box);
+ else
+ {
+ mBufferedData.visualizationCullingBoxChanged = 1;
+ mBufferedData.visualizationCullingBox = box;
+ markUpdated(BF_VISUALIZATION);
+ }
+}
+
+PX_INLINE const PxBounds3& Scb::Scene::getVisualizationCullingBox() const
+{
+ if (isBuffered(BF_VISUALIZATION) && mBufferedData.visualizationCullingBoxChanged)
+ return mBufferedData.visualizationCullingBox;
+ else
+ return mScene.getVisualizationCullingBox();
+}
+
+PX_INLINE PxU32 Scb::Scene::getNumActiveBodies() const
+{
+ return mScene.getNumActiveBodies();
+}
+PX_INLINE Sc::BodyCore* const* Scb::Scene::getActiveBodiesArray() const
+{
+ return mScene.getActiveBodiesArray();
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbSceneBuffer.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbSceneBuffer.h
new file mode 100644
index 00000000..61fea2af
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbSceneBuffer.h
@@ -0,0 +1,164 @@
+// 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_SCB_SCENE_BUFFER
+#define PX_PHYSICS_SCB_SCENE_BUFFER
+
+#include "CmPhysXCommon.h"
+
+#include "ScScene.h"
+
+#define PxClientBehaviorFlag_eNOT_BUFFERED PxClientBehaviorFlags(0xff)
+
+namespace physx
+{
+namespace Scb
+{
+
+struct SceneBuffer
+{
+public:
+ static const PxU32 sMaxNbDominanceGroups = 32;
+
+ PX_INLINE SceneBuffer();
+
+ PX_INLINE void clearDominanceBuffer();
+ PX_INLINE void setDominancePair(PxU32 group1, PxU32 group2, const PxDominanceGroupPair& dominance);
+ PX_INLINE bool getDominancePair(PxU32 group1, PxU32 group2, PxDominanceGroupPair& dominance) const;
+ PX_INLINE void syncDominancePairs(Sc::Scene& scene);
+
+ PX_INLINE void clearVisualizationParams();
+
+ PxReal visualizationParam[PxVisualizationParameter::eNUM_VALUES];
+ PxU8 visualizationParamChanged[PxVisualizationParameter::eNUM_VALUES];
+ PxBounds3 visualizationCullingBox;
+ PxU8 visualizationCullingBoxChanged;
+ PxU32 dominancePairFlag[sMaxNbDominanceGroups - 1];
+ PxU32 dominancePairValues[sMaxNbDominanceGroups];
+ PxVec3 gravity;
+ PxReal bounceThresholdVelocity;
+ PxSceneFlags flags;
+ PxU32 solverBatchSize;
+ PxU32 numClientsCreated;
+ Ps::Array<PxClientBehaviorFlags> clientBehaviorFlags; //a value is buffered if it is not -1.
+};
+
+
+PX_INLINE SceneBuffer::SceneBuffer() : clientBehaviorFlags(PX_DEBUG_EXP("clientBehaviorFlags"))
+{
+ clearDominanceBuffer();
+ clearVisualizationParams();
+ numClientsCreated = 0;
+ clientBehaviorFlags.pushBack(PxClientBehaviorFlag_eNOT_BUFFERED); //need member for default client, PxClientBehaviorFlag_eNOT_BUFFERED means its not storing anything.
+}
+
+
+PX_INLINE void SceneBuffer::clearDominanceBuffer()
+{
+ PxMemSet(&dominancePairFlag, 0, (sMaxNbDominanceGroups - 1) * sizeof(PxU32));
+}
+
+
+PX_INLINE void SceneBuffer::clearVisualizationParams()
+{
+ PxMemZero(visualizationParamChanged, PxVisualizationParameter::eNUM_VALUES * sizeof(PxU8));
+}
+
+
+PX_INLINE void SceneBuffer::setDominancePair(PxU32 group1, PxU32 group2, const PxDominanceGroupPair& dominance)
+{
+ PX_ASSERT(group1 != group2);
+ PX_ASSERT(group1 < sMaxNbDominanceGroups);
+ PX_ASSERT(group2 < sMaxNbDominanceGroups);
+
+ if (group1 < group2)
+ dominancePairFlag[group1] = dominancePairFlag[group1] | (1 << group2);
+ else
+ dominancePairFlag[group2] = dominancePairFlag[group2] | (1 << group1);
+
+ if (dominance.dominance0 != 0.0f)
+ dominancePairValues[group1] = dominancePairValues[group1] | (1 << group2);
+ else
+ dominancePairValues[group1] = dominancePairValues[group1] & (~(1 << group2));
+
+ if (dominance.dominance1 != 0.0f)
+ dominancePairValues[group2] = dominancePairValues[group2] | (1 << group1);
+ else
+ dominancePairValues[group2] = dominancePairValues[group2] & (~(1 << group1));
+}
+
+
+PX_INLINE bool SceneBuffer::getDominancePair(PxU32 group1, PxU32 group2, PxDominanceGroupPair& dominance) const
+{
+ PX_ASSERT(group1 != group2);
+ PX_ASSERT(group1 < sMaxNbDominanceGroups);
+ PX_ASSERT(group2 < sMaxNbDominanceGroups);
+
+ PxU32 isBuffered = 0;
+ if (group1 < group2)
+ isBuffered = dominancePairFlag[group1] & (1 << group2);
+ else
+ isBuffered = dominancePairFlag[group2] & (1 << group1);
+
+ if (isBuffered)
+ {
+ dominance.dominance0 = PxU8((dominancePairValues[group1] & (1 << group2)) >> group2 );
+ dominance.dominance1 = PxU8((dominancePairValues[group2] & (1 << group1)) >> group1 );
+ return true;
+ }
+
+ return false;
+}
+
+
+PX_INLINE void SceneBuffer::syncDominancePairs(Sc::Scene& scene)
+{
+ for(PxU32 i=0; i < (sMaxNbDominanceGroups - 1); i++)
+ {
+ if (dominancePairFlag[i])
+ {
+ for(PxU32 j=(i+1); j < sMaxNbDominanceGroups; j++)
+ {
+ PxDominanceGroupPair dominance(0, 0);
+ if (getDominancePair(i, j, dominance))
+ {
+ scene.setDominanceGroupPair(PxDominanceGroup(i), PxDominanceGroup(j), dominance);
+ }
+ }
+ }
+ }
+}
+
+
+} // namespace Scb
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbScenePvdClient.cpp b/PhysX_3.4/Source/PhysX/src/buffering/ScbScenePvdClient.cpp
new file mode 100644
index 00000000..03161149
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbScenePvdClient.cpp
@@ -0,0 +1,1240 @@
+// 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.
+
+#if PX_SUPPORT_PVD
+#include "NpCast.h"
+#include "ScbScenePvdClient.h"
+#include "PxActor.h"
+#include "PxRenderBuffer.h"
+#include "ScbScene.h"
+#include "ScbNpDeps.h"
+#include "PxPhysics.h"
+#include "ScMaterialCore.h"
+#include "PxsMaterialManager.h"
+#include "ScBodySim.h"
+#include "ScConstraintSim.h"
+#include "ScParticleSystemCore.h"
+#include "ScParticleSystemSim.h"
+
+#include "PxConstraintDesc.h"
+#include "ScConstraintCore.h"
+#include "PvdTypeNames.h"
+
+#include "gpu/PxParticleGpu.h"
+#include "PxPvdUserRenderer.h"
+#include "PxvNphaseImplementationContext.h"
+
+using namespace physx;
+using namespace physx::Vd;
+using namespace physx::pvdsdk;
+using namespace Scb;
+
+
+namespace
+{
+ PX_FORCE_INLINE PxU64 getContextId(Scb::Scene& scene) { return scene.getContextId(); }
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ // Sc-to-Np
+ PX_FORCE_INLINE static NpConstraint* getNpConstraint(Sc::ConstraintCore* scConstraint)
+ {
+ const size_t scOffset = reinterpret_cast<size_t>(&(reinterpret_cast<Scb::Constraint*>(0)->getScConstraint()));
+ const size_t scbOffset = reinterpret_cast<size_t>(&(reinterpret_cast<NpConstraint*>(0)->getScbConstraint()));
+ return reinterpret_cast<NpConstraint*>(reinterpret_cast<char*>(scConstraint) - scOffset - scbOffset);
+ }
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+ // Sc-to-Scb
+ PX_FORCE_INLINE static Scb::ParticleSystem* getScbParticleSystem(Sc::ParticleSystemCore* scParticleSystem)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<Scb::ParticleSystem*>(0)->getScParticleSystem()));
+ return reinterpret_cast<Scb::ParticleSystem*>(reinterpret_cast<char*>(scParticleSystem) - offset);
+ }
+
+#endif
+
+ ///////////////////////////////////////////////////////////////////////////////
+
+ PX_FORCE_INLINE static const PxActor* getPxActor(const Scb::Actor* scbActor)
+ {
+ const PxActorType::Enum type = scbActor->getActorCore().getActorCoreType();
+ if(type == PxActorType::eRIGID_DYNAMIC)
+ {
+ return getNpRigidDynamic(static_cast<const Scb::Body*>(scbActor));
+ }
+ else if(type == PxActorType::eRIGID_STATIC)
+ {
+ return getNpRigidStatic(static_cast<const Scb::RigidStatic*>(scbActor));
+ }
+#if PX_USE_PARTICLE_SYSTEM_API
+ else if(type == PxActorType::ePARTICLE_SYSTEM)
+ {
+ return getNpParticleSystem(static_cast<const Scb::ParticleSystem*>(scbActor));
+ }
+ else if(type == PxActorType::ePARTICLE_FLUID)
+ {
+ return getNpParticleFluid(static_cast<const Scb::ParticleSystem*>(scbActor));
+ }
+#endif
+ else if(type == PxActorType::eARTICULATION_LINK)
+ {
+ return getNpArticulationLink(static_cast<const Scb::Body*>(scbActor));
+ }
+#if PX_USE_CLOTH_API
+ else if(type == PxActorType::eCLOTH)
+ {
+ return getNpCloth(const_cast<Scb::Cloth*>(static_cast<const Scb::Cloth*>(scbActor)));
+ }
+#endif
+
+ return NULL;
+ }
+
+ struct CreateOp
+ {
+ CreateOp& operator=(const CreateOp&);
+ physx::pvdsdk::PvdDataStream& mStream;
+ PvdMetaDataBinding& mBinding;
+ PsPvd* mPvd;
+ PxScene& mScene;
+ CreateOp(physx::pvdsdk::PvdDataStream& str, PvdMetaDataBinding& bind, PsPvd* pvd, PxScene& scene)
+ : mStream(str), mBinding(bind), mPvd(pvd), mScene(scene)
+ {
+ }
+ template <typename TDataType>
+ void operator()(const TDataType& dtype)
+ {
+ mBinding.createInstance(mStream, dtype, mScene, mPvd);
+ }
+ void operator()(const PxArticulationLink&)
+ {
+ }
+#if PX_USE_PARTICLE_SYSTEM_API
+ void operator()(const PxParticleSystem& dtype)
+ {
+ mBinding.createInstance(mStream, dtype, mScene);
+ }
+ void operator()(const PxParticleFluid& dtype)
+ {
+ mBinding.createInstance(mStream, dtype, mScene);
+ }
+#endif
+ };
+
+ struct UpdateOp
+ {
+ UpdateOp& operator=(const UpdateOp&);
+ physx::pvdsdk::PvdDataStream& mStream;
+ PvdMetaDataBinding& mBinding;
+ UpdateOp(physx::pvdsdk::PvdDataStream& str, PvdMetaDataBinding& bind) : mStream(str), mBinding(bind)
+ {
+ }
+ template <typename TDataType>
+ void operator()(const TDataType& dtype)
+ {
+ mBinding.sendAllProperties(mStream, dtype);
+ }
+ };
+
+ struct DestroyOp
+ {
+ DestroyOp& operator=(const DestroyOp&);
+ physx::pvdsdk::PvdDataStream& mStream;
+ PvdMetaDataBinding& mBinding;
+ PxScene& mScene;
+ DestroyOp(physx::pvdsdk::PvdDataStream& str, PvdMetaDataBinding& bind, PxScene& scene)
+ : mStream(str), mBinding(bind), mScene(scene)
+ {
+ }
+ template <typename TDataType>
+ void operator()(const TDataType& dtype)
+ {
+ mBinding.destroyInstance(mStream, dtype, mScene);
+ }
+ void operator()(const PxArticulationLink& dtype)
+ {
+ mBinding.destroyInstance(mStream, dtype);
+ }
+#if PX_USE_PARTICLE_SYSTEM_API
+ void operator()(const PxParticleSystem& dtype)
+ {
+ mBinding.destroyInstance(mStream, dtype, mScene);
+ }
+ void operator()(const PxParticleFluid& dtype)
+ {
+ mBinding.destroyInstance(mStream, dtype, mScene);
+ }
+#endif
+ };
+
+ template <typename TOperator>
+ inline void BodyTypeOperation(const Scb::Body* scbBody, TOperator op)
+ {
+ bool isArticulationLink = scbBody->getActorType() == PxActorType::eARTICULATION_LINK;
+ if(isArticulationLink)
+ {
+ const NpArticulationLink* link = getNpArticulationLink(scbBody);
+ op(*static_cast<const PxArticulationLink*>(link));
+ }
+ else
+ {
+ const NpRigidDynamic* npRigidDynamic = getNpRigidDynamic(scbBody);
+ op(*static_cast<const PxRigidDynamic*>(npRigidDynamic));
+ }
+ }
+
+ template <typename TOperator>
+ inline void ActorTypeOperation(const PxActor* actor, TOperator op)
+ {
+ switch(actor->getType())
+ {
+ case PxActorType::eRIGID_STATIC:
+ op(*static_cast<const PxRigidStatic*>(actor));
+ break;
+ case PxActorType::eRIGID_DYNAMIC:
+ op(*static_cast<const PxRigidDynamic*>(actor));
+ break;
+ case PxActorType::eARTICULATION_LINK:
+ op(*static_cast<const PxArticulationLink*>(actor));
+ break;
+#if PX_USE_PARTICLE_SYSTEM_API
+ case PxActorType::ePARTICLE_SYSTEM:
+ op(*static_cast<const PxParticleSystem*>(actor));
+ break;
+ case PxActorType::ePARTICLE_FLUID:
+ op(*static_cast<const PxParticleFluid*>(actor));
+ break;
+#endif
+#if PX_USE_CLOTH_API
+ case PxActorType::eCLOTH:
+ op(*static_cast<const PxCloth*>(actor));
+ break;
+#endif
+ case PxActorType::eACTOR_COUNT:
+ case PxActorType::eACTOR_FORCE_DWORD:
+ PX_ASSERT(false);
+ break;
+ };
+ }
+
+ namespace
+ {
+ struct PvdConstraintVisualizer : public PxConstraintVisualizer
+ {
+ PX_NOCOPY(PvdConstraintVisualizer)
+ public:
+ physx::pvdsdk::PvdUserRenderer& mRenderer;
+ PvdConstraintVisualizer(const void* id, physx::pvdsdk::PvdUserRenderer& r) : mRenderer(r)
+ {
+ mRenderer.setInstanceId(id);
+ }
+ virtual void visualizeJointFrames(const PxTransform& parent, const PxTransform& child)
+ {
+ mRenderer.visualizeJointFrames(parent, child);
+ }
+
+ virtual void visualizeLinearLimit(const PxTransform& t0, const PxTransform& t1, PxReal value, bool active)
+ {
+ mRenderer.visualizeLinearLimit(t0, t1, PxF32(value), active);
+ }
+
+ virtual void visualizeAngularLimit(const PxTransform& t0, PxReal lower, PxReal upper, bool active)
+ {
+ mRenderer.visualizeAngularLimit(t0, PxF32(lower), PxF32(upper), active);
+ }
+
+ virtual void visualizeLimitCone(const PxTransform& t, PxReal ySwing, PxReal zSwing, bool active)
+ {
+ mRenderer.visualizeLimitCone(t, PxF32(ySwing), PxF32(zSwing), active);
+ }
+
+ virtual void visualizeDoubleCone(const PxTransform& t, PxReal angle, bool active)
+ {
+ mRenderer.visualizeDoubleCone(t, PxF32(angle), active);
+ }
+ };
+ }
+
+ class SceneRendererClient : public RendererEventClient, public physx::shdfnd::UserAllocated
+ {
+ PX_NOCOPY(SceneRendererClient)
+ public:
+ SceneRendererClient(PvdUserRenderer* renderer, PxPvd* pvd):mRenderer(renderer)
+ {
+ mStream = PvdDataStream::create(pvd);
+ mStream->createInstance(renderer);
+ }
+
+ ~SceneRendererClient()
+ {
+ mStream->destroyInstance(mRenderer);
+ mStream->release();
+ }
+
+ virtual void handleBufferFlush(const uint8_t* inData, uint32_t inLength)
+ {
+ mStream->setPropertyValue(mRenderer, "events", inData, inLength);
+ }
+
+ private:
+
+ PvdUserRenderer* mRenderer;
+ PvdDataStream* mStream;
+ };
+
+} // namespace
+
+ScbScenePvdClient::ScbScenePvdClient(Scb::Scene& scene)
+ : mPvd(NULL), mScbScene(scene), mPvdDataStream(NULL), mUserRender(NULL), mRenderClient(NULL), mIsConnected(false)
+{
+}
+
+ScbScenePvdClient::~ScbScenePvdClient()
+{
+ if(mPvd)
+ mPvd->removeClient(this);
+}
+
+void ScbScenePvdClient::updateCamera(const char* name, const PxVec3& origin, const PxVec3& up, const PxVec3& target)
+{
+ if(mIsConnected)
+ mPvdDataStream->updateCamera(name, origin, up, target);
+}
+
+void ScbScenePvdClient::drawPoints(const PvdDebugPoint* points, PxU32 count)
+{
+ if(mUserRender)
+ mUserRender->drawPoints(points, count);
+}
+
+void ScbScenePvdClient::drawLines(const PvdDebugLine* lines, PxU32 count)
+{
+ if(mUserRender)
+ mUserRender->drawLines(lines, count);
+}
+
+void ScbScenePvdClient::drawTriangles(const PvdDebugTriangle* triangles, PxU32 count)
+{
+ if(mUserRender)
+ mUserRender->drawTriangles(triangles, count);
+}
+
+void ScbScenePvdClient::drawText(const PvdDebugText& text)
+{
+ if(mUserRender)
+ mUserRender->drawText(text);
+}
+
+PvdUserRenderer* ScbScenePvdClient::getUserRender()
+{
+ return mUserRender;
+}
+
+
+PsPvd* ScbScenePvdClient::getPsPvd()
+{
+ return mPvd;
+}
+
+void ScbScenePvdClient::setPsPvd(PsPvd* pvd)
+{
+ mPvd = pvd;
+}
+
+physx::pvdsdk::PvdClient* ScbScenePvdClient::getClientInternal()
+{
+ return this;
+}
+
+void ScbScenePvdClient::setScenePvdFlag(PxPvdSceneFlag::Enum flag, bool value)
+{
+ if(value)
+ mFlags |= flag;
+ else
+ mFlags &= ~flag;
+}
+
+void ScbScenePvdClient::setScenePvdFlags(PxPvdSceneFlags flags)
+{
+ mFlags = flags;
+}
+
+PxPvdSceneFlags ScbScenePvdClient::getScenePvdFlags() const
+{
+ return mFlags;
+}
+
+bool ScbScenePvdClient::isConnected() const
+{
+ return mIsConnected;
+}
+
+void ScbScenePvdClient::onPvdConnected()
+{
+ if(mIsConnected || !mPvd)
+ return;
+
+ mIsConnected = true;
+
+
+ mPvdDataStream = PvdDataStream::create(mPvd);
+
+ mUserRender = PvdUserRenderer::create();
+ mRenderClient = PX_NEW(SceneRendererClient)(mUserRender, mPvd);
+ mUserRender->setClient(mRenderClient);
+ sendEntireScene();
+}
+
+void ScbScenePvdClient::onPvdDisconnected()
+{
+ if(!mIsConnected)
+ return;
+ mIsConnected = false;
+
+ PX_DELETE(mRenderClient);
+ mRenderClient = NULL;
+ mUserRender->release();
+ mUserRender = NULL;
+ mPvdDataStream->release();
+ mPvdDataStream = NULL;
+}
+
+void ScbScenePvdClient::flush()
+{
+}
+
+PvdDataStream* ScbScenePvdClient::getDataStream()
+{
+ return mPvdDataStream;
+}
+
+PvdMetaDataBinding* ScbScenePvdClient::getMetaDataBinding()
+{
+ return &mMetaDataBinding;
+}
+
+void ScbScenePvdClient::updatePvdProperties()
+{
+ mMetaDataBinding.sendAllProperties(*mPvdDataStream, *mScbScene.getPxScene());
+}
+
+void ScbScenePvdClient::releasePvdInstance()
+{
+ if(mPvdDataStream)
+ {
+ PxScene* theScene = mScbScene.getPxScene();
+ // remove from parent
+ mPvdDataStream->removeObjectRef(&PxGetPhysics(), "Scenes", theScene);
+ mPvdDataStream->destroyInstance(theScene);
+ }
+}
+
+// PT: this is only called once, from "onPvdConnected"
+void ScbScenePvdClient::sendEntireScene()
+{
+ NpScene* npScene = static_cast<NpScene*>(mScbScene.getPxScene());
+
+ if(npScene->getFlagsFast() & PxSceneFlag::eREQUIRE_RW_LOCK) // getFlagsFast() will trigger a warning of lock check
+ npScene->lockRead(__FILE__, __LINE__);
+
+ {
+ PxScene* theScene = mScbScene.getPxScene();
+ mPvdDataStream->createInstance(theScene);
+ updatePvdProperties();
+
+ PxPhysics* physics = &PxGetPhysics();
+ // Create parent/child relationship.
+ mPvdDataStream->setPropertyValue(theScene, "Physics", reinterpret_cast<const void*>(physics));
+ mPvdDataStream->pushBackObjectRef(physics, "Scenes", theScene);
+ }
+
+ // materials:
+ {
+ PxsMaterialManager& manager = mScbScene.getScScene().getMaterialManager();
+ PxsMaterialManagerIterator iter(manager);
+ PxsMaterialCore* mat;
+ while(iter.getNextMaterial(mat))
+ {
+ const PxMaterial* theMaterial = mat->getNxMaterial();
+ if(mPvd->registerObject(theMaterial))
+ mMetaDataBinding.createInstance(*mPvdDataStream, *theMaterial, PxGetPhysics());
+ };
+ }
+
+ if(mPvd->getInstrumentationFlags() & PxPvdInstrumentationFlag::eDEBUG)
+ {
+ Ps::Array<PxActor*> actorArray;
+
+ // RBs
+ // static:
+ {
+ PxU32 numActors = npScene->getNbActors(PxActorTypeFlag::eRIGID_STATIC | PxActorTypeFlag::eRIGID_DYNAMIC);
+ actorArray.resize(numActors);
+ npScene->getActors(PxActorTypeFlag::eRIGID_STATIC | PxActorTypeFlag::eRIGID_DYNAMIC, actorArray.begin(),
+ actorArray.size());
+ for(PxU32 i = 0; i < numActors; i++)
+ {
+ PxActor* pxActor = actorArray[i];
+ if(pxActor->is<PxRigidStatic>())
+ mMetaDataBinding.createInstance(*mPvdDataStream, *static_cast<PxRigidStatic*>(pxActor), *npScene, mPvd);
+ else
+ mMetaDataBinding.createInstance(*mPvdDataStream, *static_cast<PxRigidDynamic*>(pxActor), *npScene, mPvd);
+ }
+ }
+ // articulations & links
+ {
+ Ps::Array<PxArticulation*> articulations;
+ PxU32 numArticulations = npScene->getNbArticulations();
+ articulations.resize(numArticulations);
+ npScene->getArticulations(articulations.begin(), articulations.size());
+ for(PxU32 i = 0; i < numArticulations; i++)
+ mMetaDataBinding.createInstance(*mPvdDataStream, *articulations[i], *npScene, mPvd);
+ }
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ // particle systems & fluids:
+ {
+ PxU32 nbParticleSystems = mScbScene.getScScene().getNbParticleSystems();
+ Sc::ParticleSystemCore* const* particleSystems = mScbScene.getScScene().getParticleSystems();
+ for(PxU32 i = 0; i < nbParticleSystems; i++)
+ {
+ Sc::ParticleSystemCore* scParticleSystem = particleSystems[i];
+ createPvdInstance(scParticleSystem->getPxParticleBase());
+ }
+ }
+#endif
+
+#if PX_USE_CLOTH_API
+ // cloth
+ {
+ Ps::Array<PxActor*> cloths;
+ PxU32 numActors = npScene->getNbActors(PxActorTypeFlag::eCLOTH);
+ cloths.resize(numActors);
+ npScene->getActors(PxActorTypeFlag::eCLOTH, cloths.begin(), cloths.size());
+ for(PxU32 i = 0; i < numActors; i++)
+ {
+ Scb::Cloth* scbCloth = &static_cast<NpCloth*>(cloths[i])->getScbCloth();
+ createPvdInstance(scbCloth);
+ }
+ }
+#endif
+
+ // joints
+ {
+ Sc::ConstraintCore*const * constraints = mScbScene.getScScene().getConstraints();
+ PxU32 nbConstraints = mScbScene.getScScene().getNbConstraints();
+ for(PxU32 i = 0; i < nbConstraints; i++)
+ {
+ updateConstraint(*constraints[i], PxPvdUpdateType::CREATE_INSTANCE);
+ updateConstraint(*constraints[i], PxPvdUpdateType::UPDATE_ALL_PROPERTIES);
+ }
+ }
+ }
+
+ if(npScene->getFlagsFast() & PxSceneFlag::eREQUIRE_RW_LOCK)
+ npScene->unlockRead();
+}
+
+void ScbScenePvdClient::updateConstraint(const Sc::ConstraintCore& scConstraint, PxU32 updateType)
+{
+ PxConstraintConnector* conn = scConstraint.getPxConnector();
+ if(conn && checkPvdDebugFlag())
+ conn->updatePvdProperties(*mPvdDataStream, scConstraint.getPxConstraint(), PxPvdUpdateType::Enum(updateType));
+}
+
+void ScbScenePvdClient::createPvdInstance(const PxActor* actor)
+{
+ if(checkPvdDebugFlag())
+ ActorTypeOperation(actor, CreateOp(*mPvdDataStream, mMetaDataBinding, mPvd, *mScbScene.getPxScene()));
+}
+
+void ScbScenePvdClient::updatePvdProperties(const PxActor* actor)
+{
+ if(checkPvdDebugFlag())
+ ActorTypeOperation(actor, UpdateOp(*mPvdDataStream, mMetaDataBinding));
+}
+
+void ScbScenePvdClient::releasePvdInstance(const PxActor* actor)
+{
+ if(checkPvdDebugFlag())
+ ActorTypeOperation(actor, DestroyOp(*mPvdDataStream, mMetaDataBinding, *mScbScene.getPxScene()));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::createPvdInstance(const Scb::Actor* actor)
+{
+ // PT: why not UPDATE_PVD_PROPERTIES_CHECK() here?
+ createPvdInstance(getPxActor(actor));
+}
+
+void ScbScenePvdClient::updatePvdProperties(const Scb::Actor* actor)
+{
+ // PT: why not UPDATE_PVD_PROPERTIES_CHECK() here?
+ updatePvdProperties(getPxActor(actor));
+}
+
+void ScbScenePvdClient::releasePvdInstance(const Scb::Actor* actor)
+{
+ // PT: why not UPDATE_PVD_PROPERTIES_CHECK() here?
+ releasePvdInstance(getPxActor(actor));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::createPvdInstance(const Scb::Body* body)
+{
+ if(checkPvdDebugFlag() && body->getActorType() != PxActorType::eARTICULATION_LINK)
+ BodyTypeOperation(body, CreateOp(*mPvdDataStream, mMetaDataBinding, mPvd, *mScbScene.getPxScene()));
+}
+
+void ScbScenePvdClient::updatePvdProperties(const Scb::Body* body)
+{
+ if(checkPvdDebugFlag())
+ BodyTypeOperation(body, UpdateOp(*mPvdDataStream, mMetaDataBinding));
+}
+
+void ScbScenePvdClient::updateKinematicTarget(const Scb::Body* body, const PxTransform& p)
+{
+ if(checkPvdDebugFlag())
+ mPvdDataStream->setPropertyValue(getNpRigidDynamic(body), "KinematicTarget", p);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::createPvdInstance(const Scb::RigidStatic* rigidStatic)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.createInstance(*mPvdDataStream, *getNpRigidStatic(rigidStatic), *mScbScene.getPxScene(), mPvd);
+}
+
+void ScbScenePvdClient::updatePvdProperties(const Scb::RigidStatic* rigidStatic)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendAllProperties(*mPvdDataStream, *getNpRigidStatic(rigidStatic));
+}
+
+void ScbScenePvdClient::releasePvdInstance(const Scb::RigidObject* rigidObject)
+{
+ releasePvdInstance(getPxActor(rigidObject));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::createPvdInstance(const Scb::Constraint* constraint)
+{
+ if(checkPvdDebugFlag())
+ updateConstraint(constraint->getScConstraint(), PxPvdUpdateType::CREATE_INSTANCE);
+}
+
+void ScbScenePvdClient::updatePvdProperties(const Scb::Constraint* constraint)
+{
+ if(checkPvdDebugFlag())
+ updateConstraint(constraint->getScConstraint(), PxPvdUpdateType::UPDATE_ALL_PROPERTIES);
+}
+
+void ScbScenePvdClient::releasePvdInstance(const Scb::Constraint* constraint)
+{
+ const Sc::ConstraintCore& scConstraint = constraint->getScConstraint();
+ PxConstraintConnector* conn;
+ if(checkPvdDebugFlag() && (conn = scConstraint.getPxConnector()) != NULL)
+ conn->updatePvdProperties(*mPvdDataStream, scConstraint.getPxConstraint(), PxPvdUpdateType::RELEASE_INSTANCE);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::createPvdInstance(const Scb::Articulation* articulation)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.createInstance(*mPvdDataStream, *getNpArticulation(articulation), *mScbScene.getPxScene(), mPvd);
+}
+
+void ScbScenePvdClient::updatePvdProperties(const Scb::Articulation* articulation)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendAllProperties(*mPvdDataStream, *getNpArticulation(articulation));
+}
+
+void ScbScenePvdClient::releasePvdInstance(const Scb::Articulation* articulation)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.destroyInstance(*mPvdDataStream, *getNpArticulation(articulation), *mScbScene.getPxScene());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::createPvdInstance(const Scb::ArticulationJoint* articulationJoint)
+{
+ PX_UNUSED(articulationJoint);
+}
+
+void ScbScenePvdClient::updatePvdProperties(const Scb::ArticulationJoint* articulationJoint)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendAllProperties(*mPvdDataStream, *getNpArticulationJoint(articulationJoint));
+}
+
+void ScbScenePvdClient::releasePvdInstance(const Scb::ArticulationJoint* articulationJoint)
+{
+ PX_UNUSED(articulationJoint);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::createPvdInstance(const Sc::MaterialCore* materialCore)
+{
+ if(checkPvdDebugFlag())
+ {
+ const PxMaterial* theMaterial = materialCore->getNxMaterial();
+ if(mPvd->registerObject(theMaterial))
+ mMetaDataBinding.createInstance(*mPvdDataStream, *theMaterial, PxGetPhysics());
+ }
+}
+
+void ScbScenePvdClient::updatePvdProperties(const Sc::MaterialCore* materialCore)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendAllProperties(*mPvdDataStream, *materialCore->getNxMaterial());
+}
+
+void ScbScenePvdClient::releasePvdInstance(const Sc::MaterialCore* materialCore)
+{
+ if(checkPvdDebugFlag() && mPvd->unRegisterObject(materialCore->getNxMaterial() ) )
+ mMetaDataBinding.destroyInstance(*mPvdDataStream, *materialCore->getNxMaterial(), PxGetPhysics());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::createPvdInstance(const Scb::Shape* shape, PxActor& owner)
+{
+ if(checkPvdDebugFlag())
+ {
+ PX_PROFILE_ZONE("PVD.createPVDInstance", getContextId(mScbScene));
+ const PxShape* npShape = getNpShape(shape);
+ mMetaDataBinding.createInstance(*mPvdDataStream, *npShape, static_cast<PxRigidActor&>(owner), mPvd);
+ }
+}
+
+static void addShapesToPvd(PxU32 nbShapes, void* const* shapes, const size_t offset, PxActor& pxActor, PsPvd* pvd, PvdDataStream& stream, PvdMetaDataBinding& binding)
+{
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ const Scb::Shape* shape = reinterpret_cast<Scb::Shape*>(reinterpret_cast<char*>(shapes[i]) + offset);
+ const PxShape* npShape = getNpShape(shape);
+ binding.createInstance(stream, *npShape, static_cast<PxRigidActor&>(pxActor), pvd);
+ }
+}
+
+void ScbScenePvdClient::addBodyAndShapesToPvd(Scb::Body& b)
+{
+ if(checkPvdDebugFlag())
+ {
+ PX_PROFILE_ZONE("PVD.createPVDInstance", getContextId(mScbScene));
+ createPvdInstance(&b);
+
+ const size_t offset = NpShapeGetScPtrOffset() - Scb::Shape::getScOffset();
+ PxActor& pxActor = *b.getScBody().getPxActor();
+
+ void* const* shapes;
+ const PxU32 nbShapes = NpRigidDynamicGetShapes(b, shapes);
+ addShapesToPvd(nbShapes, shapes, offset, pxActor, mPvd, *mPvdDataStream, mMetaDataBinding);
+ }
+}
+
+void ScbScenePvdClient::addStaticAndShapesToPvd(Scb::RigidStatic& s)
+{
+ if(checkPvdDebugFlag())
+ {
+ PX_PROFILE_ZONE("PVD.createPVDInstance", getContextId(mScbScene));
+ createPvdInstance(&s);
+
+ const size_t offset = NpShapeGetScPtrOffset() - Scb::Shape::getScOffset();
+ PxActor& pxActor = *s.getScStatic().getPxActor();
+
+ void* const* shapes;
+ const PxU32 nbShapes = NpRigidStaticGetShapes(s, shapes);
+ addShapesToPvd(nbShapes, shapes, offset, pxActor, mPvd, *mPvdDataStream, mMetaDataBinding);
+ }
+}
+
+void ScbScenePvdClient::updateMaterials(const Scb::Shape* shape)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.updateMaterials(*mPvdDataStream, *getNpShape(const_cast<Scb::Shape*>(shape)), mPvd);
+}
+
+void ScbScenePvdClient::updatePvdProperties(const Scb::Shape* shape)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendAllProperties(*mPvdDataStream, *getNpShape(const_cast<Scb::Shape*>(shape)));
+}
+
+void ScbScenePvdClient::releaseAndRecreateGeometry(const Scb::Shape* shape)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.releaseAndRecreateGeometry(*mPvdDataStream, *getNpShape(const_cast<Scb::Shape*>(shape)),
+ NpPhysics::getInstance(), mPvd);
+}
+
+void ScbScenePvdClient::releasePvdInstance(const Scb::Shape* shape, PxActor& owner)
+{
+ if(checkPvdDebugFlag())
+ {
+ PX_PROFILE_ZONE("PVD.releasePVDInstance", getContextId(mScbScene));
+
+ const NpShape* npShape = getNpShape(shape);
+ mMetaDataBinding.destroyInstance(*mPvdDataStream, *npShape, static_cast<PxRigidActor&>(owner));
+
+ const PxU32 numMaterials = npShape->getNbMaterials();
+ PX_ALLOCA(materialPtr, PxMaterial*, numMaterials);
+ npShape->getMaterials(materialPtr, numMaterials);
+
+ for(PxU32 idx = 0; idx < numMaterials; ++idx)
+ releasePvdInstance(&(static_cast<NpMaterial*>(materialPtr[idx])->getScMaterial()));
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::originShift(PxVec3 shift)
+{
+ mMetaDataBinding.originShift(*mPvdDataStream, mScbScene.getPxScene(), shift);
+}
+
+template <typename TPropertyType>
+void ScbScenePvdClient::sendArray(const void* instance, const char* propName, const Cm::BitMap* bitMap,
+ PxU32 nbValidParticles, PxStrideIterator<const TPropertyType>& iterator)
+{
+ PX_ASSERT(nbValidParticles > 0);
+ if(!iterator.ptr())
+ return;
+
+ // setup the pvd array PxParticleFlags
+ pvdsdk::DataRef<const PxU8> propData;
+ Ps::Array<PxU8> mTempU8Array;
+ mTempU8Array.resize(nbValidParticles * sizeof(TPropertyType));
+ TPropertyType* tmpArray = reinterpret_cast<TPropertyType*>(mTempU8Array.begin());
+ propData = pvdsdk::DataRef<const PxU8>(mTempU8Array.begin(), mTempU8Array.size());
+
+ PxU32 tIdx = 0;
+ Cm::BitMap::Iterator it(*bitMap);
+ for(PxU32 index = it.getNext(); index != Cm::BitMap::Iterator::DONE; index = it.getNext())
+ {
+ tmpArray[tIdx++] = iterator[index];
+ }
+ PX_ASSERT(tIdx == nbValidParticles);
+
+ mPvdDataStream->setPropertyValue(instance, propName, propData,
+ pvdsdk::getPvdNamespacedNameForType<TPropertyType>());
+}
+
+void ScbScenePvdClient::sendStateDatas(Sc::ParticleSystemCore* psCore)
+{
+ PX_UNUSED(psCore);
+#if PX_USE_PARTICLE_SYSTEM_API
+
+ if(!checkPvdDebugFlag())
+ return;
+
+ Scb::ParticleSystem* scbParticleSystem = getScbParticleSystem(psCore);
+ bool doProcess = scbParticleSystem->getFlags() & PxParticleBaseFlag::eENABLED;
+#if PX_SUPPORT_GPU_PHYSX
+ doProcess &= (scbParticleSystem->getDeviceExclusiveAccessGpu() == NULL);
+#endif
+ if(doProcess)
+ {
+ Sc::ParticleSystemSim* particleSystem = psCore->getSim();
+ Pt::ParticleSystemStateDataDesc stateData;
+ particleSystem->getParticleState().getParticlesV(stateData, true, false);
+ Pt::ParticleSystemSimDataDesc simParticleData;
+ particleSystem->getSimParticleData(simParticleData, false);
+
+ const PxActor* pxActor = getPxActor(scbParticleSystem);
+
+ // mPvdDataStream->setPropertyValue( pxActor, "WorldBounds", psCore->getWorldBounds());
+ mPvdDataStream->setPropertyValue(pxActor, "NbParticles", stateData.numParticles);
+ mPvdDataStream->setPropertyValue(pxActor, "ValidParticleRange", stateData.validParticleRange);
+
+ if(stateData.validParticleRange > 0)
+ {
+ mPvdDataStream->setPropertyValue(pxActor, "ValidParticleBitmap", stateData.bitMap->getWords(),
+ (stateData.validParticleRange >> 5) + 1);
+ sendArray<PxVec3>(pxActor, "Positions", stateData.bitMap, stateData.numParticles, stateData.positions);
+ sendArray<PxVec3>(pxActor, "Velocities", stateData.bitMap, stateData.numParticles, stateData.velocities);
+ sendArray<PxF32>(pxActor, "RestOffsets", stateData.bitMap, stateData.numParticles, stateData.restOffsets);
+ sendArray<PxVec3>(pxActor, "CollisionNormals", stateData.bitMap, stateData.numParticles,
+ simParticleData.collisionNormals);
+ sendArray<PxF32>(pxActor, "Densities", stateData.bitMap, stateData.numParticles, simParticleData.densities);
+ // todo: twoway data if need more particle retrieval
+
+ { // send PxParticleFlags, we have Pt::ParticleFlags here
+ pvdsdk::DataRef<const PxU8> propData;
+ Ps::Array<PxU8> mTempU8Array;
+ mTempU8Array.resize(stateData.numParticles * sizeof(PxU16));
+ PxU16* tmpArray = reinterpret_cast<PxU16*>(mTempU8Array.begin());
+ propData = pvdsdk::DataRef<const PxU8>(mTempU8Array.begin(), mTempU8Array.size());
+
+ PxU32 tIdx = 0;
+ PxStrideIterator<const Pt::ParticleFlags>& iterator = stateData.flags;
+ Cm::BitMap::Iterator it(*stateData.bitMap);
+ for(PxU32 index = it.getNext(); index != Cm::BitMap::Iterator::DONE; index = it.getNext())
+ {
+ tmpArray[tIdx++] = iterator[index].api;
+ }
+
+ mPvdDataStream->setPropertyValue(pxActor, "Flags", propData,
+ pvdsdk::getPvdNamespacedNameForType<PxU16>());
+ }
+ }
+ }
+#endif
+}
+
+void ScbScenePvdClient::frameStart(PxReal simulateElapsedTime)
+{
+ PX_PROFILE_ZONE("Basic.pvdFrameStart", mScbScene.getContextId());
+
+ if(!mIsConnected)
+ return;
+
+ mPvdDataStream->flushPvdCommand();
+ mMetaDataBinding.sendBeginFrame(*mPvdDataStream, mScbScene.getPxScene(), simulateElapsedTime);
+}
+
+void ScbScenePvdClient::frameEnd()
+{
+ PX_PROFILE_ZONE("Basic.pvdFrameEnd", mScbScene.getContextId());
+
+ if(!mIsConnected)
+ {
+ if(mPvd)
+ mPvd->flush(); // Even if we aren't connected, we may need to flush buffered events.
+ return;
+ }
+
+ PxScene* theScene = mScbScene.getPxScene();
+
+ // Send the statistics for last frame.
+ void* tmp = NULL;
+#if PX_SUPPORT_GPU_PHYSX
+ if(mScbScene.getScScene().getSceneGpu())
+ {
+ NpPhysics& npPhysics = static_cast<NpPhysics&>(theScene->getPhysics());
+ PxTriangleMeshCacheStatistics triMeshCacheStats =
+ npPhysics.getNpPhysicsGpu().getTriangleMeshCacheStatistics(*theScene);
+ tmp = &triMeshCacheStats;
+ }
+#endif
+ mMetaDataBinding.sendStats(*mPvdDataStream, theScene, tmp);
+
+ if(mPvd->getInstrumentationFlags() & PxPvdInstrumentationFlag::eDEBUG)
+ {
+#if PX_USE_PARTICLE_SYSTEM_API
+ // particle systems & fluids:
+ {
+ PX_PROFILE_ZONE("PVD.updatePariclesAndFluids", getContextId(mScbScene));
+ PxU32 nbParticleSystems = mScbScene.getScScene().getNbParticleSystems();
+ Sc::ParticleSystemCore* const* particleSystems = mScbScene.getScScene().getParticleSystems();
+ for(PxU32 i = 0; i < nbParticleSystems; i++)
+ {
+ sendStateDatas(particleSystems[i]);
+ }
+ }
+#endif
+
+#if PX_USE_CLOTH_API
+ {
+ PX_PROFILE_ZONE("PVD.updateCloths", getContextId(mScbScene));
+ mMetaDataBinding.updateCloths(*mPvdDataStream, *theScene);
+ }
+#endif
+ }
+
+ // flush our data to the main connection
+ mPvd->flush();
+
+ // End the frame *before* we send the dynamic object current data.
+ // This ensures that contacts end up synced with the rest of the system.
+ // Note that contacts were sent much earler in NpScene::fetchResults.
+ mMetaDataBinding.sendEndFrame(*mPvdDataStream, mScbScene.getPxScene());
+
+ if(mPvd->getInstrumentationFlags() & PxPvdInstrumentationFlag::eDEBUG)
+ {
+ PvdVisualizer* vizualizer = NULL;
+ const bool visualizeJoints = getScenePvdFlags() & PxPvdSceneFlag::eTRANSMIT_CONSTRAINTS;
+ if(visualizeJoints)
+ vizualizer = this;
+
+ PX_PROFILE_ZONE("PVD.sceneUpdate", getContextId(mScbScene));
+ mMetaDataBinding.updateDynamicActorsAndArticulations(*mPvdDataStream, theScene, vizualizer);
+ }
+
+ // frame end moved to update contacts to have them in the previous frame.
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::createPvdInstance(const Scb::Aggregate* aggregate)
+{
+ if(checkPvdDebugFlag())
+ {
+ PX_PROFILE_ZONE("PVD.createPVDInstance", getContextId(mScbScene));
+ const NpAggregate* npAggregate = getNpAggregate(aggregate);
+ mMetaDataBinding.createInstance(*mPvdDataStream, *npAggregate, *mScbScene.getPxScene());
+ }
+}
+
+void ScbScenePvdClient::updatePvdProperties(const Scb::Aggregate* aggregate)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendAllProperties(*mPvdDataStream, *getNpAggregate(aggregate));
+}
+
+void ScbScenePvdClient::attachAggregateActor(const Scb::Aggregate* aggregate, Scb::Actor* actor)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.attachAggregateActor(*mPvdDataStream, *getNpAggregate(aggregate), *getPxActor(actor));
+}
+
+void ScbScenePvdClient::detachAggregateActor(const Scb::Aggregate* aggregate, Scb::Actor* actor)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.detachAggregateActor(*mPvdDataStream, *getNpAggregate(aggregate), *getPxActor(actor));
+}
+
+void ScbScenePvdClient::releasePvdInstance(const Scb::Aggregate* aggregate)
+{
+ if(checkPvdDebugFlag())
+ {
+ PX_PROFILE_ZONE("PVD.releasePVDInstance", getContextId(mScbScene));
+ const NpAggregate* npAggregate = getNpAggregate(aggregate);
+ mMetaDataBinding.destroyInstance(*mPvdDataStream, *npAggregate, *mScbScene.getPxScene());
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_USE_CLOTH_API
+static inline const PxCloth* toPx(const Scb::Cloth* cloth)
+{
+ const NpCloth* realCloth = getNpCloth(cloth);
+ return static_cast<const PxCloth*>(realCloth);
+}
+
+void ScbScenePvdClient::createPvdInstance(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.createInstance(*mPvdDataStream, *getNpCloth(cloth), *mScbScene.getPxScene(), mPvd);
+}
+
+void ScbScenePvdClient::sendSimpleProperties(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendSimpleProperties(*mPvdDataStream, *toPx(cloth));
+}
+
+void ScbScenePvdClient::sendMotionConstraints(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendMotionConstraints(*mPvdDataStream, *toPx(cloth));
+}
+
+void ScbScenePvdClient::sendSelfCollisionIndices(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendSelfCollisionIndices(*mPvdDataStream, *toPx(cloth));
+}
+
+void ScbScenePvdClient::sendRestPositions(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendRestPositions(*mPvdDataStream, *toPx(cloth));
+}
+
+void ScbScenePvdClient::sendSeparationConstraints(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendSeparationConstraints(*mPvdDataStream, *toPx(cloth));
+}
+
+void ScbScenePvdClient::sendCollisionSpheres(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendCollisionSpheres(*mPvdDataStream, *toPx(cloth));
+}
+
+void ScbScenePvdClient::sendCollisionCapsules(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendCollisionSpheres(*mPvdDataStream, *toPx(cloth), true);
+}
+
+void ScbScenePvdClient::sendCollisionTriangles(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendCollisionTriangles(*mPvdDataStream, *toPx(cloth));
+}
+
+void ScbScenePvdClient::sendParticleAccelerations(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendParticleAccelerations(*mPvdDataStream, *toPx(cloth));
+}
+
+void ScbScenePvdClient::sendVirtualParticles(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.sendVirtualParticles(*mPvdDataStream, *toPx(cloth));
+}
+
+void ScbScenePvdClient::releasePvdInstance(const Scb::Cloth* cloth)
+{
+ if(checkPvdDebugFlag())
+ mMetaDataBinding.destroyInstance(*mPvdDataStream, *toPx(cloth), *mScbScene.getPxScene());
+}
+#endif // PX_USE_CLOTH_API
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ScbScenePvdClient::updateJoints()
+{
+ if(checkPvdDebugFlag())
+ {
+ const bool visualizeJoints = getScenePvdFlags() & PxPvdSceneFlag::eTRANSMIT_CONTACTS;
+
+ // joints
+ {
+ PX_PROFILE_ZONE("PVD.updateJoints", getContextId(mScbScene));
+ Sc::ConstraintCore*const * constraints = mScbScene.getScScene().getConstraints();
+ PxU32 nbConstraints = mScbScene.getScScene().getNbConstraints();
+ PxI64 constraintCount = 0;
+
+ for(PxU32 i = 0; i < nbConstraints; i++)
+ {
+ Sc::ConstraintCore* constraint = constraints[i];
+ PxPvdUpdateType::Enum updateType = getNpConstraint(constraint)->isDirty()
+ ? PxPvdUpdateType::UPDATE_ALL_PROPERTIES
+ : PxPvdUpdateType::UPDATE_SIM_PROPERTIES;
+ updateConstraint(*constraint, updateType);
+ PxConstraintConnector* conn = constraint->getPxConnector();
+ // visualization is updated here
+ {
+ PxU32 typeId = 0;
+ void* joint = NULL;
+ if(conn)
+ joint = conn->getExternalReference(typeId);
+ // visualize:
+ Sc::ConstraintSim* sim = constraint->getSim();
+ if(visualizeJoints && sim && sim->getConstantsLL() && joint && constraint->getVisualize())
+ {
+ Sc::BodySim* b0 = sim->getBody(0);
+ Sc::BodySim* b1 = sim->getBody(1);
+ PxTransform t0 = b0 ? b0->getBody2World() : PxTransform(PxIdentity);
+ PxTransform t1 = b1 ? b1->getBody2World() : PxTransform(PxIdentity);
+ PvdConstraintVisualizer viz(joint, *mUserRender);
+ (*constraint->getVisualize())(viz, sim->getConstantsLL(), t0, t1, 0xffffFFFF);
+ }
+ }
+ ++constraintCount;
+ }
+
+ mUserRender->flushRenderEvents();
+ }
+ }
+}
+
+void ScbScenePvdClient::updateContacts()
+{
+ if(!checkPvdDebugFlag())
+ return;
+
+ // if contacts are disabled, send empty array and return
+ const PxScene* theScene(mScbScene.getPxScene());
+ if(!(getScenePvdFlags() & PxPvdSceneFlag::eTRANSMIT_CONTACTS))
+ {
+ mMetaDataBinding.sendContacts(*mPvdDataStream, *theScene);
+ return;
+ }
+
+ PX_PROFILE_ZONE("PVD.updateContacts", getContextId(mScbScene));
+
+ PxsContactManagerOutputIterator outputIter;
+
+ Sc::ContactIterator contactIter;
+ mScbScene.getScScene().initContactsIterator(contactIter, outputIter);
+ Sc::ContactIterator::Pair* pair;
+ Sc::Contact* contact;
+ Ps::Array<Sc::Contact> contacts;
+ while ((pair = contactIter.getNextPair()) != NULL)
+ {
+ while ((contact = pair->getNextContact()) != NULL)
+ contacts.pushBack(*contact);
+ }
+
+ mMetaDataBinding.sendContacts(*mPvdDataStream, *theScene, contacts);
+}
+
+
+void ScbScenePvdClient::updateSceneQueries()
+{
+ // if contacts are disabled, send empty array and return
+ if(checkPvdDebugFlag() && (getScenePvdFlags() & PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES))
+ mMetaDataBinding.sendSceneQueries(*mPvdDataStream, *mScbScene.getPxScene(), mPvd);
+}
+
+void ScbScenePvdClient::setCreateContactReports(bool b)
+{
+ mScbScene.getScScene().setCreateContactReports(b);
+}
+
+void ScbScenePvdClient::visualize(PxArticulationLink& link)
+{
+ NpArticulationLink& npLink = static_cast<NpArticulationLink&>(link);
+ const void* itemId = npLink.getInboundJoint();
+ if(itemId && mUserRender)
+ {
+ PvdConstraintVisualizer viz(itemId, *mUserRender);
+ npLink.visualizeJoint(viz);
+ }
+}
+
+void ScbScenePvdClient::visualize(const PxRenderBuffer& debugRenderable)
+{
+ if(mUserRender)
+ {
+ mUserRender->drawRenderbuffer(reinterpret_cast<const PvdDebugPoint*>(debugRenderable.getPoints()), debugRenderable.getNbPoints(),
+ reinterpret_cast<const PvdDebugLine*>(debugRenderable.getLines()), debugRenderable.getNbLines(),
+ reinterpret_cast<const PvdDebugTriangle*>(debugRenderable.getTriangles()), debugRenderable.getNbTriangles());
+ mUserRender->flushRenderEvents();
+ }
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbScenePvdClient.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbScenePvdClient.h
new file mode 100644
index 00000000..a7461571
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbScenePvdClient.h
@@ -0,0 +1,223 @@
+// 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 SCB_SCENE_PVD_CLIENT_H
+#define SCB_SCENE_PVD_CLIENT_H
+
+#include "PxPhysXConfig.h"
+
+#if PX_SUPPORT_PVD
+
+#include "foundation/PxStrideIterator.h"
+#include "pvd/PxPvdTransport.h"
+
+#include "PxPvdSceneClient.h"
+#include "PvdMetaDataPvdBinding.h"
+
+#include "CmBitMap.h"
+
+#include "PxPvdClient.h"
+#include "PxPvdUserRenderer.h"
+#include "PsPvd.h"
+
+namespace physx
+{
+class PxScene;
+class PxActor;
+class PxShape;
+class PxGeometryHolder;
+class PxArticulationLink;
+class PxRenderBuffer;
+
+namespace Scb
+{
+class Scene;
+class Actor;
+class Body;
+class RigidStatic;
+class RigidObject;
+class Shape;
+class ParticleSystem;
+class Constraint;
+class Articulation;
+class ArticulationJoint;
+class Cloth;
+class Aggregate;
+}
+
+namespace Sc
+{
+class MaterialCore;
+class ConstraintCore;
+class ParticleSystemCore;
+}
+
+namespace Vd
+{
+
+class ScbScenePvdClient : public PxPvdSceneClient, public PvdClient, public PvdVisualizer
+{
+ PX_NOCOPY(ScbScenePvdClient)
+ public:
+ ScbScenePvdClient(Scb::Scene& scene);
+ virtual ~ScbScenePvdClient();
+
+ // PxPvdSceneClient
+ virtual void setScenePvdFlag(PxPvdSceneFlag::Enum flag, bool value);
+ virtual void setScenePvdFlags(PxPvdSceneFlags flags);
+ virtual PxPvdSceneFlags getScenePvdFlags() const;
+ virtual void updateCamera(const char* name, const PxVec3& origin, const PxVec3& up, const PxVec3& target);
+ virtual void drawPoints(const PvdDebugPoint* points, PxU32 count);
+ virtual void drawLines(const PvdDebugLine* lines, PxU32 count);
+ virtual void drawTriangles(const PvdDebugTriangle* triangles, PxU32 count);
+ virtual void drawText(const PvdDebugText& text);
+ virtual PvdClient* getClientInternal();
+ //~PxPvdSceneClient
+
+ // pvdClient
+ virtual PvdDataStream* getDataStream();
+ virtual PvdMetaDataBinding* getMetaDataBinding();
+ virtual PvdUserRenderer* getUserRender();
+ virtual bool isConnected() const ;
+ virtual void onPvdConnected();
+ virtual void onPvdDisconnected();
+ virtual void flush();
+ //~pvdClient
+
+ PsPvd* getPsPvd();
+ void setPsPvd(PsPvd* pvd);
+
+ PX_INLINE bool checkPvdDebugFlag()
+ {
+ return mIsConnected && (mPvd->getInstrumentationFlags() & PxPvdInstrumentationFlag::eDEBUG);
+ }
+
+ void frameStart(PxReal simulateElapsedTime);
+ void frameEnd();
+
+ void updatePvdProperties();
+ void releasePvdInstance();
+
+ void createPvdInstance (const PxActor* actor); // temporary for deformables and particle systems
+ void updatePvdProperties(const PxActor* actor);
+ void releasePvdInstance (const PxActor* actor); // temporary for deformables and particle systems
+
+ void createPvdInstance (const Scb::Actor* actor); // temporary for deformables and particle systems
+ void updatePvdProperties(const Scb::Actor* actor);
+ void releasePvdInstance (const Scb::Actor* actor); // temporary for deformables and particle systems
+
+ void createPvdInstance (const Scb::Body* body);
+ void updatePvdProperties (const Scb::Body* body);
+ void updateKinematicTarget (const Scb::Body* body, const PxTransform& p);
+
+ void createPvdInstance (const Scb::RigidStatic* rigidStatic);
+ void updatePvdProperties (const Scb::RigidStatic* rigidStatic);
+
+ void releasePvdInstance (const Scb::RigidObject* rigidObject);
+
+ void createPvdInstance (const Scb::Constraint* constraint);
+ void updatePvdProperties(const Scb::Constraint* constraint);
+ void releasePvdInstance (const Scb::Constraint* constraint);
+
+ void createPvdInstance (const Scb::Articulation* articulation);
+ void updatePvdProperties(const Scb::Articulation* articulation);
+ void releasePvdInstance (const Scb::Articulation* articulation);
+
+ void createPvdInstance (const Scb::ArticulationJoint* articulationJoint);
+ void updatePvdProperties(const Scb::ArticulationJoint* articulationJoint);
+ void releasePvdInstance (const Scb::ArticulationJoint* articulationJoint);
+
+ void createPvdInstance (const Sc::MaterialCore* materialCore);
+ void updatePvdProperties(const Sc::MaterialCore* materialCore);
+ void releasePvdInstance (const Sc::MaterialCore* materialCore);
+
+ void createPvdInstance (const Scb::Shape* shape, PxActor& owner);
+ void updateMaterials (const Scb::Shape* shape);
+ void updatePvdProperties (const Scb::Shape* shape);
+ void releaseAndRecreateGeometry (const Scb::Shape* shape);
+ void releasePvdInstance (const Scb::Shape* shape, PxActor& owner);
+ void addBodyAndShapesToPvd (Scb::Body& b);
+ void addStaticAndShapesToPvd (Scb::RigidStatic& s);
+
+ void createPvdInstance (const Scb::Aggregate* aggregate);
+ void updatePvdProperties (const Scb::Aggregate* aggregate);
+ void attachAggregateActor (const Scb::Aggregate* aggregate, Scb::Actor* actor);
+ void detachAggregateActor (const Scb::Aggregate* aggregate, Scb::Actor* actor);
+ void releasePvdInstance (const Scb::Aggregate* aggregate);
+
+ void createPvdInstance (const Scb::Cloth* cloth);
+ void sendSimpleProperties (const Scb::Cloth* cloth);
+ void sendMotionConstraints (const Scb::Cloth* cloth);
+ void sendCollisionSpheres (const Scb::Cloth* cloth);
+ void sendCollisionCapsules (const Scb::Cloth* cloth);
+ void sendCollisionTriangles (const Scb::Cloth* cloth);
+ void sendVirtualParticles (const Scb::Cloth* cloth);
+ void sendSeparationConstraints (const Scb::Cloth* cloth);
+ void sendParticleAccelerations (const Scb::Cloth* cloth);
+ void sendSelfCollisionIndices (const Scb::Cloth* cloth);
+ void sendRestPositions (const Scb::Cloth* cloth);
+ void releasePvdInstance (const Scb::Cloth* cloth);
+
+ void originShift(PxVec3 shift);
+ void updateJoints();
+ void updateContacts();
+ void updateSceneQueries();
+
+ // PvdVisualizer
+ void visualize(PxArticulationLink& link);
+ void visualize(const PxRenderBuffer& debugRenderable);
+
+ private:
+
+ template <typename TPropertyType>
+ void sendArray( const void* instance, const char* propName, const Cm::BitMap* bitMap, PxU32 nbValidParticles,
+ PxStrideIterator<const TPropertyType>& iterator);
+
+ void sendStateDatas(Sc::ParticleSystemCore* psCore);
+ void sendEntireScene();
+ void updateConstraint(const Sc::ConstraintCore& scConstraint, PxU32 updateType);
+ void setCreateContactReports(bool b);
+
+ PxPvdSceneFlags mFlags;
+ PsPvd* mPvd;
+ Scb::Scene& mScbScene;
+
+ PvdDataStream* mPvdDataStream;
+ PvdMetaDataBinding mMetaDataBinding;
+ PvdUserRenderer* mUserRender;
+ RendererEventClient* mRenderClient;
+ bool mIsConnected;
+};
+
+} // pvd
+
+} // physx
+#endif // PX_SUPPORT_PVD
+
+#endif // SCB_SCENE_PVD_CLIENT_H
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbShape.cpp b/PhysX_3.4/Source/PhysX/src/buffering/ScbShape.cpp
new file mode 100644
index 00000000..59f07169
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbShape.cpp
@@ -0,0 +1,146 @@
+// 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 "ScbShape.h"
+
+using namespace physx;
+
+bool Scb::Shape::setMaterialsHelper(PxMaterial* const* materials, PxU16 materialCount)
+{
+ PX_ASSERT(!isBuffering());
+
+ if (materialCount == 1)
+ {
+ PxU16 materialIndex = Ps::to16((static_cast<NpMaterial*>(materials[0]))->getHandle());
+
+ mShape.setMaterialIndices(&materialIndex, 1);
+ }
+ else
+ {
+ PX_ASSERT(materialCount > 1);
+
+ PX_ALLOCA(materialIndices, PxU16, materialCount);
+
+ if (materialIndices)
+ {
+ NpMaterial::getMaterialIndices(materials, materialIndices, materialCount);
+ mShape.setMaterialIndices(materialIndices, materialCount);
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eOUT_OF_MEMORY, __FILE__, __LINE__,
+ "PxShape::setMaterials() failed. Out of memory. Call will be ignored.");
+ return false;
+ }
+ }
+
+ Scb::Scene* sc = getScbScene();
+
+ if (sc)
+ {
+ sc->getScScene().notifyNphaseOnUpdateShapeMaterial(mShape);
+ }
+
+ return true;
+}
+
+
+void Scb::Shape::syncState()
+{
+ PxU32 flags = getBufferFlags();
+ if (flags)
+ {
+
+ PxShapeFlags oldShapeFlags = mShape.getFlags();
+
+ const Scb::ShapeBuffer& buffer = *getBufferedData();
+
+ if (flags & Buf::BF_Geometry)
+ {
+ Scb::Scene* sc = getScbScene();
+
+ if (sc)
+ {
+ sc->getScScene().unregisterShapeFromNphase(mShape);
+ }
+
+ mShape.setGeometry(buffer.geometry.getGeometry());
+
+ if (sc)
+ {
+ sc->getScScene().registerShapeInNphase(mShape);
+ }
+
+#if PX_SUPPORT_PVD
+ if(getControlState() == ControlState::eIN_SCENE)
+ {
+ Scb::Scene* scbScene = getScbScene();
+ PX_ASSERT(scbScene);
+ scbScene->getScenePvdClient().releaseAndRecreateGeometry(this);
+ }
+#endif
+ }
+
+ if (flags & Buf::BF_Material)
+ {
+ const PxU16* materialIndices = getMaterialBuffer(*getScbScene(), buffer);
+ mShape.setMaterialIndices(materialIndices, buffer.materialCount);
+ getScbScene()->getScScene().notifyNphaseOnUpdateShapeMaterial(mShape);
+ UPDATE_PVD_MATERIALS()
+ // TODO: So far we did not bother to fail gracefully in the case of running out of memory. If that should change then this
+ // method is somewhat problematic. The material ref counters have been adjusted at the time when the public API was called.
+ // Could be that one of the old materials was deleted afterwards. The problem now is what to do if this method fails?
+ // We can't adjust the material ref counts any longer since some of the old materials might have been deleted.
+ // One solution could be that this class allocates an array of material pointers when the buffered method is called.
+ // This array is then passed into the core object and is used by the core object, i.e., the core object does not allocate the
+ // buffer itself.
+ }
+
+ flush<Buf::BF_Shape2Actor>(buffer);
+ flush<Buf::BF_SimulationFilterData>(buffer);
+
+ if(isBuffered(Buf::BF_ContactOffset))
+ {
+ mShape.setContactOffset(buffer.mContactOffset);
+ }
+
+ flush<Buf::BF_RestOffset>(buffer);
+ flush<Buf::BF_Flags>(buffer);
+
+ Sc::RigidCore* scRigidCore = NpShapeGetScRigidObjectFromScbSLOW(*this);
+
+ if (scRigidCore) // may be NULL for exclusive shapes because of pending shape updates after buffered release of actor.
+ {
+ scRigidCore->onShapeChange(mShape, Sc::ShapeChangeNotifyFlags(flags), oldShapeFlags, true);
+ }
+ }
+
+ postSyncState();
+}
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbShape.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbShape.h
new file mode 100644
index 00000000..697017bf
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbShape.h
@@ -0,0 +1,452 @@
+// 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_SCB_SHAPE
+#define PX_PHYSICS_SCB_SHAPE
+
+#include "NpMaterial.h"
+#include "NpPhysics.h"
+#include "ScbNpDeps.h"
+#include "ScShapeCore.h"
+#include "ScRigidCore.h"
+
+#include "PsUtilities.h"
+
+// PX_SERIALIZATION
+#include "PxSerialFramework.h"
+//~PX_SERIALIZATION
+
+#include "ScbDefs.h"
+
+namespace physx
+{
+
+#if PX_SUPPORT_PVD
+ #define UPDATE_PVD_MATERIALS() \
+ if(getControlState() == ControlState::eIN_SCENE) \
+ { \
+ getScbScene()->getScenePvdClient().updateMaterials(this); \
+ }
+#else
+ #define UPDATE_PVD_MATERIALS() {}
+#endif
+
+namespace Scb
+{
+
+class RigidObject;
+
+struct ShapeBuffer
+{
+ template <PxU32 I, PxU32 dummy> struct Fns {}; // TODO: make the base class traits visible
+ typedef Sc::ShapeCore Core;
+ typedef ShapeBuffer Buf;
+
+ ShapeBuffer() : materialBufferIndex(0), materialCount(0) {}
+
+ SCB_REGULAR_ATTRIBUTE_ALIGNED(2, PxTransform, Shape2Actor, 16)
+ SCB_REGULAR_ATTRIBUTE(3, PxFilterData, SimulationFilterData)
+ SCB_REGULAR_ATTRIBUTE(4, PxReal, ContactOffset)
+ SCB_REGULAR_ATTRIBUTE(5, PxReal, RestOffset)
+ SCB_REGULAR_ATTRIBUTE(6, PxShapeFlags, Flags)
+
+ Gu::GeometryUnion geometry;
+
+ union
+ {
+ PxU16 materialIndex; // for single material shapes
+ PxU32 materialBufferIndex; // for multi material shapes
+ };
+ PxU16 materialCount;
+
+ enum
+ {
+ BF_Geometry = 1<<0,
+ BF_Material = 1<<1
+ };
+
+};
+
+class Shape : public Base
+{
+//= ATTENTION! =====================================================================================
+// Changing the data layout of this class breaks the binary serialization format. See comments for
+// PX_BINARY_SERIAL_VERSION. If a modification is required, please adjust the getBinaryMetaData
+// function. If the modification is made on a custom branch, please change PX_BINARY_SERIAL_VERSION
+// accordingly.
+//==================================================================================================
+
+ typedef Sc::ShapeCore Core;
+ typedef ShapeBuffer Buf;
+public:
+// PX_SERIALIZATION
+ Shape(const PxEMPTY) : Base(PxEmpty), mShape(PxEmpty) {}
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+
+ PX_INLINE Shape(const PxGeometry& geometry,
+ PxShapeFlags shapeFlags,
+ const PxU16* materialIndices,
+ PxU16 materialCount,
+ bool isExclusive);
+
+ PX_INLINE PxGeometryType::Enum getGeometryType() const;
+
+ PX_INLINE const PxGeometry& getGeometry() const;
+ PX_INLINE const Gu::GeometryUnion&getGeometryUnion() const;
+ PX_INLINE Scb::ShapeBuffer* setGeometry(const PxGeometry& geom);
+
+ PX_INLINE PxU16 getNbMaterials() const;
+ PX_INLINE PxMaterial* getMaterial(PxU32 index) const;
+ PX_INLINE PxU32 getMaterials(PxMaterial** buffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+ PX_INLINE bool setMaterials(PxMaterial*const* materials, PxU16 materialCount);
+
+ PX_INLINE const PxTransform& getShape2Actor() const { return read<Buf::BF_Shape2Actor>(); }
+ PX_INLINE void setShape2Actor(const PxTransform& v) { write<Buf::BF_Shape2Actor>(v); }
+
+ PX_INLINE PxFilterData getSimulationFilterData() const { return read<Buf::BF_SimulationFilterData>(); }
+ PX_INLINE void setSimulationFilterData(const PxFilterData& v) { write<Buf::BF_SimulationFilterData>(v); }
+
+ PX_INLINE PxReal getContactOffset() const { return read<Buf::BF_ContactOffset>(); }
+ PX_INLINE void setContactOffset(PxReal v);
+
+ PX_INLINE PxReal getRestOffset() const { return read<Buf::BF_RestOffset>(); }
+ PX_INLINE void setRestOffset(PxReal v) { write<Buf::BF_RestOffset>(v); }
+
+ PX_INLINE PxShapeFlags getFlags() const { return read<Buf::BF_Flags>(); }
+ PX_INLINE void setFlags(PxShapeFlags v) { write<Buf::BF_Flags>(v); }
+
+
+ //---------------------------------------------------------------------------------
+ // Data synchronization
+ //---------------------------------------------------------------------------------
+ void syncState();
+
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ PX_FORCE_INLINE const PxU16* getScMaterialIndices() const { return mShape.getMaterialIndices(); } // Only use if you know what you're doing!
+
+ PX_FORCE_INLINE Sc::ShapeCore& getScShape() { return mShape; } // Only use if you know what you're doing!
+ PX_FORCE_INLINE const Sc::ShapeCore& getScShape() const { return mShape; }
+
+ PX_FORCE_INLINE bool isExclusive() const { return getScbType() == ScbType::SHAPE_EXCLUSIVE; }
+ PX_FORCE_INLINE void setControlStateIfExclusive(Scene* s, ControlState::Enum cs); // for exclusive shapes
+
+ template<bool sync> PX_FORCE_INLINE void checkUpdateOnRemove(Scene* s);
+
+ static size_t getScOffset()
+ {
+ return reinterpret_cast<size_t>(&reinterpret_cast<Shape*>(0)->mShape);
+ }
+
+private:
+ bool setMaterialsHelper(PxMaterial* const* materials, PxU16 materialCount);
+
+ Sc::ShapeCore mShape;
+
+ PX_FORCE_INLINE const Scb::ShapeBuffer* getBufferedData() const { return reinterpret_cast<const Scb::ShapeBuffer*>(getStream()); }
+ PX_FORCE_INLINE Scb::ShapeBuffer* getBufferedData() { return reinterpret_cast<Scb::ShapeBuffer*>(getStream()); }
+
+
+ PX_FORCE_INLINE const PxU16* getMaterialBuffer(const Scb::Scene& scene, const Scb::ShapeBuffer& sb) const
+ {
+ if (sb.materialCount == 1)
+ return &sb.materialIndex;
+ else
+ return scene.getShapeMaterialBuffer(sb.materialBufferIndex);
+ }
+
+ //---------------------------------------------------------------------------------
+ // Infrastructure for regular attributes
+ //---------------------------------------------------------------------------------
+
+ struct Access: public BufferedAccess<Buf, Core, Shape>
+ {
+ template<typename Fns>
+ static PX_FORCE_INLINE void write(Shape& base, Core& core, typename Fns::Arg v)
+ {
+ if (!base.isBuffering())
+ {
+ PxShapeFlags oldShapeFlags = core.getFlags();
+ Fns::setCore(core, v);
+
+ // shared shapes return NULL. But shared shapes aren't mutable when attached to an actor, so no notification needed.
+ Sc::RigidCore* rigidCore = NpShapeGetScRigidObjectFromScbSLOW(base);
+ if(rigidCore && base.getControlState() != ControlState::eINSERT_PENDING)
+ rigidCore->onShapeChange(core, Sc::ShapeChangeNotifyFlags(Fns::flag), oldShapeFlags);
+#if PX_SUPPORT_PVD
+ Scb::Scene* scene = base.getScbSceneForAPI(); // shared shapes also return zero here
+ if(scene && !base.insertPending())
+ scene->getScenePvdClient().updatePvdProperties(&base);
+#endif
+ }
+ else
+ {
+ Fns::setBuffered(*reinterpret_cast<Buf*>(base.getStream()), v);
+ base.markUpdated(Fns::flag);
+ }
+ }
+
+ };
+ template<PxU32 f> PX_FORCE_INLINE typename Buf::Fns<f,0>::Arg read() const { return Access::read<Buf::Fns<f,0> >(*this, mShape); }
+ template<PxU32 f> PX_FORCE_INLINE void write(typename Buf::Fns<f,0>::Arg v) { Access::write<Buf::Fns<f,0> >(*this, mShape, v); }
+ template<PxU32 f> PX_FORCE_INLINE void flush(const Buf& buf) { Access::flush<Buf::Fns<f,0> >(*this, mShape, buf); }
+
+};
+
+
+PX_INLINE Shape::Shape(const PxGeometry& geometry,
+ PxShapeFlags shapeFlags,
+ const PxU16* materialIndices,
+ PxU16 materialCount,
+ bool isExclusive) :
+ mShape(geometry, shapeFlags, materialIndices, materialCount)
+{
+ // paranoia: the notify flags in Sc have to match up
+
+ PX_COMPILE_TIME_ASSERT(PxU32(ShapeBuffer::BF_Geometry) == PxU32(Sc::ShapeChangeNotifyFlag::eGEOMETRY));
+ PX_COMPILE_TIME_ASSERT(PxU32(ShapeBuffer::BF_Material) == PxU32(Sc::ShapeChangeNotifyFlag::eMATERIAL));
+ PX_COMPILE_TIME_ASSERT(PxU32(ShapeBuffer::BF_Shape2Actor) == PxU32(Sc::ShapeChangeNotifyFlag::eSHAPE2BODY));
+ PX_COMPILE_TIME_ASSERT(PxU32(ShapeBuffer::BF_SimulationFilterData) == PxU32(Sc::ShapeChangeNotifyFlag::eFILTERDATA));
+ PX_COMPILE_TIME_ASSERT(PxU32(ShapeBuffer::BF_ContactOffset) == PxU32(Sc::ShapeChangeNotifyFlag::eCONTACTOFFSET));
+ PX_COMPILE_TIME_ASSERT(PxU32(ShapeBuffer::BF_RestOffset) == PxU32(Sc::ShapeChangeNotifyFlag::eRESTOFFSET));
+ PX_COMPILE_TIME_ASSERT(PxU32(ShapeBuffer::BF_Flags) == PxU32(Sc::ShapeChangeNotifyFlag::eFLAGS));
+ PX_COMPILE_TIME_ASSERT(PxU32(ShapeBuffer::BF_Geometry) == PxU32(Sc::ShapeChangeNotifyFlag::eGEOMETRY));
+
+ if (isExclusive)
+ setScbType(ScbType::SHAPE_EXCLUSIVE);
+ else
+ setScbType(ScbType::SHAPE_SHARED);
+}
+
+
+PX_INLINE PxGeometryType::Enum Shape::getGeometryType() const
+{
+ return mShape.getGeometryType();
+}
+
+PX_INLINE const PxGeometry& Shape::getGeometry() const
+{
+ if (isBuffered(Buf::BF_Geometry))
+ return getBufferedData()->geometry.getGeometry();
+ else
+ return mShape.getGeometry();
+}
+
+PX_INLINE const Gu::GeometryUnion& Shape::getGeometryUnion() const
+{
+ if (isBuffered(Buf::BF_Geometry))
+ return getBufferedData()->geometry;
+ else
+ return mShape.getGeometryUnion();
+}
+
+
+PX_INLINE Scb::ShapeBuffer* Shape::setGeometry(const PxGeometry& geom)
+{
+ Scb::ShapeBuffer* shapeBuffer = NULL;
+ if (!isBuffering())
+ {
+ Scb::Scene* sc = getScbScene();
+
+ if (sc)
+ {
+ sc->getScScene().unregisterShapeFromNphase(mShape);
+ }
+
+ mShape.setGeometry(geom);
+
+ if (sc)
+ {
+ sc->getScScene().registerShapeInNphase(mShape);
+ }
+
+ Sc::RigidCore* rigidCore = NpShapeGetScRigidObjectFromScbSLOW(*this);
+ if(rigidCore)
+ rigidCore->onShapeChange(mShape, Sc::ShapeChangeNotifyFlag::eGEOMETRY, PxShapeFlags());
+
+#if PX_SUPPORT_PVD
+ Scb::Scene* scbScene = getScbSceneForAPI();
+ if(scbScene)
+ {
+ scbScene->getScenePvdClient().releaseAndRecreateGeometry( this );
+ }
+#endif
+ }
+ else
+ {
+ markUpdated(Buf::BF_Geometry);
+ shapeBuffer = getBufferedData();
+ shapeBuffer->geometry.set(geom);
+ }
+
+ return shapeBuffer;
+}
+
+
+PX_INLINE PxU16 Shape::getNbMaterials() const
+{
+ if (isBuffered(Buf::BF_Material))
+ return getBufferedData()->materialCount;
+ else
+ return mShape.getNbMaterialIndices();
+}
+
+
+PX_INLINE PxMaterial* Shape::getMaterial(PxU32 index) const
+{
+ PX_ASSERT(index < getNbMaterials());
+
+ NpMaterialManager& matManager = NpPhysics::getInstance().getMaterialManager();
+ if (isBuffered(Buf::BF_Material))
+ {
+ const PxU16* materialIndices = getMaterialBuffer(*getScbScene(), *getBufferedData());
+ return matManager.getMaterial(materialIndices[index]);
+ }
+ else
+ {
+ PxU16 matTableIndex = mShape.getMaterialIndices()[index];
+ return matManager.getMaterial(matTableIndex);
+ }
+}
+
+
+PX_INLINE PxU32 Shape::getMaterials(PxMaterial** buffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ const PxU16* materialIndices;
+ PxU32 matCount;
+ NpMaterialManager& matManager = NpPhysics::getInstance().getMaterialManager();
+ if (isBuffered(Buf::BF_Material))
+ {
+ // IMPORTANT:
+ // As long as the material pointers get copied to a user buffer, this works fine.
+ // Never give direct access to the internal material buffer because in the
+ // double buffered case the pointer changes on resize.
+
+ const Scb::ShapeBuffer* PX_RESTRICT bufferedData = getBufferedData();
+
+ materialIndices = getMaterialBuffer(*getScbScene(), *bufferedData);
+ matCount = bufferedData->materialCount;
+ }
+ else
+ {
+ materialIndices = mShape.getMaterialIndices();
+ matCount = mShape.getNbMaterialIndices();
+ }
+
+ // PT: this is copied from Cm::getArrayOfPointers(). We cannot use the Cm function here
+ // because of the extra indirection needed to access the materials.
+ PxU32 size = matCount;
+ const PxU32 remainder = PxU32(PxMax<PxI32>(PxI32(size - startIndex), 0));
+ const PxU32 writeCount = PxMin(remainder, bufferSize);
+ materialIndices += startIndex;
+ for(PxU32 i=0;i<writeCount;i++)
+ buffer[i] = matManager.getMaterial(materialIndices[i]);
+
+ return writeCount;
+}
+
+
+PX_INLINE bool Shape::setMaterials(PxMaterial* const* materials, PxU16 materialCount)
+{
+ if (!isBuffering())
+ {
+ bool ret = setMaterialsHelper(materials, materialCount);
+ UPDATE_PVD_MATERIALS()
+ return ret;
+ }
+ else
+ {
+ Scb::ShapeBuffer* PX_RESTRICT bufferedData = getBufferedData();
+
+ PxU16* materialIndices;
+ if (materialCount == 1)
+ materialIndices = &bufferedData->materialIndex;
+ else
+ {
+ PxU32 bufferIdx;
+ materialIndices = getScbScene()->allocShapeMaterialBuffer(materialCount, bufferIdx);
+ bufferedData->materialBufferIndex = bufferIdx;
+ }
+ bufferedData->materialCount = materialCount;
+
+ NpMaterial::getMaterialIndices(materials, materialIndices, materialCount);
+
+ markUpdated(Buf::BF_Material);
+
+ return true;
+ }
+}
+
+PX_INLINE void Shape::setContactOffset(PxReal v)
+{
+ write<Buf::BF_ContactOffset>(v);
+}
+
+
+PX_FORCE_INLINE void Shape::setControlStateIfExclusive(Scene* s, ControlState::Enum cs)
+{
+ if (isExclusive())
+ {
+ setControlState(cs);
+ setScbScene(s);
+ }
+}
+
+
+template<bool sync>
+PX_FORCE_INLINE void Shape::checkUpdateOnRemove(Scene* s)
+{
+ // special code to cover the case where a shape has a pending update and gets released. The following operations have to be done
+ // before the ref-counter of the shape gets decremented because that could cause the shape to be deleted in which case it must not
+ // be in the pending update list any longer.
+ if (getControlFlags() & Scb::ControlFlag::eIS_UPDATED)
+ {
+ if (sync)
+ syncState();
+ s->removeShapeFromPendingUpdateList(*this);
+ }
+}
+
+
+//--------------------------------------------------------------
+//
+// Data synchronization
+//
+//--------------------------------------------------------------
+
+
+} // namespace Scb
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/buffering/ScbType.h b/PhysX_3.4/Source/PhysX/src/buffering/ScbType.h
new file mode 100644
index 00000000..b1725661
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/buffering/ScbType.h
@@ -0,0 +1,61 @@
+// 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_SCB_TYPE
+#define PX_PHYSICS_SCB_TYPE
+
+namespace physx
+{
+ struct ScbType
+ {
+ enum Enum
+ {
+ UNDEFINED,
+ SHAPE_EXCLUSIVE,
+ SHAPE_SHARED,
+ BODY,
+ BODY_FROM_ARTICULATION_LINK,
+ RIGID_STATIC,
+ CONSTRAINT,
+#if PX_USE_PARTICLE_SYSTEM_API
+ PARTICLE_SYSTEM,
+#endif
+ ARTICULATION,
+ ARTICULATION_JOINT,
+ AGGREGATE,
+#if PX_USE_CLOTH_API
+ CLOTH,
+#endif
+ TYPE_COUNT
+ };
+ };
+}
+
+#endif