aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/PhysX
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/PhysX
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/PhysX')
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpActor.cpp511
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpActor.h163
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpActorTemplate.h270
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpAggregate.cpp394
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpAggregate.h100
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpArticulation.cpp528
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpArticulation.h184
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpArticulationJoint.cpp403
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpArticulationJoint.h159
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpArticulationLink.cpp384
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpArticulationLink.h158
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpBatchQuery.cpp602
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpBatchQuery.h167
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpCast.h124
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpConnector.h135
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpConstraint.cpp408
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpConstraint.h131
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpFactory.cpp1256
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpFactory.h304
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpMaterial.cpp205
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpMaterial.h122
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpMaterialManager.h164
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpMetaData.cpp646
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpPhysics.cpp893
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpPhysics.h274
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpPhysicsInsertionCallback.h69
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpPtrTableStorageManager.h105
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpPvdSceneQueryCollector.cpp159
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpPvdSceneQueryCollector.h305
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpQueryShared.h106
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpReadCheck.cpp83
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpReadCheck.h69
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpRigidActorTemplate.h467
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpRigidActorTemplateInternal.h69
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpRigidBodyTemplate.h593
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpRigidDynamic.cpp533
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpRigidDynamic.h171
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpRigidStatic.cpp180
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpRigidStatic.h118
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpScene.cpp3185
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpScene.h544
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpSceneQueries.cpp836
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpSceneQueries.h211
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpSerializerAdapter.cpp207
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpShape.cpp851
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpShape.h216
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp309
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpShapeManager.h126
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpSpatialIndex.cpp221
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpSpatialIndex.h92
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpVolumeCache.cpp806
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpVolumeCache.h111
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpWriteCheck.cpp92
-rw-r--r--PhysX_3.4/Source/PhysX/src/NpWriteCheck.h79
-rw-r--r--PhysX_3.4/Source/PhysX/src/PvdMetaDataBindingData.h82
-rw-r--r--PhysX_3.4/Source/PhysX/src/PvdMetaDataPvdBinding.cpp2416
-rw-r--r--PhysX_3.4/Source/PhysX/src/PvdMetaDataPvdBinding.h188
-rw-r--r--PhysX_3.4/Source/PhysX/src/PvdPhysicsClient.cpp243
-rw-r--r--PhysX_3.4/Source/PhysX/src/PvdPhysicsClient.h103
-rw-r--r--PhysX_3.4/Source/PhysX/src/PvdTypeNames.h189
-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
-rw-r--r--PhysX_3.4/Source/PhysX/src/cloth/NpCloth.cpp1342
-rw-r--r--PhysX_3.4/Source/PhysX/src/cloth/NpCloth.h269
-rw-r--r--PhysX_3.4/Source/PhysX/src/cloth/NpClothFabric.cpp203
-rw-r--r--PhysX_3.4/Source/PhysX/src/cloth/NpClothFabric.h112
-rw-r--r--PhysX_3.4/Source/PhysX/src/cloth/NpClothParticleData.cpp65
-rw-r--r--PhysX_3.4/Source/PhysX/src/cloth/NpClothParticleData.h74
-rw-r--r--PhysX_3.4/Source/PhysX/src/device/PhysXIndicator.h56
-rw-r--r--PhysX_3.4/Source/PhysX/src/device/linux/PhysXIndicatorLinux.cpp51
-rw-r--r--PhysX_3.4/Source/PhysX/src/device/nvPhysXtoDrv.h93
-rw-r--r--PhysX_3.4/Source/PhysX/src/device/windows/PhysXIndicatorWindows.cpp131
-rw-r--r--PhysX_3.4/Source/PhysX/src/gpu/NpPhysicsGpu.cpp291
-rw-r--r--PhysX_3.4/Source/PhysX/src/gpu/NpPhysicsGpu.h101
-rw-r--r--PhysX_3.4/Source/PhysX/src/gpu/PxGpu.cpp68
-rw-r--r--PhysX_3.4/Source/PhysX/src/gpu/PxParticleDeviceExclusive.cpp130
-rw-r--r--PhysX_3.4/Source/PhysX/src/gpu/PxParticleGpu.cpp89
-rw-r--r--PhysX_3.4/Source/PhysX/src/gpu/PxPhysXGpuModuleLoader.cpp141
-rw-r--r--PhysX_3.4/Source/PhysX/src/gpu/PxPhysXIndicatorDeviceExclusive.cpp50
-rw-r--r--PhysX_3.4/Source/PhysX/src/particles/NpParticleBaseTemplate.h925
-rw-r--r--PhysX_3.4/Source/PhysX/src/particles/NpParticleFluid.cpp132
-rw-r--r--PhysX_3.4/Source/PhysX/src/particles/NpParticleFluid.h94
-rw-r--r--PhysX_3.4/Source/PhysX/src/particles/NpParticleFluidReadData.h85
-rw-r--r--PhysX_3.4/Source/PhysX/src/particles/NpParticleSystem.cpp70
-rw-r--r--PhysX_3.4/Source/PhysX/src/particles/NpParticleSystem.h95
-rw-r--r--PhysX_3.4/Source/PhysX/src/windows/NpWindowsDelayLoadHook.cpp82
111 files changed, 38550 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysX/src/NpActor.cpp b/PhysX_3.4/Source/PhysX/src/NpActor.cpp
new file mode 100644
index 00000000..940c1dc8
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpActor.cpp
@@ -0,0 +1,511 @@
+// 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 "NpActor.h"
+#include "PxRigidActor.h"
+#include "NpConstraint.h"
+#include "NpFactory.h"
+#include "NpShape.h"
+#include "NpPhysics.h"
+#include "NpAggregate.h"
+#include "NpScene.h"
+#include "NpRigidStatic.h"
+#include "NpRigidDynamic.h"
+#include "NpParticleSystem.h"
+#include "NpParticleFluid.h"
+#include "NpArticulationLink.h"
+#include "NpCloth.h"
+#include "CmTransformUtils.h"
+
+using namespace physx;
+
+///////////////////////////////////////////////////////////////////////////////
+
+NpActor::NpActor(const char* name) :
+ mName(name),
+ mConnectorArray(NULL)
+{
+}
+
+NpActor::~NpActor()
+{
+}
+
+
+typedef Ps::HashMap<NpActor*, NpConnectorArray*> ConnectorMap;
+struct NpActorUserData
+{
+ PxU32 referenceCount;
+ ConnectorMap* tmpOriginalConnectors;
+};
+
+void NpActor::exportExtraData(PxSerializationContext& stream)
+{
+ const PxCollection& collection = stream.getCollection();
+ if(mConnectorArray)
+ {
+ PxU32 connectorSize = mConnectorArray->size();
+ PxU32 missedCount = 0;
+ for(PxU32 i = 0; i < connectorSize; ++i)
+ {
+ NpConnector& c = (*mConnectorArray)[i];
+ PxBase* object = c.mObject;
+ if(!collection.contains(*object))
+ {
+ ++missedCount;
+ }
+ }
+
+ NpConnectorArray* exportConnectorArray = mConnectorArray;
+
+ if(missedCount > 0)
+ {
+ exportConnectorArray = NpFactory::getInstance().acquireConnectorArray();
+ if(missedCount < connectorSize)
+ {
+ exportConnectorArray->reserve(connectorSize - missedCount);
+ for(PxU32 i = 0; i < connectorSize; ++i)
+ {
+ NpConnector& c = (*mConnectorArray)[i];
+ PxBase* object = c.mObject;
+ if(collection.contains(*object))
+ {
+ exportConnectorArray->pushBack(c);
+ }
+ }
+ }
+ }
+
+ stream.alignData(PX_SERIAL_ALIGN);
+ stream.writeData(exportConnectorArray, sizeof(NpConnectorArray));
+ Cm::exportInlineArray(*exportConnectorArray, stream);
+
+ if(missedCount > 0)
+ NpFactory::getInstance().releaseConnectorArray(exportConnectorArray);
+ }
+ stream.writeName(mName);
+}
+
+void NpActor::importExtraData(PxDeserializationContext& context)
+{
+ if(mConnectorArray)
+ {
+ mConnectorArray = context.readExtraData<NpConnectorArray, PX_SERIAL_ALIGN>();
+ new (mConnectorArray) NpConnectorArray(PxEmpty);
+
+ if(mConnectorArray->size() == 0)
+ mConnectorArray = NULL;
+ else
+ Cm::importInlineArray(*mConnectorArray, context);
+ }
+ context.readName(mName);
+}
+
+void NpActor::resolveReferences(PxDeserializationContext& context)
+{
+ // Resolve connector pointers if needed
+ if(mConnectorArray)
+ {
+ const PxU32 nbConnectors = mConnectorArray->size();
+ for(PxU32 i=0; i<nbConnectors; i++)
+ {
+ NpConnector& c = (*mConnectorArray)[i];
+ context.translatePxBase(c.mObject);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpActor::releaseConstraints(PxRigidActor& owner)
+{
+ if(mConnectorArray)
+ {
+ PxU32 nbConnectors = mConnectorArray->size();
+ PxU32 currentIndex = 0;
+ while(nbConnectors--)
+ {
+ NpConnector& connector = (*mConnectorArray)[currentIndex];
+ if (connector.mType == NpConnectorType::eConstraint)
+ {
+ NpConstraint* c = static_cast<NpConstraint*>(connector.mObject);
+ c->actorDeleted(&owner);
+
+ NpScene* s = c->getNpScene();
+ if (s)
+ {
+ s->getScene().removeConstraint(c->getScbConstraint());
+ s->removeFromConstraintList(*c);
+ }
+
+ removeConnector(owner, currentIndex);
+ }
+ else
+ currentIndex++;
+ }
+ }
+}
+
+void NpActor::release(PxActor& owner)
+{
+// PX_AGGREGATE
+ if (mConnectorArray) // Need to test again because the code above might purge the connector array if no element remains
+ {
+ PX_ASSERT(mConnectorArray->size() == 1); // At this point only the aggregate should remain
+ PX_ASSERT((*mConnectorArray)[0].mType == NpConnectorType::eAggregate);
+
+ NpAggregate* a = static_cast<NpAggregate*>((*mConnectorArray)[0].mObject);
+ bool status = a->removeActorAndReinsert(owner, false);
+ PX_ASSERT(status);
+ PX_UNUSED(status);
+ PX_ASSERT(!mConnectorArray); // Remove should happen in aggregate code
+ }
+//~PX_AGGREGATE
+
+ PX_ASSERT(!mConnectorArray); // All the connector objects should have been removed at this point
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxU32 NpActor::findConnector(NpConnectorType::Enum type, PxBase* object) const
+{
+ if(!mConnectorArray)
+ return 0xffffffff;
+
+ for(PxU32 i=0; i < mConnectorArray->size(); i++)
+ {
+ NpConnector& c = (*mConnectorArray)[i];
+ if (c.mType == type && c.mObject == object)
+ return i;
+ }
+
+ return 0xffffffff;
+}
+
+void NpActor::addConnector(NpConnectorType::Enum type, PxBase* object, const char* errMsg)
+{
+ if(!mConnectorArray)
+ mConnectorArray = NpFactory::getInstance().acquireConnectorArray();
+
+ PX_CHECK_MSG(findConnector(type, object) == 0xffffffff, errMsg);
+ PX_UNUSED(errMsg);
+
+ if(mConnectorArray->isInUserMemory() && mConnectorArray->size() == mConnectorArray->capacity())
+ {
+ NpConnectorArray* newConnectorArray = NpFactory::getInstance().acquireConnectorArray();
+ newConnectorArray->assign(mConnectorArray->begin(), mConnectorArray->end());
+ mConnectorArray->~NpConnectorArray();
+ mConnectorArray = newConnectorArray;
+ }
+
+ NpConnector c(type, object);
+ mConnectorArray->pushBack(c);
+}
+
+void NpActor::removeConnector(PxActor& /*owner*/, PxU32 index)
+{
+ PX_ASSERT(mConnectorArray);
+ PX_ASSERT(index < mConnectorArray->size());
+
+ mConnectorArray->replaceWithLast(index);
+
+ if(mConnectorArray->size() == 0)
+ {
+ if(!mConnectorArray->isInUserMemory())
+ NpFactory::getInstance().releaseConnectorArray(mConnectorArray);
+ else
+ mConnectorArray->~NpConnectorArray();
+ mConnectorArray = NULL;
+ }
+}
+
+void NpActor::removeConnector(PxActor& owner, NpConnectorType::Enum type, PxBase* object, const char* errorMsg)
+{
+ PX_CHECK_MSG(mConnectorArray, errorMsg);
+ PX_UNUSED(errorMsg);
+
+ if(mConnectorArray)
+ {
+ PxU32 index = findConnector(type, object);
+
+ PX_CHECK_MSG(index != 0xffffffff, errorMsg);
+
+ removeConnector(owner, index);
+ }
+}
+
+PxU32 NpActor::getNbConnectors(NpConnectorType::Enum type) const
+{
+ PxU32 nbConnectors = 0;
+
+ if(mConnectorArray)
+ {
+ for(PxU32 i=0; i < mConnectorArray->size(); i++)
+ {
+ if ((*mConnectorArray)[i].mType == type)
+ nbConnectors++;
+ }
+ }
+
+ return nbConnectors;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+NpAggregate* NpActor::getNpAggregate(PxU32& index) const
+{
+ PX_ASSERT(getNbConnectors(NpConnectorType::eAggregate) <= 1);
+
+ if(mConnectorArray)
+ {
+ // PT: TODO: sort by type to optimize this...
+ for(PxU32 i=0; i < mConnectorArray->size(); i++)
+ {
+ NpConnector& c = (*mConnectorArray)[i];
+ if (c.mType == NpConnectorType::eAggregate)
+ {
+ index = i;
+ return static_cast<NpAggregate*>(c.mObject);
+ }
+ }
+ }
+
+ return NULL;
+}
+
+void NpActor::setAggregate(NpAggregate* np, PxActor& owner)
+{
+ PxU32 index = 0xffffffff;
+ NpAggregate* a = getNpAggregate(index);
+
+ if (!a)
+ {
+ PX_ASSERT(np);
+ addConnector(NpConnectorType::eAggregate, np, "NpActor::setAggregate() failed");
+ }
+ else
+ {
+ PX_ASSERT(mConnectorArray);
+ PX_ASSERT(index != 0xffffffff);
+ if (!np)
+ removeConnector(owner, index);
+ else
+ (*mConnectorArray)[index].mObject = np;
+ }
+}
+
+PxAggregate* NpActor::getAggregate() const
+{
+ PxU32 index = 0xffffffff;
+ NpAggregate* a = getNpAggregate(index);
+ return static_cast<PxAggregate*>(a);
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpActor::removeConstraintsFromScene()
+{
+ NpConnectorIterator iter = getConnectorIterator(NpConnectorType::eConstraint);
+ while (PxBase* ser = iter.getNext())
+ {
+ NpConstraint* c = static_cast<NpConstraint*>(ser);
+
+ NpScene* s = c->getNpScene();
+
+ if (s)
+ {
+ s->removeFromConstraintList(*c);
+ s->getScene().removeConstraint(c->getScbConstraint());
+ }
+ }
+}
+
+void NpActor::addConstraintsToSceneInternal()
+{
+ if(!mConnectorArray)
+ return;
+
+ NpConnectorIterator iter = getConnectorIterator(NpConnectorType::eConstraint);
+ while (PxBase* ser = iter.getNext())
+ {
+ NpConstraint* c = static_cast<NpConstraint*>(ser);
+ PX_ASSERT(c->getNpScene() == NULL);
+
+ c->markDirty(); // PT: "temp" fix for crash when removing/re-adding jointed actor from/to a scene
+
+ NpScene* s = c->getSceneFromActors();
+ if (s)
+ {
+ s->addToConstraintList(*c);
+ s->getScene().addConstraint(c->getScbConstraint());
+ }
+ }
+}
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+NpShapeManager* NpActor::getShapeManager(PxRigidActor& actor)
+{
+ // DS: if the performance here becomes an issue we can use the same kind of offset hack as below
+
+ const PxType actorType = actor.getConcreteType();
+
+ if (actorType == PxConcreteType::eRIGID_DYNAMIC)
+ return &static_cast<NpRigidDynamic&>(actor).getShapeManager();
+ else if(actorType == PxConcreteType::eRIGID_STATIC)
+ return &static_cast<NpRigidStatic&>(actor).getShapeManager();
+ else if (actorType == PxConcreteType::eARTICULATION_LINK)
+ return &static_cast<NpArticulationLink&>(actor).getShapeManager();
+ else
+ {
+ PX_ASSERT(0);
+ return NULL;
+ }
+}
+
+const NpShapeManager* NpActor::getShapeManager(const PxRigidActor& actor)
+{
+ // DS: if the performance here becomes an issue we can use the same kind of offset hack as below
+
+ const PxType actorType = actor.getConcreteType();
+
+ if (actorType == PxConcreteType::eRIGID_DYNAMIC)
+ return &static_cast<const NpRigidDynamic&>(actor).getShapeManager();
+ else if(actorType == PxConcreteType::eRIGID_STATIC)
+ return &static_cast<const NpRigidStatic&>(actor).getShapeManager();
+ else if (actorType == PxConcreteType::eARTICULATION_LINK)
+ return &static_cast<const NpArticulationLink&>(actor).getShapeManager();
+ else
+ {
+ PX_ASSERT(0);
+ return NULL;
+ }
+}
+
+void NpActor::getGlobalPose(PxTransform& globalPose, const NpShape& shape, const PxRigidActor& actor)
+{
+ const Scb::Actor& scbActor = NpActor::getScbFromPxActor(actor);
+ const Scb::Shape& scbShape = shape.getScbShape();
+
+ NpActor::getGlobalPose(globalPose, scbShape, scbActor);
+}
+
+void NpActor::getGlobalPose(PxTransform& globalPose, const Scb::Shape& scbShape, const Scb::Actor& scbActor)
+{
+ const PxTransform& shape2Actor = scbShape.getShape2Actor();
+
+ // PT: TODO: duplicated from SqBounds.cpp. Refactor.
+ const ScbType::Enum actorType = scbActor.getScbType();
+ if(actorType==ScbType::RIGID_STATIC)
+ {
+ Cm::getStaticGlobalPoseAligned(static_cast<const Scb::RigidStatic&>(scbActor).getActor2World(), shape2Actor, globalPose);
+ }
+ else
+ {
+ PX_ASSERT(actorType==ScbType::BODY || actorType == ScbType::BODY_FROM_ARTICULATION_LINK);
+
+ const Scb::Body& body = static_cast<const Scb::Body&>(scbActor);
+ PX_ALIGN(16, PxTransform) kinematicTarget;
+ const PxU16 sqktFlags = PxRigidBodyFlag::eKINEMATIC | PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES;
+ const bool useTarget = (PxU16(body.getFlags()) & sqktFlags) == sqktFlags;
+ const PxTransform& body2World = (useTarget && body.getKinematicTarget(kinematicTarget)) ? kinematicTarget : body.getBody2World();
+ Cm::getDynamicGlobalPoseAligned(body2World, shape2Actor, body.getBody2Actor(), globalPose);
+ }
+}
+
+namespace
+{
+ template <typename N> NpActor* pxToNpActor(PxActor *p)
+ {
+ return static_cast<NpActor*>(static_cast<N*>(p));
+ }
+
+ template <typename N> const NpActor* pxToNpActor(const PxActor *p)
+ {
+ return static_cast<const NpActor*>(static_cast<const N*>(p));
+ }
+}
+
+NpActor::Offsets::Offsets()
+{
+ for(PxU32 i=0;i<PxConcreteType::ePHYSX_CORE_COUNT;i++)
+ pxActorToScbActor[i] = pxActorToNpActor[i] = 0;
+ size_t addr = 0x100; // casting the null ptr takes a special-case code path, which we don't want
+ PxActor* n = reinterpret_cast<PxActor*>(addr);
+ pxActorToNpActor[PxConcreteType::eRIGID_STATIC] = reinterpret_cast<size_t>(pxToNpActor<NpRigidStatic>(n)) - addr;
+ pxActorToNpActor[PxConcreteType::eRIGID_DYNAMIC] = reinterpret_cast<size_t>(pxToNpActor<NpRigidDynamic>(n)) - addr;
+#if PX_USE_PARTICLE_SYSTEM_API
+ pxActorToNpActor[PxConcreteType::ePARTICLE_SYSTEM] = reinterpret_cast<size_t>(pxToNpActor<NpParticleSystem>(n)) - addr;
+ pxActorToNpActor[PxConcreteType::ePARTICLE_FLUID] = reinterpret_cast<size_t>(pxToNpActor<NpParticleFluid>(n)) - addr;
+#endif
+ pxActorToNpActor[PxConcreteType::eARTICULATION_LINK] = reinterpret_cast<size_t>(pxToNpActor<NpArticulationLink>(n)) - addr;
+#if PX_USE_CLOTH_API
+ pxActorToNpActor[PxConcreteType::eCLOTH] = reinterpret_cast<size_t>(pxToNpActor<NpCloth>(n)) - addr;
+#endif
+
+ pxActorToScbActor[PxConcreteType::eRIGID_STATIC] = PX_OFFSET_OF_RT(NpRigidStatic, getScbActorFast());
+ pxActorToScbActor[PxConcreteType::eRIGID_DYNAMIC] = PX_OFFSET_OF_RT(NpRigidDynamic, getScbActorFast());
+#if PX_USE_PARTICLE_SYSTEM_API
+ pxActorToScbActor[PxConcreteType::ePARTICLE_SYSTEM] = PX_OFFSET_OF_RT(NpParticleSystem, getScbActor());
+ pxActorToScbActor[PxConcreteType::ePARTICLE_FLUID] = PX_OFFSET_OF_RT(NpParticleFluid, getScbActor());
+#endif
+ pxActorToScbActor[PxConcreteType::eARTICULATION_LINK] = PX_OFFSET_OF_RT(NpArticulationLink, getScbActorFast());
+#if PX_USE_CLOTH_API
+ pxActorToScbActor[PxConcreteType::eCLOTH] = PX_OFFSET_OF_RT(NpCloth, getScbCloth());
+#endif
+}
+
+const NpActor::Offsets NpActor::sOffsets;
+
+
+NpScene* NpActor::getOwnerScene(const PxActor& actor)
+{
+ const Scb::Actor& scbActor = getScbFromPxActor(actor);
+ Scb::Scene* scbScene = scbActor.getScbScene();
+ return scbScene? static_cast<NpScene*>(scbScene->getPxScene()) : NULL;
+}
+
+NpScene* NpActor::getAPIScene(const PxActor& actor)
+{
+ const Scb::Actor& scbActor = getScbFromPxActor(actor);
+ Scb::Scene* scbScene = scbActor.getScbSceneForAPI();
+ return scbScene? static_cast<NpScene*>(scbScene->getPxScene()) : NULL;
+}
+
+void NpActor::onActorRelease(PxActor* actor)
+{
+ NpFactory::getInstance().onActorRelease(actor);
+}
diff --git a/PhysX_3.4/Source/PhysX/src/NpActor.h b/PhysX_3.4/Source/PhysX/src/NpActor.h
new file mode 100644
index 00000000..b9403cba
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpActor.h
@@ -0,0 +1,163 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_ACTOR
+#define PX_PHYSICS_NP_ACTOR
+
+#include "NpConnector.h"
+#include "ScbActor.h" // DM: without this inclusion PVD-diabled android build fails, lacking Scb::Actor definition
+
+namespace physx
+{
+ class NpShapeManager;
+ class NpAggregate;
+ class NpScene;
+ class NpShape;
+
+class NpActor
+{
+//= 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.
+//==================================================================================================
+
+ // We sometimes pass in the PxActor here even though it's always a base class
+ // of the objects which inherit from this class too. But passing
+ // context to functions which need it allows this to be purely a mixin containing shared
+ // utility code rather than an abstract base class.
+
+public:
+// PX_SERIALIZATION
+ NpActor(const PxEMPTY) {}
+
+ void exportExtraData(PxSerializationContext& stream);
+ void importExtraData(PxDeserializationContext& context);
+ void resolveReferences(PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ NpActor(const char* name);
+
+ void releaseConstraints(PxRigidActor& owner);
+ void release(PxActor& owner);
+
+ NpAggregate* getNpAggregate(PxU32& index) const;
+ void setAggregate(NpAggregate* np, PxActor& owner);
+ PxAggregate* getAggregate() const;
+
+ void removeConstraintsFromScene();
+ PX_FORCE_INLINE void addConstraintsToScene() // inline the fast path for addActors()
+ {
+ if(mConnectorArray)
+ addConstraintsToSceneInternal();
+ }
+
+ PX_FORCE_INLINE NpConnectorArray** getConnectorArrayAddress() { return &mConnectorArray;}
+ PxU32 findConnector(NpConnectorType::Enum type, PxBase* object) const;
+ void addConnector(NpConnectorType::Enum type, PxBase* object, const char* errMsg);
+ void removeConnector(PxActor& owner, NpConnectorType::Enum type, PxBase* object, const char* errorMsg);
+ PxU32 getNbConnectors(NpConnectorType::Enum type) const;
+
+ static NpShapeManager* getShapeManager(PxRigidActor& actor); // bit misplaced here, but we don't want a separate subclass just for this
+ static const NpShapeManager* getShapeManager(const PxRigidActor& actor); // bit misplaced here, but we don't want a separate subclass just for this
+
+ static void getGlobalPose(PxTransform& globalPose, const NpShape& shape, const PxRigidActor& actor);
+ static void getGlobalPose(PxTransform& globalPose, const Scb::Shape& scbShape, const Scb::Actor& scbActor);
+
+ static NpActor& getFromPxActor(PxActor& actor) { return *Ps::pointerOffset<NpActor*>(&actor, ptrdiff_t(sOffsets.pxActorToNpActor[actor.getConcreteType()])); }
+ static const NpActor& getFromPxActor(const PxActor& actor) { return *Ps::pointerOffset<const NpActor*>(&actor, ptrdiff_t(sOffsets.pxActorToNpActor[actor.getConcreteType()])); }
+
+ static Scb::Actor& getScbFromPxActor(PxActor& actor) { return *Ps::pointerOffset<Scb::Actor*>(&actor, ptrdiff_t(sOffsets.pxActorToScbActor[actor.getConcreteType()])); }
+ static const Scb::Actor& getScbFromPxActor(const PxActor& actor) { return *Ps::pointerOffset<const Scb::Actor*>(&actor, ptrdiff_t(sOffsets.pxActorToScbActor[actor.getConcreteType()])); }
+
+ static NpScene* getAPIScene(const PxActor& actor); // the scene the user thinks the actor is in
+ static NpScene* getOwnerScene(const PxActor& actor); // the scene the user thinks the actor is in, or from which the actor is pending removal
+
+ PX_FORCE_INLINE NpConnectorIterator getConnectorIterator(NpConnectorType::Enum type)
+ {
+ if (mConnectorArray)
+ return NpConnectorIterator(&mConnectorArray->front(), mConnectorArray->size(), type);
+ else
+ return NpConnectorIterator(NULL, 0, type);
+ }
+
+ // a couple of methods that sever include dependencies in NpActor.h
+
+ static void onActorRelease(PxActor* actor);
+
+
+
+template<typename T>
+PxU32 getConnectors(NpConnectorType::Enum type, T** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const
+{
+ PxU32 nbConnectors = 0;
+
+ if(mConnectorArray)
+ {
+ for(PxU32 i=0; i < mConnectorArray->size(); i++)
+ {
+ NpConnector& c = (*mConnectorArray)[i];
+ if (c.mType == type && nbConnectors < bufferSize && i>=startIndex)
+ {
+ userBuffer[nbConnectors] = static_cast<T*>(c.mObject);
+ nbConnectors++;
+ }
+ }
+ }
+
+ return nbConnectors;
+}
+
+protected:
+ ~NpActor();
+ const char* mName;
+ // Lazy-create array for connector objects like constraints, observers, ...
+ // Most actors have no such objects, so we bias this class accordingly:
+ NpConnectorArray* mConnectorArray;
+
+private:
+ void addConstraintsToSceneInternal();
+ void removeConnector(PxActor& owner, PxU32 index);
+ struct Offsets
+ {
+ size_t pxActorToNpActor[PxConcreteType::ePHYSX_CORE_COUNT];
+ size_t pxActorToScbActor[PxConcreteType::ePHYSX_CORE_COUNT];
+ Offsets();
+ };
+public:
+ static const Offsets sOffsets;
+};
+
+
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpActorTemplate.h b/PhysX_3.4/Source/PhysX/src/NpActorTemplate.h
new file mode 100644
index 00000000..0236bdbc
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpActorTemplate.h
@@ -0,0 +1,270 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_ACTOR_TEMPLATE
+#define PX_PHYSICS_NP_ACTOR_TEMPLATE
+
+#include "PsUserAllocated.h"
+#include "NpWriteCheck.h"
+#include "NpReadCheck.h"
+#include "NpActor.h"
+#include "ScbActor.h"
+#include "NpScene.h"
+
+namespace physx
+{
+
+// PT: only API (virtual) functions should be implemented here. Other shared non-virtual functions should go to NpActor.
+
+/**
+This is an API class. API classes run in a different thread than the simulation.
+For the sake of simplicity they have their own methods, and they do not call simulation
+methods directly. To set simulation state, they also have their own custom set
+methods in the implementation classes.
+
+Changing the data layout of this class breaks the binary serialization format.
+See comments for PX_BINARY_SERIAL_VERSION.
+*/
+template<class APIClass>
+class NpActorTemplate : public APIClass, public NpActor, 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.
+//==================================================================================================
+ PX_NOCOPY(NpActorTemplate)
+public:
+// PX_SERIALIZATION
+ NpActorTemplate(PxBaseFlags baseFlags) : APIClass(baseFlags), NpActor(PxEmpty) {}
+ virtual void exportExtraData(PxSerializationContext& stream) { NpActor::exportExtraData(stream); }
+ void importExtraData(PxDeserializationContext& context) { NpActor::importExtraData(context); }
+ virtual void resolveReferences(PxDeserializationContext& context) { NpActor::resolveReferences(context); }
+//~PX_SERIALIZATION
+
+ NpActorTemplate(PxType concreteType, PxBaseFlags baseFlags, const char* name, void* userData);
+ virtual ~NpActorTemplate();
+
+ //---------------------------------------------------------------------------------
+ // PxActor implementation
+ //---------------------------------------------------------------------------------
+ virtual void release() { NpActor::release(*this); }
+
+ // The rule is: If an API method is used somewhere in here, it has to be redeclared, else GCC whines
+ virtual PxActorType::Enum getType() const = 0;
+
+ virtual PxScene* getScene() const;
+
+ // Debug name
+ virtual void setName(const char*);
+ virtual const char* getName() const;
+
+ virtual PxBounds3 getWorldBounds(float inflation=1.01f) const = 0;
+
+ // Flags
+ virtual void setActorFlag(PxActorFlag::Enum flag, bool value);
+ virtual void setActorFlags(PxActorFlags inFlags);
+ virtual PxActorFlags getActorFlags() const;
+
+ // Dominance
+ virtual void setDominanceGroup(PxDominanceGroup dominanceGroup);
+ virtual PxDominanceGroup getDominanceGroup() const;
+
+ // Multiclient
+ virtual void setOwnerClient( PxClientID inClient );
+ virtual PxClientID getOwnerClient() const;
+ virtual void setClientBehaviorFlags(PxActorClientBehaviorFlags);
+ virtual PxActorClientBehaviorFlags getClientBehaviorFlags() const;
+
+ // Aggregates
+ virtual PxAggregate* getAggregate() const { return NpActor::getAggregate(); }
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+protected:
+ PX_FORCE_INLINE void setActorFlagInternal(PxActorFlag::Enum flag, bool value);
+ PX_FORCE_INLINE void setActorFlagsInternal(PxActorFlags inFlags);
+};
+
+///////////////////////////////////////////////////////////////////////////////
+
+template<class APIClass>
+NpActorTemplate<APIClass>::NpActorTemplate(PxType concreteType,
+ PxBaseFlags baseFlags,
+ const char* name,
+ void* actorUserData)
+:APIClass(concreteType, baseFlags),
+NpActor(name)
+{
+ // don't ref Scb actor here, it hasn't been assigned yet
+
+ APIClass::userData = actorUserData;
+}
+
+
+template<class APIClass>
+NpActorTemplate<APIClass>::~NpActorTemplate()
+{
+ NpActor::onActorRelease(this);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PT: this one is very slow
+template<class APIClass>
+PxScene* NpActorTemplate<APIClass>::getScene() const
+{
+ return NpActor::getAPIScene(*this);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+template<class APIClass>
+void NpActorTemplate<APIClass>::setName(const char* debugName)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ mName = debugName;
+
+#if PX_SUPPORT_PVD
+ Scb::Scene* scbScene = getScbFromPxActor(*this).getScbSceneForAPI();
+ Scb::Actor& scbActor = NpActor::getScbFromPxActor(*this);
+ //Name changing is not bufferred
+ if(scbScene)
+ scbScene->getScenePvdClient().updatePvdProperties(&scbActor);
+#endif
+}
+
+template<class APIClass>
+const char* NpActorTemplate<APIClass>::getName() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mName;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+template<class APIClass>
+void NpActorTemplate<APIClass>::setDominanceGroup(PxDominanceGroup dominanceGroup)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ NpActor::getScbFromPxActor(*this).setDominanceGroup(dominanceGroup);
+}
+
+
+template<class APIClass>
+PxDominanceGroup NpActorTemplate<APIClass>::getDominanceGroup() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return NpActor::getScbFromPxActor(*this).getDominanceGroup();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+template<class APIClass>
+void NpActorTemplate<APIClass>::setOwnerClient( PxClientID inId )
+{
+ if ( NpActor::getOwnerScene(*this) != NULL )
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Attempt to set the client id when an actor is already in a scene.");
+ }
+ else
+ NpActor::getScbFromPxActor(*this).setOwnerClient( inId );
+}
+
+template<class APIClass>
+PxClientID NpActorTemplate<APIClass>::getOwnerClient() const
+{
+ return NpActor::getScbFromPxActor(*this).getOwnerClient();
+}
+
+template<class APIClass>
+void NpActorTemplate<APIClass>::setClientBehaviorFlags(PxActorClientBehaviorFlags bits)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ NpActor::getScbFromPxActor(*this).setClientBehaviorFlags(bits);
+}
+
+template<class APIClass>
+PxActorClientBehaviorFlags NpActorTemplate<APIClass>::getClientBehaviorFlags() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return NpActor::getScbFromPxActor(*this).getClientBehaviorFlags();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+template<class APIClass>
+PX_FORCE_INLINE void NpActorTemplate<APIClass>::setActorFlagInternal(PxActorFlag::Enum flag, bool value)
+{
+ Scb::Actor& a = NpActor::getScbFromPxActor(*this);
+ if (value)
+ a.setActorFlags( a.getActorFlags() | flag );
+ else
+ a.setActorFlags( a.getActorFlags() & (~PxActorFlags(flag)) );
+}
+
+template<class APIClass>
+PX_FORCE_INLINE void NpActorTemplate<APIClass>::setActorFlagsInternal(PxActorFlags inFlags)
+{
+ Scb::Actor& a = NpActor::getScbFromPxActor(*this);
+ a.setActorFlags( inFlags );
+}
+
+template<class APIClass>
+void NpActorTemplate<APIClass>::setActorFlag(PxActorFlag::Enum flag, bool value)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ setActorFlagInternal(flag, value);
+}
+
+template<class APIClass>
+void NpActorTemplate<APIClass>::setActorFlags(PxActorFlags inFlags)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ setActorFlagsInternal(inFlags);
+}
+
+template<class APIClass>
+PxActorFlags NpActorTemplate<APIClass>::getActorFlags() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return NpActor::getScbFromPxActor(*this).getActorFlags();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpAggregate.cpp b/PhysX_3.4/Source/PhysX/src/NpAggregate.cpp
new file mode 100644
index 00000000..4b6114fa
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpAggregate.cpp
@@ -0,0 +1,394 @@
+// 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 "NpAggregate.h"
+
+///////////////////////////////////////////////////////////////////////////////
+
+#include "PxActor.h"
+#include "NpRigidStatic.h"
+#include "NpRigidDynamic.h"
+#include "NpParticleSystem.h"
+#include "NpParticleFluid.h"
+#include "NpArticulation.h"
+#include "CmUtils.h"
+
+using namespace physx;
+
+PX_FORCE_INLINE void setAggregate(NpAggregate* aggregate, PxActor& actor)
+{
+ NpActor& np = NpActor::getFromPxActor(actor);
+ np.setAggregate(aggregate, actor);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+NpAggregate::NpAggregate(PxU32 maxActors, bool selfCollisions)
+: PxAggregate(PxConcreteType::eAGGREGATE, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+, mAggregate(this, maxActors, selfCollisions)
+, mNbActors(0)
+{
+ mActors = reinterpret_cast<PxActor**>(PX_ALLOC(sizeof(PxActor*)*maxActors, "PxActor*"));
+}
+
+NpAggregate::~NpAggregate()
+{
+ NpFactory::getInstance().onAggregateRelease(this);
+ if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY)
+ PX_FREE(mActors);
+}
+
+void NpAggregate::removeAndReinsert(PxActor& actor, bool reinsert)
+{
+ NpActor& np = NpActor::getFromPxActor(actor);
+ Scb::Actor& scb = NpActor::getScbFromPxActor(actor);
+
+ np.setAggregate(NULL, actor);
+
+ mAggregate.removeActor(scb, reinsert);
+}
+
+void NpAggregate::release()
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_SIMD_GUARD;
+
+ NpPhysics::getInstance().notifyDeletionListenersUserRelease(this, NULL);
+
+ /*
+ "An aggregate should be empty when it gets released. If it isn't, the behavior should be: remove the actors from
+ the aggregate, then remove the aggregate from the scene (if any) then delete it. I guess that implies the actors
+ get individually reinserted into the broad phase if the aggregate is in a scene."
+ */
+ for(PxU32 i=0;i<mNbActors;i++)
+ {
+ if (mActors[i]->getType() == PxActorType::eARTICULATION_LINK)
+ static_cast<NpArticulationLink*>(mActors[i])->getRoot().setAggregate(NULL);
+
+ removeAndReinsert(*mActors[i], true);
+ }
+
+ NpScene* s = getAPIScene();
+ if(s)
+ {
+ s->getScene().removeAggregate(getScbAggregate());
+ s->removeFromAggregateList(*this);
+ }
+
+ mAggregate.destroy();
+}
+
+void NpAggregate::addActorInternal(PxActor& actor, NpScene& s)
+{
+ if (actor.getType() != PxActorType::eARTICULATION_LINK)
+ {
+ Scb::Actor& scb = NpActor::getScbFromPxActor(actor);
+
+ mAggregate.addActor(scb);
+
+ s.addActorInternal(actor);
+ }
+ else if (!actor.getScene()) // This check makes sure that a link of an articulation gets only added once.
+ {
+ NpArticulationLink& al = static_cast<NpArticulationLink&>(actor);
+ NpArticulation& npArt = al.getRoot();
+ NpArticulationLink* const* links = npArt.getLinks();
+ for(PxU32 i=0; i < npArt.getNbLinks(); i++)
+ {
+ mAggregate.addActor(links[i]->getScbActorFast());
+ }
+
+ s.addArticulationInternal(npArt);
+ }
+}
+
+bool NpAggregate::addActor(PxActor& actor)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_SIMD_GUARD;
+
+ if(mNbActors==mAggregate.getMaxActorCount())
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxAggregate: can't add actor to aggregate, max number of actors reached");
+ return false;
+ }
+
+ if(actor.getAggregate())
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxAggregate: can't add actor to aggregate, actor already belongs to an aggregate");
+ return false;
+ }
+
+ if(actor.getScene())
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxAggregate: can't add actor to aggregate, actor already belongs to a scene");
+ return false;
+ }
+
+ if(actor.getType() == PxActorType::eARTICULATION_LINK)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxAggregate: can't add articulation link to aggregate, only whole articulations can be added");
+ return false;
+ }
+
+ setAggregate(this, actor);
+
+ mActors[mNbActors++] = &actor;
+
+ // PT: when an object is added to a aggregate at runtime, i.e. when the aggregate has already been added to the scene,
+ // we need to immediately add the newcomer to the scene as well.
+ NpScene* s = getAPIScene();
+ if(s)
+ {
+ addActorInternal(actor, *s);
+ }
+
+ return true;
+}
+
+bool NpAggregate::removeActorAndReinsert(PxActor& actor, bool reinsert)
+{
+ for(PxU32 i=0;i<mNbActors;i++)
+ {
+ if(mActors[i]==&actor)
+ {
+ mActors[i] = mActors[--mNbActors];
+ removeAndReinsert(actor, reinsert);
+ return true;
+ }
+ }
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxAggregate: can't remove actor, actor doesn't belong to aggregate");
+ return false;
+}
+
+bool NpAggregate::removeActor(PxActor& actor)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_SIMD_GUARD;
+
+ if(actor.getType() == PxActorType::eARTICULATION_LINK)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxAggregate: can't remove articulation link, only whole articulations can be removed");
+ return false;
+ }
+
+ // PT: there are really 2 cases here:
+ // a) the user just wants to remove the actor from the aggregate, but the actor is still alive so if the aggregate has been added to a scene,
+ // we must reinsert the removed actor to that same scene
+ // b) this is called by the framework when releasing an actor, in which case we don't want to reinsert it anywhere.
+ //
+ // We assume that when called by the user, we always want to reinsert. The framework however will call the internal function
+ // without reinsertion.
+ return removeActorAndReinsert(actor, true);
+}
+
+bool NpAggregate::addArticulation(PxArticulation& art)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_SIMD_GUARD;
+
+ if((mNbActors+art.getNbLinks()) > mAggregate.getMaxActorCount())
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxAggregate: can't add articulation links, max number of actors reached");
+ return false;
+ }
+
+ if(art.getAggregate())
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxAggregate: can't add articulation to aggregate, articulation already belongs to an aggregate");
+ return false;
+ }
+
+ if(art.getScene())
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxAggregate: can't add articulation to aggregate, articulation already belongs to a scene");
+ return false;
+ }
+
+ NpArticulation& npArt = static_cast<NpArticulation&>(art);
+ npArt.setAggregate(this);
+ NpArticulationLink* const* links = npArt.getLinks();
+ for(PxU32 i=0; i < npArt.getNbLinks(); i++)
+ {
+ NpArticulationLink& l = *links[i];
+
+ setAggregate(this, l);
+
+ mActors[mNbActors++] = &l;
+
+ mAggregate.addActor(l.getScbActorFast());
+ }
+
+ // PT: when an object is added to a aggregate at runtime, i.e. when the aggregate has already been added to the scene,
+ // we need to immediately add the newcomer to the scene as well.
+ NpScene* s = getAPIScene();
+ if(s)
+ {
+ s->addArticulationInternal(art);
+ }
+
+ return true;
+}
+
+bool NpAggregate::removeArticulationAndReinsert(PxArticulation& art, bool reinsert)
+{
+ NpArticulation* npArt = static_cast<NpArticulation*>(&art);
+
+ bool found = false;
+ PxU32 idx = 0;
+ while(idx < mNbActors)
+ {
+ if ((mActors[idx]->getType() == PxActorType::eARTICULATION_LINK) && (&static_cast<NpArticulationLink*>(mActors[idx])->getRoot() == npArt))
+ {
+ PxActor* a = mActors[idx];
+ mActors[idx] = mActors[--mNbActors];
+ removeAndReinsert(*a, reinsert);
+ found = true;
+ }
+ else
+ idx++;
+ }
+
+ npArt->setAggregate(NULL);
+
+ if (!found)
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxAggregate: can't remove articulation, articulation doesn't belong to aggregate");
+ return found;
+}
+
+bool NpAggregate::removeArticulation(PxArticulation& art)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_SIMD_GUARD;
+
+ // see comments in removeActor()
+ return removeArticulationAndReinsert(art, true);
+}
+
+PxU32 NpAggregate::getNbActors() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mNbActors;
+}
+
+PxU32 NpAggregate::getMaxNbActors() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mAggregate.getMaxActorCount();
+}
+
+PxU32 NpAggregate::getActors(PxActor** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return Cm::getArrayOfPointers(userBuffer, bufferSize, startIndex, mActors, getCurrentSizeFast());
+}
+
+PxScene* NpAggregate::getScene()
+{
+ return getAPIScene();
+}
+
+NpScene* NpAggregate::getAPIScene() const
+{
+ return mAggregate.getScbSceneForAPI() ? static_cast<NpScene*>(mAggregate.getScbSceneForAPI()->getPxScene()) : NULL;
+}
+
+NpScene* NpAggregate::getOwnerScene() const
+{
+ return mAggregate.getScbScene() ? static_cast<NpScene*>(mAggregate.getScbScene()->getPxScene()) : NULL;
+}
+
+bool NpAggregate::getSelfCollision() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mAggregate.getSelfCollide();
+}
+
+// PX_SERIALIZATION
+void NpAggregate::exportExtraData(PxSerializationContext& stream)
+{
+ if(mActors)
+ {
+ stream.alignData(PX_SERIAL_ALIGN);
+ stream.writeData(mActors, mNbActors * sizeof(PxActor*));
+ }
+}
+
+void NpAggregate::importExtraData(PxDeserializationContext& context)
+{
+ if(mActors)
+ mActors = context.readExtraData<PxActor*, PX_SERIAL_ALIGN>(mNbActors);
+}
+
+void NpAggregate::resolveReferences(PxDeserializationContext& context)
+{
+ // Resolve actor pointers if needed
+ for(PxU32 i=0; i < mNbActors; i++)
+ {
+ context.translatePxBase(mActors[i]);
+ {
+ //update aggregate if mActors is in external reference
+ NpActor& np = NpActor::getFromPxActor(*mActors[i]);
+ if(np.getAggregate() == NULL)
+ {
+ np.setAggregate(this, *mActors[i]);
+ }
+ if(mActors[i]->getType() == PxActorType::eARTICULATION_LINK)
+ {
+ NpArticulation& articulation = static_cast<NpArticulationLink*>(mActors[i])->getRoot();
+ if(!articulation.getAggregate())
+ articulation.setAggregate(this);
+ }
+ }
+ }
+}
+
+NpAggregate* NpAggregate::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpAggregate* obj = new (address) NpAggregate(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpAggregate);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+
+void NpAggregate::requires(PxProcessPxBaseCallback& c)
+{
+ for(PxU32 i=0; i < mNbActors; i++)
+ {
+ PxArticulationLink* link = mActors[i]->is<PxArticulationLink>();
+ if(link)
+ c.process(link->getArticulation());
+ else
+ c.process(*mActors[i]);
+ }
+}
+// ~PX_SERIALIZATION
diff --git a/PhysX_3.4/Source/PhysX/src/NpAggregate.h b/PhysX_3.4/Source/PhysX/src/NpAggregate.h
new file mode 100644
index 00000000..fb2af9c6
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpAggregate.h
@@ -0,0 +1,100 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_AGGREGATE
+#define PX_PHYSICS_NP_AGGREGATE
+
+#include "CmPhysXCommon.h"
+#include "PxAggregate.h"
+#include "ScbAggregate.h"
+#include "PsUserAllocated.h"
+
+namespace physx
+{
+
+class NpScene;
+
+class NpAggregate : public PxAggregate, 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:
+// PX_SERIALIZATION
+ NpAggregate(PxBaseFlags baseFlags) : PxAggregate(baseFlags), mAggregate(PxEmpty) {}
+ virtual void exportExtraData(PxSerializationContext& stream);
+ void importExtraData(PxDeserializationContext& context);
+ void resolveReferences(PxDeserializationContext& context);
+ virtual void requires(PxProcessPxBaseCallback& c);
+ static NpAggregate* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ NpAggregate(PxU32 maxActors, bool selfCollision);
+ virtual ~NpAggregate();
+
+ virtual void release();
+ virtual bool addActor(PxActor&);
+ virtual bool removeActor(PxActor&);
+ virtual bool addArticulation(PxArticulation&);
+ virtual bool removeArticulation(PxArticulation&);
+
+ virtual PxU32 getNbActors() const;
+ virtual PxU32 getMaxNbActors() const;
+ virtual PxU32 getActors(PxActor** userBuffer, PxU32 bufferSize, PxU32 startIndex) const;
+
+ virtual PxScene* getScene();
+ virtual bool getSelfCollision() const;
+
+ PX_FORCE_INLINE PxU32 getCurrentSizeFast() const { return mNbActors; }
+ PX_FORCE_INLINE PxActor* getActorFast(PxU32 i) const { return mActors[i]; }
+ PX_FORCE_INLINE bool getSelfCollideFast() const { return mAggregate.getSelfCollide(); }
+
+ NpScene* getAPIScene() const;
+ NpScene* getOwnerScene() const; // the scene the user thinks the actor is in, or from which the actor is pending removal
+
+ void addActorInternal(PxActor& actor, NpScene& s);
+ void removeAndReinsert(PxActor& actor, bool reinsert);
+ bool removeActorAndReinsert(PxActor& actor, bool reinsert);
+ bool removeArticulationAndReinsert(PxArticulation& art, bool reinsert);
+
+ PX_FORCE_INLINE Scb::Aggregate& getScbAggregate() { return mAggregate; }
+
+private:
+ Scb::Aggregate mAggregate;
+ PxU32 mNbActors;
+ PxActor** mActors;
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpArticulation.cpp b/PhysX_3.4/Source/PhysX/src/NpArticulation.cpp
new file mode 100644
index 00000000..5ec4e6ef
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpArticulation.cpp
@@ -0,0 +1,528 @@
+// 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/PxTransform.h"
+#include "NpArticulation.h"
+#include "NpArticulationLink.h"
+#include "NpWriteCheck.h"
+#include "NpReadCheck.h"
+#include "NpFactory.h"
+#include "ScbArticulation.h"
+#include "NpAggregate.h"
+#include "CmUtils.h"
+
+namespace physx
+{
+
+// PX_SERIALIZATION
+void NpArticulation::requires(PxProcessPxBaseCallback& c)
+{
+ // Collect articulation links
+ const PxU32 nbLinks = mArticulationLinks.size();
+ for(PxU32 i=0; i<nbLinks; i++)
+ c.process(*mArticulationLinks[i]);
+}
+
+void NpArticulation::exportExtraData(PxSerializationContext& stream)
+{
+ Cm::exportInlineArray(mArticulationLinks, stream);
+ stream.writeName(mName);
+}
+
+void NpArticulation::importExtraData(PxDeserializationContext& context)
+{
+ Cm::importInlineArray(mArticulationLinks, context);
+ context.readName(mName);
+}
+
+void NpArticulation::resolveReferences(PxDeserializationContext& context)
+{
+ const PxU32 nbLinks = mArticulationLinks.size();
+ for(PxU32 i=0;i<nbLinks;i++)
+ {
+ context.translatePxBase(mArticulationLinks[i]);
+ }
+
+ mAggregate = NULL;
+}
+
+NpArticulation* NpArticulation::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpArticulation* obj = new (address) NpArticulation(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpArticulation);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+NpArticulation::NpArticulation()
+: PxArticulation(PxConcreteType::eARTICULATION, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+, mAggregate(NULL)
+, mName(NULL)
+{
+ PxArticulation::userData = NULL;
+}
+
+
+NpArticulation::~NpArticulation()
+{
+ NpFactory::getInstance().onArticulationRelease(this);
+}
+
+
+void NpArticulation::release()
+{
+ NP_WRITE_CHECK(getOwnerScene());
+
+ NpPhysics::getInstance().notifyDeletionListenersUserRelease(this, userData);
+
+ //!!!AL TODO: Order should not matter in this case. Optimize by having a path which does not restrict release to leaf links or
+ // by using a more advanced data structure
+ PxU32 idx = 0;
+ while(mArticulationLinks.size())
+ {
+ idx = idx % mArticulationLinks.size();
+
+ if (mArticulationLinks[idx]->getNbChildren() == 0)
+ {
+ mArticulationLinks[idx]->releaseInternal(); // deletes joint, link and removes link from list
+ }
+ else
+ {
+ idx++;
+ }
+ }
+
+ NpScene* npScene = getAPIScene();
+ if(npScene)
+ {
+ npScene->getScene().removeArticulation(getArticulation());
+
+ npScene->removeFromArticulationList(*this);
+ }
+
+ mArticulationLinks.clear();
+
+ mArticulation.destroy();
+}
+
+
+PxScene* NpArticulation::getScene() const
+{
+ return getAPIScene();
+}
+
+
+PxU32 NpArticulation::getInternalDriveIterations() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return getArticulation().getInternalDriveIterations();
+}
+
+void NpArticulation::setInternalDriveIterations(PxU32 iterations)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ getArticulation().setInternalDriveIterations(iterations);
+}
+
+PxU32 NpArticulation::getExternalDriveIterations() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return getArticulation().getExternalDriveIterations();
+}
+
+void NpArticulation::setExternalDriveIterations(PxU32 iterations)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ getArticulation().setExternalDriveIterations(iterations);
+}
+
+PxU32 NpArticulation::getMaxProjectionIterations() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return getArticulation().getMaxProjectionIterations();
+}
+
+void NpArticulation::setMaxProjectionIterations(PxU32 iterations)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ getArticulation().setMaxProjectionIterations(iterations);
+}
+
+PxReal NpArticulation::getSeparationTolerance() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return getArticulation().getSeparationTolerance();
+}
+
+void NpArticulation::setSeparationTolerance(PxReal tolerance)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ getArticulation().setSeparationTolerance(tolerance);
+}
+
+void NpArticulation::setSolverIterationCounts(PxU32 positionIters, PxU32 velocityIters)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(positionIters > 0, "Articulation::setSolverIterationCount: positionIters must be more than zero!");
+ PX_CHECK_AND_RETURN(positionIters <= 255, "Articulation::setSolverIterationCount: positionIters must be no greater than 255!");
+ PX_CHECK_AND_RETURN(velocityIters > 0, "Articulation::setSolverIterationCount: velocityIters must be more than zero!");
+ PX_CHECK_AND_RETURN(velocityIters <= 255, "Articulation::setSolverIterationCount: velocityIters must be no greater than 255!");
+
+ getArticulation().setSolverIterationCounts((velocityIters & 0xff) << 8 | (positionIters & 0xff));
+}
+
+
+void NpArticulation::getSolverIterationCounts(PxU32 & positionIters, PxU32 & velocityIters) const
+{
+ NP_READ_CHECK(getOwnerScene());
+ PxU16 x = getArticulation().getSolverIterationCounts();
+ velocityIters = PxU32(x >> 8);
+ positionIters = PxU32(x & 0xff);
+}
+
+
+bool NpArticulation::isSleeping() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN_VAL(getAPIScene(), "Articulation::isSleeping: articulation must be in a scene.", true);
+
+ return getArticulation().isSleeping();
+}
+
+
+void NpArticulation::setSleepThreshold(PxReal threshold)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ getArticulation().setSleepThreshold(threshold);
+}
+
+
+PxReal NpArticulation::getSleepThreshold() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return getArticulation().getSleepThreshold();
+}
+
+void NpArticulation::setStabilizationThreshold(PxReal threshold)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ getArticulation().setFreezeThreshold(threshold);
+}
+
+
+PxReal NpArticulation::getStabilizationThreshold() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return getArticulation().getFreezeThreshold();
+}
+
+
+
+void NpArticulation::setWakeCounter(PxReal wakeCounterValue)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+
+ for(PxU32 i=0; i < mArticulationLinks.size(); i++)
+ {
+ mArticulationLinks[i]->getScbBodyFast().setWakeCounter(wakeCounterValue);
+ }
+
+ getArticulation().setWakeCounter(wakeCounterValue);
+}
+
+
+PxReal NpArticulation::getWakeCounter() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return getArticulation().getWakeCounter();
+}
+
+
+void NpArticulation::wakeUpInternal(bool forceWakeUp, bool autowake)
+{
+ NpScene* scene = getAPIScene();
+ PX_ASSERT(scene);
+ PxReal wakeCounterResetValue = scene->getWakeCounterResetValueInteral();
+
+ Scb::Articulation& a = getArticulation();
+ PxReal wakeCounter = a.getWakeCounter();
+
+ bool needsWakingUp = isSleeping() && (autowake || forceWakeUp);
+ if (autowake && (wakeCounter < wakeCounterResetValue))
+ {
+ wakeCounter = wakeCounterResetValue;
+ needsWakingUp = true;
+ }
+
+ if (needsWakingUp)
+ {
+ for(PxU32 i=0; i < mArticulationLinks.size(); i++)
+ {
+ mArticulationLinks[i]->getScbBodyFast().wakeUpInternal(wakeCounter);
+ }
+
+ a.wakeUpInternal(wakeCounter);
+ }
+}
+
+
+void NpArticulation::wakeUp()
+{
+ NpScene* scene = getAPIScene();
+
+ NP_WRITE_CHECK(getOwnerScene()); // don't use the API scene, since it will be NULL on pending removal
+ PX_CHECK_AND_RETURN(scene, "Articulation::wakeUp: articulation must be in a scene.");
+
+ for(PxU32 i=0; i < mArticulationLinks.size(); i++)
+ {
+ mArticulationLinks[i]->getScbBodyFast().wakeUpInternal(scene->getWakeCounterResetValueInteral());
+ }
+
+ getArticulation().wakeUp();
+}
+
+
+void NpArticulation::putToSleep()
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(getAPIScene(), "Articulation::putToSleep: articulation must be in a scene.");
+
+ for(PxU32 i=0; i < mArticulationLinks.size(); i++)
+ {
+ mArticulationLinks[i]->getScbBodyFast().putToSleepInternal();
+ }
+
+ getArticulation().putToSleep();
+}
+
+
+PxArticulationLink* NpArticulation::createLink(PxArticulationLink* parent, const PxTransform& pose)
+{
+ PX_CHECK_AND_RETURN_NULL(pose.isSane(), "NpArticulation::createLink pose is not valid.");
+ PX_CHECK_AND_RETURN_NULL(mArticulationLinks.size()<64, "NpArticulation::createLink: at most 64 links allowed in an articulation");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ if(parent && mArticulationLinks.empty())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Root articulation link must have NULL parent pointer!");
+ return NULL;
+ }
+
+ if(!parent && !mArticulationLinks.empty())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "Non-root articulation link must have valid parent pointer!");
+ return NULL;
+ }
+
+ NpArticulationLink* parentLink = static_cast<NpArticulationLink*>(parent);
+
+ NpArticulationLink* link = static_cast<NpArticulationLink*>(NpFactory::getInstance().createArticulationLink(*this, parentLink, pose.getNormalized()));
+
+ if(link)
+ {
+ NpScene* scene = getAPIScene();
+ if(scene)
+ scene->addArticulationLink(*link);
+ }
+ return link;
+}
+
+
+PxU32 NpArticulation::getNbLinks() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mArticulationLinks.size();
+}
+
+
+PxU32 NpArticulation::getLinks(PxArticulationLink** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return Cm::getArrayOfPointers(userBuffer, bufferSize, startIndex, mArticulationLinks.begin(), mArticulationLinks.size());
+}
+
+
+PxBounds3 NpArticulation::getWorldBounds(float inflation) const
+{
+ NP_READ_CHECK(getOwnerScene());
+ PxBounds3 bounds = PxBounds3::empty();
+
+ for(PxU32 i=0; i < mArticulationLinks.size(); i++)
+ {
+ bounds.include(mArticulationLinks[i]->getWorldBounds());
+ }
+ PX_ASSERT(bounds.isValid());
+
+ // PT: unfortunately we can't just scale the min/max vectors, we need to go through center/extents.
+ const PxVec3 center = bounds.getCenter();
+ const PxVec3 inflatedExtents = bounds.getExtents() * inflation;
+ return PxBounds3::centerExtents(center, inflatedExtents);
+}
+
+
+PxAggregate* NpArticulation::getAggregate() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mAggregate;
+}
+
+
+void NpArticulation::setName(const char* debugName)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ mName = debugName;
+}
+
+
+const char* NpArticulation::getName() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mName;
+}
+
+
+NpScene* NpArticulation::getAPIScene() const
+{
+ return static_cast<NpScene*>(mArticulation.getScbSceneForAPI() ? mArticulation.getScbSceneForAPI()->getPxScene() : NULL);
+}
+
+
+NpScene* NpArticulation::getOwnerScene() const
+{
+ return static_cast<NpScene*>(mArticulation.getScbScene() ? mArticulation.getScbScene()->getPxScene() : NULL);
+}
+
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+void NpArticulation::visualize(Cm::RenderOutput& out, NpScene* scene)
+{
+ for(PxU32 i=0;i<mArticulationLinks.size();i++)
+ mArticulationLinks[i]->visualize(out, scene);
+}
+#endif // PX_ENABLE_DEBUG_VISUALIZATION
+
+
+PxArticulationDriveCache* NpArticulation::createDriveCache(PxReal compliance, PxU32 driveIterations) const
+{
+ PX_CHECK_AND_RETURN_NULL(getAPIScene(), "PxArticulation::createDriveCache: object must be in a scene");
+ NP_READ_CHECK(getOwnerScene()); // doesn't modify the scene, only reads
+
+ return reinterpret_cast<PxArticulationDriveCache*>(mArticulation.getScArticulation().createDriveCache(compliance, driveIterations));
+}
+
+
+void NpArticulation::updateDriveCache(PxArticulationDriveCache& cache, PxReal compliance, PxU32 driveIterations) const
+{
+ PX_CHECK_AND_RETURN(getAPIScene(), "PxArticulation::updateDriveCache: object must be in a scene");
+
+ Sc::ArticulationDriveCache& c = reinterpret_cast<Sc::ArticulationDriveCache&>(cache);
+ PX_CHECK_AND_RETURN(mArticulation.getScArticulation().getCacheLinkCount(c) == mArticulationLinks.size(), "PxArticulation::updateDriveCache: Articulation size has changed; drive cache is invalid");
+
+ NP_READ_CHECK(getOwnerScene()); // doesn't modify the scene, only reads
+ mArticulation.getScArticulation().updateDriveCache(c, compliance, driveIterations);
+}
+
+void NpArticulation::releaseDriveCache(PxArticulationDriveCache&cache ) const
+{
+ PX_CHECK_AND_RETURN(getAPIScene(), "PxArticulation::releaseDriveCache: object must be in a scene");
+ NP_READ_CHECK(getOwnerScene()); // doesn't modify the scene, only reads
+
+ mArticulation.getScArticulation().releaseDriveCache(reinterpret_cast<Sc::ArticulationDriveCache&>(cache));
+}
+
+void NpArticulation::applyImpulse(PxArticulationLink* link,
+ const PxArticulationDriveCache& driveCache,
+ const PxVec3& force,
+ const PxVec3& torque)
+{
+ PX_CHECK_AND_RETURN(getAPIScene(), "PxArticulation::applyImpulse: object must be in a scene");
+ PX_CHECK_AND_RETURN(force.isFinite() && torque.isFinite(), "PxArticulation::applyImpulse: invalid force/torque");
+ const Sc::ArticulationDriveCache& c = reinterpret_cast<const Sc::ArticulationDriveCache&>(driveCache);
+ PX_CHECK_AND_RETURN(mArticulation.getScArticulation().getCacheLinkCount(c) == mArticulationLinks.size(), "PxArticulation::applyImpulse: Articulation size has changed; drive cache is invalid");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ if(isSleeping())
+ wakeUp();
+
+ mArticulation.getScArticulation().applyImpulse(static_cast<NpArticulationLink*>(link)->getScbBodyFast().getScBody(), c,force, torque);
+ for(PxU32 i=0;i<mArticulationLinks.size();i++)
+ {
+ PxVec3 lv = mArticulationLinks[i]->getScbBodyFast().getScBody().getLinearVelocity(),
+ av = mArticulationLinks[i]->getScbBodyFast().getScBody().getAngularVelocity();
+ mArticulationLinks[i]->setLinearVelocity(lv);
+ mArticulationLinks[i]->setAngularVelocity(av);
+ }
+}
+
+void NpArticulation::computeImpulseResponse(PxArticulationLink* link,
+ PxVec3& linearResponse,
+ PxVec3& angularResponse,
+ const PxArticulationDriveCache& driveCache,
+ const PxVec3& force,
+ const PxVec3& torque) const
+{
+
+ PX_CHECK_AND_RETURN(getAPIScene(), "PxArticulation::computeImpulseResponse: object must be in a scene");
+ PX_CHECK_AND_RETURN(force.isFinite() && torque.isFinite(), "PxArticulation::computeImpulseResponse: invalid force/torque");
+ NP_READ_CHECK(getOwnerScene());
+
+ const Sc::ArticulationDriveCache& c = reinterpret_cast<const Sc::ArticulationDriveCache&>(driveCache);
+ PX_CHECK_AND_RETURN(mArticulation.getScArticulation().getCacheLinkCount(c) == mArticulationLinks.size(), "PxArticulation::computeImpulseResponse: Articulation size has changed; drive cache is invalid");
+ PX_UNUSED(&c);
+
+ mArticulation.getScArticulation().computeImpulseResponse(static_cast<NpArticulationLink*>(link)->getScbBodyFast().getScBody(),
+ linearResponse, angularResponse,
+ reinterpret_cast<const Sc::ArticulationDriveCache&>(driveCache),
+ force, torque);
+}
+
+NpArticulationLink* NpArticulation::getRoot()
+{
+ if(!mArticulationLinks.size())
+ return NULL;
+
+ PX_ASSERT(mArticulationLinks[0]->getInboundJoint()==NULL);
+ return mArticulationLinks[0];
+}
+
+
+Scb::Body* NpArticulationGetRootFromScb(Scb::Articulation&c)
+{
+ const size_t offset = size_t(&(reinterpret_cast<NpArticulation*>(0)->getScbArticulation()));
+ NpArticulation* np = reinterpret_cast<NpArticulation*>(reinterpret_cast<char*>(&c)-offset);
+
+ NpArticulationLink* a = np->getRoot();
+ return a ? &a->getScbBodyFast() : NULL;
+}
+
+}
diff --git a/PhysX_3.4/Source/PhysX/src/NpArticulation.h b/PhysX_3.4/Source/PhysX/src/NpArticulation.h
new file mode 100644
index 00000000..13d68e28
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpArticulation.h
@@ -0,0 +1,184 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_ARTICULATION
+#define PX_PHYSICS_NP_ARTICULATION
+
+#include "PxArticulation.h"
+#include "CmPhysXCommon.h"
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+#include "CmRenderOutput.h"
+#endif
+
+#include "ScbArticulation.h"
+#include "NpArticulationLink.h"
+
+namespace physx
+{
+
+class NpArticulationLink;
+class NpScene;
+class NpAggregate;
+class PxAggregate;
+
+
+class NpArticulation : public PxArticulation, 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:
+ virtual ~NpArticulation();
+
+// PX_SERIALIZATION
+ NpArticulation(PxBaseFlags baseFlags) : PxArticulation(baseFlags), mArticulation(PxEmpty), mArticulationLinks(PxEmpty) {}
+ virtual void exportExtraData(PxSerializationContext& stream);
+ void importExtraData(PxDeserializationContext& context);
+ void resolveReferences(PxDeserializationContext& context);
+ virtual void requires(PxProcessPxBaseCallback& c);
+ static NpArticulation* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+
+ //---------------------------------------------------------------------------------
+ // PxArticulation implementation
+ //---------------------------------------------------------------------------------
+ virtual void release();
+
+ virtual PxScene* getScene() const;
+
+ virtual PxU32 getInternalDriveIterations() const;
+ virtual void setInternalDriveIterations(PxU32 iterations);
+
+ virtual PxU32 getExternalDriveIterations() const;
+ virtual void setExternalDriveIterations(PxU32 iterations);
+
+ virtual PxU32 getMaxProjectionIterations() const;
+ virtual void setMaxProjectionIterations(PxU32 iterations);
+
+ virtual PxReal getSeparationTolerance() const;
+ virtual void setSeparationTolerance(PxReal tolerance);
+
+ virtual void setSleepThreshold(PxReal threshold);
+ virtual PxReal getSleepThreshold() const;
+
+ virtual void setStabilizationThreshold(PxReal threshold);
+ virtual PxReal getStabilizationThreshold() const;
+
+ virtual void setWakeCounter(PxReal wakeCounterValue);
+ virtual PxReal getWakeCounter() const;
+
+ virtual void setSolverIterationCounts(PxU32 positionIters, PxU32 velocityIters);
+ virtual void getSolverIterationCounts(PxU32 & positionIters, PxU32 & velocityIters) const;
+
+ virtual bool isSleeping() const;
+ virtual void wakeUp();
+ virtual void putToSleep();
+
+ virtual PxArticulationLink* createLink(PxArticulationLink* parent, const PxTransform& pose);
+
+ virtual PxU32 getNbLinks() const;
+ virtual PxU32 getLinks(PxArticulationLink** userBuffer, PxU32 bufferSize, PxU32 startIndex) const;
+
+ virtual PxBounds3 getWorldBounds(float inflation=1.01f) const;
+
+ virtual PxAggregate* getAggregate() const;
+
+ // Debug name
+ virtual void setName(const char*);
+ virtual const char* getName() const;
+
+ virtual PxArticulationDriveCache*
+ createDriveCache(PxReal compliance, PxU32 driveIterations) const;
+
+ virtual void updateDriveCache(PxArticulationDriveCache& cache, PxReal compliance, PxU32 driveIterations) const;
+
+ virtual void releaseDriveCache(PxArticulationDriveCache&) const;
+
+ virtual void applyImpulse(PxArticulationLink*,
+ const PxArticulationDriveCache& driveCache,
+ const PxVec3& force,
+ const PxVec3& torque);
+
+ virtual void computeImpulseResponse(PxArticulationLink*,
+ PxVec3& linearResponse,
+ PxVec3& angularResponse,
+ const PxArticulationDriveCache& driveCache,
+ const PxVec3& force,
+ const PxVec3& torque) const;
+
+
+
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ NpArticulation();
+
+ PX_INLINE void addToLinkList(NpArticulationLink& link) { mArticulationLinks.pushBack(&link); }
+ bool removeLinkFromList(NpArticulationLink& link) { PX_ASSERT(mArticulationLinks.find(&link) != mArticulationLinks.end()); return mArticulationLinks.findAndReplaceWithLast(&link); }
+ PX_FORCE_INLINE NpArticulationLink* const* getLinks() { return &mArticulationLinks.front(); }
+
+ NpArticulationLink* getRoot();
+
+ PX_FORCE_INLINE const Scb::Articulation& getArticulation() const { return mArticulation; }
+ PX_FORCE_INLINE Scb::Articulation& getArticulation() { return mArticulation; }
+
+ NpScene* getAPIScene() const;
+ NpScene* getOwnerScene() const; // the scene the user thinks the actor is in, or from which the actor is pending removal
+
+ PX_FORCE_INLINE void setAggregate(NpAggregate* a) { mAggregate = a; }
+
+ void wakeUpInternal(bool forceWakeUp, bool autowake);
+
+ PX_FORCE_INLINE Scb::Articulation& getScbArticulation() { return mArticulation; }
+ PX_FORCE_INLINE const Scb::Articulation& getScbArticulation() const { return mArticulation; }
+
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+public:
+ void visualize(Cm::RenderOutput& out, NpScene* scene);
+#endif
+
+private:
+ Scb::Articulation mArticulation;
+ NpArticulationLinkArray mArticulationLinks;
+ NpAggregate* mAggregate;
+ const char* mName;
+};
+
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpArticulationJoint.cpp b/PhysX_3.4/Source/PhysX/src/NpArticulationJoint.cpp
new file mode 100644
index 00000000..a519c8ec
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpArticulationJoint.cpp
@@ -0,0 +1,403 @@
+// 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 "NpWriteCheck.h"
+#include "NpReadCheck.h"
+
+namespace physx
+{
+
+// PX_SERIALIZATION
+void NpArticulationJoint::resolveReferences(PxDeserializationContext& context)
+{
+ context.translatePxBase(mParent);
+ context.translatePxBase(mChild);
+ // temporary 3.3.1 -> 3.3.2 backwards compatibility patch; remove in 3.4.
+ PxU32 version = context.getPhysXVersion();
+ if(version < 0x03030200)
+ mJoint.getScArticulationJoint().setDriveType(PxArticulationJointDriveType::eTARGET);
+}
+
+NpArticulationJoint* NpArticulationJoint::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpArticulationJoint* obj = new (address) NpArticulationJoint(PxBaseFlags(0));
+ address += sizeof(NpArticulationJoint);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+// ~PX_SERIALIZATION
+
+NpArticulationJoint::NpArticulationJoint(NpArticulationLink& parent,
+ const PxTransform& parentFrame,
+ NpArticulationLink& child,
+ const PxTransform& childFrame)
+: PxArticulationJoint(PxConcreteType::eARTICULATION_JOINT, PxBaseFlag::eOWNS_MEMORY)
+, mJoint(parentFrame, childFrame)
+, mParent(&parent)
+, mChild(&child)
+{}
+
+
+NpArticulationJoint::~NpArticulationJoint()
+{
+}
+
+
+void NpArticulationJoint::release()
+{
+ NpPhysics::getInstance().notifyDeletionListenersUserRelease(this, NULL);
+
+ if (mJoint.getScbSceneForAPI())
+ mJoint.getScbSceneForAPI()->removeArticulationJoint(mJoint);
+
+ mJoint.destroy();
+}
+
+
+
+PxTransform NpArticulationJoint::getParentPose() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mParent->getCMassLocalPose().transform(mJoint.getParentPose());
+}
+
+void NpArticulationJoint::setParentPose(const PxTransform& t)
+{
+ PX_CHECK_AND_RETURN(t.isSane(), "NpArticulationJoint::setParentPose t is not valid.");
+
+ NP_WRITE_CHECK(getOwnerScene());
+ if(mParent==NULL)
+ return;
+
+ mJoint.setParentPose(mParent->getCMassLocalPose().transformInv(t.getNormalized()));
+}
+
+
+
+PxTransform NpArticulationJoint::getChildPose() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mChild->getCMassLocalPose().transform(mJoint.getChildPose());
+}
+
+void NpArticulationJoint::setChildPose(const PxTransform& t)
+{
+ PX_CHECK_AND_RETURN(t.isSane(), "NpArticulationJoint::setChildPose t is not valid.");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setChildPose(mChild->getCMassLocalPose().transformInv(t.getNormalized()));
+}
+
+
+
+void NpArticulationJoint::setTargetOrientation(const PxQuat& p)
+{
+ PX_CHECK_AND_RETURN(mJoint.getDriveType() != PxArticulationJointDriveType::eTARGET || p.isUnit(), "NpArticulationJoint::setTargetOrientation, quat orientation is not valid.");
+ PX_CHECK_AND_RETURN(mJoint.getDriveType() != PxArticulationJointDriveType::eERROR || (p.getImaginaryPart().isFinite() && p.w == 0), "NpArticulationJoint::setTargetOrientation rotation vector orientation is not valid.");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setTargetOrientation(p);
+}
+
+
+PxQuat NpArticulationJoint::getTargetOrientation() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getTargetOrientation();
+}
+
+
+void NpArticulationJoint::setTargetVelocity(const PxVec3& v)
+{
+ PX_CHECK_AND_RETURN(v.isFinite(), "NpArticulationJoint::setTargetVelocity v is not valid.");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setTargetVelocity(v);
+}
+
+
+PxArticulationJointDriveType::Enum NpArticulationJoint::getDriveType() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mJoint.getDriveType();
+}
+
+void NpArticulationJoint::setDriveType(PxArticulationJointDriveType::Enum driveType)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ mJoint.setDriveType(driveType);
+}
+
+
+PxVec3 NpArticulationJoint::getTargetVelocity() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getTargetVelocity();
+}
+
+
+void NpArticulationJoint::setStiffness(PxReal s)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(s) && s >= 0.0f, "PxArticulationJoint::setStiffness: spring coefficient must be >= 0!");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setStiffness(s);
+}
+
+
+PxReal NpArticulationJoint::getStiffness() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getStiffness();
+}
+
+
+void NpArticulationJoint::setDamping(PxReal d)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(d) && d >= 0.0f, "PxArticulationJoint::setDamping: damping coefficient must be >= 0!");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setDamping(d);
+}
+
+
+PxReal NpArticulationJoint::getDamping() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getDamping();
+}
+
+
+void NpArticulationJoint::setSwingLimitContactDistance(PxReal d)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(d) && d >= 0.0f, "PxArticulationJoint::setSwingLimitContactDistance: padding coefficient must be > 0!");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setSwingLimitContactDistance(d);
+}
+
+
+PxReal NpArticulationJoint::getSwingLimitContactDistance() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getSwingLimitContactDistance();
+}
+
+
+void NpArticulationJoint::setTwistLimitContactDistance(PxReal d)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(d) && d >= 0.0f, "PxArticulationJoint::setTwistLimitContactDistance: padding coefficient must be > 0!");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setTwistLimitContactDistance(d);
+}
+
+
+PxReal NpArticulationJoint::getTwistLimitContactDistance() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getTwistLimitContactDistance();
+}
+
+
+void NpArticulationJoint::setInternalCompliance(PxReal r)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(r) && r>0, "PxArticulationJoint::setInternalCompliance: compliance must be > 0");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setInternalCompliance(r);
+}
+
+
+
+PxReal NpArticulationJoint::getInternalCompliance() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getInternalCompliance();
+}
+
+
+void NpArticulationJoint::setExternalCompliance(PxReal r)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(r) && r>0, "PxArticulationJoint::setExternalCompliance: compliance must be > 0");
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setExternalCompliance(r);
+}
+
+
+PxReal NpArticulationJoint::getExternalCompliance() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getExternalCompliance();
+}
+
+
+void NpArticulationJoint::setSwingLimit(PxReal yLimit, PxReal zLimit)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(yLimit) && PxIsFinite(zLimit) && yLimit > 0 && zLimit > 0 && yLimit < PxPi && zLimit < PxPi,
+ "PxArticulationJoint::setSwingLimit: values must be >0 and < Pi");
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setSwingLimit(yLimit, zLimit);
+}
+
+
+void NpArticulationJoint::getSwingLimit(PxReal &yLimit, PxReal &zLimit) const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ mJoint.getSwingLimit(yLimit, zLimit);
+}
+
+
+void NpArticulationJoint::setTangentialStiffness(PxReal stiffness)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(stiffness) && stiffness >= 0, "PxArticulationJoint::setTangentialStiffness: stiffness must be > 0");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setTangentialStiffness(stiffness);
+}
+
+
+PxReal NpArticulationJoint::getTangentialStiffness() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getTangentialStiffness();
+}
+
+
+void NpArticulationJoint::setTangentialDamping(PxReal damping)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(damping) && damping >= 0, "PxArticulationJoint::setTangentialDamping: damping must be > 0");
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setTangentialDamping(damping);
+}
+
+
+PxReal NpArticulationJoint::getTangentialDamping() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getTangentialDamping();
+}
+
+
+
+void NpArticulationJoint::setSwingLimitEnabled(bool e)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setSwingLimitEnabled(e);
+}
+
+
+bool NpArticulationJoint::getSwingLimitEnabled() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getSwingLimitEnabled();
+}
+
+
+void NpArticulationJoint::setTwistLimit(PxReal lower, PxReal upper)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(lower) && PxIsFinite(upper) && lower<upper && lower>-PxPi && upper < PxPi, "PxArticulationJoint::setTwistLimit: illegal parameters");
+
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setTwistLimit(lower, upper);
+}
+
+
+void NpArticulationJoint::getTwistLimit(PxReal &lower, PxReal &upper) const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ mJoint.getTwistLimit(lower, upper);
+}
+
+
+void NpArticulationJoint::setTwistLimitEnabled(bool e)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mJoint.setTwistLimitEnabled(e);
+}
+
+
+bool NpArticulationJoint::getTwistLimitEnabled() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mJoint.getTwistLimitEnabled();
+}
+
+
+NpScene* NpArticulationJoint::getOwnerScene() const
+{
+ return mJoint.getScbScene() ? static_cast<NpScene *>(mJoint.getScbScene()->getPxScene()) : NULL;
+}
+
+
+void NpArticulationJointGetBodiesFromScb(Scb::ArticulationJoint&c, Scb::Body*&b0, Scb::Body*&b1)
+{
+ NpArticulationJoint* np = const_cast<NpArticulationJoint*>(getNpArticulationJoint(&c));
+
+ NpArticulationLink& a0 = np->getParent(), & a1 = np->getChild();
+ b0 = &a0.getScbBodyFast();
+ b1 = &a1.getScbBodyFast();
+}
+
+
+}
diff --git a/PhysX_3.4/Source/PhysX/src/NpArticulationJoint.h b/PhysX_3.4/Source/PhysX/src/NpArticulationJoint.h
new file mode 100644
index 00000000..c1bf03a2
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpArticulationJoint.h
@@ -0,0 +1,159 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_ARTICULATION_JOINT
+#define PX_PHYSICS_NP_ARTICULATION_JOINT
+
+#include "PxArticulationJoint.h"
+#include "ScbArticulationJoint.h"
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+#include "CmRenderOutput.h"
+#endif
+
+namespace physx
+{
+
+class NpScene;
+class NpArticulationLink;
+
+class NpArticulationJoint : public PxArticulationJoint, 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:
+// PX_SERIALIZATION
+ NpArticulationJoint(PxBaseFlags baseFlags) : PxArticulationJoint(baseFlags), mJoint(PxEmpty) {}
+ virtual void resolveReferences(PxDeserializationContext& context);
+ static NpArticulationJoint* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+ void exportExtraData(PxSerializationContext&) {}
+ void importExtraData(PxDeserializationContext&) {}
+ virtual void requires(PxProcessPxBaseCallback&){}
+ virtual bool isSubordinate() const { return true; }
+//~PX_SERIALIZATION
+ NpArticulationJoint(NpArticulationLink& parent,
+ const PxTransform& parentFrame,
+ NpArticulationLink& child,
+ const PxTransform& childFrame);
+
+ virtual ~NpArticulationJoint();
+
+ //---------------------------------------------------------------------------------
+ // PxArticulationJoint implementation
+ //---------------------------------------------------------------------------------
+ // Save
+
+ virtual PxTransform getParentPose() const;
+ virtual void setParentPose(const PxTransform&);
+
+ virtual PxTransform getChildPose() const;
+ virtual void setChildPose(const PxTransform&);
+
+ virtual void setTargetOrientation(const PxQuat&);
+ virtual PxQuat getTargetOrientation() const;
+
+ virtual void setTargetVelocity(const PxVec3&);
+ virtual PxVec3 getTargetVelocity() const;
+
+ virtual void setDriveType(PxArticulationJointDriveType::Enum driveType);
+ virtual PxArticulationJointDriveType::Enum
+ getDriveType() const;
+
+
+ virtual void setStiffness(PxReal);
+ virtual PxReal getStiffness() const;
+
+ virtual void setDamping(PxReal);
+ virtual PxReal getDamping() const;
+
+ virtual void setInternalCompliance(PxReal);
+ virtual PxReal getInternalCompliance() const;
+
+ virtual void setExternalCompliance(PxReal);
+ virtual PxReal getExternalCompliance() const;
+
+ virtual void setSwingLimit(PxReal yLimit, PxReal zLimit);
+ virtual void getSwingLimit(PxReal &yLimit, PxReal &zLimit) const;
+
+ virtual void setTangentialStiffness(PxReal spring);
+ virtual PxReal getTangentialStiffness() const;
+
+ virtual void setTangentialDamping(PxReal damping);
+ virtual PxReal getTangentialDamping() const;
+
+ virtual void setSwingLimitEnabled(bool);
+ virtual bool getSwingLimitEnabled() const;
+
+ virtual void setSwingLimitContactDistance(PxReal contactDistance);
+ virtual PxReal getSwingLimitContactDistance() const;
+
+ virtual void setTwistLimit(PxReal lower, PxReal upper);
+ virtual void getTwistLimit(PxReal &lower, PxReal &upper) const;
+
+ virtual void setTwistLimitEnabled(bool);
+ virtual bool getTwistLimitEnabled() const;
+
+ virtual void setTwistLimitContactDistance(PxReal contactDistance);
+ virtual PxReal getTwistLimitContactDistance() const;
+
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+public:
+ void release();
+
+ PX_INLINE const Scb::ArticulationJoint& getScbArticulationJoint() const { return mJoint; }
+ PX_INLINE Scb::ArticulationJoint& getScbArticulationJoint() { return mJoint; }
+
+ PX_INLINE const NpArticulationLink& getParent() const { return *mParent; }
+ PX_INLINE NpArticulationLink& getParent() { return *mParent; }
+
+ PX_INLINE const NpArticulationLink& getChild() const { return *mChild; }
+ PX_INLINE NpArticulationLink& getChild() { return *mChild; }
+
+private:
+ NpScene* getOwnerScene() const; // the scene the user thinks the actor is in, or from which the actor is pending removal
+
+
+private:
+ Scb::ArticulationJoint mJoint;
+ NpArticulationLink* mParent;
+ NpArticulationLink* mChild;
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpArticulationLink.cpp b/PhysX_3.4/Source/PhysX/src/NpArticulationLink.cpp
new file mode 100644
index 00000000..1843d7d1
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpArticulationLink.cpp
@@ -0,0 +1,384 @@
+// 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 "NpArticulationLink.h"
+#include "NpArticulationJoint.h"
+#include "NpWriteCheck.h"
+#include "NpReadCheck.h"
+#include "ScbArticulation.h"
+#include "CmVisualization.h"
+#include "CmConeLimitHelper.h"
+#include "CmUtils.h"
+#include "NpArticulation.h"
+
+using namespace physx;
+
+// PX_SERIALIZATION
+void NpArticulationLink::requires(PxProcessPxBaseCallback& c)
+{
+ NpArticulationLinkT::requires(c);
+
+ if(mInboundJoint)
+ c.process(*mInboundJoint);
+}
+
+void NpArticulationLink::exportExtraData(PxSerializationContext& stream)
+{
+ NpArticulationLinkT::exportExtraData(stream);
+ Cm::exportInlineArray(mChildLinks, stream);
+}
+
+void NpArticulationLink::importExtraData(PxDeserializationContext& context)
+{
+ NpArticulationLinkT::importExtraData(context);
+ Cm::importInlineArray(mChildLinks, context);
+}
+
+void NpArticulationLink::resolveReferences(PxDeserializationContext& context)
+{
+ context.translatePxBase(mRoot);
+ context.translatePxBase(mInboundJoint);
+ context.translatePxBase(mParent);
+
+ NpArticulationLinkT::resolveReferences(context);
+
+ const PxU32 nbLinks = mChildLinks.size();
+ for(PxU32 i=0;i<nbLinks;i++)
+ context.translatePxBase(mChildLinks[i]);
+}
+
+NpArticulationLink* NpArticulationLink::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpArticulationLink* obj = new (address) NpArticulationLink(PxBaseFlags(0));
+ address += sizeof(NpArticulationLink);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+NpArticulationLink::NpArticulationLink(const PxTransform& bodyPose, NpArticulation& root, NpArticulationLink* parent)
+: NpArticulationLinkT(PxConcreteType::eARTICULATION_LINK, PxBaseFlag::eOWNS_MEMORY, PxActorType::eARTICULATION_LINK, bodyPose)
+, mRoot(&root)
+, mInboundJoint(NULL)
+, mParent(parent)
+{
+ PX_ASSERT(mBody.getScbType() == ScbType::BODY);
+ mBody.setScbType(ScbType::BODY_FROM_ARTICULATION_LINK);
+
+ mRoot->addToLinkList(*this);
+
+ if (parent)
+ parent->addToChildList(*this);
+}
+
+
+NpArticulationLink::~NpArticulationLink()
+{
+}
+
+void NpArticulationLink::releaseInternal()
+{
+ NpPhysics::getInstance().notifyDeletionListenersUserRelease(this, userData);
+
+ NpArticulationLinkT::release();
+
+ mRoot->removeLinkFromList(*this);
+
+ if (mParent)
+ mParent->removeFromChildList(*this);
+
+ if (mInboundJoint)
+ mInboundJoint->release();
+
+ NpScene* npScene = NpActor::getAPIScene(*this);
+ if (npScene)
+ npScene->getScene().removeActor(mBody, true, false);
+
+ mBody.destroy();
+}
+
+
+void NpArticulationLink::release()
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(mRoot->getRoot() != this || NpActor::getOwnerScene(*this) == NULL, "PxArticulationLink::release(): root link may not be released while articulation is in a scene");
+
+ //! this function doesn't get called when the articulation root is released
+ // therefore, put deregistration code etc. into dtor, not here
+
+ if (mChildLinks.empty())
+ {
+ releaseInternal();
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxArticulationLink::release(): Only leaf articulation links can be released. Release call failed");
+ }
+}
+
+
+
+PxTransform NpArticulationLink::getGlobalPose() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ //!!!AL TODO: Need to start from root and compute along the branch to reflect double buffered state of root link
+ return getScbBodyFast().getBody2World() * getScbBodyFast().getBody2Actor().getInverse();
+}
+
+
+PxArticulation& NpArticulationLink::getArticulation() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return *mRoot;
+}
+
+
+PxArticulationJoint* NpArticulationLink::getInboundJoint() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mInboundJoint;
+}
+
+
+PxU32 NpArticulationLink::getNbChildren() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mChildLinks.size();
+}
+
+
+PxU32 NpArticulationLink::getChildren(PxArticulationLink** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return Cm::getArrayOfPointers(userBuffer, bufferSize, startIndex, mChildLinks.begin(), mChildLinks.size());
+}
+
+
+void NpArticulationLink::setCMassLocalPose(const PxTransform& pose)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(pose.isSane(), "PxArticulationLink::setCMassLocalPose: invalid parameter");
+
+ PxTransform p = pose.getNormalized();
+ PxTransform oldpose = getScbBodyFast().getBody2Actor();
+ PxTransform comShift = p.transformInv(oldpose);
+
+ NpArticulationLinkT::setCMassLocalPoseInternal(p);
+
+ if(mInboundJoint)
+ {
+ Scb::ArticulationJoint &j = mInboundJoint->getScbArticulationJoint();
+ j.setChildPose(comShift.transform(j.getChildPose()));
+ }
+
+ for(PxU32 i=0; i<mChildLinks.size(); i++)
+ {
+ Scb::ArticulationJoint &j = static_cast<NpArticulationJoint*>(mChildLinks[i]->getInboundJoint())->getScbArticulationJoint();
+ j.setParentPose(comShift.transform(j.getParentPose()));
+ }
+}
+
+
+void NpArticulationLink::addForce(const PxVec3& force, PxForceMode::Enum mode, bool autowake)
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+ PX_UNUSED(scene);
+
+ PX_CHECK_AND_RETURN(force.isFinite(), "NpArticulationLink::addForce: force is not valid.");
+ NP_WRITE_CHECK(scene);
+ PX_CHECK_AND_RETURN(scene, "NpArticulationLink::addForce: articulation link must be in a scene!");
+
+ addSpatialForce(&force, 0, mode);
+
+ mRoot->wakeUpInternal((!force.isZero()), autowake);
+}
+
+
+void NpArticulationLink::addTorque(const PxVec3& torque, PxForceMode::Enum mode, bool autowake)
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+ PX_UNUSED(scene);
+
+ PX_CHECK_AND_RETURN(torque.isFinite(), "NpArticulationLink::addTorque: force is not valid.");
+ NP_WRITE_CHECK(scene);
+ PX_CHECK_AND_RETURN(scene, "NpArticulationLink::addTorque: articulation link must be in a scene!");
+
+ addSpatialForce(0, &torque, mode);
+
+ mRoot->wakeUpInternal((!torque.isZero()), autowake);
+}
+
+void NpArticulationLink::clearForce(PxForceMode::Enum mode)
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+ PX_UNUSED(scene);
+ NP_WRITE_CHECK(scene);
+ PX_CHECK_AND_RETURN(scene, "NpArticulationLink::clearForce: articulation link must be in a scene!");
+
+ clearSpatialForce(mode, true, false);
+}
+
+void NpArticulationLink::clearTorque(PxForceMode::Enum mode)
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+ PX_UNUSED(scene);
+ NP_WRITE_CHECK(scene);
+ PX_CHECK_AND_RETURN(scene, "NpArticulationLink::clearTorque: articulation link must be in a scene!");
+
+ clearSpatialForce(mode, false, true);
+}
+
+void NpArticulationLink::setGlobalPose(const PxTransform& pose)
+{
+ // clow: no need to test inputs here, it's done in the setGlobalPose function already
+ setGlobalPose(pose, true);
+}
+
+void NpArticulationLink::setGlobalPose(const PxTransform& pose, bool autowake)
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+
+ PX_CHECK_AND_RETURN(pose.isValid(), "NpArticulationLink::setGlobalPose pose is not valid.");
+
+ NP_WRITE_CHECK(scene);
+
+#if PX_CHECKED
+ if(scene)
+ scene->checkPositionSanity(*this, pose, "PxArticulationLink::setGlobalPose");
+#endif
+
+ PxTransform body2World = pose * getScbBodyFast().getBody2Actor();
+ getScbBodyFast().setBody2World(body2World, false);
+
+ if (scene && autowake)
+ mRoot->wakeUpInternal(false, true);
+}
+
+
+void NpArticulationLink::setLinearVelocity(const PxVec3& velocity, bool autowake)
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+
+ PX_CHECK_AND_RETURN(velocity.isFinite(), "NpArticulationLink::setLinearVelocity velocity is not valid.");
+
+ NP_WRITE_CHECK(scene);
+
+ getScbBodyFast().setLinearVelocity(velocity);
+
+ if (scene)
+ mRoot->wakeUpInternal((!velocity.isZero()), autowake);
+}
+
+
+void NpArticulationLink::setAngularVelocity(const PxVec3& velocity, bool autowake)
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+
+ PX_CHECK_AND_RETURN(velocity.isFinite(), "NpArticulationLink::setAngularVelocity velocity is not valid.");
+
+ NP_WRITE_CHECK(scene);
+
+ getScbBodyFast().setAngularVelocity(velocity);
+
+ if (scene)
+ mRoot->wakeUpInternal((!velocity.isZero()), autowake);
+}
+
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+void NpArticulationLink::visualize(Cm::RenderOutput& out, NpScene* scene)
+{
+ NpArticulationLinkT::visualize(out, scene);
+
+ if (getScbBodyFast().getActorFlags() & PxActorFlag::eVISUALIZATION)
+ {
+ PX_ASSERT(getScene());
+ PxReal scale = getScene()->getVisualizationParameter(PxVisualizationParameter::eSCALE);
+
+ PxReal massAxes = scale * getScene()->getVisualizationParameter(PxVisualizationParameter::eBODY_MASS_AXES);
+ if (massAxes != 0)
+ {
+ PxU32 color = 0xff;
+ color = (color<<16 | color<<8 | color);
+ PxVec3 dims = invertDiagInertia(getScbBodyFast().getInverseInertia());
+ dims = getDimsFromBodyInertia(dims, 1.0f / getScbBodyFast().getInverseMass());
+
+ out << color << getScbBodyFast().getBody2World() << Cm::DebugBox(dims * 0.5f);
+ }
+ PxReal frameScale = scale * getScene()->getVisualizationParameter(PxVisualizationParameter::eJOINT_LOCAL_FRAMES);
+ PxReal limitScale = scale * getScene()->getVisualizationParameter(PxVisualizationParameter::eJOINT_LIMITS);
+ if ( frameScale != 0.0f || limitScale != 0.0f )
+ {
+ Cm::ConstraintImmediateVisualizer viz( frameScale, limitScale, out );
+ visualizeJoint( viz );
+ }
+ }
+}
+
+void NpArticulationLink::visualizeJoint(PxConstraintVisualizer& jointViz)
+{
+ NpArticulationLink* parent = getParent();
+ if(parent)
+ {
+ PxTransform cA2w = getGlobalPose().transform(mInboundJoint->getChildPose());
+ PxTransform cB2w = parent->getGlobalPose().transform(mInboundJoint->getParentPose());
+
+ jointViz.visualizeJointFrames(cA2w, cB2w);
+
+ PxTransform parentFrame = cB2w;
+
+ if(cA2w.q.dot(cB2w.q)<0)
+ cB2w.q = -cB2w.q;
+
+ PxTransform cB2cA = cA2w.transformInv(cB2w);
+
+ PxQuat swing, twist;
+ Ps::separateSwingTwist(cB2cA.q,swing,twist);
+
+ PxMat33 cA2w_m(cA2w.q), cB2w_m(cB2w.q);
+
+ PxReal tqPhi = Ps::tanHalf(twist.x, twist.w); // always support (-pi, +pi)
+
+ PxReal lower, upper, yLimit, zLimit;
+
+ mInboundJoint->getTwistLimit(lower, upper);
+ mInboundJoint->getSwingLimit(yLimit, zLimit);
+ PxReal swingPad = mInboundJoint->getSwingLimitContactDistance(), twistPad = mInboundJoint->getTwistLimitContactDistance();
+ jointViz.visualizeAngularLimit(parentFrame, lower, upper, PxAbs(tqPhi) > PxTan(upper-twistPad));
+
+ PxVec3 tanQSwing = PxVec3(0, Ps::tanHalf(swing.z,swing.w), -Ps::tanHalf(swing.y,swing.w));
+ Cm::ConeLimitHelper coneHelper(PxTan(yLimit/4), PxTan(zLimit/4), PxTan(swingPad/4));
+ jointViz.visualizeLimitCone(parentFrame, PxTan(yLimit/4), PxTan(zLimit/4), !coneHelper.contains(tanQSwing));
+ }
+}
+#endif // PX_ENABLE_DEBUG_VISUALIZATION
diff --git a/PhysX_3.4/Source/PhysX/src/NpArticulationLink.h b/PhysX_3.4/Source/PhysX/src/NpArticulationLink.h
new file mode 100644
index 00000000..752fa0bc
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpArticulationLink.h
@@ -0,0 +1,158 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_ARTICULATION_LINK
+#define PX_PHYSICS_NP_ARTICULATION_LINK
+
+#include "NpRigidBodyTemplate.h"
+#include "PxArticulationLink.h"
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+#include "CmRenderOutput.h"
+#endif
+
+namespace physx
+{
+
+class NpArticulation;
+class NpArticulationLink;
+class NpArticulationJoint;
+class PxConstraintVisualizer;
+
+class NpArticulationLink;
+typedef NpRigidBodyTemplate<PxArticulationLink> NpArticulationLinkT;
+
+class NpArticulationLinkArray : public Ps::InlineArray<NpArticulationLink*, 4> //!!!AL TODO: check if default of 4 elements makes sense
+{
+//= 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
+ NpArticulationLinkArray(const PxEMPTY) : Ps::InlineArray<NpArticulationLink*, 4> (PxEmpty) {}
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ NpArticulationLinkArray() : Ps::InlineArray<NpArticulationLink*, 4>(PX_DEBUG_EXP("articulationLinkArray")) {}
+};
+
+
+
+class NpArticulationLink : public NpArticulationLinkT
+{
+//= 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
+ NpArticulationLink(PxBaseFlags baseFlags) : NpArticulationLinkT(baseFlags), mChildLinks(PxEmpty) {}
+ virtual void exportExtraData(PxSerializationContext& stream);
+ void importExtraData(PxDeserializationContext& context);
+ void registerReferences(PxSerializationContext& stream);
+ void resolveReferences(PxDeserializationContext& context);
+ virtual void requires(PxProcessPxBaseCallback& c);
+ virtual bool isSubordinate() const { return true; }
+ static NpArticulationLink* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ virtual ~NpArticulationLink();
+
+ //---------------------------------------------------------------------------------
+ // PxArticulationLink implementation
+ //---------------------------------------------------------------------------------
+ virtual void release();
+
+
+ virtual PxActorType::Enum getType() const { return PxActorType::eARTICULATION_LINK; }
+
+ // Pose
+ virtual void setGlobalPose(const PxTransform& pose);
+ virtual void setGlobalPose(const PxTransform& pose, bool autowake);
+ virtual PxTransform getGlobalPose() const;
+
+ // Velocity
+ virtual void setLinearVelocity(const PxVec3&, bool autowake = true);
+ virtual void setAngularVelocity(const PxVec3&, bool autowake = true);
+
+ virtual PxArticulation& getArticulation() const;
+
+ virtual PxArticulationJoint* getInboundJoint() const;
+
+ virtual PxU32 getNbChildren() const;
+ virtual PxU32 getChildren(PxArticulationLink** userBuffer, PxU32 bufferSize, PxU32 startIndex) const;
+
+ virtual void setCMassLocalPose(const PxTransform& pose);
+
+ virtual void addForce(const PxVec3& force, PxForceMode::Enum mode = PxForceMode::eFORCE, bool autowake = true);
+ virtual void addTorque(const PxVec3& torque, PxForceMode::Enum mode = PxForceMode::eFORCE, bool autowake = true);
+ virtual void clearForce(PxForceMode::Enum mode = PxForceMode::eFORCE);
+ virtual void clearTorque(PxForceMode::Enum mode = PxForceMode::eFORCE);
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ NpArticulationLink(const PxTransform& bodyPose, NpArticulation& root, NpArticulationLink* parent);
+
+ void releaseInternal();
+
+ PX_INLINE NpArticulation& getRoot() { return *mRoot; }
+ PX_INLINE NpArticulationLink* getParent() { return mParent; }
+
+ PX_INLINE void setInboundJoint(NpArticulationJoint& joint) { mInboundJoint = &joint; }
+
+private:
+ PX_INLINE void addToChildList(NpArticulationLink& link) { mChildLinks.pushBack(&link); }
+ PX_INLINE void removeFromChildList(NpArticulationLink& link) { PX_ASSERT(mChildLinks.find(&link) != mChildLinks.end()); mChildLinks.findAndReplaceWithLast(&link); }
+
+public:
+ PX_INLINE NpArticulationLink* const* getChildren() { return mChildLinks.empty() ? NULL : &mChildLinks.front(); }
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+public:
+ void visualize(Cm::RenderOutput& out, NpScene* scene);
+ void visualizeJoint(PxConstraintVisualizer& jointViz);
+#endif
+
+
+private:
+ NpArticulation* mRoot; //!!!AL TODO: Revisit: Could probably be avoided if registration and deregistration in root is handled differently
+ NpArticulationJoint* mInboundJoint;
+ NpArticulationLink* mParent; //!!!AL TODO: Revisit: Some memory waste but makes things faster
+ NpArticulationLinkArray mChildLinks;
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpBatchQuery.cpp b/PhysX_3.4/Source/PhysX/src/NpBatchQuery.cpp
new file mode 100644
index 00000000..f428e706
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpBatchQuery.cpp
@@ -0,0 +1,602 @@
+// 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 "NpBatchQuery.h"
+#include "NpReadCheck.h"
+#include "NpActor.h"
+#include "NpShapeManager.h"
+#include "PsAtomic.h"
+#include "PsFoundation.h"
+#include "PsUtilities.h"
+#include "NpScene.h"
+
+using namespace physx;
+using namespace Sq;
+using namespace Cm;
+
+#if !PX_P64_FAMILY
+PX_COMPILE_TIME_ASSERT(0==(sizeof(PxRaycastHit)& 0x0f));
+PX_COMPILE_TIME_ASSERT(0==(sizeof(PxSweepHit)& 0x0f));
+PX_COMPILE_TIME_ASSERT(0==(sizeof(PxOverlapHit)& 0x0f));
+#endif
+
+#define CHECK_RUNNING(QueryMessage) \
+ if(Ps::atomicCompareExchange(&mBatchQueryIsRunning, -1, 0) == 1)\
+ {\
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, QueryMessage); return;\
+ }
+
+NpBatchQuery::NpBatchQuery(NpScene& owner, const PxBatchQueryDesc& d)
+ : mNpScene(&owner), mNbRaycasts(0), mNbOverlaps(0), mNbSweeps(0), mBatchQueryIsRunning(0), mDesc(d), mPrevOffset(PxU32(eTERMINAL))
+{
+ mHasMtdSweep = false;
+}
+
+NpBatchQuery::~NpBatchQuery()
+{
+}
+
+void NpBatchQuery::setUserMemory(const PxBatchQueryMemory& userMem)
+{
+ if(Ps::atomicCompareExchange(&mBatchQueryIsRunning, 0, 0) != 0)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxBatchQuery::setUserMemory: This batch is still executing, skipping setUserMemory");
+ return;
+ }
+
+ PxBatchQueryDesc& desc = getDesc();
+
+ desc.queryMemory = userMem;
+}
+
+const PxBatchQueryMemory& NpBatchQuery::getUserMemory()
+{
+ return getDesc().queryMemory;
+}
+
+// ROS abbreviates Raycast/Overlap/Sweep
+struct QTypeROS { enum Enum { eRAYCAST = 0, eOVERLAP = 1, eSWEEP = 2 }; }; // AP: perhaps can be shared with some other code
+
+namespace physx
+{
+struct BatchStreamHeader
+{
+ BatchStreamHeader(
+ PxHitFlags aHitFlags, const PxQueryCache* aCache, const PxQueryFilterData& aFd,
+ void* aUserData, PxU16 aMaxTouchHits, QTypeROS::Enum aHitTypeId) :
+ hitFlags(aHitFlags), fd(aFd), userData(aUserData), cache(aCache),
+ maxTouchHits(aMaxTouchHits), hitTypeId(char(aHitTypeId))
+ {
+ nextQueryOffset = PxU32(NpBatchQuery::eTERMINAL);
+ }
+
+ BatchStreamHeader() {}
+
+ // TODO: possibly maintain 3 separate offset lists in the same array for raycasts/overlaps/sweeps
+ // offset of a 4-byte ptr to offset in the previously stored batch query in the stream, this is not a ptr because of reallocs
+ PxU32 nextQueryOffset;
+ PxHitFlags hitFlags;
+ PxQueryFilterData fd;
+ void* userData;
+ const PxQueryCache* cache;
+ PxU16 maxTouchHits;
+ char hitTypeId; // Sq::QTypeROS
+};
+} // namespace physx
+
+static void writeGeom(BatchQueryStream& stream, const PxGeometry& geom)
+{
+ PxGeometryType::Enum geomType = geom.getType();
+ stream.write<PxU32>(PxU32(geomType));
+ switch (geomType)
+ {
+ case PxGeometryType::eCAPSULE:
+ stream.write<PxCapsuleGeometry>(static_cast<const PxCapsuleGeometry&>(geom));
+ break;
+ case PxGeometryType::eSPHERE:
+ stream.write<PxSphereGeometry>(static_cast<const PxSphereGeometry&>(geom));
+ break;
+ case PxGeometryType::eCONVEXMESH:
+ stream.write<PxConvexMeshGeometry>(static_cast<const PxConvexMeshGeometry&>(geom));
+ break;
+ case PxGeometryType::eBOX:
+ stream.write<PxBoxGeometry>(static_cast<const PxBoxGeometry&>(geom));
+ break;
+ case PxGeometryType::ePLANE:
+ case PxGeometryType::eTRIANGLEMESH:
+ case PxGeometryType::eHEIGHTFIELD:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ PX_ALWAYS_ASSERT_MESSAGE("Unsupported geometry type in writeGeom");
+ }
+}
+
+static PxGeometry* readGeom(BatchQueryStreamReader& reader)
+{
+ PxU32 geomType = *reader.read<PxU32>();
+ PxGeometry* anyGeom = NULL;
+ switch (geomType)
+ {
+ case PxGeometryType::eCAPSULE:
+ anyGeom = reader.read<PxCapsuleGeometry>();
+ break;
+ case PxGeometryType::eSPHERE:
+ anyGeom = reader.read<PxSphereGeometry>();
+ break;
+ case PxGeometryType::eCONVEXMESH:
+ anyGeom = reader.read<PxConvexMeshGeometry>();
+ break;
+ case PxGeometryType::eBOX:
+ anyGeom = reader.read<PxBoxGeometry>();
+ break;
+ default:
+ PX_ALWAYS_ASSERT_MESSAGE("Unsupported geometry type in readGeom");
+ }
+
+ return anyGeom;
+}
+
+static void writeQueryInput(BatchQueryStream& stream, const MultiQueryInput& input)
+{
+ stream.write<MultiQueryInput>(input);
+ if (input.rayOrigin)
+ stream.write<PxVec3>(input.rayOrigin);
+ if (input.unitDir)
+ stream.write<PxVec3>(input.unitDir);
+ if (input.pose)
+ stream.write<PxTransform>(input.pose);
+ if (input.geometry)
+ writeGeom(stream, *input.geometry);
+}
+
+static MultiQueryInput* readQueryInput(BatchQueryStreamReader& stream)
+{
+ MultiQueryInput* input = stream.read<MultiQueryInput>();
+ if (input->rayOrigin)
+ input->rayOrigin = stream.read<PxVec3>();
+ if (input->unitDir)
+ input->unitDir = stream.read<PxVec3>();
+ if (input->pose)
+ input->pose = stream.read<PxTransform>();
+ if (input->geometry)
+ input->geometry = readGeom(stream);
+
+ return input;
+}
+
+template<typename ResultType, typename HitType>
+void writeStatus(ResultType* aRes, const PxHitBuffer<HitType>& hits, void* userData, bool overflow)
+{
+ ResultType* res = aRes;
+ res->userData = userData;
+ res->block = hits.block;
+ res->hasBlock = hits.hasBlock;
+ res->nbTouches = hits.nbTouches;
+ res->queryStatus = PxU8(overflow ? PxBatchQueryStatus::eOVERFLOW : PxBatchQueryStatus::eSUCCESS);
+ res->touches = (overflow && res->nbTouches == 0) ? NULL : hits.touches;
+}
+
+void NpBatchQuery::resetResultBuffers()
+{
+ for (PxU32 i = 0; i<mNbRaycasts; i++)
+ {
+ mDesc.queryMemory.userRaycastResultBuffer[i].queryStatus = PxBatchQueryStatus::ePENDING;
+ mDesc.queryMemory.userRaycastResultBuffer[i].hasBlock = false;
+ mDesc.queryMemory.userRaycastResultBuffer[i].nbTouches = 0;
+ mDesc.queryMemory.userRaycastResultBuffer[i].touches = NULL;
+ mDesc.queryMemory.userRaycastResultBuffer[i].userData = NULL;
+ }
+ for (PxU32 i = 0; i<mNbOverlaps; i++)
+ {
+ mDesc.queryMemory.userOverlapResultBuffer[i].queryStatus = PxBatchQueryStatus::ePENDING;
+ mDesc.queryMemory.userOverlapResultBuffer[i].hasBlock = false;
+ mDesc.queryMemory.userOverlapResultBuffer[i].nbTouches = 0;
+ mDesc.queryMemory.userOverlapResultBuffer[i].touches = NULL;
+ mDesc.queryMemory.userOverlapResultBuffer[i].userData = NULL;
+ }
+ for (PxU32 i = 0; i<mNbSweeps; i++)
+ {
+ mDesc.queryMemory.userSweepResultBuffer[i].queryStatus = PxBatchQueryStatus::ePENDING;
+ mDesc.queryMemory.userSweepResultBuffer[i].hasBlock = false;
+ mDesc.queryMemory.userSweepResultBuffer[i].nbTouches = 0;
+ mDesc.queryMemory.userSweepResultBuffer[i].touches = NULL;
+ mDesc.queryMemory.userSweepResultBuffer[i].userData = NULL;
+ }
+}
+
+void NpBatchQuery::finalizeExecute()
+{
+ mPrevOffset = PxU32(eTERMINAL); // reset the first BatchStreamHeader offset
+ mStream.rewind(); // clear out the executed queries - rewind the data stream so that the query object can be reused
+ mNbRaycasts = mNbOverlaps = mNbSweeps = 0; // also reset the counts so the query object can be reused
+ mHasMtdSweep = false; // reset the mtd flag
+
+ Ps::atomicExchange(&mBatchQueryIsRunning, 0);
+}
+
+// fixed memory buffer with extra single hit for overflow detection
+template<typename HitType>
+struct PxOverflowBuffer : PxHitBuffer<HitType>
+{
+ bool overflow;
+ PxU32 saveNbTouches;
+ HitType extraHit;
+ HitType* saveTouches;
+ bool processCalled;
+ PxOverflowBuffer(HitType* hits, PxU32 count) : PxHitBuffer<HitType>(hits, count), overflow(false), processCalled(false)
+ {
+ }
+
+ virtual PxAgain processTouches(const HitType* /*hits*/, PxU32 /*count*/)
+ {
+ if (processCalled)
+ return false;
+ saveTouches = this->touches;
+ saveNbTouches = this->nbTouches;
+ processCalled = true;
+ this->touches = &extraHit;
+ this->maxNbTouches = 1;
+ return true;
+ }
+
+ virtual void finalizeQuery()
+ {
+ if (processCalled)
+ {
+ overflow = (this->nbTouches > 0);
+ this->nbTouches = saveNbTouches;
+ this->touches = saveTouches;
+ }
+ }
+};
+
+void NpBatchQuery::execute()
+{
+ NP_READ_CHECK(mNpScene);
+
+ if(mNbRaycasts)
+ {
+ PX_CHECK_AND_RETURN(mDesc.queryMemory.userRaycastResultBuffer!=NULL, "PxBatchQuery execute: userRaycastResultBuffer is NULL");
+ PX_CHECK_AND_RETURN(mDesc.queryMemory.raycastTouchBufferSize > 0 ?
+ (mDesc.queryMemory.userRaycastTouchBuffer != NULL) : true, "PxBatchQuery execute: userRaycastTouchBuffer is NULL");
+ }
+ if(mNbOverlaps)
+ {
+ PX_CHECK_AND_RETURN(mDesc.queryMemory.userOverlapResultBuffer!=NULL, "PxBatchQuery execute: userOverlapResultBuffer is NULL");
+ PX_CHECK_AND_RETURN(mDesc.queryMemory.overlapTouchBufferSize > 0 ?
+ (mDesc.queryMemory.userOverlapTouchBuffer != NULL) : true, "PxBatchQuery execute: userOverlapTouchBuffer is NULL");
+ }
+ if(mNbSweeps)
+ {
+ PX_CHECK_AND_RETURN(mDesc.queryMemory.userSweepResultBuffer!=NULL, "PxBatchQuery execute: userSweepResultBuffer is NULL");
+ PX_CHECK_AND_RETURN(mDesc.queryMemory.sweepTouchBufferSize > 0 ?
+ (mDesc.queryMemory.userSweepTouchBuffer != NULL) : true, "PxBatchQuery execute: userSweepTouchBuffer is NULL");
+ }
+
+ PX_SIMD_GUARD;
+
+ PX_PROFILE_ZONE("BatchedSceneQuery.execute", mNpScene->getContextId());
+ PxI32 ret = Ps::atomicCompareExchange(&mBatchQueryIsRunning, 1, 0);
+ if(ret == 1)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxBatchQuery::execute: This batch is already executing");
+ return;
+ }
+ else if(ret == -1)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxBatchQuery::execute: Another thread is still adding queries to this batch");
+ return;
+ }
+
+ resetResultBuffers();
+
+ // If PVD is connected and IS_PVD_SQ_ENABLED, record the offsets for queries in pvd buffers and run the queries on PPU
+ bool isSqCollectorLocked = false;
+ PX_UNUSED(isSqCollectorLocked);
+
+#if PX_SUPPORT_PVD
+ PxU32 pvdRayQstartIdx = 0;
+ PxU32 pvdOverlapQstartIdx = 0;
+ PxU32 pvdSweepQstartIdx = 0;
+
+ Vd::ScbScenePvdClient& pvdClient = mNpScene->mScene.getScenePvdClient();
+ const bool needUpdatePvd = pvdClient.checkPvdDebugFlag() && (pvdClient.getScenePvdFlags() & PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES);
+
+ if(needUpdatePvd)
+ {
+ mNpScene->getBatchedSqCollector().getLock().lock();
+ isSqCollectorLocked = true;
+
+ pvdRayQstartIdx = mNpScene->getBatchedSqCollector().mAccumulatedRaycastQueries.size();
+ pvdOverlapQstartIdx = mNpScene->getBatchedSqCollector().mAccumulatedOverlapQueries.size();
+ pvdSweepQstartIdx = mNpScene->getBatchedSqCollector().mAccumulatedSweepQueries.size();
+ }
+#endif
+
+ PxClientID clientId = mDesc.ownerClient;
+
+ // setup local pointers to user provided output buffers
+ PxRaycastHit* raycastHits = mDesc.queryMemory.userRaycastTouchBuffer; PX_UNUSED(raycastHits);
+ PxRaycastQueryResult* raycastResults = mDesc.queryMemory.userRaycastResultBuffer; PX_UNUSED(raycastResults);
+ PxU32 raycastHitsSize = mDesc.queryMemory.raycastTouchBufferSize; PX_UNUSED(raycastHitsSize);
+
+ PxOverlapHit* overlapHits = mDesc.queryMemory.userOverlapTouchBuffer; PX_UNUSED(overlapHits);
+ PxOverlapQueryResult* overlapResults = mDesc.queryMemory.userOverlapResultBuffer; PX_UNUSED(overlapResults);
+ PxU32 overlapHitsSize = mDesc.queryMemory.overlapTouchBufferSize; PX_UNUSED(overlapHitsSize);
+
+ PxSweepHit* sweepHits = mDesc.queryMemory.userSweepTouchBuffer; PX_UNUSED(sweepHits);
+ PxSweepQueryResult* sweepResults = mDesc.queryMemory.userSweepResultBuffer; PX_UNUSED(sweepResults);
+ PxU32 sweepHitsSize = mDesc.queryMemory.sweepTouchBufferSize; PX_UNUSED(sweepHitsSize);
+
+ BatchQueryFilterData bfd(mDesc.filterShaderData, mDesc.filterShaderDataSize, mDesc.preFilterShader, mDesc.postFilterShader);
+
+ // data declarations for double buffering the input stream
+ PxU32 curQueryOffset = 0; // first query starts at 0
+ if (mPrevOffset == eTERMINAL) // except if zero queries were queued
+ {
+ finalizeExecute();
+ return;
+ }
+
+ PxU32 hitsSpaceLeft; PX_UNUSED(hitsSpaceLeft);
+
+ // ====================== parse and execute the batch query memory stream ======================
+ PxU32 queryCount = 0;
+ do {
+ // parse a query from the input stream, create a stream reader at current double buffer
+ BatchQueryStreamReader reader(mStream.begin()+curQueryOffset);
+ BatchStreamHeader& h = *reader.read<BatchStreamHeader>();
+ if (h.fd.clientId == 0)
+ h.fd.clientId = clientId; // override a zero clientId with PxBatchQueryDesc.ownerClient
+
+ curQueryOffset = h.nextQueryOffset;
+ Ps::prefetchLine(mStream.begin() + curQueryOffset);
+
+ MultiQueryInput& input = *readQueryInput(reader);
+
+ // ====================== switch over query type - QTypeROS::eRAYCAST, eOVERLAP, eSWEEP =====================
+ switch (h.hitTypeId)
+ {
+ // =============== Current query is a raycast =====================
+ case QTypeROS::eRAYCAST:
+ {
+ PxU32 nbRaycastHits = PxU32(raycastHits - mDesc.queryMemory.userRaycastTouchBuffer);
+ PX_ASSERT(nbRaycastHits <= raycastHitsSize);
+ hitsSpaceLeft = raycastHitsSize - nbRaycastHits;
+ PxOverflowBuffer<PxRaycastHit> hits(raycastHits, PxMin<PxU32>(h.maxTouchHits, hitsSpaceLeft));
+ mNpScene->NpScene::multiQuery<PxRaycastHit>(input, hits, h.hitFlags, h.cache, h.fd, NULL, &bfd);
+ hits.overflow |= (hitsSpaceLeft == 0 && h.maxTouchHits > 0); // report overflow if 0 space left and maxTouchHits>0
+ writeStatus<PxRaycastQueryResult, PxRaycastHit>(raycastResults++, hits, h.userData, hits.overflow);
+ raycastHits += hits.nbTouches;
+ } break;
+
+ // ================ Current query is an overlap ====================
+ case QTypeROS::eOVERLAP:
+ {
+ PxU32 nbOverlapHits = PxU32(overlapHits - mDesc.queryMemory.userOverlapTouchBuffer);
+ PX_ASSERT(nbOverlapHits <= overlapHitsSize);
+ hitsSpaceLeft = overlapHitsSize - nbOverlapHits;
+ PxOverflowBuffer<PxOverlapHit> hits(overlapHits, PxMin<PxU32>(h.maxTouchHits, hitsSpaceLeft));
+ mNpScene->NpScene::multiQuery<PxOverlapHit>(input, hits, h.hitFlags, h.cache, h.fd, NULL, &bfd);
+ hits.overflow |= (hitsSpaceLeft == 0 && h.maxTouchHits > 0); // report overflow if 0 space left and maxTouchHits>0
+ writeStatus<PxOverlapQueryResult, PxOverlapHit>(overlapResults++, hits, h.userData, hits.overflow);
+ overlapHits += hits.nbTouches;
+ } break;
+
+ // ================== Current query is a sweep =========================
+ case QTypeROS::eSWEEP:
+ {
+
+ PxU32 nbSweepHits = PxU32(sweepHits - mDesc.queryMemory.userSweepTouchBuffer);
+ PX_ASSERT(nbSweepHits <= sweepHitsSize);
+ hitsSpaceLeft = sweepHitsSize - nbSweepHits;
+ PxOverflowBuffer<PxSweepHit> hits(sweepHits, PxMin<PxU32>(h.maxTouchHits, hitsSpaceLeft));
+ mNpScene->NpScene::multiQuery<PxSweepHit>(input, hits, h.hitFlags, h.cache, h.fd, NULL, &bfd);
+ hits.overflow |= (hitsSpaceLeft == 0 && h.maxTouchHits > 0); // report overflow if 0 space left and maxTouchHits>0
+ writeStatus<PxSweepQueryResult, PxSweepHit>(sweepResults++, hits, h.userData, hits.overflow);
+ sweepHits += hits.nbTouches;
+ } break;
+ default:
+ PX_ALWAYS_ASSERT_MESSAGE("Unexpected batch query type (raycast/overlap/sweep).");
+ }
+
+ if (h.nextQueryOffset == eTERMINAL) // end of stream
+ // AP: previously also had a break on hitCount==-1 which is aborted due to out of space
+ // abort stream parsing if we ran into an aborted query (hitCount==-1).. but it was easier to just continue
+ // the perf implications for aborted queries are not a significant consideration and this allows to avoid
+ // writing special case code for filling the query buffers after aborted query
+ break;
+ #undef MULTIQ
+ queryCount++;
+ } while (queryCount < 1000000);
+
+#if PX_SUPPORT_PVD
+ if( isSqCollectorLocked && needUpdatePvd)
+ {
+ mNpScene->getBatchedSqCollector().collectAllBatchedHits( mDesc.queryMemory.userRaycastResultBuffer, mNbRaycasts, pvdRayQstartIdx,
+ mDesc.queryMemory.userOverlapResultBuffer, mNbOverlaps, pvdOverlapQstartIdx,
+ mDesc.queryMemory.userSweepResultBuffer, mNbSweeps, pvdSweepQstartIdx);
+ }
+
+ // Maybe connection is disconnected after the lock
+ if( isSqCollectorLocked )
+ {
+ mNpScene->getBatchedSqCollector().getLock().unlock();
+ isSqCollectorLocked = false;
+ }
+#endif
+
+ finalizeExecute();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void NpBatchQuery::writeBatchHeader(const BatchStreamHeader& h)
+{
+ PxU32 streamPos = PxU32(mStream.getPos()); // save the stream pos before we write the header
+ mStream.write<BatchStreamHeader>(h);
+ // link into a list as offset
+ PxU32* prevPtr = (mPrevOffset == eTERMINAL) ? &mPrevOffset : reinterpret_cast<PxU32*>(mStream.begin()+mPrevOffset);
+ PxU32 headerPtr = streamPos+PX_OFFSET_OF(BatchStreamHeader, nextQueryOffset);
+ *prevPtr = headerPtr;
+ mPrevOffset = headerPtr;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void NpBatchQuery::raycast(
+ const PxVec3& origin, const PxVec3& unitDir, PxReal distance, PxU16 maxTouchHits,
+ PxHitFlags hitFlags, const PxQueryFilterData& fd, void* userData, const PxQueryCache* cache)
+{
+ PX_CHECK_AND_RETURN(distance>0, "PxBatchQuery::raycast: The maximum distance must be greater than zero!");
+ PX_CHECK_AND_RETURN(unitDir.isNormalized(), "PxBatchQuery::raycast: Direction must be normalized");
+ PX_CHECK_AND_RETURN(origin.isFinite(), "PxBatchQuery::raycast: origin is not valid");
+ if (mNbRaycasts >= mDesc.queryMemory.getMaxRaycastsPerExecute())
+ {
+ PX_CHECK_AND_RETURN(mNbRaycasts < mDesc.queryMemory.getMaxRaycastsPerExecute(),
+ "PxBatchQuery: number of raycast() calls exceeds PxBatchQueryMemory::raycastResultBufferSize, query discarded");
+ return;
+ }
+ CHECK_RUNNING("PxBatchQuery::raycast: This batch is still executing, skipping query.");
+ mNbRaycasts++;
+
+ writeBatchHeader(BatchStreamHeader(hitFlags, cache, fd, userData, maxTouchHits, QTypeROS::eRAYCAST));
+ writeQueryInput(mStream, MultiQueryInput(origin, unitDir, distance));
+
+ Ps::atomicExchange(&mBatchQueryIsRunning, 0);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void NpBatchQuery::overlap(
+ const PxGeometry& geometry, const PxTransform& pose, PxU16 maxTouchHits,
+ const PxQueryFilterData& fd, void* userData, const PxQueryCache* cache)
+{
+ PX_CHECK_AND_RETURN(pose.isValid(), "NpBatchQuery::overlapMultiple pose is not valid.");
+ if (mNbOverlaps >= mDesc.queryMemory.getMaxOverlapsPerExecute())
+ {
+ PX_CHECK_AND_RETURN(mNbOverlaps < mDesc.queryMemory.getMaxOverlapsPerExecute(),
+ "PxBatchQuery: number of overlap() calls exceeds PxBatchQueryMemory::overlapResultBufferSize, query discarded");
+ return;
+ }
+ CHECK_RUNNING("PxBatchQuery::overlap: This batch is still executing, skipping query.")
+ mNbOverlaps++;
+
+ writeBatchHeader(BatchStreamHeader(PxHitFlags(), cache, fd, userData, maxTouchHits, QTypeROS::eOVERLAP));
+ writeQueryInput(mStream, MultiQueryInput(&geometry, &pose));
+
+ Ps::atomicExchange(&mBatchQueryIsRunning, 0);
+}
+
+void NpBatchQuery::sweep(
+ const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance, PxU16 maxTouchHits,
+ PxHitFlags hitFlags, const PxQueryFilterData& fd, void* userData, const PxQueryCache* cache, const PxReal inflation)
+{
+ PX_CHECK_AND_RETURN(pose.isValid(), "Batch sweep input check: pose is not valid.");
+ PX_CHECK_AND_RETURN(unitDir.isFinite(), "Batch sweep input check: unitDir is not valid.");
+ PX_CHECK_AND_RETURN(unitDir.isNormalized(), "Batch sweep input check: direction must be normalized");
+ PX_CHECK_AND_RETURN(distance >= 0.0f, "Batch sweep input check: distance cannot be negative");
+ PX_CHECK_AND_RETURN(distance != 0.0f || !(hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP),
+ "Batch sweep input check: zero-length sweep only valid without the PxHitFlag::eASSUME_NO_INITIAL_OVERLAP flag");
+
+ if (mNbSweeps >= mDesc.queryMemory.getMaxSweepsPerExecute())
+ {
+ PX_CHECK_AND_RETURN(mNbSweeps < mDesc.queryMemory.getMaxSweepsPerExecute(),
+ "PxBatchQuery: number of sweep() calls exceeds PxBatchQueryMemory::sweepResultBufferSize, query discarded");
+ return;
+ }
+
+
+ CHECK_RUNNING("PxBatchQuery::sweep: This batch is still executing, skipping query.")
+ mNbSweeps++;
+
+ writeBatchHeader(BatchStreamHeader(hitFlags, cache, fd, userData, maxTouchHits, QTypeROS::eSWEEP));
+
+ //set the MTD flag
+ mHasMtdSweep |= !!(hitFlags & PxHitFlag::eMTD);
+
+ if((hitFlags & PxHitFlag::ePRECISE_SWEEP) && (hitFlags & PxHitFlag::eMTD))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " Precise sweep doesn't support MTD. Perform MTD with default sweep");
+ hitFlags &= ~PxHitFlag::ePRECISE_SWEEP;
+ }
+
+ if((hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP) && (hitFlags & PxHitFlag::eMTD))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " eMTD cannot be used in conjunction with eASSUME_NO_INITIAL_OVERLAP. eASSUME_NO_INITIAL_OVERLAP will be ignored");
+ hitFlags &= ~PxHitFlag::eASSUME_NO_INITIAL_OVERLAP;
+ }
+
+ PxReal realInflation = inflation;
+ if((hitFlags & PxHitFlag::ePRECISE_SWEEP)&& inflation > 0.f)
+ {
+ realInflation = 0.f;
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " Precise sweep doesn't support inflation, inflation will be overwritten to be zero");
+ }
+
+ writeQueryInput(mStream, MultiQueryInput(&geometry, &pose, unitDir, distance, realInflation));
+
+ Ps::atomicExchange(&mBatchQueryIsRunning, 0);
+}
+
+void NpBatchQuery::release()
+{
+ if(Ps::atomicCompareExchange(&mBatchQueryIsRunning, 0, 0) != 0)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxBatchQuery::release: This batch is still executing, skipping release");
+ return;
+ }
+
+ mNpScene->releaseBatchQuery(this);
+}
+
+PxBatchQueryPreFilterShader NpBatchQuery::getPreFilterShader() const
+{
+ return mDesc.preFilterShader;
+}
+
+PxBatchQueryPostFilterShader NpBatchQuery::getPostFilterShader() const
+{
+ return mDesc.postFilterShader;
+}
+
+const void* NpBatchQuery::getFilterShaderData() const
+{
+ return mDesc.filterShaderData;
+}
+
+PxU32 NpBatchQuery::getFilterShaderDataSize() const
+{
+ return mDesc.filterShaderDataSize;
+}
+
+PxClientID NpBatchQuery::getOwnerClient() const
+{
+ return mDesc.ownerClient;
+}
+
+
diff --git a/PhysX_3.4/Source/PhysX/src/NpBatchQuery.h b/PhysX_3.4/Source/PhysX/src/NpBatchQuery.h
new file mode 100644
index 00000000..7fa45890
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpBatchQuery.h
@@ -0,0 +1,167 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_SCENEQUERY
+#define PX_PHYSICS_NP_SCENEQUERY
+/** \addtogroup physics
+@{ */
+
+#include "PxBatchQuery.h"
+#include "PsArray.h"
+#include "PsUserAllocated.h"
+#include "CmPhysXCommon.h"
+#include "PsSync.h"
+
+namespace physx
+{
+
+class NpSceneQueryManager;
+struct BatchStreamHeader;
+class NpScene;
+
+namespace Sq
+{
+class SceneQueryManager;
+}
+
+struct BatchQueryStream : Ps::Array<char>
+{
+ BatchQueryStream() { rewind(); }
+
+ void rewind() { mPosition = 0; }
+
+ PX_FORCE_INLINE PxI32 getPos() { return PxI32(mPosition); } // signed to avoid casts elsewhere
+
+ // write an object of type T to the stream, copying by value
+ template<typename T>
+ PX_FORCE_INLINE void write(const T* val, PxU32 count = 1)
+ {
+ PX_COMPILE_TIME_ASSERT(sizeof(T) > 0);
+ PxU32 newPosition = mPosition + sizeof(T)*count;
+ if (newPosition > capacity())
+ reserve(newPosition+(newPosition<<1));
+ resizeUninitialized(newPosition);
+ T* dest = reinterpret_cast<T*>(begin() + mPosition);
+ for (PxU32 i = 0; i < count; i++)
+ {
+ *dest = *(val+i);
+ dest++;
+ }
+ mPosition = newPosition;
+ }
+
+ template<typename T>
+ PX_FORCE_INLINE void write(const T& val)
+ {
+ write(&val, 1);
+ }
+
+ PX_FORCE_INLINE bool atEnd() const { return mPosition >= size(); }
+
+protected:
+ mutable PxU32 mPosition;
+};
+
+struct BatchQueryStreamReader
+{
+ BatchQueryStreamReader(char* buffer) : mBuffer(buffer), mReadPos(0) {}
+
+ // read an object of type T from the stream (simply returns a pointer without copying)
+ template<typename T>
+ PX_FORCE_INLINE T* read(PxU32 count = 1)
+ {
+ //PX_ASSERT(mPosition+sizeof(T)*count <= size());
+ T* result = reinterpret_cast<T*>(mBuffer+mReadPos);
+ mReadPos += sizeof(T)*count;
+ return result;
+ }
+
+ char* mBuffer;
+ PxU32 mReadPos;
+};
+
+class NpBatchQuery : public PxBatchQuery, public Ps::UserAllocated
+{
+public:
+ NpBatchQuery(NpScene& owner, const PxBatchQueryDesc& d);
+ virtual ~NpBatchQuery();
+
+ // PxBatchQuery interface
+ virtual void execute();
+ virtual void release();
+ virtual PxBatchQueryPreFilterShader getPreFilterShader() const;
+ virtual PxBatchQueryPostFilterShader getPostFilterShader() const;
+ virtual const void* getFilterShaderData() const;
+ virtual PxU32 getFilterShaderDataSize() const;
+ virtual PxClientID getOwnerClient() const;
+ virtual void setUserMemory(const PxBatchQueryMemory& );
+ virtual const PxBatchQueryMemory& getUserMemory();
+
+ virtual void raycast(const PxVec3& origin, const PxVec3& unitDir, PxReal distance, PxU16 maxTouchHits,
+ PxHitFlags hitFlags, const PxQueryFilterData& filterData,
+ void* userData, const PxQueryCache* cache);
+
+ virtual void overlap(const PxGeometry& geometry, const PxTransform& pose, PxU16 maxTouchHits,
+ const PxQueryFilterData& filterData, void* userData,
+ const PxQueryCache* cache);
+
+ virtual void sweep(const PxGeometry& geometry, const PxTransform& pose,
+ const PxVec3& unitDir, const PxReal distance, PxU16 maxTouchHits,
+ PxHitFlags hitFlags, const PxQueryFilterData& filterData,
+ void* userData, const PxQueryCache* cache, const PxReal inflation);
+
+ PxBatchQueryDesc& getDesc() { return mDesc; }
+ virtual const PxBatchQueryDesc& getDesc() const { return mDesc; }
+
+ enum { eTERMINAL = PxU32(-16) }; // -16 so it's aligned to avoid SPU checks
+
+ // sync object for batch query completion wait
+ shdfnd::Sync mSync;
+private:
+ void resetResultBuffers();
+ void finalizeExecute();
+ void writeBatchHeader(const BatchStreamHeader& h);
+
+ NpScene* mNpScene;
+ BatchQueryStream mStream;
+ PxU32 mNbRaycasts, mNbOverlaps, mNbSweeps;
+ volatile PxI32 mBatchQueryIsRunning;
+ PxBatchQueryDesc mDesc;
+ // offset in mStream of the offset to the next query for the last header written by BQ query functions
+ PxU32 mPrevOffset;
+ bool mHasMtdSweep;
+
+ friend class physx::Sq::SceneQueryManager;
+};
+
+}
+
+/** @} */
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpCast.h b/PhysX_3.4/Source/PhysX/src/NpCast.h
new file mode 100644
index 00000000..c67370ef
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpCast.h
@@ -0,0 +1,124 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef PX_PHYSICS_NP_CAST
+#define PX_PHYSICS_NP_CAST
+
+#include "PxPhysXConfig.h"
+#include "NpScene.h"
+#include "NpRigidDynamic.h"
+#include "NpRigidStatic.h"
+#include "NpArticulation.h"
+#include "NpArticulationLink.h"
+#include "NpArticulationJoint.h"
+#include "NpAggregate.h"
+#if PX_USE_PARTICLE_SYSTEM_API
+ #include "NpParticleFluid.h"
+#endif
+#if PX_USE_CLOTH_API
+ #include "NpCloth.h"
+#endif
+
+namespace physx
+{
+ // PT: Scb-to-Np casts
+
+ PX_FORCE_INLINE const NpScene* getNpScene(const Scb::Scene* scene)
+ {
+ const size_t scbOffset = reinterpret_cast<size_t>(&(reinterpret_cast<NpScene*>(0)->getScene()));
+ return reinterpret_cast<const NpScene*>(reinterpret_cast<const char*>(scene) - scbOffset);
+ }
+
+ PX_FORCE_INLINE const NpRigidDynamic* getNpRigidDynamic(const Scb::Body* scbBody)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<NpRigidDynamic*>(0)->getScbActorFast()));
+ return reinterpret_cast<const NpRigidDynamic*>(reinterpret_cast<const char*>(scbBody) - offset);
+ }
+
+ PX_FORCE_INLINE const NpRigidStatic* getNpRigidStatic(const Scb::RigidStatic* scbRigidStatic)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<NpRigidStatic*>(0)->getScbActorFast()));
+ return reinterpret_cast<const NpRigidStatic*>(reinterpret_cast<const char*>(scbRigidStatic) - offset);
+ }
+
+ PX_FORCE_INLINE const NpShape* getNpShape(const Scb::Shape* scbShape)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<NpShape*>(0)->getScbShape()));
+ return reinterpret_cast<const NpShape*>(reinterpret_cast<const char*>(scbShape) - offset);
+ }
+
+ PX_FORCE_INLINE const NpArticulationLink* getNpArticulationLink(const Scb::Body* scbArticulationLink)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<NpArticulationLink*>(0)->getScbActorFast()));
+ return reinterpret_cast<const NpArticulationLink*>(reinterpret_cast<const char*>(scbArticulationLink) - offset);
+ }
+
+ PX_FORCE_INLINE const NpArticulation* getNpArticulation(const Scb::Articulation* scbArticulation)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<NpArticulation*>(0)->getArticulation()));
+ return reinterpret_cast<const NpArticulation*>(reinterpret_cast<const char*>(scbArticulation) - offset);
+ }
+
+ PX_FORCE_INLINE const NpArticulationJoint* getNpArticulationJoint(const Scb::ArticulationJoint* scbArticulationJoint)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<NpArticulationJoint*>(0)->getScbArticulationJoint()));
+ return reinterpret_cast<const NpArticulationJoint*>(reinterpret_cast<const char*>(scbArticulationJoint) - offset);
+ }
+
+ PX_FORCE_INLINE const NpAggregate* getNpAggregate(const Scb::Aggregate* aggregate)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<NpAggregate*>(0)->getScbAggregate()));
+ return reinterpret_cast<const NpAggregate*>(reinterpret_cast<const char*>(aggregate) - offset);
+ }
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ PX_FORCE_INLINE const NpParticleSystem* getNpParticleSystem(const Scb::ParticleSystem* scbParticleSystem)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<NpParticleSystem*>(0)->getScbParticleSystem()));
+ return reinterpret_cast<const NpParticleSystem*>(reinterpret_cast<const char*>(scbParticleSystem) - offset);
+ }
+
+ PX_FORCE_INLINE const NpParticleFluid* getNpParticleFluid(const Scb::ParticleSystem* scbParticleSystem)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<NpParticleFluid*>(0)->getScbParticleSystem()));
+ return reinterpret_cast<const NpParticleFluid*>(reinterpret_cast<const char*>(scbParticleSystem) - offset);
+ }
+#endif
+
+#if PX_USE_CLOTH_API
+ PX_FORCE_INLINE const NpCloth* getNpCloth(const Scb::Cloth* cloth)
+ {
+ const size_t offset = reinterpret_cast<size_t>(&(reinterpret_cast<NpCloth*>(0)->getScbCloth()));
+ return reinterpret_cast<const NpCloth*>(reinterpret_cast<const char*>(cloth) - offset);
+ }
+#endif
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpConnector.h b/PhysX_3.4/Source/PhysX/src/NpConnector.h
new file mode 100644
index 00000000..465b0967
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpConnector.h
@@ -0,0 +1,135 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_CONNECTOR
+#define PX_PHYSICS_NP_CONNECTOR
+
+#include "CmPhysXCommon.h"
+#include "PsInlineArray.h"
+#include "PxSerialFramework.h"
+#include "CmUtils.h"
+#include "PsUtilities.h"
+
+namespace physx
+{
+
+struct NpConnectorType
+{
+ enum Enum
+ {
+ eConstraint,
+ eAggregate,
+ eObserver,
+ eInvalid
+ };
+};
+
+
+class NpConnector
+{
+//= 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:
+ NpConnector() : mType(NpConnectorType::eInvalid), mObject(NULL) {}
+ NpConnector(NpConnectorType::Enum type, PxBase* object) : mType(Ps::to8(type)), mObject(object) {}
+// PX_SERIALIZATION
+ NpConnector(const NpConnector& c)
+ {
+ //special copy constructor that initializes padding bytes for meta data verification (PX_CHECKED only)
+ Cm::markSerializedMem(this, sizeof(NpConnector));
+ mType = c.mType;
+ mObject = c.mObject;
+ }
+
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+
+ PxU8 mType; // Revisit whether the type is really necessary or whether the serializable type is enough.
+ // Since joints might gonna inherit from observers to register for constraint release events, the type
+ // is necessary because a joint has its own serializable type and could not be detected as observer anymore.
+ PxU8 mPadding[3]; // PT: padding from prev byte
+ PxBase* mObject; // So far the serialization framework only supports ptr resolve for PxBase objects.
+ // However, so far the observers all are PxBase, hence this choice of type.
+};
+
+
+class NpConnectorIterator
+{
+public:
+ PX_FORCE_INLINE NpConnectorIterator(NpConnector* c, PxU32 size, NpConnectorType::Enum type) : mConnectors(c), mSize(size), mIndex(0), mType(type) {}
+
+ PX_FORCE_INLINE PxBase* getNext()
+ {
+ PxBase* s = NULL;
+ while(mIndex < mSize)
+ {
+ NpConnector& c = mConnectors[mIndex];
+ mIndex++;
+ if (c.mType == mType)
+ return c.mObject;
+ }
+ return s;
+ }
+
+private:
+ NpConnector* mConnectors;
+ PxU32 mSize;
+ PxU32 mIndex;
+ NpConnectorType::Enum mType;
+};
+
+
+class NpConnectorArray: public Ps::InlineArray<NpConnector, 4>
+{
+//= 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
+ NpConnectorArray(const PxEMPTY) : Ps::InlineArray<NpConnector, 4> (PxEmpty) {}
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ NpConnectorArray() : Ps::InlineArray<NpConnector, 4>(PX_DEBUG_EXP("connectorArray"))
+ {
+ //special default constructor that initializes padding bytes for meta data verification (PX_CHECKED only)
+ Cm::markSerializedMem(this->mData, 4*sizeof(NpConnector));
+ }
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpConstraint.cpp b/PhysX_3.4/Source/PhysX/src/NpConstraint.cpp
new file mode 100644
index 00000000..798d13b0
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpConstraint.cpp
@@ -0,0 +1,408 @@
+// 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 "PxConstraint.h"
+#include "NpConstraint.h"
+#include "NpPhysics.h"
+#include "NpRigidDynamic.h"
+#include "NpRigidStatic.h"
+#include "NpArticulationLink.h"
+#include "ScbConstraint.h"
+#include "ScbNpDeps.h"
+
+using namespace physx;
+
+void NpConstraint::setConstraintFunctions(PxConstraintConnector& n, const PxConstraintShaderTable& shaders)
+{
+ mConstraint.getScConstraint().setConstraintFunctions(n, shaders);
+
+ //update mConnectorArray, since mActor0 or mActor1 should be in external reference
+ bool bNeedUpdate = false;
+ if(mActor0)
+ {
+ NpActor& npActor = NpActor::getFromPxActor(*mActor0);
+ if(npActor.findConnector(NpConnectorType::eConstraint, this) == 0xffffffff)
+ {
+ bNeedUpdate = true;
+ npActor.addConnector(NpConnectorType::eConstraint, this, "PxConstraint: Add to rigid actor 0: Constraint already added");
+ }
+ }
+
+ if(mActor1)
+ {
+ NpActor& npActor = NpActor::getFromPxActor(*mActor1);
+ if(npActor.findConnector(NpConnectorType::eConstraint, this) == 0xffffffff)
+ {
+ bNeedUpdate = true;
+ npActor.addConnector(NpConnectorType::eConstraint, this, "PxConstraint: Add to rigid actor 1: Constraint already added");
+ }
+ }
+
+ if(bNeedUpdate)
+ {
+ NpScene* newScene = getSceneFromActors(mActor0, mActor1);
+ NpScene* oldScene = getNpScene();
+
+ if (oldScene != newScene)
+ {
+ if (oldScene)
+ {
+ oldScene->removeFromConstraintList(*this);
+ oldScene->getScene().removeConstraint(getScbConstraint());
+ }
+ if (newScene)
+ {
+ newScene->addToConstraintList(*this);
+ newScene->getScene().addConstraint(getScbConstraint());
+ }
+ }
+ }
+}
+
+NpConstraint::NpConstraint(PxRigidActor* actor0, PxRigidActor* actor1, PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize)
+: PxConstraint(PxConcreteType::eCONSTRAINT, PxBaseFlag::eOWNS_MEMORY)
+, mActor0 (actor0)
+, mActor1 (actor1)
+, mConstraint (connector, shaders, dataSize)
+, mIsDirty (true)
+{
+
+ mConstraint.setFlags(shaders.flag);
+ if(actor0)
+ NpActor::getFromPxActor(*actor0).addConnector(NpConnectorType::eConstraint, this, "PxConstraint: Add to rigid actor 0: Constraint already added");
+ if(actor1)
+ NpActor::getFromPxActor(*actor1).addConnector(NpConnectorType::eConstraint, this, "PxConstraint: Add to rigid actor 1: Constraint already added");
+
+ NpScene* s = getSceneFromActors(actor0, actor1);
+ if (s)
+ {
+ s->addToConstraintList(*this);
+ s->getScene().addConstraint(mConstraint);
+ }
+}
+
+
+NpConstraint::~NpConstraint()
+{
+ if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY)
+ mConstraint.getPxConnector()->onConstraintRelease();
+
+ NpFactory::getInstance().onConstraintRelease(this);
+}
+
+void NpConstraint::release()
+{
+ NpScene* npScene = getNpScene();
+ NP_WRITE_CHECK(npScene);
+
+ NpPhysics::getInstance().notifyDeletionListenersUserRelease(this, NULL);
+
+ if(mActor0)
+ NpActor::getFromPxActor(*mActor0).removeConnector(*mActor0, NpConnectorType::eConstraint, this, "PxConstraint: Add to rigid actor 0: Constraint already added");
+ if(mActor1)
+ NpActor::getFromPxActor(*mActor1).removeConnector(*mActor1, NpConnectorType::eConstraint, this, "PxConstraint: Add to rigid actor 1: Constraint already added");
+
+ if (npScene)
+ {
+ npScene->removeFromConstraintList(*this);
+ npScene->getScene().removeConstraint(getScbConstraint());
+ }
+
+ mConstraint.destroy();
+}
+
+// PX_SERIALIZATION
+void NpConstraint::resolveReferences(PxDeserializationContext& context)
+{
+ context.translatePxBase(mActor0);
+ context.translatePxBase(mActor1);
+}
+
+NpConstraint* NpConstraint::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpConstraint* obj = new (address) NpConstraint(PxBaseFlags(0));
+ address += sizeof(NpConstraint);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+
+// ~PX_SERIALIZATION
+
+PxScene* NpConstraint::getScene() const
+{
+ return getNpScene();
+}
+
+void NpConstraint::getActors(PxRigidActor*& actor0, PxRigidActor*& actor1) const
+{
+ NP_READ_CHECK(getNpScene());
+ actor0 = mActor0;
+ actor1 = mActor1;
+}
+
+void NpConstraint::setActors(PxRigidActor* actor0, PxRigidActor* actor1)
+{
+ NP_WRITE_CHECK(getNpScene());
+
+ PX_CHECK_AND_RETURN((actor0 && !actor0->is<PxRigidStatic>()) || (actor1 && !actor1->is<PxRigidStatic>()), "PxConstraint: at least one actor must be non-static");
+ PX_SIMD_GUARD;
+
+ if(mActor0)
+ NpActor::getFromPxActor(*mActor0).removeConnector(*mActor0, NpConnectorType::eConstraint, this, "PxConstraint: Add to rigid actor 0: Constraint already added");
+ if(mActor1)
+ NpActor::getFromPxActor(*mActor1).removeConnector(*mActor1, NpConnectorType::eConstraint, this, "PxConstraint: Add to rigid actor 1: Constraint already added");
+
+ if(actor0)
+ NpActor::getFromPxActor(*actor0).addConnector(NpConnectorType::eConstraint, this, "PxConstraint: Add to rigid actor 0: Constraint already added");
+ if(actor1)
+ NpActor::getFromPxActor(*actor1).addConnector(NpConnectorType::eConstraint, this, "PxConstraint: Add to rigid actor 1: Constraint already added");
+
+ mActor0 = actor0;
+ mActor1 = actor1;
+
+ NpScene* newScene = getSceneFromActors(actor0, actor1);
+ NpScene* oldScene = getNpScene();
+
+ if (oldScene != newScene)
+ {
+ if (oldScene)
+ {
+ oldScene->removeFromConstraintList(*this);
+ oldScene->getScene().removeConstraint(getScbConstraint());
+ }
+
+ getScbConstraint().setBodies(getScbRigidObject(actor0), getScbRigidObject(actor1));
+
+ if (newScene)
+ {
+ newScene->addToConstraintList(*this);
+ newScene->getScene().addConstraint(getScbConstraint());
+ }
+ }
+ else
+ getScbConstraint().setBodies(getScbRigidObject(actor0), getScbRigidObject(actor1));
+}
+
+void NpConstraint::markDirty()
+{
+ mIsDirty = true;
+}
+
+void NpConstraint::setFlags(PxConstraintFlags flags)
+{
+ NP_WRITE_CHECK(getNpScene());
+ // check for eBROKEN which is a read only flag
+ PX_CHECK_AND_RETURN(!(flags & PxConstraintFlag::eBROKEN), "PxConstraintFlag::eBROKEN is a read only flag");
+
+ PX_CHECK_AND_RETURN(!(flags & PxConstraintFlag::eGPU_COMPATIBLE), "PxConstraintFlag::eGPU_COMPATIBLE is an internal flag and is illegal to set via the API");
+
+ PX_SIMD_GUARD;
+
+ mConstraint.setFlags(flags);
+}
+
+PxConstraintFlags NpConstraint::getFlags() const
+{
+ NP_READ_CHECK(getNpScene());
+ return mConstraint.getFlags();
+}
+
+
+void NpConstraint::setFlag(PxConstraintFlag::Enum flag, bool value)
+{
+ NP_WRITE_CHECK(getNpScene());
+
+ // check for eBROKEN which is a read only flag
+ PX_CHECK_AND_RETURN(flag != PxConstraintFlag::eBROKEN, "PxConstraintFlag::eBROKEN is a read only flag");
+
+ PX_CHECK_AND_RETURN(flag != PxConstraintFlag::eGPU_COMPATIBLE, "PxConstraintFlag::eGPU_COMPATIBLE is an internal flag and is illegal to set via the API");
+
+ PX_SIMD_GUARD;
+
+ PxConstraintFlags f = mConstraint.getFlags();
+
+ mConstraint.setFlags(value ? f|flag : f&~flag);
+}
+
+
+void NpConstraint::getForce(PxVec3& linear, PxVec3& angular) const
+{
+ NP_READ_CHECK(getNpScene());
+ mConstraint.getForce(linear, angular);
+}
+
+void NpConstraint::updateConstants()
+{
+ if(!mIsDirty)
+ return;
+
+ //ML - we can't just set dirty to false because this fails with constraints that were created while the scene was buffering!
+ if(mConstraint.updateConstants(mConstraint.getPxConnector()->prepareData()))
+ mIsDirty = false;
+#if PX_SUPPORT_PVD
+ Scb::Scene* scbScene = mConstraint.getScbSceneForAPI();
+ //Changed to use the visual scenes update system which respects
+ //the debugger's connection type flag.
+ if( scbScene && !scbScene->isPhysicsBuffering() )
+ scbScene->getScenePvdClient().updatePvdProperties( &mConstraint );
+#endif
+}
+
+void NpConstraint::setBreakForce(PxReal linear, PxReal angular)
+{
+ NP_WRITE_CHECK(getNpScene());
+ PX_SIMD_GUARD;
+ mConstraint.setBreakForce(linear, angular);
+}
+
+void NpConstraint::getBreakForce(PxReal& linear, PxReal& angular) const
+{
+ NP_READ_CHECK(getNpScene());
+ PX_SIMD_GUARD;
+ mConstraint.getBreakForce(linear, angular);
+}
+
+
+void NpConstraint::setMinResponseThreshold(PxReal threshold)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(threshold) && threshold>=0, "PxConstraint::setMinResponseThreshold: threshold must be non-negative");
+ NP_WRITE_CHECK(getNpScene());
+ PX_SIMD_GUARD;
+ mConstraint.setMinResponseThreshold(threshold);
+}
+
+PxReal NpConstraint::getMinResponseThreshold() const
+{
+ NP_READ_CHECK(getNpScene());
+ PX_SIMD_GUARD;
+ return mConstraint.getMinResponseThreshold();
+}
+
+
+bool NpConstraint::isValid() const
+{
+ NP_READ_CHECK(getNpScene());
+ bool isValid0 = mActor0 && !mActor0->is<PxRigidStatic>();
+ bool isValid1 = mActor1 && !mActor1->is<PxRigidStatic>();
+ return isValid0 || isValid1;
+}
+
+void* NpConstraint::getExternalReference(PxU32& typeID)
+{
+ NP_READ_CHECK(getNpScene());
+ PxConstraintConnector* connector = mConstraint.getPxConnector();
+ return connector->getExternalReference(typeID);
+}
+
+void NpConstraint::comShift(PxRigidActor* actor)
+{
+ PX_ASSERT(actor == mActor0 || actor == mActor1);
+ PxConstraintConnector* connector = mConstraint.getPxConnector();
+ if(actor == mActor0)
+ connector->onComShift(0);
+ if(actor == mActor1)
+ connector->onComShift(1);
+}
+
+void NpConstraint::actorDeleted(PxRigidActor* actor)
+{
+ // the actor cannot be deleted without also removing it from the scene,
+ // which means that the joint will also have been removed from the scene,
+ // so we can just reset the actor here.
+ PX_ASSERT(actor == mActor0 || actor == mActor1);
+
+ if(actor == mActor0)
+ mActor0 = 0;
+ else
+ mActor1 = 0;
+}
+
+
+
+NpScene* NpConstraint::getNpScene() const
+{
+ return mConstraint.getScbSceneForAPI() ? static_cast<NpScene*>(mConstraint.getScbSceneForAPI()->getPxScene()) : NULL;
+}
+
+Scb::RigidObject* NpConstraint::getScbRigidObject(PxRigidActor* a)
+{
+ if(!a)
+ return NULL;
+
+ PxType type = a->getConcreteType();
+
+ if (type == PxConcreteType::eRIGID_DYNAMIC)
+ return &(static_cast<NpRigidDynamic*>(a)->getScbBodyFast());
+ else if (type == PxConcreteType::eARTICULATION_LINK)
+ return &(static_cast<NpArticulationLink*>(a)->getScbBodyFast());
+ else
+ {
+ PX_ASSERT(type == PxConcreteType::eRIGID_STATIC);
+ return &(static_cast<NpRigidStatic*>(a)->getScbRigidStaticFast());
+ }
+}
+
+void physx::NpConstraintGetRigidObjectsFromScb(const Scb::Constraint&c, Scb::RigidObject*&b0, Scb::RigidObject*&b1)
+{
+ const size_t offset = size_t(&(reinterpret_cast<NpConstraint*>(0)->getScbConstraint()));
+ const NpConstraint* np = reinterpret_cast<const NpConstraint*>(reinterpret_cast<const char*>(&c)-offset);
+
+ PxRigidActor* a0, * a1;
+ np->getActors(a0, a1);
+ b0 = NpConstraint::getScbRigidObject(a0);
+ b1 = NpConstraint::getScbRigidObject(a1);
+}
+
+NpScene* NpConstraint::getSceneFromActors() const
+{
+ return getSceneFromActors(mActor0, mActor1);
+}
+
+PX_FORCE_INLINE NpScene* NpConstraint::getSceneFromActors(const PxRigidActor* actor0, const PxRigidActor* actor1)
+{
+ NpScene* s0 = NULL;
+ NpScene* s1 = NULL;
+
+ if (actor0 && (!(actor0->getActorFlags() & PxActorFlag::eDISABLE_SIMULATION)))
+ s0 = static_cast<NpScene*>(actor0->getScene());
+ if (actor1 && (!(actor1->getActorFlags() & PxActorFlag::eDISABLE_SIMULATION)))
+ s1 = static_cast<NpScene*>(actor1->getScene());
+
+#if PX_CHECKED
+ if ((s0 && s1) && (s0 != s1))
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Adding constraint to scene: Actors belong to different scenes, undefined behavior expected!");
+#endif
+
+ if ((!actor0 || s0) && (!actor1 || s1))
+ return s0 ? s0 : s1;
+ else
+ return NULL;
+}
diff --git a/PhysX_3.4/Source/PhysX/src/NpConstraint.h b/PhysX_3.4/Source/PhysX/src/NpConstraint.h
new file mode 100644
index 00000000..b8680a77
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpConstraint.h
@@ -0,0 +1,131 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_CONSTRAINT
+#define PX_PHYSICS_NP_CONSTRAINT
+
+#include "PsUserAllocated.h"
+#include "PxConstraint.h"
+#include "ScbConstraint.h"
+
+namespace physx
+{
+
+class NpScene;
+class NpRigidDynamic;
+
+namespace Scb
+{
+ class RigidObject;
+}
+
+class NpConstraint : public PxConstraint, 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:
+// PX_SERIALIZATION
+ NpConstraint(PxBaseFlags baseFlags) : PxConstraint(baseFlags), mConstraint(PxEmpty) {}
+ virtual void setConstraintFunctions(PxConstraintConnector& n,
+ const PxConstraintShaderTable &t);
+ static NpConstraint* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+ void exportExtraData(PxSerializationContext&) {}
+ void importExtraData(PxDeserializationContext&) { }
+ void resolveReferences(PxDeserializationContext& context);
+ virtual void requires(PxProcessPxBaseCallback&){}
+ virtual bool isSubordinate() const { return true; }
+//~PX_SERIALIZATION
+ NpConstraint(PxRigidActor* actor0, PxRigidActor* actor1, PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize);
+ ~NpConstraint();
+
+ virtual void release();
+
+ virtual PxScene* getScene() const;
+
+ virtual void getActors(PxRigidActor*& actor0, PxRigidActor*& actor1) const;
+ virtual void setActors(PxRigidActor* actor0, PxRigidActor* actor1);
+
+ virtual PxConstraintFlags getFlags() const;
+ virtual void setFlags(PxConstraintFlags flags);
+ virtual void setFlag(PxConstraintFlag::Enum flag, bool value);
+
+ virtual void getForce(PxVec3& linear, PxVec3& angular) const;
+
+ virtual void markDirty();
+
+ virtual void setBreakForce(PxReal linear, PxReal angular);
+ virtual void getBreakForce(PxReal& linear, PxReal& angular) const;
+
+ virtual void setMinResponseThreshold(PxReal threshold);
+ virtual PxReal getMinResponseThreshold() const;
+
+ virtual bool isValid() const;
+
+ virtual void* getExternalReference(PxU32& typeID);
+
+ void initialize(const PxConstraintDesc&, Scb::Constraint*);
+ void updateConstants();
+ void comShift(PxRigidActor*);
+ void actorDeleted(PxRigidActor*);
+
+
+
+ NpScene* getNpScene() const;
+
+ NpScene* getSceneFromActors() const;
+ PX_FORCE_INLINE Scb::Constraint& getScbConstraint() { return mConstraint; }
+ PX_FORCE_INLINE const Scb::Constraint& getScbConstraint() const { return mConstraint; }
+ PX_FORCE_INLINE bool isDirty() const { return mIsDirty; }
+
+
+ static Scb::RigidObject* getScbRigidObject(PxRigidActor*);
+private:
+ PX_FORCE_INLINE static NpScene* getSceneFromActors(const PxRigidActor* actor0, const PxRigidActor* actor1); // Returns the scene if both actors are in the scene, else NULL
+
+ PxRigidActor* mActor0;
+ PxRigidActor* mActor1;
+ Scb::Constraint mConstraint;
+
+ // this used to be stored in Scb, but that doesn't really work since Scb::Constraint's
+ // flags all get cleared on fetchResults. In any case, in order to support O(1)
+ // insert/remove this really wants to be an index into NpScene's dirty joint array
+
+ bool mIsDirty;
+ bool mPaddingFromBool[3]; // PT: because of mIsDirty
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpFactory.cpp b/PhysX_3.4/Source/PhysX/src/NpFactory.cpp
new file mode 100644
index 00000000..bd026191
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpFactory.cpp
@@ -0,0 +1,1256 @@
+// 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 "NpFactory.h"
+#include "NpPhysics.h"
+#include "ScPhysics.h"
+#include "ScbScene.h"
+#include "ScbActor.h"
+#include "GuHeightField.h"
+#include "GuTriangleMesh.h"
+#include "GuConvexMesh.h"
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ #include "NpParticleSystem.h"
+#endif
+
+#if PX_USE_CLOTH_API
+ #include "NpClothFabric.h"
+ #include "PxClothCollisionData.h"
+#endif
+
+#include "NpConnector.h"
+#include "NpPtrTableStorageManager.h"
+#include "CmCollection.h"
+
+using namespace physx;
+
+NpFactory::NpFactory()
+: GuMeshFactory()
+, mConnectorArrayPool(PX_DEBUG_EXP("connectorArrayPool"))
+, mPtrTableStorageManager(PX_NEW(NpPtrTableStorageManager))
+, mMaterialPool(PX_DEBUG_EXP("MaterialPool"))
+#if PX_USE_CLOTH_API
+ , mClothFabricArray(PX_DEBUG_EXP("clothFabricArray"))
+#endif
+#if PX_SUPPORT_PVD
+ , mNpFactoryListener(NULL)
+#endif
+{
+}
+
+namespace
+{
+ template <typename T> void releaseAll(Ps::HashSet<T*>& container)
+ {
+ // a bit tricky: release will call the factory back to remove the object from
+ // the tracking array, immediately evaluating the iterator. Reconstructing the
+ // iterator per delete can be expensive. So, we use a temporary object.
+ //
+ // a coalesced hash would be efficient too, but we only ever iterate over it
+ // here so it's not worth the 2x remove penalty over the normal hash.
+
+ Ps::Array<T*, Ps::ReflectionAllocator<T*> > tmp;
+ tmp.reserve(container.size());
+ for(typename Ps::HashSet<T*>::Iterator iter = container.getIterator(); !iter.done(); ++iter)
+ tmp.pushBack(*iter);
+
+ PX_ASSERT(tmp.size() == container.size());
+ for(PxU32 i=0;i<tmp.size();i++)
+ tmp[i]->release();
+ }
+}
+
+
+
+NpFactory::~NpFactory()
+{
+ PX_DELETE(mPtrTableStorageManager);
+}
+
+
+void NpFactory::release()
+{
+ releaseAll(mAggregateTracking);
+ releaseAll(mConstraintTracking);
+ releaseAll(mArticulationTracking);
+ releaseAll(mActorTracking);
+ while(mShapeTracking.size())
+ static_cast<NpShape*>(mShapeTracking.getEntries()[0])->releaseInternal();
+
+#if PX_USE_CLOTH_API
+ while(mClothFabricArray.size())
+ {
+ mClothFabricArray[0]->release();
+ }
+#endif
+
+ GuMeshFactory::release(); // deletes the class
+}
+
+void NpFactory::createInstance()
+{
+ PX_ASSERT(!mInstance);
+ mInstance = PX_NEW(NpFactory)();
+}
+
+
+void NpFactory::destroyInstance()
+{
+ PX_ASSERT(mInstance);
+ mInstance->release();
+ mInstance = NULL;
+}
+
+
+NpFactory* NpFactory::mInstance = NULL;
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace
+{
+ template <typename T> void addToTracking(Ps::HashSet<T*>& set, T* element, Ps::Mutex& mutex, bool lock=true)
+ {
+ if(!element)
+ return;
+
+ if(lock)
+ mutex.lock();
+
+ set.insert(element);
+
+ if(lock)
+ mutex.unlock();
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////////// Actors
+
+void NpFactory::addRigidStatic(PxRigidStatic* npActor, bool lock)
+{
+ addToTracking<PxActor>(mActorTracking, npActor, mTrackingMutex, lock);
+}
+
+void NpFactory::addRigidDynamic(PxRigidDynamic* npBody, bool lock)
+{
+ addToTracking<PxActor>(mActorTracking, npBody, mTrackingMutex, lock);
+}
+
+void NpFactory::addShape(PxShape* shape, bool lock)
+{
+ // this uses a coalesced hash set rather than a normal hash set so that we can iterate over it efficiently
+ if(!shape)
+ return;
+
+ if(lock)
+ mTrackingMutex.lock();
+
+ mShapeTracking.insert(shape);
+
+ if(lock)
+ mTrackingMutex.unlock();
+}
+
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+namespace
+{
+ NpParticleSystem* createParticleSystem(PxU32 maxParticles, bool perParticleRestOffset)
+ {
+ return NpFactory::getInstance().createNpParticleSystem(maxParticles, perParticleRestOffset);
+ }
+
+ NpParticleFluid* createParticleFluid(PxU32 maxParticles, bool perParticleRestOffset)
+ {
+ return NpFactory::getInstance().createNpParticleFluid(maxParticles, perParticleRestOffset);
+ }
+
+ // pointers to function above, initialized during subsystem registration
+ NpParticleSystem* (*sCreateParticleSystemFn)(PxU32 maxParticles, bool perParticleRestOffset) = 0;
+ NpParticleFluid* (*sCreateParticleFluidFn)(PxU32 maxParticles, bool perParticleRestOffset) = 0;
+}
+
+void NpFactory::registerParticles()
+{
+ sCreateParticleSystemFn = &::createParticleSystem;
+ sCreateParticleFluidFn = &::createParticleFluid;
+}
+
+void NpFactory::addParticleSystem(PxParticleSystem* ps, bool lock)
+{
+ addToTracking<PxActor>(mActorTracking, ps, mTrackingMutex, lock);
+}
+
+void NpFactory::addParticleFluid(PxParticleFluid* fluid, bool lock)
+{
+ addToTracking<PxActor>(mActorTracking, fluid, mTrackingMutex, lock);
+}
+
+NpParticleSystem* NpFactory::createNpParticleSystem(PxU32 maxParticles, bool perParticleRestOffset)
+{
+ NpParticleSystem* npParticleSystem;
+ {
+ Ps::Mutex::ScopedLock lock(mParticleSystemPoolLock);
+ npParticleSystem = mParticleSystemPool.construct(maxParticles, perParticleRestOffset);
+ }
+ return npParticleSystem;
+}
+
+void NpFactory::releaseParticleSystemToPool(NpParticleSystem& particleSystem)
+{
+ PX_ASSERT(particleSystem.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mParticleSystemPoolLock);
+ mParticleSystemPool.destroy(&particleSystem);
+}
+
+NpParticleFluid* NpFactory::createNpParticleFluid(PxU32 maxParticles, bool perParticleRestOffset)
+{
+ NpParticleFluid* npParticleFluid;
+ {
+ Ps::Mutex::ScopedLock lock(mParticleFluidPoolLock);
+ npParticleFluid = mParticleFluidPool.construct(maxParticles, perParticleRestOffset);
+ }
+ return npParticleFluid;
+}
+
+void NpFactory::releaseParticleFluidToPool(NpParticleFluid& particleFluid)
+{
+ PX_ASSERT(particleFluid.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mParticleFluidPoolLock);
+ mParticleFluidPool.destroy(&particleFluid);
+}
+
+PxParticleFluid* NpFactory::createParticleFluid(PxU32 maxParticles, bool perParticleRestOffset)
+{
+ if (!sCreateParticleFluidFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle fluid creation failed. Use PxRegisterParticles to register particle module: returned NULL.");
+ return NULL;
+ }
+
+ PxParticleFluid* fluid = sCreateParticleFluidFn(maxParticles, perParticleRestOffset);
+ if (!fluid)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Particle fluid initialization failed: returned NULL.");
+ return NULL;
+ }
+
+ addParticleFluid(fluid);
+ return fluid;
+}
+
+PxParticleSystem* NpFactory::createParticleSystem(PxU32 maxParticles, bool perParticleRestOffset)
+{
+ if (!sCreateParticleSystemFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Particle system creation failed. Use PxRegisterParticles to register particle module: returned NULL.");
+ return NULL;
+ }
+
+ PxParticleSystem* ps = sCreateParticleSystemFn(maxParticles, perParticleRestOffset);
+ if (!ps)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Particle system initialization failed: returned NULL.");
+ return NULL;
+ }
+
+ addParticleSystem(ps);
+ return ps;
+}
+
+#endif
+
+
+#if PX_USE_CLOTH_API
+
+namespace
+{
+ NpCloth* createCloth(const PxTransform& globalPose, PxClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags)
+ {
+ return NpFactory::getInstance().createNpCloth(globalPose, static_cast<NpClothFabric&>(fabric), particles, flags);
+ }
+
+ NpClothFabric* createClothFabric(PxInputStream& stream)
+ {
+ NpClothFabric* fabric = NpFactory::getInstance().createNpClothFabric();
+ if(fabric)
+ {
+ if(fabric->load(stream))
+ return fabric;
+ fabric->decRefCount();
+ }
+ return NULL;
+ }
+
+ NpClothFabric* createClothFabric(const PxClothFabricDesc& desc)
+ {
+ NpClothFabric* fabric = NpFactory::getInstance().createNpClothFabric();
+ if(fabric)
+ {
+ if(fabric->load(desc))
+ return fabric;
+ fabric->decRefCount();
+ }
+ return NULL;
+ }
+
+ // pointers to functions above, initialized during subsystem registration
+ NpCloth* (*sCreateClothFn)(const PxTransform&, PxClothFabric&, const PxClothParticle*, PxClothFlags) = 0;
+ NpClothFabric* (*sCreateClothFabricFromStreamFn)(PxInputStream&) = 0;
+ NpClothFabric* (*sCreateClothFabricFromDescFn)(const PxClothFabricDesc&) = 0;
+}
+
+void NpFactory::registerCloth()
+{
+ sCreateClothFn = &::createCloth;
+ sCreateClothFabricFromStreamFn = &::createClothFabric;
+ sCreateClothFabricFromDescFn = &::createClothFabric;
+
+ Sc::Physics::getInstance().registerCloth();
+}
+
+void NpFactory::addCloth(PxCloth* cloth, bool lock)
+{
+ addToTracking<PxActor>(mActorTracking, cloth, mTrackingMutex, lock);
+}
+
+NpCloth* NpFactory::createNpCloth(const PxTransform& globalPose, PxClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags)
+{
+ NpCloth* npCloth;
+ {
+ Ps::Mutex::ScopedLock lock(mClothPoolLock);
+ npCloth = mClothPool.construct(globalPose, static_cast<NpClothFabric&>(fabric), particles, flags);
+ }
+ return npCloth;
+}
+
+void NpFactory::releaseClothToPool(NpCloth& cloth)
+{
+ PX_ASSERT(cloth.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mClothPoolLock);
+ mClothPool.destroy(&cloth);
+}
+
+NpClothFabric* NpFactory::createNpClothFabric()
+{
+ NpClothFabric* npClothFabric;
+ {
+ Ps::Mutex::ScopedLock lock(mClothFabricPoolLock);
+ npClothFabric = mClothFabricPool.construct();
+ }
+ return npClothFabric;
+}
+
+void NpFactory::releaseClothFabricToPool(NpClothFabric& clothFabric)
+{
+ PX_ASSERT(clothFabric.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mClothFabricPoolLock);
+ mClothFabricPool.destroy(&clothFabric);
+}
+
+void NpFactory::addClothFabric(NpClothFabric* cf, bool lock)
+{
+ if(lock)
+ {
+ Ps::Mutex::ScopedLock lock_(mTrackingMutex);
+ if(!mClothFabricArray.size())
+ mClothFabricArray.reserve(64);
+
+ mClothFabricArray.pushBack(cf);
+ }
+ else
+ {
+ if(!mClothFabricArray.size())
+ mClothFabricArray.reserve(64);
+
+ mClothFabricArray.pushBack(cf);
+ }
+}
+
+PxClothFabric* NpFactory::createClothFabric(PxInputStream& stream)
+{
+ if(!sCreateClothFabricFromStreamFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Cloth not registered: returned NULL.");
+ return NULL;
+ }
+
+ NpClothFabric* result = (*sCreateClothFabricFromStreamFn)(stream);
+
+ if(result)
+ addClothFabric(result);
+
+ return result;
+}
+
+PxClothFabric* NpFactory::createClothFabric(const PxClothFabricDesc& desc)
+{
+ if(!sCreateClothFabricFromDescFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Cloth not registered: returned NULL.");
+ return NULL;
+ }
+
+ NpClothFabric* result = (*sCreateClothFabricFromDescFn)(desc);
+
+ if(result)
+ addClothFabric(result);
+
+ return result;
+}
+
+bool NpFactory::removeClothFabric(PxClothFabric& cf)
+{
+ NpClothFabric* npClothFabric = &static_cast<NpClothFabric&>(cf);
+
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+
+ // remove the cloth fabric from the array
+ for(PxU32 i=0; i<mClothFabricArray.size(); i++)
+ {
+ if(mClothFabricArray[i]==npClothFabric)
+ {
+ mClothFabricArray.replaceWithLast(i);
+#if PX_SUPPORT_PVD
+ if(mNpFactoryListener)
+ mNpFactoryListener->onNpFactoryBufferRelease(cf);
+#endif
+ return true;
+ }
+ }
+ return false;
+}
+
+PxU32 NpFactory::getNbClothFabrics() const
+{
+ return mClothFabricArray.size();
+}
+
+PxU32 NpFactory::getClothFabrics(PxClothFabric** userBuffer, PxU32 bufferSize) const
+{
+ const PxU32 size = mClothFabricArray.size();
+
+ const PxU32 writeCount = PxMin(size, bufferSize);
+ for(PxU32 i=0; i<writeCount; i++)
+ userBuffer[i] = mClothFabricArray[i];
+
+ return writeCount;
+}
+
+PxCloth* NpFactory::createCloth(const PxTransform& globalPose, PxClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags)
+{
+ PX_CHECK_AND_RETURN_NULL(globalPose.isValid(),"globalPose is not valid. createCloth returns NULL.");
+ PX_CHECK_AND_RETURN_NULL((particles != NULL) && fabric.getNbParticles(), "No particles supplied. createCloth returns NULL.");
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN_NULL(NpCloth::checkParticles(fabric.getNbParticles(), particles), "PxPhysics::createCloth: particle values must be finite and inverse weight must not be negative");
+#endif
+
+ if(!sCreateClothFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Cloth not registered: returned NULL.");
+ return NULL;
+ }
+
+ // create the internal cloth object
+ NpCloth* npCloth = (*sCreateClothFn)(globalPose, fabric, particles, flags);
+ if (npCloth)
+ {
+ addToTracking<PxActor>(mActorTracking, npCloth, mTrackingMutex);
+ return npCloth;
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Cloth initialization failed: returned NULL.");
+ return NULL;
+ }
+}
+#endif
+
+void NpFactory::onActorRelease(PxActor* a)
+{
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+ mActorTracking.erase(a);
+}
+
+void NpFactory::onShapeRelease(PxShape* a)
+{
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+ mShapeTracking.erase(a);
+}
+
+
+void NpFactory::addArticulation(PxArticulation* npArticulation, bool lock)
+{
+ addToTracking<PxArticulation>(mArticulationTracking, npArticulation, mTrackingMutex, lock);
+}
+
+namespace
+{
+ NpArticulation* createArticulation()
+ {
+ NpArticulation* npArticulation = NpFactory::getInstance().createNpArticulation();
+ if (!npArticulation)
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Articulation initialization failed: returned NULL.");
+
+ return npArticulation;
+ }
+
+ NpArticulationLink* createArticulationLink(NpArticulation&root, NpArticulationLink* parent, const PxTransform& pose)
+ {
+ PX_CHECK_AND_RETURN_NULL(pose.isValid(),"Supplied PxArticulation pose is not valid. Articulation link creation method returns NULL.");
+ PX_CHECK_AND_RETURN_NULL((!parent || (&parent->getRoot() == &root)), "specified parent link is not part of the destination articulation. Articulation link creation method returns NULL.");
+
+ NpArticulationLink* npArticulationLink = NpFactory::getInstance().createNpArticulationLink(root, parent, pose);
+ if (!npArticulationLink)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Articulation link initialization failed: returned NULL.");
+ return NULL;
+ }
+
+ if (parent)
+ {
+ PxTransform parentPose = parent->getCMassLocalPose().transformInv(pose);
+ PxTransform childPose = PxTransform(PxIdentity);
+
+ NpArticulationJoint* npArticulationJoint = NpFactory::getInstance().createNpArticulationJoint(*parent, parentPose, *npArticulationLink, childPose);
+ if (!npArticulationJoint)
+ {
+ PX_DELETE(npArticulationLink);
+
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Articulation link initialization failed due to joint creation failure: returned NULL.");
+ return NULL;
+ }
+
+ npArticulationLink->setInboundJoint(*npArticulationJoint);
+ }
+
+ return npArticulationLink;
+ }
+
+ // pointers to functions above, initialized during subsystem registration
+ static NpArticulation* (*sCreateArticulationFn)() = 0;
+ static NpArticulationLink* (*sCreateArticulationLinkFn)(NpArticulation&, NpArticulationLink* parent, const PxTransform& pose) = 0;
+}
+
+void NpFactory::registerArticulations()
+{
+ sCreateArticulationFn = &::createArticulation;
+ sCreateArticulationLinkFn = &::createArticulationLink;
+}
+
+NpArticulation* NpFactory::createNpArticulation()
+{
+ NpArticulation* npArticulation;
+ {
+ Ps::Mutex::ScopedLock lock(mArticulationPoolLock);
+ npArticulation = mArticulationPool.construct();
+ }
+ return npArticulation;
+}
+
+void NpFactory::releaseArticulationToPool(NpArticulation& articulation)
+{
+ PX_ASSERT(articulation.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mArticulationPoolLock);
+ mArticulationPool.destroy(&articulation);
+}
+
+PxArticulation* NpFactory::createArticulation()
+{
+ if(!sCreateArticulationFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Articulations not registered: returned NULL.");
+ return NULL;
+ }
+
+ NpArticulation* npArticulation = (*sCreateArticulationFn)();
+ if(npArticulation)
+ addArticulation(npArticulation);
+
+ return npArticulation;
+}
+
+void NpFactory::onArticulationRelease(PxArticulation* a)
+{
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+ mArticulationTracking.erase(a);
+}
+
+NpArticulationLink* NpFactory::createNpArticulationLink(NpArticulation&root, NpArticulationLink* parent, const PxTransform& pose)
+{
+ NpArticulationLink* npArticulationLink;
+ {
+ Ps::Mutex::ScopedLock lock(mArticulationLinkPoolLock);
+ npArticulationLink = mArticulationLinkPool.construct(pose, root, parent);
+ }
+ return npArticulationLink;
+}
+
+void NpFactory::releaseArticulationLinkToPool(NpArticulationLink& articulationLink)
+{
+ PX_ASSERT(articulationLink.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mArticulationLinkPoolLock);
+ mArticulationLinkPool.destroy(&articulationLink);
+}
+
+PxArticulationLink* NpFactory::createArticulationLink(NpArticulation& root, NpArticulationLink* parent, const PxTransform& pose)
+{
+ if(!sCreateArticulationLinkFn)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Articulations not registered: returned NULL.");
+ return NULL;
+ }
+
+ return (*sCreateArticulationLinkFn)(root, parent, pose);
+}
+
+NpArticulationJoint* NpFactory::createNpArticulationJoint(NpArticulationLink& parent, const PxTransform& parentFrame, NpArticulationLink& child, const PxTransform& childFrame)
+{
+ NpArticulationJoint* npArticulationJoint;
+ {
+ Ps::Mutex::ScopedLock lock(mArticulationJointPoolLock);
+ npArticulationJoint = mArticulationJointPool.construct(parent, parentFrame, child, childFrame);
+ }
+ return npArticulationJoint;
+}
+
+void NpFactory::releaseArticulationJointToPool(NpArticulationJoint& articulationJoint)
+{
+ PX_ASSERT(articulationJoint.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mArticulationJointPoolLock);
+ mArticulationJointPool.destroy(&articulationJoint);
+}
+
+/////////////////////////////////////////////////////////////////////////////// constraint
+
+void NpFactory::addConstraint(PxConstraint* npConstraint, bool lock)
+{
+ addToTracking<PxConstraint>(mConstraintTracking, npConstraint, mTrackingMutex, lock);
+}
+
+PxConstraint* NpFactory::createConstraint(PxRigidActor* actor0, PxRigidActor* actor1, PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize)
+{
+ PX_CHECK_AND_RETURN_NULL((actor0 && !actor0->is<PxRigidStatic>()) || (actor1 && !actor1->is<PxRigidStatic>()), "createConstraint: At least one actor must be dynamic or an articulation link");
+
+ NpConstraint* npConstraint;
+ {
+ Ps::Mutex::ScopedLock lock(mConstraintPoolLock);
+ npConstraint = mConstraintPool.construct(actor0, actor1, connector, shaders, dataSize);
+ }
+ addConstraint(npConstraint);
+ return npConstraint;
+}
+
+void NpFactory::releaseConstraintToPool(NpConstraint& constraint)
+{
+ PX_ASSERT(constraint.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mConstraintPoolLock);
+ mConstraintPool.destroy(&constraint);
+}
+
+void NpFactory::onConstraintRelease(PxConstraint* c)
+{
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+ mConstraintTracking.erase(c);
+}
+
+/////////////////////////////////////////////////////////////////////////////// aggregate
+
+// PX_AGGREGATE
+void NpFactory::addAggregate(PxAggregate* npAggregate, bool lock)
+{
+ addToTracking<PxAggregate>(mAggregateTracking, npAggregate, mTrackingMutex, lock);
+}
+
+PxAggregate* NpFactory::createAggregate(PxU32 maxActors, bool selfCollisions)
+{
+ PX_CHECK_AND_RETURN_NULL(maxActors<=128, "maxActors limited to 128. createAggregate method returns NULL.");
+
+ NpAggregate* npAggregate;
+
+ {
+ Ps::Mutex::ScopedLock lock(mAggregatePoolLock);
+ npAggregate = mAggregatePool.construct(maxActors, selfCollisions);
+ }
+
+ addAggregate(npAggregate);
+ return npAggregate;
+}
+
+void NpFactory::releaseAggregateToPool(NpAggregate& aggregate)
+{
+ PX_ASSERT(aggregate.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mAggregatePoolLock);
+ mAggregatePool.destroy(&aggregate);
+}
+
+void NpFactory::onAggregateRelease(PxAggregate* a)
+{
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+ mAggregateTracking.erase(a);
+}
+//~PX_AGGREGATE
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxMaterial* NpFactory::createMaterial(PxReal staticFriction, PxReal dynamicFriction, PxReal restitution)
+{
+ PX_CHECK_AND_RETURN_NULL(dynamicFriction >= 0.0f, "createMaterial: dynamicFriction must be >= 0.");
+ PX_CHECK_AND_RETURN_NULL(staticFriction >= 0.0f, "createMaterial: staticFriction must be >= 0.");
+ PX_CHECK_AND_RETURN_NULL(restitution >= 0.0f || restitution <= 1.0f, "createMaterial: restitution must be between 0 and 1.");
+
+ Sc::MaterialData data;
+ data.staticFriction = staticFriction;
+ data.dynamicFriction = dynamicFriction;
+ data.restitution = restitution;
+
+ NpMaterial* npMaterial;
+ {
+ Ps::Mutex::ScopedLock lock(mMaterialPoolLock);
+ npMaterial = mMaterialPool.construct(data);
+ }
+ return npMaterial;
+}
+
+void NpFactory::releaseMaterialToPool(NpMaterial& material)
+{
+ PX_ASSERT(material.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mMaterialPoolLock);
+ mMaterialPool.destroy(&material);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+NpConnectorArray* NpFactory::acquireConnectorArray()
+{
+ Ps::MutexT<>::ScopedLock l(mConnectorArrayPoolLock);
+ return mConnectorArrayPool.construct();
+}
+
+void NpFactory::releaseConnectorArray(NpConnectorArray* array)
+{
+ Ps::MutexT<>::ScopedLock l(mConnectorArrayPoolLock);
+ mConnectorArrayPool.destroy(array);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+NpShape* NpFactory::createShape(const PxGeometry& geometry,
+ PxShapeFlags shapeFlags,
+ PxMaterial*const* materials,
+ PxU16 materialCount,
+ bool isExclusive)
+{
+ switch(geometry.getType())
+ {
+ case PxGeometryType::eBOX:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxBoxGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eSPHERE:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxSphereGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eCAPSULE:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxCapsuleGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eCONVEXMESH:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxConvexMeshGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::ePLANE:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxPlaneGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eHEIGHTFIELD:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxHeightFieldGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eTRIANGLEMESH:
+ PX_CHECK_AND_RETURN_NULL(static_cast<const PxTriangleMeshGeometry&>(geometry).isValid(), "Supplied PxGeometry is not valid. Shape creation method returns NULL.");
+ break;
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ PX_ASSERT(0);
+ }
+
+ //
+ // Check for invalid material table setups
+ //
+
+#if PX_CHECKED
+ if (!NpShape::checkMaterialSetup(geometry, "Shape creation", materials, materialCount))
+ return NULL;
+#endif
+
+ Ps::InlineArray<PxU16, 4> materialIndices("NpFactory::TmpMaterialIndexBuffer");
+ materialIndices.resize(materialCount);
+ if (materialCount == 1)
+ {
+ materialIndices[0] = Ps::to16((static_cast<NpMaterial*>(materials[0]))->getHandle());
+ }
+ else
+ {
+ NpMaterial::getMaterialIndices(materials, materialIndices.begin(), materialCount);
+ }
+
+ NpShape* npShape;
+ {
+ Ps::Mutex::ScopedLock lock(mShapePoolLock);
+ PxU16* mi = materialIndices.begin(); // required to placate pool constructor arg passing
+ npShape = mShapePool.construct(geometry, shapeFlags, mi, materialCount, isExclusive);
+ }
+
+ if(!npShape)
+ return NULL;
+
+ for (PxU32 i=0; i < materialCount; i++)
+ static_cast<NpMaterial*>(npShape->getMaterial(i))->incRefCount();
+
+ addShape(npShape);
+
+ return npShape;
+}
+
+void NpFactory::releaseShapeToPool(NpShape& shape)
+{
+ PX_ASSERT(shape.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mShapePoolLock);
+ mShapePool.destroy(&shape);
+}
+
+
+
+PxU32 NpFactory::getNbShapes() const
+{
+ return mShapeTracking.size();
+}
+
+PxU32 NpFactory::getShapes(PxShape** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ if(mShapeTracking.size()<startIndex)
+ return 0;
+ PxU32 count = PxMax(bufferSize, mShapeTracking.size()-startIndex);
+ PxShape*const *shapes = mShapeTracking.getEntries();
+ for(PxU32 i=0;i<count;i++)
+ userBuffer[i] = shapes[startIndex+i];
+ return count;
+}
+
+
+PxRigidStatic* NpFactory::createRigidStatic(const PxTransform& pose)
+{
+ PX_CHECK_AND_RETURN_NULL(pose.isValid(), "pose is not valid. createRigidStatic returns NULL.");
+
+ NpRigidStatic* npActor;
+
+ {
+ Ps::Mutex::ScopedLock lock(mRigidStaticPoolLock);
+ npActor = mRigidStaticPool.construct(pose);
+ }
+
+ addRigidStatic(npActor);
+ return npActor;
+}
+
+void NpFactory::releaseRigidStaticToPool(NpRigidStatic& rigidStatic)
+{
+ PX_ASSERT(rigidStatic.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mRigidStaticPoolLock);
+ mRigidStaticPool.destroy(&rigidStatic);
+}
+
+PxRigidDynamic* NpFactory::createRigidDynamic(const PxTransform& pose)
+{
+ PX_CHECK_AND_RETURN_NULL(pose.isValid(), "pose is not valid. createRigidDynamic returns NULL.");
+
+ NpRigidDynamic* npBody;
+ {
+ Ps::Mutex::ScopedLock lock(mRigidDynamicPoolLock);
+ npBody = mRigidDynamicPool.construct(pose);
+ }
+ addRigidDynamic(npBody);
+ return npBody;
+}
+
+
+void NpFactory::releaseRigidDynamicToPool(NpRigidDynamic& rigidDynamic)
+{
+ PX_ASSERT(rigidDynamic.getBaseFlags() & PxBaseFlag::eOWNS_MEMORY);
+ Ps::Mutex::ScopedLock lock(mRigidDynamicPoolLock);
+ mRigidDynamicPool.destroy(&rigidDynamic);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PT: this function is here to minimize the amount of locks when deserializing a collection
+void NpFactory::addCollection(const Cm::Collection& collection)
+{
+
+ PxU32 nb = collection.getNbObjects();
+ const Ps::Pair<PxBase* const, PxSerialObjectId>* entries = collection.internalGetObjects();
+ // PT: we take the lock only once, here
+ Ps::Mutex::ScopedLock lock(mTrackingMutex);
+
+ for(PxU32 i=0;i<nb;i++)
+ {
+ PxBase* s = entries[i].first;
+ const PxType serialType = s->getConcreteType();
+//////////////////////////
+ if(serialType==PxConcreteType::eHEIGHTFIELD)
+ {
+ Gu::HeightField* gu = static_cast<Gu::HeightField*>(s);
+ gu->setMeshFactory(this);
+ addHeightField(gu, false);
+ }
+ else if(serialType==PxConcreteType::eCONVEX_MESH)
+ {
+ Gu::ConvexMesh* gu = static_cast<Gu::ConvexMesh*>(s);
+ gu->setMeshFactory(this);
+ addConvexMesh(gu, false);
+ }
+ else if(serialType==PxConcreteType::eTRIANGLE_MESH_BVH33 || serialType==PxConcreteType::eTRIANGLE_MESH_BVH34)
+ {
+ Gu::TriangleMesh* gu = static_cast<Gu::TriangleMesh*>(s);
+ gu->setMeshFactory(this);
+ addTriangleMesh(gu, false);
+ }
+//////////////////////////
+#if PX_USE_CLOTH_API
+ else if (serialType==PxConcreteType::eCLOTH_FABRIC)
+ {
+ NpClothFabric* np = static_cast<NpClothFabric*>(s);
+ // PT: TODO: investigate why cloth don't need a "setMeshFactory" call here
+ addClothFabric(np, false);
+ }
+#endif
+ else if(serialType==PxConcreteType::eRIGID_DYNAMIC)
+ {
+ NpRigidDynamic* np = static_cast<NpRigidDynamic*>(s);
+ addRigidDynamic(np, false);
+ }
+ else if(serialType==PxConcreteType::eRIGID_STATIC)
+ {
+ NpRigidStatic* np = static_cast<NpRigidStatic*>(s);
+ addRigidStatic(np, false);
+ }
+ else if(serialType==PxConcreteType::eSHAPE)
+ {
+ NpShape* np = static_cast<NpShape*>(s);
+ addShape(np, false);
+ }
+ else if(serialType==PxConcreteType::eMATERIAL)
+ {
+ }
+ else if(serialType==PxConcreteType::eCONSTRAINT)
+ {
+ NpConstraint* np = static_cast<NpConstraint*>(s);
+ addConstraint(np, false);
+ }
+#if PX_USE_CLOTH_API
+ else if (serialType==PxConcreteType::eCLOTH)
+ {
+ NpCloth* np = static_cast<NpCloth*>(s);
+ addCloth(np, false);
+ }
+#endif
+#if PX_USE_PARTICLE_SYSTEM_API
+ else if(serialType==PxConcreteType::ePARTICLE_SYSTEM)
+ {
+ NpParticleSystem* np = static_cast<NpParticleSystem*>(s);
+ addParticleSystem(np, false);
+ }
+ else if(serialType==PxConcreteType::ePARTICLE_FLUID)
+ {
+ NpParticleFluid* np = static_cast<NpParticleFluid*>(s);
+ addParticleFluid(np, false);
+ }
+#endif
+ else if(serialType==PxConcreteType::eAGGREGATE)
+ {
+ NpAggregate* np = static_cast<NpAggregate*>(s);
+ addAggregate(np, false);
+
+ // PT: TODO: double-check this.... is it correct?
+ for(PxU32 j=0;j<np->getCurrentSizeFast();j++)
+ {
+ PxBase* actor = np->getActorFast(j);
+ const PxType serialType1 = actor->getConcreteType();
+
+ if(serialType1==PxConcreteType::eRIGID_STATIC)
+ addRigidStatic(static_cast<NpRigidStatic*>(actor), false);
+ else if(serialType1==PxConcreteType::eRIGID_DYNAMIC)
+ addRigidDynamic(static_cast<NpRigidDynamic*>(actor), false);
+ else if(serialType1==PxConcreteType::ePARTICLE_SYSTEM)
+ {}
+ else if(serialType1==PxConcreteType::ePARTICLE_FLUID)
+ {}
+ else if(serialType1==PxConcreteType::eARTICULATION_LINK)
+ {}
+ else PX_ASSERT(0);
+ }
+ }
+ else if(serialType==PxConcreteType::eARTICULATION)
+ {
+ NpArticulation* np = static_cast<NpArticulation*>(s);
+ addArticulation(np, false);
+ }
+ else if(serialType==PxConcreteType::eARTICULATION_LINK)
+ {
+// NpArticulationLink* np = static_cast<NpArticulationLink*>(s);
+ }
+ else if(serialType==PxConcreteType::eARTICULATION_JOINT)
+ {
+// NpArticulationJoint* np = static_cast<NpArticulationJoint*>(s);
+ }
+ else
+ {
+// assert(0);
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_SUPPORT_GPU_PHYSX
+void NpFactory::notifyReleaseTriangleMesh(const PxTriangleMesh& tm)
+{
+ NpPhysics::getInstance().getNpPhysicsGpu().releaseTriangleMeshMirror(tm);
+}
+
+void NpFactory::notifyReleaseHeightField(const PxHeightField& hf)
+{
+ NpPhysics::getInstance().getNpPhysicsGpu().releaseHeightFieldMirror(hf);
+}
+
+void NpFactory::notifyReleaseConvexMesh(const PxConvexMesh& cm)
+{
+ NpPhysics::getInstance().getNpPhysicsGpu().releaseConvexMeshMirror(cm);
+}
+#endif
+
+#if PX_SUPPORT_PVD
+void NpFactory::setNpFactoryListener( NpFactoryListener& inListener)
+{
+ mNpFactoryListener = &inListener;
+ addFactoryListener(inListener);
+}
+#endif
+///////////////////////////////////////////////////////////////////////////////
+
+// these calls are issued from the Scb layer when buffered deletes are issued.
+// TODO: we should really push these down as a virtual interface that is part of Scb's reqs
+// to eliminate this link-time dep.
+
+
+static void NpDestroyRigidActor(Scb::RigidStatic& scb)
+{
+ NpRigidStatic* np = const_cast<NpRigidStatic*>(getNpRigidStatic(&scb));
+
+ void* ud = np->userData;
+
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseRigidStaticToPool(*np);
+ else
+ np->~NpRigidStatic();
+
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+
+static void NpDestroyRigidDynamic(Scb::Body& scb)
+{
+ NpRigidDynamic* np = const_cast<NpRigidDynamic*>(getNpRigidDynamic(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseRigidDynamicToPool(*np);
+ else
+ np->~NpRigidDynamic();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+
+#if PX_USE_PARTICLE_SYSTEM_API
+static void NpDestroyParticleSystem(Scb::ParticleSystem& scb)
+{
+ if(scb.getActorType() == PxActorType::ePARTICLE_SYSTEM)
+ {
+ NpParticleSystem* np = const_cast<NpParticleSystem*>(getNpParticleSystem(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseParticleSystemToPool(*np);
+ else
+ np->~NpParticleSystem();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+ }
+ else
+ {
+ NpParticleFluid* np = const_cast<NpParticleFluid*>(getNpParticleFluid(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseParticleFluidToPool(*np);
+ else
+ np->~NpParticleFluid();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+ }
+}
+#endif
+
+static void NpDestroyArticulationLink(Scb::Body& scb)
+{
+ NpArticulationLink* np = const_cast<NpArticulationLink*>(getNpArticulationLink(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseArticulationLinkToPool(*np);
+ else
+ np->~NpArticulationLink();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+
+static void NpDestroyArticulationJoint(Scb::ArticulationJoint& scb)
+{
+ NpArticulationJoint* np = const_cast<NpArticulationJoint*>(getNpArticulationJoint(&scb));
+
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseArticulationJointToPool(*np);
+ else
+ np->~NpArticulationJoint();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, NULL);
+}
+
+static void NpDestroyArticulation(Scb::Articulation& scb)
+{
+ NpArticulation* np = const_cast<NpArticulation*>(getNpArticulation(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseArticulationToPool(*np);
+ else
+ np->~NpArticulation();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+
+static void NpDestroyAggregate(Scb::Aggregate& scb)
+{
+ NpAggregate* np = const_cast<NpAggregate*>(getNpAggregate(&scb));
+
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseAggregateToPool(*np);
+ else
+ np->~NpAggregate();
+
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, NULL);
+}
+
+static void NpDestroyShape(Scb::Shape& scb)
+{
+ NpShape* np = const_cast<NpShape*>(getNpShape(&scb));
+
+ void* ud = np->userData;
+
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseShapeToPool(*np);
+ else
+ np->~NpShape();
+
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+
+static void NpDestroyConstraint(Scb::Constraint& scb)
+{
+ const size_t offset = size_t(&(reinterpret_cast<NpConstraint*>(0)->getScbConstraint()));
+ NpConstraint* np = reinterpret_cast<NpConstraint*>(reinterpret_cast<char*>(&scb)-offset);
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseConstraintToPool(*np);
+ else
+ np->~NpConstraint();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, NULL);
+}
+
+#if PX_USE_CLOTH_API
+static void NpDestroyCloth(Scb::Cloth& scb)
+{
+ NpCloth* np = const_cast<NpCloth*>(getNpCloth(&scb));
+
+ void* ud = np->userData;
+ if(np->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseClothToPool(*np);
+ else
+ np->~NpCloth();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(np, ud);
+}
+#endif
+
+namespace physx
+{
+ void NpDestroy(Scb::Base& base)
+ {
+ switch(base.getScbType())
+ {
+ case ScbType::SHAPE_EXCLUSIVE:
+ case ScbType::SHAPE_SHARED: { NpDestroyShape(static_cast<Scb::Shape&>(base)); }break;
+ case ScbType::BODY: { NpDestroyRigidDynamic(static_cast<Scb::Body&>(base)); }break;
+ case ScbType::BODY_FROM_ARTICULATION_LINK: { NpDestroyArticulationLink(static_cast<Scb::Body&>(base)); }break;
+ case ScbType::RIGID_STATIC: { NpDestroyRigidActor(static_cast<Scb::RigidStatic&>(base)); }break;
+ case ScbType::CONSTRAINT: { NpDestroyConstraint(static_cast<Scb::Constraint&>(base)); }break;
+#if PX_USE_PARTICLE_SYSTEM_API
+ case ScbType::PARTICLE_SYSTEM: { NpDestroyParticleSystem(static_cast<Scb::ParticleSystem&>(base)); }break;
+#endif
+ case ScbType::ARTICULATION: { NpDestroyArticulation(static_cast<Scb::Articulation&>(base)); }break;
+ case ScbType::ARTICULATION_JOINT: { NpDestroyArticulationJoint(static_cast<Scb::ArticulationJoint&>(base)); }break;
+ case ScbType::AGGREGATE: { NpDestroyAggregate(static_cast<Scb::Aggregate&>(base)); }break;
+#if PX_USE_CLOTH_API
+ case ScbType::CLOTH: { NpDestroyCloth(static_cast<Scb::Cloth&>(base)); }break;
+#endif
+ case ScbType::UNDEFINED:
+ case ScbType::TYPE_COUNT:
+ PX_ALWAYS_ASSERT_MESSAGE("NpDestroy: missing type!");
+ break;
+ }
+ }
+}
+
diff --git a/PhysX_3.4/Source/PhysX/src/NpFactory.h b/PhysX_3.4/Source/PhysX/src/NpFactory.h
new file mode 100644
index 00000000..ac8dc6fb
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpFactory.h
@@ -0,0 +1,304 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_FACTORY
+#define PX_PHYSICS_NP_FACTORY
+
+#include "PsPool.h"
+#include "PsMutex.h"
+#include "PsHashSet.h"
+
+#include "GuMeshFactory.h"
+#include "CmPhysXCommon.h"
+#include "PxPhysXConfig.h"
+#include "PxShape.h"
+
+#if PX_USE_CLOTH_API
+#include "cloth/PxClothTypes.h"
+#include "cloth/PxClothFabric.h"
+#endif
+
+namespace physx
+{
+
+class PxActor;
+
+class PxRigidActor;
+
+class PxRigidStatic;
+class NpRigidStatic;
+
+class PxRigidDynamic;
+class NpRigidDynamic;
+
+class NpConnectorArray;
+
+struct PxConstraintShaderTable;
+class PxConstraintConnector;
+class PxConstraint;
+class NpConstraint;
+
+class PxArticulation;
+class NpArticulation;
+class PxArticulationLink;
+class NpArticulationLink;
+class NpArticulationJoint;
+
+class PxParticleBase;
+class PxParticleSystem;
+class NpParticleSystem;
+class PxParticleFluid;
+class NpParticleFluid;
+
+class PxClothFabric;
+class NpClothFabric;
+class PxCloth;
+class NpCloth;
+class PxMaterial;
+class NpMaterial;
+
+class PxGeometry;
+
+class NpShape;
+
+class NpScene;
+
+class PxAggregate;
+class NpAggregate;
+
+class NpConnectorArray;
+class NpPtrTableStorageManager;
+
+namespace Cm
+{
+ class Collection;
+}
+
+namespace Scb
+{
+ class RigidObject;
+}
+
+class NpFactoryListener : public GuMeshFactoryListener
+{
+protected:
+ virtual ~NpFactoryListener(){}
+public:
+#if PX_USE_CLOTH_API
+ virtual void onNpFactoryBufferRelease(PxClothFabric& data) = 0;
+#endif
+};
+
+
+
+class NpFactory : public GuMeshFactory
+{
+ PX_NOCOPY(NpFactory)
+public:
+ NpFactory();
+private:
+ ~NpFactory();
+
+public:
+ static void createInstance();
+ static void destroyInstance();
+ static void registerArticulations();
+ static void registerCloth();
+ static void registerParticles();
+
+ void release();
+
+ void addCollection(const Cm::Collection& collection);
+
+ PX_INLINE static NpFactory& getInstance() { return *mInstance; }
+
+ PxRigidDynamic* createRigidDynamic(const PxTransform& pose);
+ void addRigidDynamic(PxRigidDynamic*, bool lock=true);
+ void releaseRigidDynamicToPool(NpRigidDynamic&);
+
+ PxRigidStatic* createRigidStatic(const PxTransform& pose);
+ void addRigidStatic(PxRigidStatic*, bool lock=true);
+ void releaseRigidStaticToPool(NpRigidStatic&);
+
+ NpShape* createShape(const PxGeometry& geometry,
+ PxShapeFlags shapeFlags,
+ PxMaterial*const* materials,
+ PxU16 materialCount,
+ bool isExclusive);
+
+ void addShape(PxShape*, bool lock=true);
+ void releaseShapeToPool(NpShape&);
+
+ PxU32 getNbShapes() const;
+ PxU32 getShapes(PxShape** userBuffer, PxU32 bufferSize, PxU32 startIndex) const;
+
+ void addConstraint(PxConstraint*, bool lock=true);
+ PxConstraint* createConstraint(PxRigidActor* actor0, PxRigidActor* actor1, PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize);
+ void releaseConstraintToPool(NpConstraint&);
+
+ void addArticulation(PxArticulation*, bool lock=true);
+ PxArticulation* createArticulation();
+ NpArticulation* createNpArticulation();
+ void releaseArticulationToPool(NpArticulation& articulation);
+
+ NpArticulationLink* createNpArticulationLink(NpArticulation&root, NpArticulationLink* parent, const PxTransform& pose);
+ void releaseArticulationLinkToPool(NpArticulationLink& articulation);
+ PxArticulationLink* createArticulationLink(NpArticulation&, NpArticulationLink* parent, const PxTransform& pose);
+
+ NpArticulationJoint* createNpArticulationJoint(NpArticulationLink& parent, const PxTransform& parentFrame, NpArticulationLink& child, const PxTransform& childFrame);
+ void releaseArticulationJointToPool(NpArticulationJoint& articulationJoint);
+
+ void addAggregate(PxAggregate*, bool lock=true);
+ PxAggregate* createAggregate(PxU32 maxActors, bool selfCollisions);
+ void releaseAggregateToPool(NpAggregate&);
+
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ NpParticleSystem* createNpParticleSystem(PxU32 maxParticles, bool perParticleRestOffset);
+ void releaseParticleSystemToPool(NpParticleSystem& ps);
+ NpParticleFluid* createNpParticleFluid(PxU32 maxParticles, bool perParticleRestOffset);
+ void releaseParticleFluidToPool(NpParticleFluid& pf);
+ void addParticleSystem(PxParticleSystem*, bool lock=true);
+ PxParticleSystem* createParticleSystem(PxU32 maxParticles, bool perParticleRestOffset);
+ void addParticleFluid(PxParticleFluid*, bool lock=true);
+ PxParticleFluid* createParticleFluid(PxU32 maxParticles, bool perParticleRestOffset);
+#endif
+
+#if PX_USE_CLOTH_API
+ NpCloth* createNpCloth(const PxTransform& globalPose, PxClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags);
+ void releaseClothToPool(NpCloth& cloth);
+ void addCloth(PxCloth* cloth, bool lock=true);
+ void addClothFabric(NpClothFabric* cf, bool lock=true);
+ PxClothFabric* createClothFabric(PxInputStream&);
+ PxClothFabric* createClothFabric(const PxClothFabricDesc& desc);
+ NpClothFabric* createNpClothFabric();
+ void releaseClothFabricToPool(NpClothFabric& clothFabric);
+ bool removeClothFabric(PxClothFabric&);
+ PxU32 getNbClothFabrics() const;
+ PxU32 getClothFabrics(PxClothFabric** userBuffer, PxU32 bufferSize) const;
+
+ PxCloth* createCloth(const PxTransform& globalPose, PxClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags);
+#endif
+
+ PxMaterial* createMaterial(PxReal staticFriction, PxReal dynamicFriction, PxReal restitution);
+ void releaseMaterialToPool(NpMaterial& material);
+
+ // It's easiest to track these uninvasively, so it's OK to use the Px pointers
+
+ void onActorRelease(PxActor*);
+ void onConstraintRelease(PxConstraint*);
+ void onAggregateRelease(PxAggregate*);
+ void onArticulationRelease(PxArticulation*);
+ void onShapeRelease(PxShape*);
+
+ NpConnectorArray* acquireConnectorArray();
+ void releaseConnectorArray(NpConnectorArray*);
+
+ NpPtrTableStorageManager& getPtrTableStorageManager() { return *mPtrTableStorageManager; }
+
+#if PX_SUPPORT_PVD
+ void setNpFactoryListener( NpFactoryListener& );
+#endif
+
+
+private:
+
+ void releaseExclusiveShapeUserReferences();
+#if PX_SUPPORT_GPU_PHYSX
+ virtual void notifyReleaseTriangleMesh(const PxTriangleMesh& tm);
+ virtual void notifyReleaseHeightField(const PxHeightField& hf);
+ virtual void notifyReleaseConvexMesh(const PxConvexMesh& cm);
+#endif
+
+ Ps::Pool<NpConnectorArray> mConnectorArrayPool;
+ Ps::Mutex mConnectorArrayPoolLock;
+
+ NpPtrTableStorageManager* mPtrTableStorageManager;
+
+ Ps::HashSet<PxAggregate*> mAggregateTracking;
+ Ps::HashSet<PxArticulation*> mArticulationTracking;
+ Ps::HashSet<PxConstraint*> mConstraintTracking;
+ Ps::HashSet<PxActor*> mActorTracking;
+ Ps::CoalescedHashSet<PxShape*> mShapeTracking;
+
+ Ps::Pool2<NpRigidDynamic, 4096> mRigidDynamicPool;
+ Ps::Mutex mRigidDynamicPoolLock;
+
+ Ps::Pool2<NpRigidStatic, 4096> mRigidStaticPool;
+ Ps::Mutex mRigidStaticPoolLock;
+
+ Ps::Pool2<NpShape, 4096> mShapePool;
+ Ps::Mutex mShapePoolLock;
+
+ Ps::Pool2<NpAggregate, 4096> mAggregatePool;
+ Ps::Mutex mAggregatePoolLock;
+
+ Ps::Pool2<NpConstraint, 4096> mConstraintPool;
+ Ps::Mutex mConstraintPoolLock;
+
+ Ps::Pool2<NpMaterial, 4096> mMaterialPool;
+ Ps::Mutex mMaterialPoolLock;
+
+ Ps::Pool2<NpArticulation, 4096> mArticulationPool;
+ Ps::Mutex mArticulationPoolLock;
+
+ Ps::Pool2<NpArticulationLink, 4096> mArticulationLinkPool;
+ Ps::Mutex mArticulationLinkPoolLock;
+
+ Ps::Pool2<NpArticulationJoint, 4096> mArticulationJointPool;
+ Ps::Mutex mArticulationJointPoolLock;
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ Ps::Pool2<NpParticleSystem, 4096> mParticleSystemPool;
+ Ps::Mutex mParticleSystemPoolLock;
+ Ps::Pool2<NpParticleFluid, 4096> mParticleFluidPool;
+ Ps::Mutex mParticleFluidPoolLock;
+#endif
+
+#if PX_USE_CLOTH_API
+ Ps::Array<NpClothFabric*> mClothFabricArray;
+ Ps::Pool2<NpCloth, 4096> mClothPool;
+ Ps::Mutex mClothPoolLock;
+ Ps::Pool2<NpClothFabric, 4096> mClothFabricPool;
+ Ps::Mutex mClothFabricPoolLock;
+#endif
+
+ static NpFactory* mInstance;
+
+#if PX_SUPPORT_PVD
+ NpFactoryListener* mNpFactoryListener;
+#endif
+
+};
+
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpMaterial.cpp b/PhysX_3.4/Source/PhysX/src/NpMaterial.cpp
new file mode 100644
index 00000000..ab68eebc
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpMaterial.cpp
@@ -0,0 +1,205 @@
+// 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 "NpMaterial.h"
+#include "NpPhysics.h"
+#include "CmUtils.h"
+
+using namespace physx;
+
+NpMaterial::NpMaterial(const Sc::MaterialCore& desc)
+: PxMaterial(PxConcreteType::eMATERIAL, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+, mMaterial(desc)
+{
+ mMaterial.setNxMaterial(this); // back-reference
+}
+
+NpMaterial::~NpMaterial()
+{
+ NpPhysics::getInstance().removeMaterialFromTable(*this);
+}
+
+// PX_SERIALIZATION
+void NpMaterial::resolveReferences(PxDeserializationContext&)
+{
+ // ### this one could be automated if NpMaterial would inherit from MaterialCore
+ // ### well actually in that case the pointer would not even be needed....
+ mMaterial.setNxMaterial(this); // Resolve MaterialCore::mNxMaterial
+
+ // Maybe not the best place to do it but it has to be done before the shapes resolve material indices
+ // since the material index translation table is needed there. This requires that the materials have
+ // been added to the table already.
+ NpPhysics::getInstance().addMaterial(this);
+}
+
+void NpMaterial::onRefCountZero()
+{
+ void* ud = userData;
+
+ if(getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseMaterialToPool(*this);
+ else
+ this->~NpMaterial();
+
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(this, ud);
+}
+
+NpMaterial* NpMaterial::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpMaterial* obj = new (address) NpMaterial(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpMaterial);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+void NpMaterial::release()
+{
+ decRefCount();
+}
+
+void NpMaterial::acquireReference()
+{
+ incRefCount();
+}
+
+PxU32 NpMaterial::getReferenceCount() const
+{
+ return getRefCount();
+}
+
+PX_INLINE void NpMaterial::updateMaterial()
+{
+ NpPhysics::getInstance().updateMaterial(*this);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpMaterial::setDynamicFriction(PxReal x)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(x), "PxMaterial::setDynamicFriction: invalid float");
+ mMaterial.dynamicFriction = x;
+
+ updateMaterial();
+}
+
+PxReal NpMaterial::getDynamicFriction() const
+{
+ return mMaterial.dynamicFriction;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpMaterial::setStaticFriction(PxReal x)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(x), "PxMaterial::setStaticFriction: invalid float");
+ mMaterial.staticFriction = x;
+
+ updateMaterial();
+}
+
+PxReal NpMaterial::getStaticFriction() const
+{
+ return mMaterial.staticFriction;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpMaterial::setRestitution(PxReal x)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(x), "PxMaterial::setRestitution: invalid float");
+ PX_CHECK_MSG(((x >= 0.0f) && (x <= 1.0f)), "PxMaterial::setRestitution: Restitution value has to be in [0,1]!");
+ if ((x < 0.0f) || (x > 1.0f))
+ {
+ PxClamp(x, 0.0f, 1.0f);
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxMaterial::setRestitution: Invalid value %f was clamped to [0,1]!", PxF64(x));
+ }
+ mMaterial.restitution = x;
+
+ updateMaterial();
+}
+
+PxReal NpMaterial::getRestitution() const
+{
+ return mMaterial.restitution;
+}
+
+/////////////////////////////////////////////////////////////////////////////////
+
+void NpMaterial::setFlag(PxMaterialFlag::Enum flag, bool value)
+{
+ if (value)
+ mMaterial.flags |= flag;
+ else
+ mMaterial.flags &= ~PxMaterialFlags(flag);
+
+ updateMaterial();
+}
+
+void NpMaterial::setFlags(PxMaterialFlags inFlags)
+{
+ mMaterial.flags = inFlags;
+ updateMaterial();
+}
+
+PxMaterialFlags NpMaterial::getFlags() const
+{
+ return mMaterial.flags;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpMaterial::setFrictionCombineMode(PxCombineMode::Enum x)
+{
+ mMaterial.setFrictionCombineMode(x);
+
+ updateMaterial();
+}
+
+PxCombineMode::Enum NpMaterial::getFrictionCombineMode() const
+{
+ return mMaterial.getFrictionCombineMode();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpMaterial::setRestitutionCombineMode(PxCombineMode::Enum x)
+{
+ mMaterial.setRestitutionCombineMode(x);
+ updateMaterial();
+}
+
+PxCombineMode::Enum NpMaterial::getRestitutionCombineMode() const
+{
+ return mMaterial.getRestitutionCombineMode();
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/PhysX_3.4/Source/PhysX/src/NpMaterial.h b/PhysX_3.4/Source/PhysX/src/NpMaterial.h
new file mode 100644
index 00000000..fd2665f9
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpMaterial.h
@@ -0,0 +1,122 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_MATERIAL
+#define PX_PHYSICS_NP_MATERIAL
+
+#include "PxMaterial.h"
+#include "ScMaterialCore.h"
+#include "PsUserAllocated.h"
+#include "CmRefCountable.h"
+#include "PsUtilities.h"
+
+// PX_SERIALIZATION
+#include "PxSerialFramework.h"
+//~PX_SERIALIZATION
+
+namespace physx
+{
+
+// Compared to other objects, materials are special since they belong to the SDK and not to scenes
+// (similar to meshes). That's why the NpMaterial does have direct access to the core material instead
+// of having a buffered interface for it. Scenes will have copies of the SDK material table and there
+// the materials will be buffered.
+
+
+class NpMaterial : public PxMaterial, public Ps::UserAllocated, public Cm::RefCountable
+{
+//= 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
+ NpMaterial(PxBaseFlags baseFlags) : PxMaterial(baseFlags), Cm::RefCountable(PxEmpty), mMaterial(PxEmpty) {}
+ virtual void onRefCountZero();
+ virtual void resolveReferences(PxDeserializationContext& context);
+ static NpMaterial* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+ void exportExtraData(PxSerializationContext&) {}
+ void importExtraData(PxDeserializationContext&) {}
+ virtual void requires(PxProcessPxBaseCallback&){}
+//~PX_SERIALIZATION
+ NpMaterial(const Sc::MaterialCore& desc);
+ ~NpMaterial();
+
+ virtual void release();
+
+ virtual void acquireReference();
+ virtual PxU32 getReferenceCount() const;
+
+ virtual void setDynamicFriction(PxReal);
+ virtual PxReal getDynamicFriction() const;
+ virtual void setStaticFriction(PxReal);
+ virtual PxReal getStaticFriction() const;
+ virtual void setRestitution(PxReal);
+ virtual PxReal getRestitution() const;
+ virtual void setFlag(PxMaterialFlag::Enum flag, bool value);
+ virtual void setFlags(PxMaterialFlags inFlags);
+ virtual PxMaterialFlags getFlags() const;
+ virtual void setFrictionCombineMode(PxCombineMode::Enum);
+ virtual PxCombineMode::Enum getFrictionCombineMode() const;
+ virtual void setRestitutionCombineMode(PxCombineMode::Enum);
+ virtual PxCombineMode::Enum getRestitutionCombineMode() const;
+
+ PX_INLINE const Sc::MaterialCore& getScMaterial() const { return mMaterial; }
+ PX_INLINE Sc::MaterialCore& getScMaterial() { return mMaterial; }
+ PX_INLINE PxU32 getHandle() const { return mMaterial.getMaterialIndex();}
+ PX_INLINE void setHandle(PxU32 handle) { return mMaterial.setMaterialIndex(handle);}
+
+ PX_FORCE_INLINE static void getMaterialIndices(PxMaterial*const* materials, PxU16* materialIndices, PxU32 materialCount);
+
+private:
+ PX_INLINE void updateMaterial();
+
+// PX_SERIALIZATION
+public:
+//~PX_SERIALIZATION
+ Sc::MaterialCore mMaterial;
+};
+
+
+PX_FORCE_INLINE void NpMaterial::getMaterialIndices(PxMaterial*const* materials, PxU16* materialIndices, PxU32 materialCount)
+{
+ for(PxU32 i=0; i < materialCount; i++)
+ {
+ materialIndices[i] = Ps::to16((static_cast<NpMaterial*>(materials[i]))->getHandle());
+ }
+}
+
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpMaterialManager.h b/PhysX_3.4/Source/PhysX/src/NpMaterialManager.h
new file mode 100644
index 00000000..1d509ba1
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpMaterialManager.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 NP_MATERIALMANAGER
+#define NP_MATERIALMANAGER
+
+#include "foundation/PxMemory.h"
+#include "NpMaterial.h"
+#include "CmIDPool.h"
+
+namespace physx
+{
+ class NpMaterialManager
+ {
+ public:
+ NpMaterialManager()
+ {
+ const PxU32 matCount = 128;
+ mMaterials = reinterpret_cast<NpMaterial**>(PX_ALLOC(sizeof(NpMaterial*) * matCount, "NpMaterialManager::initialise"));
+ mMaxMaterials = matCount;
+ PxMemZero(mMaterials, sizeof(NpMaterial*)*mMaxMaterials);
+ }
+
+ ~NpMaterialManager() {}
+
+ void releaseMaterials()
+ {
+ for(PxU32 i=0; i<mMaxMaterials; ++i)
+ {
+ if(mMaterials[i])
+ {
+ const PxU32 handle = mMaterials[i]->getHandle();
+ mHandleManager.freeID(handle);
+ mMaterials[i]->release();
+ mMaterials[i] = NULL;
+ }
+ }
+ PX_FREE(mMaterials);
+ }
+
+ bool setMaterial(NpMaterial& mat)
+ {
+ const PxU32 materialIndex = mHandleManager.getNewID();
+
+ if(materialIndex >= mMaxMaterials)
+ resize();
+
+ mMaterials[materialIndex] = &mat;
+ mat.setHandle(materialIndex);
+ return true;
+ }
+
+ void updateMaterial(NpMaterial& mat)
+ {
+ mMaterials[mat.getHandle()] = &mat;
+ }
+
+ PX_FORCE_INLINE PxU32 getNumMaterials() const
+ {
+ return mHandleManager.getNumUsedID();
+ }
+
+ void removeMaterial(NpMaterial& mat)
+ {
+ const PxU32 handle = mat.getHandle();
+ if(handle != MATERIAL_INVALID_HANDLE)
+ {
+ mMaterials[handle] = NULL;
+ mHandleManager.freeID(handle);
+ }
+ }
+
+ PX_FORCE_INLINE NpMaterial* getMaterial(const PxU32 index) const
+ {
+ PX_ASSERT(index < mMaxMaterials);
+ return mMaterials[index];
+ }
+
+ PX_FORCE_INLINE PxU32 getMaxSize() const
+ {
+ return mMaxMaterials;
+ }
+
+ PX_FORCE_INLINE NpMaterial** getMaterials() const
+ {
+ return mMaterials;
+ }
+
+ private:
+ void resize()
+ {
+ const PxU32 numMaterials = mMaxMaterials;
+ mMaxMaterials = mMaxMaterials*2;
+
+ NpMaterial** mat = reinterpret_cast<NpMaterial**>(PX_ALLOC(sizeof(NpMaterial*)*mMaxMaterials, "NpMaterialManager::resize"));
+ PxMemZero(mat, sizeof(NpMaterial*)*mMaxMaterials);
+ for(PxU32 i=0; i<numMaterials; ++i)
+ mat[i] = mMaterials[i];
+
+ PX_FREE(mMaterials);
+
+ mMaterials = mat;
+ }
+
+ Cm::IDPool mHandleManager;
+ NpMaterial** mMaterials;
+ PxU32 mMaxMaterials;
+ };
+
+ class NpMaterialManagerIterator
+ {
+ public:
+ NpMaterialManagerIterator(const NpMaterialManager& manager) : mManager(manager), mIndex(0)
+ {
+ }
+
+ bool getNextMaterial(NpMaterial*& np)
+ {
+ const PxU32 maxSize = mManager.getMaxSize();
+ PxU32 index = mIndex;
+ while(index < maxSize && mManager.getMaterial(index)==NULL)
+ index++;
+ np = NULL;
+ if(index < maxSize)
+ np = mManager.getMaterial(index++);
+ mIndex = index;
+ return np!=NULL;
+ }
+
+ private:
+ NpMaterialManagerIterator& operator=(const NpMaterialManagerIterator&);
+ const NpMaterialManager& mManager;
+ PxU32 mIndex;
+ };
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpMetaData.cpp b/PhysX_3.4/Source/PhysX/src/NpMetaData.cpp
new file mode 100644
index 00000000..531467b3
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpMetaData.cpp
@@ -0,0 +1,646 @@
+// 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 "PxPhysicsSerialization.h"
+#include "NpShape.h"
+#include "NpShapeManager.h"
+#include "NpConstraint.h"
+#include "NpRigidStatic.h"
+#include "NpRigidDynamic.h"
+#include "NpArticulation.h"
+#include "NpArticulationLink.h"
+#include "NpArticulationJoint.h"
+#include "NpClothFabric.h"
+#include "NpCloth.h"
+#include "NpAggregate.h"
+#include "NpParticleFluid.h"
+#include "GuConvexMesh.h"
+#include "GuTriangleMesh.h"
+#include "GuTriangleMeshBV4.h"
+#include "GuTriangleMeshRTree.h"
+#include "GuHeightField.h"
+
+using namespace physx;
+using namespace Cm;
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PT: the offsets can be different for different templated classes so I need macros here.
+
+#define DefineMetaData_PxActor(x) \
+ PX_DEF_BIN_METADATA_ITEM(stream, x, void, userData, PxMetaDataFlag::ePTR)
+
+#define DefineMetaData_NpRigidActorTemplate(x) \
+ PX_DEF_BIN_METADATA_ITEM(stream, x, NpShapeManager, mShapeManager, 0) \
+ PX_DEF_BIN_METADATA_ITEM(stream, x, PxU32, mIndex, 0) \
+
+#define DefineMetaData_NpRigidBodyTemplate(x) \
+ PX_DEF_BIN_METADATA_ITEM(stream, x, Scb::Body, mBody, 0)
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void getBinaryMetaData_PxVec3(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxVec3)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxVec3, PxReal, x, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxVec3, PxReal, y, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxVec3, PxReal, z, 0)
+}
+
+static void getBinaryMetaData_PxVec4(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxVec4)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxVec4, PxReal, x, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxVec4, PxReal, y, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxVec4, PxReal, z, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxVec4, PxReal, w, 0)
+}
+
+static void getBinaryMetaData_PxQuat(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxQuat)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxQuat, PxReal, x, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxQuat, PxReal, y, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxQuat, PxReal, z, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxQuat, PxReal, w, 0)
+}
+
+static void getBinaryMetaData_PxBounds3(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxBounds3)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxBounds3, PxVec3, minimum, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxBounds3, PxVec3, maximum, 0)
+}
+
+static void getBinaryMetaData_PxTransform(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxTransform)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxTransform, PxQuat, q, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxTransform, PxVec3, p, 0)
+}
+
+static void getBinaryMetaData_PxMat33(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxMat33)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxMat33, PxVec3, column0, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxMat33, PxVec3, column1, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxMat33, PxVec3, column2, 0)
+}
+
+namespace
+{
+ class ShadowBitMap : public BitMap
+ {
+ public:
+ static void getBinaryMetaData(PxOutputStream& stream_)
+ {
+ PX_DEF_BIN_METADATA_CLASS(stream_, ShadowBitMap)
+ PX_DEF_BIN_METADATA_ITEM(stream_, ShadowBitMap, PxU32, mMap, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream_, ShadowBitMap, PxU32, mWordCount, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream_, ShadowBitMap, Allocator, mAllocator, 0)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream_, ShadowBitMap, PxU8, mPadding, PxMetaDataFlag::ePADDING)
+
+ //------ Extra-data ------
+
+ // mMap
+ PX_DEF_BIN_METADATA_EXTRA_ARRAY(stream_, ShadowBitMap, PxU32, mWordCount, PX_SERIAL_ALIGN, PxMetaDataFlag::eCOUNT_MASK_MSB)
+ }
+ };
+}
+
+static void getBinaryMetaData_BitMap(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, Allocator, PxU8)
+ ShadowBitMap::getBinaryMetaData(stream);
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, BitMap, ShadowBitMap)
+}
+
+static void getBinaryMetaData_PxPlane(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxPlane)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxPlane, PxVec3, n, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxPlane, PxReal, d, 0)
+}
+
+static void getBinaryMetaData_PxConstraintInvMassScale(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxConstraintInvMassScale)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, PxConstraintInvMassScale, PxReal, linear0, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxConstraintInvMassScale, PxReal, angular0, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxConstraintInvMassScale, PxReal, linear1, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxConstraintInvMassScale, PxReal, angular1, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpActor::getBinaryMetaData(PxOutputStream& stream)
+{
+ // 12 bytes
+ PX_DEF_BIN_METADATA_CLASS(stream, NpActor)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, NpActor, char, mName, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpActor, NpConnectorArray, mConnectorArray, PxMetaDataFlag::ePTR)
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpMaterial::getBinaryMetaData(PxOutputStream& stream)
+{
+// 76 => 72 => 64 bytes
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpMaterial)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpMaterial, PxBase)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpMaterial, RefCountable)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, NpMaterial, void, userData, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpMaterial, MaterialCore, mMaterial, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpConstraint::getBinaryMetaData(PxOutputStream& stream)
+{
+// 136 => 140 => 144 => 128 bytes
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpConstraint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpConstraint, PxBase)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, NpConstraint, PxRigidActor, mActor0, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpConstraint, PxRigidActor, mActor1, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpConstraint, Scb::Constraint, mConstraint, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpConstraint, bool, mIsDirty, 0)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, NpConstraint, bool, mPaddingFromBool, PxMetaDataFlag::ePADDING)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpShapeManager::getBinaryMetaData(PxOutputStream& stream)
+{
+// 8 bytes
+ PX_DEF_BIN_METADATA_CLASS(stream, NpShapeManager)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpShapeManager, PtrTable, mShapes, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpShapeManager, PtrTable, mSceneQueryData, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpShapeManager, Sq::PruningStructure, mPruningStructure, PxMetaDataFlag::ePTR)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpShape::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, NpInternalShapeFlags, PxU8)
+
+// 208 => 224 => 208 => 192 bytes
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpShape)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpShape, PxBase)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpShape, RefCountable)
+
+ // PxShape
+ PX_DEF_BIN_METADATA_ITEM(stream, NpShape, void, userData, PxMetaDataFlag::ePTR)
+
+ // NpShape
+ PX_DEF_BIN_METADATA_ITEM(stream, NpShape, PxRigidActor, mActor, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpShape, Scb::Shape, mShape, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpShape, char, mName, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpShape, PxI32, mExclusiveAndActorCount, 0)
+
+
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, NpShape, mName, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpRigidStatic::getBinaryMetaData(PxOutputStream& stream)
+{
+// 124 => 128 => 124 => 108 => 96 bytes
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpRigidStatic)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpRigidStatic, PxBase)
+// PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpRigidStatic, NpRigidStaticT) // ### ???
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpRigidStatic, NpActor)
+
+ DefineMetaData_PxActor(NpRigidStatic)
+ DefineMetaData_NpRigidActorTemplate(NpRigidStatic)
+
+ // NpRigidStatic
+ PX_DEF_BIN_METADATA_ITEM(stream, NpRigidStatic, Scb::RigidStatic, mRigidStatic, 0)
+
+ //------ Extra-data ------
+
+ PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, NpRigidStatic, NpConnectorArray, mConnectorArray, PX_SERIAL_ALIGN)
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, NpRigidStatic, mName, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpConnector::getBinaryMetaData(PxOutputStream& stream)
+{
+// 8 bytes
+ PX_DEF_BIN_METADATA_CLASS(stream, NpConnector)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpConnector, PxU8, mType, 0)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, NpConnector, PxU8, mPadding, PxMetaDataFlag::ePADDING)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpConnector, PxBase, mObject, PxMetaDataFlag::ePTR)
+}
+
+void NpConnectorArray::getBinaryMetaData(PxOutputStream& stream)
+{
+// 48 bytes
+ PX_DEF_BIN_METADATA_CLASS(stream, NpConnectorArray)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, NpConnectorArray, NpConnector, mBuffer, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpConnectorArray, bool, mBufferUsed, 0)
+ // PT: OMG this is so painful... I can't put the padding explicitly in the template
+ { PxMetaDataEntry tmp = {"char", "mPadding", 1 + PxU32(PX_OFFSET_OF_RT(NpConnectorArray, mBufferUsed)), 3, 3, 0, PxMetaDataFlag::ePADDING, 0}; PX_STORE_METADATA(stream, tmp); }
+ PX_DEF_BIN_METADATA_ITEM(stream, NpConnectorArray, NpConnector, mData, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpConnectorArray, PxU32, mSize, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpConnectorArray, PxU32, mCapacity, 0)
+
+ //------ Extra-data ------
+
+ PX_DEF_BIN_METADATA_EXTRA_ITEMS(stream, NpConnectorArray, NpConnector, mBufferUsed, mCapacity, PxMetaDataFlag::eCONTROL_FLIP|PxMetaDataFlag::eCOUNT_MASK_MSB, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpRigidDynamic::getBinaryMetaData(PxOutputStream& stream)
+{
+// 368 => 352 => 304 => 288 bytes
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpRigidDynamic)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpRigidDynamic, PxBase)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpRigidDynamic, NpActor)
+
+ DefineMetaData_PxActor(NpRigidDynamic)
+ DefineMetaData_NpRigidActorTemplate(NpRigidDynamic)
+ DefineMetaData_NpRigidBodyTemplate(NpRigidDynamic)
+
+ // NpRigidDynamic
+
+ //------ Extra-data ------
+
+// Extra data:
+// - inline array from shape manager
+// - optional constraint array
+
+// PX_DEF_BIN_METADATA_ITEM(stream,NpRigidDynamic, NpShapeManager, mShapeManager.mShapes, 0)
+
+/*
+ virtual void exportExtraData(PxOutputStream& stream)
+ {
+ mShapeManager.exportExtraData(stream);
+ ActorTemplateClass::exportExtraData(stream);
+ }
+void NpActorTemplate<APIClass, LeafClass>::exportExtraData(PxOutputStream& stream)
+{
+ if(mConnectorArray)
+ {
+ stream.storeBuffer(mConnectorArray, sizeof(NpConnectorArray)
+ mConnectorArray->exportExtraData(stream);
+ }
+}
+*/
+ PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, NpRigidDynamic, NpConnectorArray, mConnectorArray, PX_SERIAL_ALIGN)
+//### missing inline array data here... only works for "buffered" arrays so far
+/*
+ Big issue: we can't output the "offset of" the inline array within the class, since the inline array itself is extra-data. But we need to read
+ the array itself to know if it's inline or not (the "is buffered" bool). So we need to read from the extra data!
+*/
+
+/*
+[17:41:39] Gordon Yeoman nvidia: PxsBodyCore need to be 16-byte aligned for spu. If it is 128-byte aligned then that is a mistake. Feel free to change it to 16.
+*/
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, NpRigidDynamic, mName, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpArticulationLinkArray::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, NpArticulationLinkArray)
+ PX_DEF_BIN_METADATA_ITEMS(stream, NpArticulationLinkArray, NpArticulationLink, mBuffer, PxMetaDataFlag::ePTR, 4)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationLinkArray, bool, mBufferUsed, 0)
+ // PT: OMG this is so painful... I can't put the padding explicitely in the template
+ { PxMetaDataEntry tmp = {"char", "mPadding", 1 + PxU32(PX_OFFSET_OF_RT(NpArticulationLinkArray, mBufferUsed)), 3, 3, 0, PxMetaDataFlag::ePADDING, 0}; PX_STORE_METADATA(stream, tmp); }
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationLinkArray, NpArticulationLink, mData, PxMetaDataFlag::ePTR) // ###
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationLinkArray, PxU32, mSize, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationLinkArray, PxU32, mCapacity, 0)
+
+ //------ Extra-data ------
+
+ PX_DEF_BIN_METADATA_EXTRA_ITEMS(stream, NpArticulationLinkArray, NpArticulationLink, mBufferUsed, mCapacity, PxMetaDataFlag::eCONTROL_FLIP|PxMetaDataFlag::eCOUNT_MASK_MSB|PxMetaDataFlag::ePTR, 0)
+}
+
+void NpArticulation::getBinaryMetaData(PxOutputStream& stream)
+{
+// 92 => 108 => 104 => 116 => 120 => 104 bytes
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpArticulation)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpArticulation, PxBase)
+
+ // PxArticulation
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulation, void, userData, PxMetaDataFlag::ePTR)
+
+ // NpArticulation
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulation, Scb::Articulation, mArticulation, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulation, NpArticulationLinkArray, mArticulationLinks, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulation, NpAggregate, mAggregate, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulation, char, mName, PxMetaDataFlag::ePTR)
+
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, NpArticulation, mName, 0)
+}
+
+void NpArticulationLink::getBinaryMetaData(PxOutputStream& stream)
+{
+// 400 (!) => 352 => 336 bytes
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpArticulationLink)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpArticulationLink, PxBase)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpArticulationLink, NpActor)
+
+ DefineMetaData_PxActor(NpArticulationLink)
+ DefineMetaData_NpRigidActorTemplate(NpArticulationLink)
+ DefineMetaData_NpRigidBodyTemplate(NpArticulationLink)
+
+ // NpArticulationLink
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationLink, NpArticulation, mRoot, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationLink, NpArticulationJoint, mInboundJoint, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationLink, NpArticulationLink, mParent, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationLink, NpArticulationLinkArray, mChildLinks, 0)
+#ifdef EXPLICIT_PADDING_METADATA
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationLink, PxU32, mPadding, PxMetaDataFlag::ePADDING)
+#endif
+
+ //------ Extra-data ------
+
+ PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, NpArticulationLink, NpConnectorArray, mConnectorArray, PX_SERIAL_ALIGN)
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, NpArticulationLink, mName, 0)
+}
+
+void NpArticulationJoint::getBinaryMetaData(PxOutputStream& stream)
+{
+// 184 => 200 => 192 => 224 => 208 bytes
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpArticulationJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpArticulationJoint, PxBase)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationJoint, Scb::ArticulationJoint, mJoint, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationJoint, NpArticulationLink, mParent, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpArticulationJoint, NpArticulationLink, mChild, PxMetaDataFlag::ePTR)
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpAggregate::getBinaryMetaData(PxOutputStream& stream)
+{
+// 36 => 56 => 40 bytes
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpAggregate)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpAggregate, PxBase)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, NpAggregate, Scb::Aggregate, mAggregate, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpAggregate, PxU32, mNbActors, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpAggregate, PxActor, mActors, PxMetaDataFlag::ePTR)
+
+ //------ Extra-data ------
+
+ // mActors
+ PX_DEF_BIN_METADATA_EXTRA_ITEMS(stream, NpAggregate, PxActor, mActors, mNbActors, PxMetaDataFlag::ePTR, PX_SERIAL_ALIGN)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+#if PX_USE_CLOTH_API
+void NpClothFabric::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpClothFabric)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpClothFabric, PxBase)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpClothFabric, RefCountable)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, NpClothFabric, Sc::ClothFabricCore, mFabric, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpCloth::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpCloth)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpCloth, PxBase)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpCloth, NpActor)
+
+ DefineMetaData_PxActor(NpCloth)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, NpCloth, Scb::Cloth, mCloth, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, NpCloth, NpClothFabric, mClothFabric, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEMS(stream, NpCloth, PxU8, mParticleData, PxMetaDataFlag::ePADDING, sizeof(NpClothParticleData))
+}
+
+#endif // PX_USE_CLOTH_API
+
+///////////////////////////////////////////
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+void NpParticleSystem::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpParticleSystem)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpParticleSystem, PxBase)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpParticleSystem, NpActor)
+
+ DefineMetaData_PxActor(NpParticleSystem)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, NpParticleFluid, Scb::ParticleSystem, mParticleSystem, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpParticleFluid::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_VCLASS(stream, NpParticleFluid)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpParticleFluid, PxBase)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, NpParticleFluid, NpActor)
+
+ DefineMetaData_PxActor(NpParticleFluid)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, NpParticleFluid, Scb::ParticleSystem, mParticleSystem, 0)
+}
+
+#endif // PX_USE_PARTICLE_SYSTEM_API
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void getBinaryMetaData_PxMeshScale(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxMeshScale)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxMeshScale, PxVec3, scale, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxMeshScale, PxQuat, rotation, 0)
+}
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+static void getBinaryMetaData_ParticleSystemParameter(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, Pt::ParticleSystemParameter)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, restParticleDistance, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, kernelRadiusMultiplier, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, viscosity, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, surfaceTension, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, fadeInTime, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxU32, flags, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxU32, packetSizeMultiplierLog2, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, restitution, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, dynamicFriction, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, staticFriction, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, restDensity, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, damping, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, stiffness, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, maxMotionDistance, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, restOffset, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxReal, contactOffset, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxPlane,projectionPlane, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxU16, particleReadDataFlags, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Pt::ParticleSystemParameter, PxU32, noiseCounter, 0)
+}
+
+#endif // PX_USE_PARTICLE_SYSTEM_API
+
+///////////////////////////////////////////////////////////////////////////////
+namespace physx
+{
+void getBinaryMetaData_PxBase(PxOutputStream& stream)
+{
+ // 8 bytes
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxBaseFlags, PxU16)
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxType, PxU16)
+ PX_DEF_BIN_METADATA_VCLASS(stream, PxBase)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxBase, PxType, mConcreteType, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxBase, PxBaseFlags, mBaseFlags, 0)
+}
+}
+void RefCountable::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_VCLASS(stream, RefCountable)
+ PX_DEF_BIN_METADATA_ITEM(stream, RefCountable, PxI32, mRefCount, 0)
+}
+
+static void getFoundationMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxU8, char)
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxI8, char)
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxU16, short)
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxI16, short)
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxU32, int)
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxI32, int)
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxReal, float)
+
+ getBinaryMetaData_PxVec3(stream);
+ getBinaryMetaData_PxVec4(stream);
+ getBinaryMetaData_PxQuat(stream);
+ getBinaryMetaData_PxBounds3(stream);
+ getBinaryMetaData_PxTransform(stream);
+ getBinaryMetaData_PxMat33(stream);
+ getBinaryMetaData_BitMap(stream);
+ Cm::PtrTable::getBinaryMetaData(stream);
+ getBinaryMetaData_PxPlane(stream);
+ getBinaryMetaData_PxConstraintInvMassScale(stream);
+
+ getBinaryMetaData_PxBase(stream);
+ RefCountable::getBinaryMetaData(stream);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void PxGetPhysicsBinaryMetaData(PxOutputStream& stream)
+{
+ getFoundationMetaData(stream);
+
+ getBinaryMetaData_PxMeshScale(stream);
+#if PX_USE_PARTICLE_SYSTEM_API
+ getBinaryMetaData_ParticleSystemParameter(stream);
+#endif
+
+ MaterialIndicesStruct::getBinaryMetaData(stream);
+ Gu::GeometryUnion::getBinaryMetaData(stream);
+ Gu::ConvexMesh::getBinaryMetaData(stream);
+ Gu::TriangleMesh::getBinaryMetaData(stream);
+ Gu::RTreeTriangleMesh::getBinaryMetaData(stream);
+ Gu::BV4TriangleMesh::getBinaryMetaData(stream);
+ Gu::HeightField::getBinaryMetaData(stream);
+
+ Sc::ActorCore::getBinaryMetaData(stream);
+ Sc::RigidCore::getBinaryMetaData(stream);
+ Sc::StaticCore::getBinaryMetaData(stream);
+ Sc::BodyCore::getBinaryMetaData(stream);
+ Sc::MaterialCore::getBinaryMetaData(stream);
+ Sc::ShapeCore::getBinaryMetaData(stream);
+ Sc::ConstraintCore::getBinaryMetaData(stream);
+ Sc::ArticulationCore::getBinaryMetaData(stream);
+ Sc::ArticulationJointCore::getBinaryMetaData(stream);
+#if PX_USE_CLOTH_API
+ Sc::ClothFabricCore::getBinaryMetaData(stream);
+ Sc::ClothCore::getBinaryMetaData(stream);
+#endif
+#if PX_USE_PARTICLE_SYSTEM_API
+ Sc::ParticleSystemCore::getBinaryMetaData(stream);
+#endif
+
+ Scb::Base::getBinaryMetaData(stream);
+ Scb::Actor::getBinaryMetaData(stream);
+ Scb::RigidObject::getBinaryMetaData(stream);
+ Scb::RigidStatic::getBinaryMetaData(stream);
+ Scb::Body::getBinaryMetaData(stream);
+ Scb::Shape::getBinaryMetaData(stream);
+ Scb::Constraint::getBinaryMetaData(stream);
+ Scb::Articulation::getBinaryMetaData(stream);
+ Scb::ArticulationJoint::getBinaryMetaData(stream);
+ Scb::Aggregate::getBinaryMetaData(stream);
+#if PX_USE_CLOTH_API
+ Scb::Cloth::getBinaryMetaData(stream);
+#endif
+#if PX_USE_PARTICLE_SYSTEM_API
+ Scb::ParticleSystem::getBinaryMetaData(stream);
+#endif
+
+ NpConnector::getBinaryMetaData(stream);
+ NpConnectorArray::getBinaryMetaData(stream);
+ NpActor::getBinaryMetaData(stream);
+ NpMaterial::getBinaryMetaData(stream); // NP_MATERIAL
+ NpRigidDynamic::getBinaryMetaData(stream); // NP_RIGID_DYNAMIC
+ NpRigidStatic::getBinaryMetaData(stream); // NP_RIGID_STATIC
+ NpShape::getBinaryMetaData(stream); // NP_SHAPE
+ NpConstraint::getBinaryMetaData(stream); // NP_CONSTRAINT
+ NpArticulation::getBinaryMetaData(stream); // NP_ARTICULATION
+ NpArticulationLink::getBinaryMetaData(stream); // NP_ARTICULATION_LINK
+ NpArticulationJoint::getBinaryMetaData(stream); // NP_ARTICULATION_JOINT
+ NpArticulationLinkArray::getBinaryMetaData(stream);
+ NpShapeManager::getBinaryMetaData(stream);
+ NpAggregate::getBinaryMetaData(stream); // NP_AGGREGATE
+#if PX_USE_CLOTH_API
+ NpClothFabric::getBinaryMetaData(stream);
+ NpCloth::getBinaryMetaData(stream);
+#endif
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ NpParticleSystem::getBinaryMetaData(stream);
+ NpParticleFluid::getBinaryMetaData(stream);
+#endif
+}
diff --git a/PhysX_3.4/Source/PhysX/src/NpPhysics.cpp b/PhysX_3.4/Source/PhysX/src/NpPhysics.cpp
new file mode 100644
index 00000000..f2397d90
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpPhysics.cpp
@@ -0,0 +1,893 @@
+// 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 "NpPhysics.h"
+
+// PX_SERIALIZATION
+#include "foundation/PxProfiler.h"
+#include "foundation/PxIO.h"
+#include "foundation/PxErrorCallback.h"
+#include "PxPhysicsVersion.h"
+#include "CmCollection.h"
+#include "CmUtils.h"
+#include "NpClothFabric.h"
+#include "NpCloth.h"
+#include "NpParticleSystem.h"
+#include "NpParticleFluid.h"
+#include "NpRigidStatic.h"
+#include "NpRigidDynamic.h"
+#include "NpArticulation.h"
+#include "NpArticulationLink.h"
+#include "NpArticulationJoint.h"
+#include "NpMaterial.h"
+#include "GuHeightFieldData.h"
+#include "GuHeightField.h"
+#include "GuConvexMesh.h"
+#include "GuTriangleMesh.h"
+#include "PsIntrinsics.h"
+#include "PxTolerancesScale.h"
+#include "PxvGlobals.h" // dynamic registration of HFs & articulations in LL
+#include "GuOverlapTests.h" // dynamic registration of HFs in Gu
+#include "PxDeletionListener.h"
+#include "PxPhysicsSerialization.h"
+#include "PsString.h"
+#include "PvdPhysicsClient.h"
+#include "SqPruningStructure.h"
+
+//~PX_SERIALIZATION
+
+#if PX_USE_PARTICLE_SYSTEM_API
+#include "PtContext.h"
+#endif
+
+#include "NpFactory.h"
+
+
+#if PX_USE_CLOTH_API
+#include "NpCloth.h"
+#endif
+
+using namespace physx;
+using namespace Cm;
+
+bool NpPhysics::apiReentryLock = false;
+NpPhysics* NpPhysics::mInstance = NULL;
+PxU32 NpPhysics::mRefCount = 0;
+
+#if PX_CHECKED
+bool NpPhysics::mHeightFieldsRegistered = false; //just for error checking
+#endif
+
+
+
+NpPhysics::NpPhysics(const PxTolerancesScale& scale, const PxvOffsetTable& pxvOffsetTable, bool trackOutstandingAllocations,
+ physx::pvdsdk::PsPvd* pvd) :
+ mSceneArray(PX_DEBUG_EXP("physicsSceneArray"))
+ , mSceneRunning(NULL)
+ , mPhysics(scale, pxvOffsetTable)
+ , mDeletionListenersExist(false)
+#if PX_SUPPORT_GPU_PHYSX
+ , mNbRegisteredGpuClients(0)
+ , mPhysicsGpu(*this)
+#endif
+{
+
+ PX_UNUSED(trackOutstandingAllocations);
+
+ //mMasterMaterialTable.reserve(10);
+
+#if PX_SUPPORT_PVD
+ mPvd = pvd;
+ if(pvd)
+ {
+ mPvdPhysicsClient = PX_NEW(Vd::PvdPhysicsClient)(mPvd);
+ shdfnd::getFoundation().registerErrorCallback(*mPvdPhysicsClient);
+ shdfnd::getFoundation().registerAllocationListener(*mPvd);
+ }
+ else
+ {
+ mPvdPhysicsClient = NULL;
+ }
+#else
+ PX_UNUSED(pvd);
+#endif
+}
+
+NpPhysics::~NpPhysics()
+{
+ // Release all scenes in case the user didn't do it
+ PxU32 nbScenes = mSceneArray.size();
+ NpScene** scenes = mSceneArray.begin();
+ for(PxU32 i=0;i<nbScenes;i++)
+ PX_DELETE_AND_RESET(scenes[i]);
+ mSceneArray.clear();
+
+ //PxU32 matCount = mMasterMaterialTable.size();
+ //while (mMasterMaterialTable.size() > 0)
+ //{
+ // // It's done this way since the material destructor removes the material from the table and adjusts indices
+
+ // PX_ASSERT(mMasterMaterialTable[0]->getRefCount() == 1);
+ // mMasterMaterialTable[0]->decRefCount();
+ //}
+ //mMasterMaterialTable.clear();
+
+ mMasterMaterialManager.releaseMaterials();
+
+#if PX_SUPPORT_PVD
+ if(mPvd)
+ {
+ mPvdPhysicsClient->destroyPvdInstance(this);
+ mPvd->removeClient(mPvdPhysicsClient);
+ shdfnd::getFoundation().deregisterErrorCallback(*mPvdPhysicsClient);
+ PX_DELETE_AND_RESET(mPvdPhysicsClient);
+ shdfnd::getFoundation().deregisterAllocationListener(*mPvd);
+ }
+#endif
+
+ const DeletionListenerMap::Entry* delListenerEntries = mDeletionListenerMap.getEntries();
+ const PxU32 delListenerEntryCount = mDeletionListenerMap.size();
+ for(PxU32 i=0; i < delListenerEntryCount; i++)
+ {
+ PX_DELETE(delListenerEntries[i].second);
+ }
+ mDeletionListenerMap.clear();
+}
+
+void NpPhysics::initOffsetTables(PxvOffsetTable& pxvOffsetTable)
+{
+ // init offset tables for Pxs/Sc/Scb/Px conversions
+ {
+ Sc::OffsetTable& offsetTable = Sc::gOffsetTable;
+ offsetTable.scRigidStatic2PxActor = -reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<NpRigidStatic*>(0)->getScbRigidStaticFast())) - static_cast<ptrdiff_t>(Scb::RigidStatic::getScOffset());
+ offsetTable.scRigidDynamic2PxActor = -reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<NpRigidDynamic*>(0)->getScbBodyFast())) - static_cast<ptrdiff_t>(Scb::Body::getScOffset());
+ offsetTable.scArticulationLink2PxActor = -reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<NpArticulationLink*>(0)->getScbBodyFast())) - static_cast<ptrdiff_t>(Scb::Body::getScOffset());
+ offsetTable.scArticulation2Px = -reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<NpArticulation*>(0)->getScbArticulation())) - static_cast<ptrdiff_t>(Scb::Articulation::getScOffset());
+ offsetTable.scConstraint2Px = -reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<NpConstraint*>(0)->getScbConstraint())) - static_cast<ptrdiff_t>(Scb::Constraint::getScOffset());
+ offsetTable.scShape2Px = -reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<NpShape*>(0)->getScbShape())) - static_cast<ptrdiff_t>(Scb::Shape::getScOffset());
+#if PX_USE_PARTICLE_SYSTEM_API
+ offsetTable.scParticleSystem2PxParticleFluid = -reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<NpParticleFluid*>(0)->getScbParticleSystem())) - static_cast<ptrdiff_t>(Scb::ParticleSystem::getScOffset());
+ offsetTable.scParticleSystem2Px = -reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<NpParticleSystem*>(0)->getScbParticleSystem())) - static_cast<ptrdiff_t>(Scb::ParticleSystem::getScOffset());
+#endif
+#if PX_USE_CLOTH_API
+ offsetTable.scCloth2Px = -reinterpret_cast<ptrdiff_t>(&(reinterpret_cast<NpCloth*>(0)->getScbCloth())) - static_cast<ptrdiff_t>(Scb::Cloth::getScOffset());
+#endif
+ for(PxU32 i=0;i<PxActorType::eACTOR_COUNT;i++)
+ offsetTable.scCore2PxActor[i] = 0;
+ offsetTable.scCore2PxActor[PxActorType::eRIGID_STATIC] = offsetTable.scRigidStatic2PxActor;
+ offsetTable.scCore2PxActor[PxActorType::eRIGID_DYNAMIC] = offsetTable.scRigidDynamic2PxActor;
+ offsetTable.scCore2PxActor[PxActorType::eARTICULATION_LINK] = offsetTable.scArticulationLink2PxActor;
+ }
+ {
+ Sq::OffsetTable& offsetTable = Sq::gOffsetTable;
+ // init pxActorToScbActor
+ for(PxU32 i=0;i<PxConcreteType::ePHYSX_CORE_COUNT;i++)
+ offsetTable.pxActorToScbActor[i] = 0;
+ ptrdiff_t addr = 0x100; // casting the null ptr takes a special-case code path, which we don't want
+ PxActor* n = reinterpret_cast<PxActor*>(addr);
+ offsetTable.pxActorToScbActor[PxConcreteType::eRIGID_STATIC] = reinterpret_cast<ptrdiff_t>(&static_cast<NpRigidStatic*>(n)->getScbActorFast()) - addr;
+ offsetTable.pxActorToScbActor[PxConcreteType::eRIGID_DYNAMIC] = reinterpret_cast<ptrdiff_t>(&static_cast<NpRigidDynamic*>(n)->getScbActorFast()) - addr;
+#if PX_USE_PARTICLE_SYSTEM_API
+ offsetTable.pxActorToScbActor[PxConcreteType::ePARTICLE_SYSTEM] = reinterpret_cast<ptrdiff_t>(&static_cast<NpParticleSystem*>(n)->getScbActor()) - addr;
+ offsetTable.pxActorToScbActor[PxConcreteType::ePARTICLE_FLUID] = reinterpret_cast<ptrdiff_t>(&static_cast<NpParticleFluid*>(n)->getScbActor()) - addr;
+#endif
+ offsetTable.pxActorToScbActor[PxConcreteType::eARTICULATION_LINK] = reinterpret_cast<ptrdiff_t>(&static_cast<NpArticulationLink*>(n)->getScbActorFast()) - addr;
+#if PX_USE_CLOTH_API
+ offsetTable.pxActorToScbActor[PxConcreteType::eCLOTH] = reinterpret_cast<ptrdiff_t>(&static_cast<NpCloth*>(n)->getScbCloth()) - addr;
+#endif
+ // init scb2sc
+ for(PxU32 i=0;i<ScbType::TYPE_COUNT;i++)
+ offsetTable.scbToSc[i] = 0;
+ ptrdiff_t staticOffset = static_cast<ptrdiff_t>(Scb::RigidStatic::getScOffset());
+ ptrdiff_t bodyOffset = static_cast<ptrdiff_t>(Scb::Body::getScOffset());
+ offsetTable.scbToSc[ScbType::RIGID_STATIC] = staticOffset;
+ offsetTable.scbToSc[ScbType::BODY] = bodyOffset;
+ offsetTable.scbToSc[ScbType::BODY_FROM_ARTICULATION_LINK] = bodyOffset;
+#if PX_USE_PARTICLE_SYSTEM_API
+ offsetTable.scbToSc[ScbType::PARTICLE_SYSTEM] = static_cast<ptrdiff_t>(Scb::ParticleSystem::getScOffset());
+#endif
+#if PX_USE_CLOTH_API
+ offsetTable.scbToSc[ScbType::CLOTH] = static_cast<ptrdiff_t>(Scb::Cloth::getScOffset());
+#endif
+ }
+ {
+ Sc::OffsetTable& scOffsetTable = Sc::gOffsetTable;
+ pxvOffsetTable.pxsShapeCore2PxShape = scOffsetTable.scShape2Px - reinterpret_cast<ptrdiff_t>(&static_cast<Sc::ShapeCore*>(0)->getCore());
+ pxvOffsetTable.pxsRigidCore2PxRigidBody = scOffsetTable.scRigidDynamic2PxActor - reinterpret_cast<ptrdiff_t>(&static_cast<Sc::BodyCore*>(0)->getCore());
+ pxvOffsetTable.pxsRigidCore2PxRigidStatic = scOffsetTable.scRigidStatic2PxActor - reinterpret_cast<ptrdiff_t>(&static_cast<Sc::StaticCore*>(0)->getCore());
+ }
+}
+
+NpPhysics* NpPhysics::createInstance(PxU32 version, PxFoundation& foundation, const PxTolerancesScale& scale, bool trackOutstandingAllocations,
+ physx::pvdsdk::PsPvd* pvd)
+{
+ PX_UNUSED(foundation);
+
+ if (version!=PX_PHYSICS_VERSION)
+ {
+ char buffer[256];
+ Ps::snprintf(buffer, 256, "Wrong version: PhysX version is 0x%08x, tried to create 0x%08x", PX_PHYSICS_VERSION, version);
+ foundation.getErrorCallback().reportError(PxErrorCode::eINVALID_PARAMETER, buffer, __FILE__, __LINE__);
+ return NULL;
+ }
+
+ if (!scale.isValid())
+ {
+ foundation.getErrorCallback().reportError(PxErrorCode::eINVALID_PARAMETER, "Scale invalid.\n", __FILE__, __LINE__);
+ return NULL;
+ }
+
+ if(0 == mRefCount)
+ {
+ PX_ASSERT(static_cast<Ps::Foundation*>(&foundation) == &Ps::Foundation::getInstance());
+
+ Ps::Foundation::incRefCount();
+
+ // init offset tables for Pxs/Sc/Scb/Px conversions
+ PxvOffsetTable pxvOffsetTable;
+ initOffsetTables(pxvOffsetTable);
+
+ //SerialFactory::createInstance();
+ mInstance = PX_NEW (NpPhysics)(scale, pxvOffsetTable, trackOutstandingAllocations, pvd);
+ NpFactory::createInstance();
+
+#if PX_SUPPORT_PVD
+ if(pvd)
+ {
+ NpFactory::getInstance().setNpFactoryListener( *mInstance->mPvdPhysicsClient );
+ pvd->addClient(mInstance->mPvdPhysicsClient);
+ }
+#endif
+
+ NpFactory::getInstance().addFactoryListener(mInstance->mDeletionMeshListener);
+ }
+ ++mRefCount;
+
+ return mInstance;
+}
+
+PxU32 NpPhysics::releaseInstance()
+{
+ PX_ASSERT(mRefCount > 0);
+ if (--mRefCount)
+ return mRefCount;
+
+#if PX_SUPPORT_PVD
+ if(mInstance->mPvd)
+ {
+ NpFactory::getInstance().removeFactoryListener( *mInstance->mPvdPhysicsClient );
+ }
+#endif
+
+ NpFactory::destroyInstance();
+
+ PX_ASSERT(mInstance);
+ PX_DELETE_AND_RESET(mInstance);
+
+ Ps::Foundation::decRefCount();
+
+ return mRefCount;
+}
+
+void NpPhysics::release()
+{
+ NpPhysics::releaseInstance();
+}
+
+PxScene* NpPhysics::createScene(const PxSceneDesc& desc)
+{
+ PX_CHECK_AND_RETURN_NULL(desc.isValid(), "Physics::createScene: desc.isValid() is false!");
+
+ const PxTolerancesScale& scale = mPhysics.getTolerancesScale();
+ const PxTolerancesScale& descScale = desc.getTolerancesScale();
+ PX_UNUSED(scale);
+ PX_UNUSED(descScale);
+ PX_CHECK_AND_RETURN_NULL((descScale.length == scale.length) && (descScale.mass == scale.mass) && (descScale.speed == scale.speed), "Physics::createScene: PxTolerancesScale must be the same as used for creation of PxPhysics!");
+
+ Ps::Mutex::ScopedLock lock(mSceneAndMaterialMutex); // done here because scene constructor accesses profiling manager of the SDK
+
+ NpScene* npScene = PX_NEW (NpScene)(desc);
+ if(!npScene)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Unable to create scene.");
+ return NULL;
+ }
+ if(!npScene->getTaskManager())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Unable to create scene. Task manager creation failed.");
+ return NULL;
+ }
+
+ npScene->loadFromDesc(desc);
+
+#if PX_SUPPORT_PVD
+ if(mPvd)
+ {
+ npScene->mScene.getScenePvdClient().setPsPvd(mPvd);
+ mPvd->addClient(&npScene->mScene.getScenePvdClient());
+ }
+#endif
+
+ if (!sendMaterialTable(*npScene) || !npScene->getScene().isValid())
+ {
+ PX_DELETE(npScene);
+ Ps::getFoundation().error(PxErrorCode::eOUT_OF_MEMORY, __FILE__, __LINE__, "Unable to create scene.");
+ return NULL;
+ }
+
+ mSceneArray.pushBack(npScene);
+ return npScene;
+}
+
+
+void NpPhysics::releaseSceneInternal(PxScene& scene)
+{
+ NpScene* pScene = static_cast<NpScene*>(&scene);
+
+ Ps::Mutex::ScopedLock lock(mSceneAndMaterialMutex);
+ for(PxU32 i=0;i<mSceneArray.size();i++)
+ {
+ if(mSceneArray[i]==pScene)
+ {
+ mSceneArray.replaceWithLast(i);
+ PX_DELETE_AND_RESET(pScene);
+ return;
+ }
+ }
+}
+
+
+PxU32 NpPhysics::getNbScenes() const
+{
+ Ps::Mutex::ScopedLock lock(const_cast<Ps::Mutex&>(mSceneAndMaterialMutex));
+ return mSceneArray.size();
+}
+
+
+PxU32 NpPhysics::getScenes(PxScene** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ Ps::Mutex::ScopedLock lock(const_cast<Ps::Mutex&>(mSceneAndMaterialMutex));
+ return Cm::getArrayOfPointers(userBuffer, bufferSize, startIndex, mSceneArray.begin(), mSceneArray.size());
+}
+
+
+PxRigidStatic* NpPhysics::createRigidStatic(const PxTransform& globalPose)
+{
+ PX_CHECK_AND_RETURN_NULL(globalPose.isSane(), "PxPhysics::createRigidStatic: invalid transform");
+ return NpFactory::getInstance().createRigidStatic(globalPose.getNormalized());
+}
+
+PxShape* NpPhysics::createShape(const PxGeometry& geometry, PxMaterial*const * materials, PxU16 materialCount, bool isExclusive, PxShapeFlags shapeFlags)
+{
+ PX_CHECK_AND_RETURN_NULL(materials, "createShape: material pointer is NULL");
+ PX_CHECK_AND_RETURN_NULL(materialCount>0, "createShape: material count is zero");
+
+#if PX_CHECKED
+ const bool isHeightfield = geometry.getType() == PxGeometryType::eHEIGHTFIELD;
+ if (isHeightfield)
+ {
+ PX_CHECK_AND_RETURN_NULL(mHeightFieldsRegistered, "NpPhysics::createShape: Creating Heightfield shape without having called PxRegister[Unified]HeightFields()!");
+ }
+ const bool hasMeshTypeGeom = isHeightfield || (geometry.getType() == PxGeometryType::eTRIANGLEMESH);
+ PX_CHECK_AND_RETURN_NULL(!(hasMeshTypeGeom && (shapeFlags & PxShapeFlag::eTRIGGER_SHAPE)), "NpPhysics::createShape: triangle mesh and heightfield triggers are not supported!");
+ PX_CHECK_AND_RETURN_NULL(!((shapeFlags & PxShapeFlag::eSIMULATION_SHAPE) && (shapeFlags & PxShapeFlag::eTRIGGER_SHAPE)), "NpPhysics::createShape: shapes cannot simultaneously be trigger shapes and simulation shapes.");
+#endif
+
+ return NpFactory::getInstance().createShape(geometry, shapeFlags, materials, materialCount, isExclusive);
+}
+
+PxU32 NpPhysics::getNbShapes() const
+{
+ return NpFactory::getInstance().getNbShapes();
+}
+
+PxU32 NpPhysics::getShapes(PxShape** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ return NpFactory::getInstance().getShapes(userBuffer, bufferSize, startIndex);
+}
+
+
+
+
+
+PxRigidDynamic* NpPhysics::createRigidDynamic(const PxTransform& globalPose)
+{
+ PX_CHECK_AND_RETURN_NULL(globalPose.isSane(), "PxPhysics::createRigidDynamic: invalid transform");
+ return NpFactory::getInstance().createRigidDynamic(globalPose.getNormalized());
+}
+
+
+PxConstraint* NpPhysics::createConstraint(PxRigidActor* actor0, PxRigidActor* actor1, PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize)
+{
+ return NpFactory::getInstance().createConstraint(actor0, actor1, connector, shaders, dataSize);
+}
+
+
+PxArticulation* NpPhysics::createArticulation()
+{
+ return NpFactory::getInstance().createArticulation();
+}
+
+
+// PX_AGGREGATE
+
+
+PxAggregate* NpPhysics::createAggregate(PxU32 maxSize, bool selfCollisionEnabled)
+{
+ return NpFactory::getInstance().createAggregate(maxSize, selfCollisionEnabled);
+}
+//~PX_AGGREGATE
+
+
+#if PX_USE_PARTICLE_SYSTEM_API
+PxParticleSystem* NpPhysics::createParticleSystem(PxU32 maxParticles, bool perParticleRestOffset)
+{
+ return NpFactory::getInstance().createParticleSystem(maxParticles, perParticleRestOffset);
+}
+
+
+PxParticleFluid* NpPhysics::createParticleFluid(PxU32 maxParticles, bool perParticleRestOffset)
+{
+ return NpFactory::getInstance().createParticleFluid(maxParticles, perParticleRestOffset);
+}
+#endif
+
+#if PX_USE_CLOTH_API
+PxCloth* NpPhysics::createCloth(const PxTransform& globalPose, PxClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags)
+{
+ PX_CHECK_AND_RETURN_NULL(globalPose.isSane(), "PxPhysics::createCloth: invalid transform");
+ return NpFactory::getInstance().createCloth(globalPose.getNormalized(), fabric, particles, flags);
+}
+#endif
+
+
+
+
+///////////////////////////////////////////////////////////////////////////////
+
+NpMaterial* NpPhysics::addMaterial(NpMaterial* m)
+{
+ if(!m)
+ return NULL;
+
+ Ps::Mutex::ScopedLock lock(mSceneAndMaterialMutex);
+
+ //the handle is set inside the setMaterial method
+ if(mMasterMaterialManager.setMaterial(*m))
+ {
+ // Let all scenes know of the new material
+ for(PxU32 i=0; i < mSceneArray.size(); i++)
+ {
+ NpScene* s = getScene(i);
+ s->addMaterial(*m);
+ }
+ return m;
+ }
+ else
+ {
+ m->release();
+ return NULL;
+ }
+}
+
+PxMaterial* NpPhysics::createMaterial(PxReal staticFriction, PxReal dynamicFriction, PxReal restitution)
+{
+ PxMaterial* m = NpFactory::getInstance().createMaterial(staticFriction, dynamicFriction, restitution);
+ return addMaterial(static_cast<NpMaterial*>(m));
+}
+
+PxU32 NpPhysics::getNbMaterials() const
+{
+ Ps::Mutex::ScopedLock lock(const_cast<Ps::Mutex&>(mSceneAndMaterialMutex));
+ return mMasterMaterialManager.getNumMaterials();
+}
+
+PxU32 NpPhysics::getMaterials(PxMaterial** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ Ps::Mutex::ScopedLock lock(const_cast<Ps::Mutex&>(mSceneAndMaterialMutex));
+ NpMaterialManagerIterator iter(mMasterMaterialManager);
+ PxU32 writeCount =0;
+ PxU32 index = 0;
+ NpMaterial* mat;
+ while(iter.getNextMaterial(mat))
+ {
+ if(index++ < startIndex)
+ continue;
+ if(writeCount == bufferSize)
+ break;
+ userBuffer[writeCount++] = mat;
+ }
+ return writeCount;
+}
+
+void NpPhysics::removeMaterialFromTable(NpMaterial& m)
+{
+ Ps::Mutex::ScopedLock lock(mSceneAndMaterialMutex);
+
+ // Let all scenes know of the deleted material
+ for(PxU32 i=0; i < mSceneArray.size(); i++)
+ {
+ NpScene* s = getScene(i);
+ s->removeMaterial(m);
+ }
+
+ mMasterMaterialManager.removeMaterial(m);
+}
+
+void NpPhysics::updateMaterial(NpMaterial& m)
+{
+ Ps::Mutex::ScopedLock lock(mSceneAndMaterialMutex);
+
+ // Let all scenes know of the updated material
+ for(PxU32 i=0; i < mSceneArray.size(); i++)
+ {
+ NpScene* s = getScene(i);
+ s->updateMaterial(m);
+ }
+ mMasterMaterialManager.updateMaterial(m);
+}
+
+bool NpPhysics::sendMaterialTable(NpScene& scene)
+{
+ // note: no lock here because this method gets only called at scene creation and there we do lock
+
+ NpMaterialManagerIterator iter(mMasterMaterialManager);
+ NpMaterial* mat;
+ while(iter.getNextMaterial(mat))
+ scene.addMaterial(*mat);
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+PxTriangleMesh* NpPhysics::createTriangleMesh(PxInputStream& stream)
+{
+ return NpFactory::getInstance().createTriangleMesh(stream);
+}
+
+PxU32 NpPhysics::getNbTriangleMeshes() const
+{
+ return NpFactory::getInstance().getNbTriangleMeshes();
+}
+
+PxU32 NpPhysics::getTriangleMeshes(PxTriangleMesh** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ return NpFactory::getInstance().getTriangleMeshes(userBuffer, bufferSize, startIndex);
+}
+
+PxHeightField* NpPhysics::createHeightField(PxInputStream& stream)
+{
+ return NpFactory::getInstance().createHeightField(stream);
+}
+
+PxU32 NpPhysics::getNbHeightFields() const
+{
+ return NpFactory::getInstance().getNbHeightFields();
+}
+
+PxU32 NpPhysics::getHeightFields(PxHeightField** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ return NpFactory::getInstance().getHeightFields(userBuffer, bufferSize, startIndex);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+PxConvexMesh* NpPhysics::createConvexMesh(PxInputStream& stream)
+{
+ return NpFactory::getInstance().createConvexMesh(stream);
+}
+
+
+PxU32 NpPhysics::getNbConvexMeshes() const
+{
+ return NpFactory::getInstance().getNbConvexMeshes();
+}
+
+PxU32 NpPhysics::getConvexMeshes(PxConvexMesh** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ return NpFactory::getInstance().getConvexMeshes(userBuffer, bufferSize, startIndex);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+#if PX_USE_CLOTH_API
+PxClothFabric* NpPhysics::createClothFabric(PxInputStream& stream)
+{
+ return NpFactory::getInstance().createClothFabric(stream);
+}
+
+PxClothFabric* NpPhysics::createClothFabric(const PxClothFabricDesc& desc)
+{
+ return NpFactory::getInstance().createClothFabric(desc);
+}
+
+PxU32 NpPhysics::getNbClothFabrics() const
+{
+ return NpFactory::getInstance().getNbClothFabrics();
+}
+
+
+PxU32 NpPhysics::getClothFabrics(PxClothFabric** userBuffer, PxU32 bufferSize) const
+{
+ return NpFactory::getInstance().getClothFabrics(userBuffer, bufferSize);
+}
+
+void NpPhysics::registerCloth()
+{
+ NpFactory::registerCloth();
+
+ Ps::Mutex::ScopedLock lock(mSceneAndMaterialMutex);
+ for(PxU32 i = 0; i < mSceneArray.size(); i++)
+ mSceneArray[i]->getScene().getScScene().createClothSolver();
+}
+#endif
+
+PxPruningStructure* NpPhysics::createPruningStructure(PxRigidActor*const* actors, PxU32 nbActors)
+{
+ PX_SIMD_GUARD;
+
+ PX_ASSERT(actors);
+ PX_ASSERT(nbActors > 0);
+
+ Sq::PruningStructure* ps = PX_NEW(Sq::PruningStructure)();
+ if(!ps->build(actors, nbActors))
+ {
+ PX_DELETE_AND_RESET(ps);
+ }
+ return ps;
+}
+
+#if PX_SUPPORT_GPU_PHYSX
+void NpPhysics::registerPhysXIndicatorGpuClient()
+{
+ Ps::Mutex::ScopedLock lock(mPhysXIndicatorMutex);
+
+ ++mNbRegisteredGpuClients;
+
+ mPhysXIndicator.setIsGpu(mNbRegisteredGpuClients>0);
+}
+
+void NpPhysics::unregisterPhysXIndicatorGpuClient()
+{
+ Ps::Mutex::ScopedLock lock(mPhysXIndicatorMutex);
+
+ if (mNbRegisteredGpuClients)
+ --mNbRegisteredGpuClients;
+
+ mPhysXIndicator.setIsGpu(mNbRegisteredGpuClients>0);
+}
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+void NpPhysics::registerDeletionListener(PxDeletionListener& observer, const PxDeletionEventFlags& deletionEvents, bool restrictedObjectSet)
+{
+ Ps::Mutex::ScopedLock lock(mDeletionListenerMutex);
+
+ const DeletionListenerMap::Entry* entry = mDeletionListenerMap.find(&observer);
+ if(!entry)
+ {
+ NpDelListenerEntry* e = PX_NEW(NpDelListenerEntry)(deletionEvents, restrictedObjectSet);
+ if (e)
+ {
+ if (mDeletionListenerMap.insert(&observer, e))
+ mDeletionListenersExist = true;
+ else
+ {
+ PX_DELETE(e);
+ PX_ALWAYS_ASSERT();
+ }
+ }
+ }
+ else
+ PX_ASSERT(mDeletionListenersExist);
+}
+
+void NpPhysics::unregisterDeletionListener(PxDeletionListener& observer)
+{
+ Ps::Mutex::ScopedLock lock(mDeletionListenerMutex);
+
+ const DeletionListenerMap::Entry* entry = mDeletionListenerMap.find(&observer);
+ if(entry)
+ {
+ NpDelListenerEntry* e = entry->second;
+ mDeletionListenerMap.erase(&observer);
+ PX_DELETE(e);
+ }
+ mDeletionListenersExist = mDeletionListenerMap.size()>0;
+}
+
+
+void NpPhysics::registerDeletionListenerObjects(PxDeletionListener& observer, const PxBase* const* observables, PxU32 observableCount)
+{
+ Ps::Mutex::ScopedLock lock(mDeletionListenerMutex);
+
+ const DeletionListenerMap::Entry* entry = mDeletionListenerMap.find(&observer);
+ if(entry)
+ {
+ NpDelListenerEntry* e = entry->second;
+ PX_CHECK_AND_RETURN(e->restrictedObjectSet, "PxPhysics::registerDeletionListenerObjects: deletion listener is not configured to receive events from specific objects.");
+
+ e->registeredObjects.reserve(e->registeredObjects.size() + observableCount);
+ for(PxU32 i=0; i < observableCount; i++)
+ e->registeredObjects.insert(observables[i]);
+ }
+ else
+ {
+ PX_CHECK_AND_RETURN(false, "PxPhysics::registerDeletionListenerObjects: deletion listener has to be registered in PxPhysics first.");
+ }
+}
+
+
+void NpPhysics::unregisterDeletionListenerObjects(PxDeletionListener& observer, const PxBase* const* observables, PxU32 observableCount)
+{
+ Ps::Mutex::ScopedLock lock(mDeletionListenerMutex);
+
+ const DeletionListenerMap::Entry* entry = mDeletionListenerMap.find(&observer);
+ if(entry)
+ {
+ NpDelListenerEntry* e = entry->second;
+ if (e->restrictedObjectSet)
+ {
+ for(PxU32 i=0; i < observableCount; i++)
+ e->registeredObjects.erase(observables[i]);
+ }
+ else
+ {
+ PX_CHECK_AND_RETURN(false, "PxPhysics::unregisterDeletionListenerObjects: deletion listener is not configured to receive events from specific objects.");
+ }
+ }
+ else
+ {
+ PX_CHECK_AND_RETURN(false, "PxPhysics::unregisterDeletionListenerObjects: deletion listener has to be registered in PxPhysics first.");
+ }
+}
+
+
+void NpPhysics::notifyDeletionListeners(const PxBase* base, void* userData, PxDeletionEventFlag::Enum deletionEvent)
+{
+ // we don't protect the check for whether there are any listeners, because we don't want to take a hit in the
+ // common case where there are no listeners. Note the API comments here, that users should not register or
+ // unregister deletion listeners while deletions are occurring
+
+ if(mDeletionListenersExist)
+ {
+ Ps::Mutex::ScopedLock lock(mDeletionListenerMutex);
+
+ const DeletionListenerMap::Entry* delListenerEntries = mDeletionListenerMap.getEntries();
+ const PxU32 delListenerEntryCount = mDeletionListenerMap.size();
+ for(PxU32 i=0; i < delListenerEntryCount; i++)
+ {
+ const NpDelListenerEntry* entry = delListenerEntries[i].second;
+
+ if (entry->flags & deletionEvent)
+ {
+ if (entry->restrictedObjectSet)
+ {
+ if (entry->registeredObjects.contains(base))
+ delListenerEntries[i].first->onRelease(base, userData, deletionEvent);
+ }
+ else
+ delListenerEntries[i].first->onRelease(base, userData, deletionEvent);
+ }
+ }
+ }
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+const PxTolerancesScale& NpPhysics::getTolerancesScale() const
+{
+ return mPhysics.getTolerancesScale();
+}
+
+PxFoundation& NpPhysics::getFoundation()
+{
+ return Ps::Foundation::getInstance();
+}
+
+PxPhysics& PxGetPhysics()
+{
+ return NpPhysics::getInstance();
+}
+
+PxPhysics* PxCreateBasePhysics(PxU32 version, PxFoundation& foundation, const PxTolerancesScale& scale, bool trackOutstandingAllocations,
+ physx::PxPvd* pvd)
+{
+ return NpPhysics::createInstance(version, foundation, scale, trackOutstandingAllocations, static_cast<physx::pvdsdk::PsPvd*>(pvd));
+}
+
+void PxRegisterArticulations(PxPhysics& physics)
+{
+ PX_UNUSED(&physics); // for the moment
+ Dy::PxvRegisterArticulations();
+ NpFactory::registerArticulations();
+}
+
+void PxRegisterHeightFields(PxPhysics& physics)
+{
+ PX_UNUSED(&physics); // for the moment
+ PX_CHECK_AND_RETURN(NpPhysics::getInstance().getNumScenes() == 0, "PxRegisterHeightFields: it is illegal to call a heightfield registration function after you have a scene.");
+
+ PxvRegisterHeightFields();
+ Gu::registerHeightFields();
+#if PX_CHECKED
+ NpPhysics::heightfieldsAreRegistered();
+#endif
+}
+
+void PxRegisterLegacyHeightFields(PxPhysics& physics)
+{
+ PX_CHECK_AND_RETURN(NpPhysics::getInstance().getNumScenes() == 0, "PxRegisterLegacyHeightFields: it is illegal to call a heightfield registration function after you have a scene.");
+ PX_UNUSED(&physics); // for the moment
+ PxvRegisterLegacyHeightFields();
+ Gu::registerHeightFields();
+#if PX_CHECKED
+ NpPhysics::heightfieldsAreRegistered();
+#endif
+}
+
+void PxRegisterCloth(PxPhysics& physics)
+{
+ PX_UNUSED(&physics);
+
+#if PX_USE_CLOTH_API
+ static_cast<NpPhysics&>(physics).registerCloth();
+#endif
+}
+
+void PxRegisterParticles(PxPhysics& physics)
+{
+ PX_UNUSED(&physics); // for the moment
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ Pt::registerParticles();
+ NpFactory::registerParticles();
+#endif
+}
+
+bool NpPhysics::lockScene()
+{
+ mSceneRunning.lock();
+
+ return true;
+}
+
+bool NpPhysics::unlockScene()
+{
+ mSceneRunning.unlock();
+
+ return true;
+}
+
+void PxAddCollectionToPhysics(const PxCollection& collection)
+{
+ NpFactory& factory = NpFactory::getInstance();
+ const Cm::Collection& c = static_cast<const Cm::Collection&>(collection);
+ factory.addCollection(c);
+}
diff --git a/PhysX_3.4/Source/PhysX/src/NpPhysics.h b/PhysX_3.4/Source/PhysX/src/NpPhysics.h
new file mode 100644
index 00000000..6aee41bc
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpPhysics.h
@@ -0,0 +1,274 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_PHYSICS
+#define PX_PHYSICS_NP_PHYSICS
+
+#include "foundation/PxProfiler.h"
+#include "PxPhysics.h"
+#include "PsUserAllocated.h"
+#include "GuMeshFactory.h"
+#include "NpMaterial.h"
+#include "NpPhysicsInsertionCallback.h"
+#include "NpMaterialManager.h"
+#include "ScPhysics.h"
+#include "PsHashSet.h"
+#include "PsHashMap.h"
+
+#if PX_SUPPORT_GPU_PHYSX
+#include "gpu/NpPhysicsGpu.h"
+#endif
+
+#ifdef LINUX
+#include <string.h>
+#endif
+
+#if PX_SUPPORT_GPU_PHYSX
+#include "device/PhysXIndicator.h"
+#endif
+
+#include "PsPvd.h"
+
+namespace physx
+{
+#if PX_SUPPORT_PVD
+namespace Vd
+{
+ class PvdPhysicsClient;
+}
+#endif
+ struct NpMaterialIndexTranslator
+ {
+ NpMaterialIndexTranslator() : indicesNeedTranslation(false) {}
+
+ Ps::HashMap<PxU16, PxU16> map;
+ bool indicesNeedTranslation;
+ };
+
+ class NpScene;
+ struct PxvOffsetTable;
+
+#if PX_VC
+#pragma warning(push)
+#pragma warning(disable:4996) // We have to implement deprecated member functions, do not warn.
+#endif
+
+class NpPhysics : public PxPhysics, public Ps::UserAllocated
+{
+ NpPhysics& operator=(const NpPhysics&);
+ NpPhysics(const NpPhysics &);
+
+ struct NpDelListenerEntry : public UserAllocated
+ {
+ NpDelListenerEntry(const PxDeletionEventFlags& de, bool restrictedObjSet)
+ : flags(de)
+ , restrictedObjectSet(restrictedObjSet)
+ {
+ }
+
+ Ps::HashSet<const PxBase*> registeredObjects; // specifically registered objects for deletion events
+ PxDeletionEventFlags flags;
+ bool restrictedObjectSet;
+ };
+
+
+ NpPhysics( const PxTolerancesScale& scale,
+ const PxvOffsetTable& pxvOffsetTable,
+ bool trackOutstandingAllocations,
+ physx::pvdsdk::PsPvd* pvd);
+ virtual ~NpPhysics();
+
+public:
+
+ static NpPhysics* createInstance( PxU32 version,
+ PxFoundation& foundation,
+ const PxTolerancesScale& scale,
+ bool trackOutstandingAllocations,
+ physx::pvdsdk::PsPvd* pvd);
+
+ static PxU32 releaseInstance();
+
+ static NpPhysics& getInstance() { return *mInstance; }
+
+ virtual void release();
+
+ virtual PxScene* createScene(const PxSceneDesc&);
+ void releaseSceneInternal(PxScene&);
+ virtual PxU32 getNbScenes() const;
+ virtual PxU32 getScenes(PxScene** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+
+ virtual PxRigidStatic* createRigidStatic(const PxTransform&);
+ virtual PxRigidDynamic* createRigidDynamic(const PxTransform&);
+ virtual PxArticulation* createArticulation();
+ virtual PxConstraint* createConstraint(PxRigidActor* actor0, PxRigidActor* actor1, PxConstraintConnector& connector, const PxConstraintShaderTable& shaders, PxU32 dataSize);
+ virtual PxAggregate* createAggregate(PxU32 maxSize, bool selfCollision);
+
+ virtual PxShape* createShape(const PxGeometry&, PxMaterial*const *, PxU16, bool, PxShapeFlags shapeFlags);
+ virtual PxU32 getNbShapes() const;
+ virtual PxU32 getShapes(PxShape** userBuffer, PxU32 bufferSize, PxU32 startIndex) const;
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ virtual PxParticleSystem* createParticleSystem(PxU32 maxParticles, bool perParticleRestOffset);
+ virtual PxParticleFluid* createParticleFluid(PxU32 maxParticles, bool perParticleRestOffset);
+#endif
+
+#if PX_USE_CLOTH_API
+ virtual PxCloth* createCloth(const PxTransform& globalPose, PxClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags);
+#endif
+
+ virtual PxMaterial* createMaterial(PxReal staticFriction, PxReal dynamicFriction, PxReal restitution);
+ virtual PxU32 getNbMaterials() const;
+ virtual PxU32 getMaterials(PxMaterial** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+
+ virtual PxTriangleMesh* createTriangleMesh(PxInputStream&);
+ virtual PxU32 getNbTriangleMeshes() const;
+ virtual PxU32 getTriangleMeshes(PxTriangleMesh** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+
+ virtual PxHeightField* createHeightField(PxInputStream& stream);
+ virtual PxU32 getNbHeightFields() const;
+ virtual PxU32 getHeightFields(PxHeightField** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+
+ virtual PxConvexMesh* createConvexMesh(PxInputStream&);
+ virtual PxU32 getNbConvexMeshes() const;
+ virtual PxU32 getConvexMeshes(PxConvexMesh** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+
+#if PX_USE_CLOTH_API
+ virtual PxClothFabric* createClothFabric(PxInputStream&);
+ virtual PxClothFabric* createClothFabric(const PxClothFabricDesc& desc);
+ virtual PxU32 getNbClothFabrics() const;
+ virtual PxU32 getClothFabrics(PxClothFabric** userBuffer, PxU32 bufferSize) const;
+ void registerCloth();
+#endif
+
+#if PX_SUPPORT_GPU_PHYSX
+ void registerPhysXIndicatorGpuClient();
+ void unregisterPhysXIndicatorGpuClient();
+#else
+ PX_FORCE_INLINE void registerPhysXIndicatorGpuClient() {}
+ PX_FORCE_INLINE void unregisterPhysXIndicatorGpuClient() {}
+#endif
+
+ virtual PxPruningStructure* createPruningStructure(PxRigidActor*const* actors, PxU32 nbActors);
+
+ virtual const PxTolerancesScale& getTolerancesScale() const;
+
+ virtual PxFoundation& getFoundation();
+
+ bool lockScene();
+ bool unlockScene();
+
+ PX_INLINE NpScene* getScene(PxU32 i) const { return mSceneArray[i]; }
+ PX_INLINE PxU32 getNumScenes() const { return mSceneArray.size(); }
+#if PX_CHECKED
+ static PX_INLINE void heightfieldsAreRegistered() { mHeightFieldsRegistered = true; }
+#endif
+
+#if PX_SUPPORT_GPU_PHYSX
+ virtual NpPhysicsGpu& getNpPhysicsGpu() { return mPhysicsGpu; }
+#endif
+
+ virtual void registerDeletionListener(PxDeletionListener& observer, const PxDeletionEventFlags& deletionEvents, bool restrictedObjectSet);
+ virtual void unregisterDeletionListener(PxDeletionListener& observer);
+ virtual void registerDeletionListenerObjects(PxDeletionListener& observer, const PxBase* const* observables, PxU32 observableCount);
+ virtual void unregisterDeletionListenerObjects(PxDeletionListener& observer, const PxBase* const* observables, PxU32 observableCount);
+
+ void notifyDeletionListeners(const PxBase*, void* userData, PxDeletionEventFlag::Enum deletionEvent);
+ PX_FORCE_INLINE void notifyDeletionListenersUserRelease(const PxBase* b, void* userData) { notifyDeletionListeners(b, userData, PxDeletionEventFlag::eUSER_RELEASE); }
+ PX_FORCE_INLINE void notifyDeletionListenersMemRelease(const PxBase* b, void* userData) { notifyDeletionListeners(b, userData, PxDeletionEventFlag::eMEMORY_RELEASE); }
+
+ virtual PxPhysicsInsertionCallback& getPhysicsInsertionCallback() { return mObjectInsertion; }
+
+ void removeMaterialFromTable(NpMaterial&);
+ void updateMaterial(NpMaterial&);
+ bool sendMaterialTable(NpScene&);
+
+ NpMaterialManager& getMaterialManager() { return mMasterMaterialManager; }
+
+ NpMaterial* addMaterial(NpMaterial* np);
+
+ static void initOffsetTables(PxvOffsetTable& pxvOffsetTable);
+
+ static bool apiReentryLock;
+
+private:
+ typedef Ps::CoalescedHashMap<PxDeletionListener*, NpDelListenerEntry*> DeletionListenerMap;
+
+ Ps::Array<NpScene*> mSceneArray;
+
+ Ps::Mutex mSceneRunning;
+
+ Sc::Physics mPhysics;
+ NpMaterialManager mMasterMaterialManager;
+
+ NpPhysicsInsertionCallback mObjectInsertion;
+
+ struct MeshDeletionListener: public GuMeshFactoryListener
+ {
+ void onGuMeshFactoryBufferRelease(const PxBase* object, PxType type)
+ {
+ PX_UNUSED(type);
+ NpPhysics::getInstance().notifyDeletionListeners(object, NULL, PxDeletionEventFlag::eMEMORY_RELEASE);
+ }
+ };
+
+ Ps::Mutex mDeletionListenerMutex;
+ DeletionListenerMap mDeletionListenerMap;
+ MeshDeletionListener mDeletionMeshListener;
+ bool mDeletionListenersExist;
+
+ Ps::Mutex mSceneAndMaterialMutex; // guarantees thread safety for API calls related to scene and material containers
+
+#if PX_SUPPORT_GPU_PHYSX
+ PhysXIndicator mPhysXIndicator;
+ PxU32 mNbRegisteredGpuClients;
+ Ps::Mutex mPhysXIndicatorMutex;
+ NpPhysicsGpu mPhysicsGpu;
+#endif
+#if PX_SUPPORT_PVD
+ physx::pvdsdk::PsPvd* mPvd;
+ Vd::PvdPhysicsClient* mPvdPhysicsClient;
+#endif
+
+ static PxU32 mRefCount;
+ static NpPhysics* mInstance;
+
+#if PX_CHECKED
+ static bool mHeightFieldsRegistered; //just for error checking
+#endif
+
+ friend class NpCollection;
+};
+
+#if PX_VC
+#pragma warning(pop)
+#endif
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpPhysicsInsertionCallback.h b/PhysX_3.4/Source/PhysX/src/NpPhysicsInsertionCallback.h
new file mode 100644
index 00000000..4bfd9b33
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpPhysicsInsertionCallback.h
@@ -0,0 +1,69 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_PHYSICS_INSERTION_CALLBACK
+#define PX_PHYSICS_NP_PHYSICS_INSERTION_CALLBACK
+
+#include "common/PxPhysicsInsertionCallback.h"
+#include "GuTriangleMesh.h"
+#include "GuHeightField.h"
+#include "GuConvexMesh.h"
+#include "NpFactory.h"
+#include "PsFoundation.h"
+
+namespace physx
+{
+ class NpPhysicsInsertionCallback: public PxPhysicsInsertionCallback
+ {
+ public:
+ NpPhysicsInsertionCallback() {}
+
+ virtual PxBase* buildObjectFromData(PxConcreteType::Enum type, void* data)
+ {
+ if(type == PxConcreteType::eTRIANGLE_MESH_BVH33 || type == PxConcreteType::eTRIANGLE_MESH_BVH34)
+ return NpFactory::getInstance().createTriangleMesh(data);
+
+ if (type == PxConcreteType::eCONVEX_MESH)
+ return NpFactory::getInstance().createConvexMesh(data);
+
+ if (type == PxConcreteType::eHEIGHTFIELD)
+ return NpFactory::getInstance().createHeightField(data);
+
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__, "Inserting object failed: "
+ "Object type not supported for buildObjectFromData.");
+
+ return NULL;
+ }
+
+ };
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpPtrTableStorageManager.h b/PhysX_3.4/Source/PhysX/src/NpPtrTableStorageManager.h
new file mode 100644
index 00000000..17c74129
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpPtrTableStorageManager.h
@@ -0,0 +1,105 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_PTRTABLESTORAGEMANAGER_H
+#define PX_PHYSICS_NP_PTRTABLESTORAGEMANAGER_H
+
+#include "CmPhysXCommon.h"
+#include "PsMutex.h"
+#include "PsUserAllocated.h"
+#include "CmPtrTable.h"
+#include "PsBitUtils.h"
+
+namespace physx
+{
+class NpPtrTableStorageManager : public Cm::PtrTableStorageManager, public Ps::UserAllocated
+{
+ PX_NOCOPY(NpPtrTableStorageManager)
+
+public:
+
+ NpPtrTableStorageManager() {}
+ ~NpPtrTableStorageManager() {}
+
+ void** allocate(PxU32 capacity)
+ {
+ PX_ASSERT(Ps::isPowerOfTwo(capacity));
+
+ Ps::Mutex::ScopedLock lock(mMutex);
+
+ return capacity<=4*sizeof(void*) ? reinterpret_cast<void**>(mPool4.construct())
+ : capacity<=16*sizeof(void*) ? reinterpret_cast<void**>(mPool16.construct())
+ : capacity<=64*sizeof(void*) ? reinterpret_cast<void**>(mPool64.construct())
+ : reinterpret_cast<void**>(PX_ALLOC(capacity*sizeof(void*), "CmPtrTable pointer array"));
+ }
+
+ void deallocate(void** addr, PxU32 capacity)
+ {
+ PX_ASSERT(Ps::isPowerOfTwo(capacity));
+
+ Ps::Mutex::ScopedLock lock(mMutex);
+
+ if(capacity<=4*sizeof(void*)) mPool4.destroy(reinterpret_cast< PtrBlock<4>*>(addr));
+ else if(capacity<=16*sizeof(void*)) mPool16.destroy(reinterpret_cast< PtrBlock<16>*>(addr));
+ else if(capacity<=64*sizeof(void*)) mPool64.destroy(reinterpret_cast< PtrBlock<64>*>(addr));
+ else PX_FREE(addr);
+ }
+
+ // originalCapacity is the only way we know which pool the alloc request belongs to,
+ // so if those are no longer going to match, we need to realloc.
+
+ bool canReuse(PxU32 originalCapacity, PxU32 newCapacity)
+ {
+ PX_ASSERT(Ps::isPowerOfTwo(originalCapacity));
+ PX_ASSERT(Ps::isPowerOfTwo(newCapacity));
+
+ return poolId(originalCapacity) == poolId(newCapacity) && newCapacity<=64;
+ }
+
+private:
+ Ps::Mutex mMutex;
+
+ int poolId(PxU32 size)
+ {
+ return size<=4 ? 0
+ : size<=16 ? 1
+ : size<=64 ? 2
+ : 3;
+ }
+
+ template<int N> class PtrBlock { void* ptr[N]; };
+
+ Ps::Pool2<PtrBlock<4>, 4096 > mPool4;
+ Ps::Pool2<PtrBlock<16>, 4096 > mPool16;
+ Ps::Pool2<PtrBlock<64>, 4096 > mPool64;
+};
+
+}
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpPvdSceneQueryCollector.cpp b/PhysX_3.4/Source/PhysX/src/NpPvdSceneQueryCollector.cpp
new file mode 100644
index 00000000..2756f1a1
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpPvdSceneQueryCollector.cpp
@@ -0,0 +1,159 @@
+// 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 "NpScene.h"
+
+#if PX_SUPPORT_PVD
+using namespace physx;
+using namespace Sq;
+using namespace Vd;
+
+void PvdSceneQueryCollector::release()
+{
+ physx::pvdsdk::PvdDataStream* stream = mScene.getScenePvdClient().getDataStream();
+ if(stream && stream->isConnected())
+ {
+ const Ps::Array<PxGeometryHolder>& geoms = getPrevFrameGeometries();
+ for(PxU32 k=0; k<geoms.size(); ++k)
+ stream->destroyInstance(&geoms[k]);
+
+ clearGeometryArrays();
+ }
+}
+
+template<class QueryResultT, class PvdHitType>
+static void collectBatchedHits(const QueryResultT* results, Ps::Array<PvdHitType>& accumulated, Ps::Array<PvdSqHit>& pvdSqHits, PxU32 nb, PxU32 startIdx, const char* arrayName)
+{
+ for(PxU32 i=0; i<nb; i++)
+ {
+ const QueryResultT& result = results[i];
+ if(result.queryStatus != PxBatchQueryStatus::eSUCCESS)
+ continue;
+
+ PvdHitType& query = accumulated[startIdx + i];
+ const PxU32 nbAnyHits = result.getNbAnyHits();
+ if(query.mHits.mCount != nbAnyHits)
+ {
+ query.mHits = PvdReference(arrayName, pvdSqHits.size(), nbAnyHits);
+
+ for(PxU32 j=0; j<nbAnyHits; j++)
+ pvdSqHits.pushBack(PvdSqHit(result.getAnyHit(j)));
+ }
+ }
+}
+
+void PvdSceneQueryCollector::collectAllBatchedHits(const PxRaycastQueryResult* r, PxU32 nbR, PxU32 idxR, const PxOverlapQueryResult* o, PxU32 nbO, PxU32 idxO, const PxSweepQueryResult* s, PxU32 nbS, PxU32 idxS)
+{
+ collectBatchedHits(r, mAccumulatedRaycastQueries, mPvdSqHits, nbR, idxR, getArrayName(mPvdSqHits));
+ collectBatchedHits(o, mAccumulatedOverlapQueries, mPvdSqHits, nbO, idxO, getArrayName(mPvdSqHits));
+ collectBatchedHits(s, mAccumulatedSweepQueries, mPvdSqHits, nbS, idxS, getArrayName(mPvdSqHits));
+}
+
+template<class SDKHitType, class PvdHitType>
+static void accumulate(PvdHitType& query, Ps::Array<PvdHitType>& accumulated, const char* arrayName, Ps::Array<PvdSqHit>& dst, const SDKHitType* src, PxU32 nb, const PxQueryFilterData& fd)
+{
+ query.mFilterFlags = fd.flags;
+ query.mHits = PvdReference(arrayName, dst.size(), nb);
+
+ PX_ASSERT(PxU32(-1) != nb);
+ for(PxU32 i=0; i<nb; i++)
+ dst.pushBack(PvdSqHit(src[i]));
+
+ accumulated.pushBack(query);
+}
+
+static PX_FORCE_INLINE void clampNbHits(PxU32& hitsNum, const PxQueryFilterData& fd, bool multipleHits)
+{
+ if((fd.flags & PxQueryFlag::eANY_HIT) || !multipleHits)
+ hitsNum = hitsNum > 0 ? 1u : 0;
+}
+
+template<class Type> static void pushBackT(Ps::Array<Type>& array, const Type& item, PvdReference& ref, const char* arrayName)
+{
+ ref = PvdReference(arrayName, array.size(), 1);
+ array.pushBack(item);
+}
+
+void PvdSceneQueryCollector::raycast(const PxVec3& origin, const PxVec3& unitDir, PxReal distance, const PxRaycastHit* hit, PxU32 hitsNum, const PxQueryFilterData& fd, bool multipleHits)
+{
+ Ps::Mutex::ScopedLock lock(mMutex);
+
+ PvdRaycast raycastQuery;
+ raycastQuery.mOrigin = origin;
+ raycastQuery.mUnitDir = unitDir;
+ raycastQuery.mDistance = distance;
+ raycastQuery.mFilterData = fd.data;
+ if(fd.flags & PxQueryFlag::eANY_HIT) raycastQuery.mType = QueryID::QUERY_RAYCAST_ANY_OBJECT;
+ else if(multipleHits) raycastQuery.mType = QueryID::QUERY_RAYCAST_ALL_OBJECTS;
+ else raycastQuery.mType = QueryID::QUERY_RAYCAST_CLOSEST_OBJECT;
+ clampNbHits(hitsNum, fd, multipleHits);
+
+ accumulate(raycastQuery, mAccumulatedRaycastQueries, getArrayName(mPvdSqHits), mPvdSqHits, hit, hitsNum, fd);
+}
+
+void PvdSceneQueryCollector::sweep(const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, PxReal distance, const PxSweepHit* hit, PxU32 hitsNum, const PxQueryFilterData& fd, bool multipleHits)
+{
+ Ps::Mutex::ScopedLock lock(mMutex);
+
+ PvdSweep sweepQuery;
+ pushBackT(mGeometries[mInUse], PxGeometryHolder(geometry), sweepQuery.mGeometries, getArrayName(mGeometries[mInUse])); // PT: TODO: optimize this. We memcopy once to the stack, then again to the array....
+ pushBackT(mPoses, pose, sweepQuery.mPoses, getArrayName(mPoses));
+ pushBackT(mFilterData, fd.data, sweepQuery.mFilterData, getArrayName(mFilterData));
+
+ const PxGeometryType::Enum type = geometry.getType(); // PT: TODO: QueryID::QUERY_LINEAR_xxx_SWEEP_ALL_OBJECTS are never used!
+ if(type==PxGeometryType::eBOX) sweepQuery.mType = QueryID::QUERY_LINEAR_OBB_SWEEP_CLOSEST_OBJECT;
+ else if(type==PxGeometryType::eSPHERE || type==PxGeometryType::eCAPSULE) sweepQuery.mType = QueryID::QUERY_LINEAR_CAPSULE_SWEEP_CLOSEST_OBJECT;
+ else if(type==PxGeometryType::eCONVEXMESH) sweepQuery.mType = QueryID::QUERY_LINEAR_CONVEX_SWEEP_CLOSEST_OBJECT;
+ else PX_ASSERT(0);
+ sweepQuery.mUnitDir = unitDir;
+ sweepQuery.mDistance = distance;
+ clampNbHits(hitsNum, fd, multipleHits);
+
+ accumulate(sweepQuery, mAccumulatedSweepQueries, getArrayName(mPvdSqHits), mPvdSqHits, hit, hitsNum, fd);
+}
+
+void PvdSceneQueryCollector::overlapMultiple(const PxGeometry& geometry, const PxTransform& pose, const PxOverlapHit* hit, PxU32 hitsNum, const PxQueryFilterData& fd)
+{
+ Ps::Mutex::ScopedLock lock(mMutex);
+
+ PvdOverlap overlapQuery;
+ pushBackT(mGeometries[mInUse], PxGeometryHolder(geometry), overlapQuery.mGeometries, getArrayName(mGeometries[mInUse])); // PT: TODO: optimize this. We memcopy once to the stack, then again to the array....
+
+ const PxGeometryType::Enum type = geometry.getType();
+ if(type==PxGeometryType::eBOX) overlapQuery.mType = pose.q.isIdentity() ? QueryID::QUERY_OVERLAP_AABB_ALL_OBJECTS : QueryID::QUERY_OVERLAP_OBB_ALL_OBJECTS;
+ else if(type==PxGeometryType::eSPHERE) overlapQuery.mType = QueryID::QUERY_OVERLAP_SPHERE_ALL_OBJECTS;
+ else if(type==PxGeometryType::eCAPSULE) overlapQuery.mType = QueryID::QUERY_OVERLAP_CAPSULE_ALL_OBJECTS;
+ else if(type==PxGeometryType::eCONVEXMESH) overlapQuery.mType = QueryID::QUERY_OVERLAP_CONVEX_ALL_OBJECTS;
+ else PX_ASSERT(0);
+ overlapQuery.mPose = pose;
+ overlapQuery.mFilterData = fd.data;
+
+ accumulate(overlapQuery, mAccumulatedOverlapQueries, getArrayName(mPvdSqHits), mPvdSqHits, hit, hitsNum, fd);
+}
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpPvdSceneQueryCollector.h b/PhysX_3.4/Source/PhysX/src/NpPvdSceneQueryCollector.h
new file mode 100644
index 00000000..38fe3091
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpPvdSceneQueryCollector.h
@@ -0,0 +1,305 @@
+// 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 NP_PVD_SCENEQUERYCOLLECTOR_H
+#define NP_PVD_SCENEQUERYCOLLECTOR_H
+
+#include "CmPhysXCommon.h"
+#include "PsArray.h"
+#include "PxFiltering.h"
+#include "PxGeometryHelpers.h"
+#include "PxQueryReport.h"
+#include "PxBatchQueryDesc.h"
+
+#if PX_SUPPORT_PVD
+
+namespace physx
+{
+namespace Scb
+{
+class Scene;
+}
+
+namespace Vd
+{
+struct PvdReference
+{
+ PX_FORCE_INLINE PvdReference() {}
+ PX_FORCE_INLINE PvdReference(const char* arrayName, PxU32 baseIndex, PxU32 count) : mArrayName(arrayName), mBaseIndex(baseIndex), mCount(count) {}
+
+ const char* mArrayName;
+ PxU32 mBaseIndex;
+ PxU32 mCount;
+};
+
+struct PvdRaycast
+{
+ PxU32 mType;
+ PxFilterData mFilterData;
+ PxU32 mFilterFlags;
+ PxVec3 mOrigin;
+ PxVec3 mUnitDir;
+ PxReal mDistance;
+ PvdReference mHits;
+};
+
+struct PvdOverlap
+{
+ PxU32 mType;
+ PxFilterData mFilterData;
+ PxU32 mFilterFlags;
+ PxTransform mPose;
+ PvdReference mGeometries;
+ PvdReference mHits;
+};
+
+struct PvdSweep
+{
+ PxU32 mType;
+ PxU32 mFilterFlags;
+ PxVec3 mUnitDir;
+ PxReal mDistance;
+ PvdReference mGeometries;
+ PvdReference mPoses;
+ PvdReference mFilterData;
+ PvdReference mHits;
+};
+
+struct PvdSqHit
+{
+ const void* mShape;
+ const void* mActor;
+ PxU32 mFaceIndex;
+ PxU32 mFlags;
+ PxVec3 mImpact;
+ PxVec3 mNormal;
+ PxF32 mDistance;
+ PxF32 mU;
+ PxF32 mV;
+
+ PvdSqHit()
+ {
+ setDefaults(PxQueryHit());
+ }
+
+ explicit PvdSqHit(const PxOverlapHit& hit)
+ {
+ setDefaults(hit);
+ }
+
+ explicit PvdSqHit(const PxRaycastHit& hit)
+ {
+ setDefaults(hit);
+
+ mImpact = hit.position;
+ mNormal = hit.normal;
+ mDistance = hit.distance;
+ mFlags = hit.flags;
+ mU = hit.u;
+ mV = hit.v;
+ }
+
+ explicit PvdSqHit(const PxSweepHit& hit)
+ {
+ setDefaults(hit);
+
+ mImpact = hit.position;
+ mNormal = hit.normal;
+ mDistance = hit.distance;
+ mFlags = hit.flags;
+ }
+
+ private:
+ void setDefaults(const PxQueryHit& hit)
+ {
+ mShape = hit.shape;
+ mActor = hit.actor;
+ mFaceIndex = hit.faceIndex;
+ mFlags = 0;
+ mImpact = mNormal = PxVec3(0.0f);
+ mDistance = mU = mV = 0.0f;
+ }
+};
+
+template <typename T, bool isBatched>
+inline const char* PvdGetArrayName()
+{
+ return T::template getArrayName<isBatched>();
+}
+template <>
+inline const char* PvdGetArrayName<PxGeometryHolder, false>()
+{
+ return "SceneQueries.GeometryList";
+}
+template <>
+inline const char* PvdGetArrayName<PxTransform, false>()
+{
+ return "SceneQueries.PoseList";
+}
+template <>
+inline const char* PvdGetArrayName<PxFilterData, false>()
+{
+ return "SceneQueries.FilterDataList";
+}
+template <>
+inline const char* PvdGetArrayName<PvdRaycast, false>()
+{
+ return "SceneQueries.Raycasts";
+}
+template <>
+inline const char* PvdGetArrayName<PvdOverlap, false>()
+{
+ return "SceneQueries.Overlaps";
+}
+template <>
+inline const char* PvdGetArrayName<PvdSweep, false>()
+{
+ return "SceneQueries.Sweeps";
+}
+template <>
+inline const char* PvdGetArrayName<PvdSqHit, false>()
+{
+ return "SceneQueries.Hits";
+}
+template <>
+inline const char* PvdGetArrayName<PxGeometryHolder, true>()
+{
+ return "BatchedQueries.GeometryList";
+}
+template <>
+inline const char* PvdGetArrayName<PxTransform, true>()
+{
+ return "BatchedQueries.PoseList";
+}
+template <>
+inline const char* PvdGetArrayName<PxFilterData, true>()
+{
+ return "BatchedQueries.FilterDataList";
+}
+template <>
+inline const char* PvdGetArrayName<PvdRaycast, true>()
+{
+ return "BatchedQueries.Raycasts";
+}
+template <>
+inline const char* PvdGetArrayName<PvdOverlap, true>()
+{
+ return "BatchedQueries.Overlaps";
+}
+template <>
+inline const char* PvdGetArrayName<PvdSweep, true>()
+{
+ return "BatchedQueries.Sweeps";
+}
+template <>
+inline const char* PvdGetArrayName<PvdSqHit, true>()
+{
+ return "BatchedQueries.Hits";
+}
+
+class PvdSceneQueryCollector
+{
+ PX_NOCOPY(PvdSceneQueryCollector)
+public:
+ PvdSceneQueryCollector(Scb::Scene& scene, bool isBatched) : mScene(scene), mInUse(0), mIsBatched(isBatched) {}
+ ~PvdSceneQueryCollector() {}
+
+ void clear()
+ {
+ Ps::Mutex::ScopedLock lock(mMutex);
+
+ mAccumulatedRaycastQueries.clear();
+ mAccumulatedOverlapQueries.clear();
+ mAccumulatedSweepQueries.clear();
+ mPvdSqHits.clear();
+ mPoses.clear();
+ mFilterData.clear();
+ }
+
+ void clearGeometryArrays()
+ {
+ mGeometries[0].clear();
+ mGeometries[1].clear();
+ }
+
+ void release();
+
+ void raycast(const PxVec3& origin, const PxVec3& unitDir, PxReal distance, const PxRaycastHit* hit, PxU32 hitsNum, const PxQueryFilterData& filterData, bool multipleHits);
+ void sweep(const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, PxReal distance, const PxSweepHit* hit, PxU32 hitsNum, const PxQueryFilterData& filterData, bool multipleHits);
+ void overlapMultiple(const PxGeometry& geometry, const PxTransform& pose, const PxOverlapHit* hit, PxU32 hitsNum, const PxQueryFilterData& filterData);
+
+ void collectAllBatchedHits (const PxRaycastQueryResult* raycastResults, PxU32 nbRaycastResults, PxU32 batchedRayQstartIdx,
+ const PxOverlapQueryResult* overlapResults, PxU32 nbOverlapResults, PxU32 batchedOverlapQstartIdx,
+ const PxSweepQueryResult* sweepResults, PxU32 nbSweepResults, PxU32 batchedSweepQstartIdx);
+
+ PX_FORCE_INLINE Ps::Mutex& getLock()
+ {
+ return mMutex;
+ }
+
+ PX_FORCE_INLINE const Ps::Array<PxGeometryHolder>& getCurrentFrameGeometries() const
+ {
+ return mGeometries[mInUse];
+ }
+ PX_FORCE_INLINE const Ps::Array<PxGeometryHolder>& getPrevFrameGeometries() const
+ {
+ return mGeometries[mInUse ^ 1];
+ }
+ void prepareNextFrameGeometries()
+ {
+ mInUse ^= 1;
+ mGeometries[mInUse].clear();
+ }
+ template <typename T>
+ const char* getArrayName(const Ps::Array<T>&)
+ {
+ return mIsBatched ? PvdGetArrayName<T, 1>() : PvdGetArrayName<T, 0>();
+ }
+
+ // Scene query and hits for pvd, collected in current frame
+ Ps::Array<PvdRaycast> mAccumulatedRaycastQueries;
+ Ps::Array<PvdSweep> mAccumulatedSweepQueries;
+ Ps::Array<PvdOverlap> mAccumulatedOverlapQueries;
+ Ps::Array<PvdSqHit> mPvdSqHits;
+ Ps::Array<PxTransform> mPoses;
+ Ps::Array<PxFilterData> mFilterData;
+
+private:
+ Scb::Scene& mScene;
+ Ps::Mutex mMutex;
+ Ps::Array<PxGeometryHolder> mGeometries[2];
+ PxU32 mInUse;
+ const bool mIsBatched;
+};
+}
+}
+
+#endif // PX_SUPPORT_PVD
+
+#endif // NP_PVD_SCENEQUERYCOLLECTOR_H
diff --git a/PhysX_3.4/Source/PhysX/src/NpQueryShared.h b/PhysX_3.4/Source/PhysX/src/NpQueryShared.h
new file mode 100644
index 00000000..9bf79883
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpQueryShared.h
@@ -0,0 +1,106 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_QUERYSHARED
+#define PX_PHYSICS_NP_QUERYSHARED
+
+#include "foundation/PxMemory.h"
+
+namespace physx
+{
+
+using namespace Cm;
+
+template <class ActorT>
+PX_FORCE_INLINE bool applyClientFilter(ActorT* actor, const PxQueryFilterData& filterData, const NpSceneQueries& scene)
+{
+ if(filterData.clientId != actor->getOwnerClient())
+ {
+ const bool passForeignShapes = scene.getClientBehaviorFlags(filterData.clientId) & PxClientBehaviorFlag::eREPORT_FOREIGN_OBJECTS_TO_SCENE_QUERY;
+ const bool reportToForeignClients = actor->getClientBehaviorFlags() & PxActorClientBehaviorFlag::eREPORT_TO_FOREIGN_CLIENTS_SCENE_QUERY;
+ if(!(passForeignShapes && reportToForeignClients))
+ return false;
+ }
+ return true;
+}
+
+PX_FORCE_INLINE bool applyFilterEquation(const Scb::Shape& scbShape, const PxFilterData& queryFd)
+{
+ // if the filterData field is non-zero, and the bitwise-AND value of filterData AND the shape's
+ // queryFilterData is zero, the shape is skipped.
+ if(queryFd.word0 | queryFd.word1 | queryFd.word2 | queryFd.word3)
+ {
+ const PxFilterData& objFd = scbShape.getScShape().getQueryFilterData();
+ const PxU32 keep = (queryFd.word0 & objFd.word0) | (queryFd.word1 & objFd.word1) | (queryFd.word2 & objFd.word2) | (queryFd.word3 & objFd.word3);
+ if(!keep)
+ return false;
+ }
+ return true;
+}
+
+//========================================================================================================================
+// these partial template specializations are used to generalize the query code to be reused for all permutations of
+// hit type=(raycast, overlap, sweep) x query type=(ANY, SINGLE, MULTIPLE)
+template <typename HitType> struct HitTypeSupport { enum { IsRaycast = 0, IsSweep = 0, IsOverlap = 0 }; };
+template <> struct HitTypeSupport<PxRaycastHit>
+{
+ enum { IsRaycast = 1, IsSweep = 0, IsOverlap = 0 };
+ static PX_FORCE_INLINE PxReal getDistance(const PxQueryHit& hit) { return static_cast<const PxRaycastHit&>(hit).distance; }
+};
+template <> struct HitTypeSupport<PxSweepHit>
+{
+ enum { IsRaycast = 0, IsSweep = 1, IsOverlap = 0 };
+ static PX_FORCE_INLINE PxReal getDistance(const PxQueryHit& hit) { return static_cast<const PxSweepHit&>(hit).distance; }
+};
+template <> struct HitTypeSupport<PxOverlapHit>
+{
+ enum { IsRaycast = 0, IsSweep = 0, IsOverlap = 1 };
+ static PX_FORCE_INLINE PxReal getDistance(const PxQueryHit&) { return -1.0f; }
+};
+
+#define HITDIST(hit) HitTypeSupport<HitType>::getDistance(hit)
+
+template<typename HitType>
+static PxU32 clipHitsToNewMaxDist(HitType* ppuHits, PxU32 count, PxReal newMaxDist)
+{
+ PxU32 i=0;
+ while(i!=count)
+ {
+ if(HITDIST(ppuHits[i]) > newMaxDist)
+ ppuHits[i] = ppuHits[--count];
+ else
+ i++;
+ }
+ return count;
+}
+
+} // namespace physx
+
+#endif // PX_PHYSICS_NP_QUERYSHARED
diff --git a/PhysX_3.4/Source/PhysX/src/NpReadCheck.cpp b/PhysX_3.4/Source/PhysX/src/NpReadCheck.cpp
new file mode 100644
index 00000000..4738866f
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpReadCheck.cpp
@@ -0,0 +1,83 @@
+// 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 "NpReadCheck.h"
+
+#include "NpScene.h"
+
+using namespace physx;
+
+NpReadCheck::NpReadCheck(const NpScene* scene, const char* functionName)
+ : mScene(scene), mName(functionName), mErrorCount(0)
+{
+ if (mScene)
+ {
+ if (!mScene->startRead())
+ {
+ if (mScene->getScene().getFlags() & PxSceneFlag::eREQUIRE_RW_LOCK)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "An API read call (%s) was made from thread %d but PxScene::lockRead() was not called first, note that "
+ "when PxSceneFlag::eREQUIRE_RW_LOCK is enabled all API reads and writes must be "
+ "wrapped in the appropriate locks.", mName, PxU32(Ps::Thread::getId()));
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Overlapping API read and write call detected during %s from thread %d! Note that read operations to "
+ "the SDK must not be overlapped with write calls, else the resulting behavior is undefined.", mName, PxU32(Ps::Thread::getId()));
+ }
+ }
+
+ // Record the NpScene read/write error counter which is
+ // incremented any time a NpScene::startWrite/startRead fails
+ // (see destructor for additional error checking based on this count)
+ mErrorCount = mScene->getReadWriteErrorCount();
+ }
+}
+
+
+NpReadCheck::~NpReadCheck()
+{
+ if (mScene)
+ {
+ // By checking if the NpScene::mConcurrentErrorCount has been incremented
+ // we can detect if an erroneous read/write was performed during
+ // this objects lifetime. In this case we also print this function's
+ // details so that the user can see which two API calls overlapped
+ if (mScene->getReadWriteErrorCount() != mErrorCount && !(mScene->getScene().getFlags() & PxSceneFlag::eREQUIRE_RW_LOCK))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Leaving %s on thread %d, an API overlapping write on another thread was detected.", mName, PxU32(Ps::Thread::getId()));
+ }
+
+ mScene->stopRead();
+ }
+}
diff --git a/PhysX_3.4/Source/PhysX/src/NpReadCheck.h b/PhysX_3.4/Source/PhysX/src/NpReadCheck.h
new file mode 100644
index 00000000..a7bd67a9
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpReadCheck.h
@@ -0,0 +1,69 @@
+// 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 NP_READ_CHECK_H
+#define NP_READ_CHECK_H
+
+#include "foundation/PxSimpleTypes.h"
+
+namespace physx
+{
+
+class NpScene;
+
+// RAII wrapper around the PxScene::startRead() method, note that this
+// object does not acquire any scene locks, it is an error checking only mechanism
+class NpReadCheck
+{
+public:
+ NpReadCheck(const NpScene* scene, const char* functionName);
+ ~NpReadCheck();
+private:
+ const NpScene* mScene;
+ const char* mName;
+ PxU32 mErrorCount;
+};
+
+#if (PX_DEBUG || PX_CHECKED)
+ // Creates a scoped read check object that detects whether appropriate scene locks
+ // have been acquired and checks if reads/writes overlap, this macro should typically
+ // be placed at the beginning of any const API methods that are not multi-thread safe,
+ // the error conditions checked can be summarized as:
+
+ // 1. PxSceneFlag::eREQUIRE_RW_LOCK was specified but PxScene::lockRead() was not yet called
+ // 2. Other threads were already writing, or began writing during the object lifetime
+ #define NP_READ_CHECK(npScenePtr) NpReadCheck npReadCheck(static_cast<const NpScene*>(npScenePtr), __FUNCTION__);
+#else
+ #define NP_READ_CHECK(npScenePtr)
+#endif
+
+}
+
+#endif // NP_Read_CHECK_H
diff --git a/PhysX_3.4/Source/PhysX/src/NpRigidActorTemplate.h b/PhysX_3.4/Source/PhysX/src/NpRigidActorTemplate.h
new file mode 100644
index 00000000..6e3bbf5a
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpRigidActorTemplate.h
@@ -0,0 +1,467 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_RIGIDACTOR_TEMPLATE
+#define PX_PHYSICS_NP_RIGIDACTOR_TEMPLATE
+
+#include "NpActorTemplate.h"
+#include "NpShapeManager.h"
+#include "NpConstraint.h"
+#include "NpFactory.h"
+
+// PX_SERIALIZATION
+#include "foundation/PxErrors.h"
+//~PX_SERIALIZATION
+
+namespace physx
+{
+
+template<class APIClass>
+class NpRigidActorTemplate : public NpActorTemplate<APIClass>
+{
+private:
+ typedef NpActorTemplate<APIClass> ActorTemplateClass;
+
+public:
+// PX_SERIALIZATION
+ NpRigidActorTemplate(PxBaseFlags baseFlags) : ActorTemplateClass(baseFlags), mShapeManager(PxEmpty), mIndex(0xFFFFFFFF) {}
+ virtual void requires(PxProcessPxBaseCallback& c);
+ virtual void exportExtraData(PxSerializationContext& stream);
+ void importExtraData(PxDeserializationContext& context);
+ void resolveReferences(PxDeserializationContext& context);
+//~PX_SERIALIZATION
+ virtual ~NpRigidActorTemplate();
+
+ //---------------------------------------------------------------------------------
+ // PxActor implementation
+ //---------------------------------------------------------------------------------
+ virtual void release();
+
+ // The rule is: If an API method is used somewhere in here, it has to be redeclared, else GCC whines
+ virtual PxActorType::Enum getType() const = 0;
+
+ virtual PxBounds3 getWorldBounds(float inflation=1.01f) const;
+
+ virtual void setActorFlag(PxActorFlag::Enum flag, bool value);
+ virtual void setActorFlags(PxActorFlags inFlags);
+
+ //---------------------------------------------------------------------------------
+ // PxRigidActor implementation
+ //---------------------------------------------------------------------------------
+
+ // Shapes
+ virtual PxU32 getNbShapes() const;
+ virtual PxU32 getShapes(PxShape** buffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+
+ // Constraint shaders
+ virtual PxU32 getNbConstraints() const;
+ virtual PxU32 getConstraints(PxConstraint** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+
+ // Multiclient
+ virtual void setClientBehaviorFlags(PxActorClientBehaviorFlags);
+
+ // shared shapes
+ virtual void attachShape(PxShape& s);
+ virtual void detachShape(PxShape& s, bool wakeOnLostTouch);
+
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ NpRigidActorTemplate(PxType concreteType, PxBaseFlags baseFlags);
+
+ // not optimal but the template alternative is hardly more readable and perf is not that critical here
+ virtual void switchToNoSim() { PX_ASSERT(false); }
+ virtual void switchFromNoSim() { PX_ASSERT(false); }
+
+ void releaseShape(NpShape& s);
+
+ PX_FORCE_INLINE NpShapeManager& getShapeManager() { return mShapeManager; }
+ PX_FORCE_INLINE const NpShapeManager& getShapeManager() const { return mShapeManager; }
+
+ void updateShaderComs();
+
+ PX_FORCE_INLINE PxU32 getRigidActorArrayIndex() const { return mIndex; }
+ PX_FORCE_INLINE void setRigidActorArrayIndex(const PxU32& index) { mIndex = index; }
+
+ bool resetFiltering(Scb::RigidObject& ro, PxShape*const* shapes, PxU32 shapeCount);
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+public:
+ void visualize(Cm::RenderOutput& out, NpScene* scene);
+#endif
+protected:
+ PX_FORCE_INLINE void setActorSimFlag(bool value);
+
+ NpShapeManager mShapeManager;
+ PxU32 mIndex; // index for the NpScene rigid actor array
+};
+
+// PX_SERIALIZATION
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::requires(PxProcessPxBaseCallback& c)
+{
+ // export shapes
+ PxU32 nbShapes = mShapeManager.getNbShapes();
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ NpShape* np = mShapeManager.getShapes()[i];
+ c.process(*np);
+ }
+}
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::exportExtraData(PxSerializationContext& stream)
+{
+ mShapeManager.exportExtraData(stream);
+ ActorTemplateClass::exportExtraData(stream);
+}
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::importExtraData(PxDeserializationContext& context)
+{
+ mShapeManager.importExtraData(context);
+ ActorTemplateClass::importExtraData(context);
+}
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::resolveReferences(PxDeserializationContext& context)
+{
+ const PxU32 nbShapes = mShapeManager.getNbShapes();
+ NpShape** shapes = const_cast<NpShape**>(mShapeManager.getShapes());
+ for(PxU32 j=0;j<nbShapes;j++)
+ {
+ context.translatePxBase(shapes[j]);
+ shapes[j]->onActorAttach(*this);
+ }
+
+ ActorTemplateClass::resolveReferences(context);
+}
+
+//~PX_SERIALIZATION
+
+template<class APIClass>
+NpRigidActorTemplate<APIClass>::NpRigidActorTemplate(PxType concreteType, PxBaseFlags baseFlags)
+: ActorTemplateClass(concreteType, baseFlags, NULL, NULL)
+{
+}
+
+template<class APIClass>
+NpRigidActorTemplate<APIClass>::~NpRigidActorTemplate()
+{
+ // TODO: no mechanism for notifying shaders of actor destruction yet
+}
+
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::release()
+{
+ NpActor::releaseConstraints(*this);
+ NpScene* scene = NpActor::getAPIScene(*this);
+ if(mShapeManager.getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxRigidActor::release: Actor is part of a pruning structure, pruning structure is now invalid!");
+ mShapeManager.getPruningStructure()->invalidate(this);
+ }
+
+ mShapeManager.detachAll(scene);
+
+// PX_AGGREGATE
+ ActorTemplateClass::release(); // PT: added for PxAggregate
+//~PX_AGGREGATE
+}
+
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::releaseShape(NpShape& s)
+{
+ // invalidate the pruning structure if the actor bounds changed
+ if (mShapeManager.getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxRigidActor::releaseShape: Actor is part of a pruning structure, pruning structure is now invalid!");
+ mShapeManager.getPruningStructure()->invalidate(this);
+ }
+ mShapeManager.detachShape(s, *this);
+}
+
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::attachShape(PxShape& shape)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(!static_cast<NpShape&>(shape).isExclusive() || shape.getActor()==NULL, "PxRigidActor::attachShape: shape must be shared or unowned");
+ PX_SIMD_GUARD
+ // invalidate the pruning structure if the actor bounds changed
+ if (mShapeManager.getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxRigidActor::attachShape: Actor is part of a pruning structure, pruning structure is now invalid!");
+ mShapeManager.getPruningStructure()->invalidate(this);
+ }
+
+ mShapeManager.attachShape(static_cast<NpShape&>(shape), *this);
+}
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::detachShape(PxShape& shape, bool wakeOnLostTouch)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(mShapeManager.shapeIsAttached(static_cast<NpShape&>(shape)), "PxRigidActor::detachShape: shape is not attached!")
+ if (mShapeManager.getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxRigidActor::detachShape: Actor is part of a pruning structure, pruning structure is now invalid!");
+ mShapeManager.getPruningStructure()->invalidate(this);
+ }
+
+ mShapeManager.detachShape(static_cast<NpShape&>(shape), *this, wakeOnLostTouch);
+}
+
+
+template<class APIClass>
+PxU32 NpRigidActorTemplate<APIClass>::getNbShapes() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mShapeManager.getNbShapes();
+}
+
+
+template<class APIClass>
+PxU32 NpRigidActorTemplate<APIClass>::getShapes(PxShape** buffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mShapeManager.getShapes(buffer, bufferSize, startIndex);
+}
+
+
+template<class APIClass>
+PxU32 NpRigidActorTemplate<APIClass>::getNbConstraints() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return ActorTemplateClass::getNbConnectors(NpConnectorType::eConstraint);
+}
+
+
+template<class APIClass>
+PxU32 NpRigidActorTemplate<APIClass>::getConstraints(PxConstraint** buffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return ActorTemplateClass::template getConnectors<PxConstraint>(NpConnectorType::eConstraint, buffer, bufferSize, startIndex); // Some people will love me for this one... The syntax is to be standard compliant and
+ // picky gcc won't compile without it. It is needed if you call a templated member function
+ // of a templated class
+}
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::setClientBehaviorFlags(PxActorClientBehaviorFlags b)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ Scb::Actor& scbActor = NpActor::getScbFromPxActor(*this);
+ if (scbActor.getClientBehaviorFlags() == b)
+ return;
+
+ scbActor.setClientBehaviorFlags(b);
+}
+
+template<class APIClass>
+PxBounds3 NpRigidActorTemplate<APIClass>::getWorldBounds(float inflation) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ PX_SIMD_GUARD;
+
+ const PxBounds3 bounds = mShapeManager.getWorldBounds(*this);
+ PX_ASSERT(bounds.isValid());
+
+ // PT: unfortunately we can't just scale the min/max vectors, we need to go through center/extents.
+ const PxVec3 center = bounds.getCenter();
+ const PxVec3 inflatedExtents = bounds.getExtents() * inflation;
+ return PxBounds3::centerExtents(center, inflatedExtents);
+}
+
+
+template<class APIClass>
+PX_FORCE_INLINE void NpRigidActorTemplate<APIClass>::setActorSimFlag(bool value)
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+
+ PxActorFlags oldFlags = ActorTemplateClass::getActorFlags();
+ bool hadNoSimFlag = oldFlags.isSet(PxActorFlag::eDISABLE_SIMULATION);
+
+ PX_CHECK_AND_RETURN((getType() != PxActorType::eARTICULATION_LINK) || (!value && !hadNoSimFlag), "PxActor::setActorFlag: PxActorFlag::eDISABLE_SIMULATION is only supported by PxRigidDynamic and PxRigidStatic objects.");
+
+ if (hadNoSimFlag && (!value))
+ {
+ switchFromNoSim();
+ ActorTemplateClass::setActorFlagsInternal(oldFlags & (~PxActorFlag::eDISABLE_SIMULATION)); // needs to be done before the code below to make sure the latest flags get picked up
+ if (scene)
+ NpActor::addConstraintsToScene();
+ }
+ else if ((!hadNoSimFlag) && value)
+ {
+ if (scene)
+ NpActor::removeConstraintsFromScene();
+ ActorTemplateClass::setActorFlagsInternal(oldFlags | PxActorFlag::eDISABLE_SIMULATION);
+ switchToNoSim();
+ }
+}
+
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::setActorFlag(PxActorFlag::Enum flag, bool value)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ if (flag == PxActorFlag::eDISABLE_SIMULATION)
+ setActorSimFlag(value);
+
+ ActorTemplateClass::setActorFlagInternal(flag, value);
+}
+
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::setActorFlags(PxActorFlags inFlags)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ bool noSim = inFlags.isSet(PxActorFlag::eDISABLE_SIMULATION);
+ setActorSimFlag(noSim);
+
+ ActorTemplateClass::setActorFlagsInternal(inFlags);
+}
+
+
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::updateShaderComs()
+{
+ NpConnectorIterator iter = ActorTemplateClass::getConnectorIterator(NpConnectorType::eConstraint);
+ while (PxBase* ser = iter.getNext())
+ {
+ NpConstraint* c = static_cast<NpConstraint*>(ser);
+ c->comShift(this);
+ }
+}
+
+
+PX_FORCE_INLINE static void fillResetFilteringShapeList(Scb::RigidObject& ro, Scb::Shape& scb, Scb::Shape** shapes, PxU32& shapeCount)
+{
+ // It is important to filter out shapes that have been added while the simulation was running because for those there is nothing to do.
+
+ if (!ro.isBuffered(Scb::RigidObjectBuffer::BF_Shapes) || !ro.isAddedShape(scb))
+ {
+ shapes[shapeCount] = &scb;
+ shapeCount++;
+ }
+}
+
+
+template<class APIClass>
+bool NpRigidActorTemplate<APIClass>::resetFiltering(Scb::RigidObject& ro, PxShape*const* shapes, PxU32 shapeCount)
+{
+ PX_CHECK_AND_RETURN_VAL(!(ro.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxScene::resetFiltering(): Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!", false);
+ for(PxU32 i=0; i < shapeCount; i++)
+ {
+#if PX_CHECKED
+ PxRigidActor* ra = shapes[i]->getActor();
+ if (ra != this)
+ {
+ bool found = false;
+ if (ra == NULL)
+ {
+ NpShape*const* sh = mShapeManager.getShapes();
+ for(PxU32 j=0; j < mShapeManager.getNbShapes(); j++)
+ {
+ if (sh[j] == shapes[i])
+ {
+ found = true;
+ break;
+ }
+ }
+ }
+
+ PX_CHECK_AND_RETURN_VAL(found, "PxScene::resetFiltering(): specified shape not in actor!", false);
+ }
+#endif
+ PX_CHECK_AND_RETURN_VAL(static_cast<NpShape*>(shapes[i])->getScbShape().getFlags() & (PxShapeFlag::eSIMULATION_SHAPE | PxShapeFlag::eTRIGGER_SHAPE), "PxScene::resetFiltering(): specified shapes not of type eSIMULATION_SHAPE or eTRIGGER_SHAPE!", false);
+ }
+
+ PxU32 sCount;
+ if (shapes)
+ sCount = shapeCount;
+ else
+ sCount = mShapeManager.getNbShapes();
+
+ PX_ALLOCA(scbShapes, Scb::Shape*, sCount);
+ if (scbShapes)
+ {
+ if (shapes) // the user specified the shapes
+ {
+ PxU32 sAccepted = 0;
+ for(PxU32 i=0; i < sCount; i++)
+ {
+ Scb::Shape& scb = static_cast<NpShape*>(shapes[i])->getScbShape();
+ fillResetFilteringShapeList(ro, scb, scbShapes, sAccepted);
+ }
+ sCount = sAccepted;
+ }
+ else // the user just specified the actor and the shapes are taken from the actor
+ {
+ NpShape* const* sh = mShapeManager.getShapes();
+ PxU32 sAccepted = 0;
+ for(PxU32 i=0; i < sCount; i++)
+ {
+ Scb::Shape& scb = sh[i]->getScbShape();
+ if (scb.getFlags() & (PxShapeFlag::eSIMULATION_SHAPE | PxShapeFlag::eTRIGGER_SHAPE))
+ {
+ fillResetFilteringShapeList(ro, scb, scbShapes, sAccepted);
+ }
+ }
+ sCount = sAccepted;
+ }
+
+ if (sCount)
+ {
+ ro.resetFiltering(scbShapes, sCount);
+ }
+ }
+
+ return true;
+}
+
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+template<class APIClass>
+void NpRigidActorTemplate<APIClass>::visualize(Cm::RenderOutput& out, NpScene* scene)
+{
+ mShapeManager.visualize(out, scene, *this);
+}
+#endif // PX_ENABLE_DEBUG_VISUALIZATION
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpRigidActorTemplateInternal.h b/PhysX_3.4/Source/PhysX/src/NpRigidActorTemplateInternal.h
new file mode 100644
index 00000000..635e1a83
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpRigidActorTemplateInternal.h
@@ -0,0 +1,69 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef PX_PHYSICS_NP_RIGIDACTOR_TEMPLATE_INTERNAL
+#define PX_PHYSICS_NP_RIGIDACTOR_TEMPLATE_INTERNAL
+
+namespace physx
+{
+
+template<class T, class T2>
+static PX_FORCE_INLINE void releaseActorT(NpRigidActorTemplate<T>* actor, T2& scbActor)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*actor));
+
+ NpPhysics::getInstance().notifyDeletionListenersUserRelease(actor, actor->userData);
+
+ Scb::Scene* s = scbActor.getScbSceneForAPI();
+
+ const bool noSim = scbActor.isSimDisabledInternally();
+ // important to check the non-buffered flag because it tells what the current internal state of the object is
+ // (someone might switch to non-simulation and release all while the sim is running). Reading is fine even if
+ // the sim is running because actor flags are read-only internally.
+ if(s && noSim)
+ {
+ // need to do it here because the Np-shape buffer will not be valid anymore after the release below
+ // and unlike simulation objects, there is no shape buffer in the simulation controller
+ actor->getShapeManager().clearShapesOnRelease(*s, *actor);
+ }
+
+ actor->NpRigidActorTemplate<T>::release();
+
+ if(s)
+ {
+ s->removeActor(scbActor, true, noSim);
+ static_cast<NpScene*>(s->getPxScene())->removeFromRigidActorList(actor->getRigidActorArrayIndex());
+ }
+
+ scbActor.destroy();
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpRigidBodyTemplate.h b/PhysX_3.4/Source/PhysX/src/NpRigidBodyTemplate.h
new file mode 100644
index 00000000..82255cdc
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpRigidBodyTemplate.h
@@ -0,0 +1,593 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_RIGIDBODY_TEMPLATE
+#define PX_PHYSICS_NP_RIGIDBODY_TEMPLATE
+
+#include "NpRigidActorTemplate.h"
+#include "ScbBody.h"
+#include "NpPhysics.h"
+#include "NpShape.h"
+#include "NpScene.h"
+
+namespace physx
+{
+
+PX_INLINE PxVec3 invertDiagInertia(const PxVec3& m)
+{
+ return PxVec3( m.x == 0.0f ? 0.0f : 1.0f/m.x,
+ m.y == 0.0f ? 0.0f : 1.0f/m.y,
+ m.z == 0.0f ? 0.0f : 1.0f/m.z);
+}
+
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+/*
+given the diagonal of the body space inertia tensor, and the total mass
+this returns the body space AABB width, height and depth of an equivalent box
+*/
+PX_INLINE PxVec3 getDimsFromBodyInertia(const PxVec3& inertiaMoments, PxReal mass)
+{
+ const PxVec3 inertia = inertiaMoments * (6.0f/mass);
+ return PxVec3( PxSqrt(PxAbs(- inertia.x + inertia.y + inertia.z)),
+ PxSqrt(PxAbs(+ inertia.x - inertia.y + inertia.z)),
+ PxSqrt(PxAbs(+ inertia.x + inertia.y - inertia.z)));
+}
+#endif
+
+
+template<class APIClass>
+class NpRigidBodyTemplate : public NpRigidActorTemplate<APIClass>
+{
+private:
+ typedef NpRigidActorTemplate<APIClass> RigidActorTemplateClass;
+public:
+// PX_SERIALIZATION
+ NpRigidBodyTemplate(PxBaseFlags baseFlags) : RigidActorTemplateClass(baseFlags), mBody(PxEmpty) {}
+//~PX_SERIALIZATION
+ virtual ~NpRigidBodyTemplate();
+
+ //---------------------------------------------------------------------------------
+ // PxRigidActor implementation
+ //---------------------------------------------------------------------------------
+ // The rule is: If an API method is used somewhere in here, it has to be redeclared, else GCC whines
+ virtual PxTransform getGlobalPose() const = 0;
+
+ //---------------------------------------------------------------------------------
+ // PxRigidBody implementation
+ //---------------------------------------------------------------------------------
+
+ // Center of mass pose
+ virtual PxTransform getCMassLocalPose() const;
+
+ // Mass
+ virtual void setMass(PxReal mass);
+ virtual PxReal getMass() const;
+ virtual PxReal getInvMass() const;
+
+ virtual void setMassSpaceInertiaTensor(const PxVec3& m);
+ virtual PxVec3 getMassSpaceInertiaTensor() const;
+ virtual PxVec3 getMassSpaceInvInertiaTensor() const;
+
+ // Velocity
+ virtual PxVec3 getLinearVelocity() const;
+ virtual PxVec3 getAngularVelocity() const;
+
+ virtual PxShape* createShape(const PxGeometry& geometry, PxMaterial*const* material, PxU16 materialCount, PxShapeFlags shapeFlags);
+ virtual void attachShape(PxShape& shape);
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ NpRigidBodyTemplate(PxType concreteType, PxBaseFlags baseFlags, const PxActorType::Enum type, const PxTransform& bodyPose);
+
+ PX_FORCE_INLINE const Scb::Body& getScbBodyFast() const { return mBody; } // PT: important: keep returning an address here (else update prefetch in SceneQueryManager::addShapes)
+ PX_FORCE_INLINE Scb::Body& getScbBodyFast() { return mBody; } // PT: important: keep returning an address here (else update prefetch in SceneQueryManager::addShapes)
+
+ PX_FORCE_INLINE Scb::Actor& getScbActorFast() { return mBody; }
+ PX_FORCE_INLINE const Scb::Actor& getScbActorFast() const { return mBody; }
+
+ // Flags
+ virtual void setRigidBodyFlag(PxRigidBodyFlag::Enum, bool value);
+ virtual void setRigidBodyFlags(PxRigidBodyFlags inFlags);
+ PX_FORCE_INLINE PxRigidBodyFlags getRigidBodyFlagsFast() const
+ {
+ return getScbBodyFast().getFlags();
+ }
+ virtual PxRigidBodyFlags getRigidBodyFlags() const
+ {
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getRigidBodyFlagsFast();
+ }
+
+ virtual void setMinCCDAdvanceCoefficient(PxReal advanceCoefficient);
+
+ virtual PxReal getMinCCDAdvanceCoefficient() const;
+
+ virtual void setMaxDepenetrationVelocity(PxReal maxDepenVel);
+
+ virtual PxReal getMaxDepenetrationVelocity() const;
+
+ virtual void setMaxContactImpulse(PxReal maxDepenVel);
+
+ virtual PxReal getMaxContactImpulse() const;
+
+protected:
+ void setCMassLocalPoseInternal(const PxTransform&);
+
+ void addSpatialForce(const PxVec3* force, const PxVec3* torque, PxForceMode::Enum mode);
+ void clearSpatialForce(PxForceMode::Enum mode, bool force, bool torque);
+
+ PX_INLINE void updateBody2Actor(const PxTransform& newBody2Actor);
+
+ PX_FORCE_INLINE void setRigidBodyFlagsInternal(const PxRigidBodyFlags& currentFlags, const PxRigidBodyFlags& newFlags);
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+public:
+ void visualize(Cm::RenderOutput& out, NpScene* scene);
+#endif
+
+ PX_FORCE_INLINE bool isKinematic()
+ {
+ return (APIClass::getConcreteType() == PxConcreteType::eRIGID_DYNAMIC) && (getScbBodyFast().getFlags() & PxRigidBodyFlag::eKINEMATIC);
+ }
+
+protected:
+ Scb::Body mBody;
+};
+
+
+template<class APIClass>
+NpRigidBodyTemplate<APIClass>::NpRigidBodyTemplate(PxType concreteType, PxBaseFlags baseFlags, PxActorType::Enum type, const PxTransform& bodyPose)
+: RigidActorTemplateClass(concreteType, baseFlags)
+, mBody(type, bodyPose)
+{
+}
+
+
+template<class APIClass>
+NpRigidBodyTemplate<APIClass>::~NpRigidBodyTemplate()
+{
+}
+
+namespace
+{
+ PX_FORCE_INLINE static bool isSimGeom(PxGeometryType::Enum t)
+ {
+ return t != PxGeometryType::eTRIANGLEMESH && t != PxGeometryType::ePLANE && t != PxGeometryType::eHEIGHTFIELD;
+ }
+}
+
+template<class APIClass>
+PxShape* NpRigidBodyTemplate<APIClass>::createShape(const PxGeometry& geometry, PxMaterial*const* materials, PxU16 materialCount, PxShapeFlags shapeFlags)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN_NULL(!(shapeFlags & PxShapeFlag::eSIMULATION_SHAPE)
+ || isSimGeom(geometry.getType())
+ || isKinematic(),
+ "createShape: Triangle mesh, heightfield or plane geometry shapes configured as eSIMULATION_SHAPE are not supported for non-kinematic PxRigidDynamic instances.");
+
+ NpShape* shape = static_cast<NpShape*>(NpPhysics::getInstance().createShape(geometry, materials, materialCount, true, shapeFlags));
+
+ if ( shape != NULL )
+ {
+ RigidActorTemplateClass::mShapeManager.attachShape(*shape, *this);
+ shape->releaseInternal();
+ }
+ return shape;
+}
+
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::attachShape(PxShape& shape)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(!(shape.getFlags() & PxShapeFlag::eSIMULATION_SHAPE)
+ || isSimGeom(shape.getGeometryType())
+ || isKinematic(),
+ "attachShape: Triangle mesh, heightfield or plane geometry shapes configured as eSIMULATION_SHAPE are not supported for non-kinematic PxRigidDynamic instances.");
+ RigidActorTemplateClass::attachShape(shape);
+}
+
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::setCMassLocalPoseInternal(const PxTransform& body2Actor)
+{
+ //the point here is to change the mass distribution w/o changing the actors' pose in the world
+
+ PxTransform newBody2World = getGlobalPose() * body2Actor;
+
+ mBody.setBody2World(newBody2World, true);
+ mBody.setBody2Actor(body2Actor);
+
+ RigidActorTemplateClass::updateShaderComs();
+}
+
+
+template<class APIClass>
+PxTransform NpRigidBodyTemplate<APIClass>::getCMassLocalPose() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return getScbBodyFast().getBody2Actor();
+}
+
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::setMass(PxReal mass)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(PxIsFinite(mass), "PxRigidDynamic::setMass: invalid float");
+ PX_CHECK_AND_RETURN(mass>=0, "PxRigidDynamic::setMass: mass must be non-negative!");
+ PX_CHECK_AND_RETURN(this->getType() != PxActorType::eARTICULATION_LINK || mass > 0.0f, "PxRigidDynamic::setMassSpaceInertiaTensor: components must be > 0 for articualtions");
+
+ getScbBodyFast().setInverseMass(mass > 0.0f ? 1.0f/mass : 0.0f);
+}
+
+
+template<class APIClass>
+PxReal NpRigidBodyTemplate<APIClass>::getMass() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ const PxReal invMass = mBody.getInverseMass();
+
+ return invMass > 0.0f ? 1.0f/invMass : 0.0f;
+}
+
+template<class APIClass>
+PxReal NpRigidBodyTemplate<APIClass>::getInvMass() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mBody.getInverseMass();
+}
+
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::setMassSpaceInertiaTensor(const PxVec3& m)
+{
+ PX_CHECK_AND_RETURN(m.isFinite(), "PxRigidDynamic::setMassSpaceInertiaTensor: invalid inertia");
+ PX_CHECK_AND_RETURN(m.x>=0.0f && m.y>=0.0f && m.z>=0.0f, "PxRigidDynamic::setMassSpaceInertiaTensor: components must be non-negative");
+ PX_CHECK_AND_RETURN(this->getType() != PxActorType::eARTICULATION_LINK || (m.x > 0.0f && m.y > 0.0f && m.z > 0.0f), "PxRigidDynamic::setMassSpaceInertiaTensor: components must be > 0 for articualtions");
+
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mBody.setInverseInertia(invertDiagInertia(m));
+}
+
+
+template<class APIClass>
+PxVec3 NpRigidBodyTemplate<APIClass>::getMassSpaceInertiaTensor() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return invertDiagInertia(mBody.getInverseInertia());
+}
+
+template<class APIClass>
+PxVec3 NpRigidBodyTemplate<APIClass>::getMassSpaceInvInertiaTensor() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mBody.getInverseInertia();
+}
+
+
+template<class APIClass>
+PxVec3 NpRigidBodyTemplate<APIClass>::getLinearVelocity() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mBody.getLinearVelocity();
+}
+
+
+template<class APIClass>
+PxVec3 NpRigidBodyTemplate<APIClass>::getAngularVelocity() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mBody.getAngularVelocity();
+}
+
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::addSpatialForce(const PxVec3* force, const PxVec3* torque, PxForceMode::Enum mode)
+{
+ PX_ASSERT(!(mBody.getFlags() & PxRigidBodyFlag::eKINEMATIC));
+
+ switch (mode)
+ {
+ case PxForceMode::eFORCE:
+ {
+ PxVec3 linAcc, angAcc;
+ if (force)
+ {
+ linAcc = (*force) * mBody.getInverseMass();
+ force = &linAcc;
+ }
+ if (torque)
+ {
+ angAcc = mBody.getGlobalInertiaTensorInverse() * (*torque);
+ torque = &angAcc;
+ }
+ mBody.addSpatialAcceleration(force, torque);
+ }
+ break;
+
+ case PxForceMode::eACCELERATION:
+ mBody.addSpatialAcceleration(force, torque);
+ break;
+
+ case PxForceMode::eIMPULSE:
+ {
+ PxVec3 linVelDelta, angVelDelta;
+ if (force)
+ {
+ linVelDelta = ((*force) * mBody.getInverseMass());
+ force = &linVelDelta;
+ }
+ if (torque)
+ {
+ angVelDelta = (mBody.getGlobalInertiaTensorInverse() * (*torque));
+ torque = &angVelDelta;
+ }
+ mBody.addSpatialVelocity(force, torque);
+ }
+ break;
+
+ case PxForceMode::eVELOCITY_CHANGE:
+ mBody.addSpatialVelocity(force, torque);
+ break;
+ }
+}
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::clearSpatialForce(PxForceMode::Enum mode, bool force, bool torque)
+{
+ PX_ASSERT(!(mBody.getFlags() & PxRigidBodyFlag::eKINEMATIC));
+
+ switch (mode)
+ {
+ case PxForceMode::eFORCE:
+ case PxForceMode::eACCELERATION:
+ mBody.clearSpatialAcceleration(force, torque);
+ break;
+ case PxForceMode::eIMPULSE:
+ case PxForceMode::eVELOCITY_CHANGE:
+ mBody.clearSpatialVelocity(force, torque);
+ break;
+ }
+}
+
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::visualize(Cm::RenderOutput& out, NpScene* scene)
+{
+ RigidActorTemplateClass::visualize(out, scene);
+
+ if (mBody.getActorFlags() & PxActorFlag::eVISUALIZATION)
+ {
+ Scb::Scene& scbScene = scene->getScene();
+ const PxReal scale = scbScene.getVisualizationParameter(PxVisualizationParameter::eSCALE);
+
+ //visualize actor frames
+ const PxReal actorAxes = scale * scbScene.getVisualizationParameter(PxVisualizationParameter::eACTOR_AXES);
+ if (actorAxes != 0.0f)
+ out << getGlobalPose() << Cm::DebugBasis(PxVec3(actorAxes));
+
+ const PxReal bodyAxes = scale * scbScene.getVisualizationParameter(PxVisualizationParameter::eBODY_AXES);
+ if (bodyAxes != 0.0f)
+ out << mBody.getBody2World() << Cm::DebugBasis(PxVec3(bodyAxes));
+
+ const PxReal linVelocity = scale * scbScene.getVisualizationParameter(PxVisualizationParameter::eBODY_LIN_VELOCITY);
+ if (linVelocity != 0.0f)
+ {
+ out << 0xffffff << PxMat44(PxIdentity) << Cm::DebugArrow(mBody.getBody2World().p,
+ mBody.getLinearVelocity() * linVelocity, 0.2f * linVelocity);
+ }
+
+ const PxReal angVelocity = scale * scbScene.getVisualizationParameter(PxVisualizationParameter::eBODY_ANG_VELOCITY);
+ if (angVelocity != 0.0f)
+ {
+ out << 0x000000 << PxMat44(PxIdentity) << Cm::DebugArrow(mBody.getBody2World().p,
+ mBody.getAngularVelocity() * angVelocity, 0.2f * angVelocity);
+ }
+ }
+}
+#endif
+
+
+PX_FORCE_INLINE void updateDynamicSceneQueryShapes(NpShapeManager& shapeManager, Sq::SceneQueryManager& sqManager)
+{
+ shapeManager.markAllSceneQueryForUpdate(sqManager);
+ sqManager.get(Sq::PruningIndex::eDYNAMIC).invalidateTimestamp();
+}
+
+
+template<class APIClass>
+PX_FORCE_INLINE void NpRigidBodyTemplate<APIClass>::setRigidBodyFlagsInternal(const PxRigidBodyFlags& currentFlags, const PxRigidBodyFlags& newFlags)
+{
+ PxRigidBodyFlags filteredNewFlags = newFlags;
+ //Test to ensure we are not enabling both CCD and kinematic state on a body. This is unsupported
+ if((filteredNewFlags & PxRigidBodyFlag::eENABLE_CCD) && (filteredNewFlags & PxRigidBodyFlag::eKINEMATIC))
+ {
+ physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "RigidBody::setRigidBodyFlag: kinematic bodies with CCD enabled are not supported! CCD will be ignored.");
+ filteredNewFlags &= PxRigidBodyFlags(~PxRigidBodyFlag::eENABLE_CCD);
+ }
+
+ if ((filteredNewFlags & PxRigidBodyFlag::eENABLE_CCD) && (filteredNewFlags & PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD))
+ {
+ physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "RigidBody::setRigidBodyFlag: eENABLE_CCD can't be raised as the same time as eENABLE_SPECULATIVE_CCD! eENABLE_SPECULATIVE_CCD will be ignored.");
+ filteredNewFlags &= PxRigidBodyFlags(~PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD);
+ }
+
+ Scb::Body& body = getScbBodyFast();
+ NpScene* scene = NpActor::getAPIScene(*this);
+
+ const bool isKinematic = currentFlags & PxRigidBodyFlag::eKINEMATIC;
+ const bool willBeKinematic = filteredNewFlags & PxRigidBodyFlag::eKINEMATIC;
+ const bool kinematicSwitchingToDynamic = isKinematic && (!willBeKinematic);
+ const bool dynamicSwitchingToKinematic = (!isKinematic) && willBeKinematic;
+
+ if(kinematicSwitchingToDynamic)
+ {
+ NpShapeManager& shapeManager = this->getShapeManager();
+ PxU32 nbShapes = shapeManager.getNbShapes();
+ NpShape*const* shapes = shapeManager.getShapes();
+ bool hasTriangleMesh = false;
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ if((shapes[i]->getFlags() & PxShapeFlag::eSIMULATION_SHAPE) && (shapes[i]->getGeometryTypeFast()==PxGeometryType::eTRIANGLEMESH || shapes[i]->getGeometryTypeFast()==PxGeometryType::ePLANE || shapes[i]->getGeometryTypeFast()==PxGeometryType::eHEIGHTFIELD))
+ {
+ hasTriangleMesh = true;
+ break;
+ }
+ }
+ if(hasTriangleMesh)
+ {
+ physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "RigidBody::setRigidBodyFlag: dynamic meshes/planes/heightfields are not supported!");
+ return;
+ }
+
+ PxTransform bodyTarget;
+ if ((currentFlags & PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES) && body.getKinematicTarget(bodyTarget) && scene)
+ {
+ updateDynamicSceneQueryShapes(shapeManager, scene->getSceneQueryManagerFast());
+ }
+
+ body.clearSimStateDataForPendingInsert();
+ }
+ else if (dynamicSwitchingToKinematic)
+ {
+ if (this->getType() != PxActorType::eARTICULATION_LINK)
+ {
+ body.transitionSimStateDataForPendingInsert();
+ }
+ else
+ {
+ //We're an articulation, raise an issue
+ physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "RigidBody::setRigidBodyFlag: kinematic articulation links are not supported!");
+ return;
+ }
+ }
+
+ const bool kinematicSwitchingUseTargetForSceneQuery = isKinematic && willBeKinematic &&
+ ((currentFlags & PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES) != (filteredNewFlags & PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES));
+ if (kinematicSwitchingUseTargetForSceneQuery)
+ {
+ PxTransform bodyTarget;
+ if (body.getKinematicTarget(bodyTarget) && scene)
+ {
+ updateDynamicSceneQueryShapes(this->getShapeManager(), scene->getSceneQueryManagerFast());
+ }
+ }
+
+ body.setFlags(filteredNewFlags);
+}
+
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::setRigidBodyFlag(PxRigidBodyFlag::Enum flag, bool value)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ Scb::Body& body = getScbBodyFast();
+ const PxRigidBodyFlags currentFlags = body.getFlags();
+ const PxRigidBodyFlags newFlags = value ? currentFlags | flag : currentFlags & (~PxRigidBodyFlags(flag));
+
+ setRigidBodyFlagsInternal(currentFlags, newFlags);
+}
+
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::setRigidBodyFlags(PxRigidBodyFlags inFlags)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ Scb::Body& body = getScbBodyFast();
+ const PxRigidBodyFlags currentFlags = body.getFlags();
+
+ setRigidBodyFlagsInternal(currentFlags, inFlags);
+}
+
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::setMinCCDAdvanceCoefficient(PxReal minCCDAdvanceCoefficient)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ mBody.setMinCCDAdvanceCoefficient(minCCDAdvanceCoefficient);
+}
+
+template<class APIClass>
+PxReal NpRigidBodyTemplate<APIClass>::getMinCCDAdvanceCoefficient() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mBody.getMinCCDAdvanceCoefficient();
+}
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::setMaxDepenetrationVelocity(PxReal maxDepenVel)
+{
+ PX_CHECK_AND_RETURN(maxDepenVel > 0.0f, "PxRigidDynamic::setMaxDepenetrationVelocity: maxDepenVel must be greater than zero.");
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ mBody.setMaxPenetrationBias(-maxDepenVel);
+}
+
+template<class APIClass>
+PxReal NpRigidBodyTemplate<APIClass>::getMaxDepenetrationVelocity() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return -mBody.getMaxPenetrationBias();
+}
+
+template<class APIClass>
+void NpRigidBodyTemplate<APIClass>::setMaxContactImpulse(const PxReal maxImpulse)
+{
+ PX_CHECK_AND_RETURN(maxImpulse >= 0.f, "NpRigidBody::setMaxImpulse: impulse limit must be greater than or equal to zero.");
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ mBody.setMaxContactImpulse(maxImpulse);
+}
+
+template<class APIClass>
+PxReal NpRigidBodyTemplate<APIClass>::getMaxContactImpulse() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mBody.getMaxContactImpulse();
+}
+
+
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpRigidDynamic.cpp b/PhysX_3.4/Source/PhysX/src/NpRigidDynamic.cpp
new file mode 100644
index 00000000..52ccccab
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpRigidDynamic.cpp
@@ -0,0 +1,533 @@
+// 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 "NpRigidDynamic.h"
+#include "NpRigidActorTemplateInternal.h"
+
+using namespace physx;
+
+NpRigidDynamic::NpRigidDynamic(const PxTransform& bodyPose)
+: NpRigidDynamicT(PxConcreteType::eRIGID_DYNAMIC, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE, PxActorType::eRIGID_DYNAMIC, bodyPose)
+{}
+
+NpRigidDynamic::~NpRigidDynamic()
+{
+}
+
+// PX_SERIALIZATION
+void NpRigidDynamic::requires(PxProcessPxBaseCallback& c)
+{
+ NpRigidDynamicT::requires(c);
+}
+
+NpRigidDynamic* NpRigidDynamic::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpRigidDynamic* obj = new (address) NpRigidDynamic(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpRigidDynamic);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+void NpRigidDynamic::release()
+{
+ releaseActorT(this, mBody);
+}
+
+
+void NpRigidDynamic::setGlobalPose(const PxTransform& pose, bool autowake)
+{
+ NpScene* scene = NpActor::getAPIScene(*this);
+
+#if PX_CHECKED
+ if(scene)
+ scene->checkPositionSanity(*this, pose, "PxRigidDynamic::setGlobalPose");
+#endif
+
+ PX_CHECK_AND_RETURN(pose.isSane(), "PxRigidDynamic::setGlobalPose: pose is not valid.");
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ if(scene)
+ updateDynamicSceneQueryShapes(mShapeManager, scene->getSceneQueryManagerFast());
+
+ const PxTransform newPose = pose.getNormalized(); //AM: added to fix 1461 where users read and write orientations for no reason.
+
+ Scb::Body& b = getScbBodyFast();
+ const PxTransform body2World = newPose * b.getBody2Actor();
+ b.setBody2World(body2World, false);
+
+ // invalidate the pruning structure if the actor bounds changed
+ if(mShapeManager.getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxRigidDynamic::setGlobalPose: Actor is part of a pruning structure, pruning structure is now invalid!");
+ mShapeManager.getPruningStructure()->invalidate(this);
+ }
+
+ if(scene && autowake && !(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION))
+ wakeUpInternal();
+}
+
+
+PX_FORCE_INLINE void NpRigidDynamic::setKinematicTargetInternal(const PxTransform& targetPose)
+{
+ Scb::Body& b = getScbBodyFast();
+
+ // The target is actor related. Transform to body related target
+ const PxTransform bodyTarget = targetPose * b.getBody2Actor();
+
+ b.setKinematicTarget(bodyTarget);
+
+ NpScene* scene = NpActor::getAPIScene(*this);
+ if ((b.getFlags() & PxRigidBodyFlag::eUSE_KINEMATIC_TARGET_FOR_SCENE_QUERIES) && scene)
+ {
+ updateDynamicSceneQueryShapes(mShapeManager, scene->getSceneQueryManagerFast());
+ }
+}
+
+
+void NpRigidDynamic::setKinematicTarget(const PxTransform& destination)
+{
+ PX_CHECK_AND_RETURN(destination.isSane(), "PxRigidDynamic::setKinematicTarget: destination is not valid.");
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+#if PX_CHECKED
+ NpScene* scene = NpActor::getAPIScene(*this);
+ if(scene)
+ scene->checkPositionSanity(*this, destination, "PxRigidDynamic::setKinematicTarget");
+
+ Scb::Body& b = getScbBodyFast();
+ PX_CHECK_AND_RETURN((b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::setKinematicTarget: Body must be kinematic!");
+ PX_CHECK_AND_RETURN(scene, "PxRigidDynamic::setKinematicTarget: Body must be in a scene!");
+ PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::setKinematicTarget: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!");
+#endif
+
+ setKinematicTargetInternal(destination.getNormalized());
+}
+
+
+bool NpRigidDynamic::getKinematicTarget(PxTransform& target)
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ Scb::Body& b = getScbBodyFast();
+ if(b.getFlags() & PxRigidBodyFlag::eKINEMATIC)
+ {
+ PxTransform bodyTarget;
+ if(b.getKinematicTarget(bodyTarget))
+ {
+ // The internal target is body related. Transform to actor related target
+ target = bodyTarget * b.getBody2Actor().getInverse();
+ return true;
+ }
+ }
+ return false;
+}
+
+
+void NpRigidDynamic::setCMassLocalPose(const PxTransform& pose)
+{
+ PX_CHECK_AND_RETURN(pose.isSane(), "PxRigidDynamic::setCMassLocalPose pose is not valid.");
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ const PxTransform p = pose.getNormalized();
+
+ const PxTransform oldBody2Actor = getScbBodyFast().getBody2Actor();
+
+ NpRigidDynamicT::setCMassLocalPoseInternal(p);
+
+ Scb::Body& b = getScbBodyFast();
+ if(b.getFlags() & PxRigidBodyFlag::eKINEMATIC)
+ {
+ PxTransform bodyTarget;
+ if(b.getKinematicTarget(bodyTarget))
+ {
+ PxTransform actorTarget = bodyTarget * oldBody2Actor.getInverse(); // get old target pose for the actor from the body target
+ setKinematicTargetInternal(actorTarget);
+ }
+ }
+}
+
+
+void NpRigidDynamic::setLinearDamping(PxReal linearDamping)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(PxIsFinite(linearDamping), "PxRigidDynamic::setLinearDamping: invalid float");
+ PX_CHECK_AND_RETURN(linearDamping >=0, "PxRigidDynamic::setLinearDamping: The linear damping must be nonnegative!");
+
+ getScbBodyFast().setLinearDamping(linearDamping);
+}
+
+
+PxReal NpRigidDynamic::getLinearDamping() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return getScbBodyFast().getLinearDamping();
+}
+
+
+void NpRigidDynamic::setAngularDamping(PxReal angularDamping)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(PxIsFinite(angularDamping), "PxRigidDynamic::setAngularDamping: invalid float");
+ PX_CHECK_AND_RETURN(angularDamping>=0, "PxRigidDynamic::setAngularDamping: The angular damping must be nonnegative!")
+
+ getScbBodyFast().setAngularDamping(angularDamping);
+}
+
+
+PxReal NpRigidDynamic::getAngularDamping() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return getScbBodyFast().getAngularDamping();
+}
+
+
+void NpRigidDynamic::setLinearVelocity(const PxVec3& velocity, bool autowake)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(velocity.isFinite(), "PxRigidDynamic::setLinearVelocity: velocity is not valid.");
+ PX_CHECK_AND_RETURN(!(getScbBodyFast().getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::setLinearVelocity: Body must be non-kinematic!");
+ PX_CHECK_AND_RETURN(!(getScbBodyFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::setLinearVelocity: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!");
+
+ Scb::Body& b = getScbBodyFast();
+ b.setLinearVelocity(velocity);
+
+ NpScene* scene = NpActor::getAPIScene(*this);
+ if(scene)
+ wakeUpInternalNoKinematicTest(b, (!velocity.isZero()), autowake);
+}
+
+
+void NpRigidDynamic::setAngularVelocity(const PxVec3& velocity, bool autowake)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(velocity.isFinite(), "PxRigidDynamic::setAngularVelocity: velocity is not valid.");
+ PX_CHECK_AND_RETURN(!(getScbBodyFast().getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::setAngularVelocity: Body must be non-kinematic!");
+ PX_CHECK_AND_RETURN(!(getScbBodyFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::setAngularVelocity: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!");
+
+ Scb::Body& b = getScbBodyFast();
+ b.setAngularVelocity(velocity);
+
+ NpScene* scene = NpActor::getAPIScene(*this);
+ if(scene)
+ wakeUpInternalNoKinematicTest(b, (!velocity.isZero()), autowake);
+}
+
+
+void NpRigidDynamic::setMaxAngularVelocity(PxReal maxAngularVelocity)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(PxIsFinite(maxAngularVelocity), "PxRigidDynamic::setMaxAngularVelocity: invalid float");
+ PX_CHECK_AND_RETURN(maxAngularVelocity>=0.0f, "PxRigidDynamic::setMaxAngularVelocity: threshold must be non-negative!");
+
+ getScbBodyFast().setMaxAngVelSq(maxAngularVelocity * maxAngularVelocity);
+}
+
+
+PxReal NpRigidDynamic::getMaxAngularVelocity() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return PxSqrt(getScbBodyFast().getMaxAngVelSq());
+}
+
+
+void NpRigidDynamic::addForce(const PxVec3& force, PxForceMode::Enum mode, bool autowake)
+{
+ Scb::Body& b = getScbBodyFast();
+
+ PX_CHECK_AND_RETURN(force.isFinite(), "PxRigidDynamic::addForce: force is not valid.");
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::addForce: Body must be in a scene!");
+ PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::addForce: Body must be non-kinematic!");
+ PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::addForce: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!");
+
+ addSpatialForce(&force, NULL, mode);
+
+ wakeUpInternalNoKinematicTest(b, (!force.isZero()), autowake);
+}
+
+
+void NpRigidDynamic::addTorque(const PxVec3& torque, PxForceMode::Enum mode, bool autowake)
+{
+ Scb::Body& b = getScbBodyFast();
+
+ PX_CHECK_AND_RETURN(torque.isFinite(), "PxRigidDynamic::addTorque: torque is not valid.");
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::addTorque: Body must be in a scene!");
+ PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::addTorque: Body must be non-kinematic!");
+ PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::addTorque: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!");
+
+ addSpatialForce(NULL, &torque, mode);
+
+ wakeUpInternalNoKinematicTest(b, (!torque.isZero()), autowake);
+}
+
+void NpRigidDynamic::clearForce(PxForceMode::Enum mode)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::clearForce: Body must be in a scene!");
+ PX_CHECK_AND_RETURN(!(getScbBodyFast().getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::clearForce: Body must be non-kinematic!");
+ PX_CHECK_AND_RETURN(!(getScbBodyFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::clearForce: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!");
+
+ clearSpatialForce(mode, true, false);
+}
+
+
+void NpRigidDynamic::clearTorque(PxForceMode::Enum mode)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::clearTorque: Body must be in a scene!");
+ PX_CHECK_AND_RETURN(!(getScbBodyFast().getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::clearTorque: Body must be non-kinematic!");
+ PX_CHECK_AND_RETURN(!(getScbBodyFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::clearTorque: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!");
+
+ clearSpatialForce(mode, false, true);
+}
+
+
+bool NpRigidDynamic::isSleeping() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN_VAL(NpActor::getAPIScene(*this), "PxRigidDynamic::isSleeping: Body must be in a scene.", true);
+
+ return getScbBodyFast().isSleeping();
+}
+
+
+void NpRigidDynamic::setSleepThreshold(PxReal threshold)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(PxIsFinite(threshold), "PxRigidDynamic::setSleepThreshold: invalid float.");
+ PX_CHECK_AND_RETURN(threshold>=0.0f, "PxRigidDynamic::setSleepThreshold: threshold must be non-negative!");
+
+ getScbBodyFast().setSleepThreshold(threshold);
+}
+
+
+PxReal NpRigidDynamic::getSleepThreshold() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return getScbBodyFast().getSleepThreshold();
+}
+
+void NpRigidDynamic::setStabilizationThreshold(PxReal threshold)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(PxIsFinite(threshold), "PxRigidDynamic::setSleepThreshold: invalid float.");
+ PX_CHECK_AND_RETURN(threshold>=0.0f, "PxRigidDynamic::setSleepThreshold: threshold must be non-negative!");
+
+ getScbBodyFast().setFreezeThreshold(threshold);
+}
+
+
+PxReal NpRigidDynamic::getStabilizationThreshold() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return getScbBodyFast().getFreezeThreshold();
+}
+
+
+void NpRigidDynamic::setWakeCounter(PxReal wakeCounterValue)
+{
+ Scb::Body& b = getScbBodyFast();
+
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(PxIsFinite(wakeCounterValue), "PxRigidDynamic::setWakeCounter: invalid float.");
+ PX_CHECK_AND_RETURN(wakeCounterValue>=0.0f, "PxRigidDynamic::setWakeCounter: wakeCounterValue must be non-negative!");
+ PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::setWakeCounter: Body must be non-kinematic!");
+ PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::setWakeCounter: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!");
+
+ b.setWakeCounter(wakeCounterValue);
+}
+
+
+PxReal NpRigidDynamic::getWakeCounter() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return getScbBodyFast().getWakeCounter();
+}
+
+
+void NpRigidDynamic::wakeUp()
+{
+ Scb::Body& b = getScbBodyFast();
+
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::wakeUp: Body must be in a scene.");
+ PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::wakeUp: Body must be non-kinematic!");
+ PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::wakeUp: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!");
+
+ b.wakeUp();
+}
+
+
+void NpRigidDynamic::putToSleep()
+{
+ Scb::Body& b = getScbBodyFast();
+
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(NpActor::getAPIScene(*this), "PxRigidDynamic::putToSleep: Body must be in a scene.");
+ PX_CHECK_AND_RETURN(!(b.getFlags() & PxRigidBodyFlag::eKINEMATIC), "PxRigidDynamic::putToSleep: Body must be non-kinematic!");
+ PX_CHECK_AND_RETURN(!(b.getActorFlags() & PxActorFlag::eDISABLE_SIMULATION), "PxRigidDynamic::putToSleep: Not allowed if PxActorFlag::eDISABLE_SIMULATION is set!");
+
+ b.putToSleep();
+}
+
+
+void NpRigidDynamic::setSolverIterationCounts(PxU32 positionIters, PxU32 velocityIters)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(positionIters > 0, "PxRigidDynamic::setSolverIterationCount: positionIters must be more than zero!");
+ PX_CHECK_AND_RETURN(positionIters <= 255, "PxRigidDynamic::setSolverIterationCount: positionIters must be no greater than 255!");
+ PX_CHECK_AND_RETURN(velocityIters > 0, "PxRigidDynamic::setSolverIterationCount: velocityIters must be more than zero!");
+ PX_CHECK_AND_RETURN(velocityIters <= 255, "PxRigidDynamic::setSolverIterationCount: velocityIters must be no greater than 255!");
+
+ getScbBodyFast().setSolverIterationCounts((velocityIters & 0xff) << 8 | (positionIters & 0xff));
+}
+
+
+void NpRigidDynamic::getSolverIterationCounts(PxU32 & positionIters, PxU32 & velocityIters) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ PxU16 x = getScbBodyFast().getSolverIterationCounts();
+ velocityIters = PxU32(x >> 8);
+ positionIters = PxU32(x & 0xff);
+}
+
+
+void NpRigidDynamic::setContactReportThreshold(PxReal threshold)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(PxIsFinite(threshold), "PxRigidDynamic::setContactReportThreshold: invalid float.");
+ PX_CHECK_AND_RETURN(threshold >= 0.0f, "PxRigidDynamic::setContactReportThreshold: Force threshold must be greater than zero!");
+
+ getScbBodyFast().setContactReportThreshold(threshold<0 ? 0 : threshold);
+}
+
+
+PxReal NpRigidDynamic::getContactReportThreshold() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return getScbBodyFast().getContactReportThreshold();
+}
+
+
+PxU32 physx::NpRigidDynamicGetShapes(Scb::Body& body, void* const*& shapes)
+{
+ NpRigidDynamic* a = static_cast<NpRigidDynamic*>(body.getScBody().getPxActor());
+ NpShapeManager& sm = a->getShapeManager();
+ shapes = reinterpret_cast<void *const *>(sm.getShapes());
+ return sm.getNbShapes();
+}
+
+
+void NpRigidDynamic::switchToNoSim()
+{
+ getScbBodyFast().switchBodyToNoSim();
+}
+
+
+void NpRigidDynamic::switchFromNoSim()
+{
+ getScbBodyFast().switchFromNoSim(true);
+}
+
+
+void NpRigidDynamic::wakeUpInternalNoKinematicTest(Scb::Body& body, bool forceWakeUp, bool autowake)
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+ PX_ASSERT(scene);
+ PxReal wakeCounterResetValue = scene->getWakeCounterResetValueInteral();
+
+ PxReal wakeCounter = body.getWakeCounter();
+
+ bool needsWakingUp = body.isSleeping() && (autowake || forceWakeUp);
+ if (autowake && (wakeCounter < wakeCounterResetValue))
+ {
+ wakeCounter = wakeCounterResetValue;
+ needsWakingUp = true;
+ }
+
+ if (needsWakingUp)
+ body.wakeUpInternal(wakeCounter);
+}
+
+PxRigidDynamicLockFlags NpRigidDynamic::getRigidDynamicLockFlags() const
+{
+ return mBody.getLockFlags();
+}
+void NpRigidDynamic::setRigidDynamicLockFlags(PxRigidDynamicLockFlags flags)
+{
+ mBody.setLockFlags(flags);
+}
+void NpRigidDynamic::setRigidDynamicLockFlag(PxRigidDynamicLockFlag::Enum flag, bool value)
+{
+ PxRigidDynamicLockFlags flags = mBody.getLockFlags();
+ if (value)
+ flags = flags | flag;
+ else
+ flags = flags & (~flag);
+
+ mBody.setLockFlags(flags);
+}
+
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+void NpRigidDynamic::visualize(Cm::RenderOutput& out, NpScene* npScene)
+{
+ NpRigidDynamicT::visualize(out, npScene);
+
+ if (getScbBodyFast().getActorFlags() & PxActorFlag::eVISUALIZATION)
+ {
+ PX_ASSERT(npScene);
+ const PxReal scale = npScene->getVisualizationParameter(PxVisualizationParameter::eSCALE);
+
+ const PxReal massAxes = scale * npScene->getVisualizationParameter(PxVisualizationParameter::eBODY_MASS_AXES);
+ if (massAxes != 0.0f)
+ {
+ PxReal sleepTime = getScbBodyFast().getWakeCounter() / npScene->getWakeCounterResetValueInteral();
+ PxU32 color = PxU32(0xff * (sleepTime>1.0f ? 1.0f : sleepTime));
+ color = getScbBodyFast().isSleeping() ? 0xff0000 : (color<<16 | color<<8 | color);
+ PxVec3 dims = invertDiagInertia(getScbBodyFast().getInverseInertia());
+ dims = getDimsFromBodyInertia(dims, 1.0f / getScbBodyFast().getInverseMass());
+
+ out << color << getScbBodyFast().getBody2World() << Cm::DebugBox(dims * 0.5f);
+ }
+ }
+}
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpRigidDynamic.h b/PhysX_3.4/Source/PhysX/src/NpRigidDynamic.h
new file mode 100644
index 00000000..1458f0fe
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpRigidDynamic.h
@@ -0,0 +1,171 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_RIGIDDYNAMIC
+#define PX_PHYSICS_NP_RIGIDDYNAMIC
+
+#include "NpRigidBodyTemplate.h"
+#include "PxRigidDynamic.h"
+#include "ScbBody.h"
+#include "PxMetaData.h"
+
+namespace physx
+{
+
+class NpRigidDynamic;
+typedef NpRigidBodyTemplate<PxRigidDynamic> NpRigidDynamicT;
+
+class NpRigidDynamic : public NpRigidDynamicT
+{
+//= 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
+ NpRigidDynamic(PxBaseFlags baseFlags) : NpRigidDynamicT(baseFlags) {}
+
+ virtual void requires(PxProcessPxBaseCallback& c);
+
+ static NpRigidDynamic* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ virtual ~NpRigidDynamic();
+
+ //---------------------------------------------------------------------------------
+ // PxActor implementation
+ //---------------------------------------------------------------------------------
+
+ virtual void release();
+
+ //---------------------------------------------------------------------------------
+ // PxRigidDynamic implementation
+ //---------------------------------------------------------------------------------
+
+ virtual PxActorType::Enum getType() const { return PxActorType::eRIGID_DYNAMIC; }
+
+ // Pose
+ virtual void setGlobalPose(const PxTransform& pose, bool autowake);
+ PX_FORCE_INLINE PxTransform getGlobalPoseFast() const
+ {
+ const Scb::Body& body=getScbBodyFast();
+ return body.getBody2World() * body.getBody2Actor().getInverse();
+ }
+ virtual PxTransform getGlobalPose() const
+ {
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getGlobalPoseFast();
+ }
+
+ virtual void setKinematicTarget(const PxTransform& destination);
+ virtual bool getKinematicTarget(PxTransform& target);
+
+ // Center of mass pose
+ virtual void setCMassLocalPose(const PxTransform&);
+
+ // Damping
+ virtual void setLinearDamping(PxReal);
+ virtual PxReal getLinearDamping() const;
+ virtual void setAngularDamping(PxReal);
+ virtual PxReal getAngularDamping() const;
+
+ // Velocity
+ virtual void setLinearVelocity(const PxVec3&, bool autowake);
+ virtual void setAngularVelocity(const PxVec3&, bool autowake);
+ virtual void setMaxAngularVelocity(PxReal);
+ virtual PxReal getMaxAngularVelocity() const;
+
+ // Force/Torque modifiers
+ virtual void addForce(const PxVec3&, PxForceMode::Enum mode, bool autowake);
+ virtual void clearForce(PxForceMode::Enum mode);
+ virtual void addTorque(const PxVec3&, PxForceMode::Enum mode, bool autowake);
+ virtual void clearTorque(PxForceMode::Enum mode);
+
+ // Sleeping
+ virtual bool isSleeping() const;
+ virtual PxReal getSleepThreshold() const;
+ virtual void setSleepThreshold(PxReal threshold);
+ virtual PxReal getStabilizationThreshold() const;
+ virtual void setStabilizationThreshold(PxReal threshold);
+ virtual void setWakeCounter(PxReal wakeCounterValue);
+ virtual PxReal getWakeCounter() const;
+ virtual void wakeUp();
+ virtual void putToSleep();
+
+ virtual void setSolverIterationCounts(PxU32 positionIters, PxU32 velocityIters);
+ virtual void getSolverIterationCounts(PxU32 & positionIters, PxU32 & velocityIters) const;
+
+ virtual void setContactReportThreshold(PxReal threshold);
+ virtual PxReal getContactReportThreshold() const;
+
+ virtual PxRigidDynamicLockFlags getRigidDynamicLockFlags() const;
+ virtual void setRigidDynamicLockFlags(PxRigidDynamicLockFlags flags);
+ virtual void setRigidDynamicLockFlag(PxRigidDynamicLockFlag::Enum flag, bool value);
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ NpRigidDynamic(const PxTransform& bodyPose);
+
+ virtual void switchToNoSim();
+ virtual void switchFromNoSim();
+
+ PX_FORCE_INLINE void wakeUpInternal();
+ void wakeUpInternalNoKinematicTest(Scb::Body& body, bool forceWakeUp, bool autowake);
+
+private:
+ PX_FORCE_INLINE void setKinematicTargetInternal(const PxTransform& destination);
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+public:
+ void visualize(Cm::RenderOutput& out, NpScene* scene);
+#endif
+};
+
+
+
+
+PX_FORCE_INLINE void NpRigidDynamic::wakeUpInternal()
+{
+ PX_ASSERT(NpActor::getOwnerScene(*this));
+
+ Scb::Body& body = getScbBodyFast();
+ const PxRigidBodyFlags currentFlags = body.getFlags();
+
+ if (!(currentFlags & PxRigidBodyFlag::eKINEMATIC)) // kinematics are only awake when a target is set, else they are asleep
+ wakeUpInternalNoKinematicTest(body, false, true);
+}
+
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpRigidStatic.cpp b/PhysX_3.4/Source/PhysX/src/NpRigidStatic.cpp
new file mode 100644
index 00000000..0f3f8a15
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpRigidStatic.cpp
@@ -0,0 +1,180 @@
+// 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 "NpRigidStatic.h"
+#include "NpPhysics.h"
+#include "ScbNpDeps.h"
+#include "NpScene.h"
+#include "NpRigidActorTemplateInternal.h"
+
+using namespace physx;
+
+NpRigidStatic::NpRigidStatic(const PxTransform& pose)
+: NpRigidStaticT(PxConcreteType::eRIGID_STATIC, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+, mRigidStatic(pose)
+{
+}
+
+NpRigidStatic::~NpRigidStatic()
+{
+}
+
+// PX_SERIALIZATION
+void NpRigidStatic::requires(PxProcessPxBaseCallback& c)
+{
+ NpRigidStaticT::requires(c);
+}
+
+NpRigidStatic* NpRigidStatic::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpRigidStatic* obj = new (address) NpRigidStatic(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpRigidStatic);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+void NpRigidStatic::release()
+{
+ releaseActorT(this, mRigidStatic);
+}
+
+void NpRigidStatic::setGlobalPose(const PxTransform& pose, bool /*wake*/)
+{
+ PX_CHECK_AND_RETURN(pose.isSane(), "PxRigidStatic::setGlobalPose: pose is not valid.");
+
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ NpScene* npScene = NpActor::getAPIScene(*this);
+#if PX_CHECKED
+ if(npScene)
+ npScene->checkPositionSanity(*this, pose, "PxRigidStatic::setGlobalPose");
+#endif
+
+ mRigidStatic.setActor2World(pose.getNormalized());
+
+ if(npScene)
+ {
+ mShapeManager.markAllSceneQueryForUpdate(npScene->getSceneQueryManagerFast());
+ npScene->getSceneQueryManagerFast().get(Sq::PruningIndex::eSTATIC).invalidateTimestamp();
+ }
+
+#if PX_SUPPORT_PVD
+ // have to do this here since this call gets not forwarded to Scb::RigidStatic
+ Scb::Scene* scbScene = NpActor::getScbFromPxActor(*this).getScbSceneForAPI();
+ if(scbScene)
+ scbScene->getScenePvdClient().updatePvdProperties(&mRigidStatic);
+#endif
+
+ // invalidate the pruning structure if the actor bounds changed
+ if (mShapeManager.getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxRigidStatic::setGlobalPose: Actor is part of a pruning structure, pruning structure is now invalid!");
+ mShapeManager.getPruningStructure()->invalidate(this);
+ }
+
+ updateShaderComs();
+}
+
+PxTransform NpRigidStatic::getGlobalPose() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mRigidStatic.getActor2World();
+}
+
+PxShape* NpRigidStatic::createShape(const PxGeometry& geometry, PxMaterial*const* materials, PxU16 materialCount, PxShapeFlags shapeFlags)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN_NULL(materials, "createShape: material pointer is NULL");
+ PX_CHECK_AND_RETURN_NULL(materialCount>0, "createShape: material count is zero");
+
+ NpShape* shape = static_cast<NpShape*>(NpPhysics::getInstance().createShape(geometry, materials, materialCount, true, shapeFlags));
+
+ if ( shape != NULL )
+ {
+ mShapeManager.attachShape(*shape, *this);
+ shape->releaseInternal();
+ }
+ return shape;
+}
+
+PxU32 physx::NpRigidStaticGetShapes(Scb::RigidStatic& rigid, void* const *&shapes)
+{
+ NpRigidStatic* a = static_cast<NpRigidStatic*>(rigid.getScRigidCore().getPxActor());
+ NpShapeManager& sm = a->getShapeManager();
+ shapes = reinterpret_cast<void *const *>(sm.getShapes());
+ return sm.getNbShapes();
+}
+
+void NpRigidStatic::switchToNoSim()
+{
+ getScbRigidStaticFast().switchToNoSim(false);
+}
+
+void NpRigidStatic::switchFromNoSim()
+{
+ getScbRigidStaticFast().switchFromNoSim(false);
+}
+
+#if PX_CHECKED
+bool NpRigidStatic::checkConstraintValidity() const
+{
+ // Perhaps NpConnectorConstIterator would be worth it...
+ NpConnectorIterator iter = (const_cast<NpRigidStatic*>(this))->getConnectorIterator(NpConnectorType::eConstraint);
+ while (PxBase* ser = iter.getNext())
+ {
+ NpConstraint* c = static_cast<NpConstraint*>(ser);
+ if(!c->NpConstraint::isValid())
+ return false;
+ }
+ return true;
+}
+#endif
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+void NpRigidStatic::visualize(Cm::RenderOutput& out, NpScene* scene)
+{
+ NpRigidStaticT::visualize(out, scene);
+
+ if (getScbRigidStaticFast().getActorFlags() & PxActorFlag::eVISUALIZATION)
+ {
+ Scb::Scene& scbScene = scene->getScene();
+ PxReal scale = scbScene.getVisualizationParameter(PxVisualizationParameter::eSCALE);
+
+ //visualize actor frames
+ PxReal actorAxes = scale * scbScene.getVisualizationParameter(PxVisualizationParameter::eACTOR_AXES);
+ if (actorAxes != 0)
+ out << getGlobalPose() << Cm::DebugBasis(PxVec3(actorAxes));
+ }
+}
+#endif
+
diff --git a/PhysX_3.4/Source/PhysX/src/NpRigidStatic.h b/PhysX_3.4/Source/PhysX/src/NpRigidStatic.h
new file mode 100644
index 00000000..fad1296c
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpRigidStatic.h
@@ -0,0 +1,118 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_RIGIDSTATIC
+#define PX_PHYSICS_NP_RIGIDSTATIC
+
+#include "NpRigidActorTemplate.h"
+#include "PxRigidStatic.h"
+#include "ScbRigidStatic.h"
+
+#include "PxMetaData.h"
+
+namespace physx
+{
+
+namespace Scb
+{
+ class RigidObject;
+}
+
+class NpRigidStatic;
+typedef NpRigidActorTemplate<PxRigidStatic> NpRigidStaticT;
+
+class NpRigidStatic : public NpRigidStaticT
+{
+//= 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
+ NpRigidStatic(PxBaseFlags baseFlags) : NpRigidStaticT(baseFlags), mRigidStatic(PxEmpty) {}
+ virtual void requires(PxProcessPxBaseCallback& c);
+ static NpRigidStatic* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+
+ virtual ~NpRigidStatic();
+
+ //---------------------------------------------------------------------------------
+ // PxActor implementation
+ //---------------------------------------------------------------------------------
+ virtual void release();
+
+ virtual PxActorType::Enum getType() const { return PxActorType::eRIGID_STATIC; }
+
+ //---------------------------------------------------------------------------------
+ // PxRigidActor implementation
+ //---------------------------------------------------------------------------------
+
+ virtual PxShape* createShape(const PxGeometry& geometry, PxMaterial*const* material,
+ PxU16 materialCount, PxShapeFlags shapeFlags);
+
+ // Pose
+ virtual void setGlobalPose(const PxTransform& pose, bool wake);
+ virtual PxTransform getGlobalPose() const;
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ NpRigidStatic(const PxTransform& pose);
+
+ virtual void switchToNoSim();
+ virtual void switchFromNoSim();
+
+#if PX_CHECKED
+ bool checkConstraintValidity() const;
+#endif
+
+ PX_FORCE_INLINE const Scb::Actor& getScbActorFast() const { return mRigidStatic; }
+ PX_FORCE_INLINE Scb::Actor& getScbActorFast() { return mRigidStatic; }
+
+ PX_FORCE_INLINE const Scb::RigidStatic& getScbRigidStaticFast() const { return mRigidStatic; }
+ PX_FORCE_INLINE Scb::RigidStatic& getScbRigidStaticFast() { return mRigidStatic; }
+
+ PX_FORCE_INLINE const PxTransform& getGlobalPoseFast() const { return mRigidStatic.getActor2World(); }
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+public:
+ void visualize(Cm::RenderOutput& out, NpScene* scene);
+#endif
+
+private:
+ Scb::RigidStatic mRigidStatic;
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpScene.cpp b/PhysX_3.4/Source/PhysX/src/NpScene.cpp
new file mode 100644
index 00000000..eb81cb66
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpScene.cpp
@@ -0,0 +1,3185 @@
+// 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 "PxSimulationEventCallback.h"
+
+#include "NpScene.h"
+#include "NpRigidStatic.h"
+#include "NpRigidDynamic.h"
+#include "NpArticulation.h"
+#include "NpArticulationLink.h"
+#include "NpArticulationJoint.h"
+// PX_AGGREGATE
+#include "NpAggregate.h"
+//~PX_AGGREGATE
+#include "NpVolumeCache.h"
+#include "NpBatchQuery.h"
+#include "SqPruner.h"
+#include "SqPrunerMergeData.h"
+#include "SqPruningStructure.h"
+#include "SqSceneQueryManager.h"
+
+#if PX_USE_PARTICLE_SYSTEM_API
+#include "particles/NpParticleSystem.h"
+#include "particles/NpParticleFluid.h"
+#include "ScbParticleSystem.h"
+#endif
+
+#if PX_USE_CLOTH_API
+#include "NpCloth.h"
+#endif
+
+#include "ScbNpDeps.h"
+#include "CmCollection.h"
+#include "CmUtils.h"
+
+#if PX_SUPPORT_GPU_PHYSX
+#include "task/PxGpuDispatcher.h"
+#endif
+
+#include "PxsIslandSim.h"
+
+using namespace physx;
+
+// enable thread checks in all debug builds
+#if PX_DEBUG || PX_CHECKED
+#define NP_ENABLE_THREAD_CHECKS 1
+#else
+#define NP_ENABLE_THREAD_CHECKS 0
+#endif
+
+using namespace shdfnd;
+using namespace Sq;
+
+///////////////////////////////////////////////////////////////////////////////
+
+static PX_FORCE_INLINE bool removeFromSceneCheck(NpScene* npScene, PxScene* scene, const char* name)
+{
+ if (scene == static_cast<PxScene*>(npScene))
+ {
+ return true;
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "%s not assigned to scene or assigned to another scene. Call will be ignored!", name);
+ return false;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+NpSceneQueries::NpSceneQueries(const PxSceneDesc& desc) :
+ mScene (desc, getContextId()),
+ mSQManager (mScene, desc.staticStructure, desc.dynamicStructure, desc.dynamicTreeRebuildRateHint, desc.limits),
+ mCachedRaycastFuncs (Gu::getRaycastFuncTable()),
+ mCachedSweepFuncs (Gu::getSweepFuncTable()),
+ mCachedOverlapFuncs (Gu::getOverlapFuncTable())
+#if PX_SUPPORT_PVD
+ , mSingleSqCollector (mScene, false),
+ mBatchedSqCollector (mScene, true)
+#endif
+{
+}
+
+NpScene::NpScene(const PxSceneDesc& desc) :
+ NpSceneQueries (desc),
+ mConstraints (PX_DEBUG_EXP("sceneConstraints")),
+ mRigidActors (PX_DEBUG_EXP("sceneRigidActors")),
+ mArticulations (PX_DEBUG_EXP("sceneArticulations")),
+ mAggregates (PX_DEBUG_EXP("sceneAggregates")),
+#if PX_USE_PARTICLE_SYSTEM_API
+ mPxParticleBaseSet (PX_DEBUG_EXP("sceneParticles")),
+#endif
+#if PX_USE_CLOTH_API
+ mPxCloths (PX_DEBUG_EXP("sceneCloths")),
+#endif
+ mSanityBounds (desc.sanityBounds),
+ mNbClients (1), //we always have the default client.
+ mClientBehaviorFlags (PX_DEBUG_EXP("sceneBehaviorFlags")),
+ mSceneCompletion (mPhysicsDone),
+ mCollisionCompletion (mCollisionDone),
+ mSceneExecution (0, "NpScene.execution"),
+ mSceneCollide (0, "NpScene.collide"),
+ mSceneAdvance (0, "NpScene.solve"),
+ mControllingSimulation (false),
+ mSimThreadStackSize (0),
+ mConcurrentWriteCount (0),
+ mConcurrentReadCount (0),
+ mConcurrentErrorCount (0),
+ mCurrentWriter (0),
+ mHasSimulatedOnce (false),
+ mBetweenFetchResults (false)
+{
+ mSceneExecution.setObject(this);
+ mSceneCollide.setObject(this);
+ mSceneAdvance.setObject(this);
+
+ mTaskManager = mScene.getScScene().getTaskManagerPtr();
+ mThreadReadWriteDepth = Ps::TlsAlloc();
+
+}
+
+NpSceneQueries::~NpSceneQueries()
+{
+}
+
+NpScene::~NpScene()
+{
+ // PT: we need to do that one first, now that we don't release the objects anymore. Otherwise we end up with a sequence like:
+ // - actor is part of an aggregate, and part of a scene
+ // - actor gets removed from the scene. This does *not* remove it from the aggregate.
+ // - aggregate gets removed from the scene, sees that one contained actor ain't in the scene => we get a warning message
+ PxU32 aggregateCount = mAggregates.size();
+ while(aggregateCount--)
+ removeAggregate(*mAggregates.getEntries()[aggregateCount], false);
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ PxU32 partCount = mPxParticleBaseSet.size();
+ while(partCount--)
+ removeActor(*mPxParticleBaseSet.getEntries()[partCount], false);
+#endif
+
+#if PX_USE_CLOTH_API
+ PxU32 clothCount = mPxCloths.size();
+ while(clothCount--)
+ removeActor(*mPxCloths.getEntries()[clothCount], false);
+#endif
+
+ PxU32 rigidActorCount = mRigidActors.size();
+ while(rigidActorCount--)
+ removeActor(*mRigidActors[rigidActorCount], false);
+
+ PxU32 articCount = mArticulations.size();
+ while(articCount--)
+ removeArticulation(*mArticulations.getEntries()[articCount], false);
+
+ // release volume caches
+ Array<NpVolumeCache*> caches; caches.reserve(mVolumeCaches.size());
+ for(HashSet<NpVolumeCache*>::Iterator iter = mVolumeCaches.getIterator(); !iter.done(); ++iter)
+ caches.pushBack(*iter);
+ for(PxU32 i = 0; i < caches.size(); i++)
+ releaseVolumeCache(caches[i]);
+
+ bool unlock = mScene.getFlags() & PxSceneFlag::eREQUIRE_RW_LOCK;
+
+#if PX_SUPPORT_PVD
+ getSingleSqCollector().release();
+ getBatchedSqCollector().release();
+#endif
+
+ // release batch queries
+ PxU32 numSq = mBatchQueries.size();
+ while(numSq--)
+ PX_DELETE(mBatchQueries[numSq]);
+ mBatchQueries.clear();
+
+ mScene.release();
+
+ // unlock the lock taken in release(), must unlock before
+ // mRWLock is destroyed otherwise behavior is undefined
+ if (unlock)
+ unlockWrite();
+
+ TlsFree(mThreadReadWriteDepth);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::release()
+{
+ // need to acquire lock for release, note this is unlocked in the destructor
+ if (mScene.getFlags() & PxSceneFlag::eREQUIRE_RW_LOCK)
+ lockWrite(__FILE__, __LINE__);
+
+ // It will be hard to do a write check here since all object release calls in the scene destructor do it and would mess
+ // up the test. If we really want it on scene destruction as well, we need to either have internal and external release
+ // calls or come up with a different approach (for example using thread ID as detector variable).
+
+ if(getSimulationStage() != Sc::SimulationStage::eCOMPLETE)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::release(): Scene is still being simulated! PxScene::fetchResults() is called implicitly.");
+
+ if(getSimulationStage() == Sc::SimulationStage::eCOLLIDE)
+ {
+ fetchCollision(true);
+ }
+
+ if(getSimulationStage() == Sc::SimulationStage::eFETCHCOLLIDE) // need to call getSimulationStage() again beacause fetchCollision() might change the value.
+ {
+ // this is for split sim
+ advance(NULL);
+ }
+
+ fetchResults(true, NULL);
+ }
+ NpPhysics::getInstance().releaseSceneInternal(*this);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool NpScene::loadFromDesc(const PxSceneDesc& desc)
+{
+ {
+ if(desc.limits.maxNbActors)
+ mRigidActors.reserve(desc.limits.maxNbActors);
+
+ //const PxU32 totalNbShapes = desc.limits.maxNbStaticShapes + desc.limits.maxNbDynamicShapes;
+ mScene.getScScene().preAllocate(desc.limits.maxNbActors, desc.limits.maxNbBodies, desc.limits.maxNbStaticShapes, desc.limits.maxNbDynamicShapes);
+ }
+
+ userData = desc.userData;
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::setGravity(const PxVec3& g)
+{
+ NP_WRITE_CHECK(this);
+ mScene.setGravity(g);
+}
+
+PxVec3 NpScene::getGravity() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getGravity();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::setBounceThresholdVelocity(const PxReal t)
+{
+ NP_WRITE_CHECK(this);
+ mScene.setBounceThresholdVelocity(t);
+}
+
+PxReal NpScene::getBounceThresholdVelocity() const
+{
+ NP_READ_CHECK(this)
+ return mScene.getBounceThresholdVelocity();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::setLimits(const PxSceneLimits& limits)
+{
+ NP_WRITE_CHECK(this);
+
+ if(limits.maxNbActors)
+ mRigidActors.reserve(limits.maxNbActors);
+
+ mScene.getScScene().preAllocate(limits.maxNbActors, limits.maxNbBodies, limits.maxNbStaticShapes, limits.maxNbDynamicShapes);
+ mScene.setLimits(limits);
+
+ mSQManager.preallocate(limits.maxNbStaticShapes, limits.maxNbDynamicShapes);
+}
+
+//////////////////////////////////////////////////////////////////////////
+
+PxSceneLimits NpScene::getLimits() const
+{
+ NP_READ_CHECK(this);
+
+ return mScene.getLimits();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::setFlag(PxSceneFlag::Enum flag, bool value)
+{
+ NP_WRITE_CHECK(this);
+
+ // this call supports mutable flags only
+ PX_CHECK_AND_RETURN(PxSceneFlags(flag) & PxSceneFlags(PxSceneFlag::eMUTABLE_FLAGS),
+ "PxScene::setFlag: This flag is not mutable - you can only set it once in PxSceneDesc at startup!");
+
+ PxSceneFlags currentFlags = mScene.getFlags();
+
+ if(value)
+ currentFlags |= flag;
+ else
+ currentFlags &= ~PxSceneFlags(flag);
+
+ mScene.setFlags(currentFlags);
+}
+
+PxSceneFlags NpScene::getFlags() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getFlags();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PT: make sure we always add to array and set the array index properly / at the same time
+template<class T>
+static PX_FORCE_INLINE void addRigidActorToArray(T& a, Ps::Array<PxRigidActor*>& rigidActors)
+{
+ a.setRigidActorArrayIndex(rigidActors.size());
+ rigidActors.pushBack(&a);
+}
+
+void NpScene::addActor(PxActor& actor)
+{
+ PX_PROFILE_ZONE("API.addActor", getContextId());
+ NP_WRITE_CHECK(this);
+ PX_SIMD_GUARD;
+
+ PxRigidStatic* a = actor.is<PxRigidStatic>();
+ if(a)
+ {
+#if PX_CHECKED
+ if(!static_cast<NpRigidStatic*>(a)->checkConstraintValidity())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addActor(): actor has invalid constraint and may not be added to scene");
+ return;
+ }
+#endif
+ if(static_cast<NpRigidStatic*>(a)->getShapeManager().getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addActor(): actor is in a pruning structure and cannot be added to a scene directly, use addActors(const PxPruningStructure& )");
+ return;
+ }
+ }
+
+ PxRigidDynamic* aD = actor.is<PxRigidDynamic>();
+ if(aD && static_cast<NpRigidDynamic*>(aD)->getShapeManager().getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addActor(): actor is in a pruning structure and cannot be added to a scene directly, use addActors(const PxPruningStructure& )");
+ return;
+ }
+
+ const Scb::ControlState::Enum cs = NpActor::getScbFromPxActor(actor).getControlState();
+ if((cs == Scb::ControlState::eNOT_IN_SCENE) || ((cs == Scb::ControlState::eREMOVE_PENDING) && (NpActor::getOwnerScene(actor) == this)))
+ addActorInternal(actor);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addActor(): Actor already assigned to a scene. Call will be ignored!");
+}
+
+void NpScene::addActorInternal(PxActor& actor)
+{
+ switch(actor.getConcreteType())
+ {
+ case PxConcreteType::eRIGID_STATIC:
+ {
+ NpRigidStatic& npStatic = static_cast<NpRigidStatic&>(actor);
+#if PX_CHECKED
+ checkPositionSanity(npStatic, npStatic.getGlobalPose(), "PxScene::addActor or PxScene::addAggregate");
+#endif
+ addRigidStatic(npStatic);
+ }
+ break;
+
+ case PxConcreteType::eRIGID_DYNAMIC:
+ {
+ NpRigidDynamic& npDynamic = static_cast<NpRigidDynamic&>(actor);
+#if PX_CHECKED
+ checkPositionSanity(npDynamic, npDynamic.getGlobalPose(), "PxScene::addActor or PxScene::addAggregate");
+#endif
+ addRigidDynamic(npDynamic);
+ }
+ break;
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ case PxConcreteType::ePARTICLE_SYSTEM:
+ {
+ NpParticleSystem& npSystem = static_cast<NpParticleSystem&>(actor);
+ addParticleSystem(npSystem);
+ }
+ break;
+
+ case PxConcreteType::ePARTICLE_FLUID:
+ {
+ NpParticleFluid& npFluid = static_cast<NpParticleFluid&>(actor);
+ addParticleFluid(npFluid);
+ }
+ break;
+#endif
+
+#if PX_USE_CLOTH_API
+ case PxConcreteType::eCLOTH:
+ {
+ NpCloth& npCloth = static_cast<NpCloth&>(actor);
+ addCloth(npCloth);
+ }
+ break;
+#endif
+ case PxConcreteType::eARTICULATION_LINK:
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::addActor(): Individual articulation links can not be added to the scene");
+ }
+ break;
+
+ default:
+ PX_ASSERT(0);
+ }
+}
+
+void NpScene::updateScbStateAndSetupSq(const PxRigidActor& rigidActor, Scb::Actor& scbActor, NpShapeManager& shapeManager, bool actorDynamic, const PxBounds3* bounds, bool hasPrunerStructure)
+{
+ // all the things Scb does in non-buffered insertion
+ SceneQueryManager& sqManager = getSceneQueryManagerFast();
+
+ scbActor.setScbScene(&mScene);
+ scbActor.setControlState(Scb::ControlState::eIN_SCENE);
+ NpShape*const * shapes = shapeManager.getShapes();
+ PxU32 nbShapes = shapeManager.getNbShapes();
+
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ NpShape& shape = *shapes[i];
+ const PxShapeFlags shapeFlags = shape.getFlagsUnbuffered(); // PT: note that the regular code reads buffered flags
+
+ shape.incRefCount();
+ if(shape.isExclusiveFast())
+ {
+ shape.getScbShape().setScbScene(&mScene);
+ shape.getScbShape().setControlState(Scb::ControlState::eIN_SCENE);
+ }
+
+ // PT: this part is copied from 'NpShapeManager::setupAllSceneQuery'
+ if(shapeFlags & PxShapeFlag::eSCENE_QUERY_SHAPE) // PT: TODO: refactor with 'isSceneQuery' in shape manager?
+ {
+ const PrunerData data = sqManager.addPrunerShape(shape, rigidActor, actorDynamic, bounds ? bounds+i : NULL, hasPrunerStructure);
+ shapeManager.setPrunerData(i, data);
+ }
+ }
+}
+
+PX_FORCE_INLINE void NpScene::updateScbStateAndSetupSq(const PxRigidActor& rigidActor, Scb::Body& body, NpShapeManager& shapeManager, bool actorDynamic, const PxBounds3* bounds, bool hasPrunerStructure)
+{
+ body.initBufferedState();
+ updateScbStateAndSetupSq(rigidActor, static_cast<Scb::Actor&>(body), shapeManager, actorDynamic, bounds, hasPrunerStructure);
+}
+
+void NpScene::addActors(PxActor*const* actors, PxU32 nbActors)
+{
+ addActorsInternal(actors, nbActors, NULL);
+}
+
+void NpScene::addActors(const PxPruningStructure& ps)
+{
+ const Sq::PruningStructure& prunerStructure = static_cast<const Sq::PruningStructure&>(ps);
+ if(!prunerStructure.isValid())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxScene::addActors(): Provided pruning structure is not valid.");
+ return;
+ }
+ addActorsInternal(prunerStructure.getActors(), prunerStructure.getNbActors(), &prunerStructure);
+}
+
+void NpScene::addActorsInternal(PxActor*const* PX_RESTRICT actors, PxU32 nbActors, const Sq::PruningStructure* pS)
+{
+ PX_PROFILE_ZONE("API.addActors", getContextId());
+ NP_WRITE_CHECK(this);
+ PX_SIMD_GUARD;
+
+ if(getSimulationStage() != Sc::SimulationStage::eCOMPLETE)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxScene::addActors() not allowed while simulation is running.");
+ return;
+ }
+
+ const bool hasPrunerStructure = pS ? true : false;
+ Sc::Scene& scScene = mScene.getScScene();
+ PxU32 actorsDone;
+
+ Sc::BatchInsertionState scState;
+ scScene.startBatchInsertion(scState);
+
+ scState.staticActorOffset = ptrdiff_t(size_t(&(reinterpret_cast<NpRigidStatic*>(0)->getScbRigidStaticFast().getScStatic())));
+ scState.staticShapeTableOffset = ptrdiff_t(size_t(&(reinterpret_cast<NpRigidStatic*>(0)->getShapeManager().getShapeTable())));
+ scState.dynamicActorOffset = ptrdiff_t(size_t(&(reinterpret_cast<NpRigidDynamic*>(0)->getScbBodyFast().getScBody())));
+ scState.dynamicShapeTableOffset = ptrdiff_t(size_t(&(reinterpret_cast<NpRigidDynamic*>(0)->getShapeManager().getShapeTable())));
+ scState.shapeOffset = ptrdiff_t(NpShapeGetScPtrOffset());
+
+ Ps::InlineArray<PxBounds3, 8> shapeBounds;
+ for(actorsDone=0; actorsDone<nbActors; actorsDone++)
+ {
+ if(actorsDone+1<nbActors)
+ Ps::prefetch(actors[actorsDone+1], sizeof(NpRigidDynamic)); // worst case: PxRigidStatic is smaller
+
+ const Scb::ControlState::Enum cs = NpActor::getScbFromPxActor(*actors[actorsDone]).getControlState();
+ if (!((cs == Scb::ControlState::eNOT_IN_SCENE) || ((cs == Scb::ControlState::eREMOVE_PENDING) && (NpActor::getOwnerScene(*actors[actorsDone]) == this))))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addActors(): Actor already assigned to a scene. Call will be ignored!");
+ break;
+ }
+
+ const PxType type = actors[actorsDone]->getConcreteType();
+ if(type == PxConcreteType::eRIGID_STATIC)
+ {
+ NpRigidStatic& a = *static_cast<NpRigidStatic*>(actors[actorsDone]);
+#if PX_CHECKED
+ if(!a.checkConstraintValidity())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addActors(): actor has invalid constraint and may not be added to scene");
+ break;
+ }
+ checkPositionSanity(a, a.getGlobalPose(), "PxScene::addActors");
+#endif
+ if(!hasPrunerStructure && a.getShapeManager().getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addActors(): actor is in a pruning structure and cannot be added to a scene directly, use addActors(const PxPruningStructure& )");
+ break;
+ }
+
+ if(!(a.getScbRigidStaticFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION))
+ {
+ shapeBounds.resizeUninitialized(a.NpRigidStatic::getNbShapes()+1); // PT: +1 for safe reads in addPrunerData/inflateBounds
+ scScene.addStatic(&a, scState, shapeBounds.begin());
+ updateScbStateAndSetupSq(a, a.getScbActorFast(), a.getShapeManager(), false, shapeBounds.begin(), hasPrunerStructure);
+ addRigidActorToArray(a, mRigidActors);
+ a.addConstraintsToScene();
+ }
+ else
+ addRigidStatic(a, hasPrunerStructure);
+ }
+ else if(type == PxConcreteType::eRIGID_DYNAMIC)
+ {
+ NpRigidDynamic& a = *static_cast<NpRigidDynamic*>(actors[actorsDone]);
+#if PX_CHECKED
+ checkPositionSanity(a, a.getGlobalPose(), "PxScene::addActors");
+#endif
+ if(!hasPrunerStructure && a.getShapeManager().getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addActors(): actor is in a pruning structure and cannot be added to a scene directly, use addActors(const PxPruningStructure& )");
+ break;
+ }
+
+ if(!(a.getScbBodyFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION))
+ {
+ shapeBounds.resizeUninitialized(a.NpRigidDynamic::getNbShapes()+1); // PT: +1 for safe reads in addPrunerData/inflateBounds
+ scScene.addBody(&a, scState, shapeBounds.begin());
+ updateScbStateAndSetupSq(a, a.getScbBodyFast(), a.getShapeManager(), true, shapeBounds.begin(), hasPrunerStructure);
+ addRigidActorToArray(a, mRigidActors);
+ a.addConstraintsToScene();
+ }
+ else
+ addRigidDynamic(a, hasPrunerStructure);
+ }
+ else if(type == PxConcreteType::eCLOTH || type == PxConcreteType::ePARTICLE_SYSTEM || type == PxConcreteType::ePARTICLE_FLUID)
+ {
+ addActorInternal(*actors[actorsDone]);
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::addRigidActors(): articulation link not permitted");
+ break;
+ }
+ }
+ // merge sq PrunerStructure
+ if(pS)
+ {
+ if(pS->getTreeNodes(PruningIndex::eSTATIC))
+ {
+ AABBPrunerMergeData params(pS->getTreeNbNodes(PruningIndex::eSTATIC), pS->getTreeNodes(PruningIndex::eSTATIC),
+ pS->getNbObjects(PruningIndex::eSTATIC), pS->getTreeIndices(PruningIndex::eSTATIC));
+ mSQManager.get(PruningIndex::eSTATIC).pruner()->merge(&params);
+ }
+ if(pS->getTreeNodes(PruningIndex::eDYNAMIC))
+ {
+ AABBPrunerMergeData params(pS->getTreeNbNodes(PruningIndex::eDYNAMIC), pS->getTreeNodes(PruningIndex::eDYNAMIC),
+ pS->getNbObjects(PruningIndex::eDYNAMIC), pS->getTreeIndices(PruningIndex::eDYNAMIC));
+ mSQManager.get(PruningIndex::eDYNAMIC).pruner()->merge(&params);
+ }
+ }
+ scScene.finishBatchInsertion(scState);
+
+ // if we failed, still complete everything for the successful inserted actors before backing out
+#if PX_SUPPORT_PVD
+ for(PxU32 i=0;i<actorsDone;i++)
+ {
+ if ((actors[i]->getConcreteType()==PxConcreteType::eRIGID_STATIC) && (!(static_cast<NpRigidStatic*>(actors[i])->getScbRigidStaticFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION)))
+ mScene.getScenePvdClient().addStaticAndShapesToPvd(static_cast<NpRigidStatic*>(actors[i])->getScbRigidStaticFast());
+ else if ((actors[i]->getConcreteType() == PxConcreteType::eRIGID_DYNAMIC) && (!(static_cast<NpRigidDynamic*>(actors[i])->getScbBodyFast().getActorFlags() & PxActorFlag::eDISABLE_SIMULATION)))
+ mScene.getScenePvdClient().addBodyAndShapesToPvd(static_cast<NpRigidDynamic*>(actors[i])->getScbBodyFast());
+ }
+#endif
+
+ if(actorsDone<nbActors) // Everything is consistent up to the failure point, so just use removeActor to back out gracefully if necessary
+ {
+ for(PxU32 j=0;j<actorsDone;j++)
+ removeActorInternal(*actors[j], false, true);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::removeActors(PxActor*const* PX_RESTRICT actors, PxU32 nbActors, bool wakeOnLostTouch)
+{
+ PX_PROFILE_ZONE("API.removeActors", getContextId());
+ NP_WRITE_CHECK(this);
+
+ Sc::Scene& scScene = mScene.getScScene();
+ // resize the bitmap so it does not allocate each remove actor call
+ scScene.resizeReleasedBodyIDMaps(mRigidActors.size(),nbActors);
+ Sc::BatchRemoveState removeState;
+ scScene.setBatchRemove(&removeState);
+
+ for(PxU32 actorsDone=0; actorsDone<nbActors; actorsDone++)
+ {
+ if(actorsDone+1<nbActors)
+ Ps::prefetch(actors[actorsDone+1], sizeof(NpRigidDynamic)); // worst case: PxRigidStatic is smaller
+
+ PxType type = actors[actorsDone]->getConcreteType();
+ if (!removeFromSceneCheck(this, actors[actorsDone]->getScene(), "PxScene::removeActors(): Actor"))
+ {
+ break;
+ }
+
+ removeState.bufferedShapes.clear();
+ removeState.removedShapes.clear();
+
+ if(type == PxConcreteType::eRIGID_STATIC)
+ {
+ NpRigidStatic& actor = *static_cast<NpRigidStatic*>(actors[actorsDone]);
+ const PxActorFlags actorFlags = actor.getScbRigidStaticFast().getActorFlags();
+
+ if(actor.getShapeManager().getNbShapes())
+ Ps::prefetch(actor.getShapeManager().getShapes()[0],sizeof(NpShape));
+ scScene.prefetchForRemove(actor.getScbRigidStaticFast().getScStatic());
+ Ps::prefetch(mRigidActors[mRigidActors.size()-1],sizeof(NpRigidDynamic));
+
+ const bool noSimBuffered = actorFlags.isSet(PxActorFlag::eDISABLE_SIMULATION);
+ if (!noSimBuffered)
+ actor.removeConstraintsFromScene();
+
+ actor.getShapeManager().teardownAllSceneQuery(getSceneQueryManagerFast());
+
+ Scb::RigidStatic& rs = actor.getScbRigidStaticFast();
+ mScene.removeActor(rs, wakeOnLostTouch, rs.isSimDisabledInternally());
+ removeFromRigidActorList(actor.getRigidActorArrayIndex());
+ }
+ else if(type == PxConcreteType::eRIGID_DYNAMIC)
+ {
+ NpRigidDynamic& actor = *static_cast<NpRigidDynamic*>(actors[actorsDone]);
+ const PxActorFlags actorFlags = actor.getScbBodyFast().getActorFlags();
+
+ if(actor.getShapeManager().getNbShapes())
+ Ps::prefetch(actor.getShapeManager().getShapes()[0],sizeof(NpShape));
+ scScene.prefetchForRemove(actor.getScbBodyFast().getScBody());
+ Ps::prefetch(mRigidActors[mRigidActors.size()-1],sizeof(NpRigidDynamic));
+
+ const bool noSimBuffered = actorFlags.isSet(PxActorFlag::eDISABLE_SIMULATION);
+ if (!noSimBuffered)
+ actor.removeConstraintsFromScene();
+
+ actor.getShapeManager().teardownAllSceneQuery(getSceneQueryManagerFast());
+
+ Scb::Body& b = actor.getScbBodyFast();
+ mScene.removeActor(b, wakeOnLostTouch, b.isSimDisabledInternally());
+ removeFromRigidActorList(actor.getRigidActorArrayIndex());
+ }
+ else if(type == PxConcreteType::eCLOTH || type == PxConcreteType::ePARTICLE_SYSTEM || type == PxConcreteType::ePARTICLE_FLUID)
+ {
+ removeActorInternal(*actors[actorsDone],wakeOnLostTouch, true);
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::removeActor(): Individual articulation links can not be removed from the scene");
+ break;
+ }
+ }
+
+ scScene.setBatchRemove(NULL);
+}
+
+void NpScene::removeActor(PxActor& actor, bool wakeOnLostTouch)
+{
+ PX_PROFILE_ZONE("API.removeActor", getContextId());
+ NP_WRITE_CHECK(this);
+ if (removeFromSceneCheck(this, actor.getScene(), "PxScene::removeActor(): Actor"))
+ {
+ removeActorInternal(actor, wakeOnLostTouch, true);
+ }
+}
+
+void NpScene::removeActorInternal(PxActor& actor, bool wakeOnLostTouch, bool removeFromAggregate)
+{
+ switch(actor.getType())
+ {
+ case PxActorType::eRIGID_STATIC:
+ {
+ NpRigidStatic& npStatic = static_cast<NpRigidStatic&>(actor);
+ removeRigidStatic(npStatic, wakeOnLostTouch, removeFromAggregate);
+ }
+ break;
+
+ case PxActorType::eRIGID_DYNAMIC:
+ {
+ NpRigidDynamic& npDynamic = static_cast<NpRigidDynamic&>(actor);
+ removeRigidDynamic(npDynamic, wakeOnLostTouch, removeFromAggregate);
+ }
+ break;
+#if PX_USE_PARTICLE_SYSTEM_API
+ case PxActorType::ePARTICLE_SYSTEM:
+ {
+ NpParticleSystem& npSystem = static_cast<NpParticleSystem&>(actor);
+ removeParticleSystem(npSystem);
+ }
+ break;
+
+ case PxActorType::ePARTICLE_FLUID:
+ {
+ NpParticleFluid& npFluid = static_cast<NpParticleFluid&>(actor);
+ removeParticleFluid(npFluid);
+ }
+ break;
+#endif
+
+#if PX_USE_CLOTH_API
+ case PxActorType::eCLOTH:
+ {
+ NpCloth& npCloth = static_cast<NpCloth&>(actor);
+ removeCloth(npCloth);
+ }
+ break;
+#endif
+
+ case PxActorType::eARTICULATION_LINK:
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::removeActor(): Individual articulation links can not be removed from the scene");
+ }
+ break;
+
+ case PxActorType::eACTOR_COUNT:
+ case PxActorType::eACTOR_FORCE_DWORD:
+ PX_ASSERT(0);
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PT: TODO: inline this one in the header for consistency
+void NpScene::removeFromRigidActorList(const PxU32& index)
+{
+ PX_ASSERT(index != 0xFFFFFFFF);
+ PX_ASSERT(index < mRigidActors.size());
+
+ {
+ const PxU32 size = mRigidActors.size() - 1;
+ mRigidActors.replaceWithLast(index);
+ if(size && size != index)
+ {
+ PxRigidActor& rigidActor = *mRigidActors[index];
+ switch(rigidActor.getType())
+ {
+ case PxActorType::eRIGID_STATIC:
+ {
+ NpRigidStatic& npStatic = static_cast<NpRigidStatic&>(rigidActor);
+ npStatic.setRigidActorArrayIndex(index);
+ }
+ break;
+ case PxActorType::eRIGID_DYNAMIC:
+ {
+ NpRigidDynamic& npDynamic = static_cast<NpRigidDynamic&>(rigidActor);
+ npDynamic.setRigidActorArrayIndex(index);
+ }
+ break;
+
+#if PX_USE_CLOTH_API
+ case PxActorType::eCLOTH:
+#endif
+#if PX_USE_PARTICLE_SYSTEM_API
+ case PxActorType::ePARTICLE_FLUID:
+ case PxActorType::ePARTICLE_SYSTEM:
+#endif
+ case PxActorType::eARTICULATION_LINK:
+ case PxActorType::eACTOR_COUNT:
+ case PxActorType::eACTOR_FORCE_DWORD:
+ PX_ASSERT(0);
+ break;
+ }
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+template<class T, class T2>
+static PX_FORCE_INLINE void addActorT(T& actor, T2& scbActor, Ps::Array<PxRigidActor*>& actors, NpScene* scene, bool hasPrunerStructure)
+{
+ const bool noSimBuffered = scbActor.getActorFlags().isSet(PxActorFlag::eDISABLE_SIMULATION);
+
+ PxBounds3 bounds[8+1]; // PT: +1 for safe reads in addPrunerData/inflateBounds
+ const bool canReuseBounds = !noSimBuffered && !scene->getScene().isPhysicsBuffering() && actor.getShapeManager().getNbShapes()<=8;
+ PxBounds3* uninflatedBounds = canReuseBounds ? bounds : NULL;
+
+ scene->getScene().addActor(scbActor, noSimBuffered, uninflatedBounds);
+
+ actor.getShapeManager().setupAllSceneQuery(scene, actor, hasPrunerStructure, uninflatedBounds);
+ if(!noSimBuffered)
+ actor.addConstraintsToScene();
+ addRigidActorToArray(actor, actors);
+}
+
+void NpScene::addRigidStatic(NpRigidStatic& actor, bool hasPrunerStructure)
+{
+ addActorT(actor, actor.getScbRigidStaticFast(), mRigidActors, this, hasPrunerStructure);
+}
+
+void NpScene::addRigidDynamic(NpRigidDynamic& body, bool hasPrunerStructure)
+{
+ addActorT(body, body.getScbBodyFast(), mRigidActors, this, hasPrunerStructure);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+template<class T, class T2>
+static PX_FORCE_INLINE void removeActorT(T& actor, T2& scbActor, NpScene* scene, bool wakeOnLostTouch, bool removeFromAggregate)
+{
+ PX_ASSERT(NpActor::getAPIScene(actor) == scene);
+ const bool noSimBuffered = scbActor.getActorFlags().isSet(PxActorFlag::eDISABLE_SIMULATION);
+
+ if(removeFromAggregate)
+ {
+ PxU32 index = 0xffffffff;
+ NpAggregate* aggregate = actor.getNpAggregate(index);
+ if(aggregate)
+ {
+ aggregate->removeActorAndReinsert(actor, false);
+ PX_ASSERT(!actor.getAggregate());
+ }
+ }
+
+ actor.getShapeManager().teardownAllSceneQuery(scene->getSceneQueryManagerFast());
+ if(!noSimBuffered)
+ actor.removeConstraintsFromScene();
+
+ scene->getScene().removeActor(scbActor, wakeOnLostTouch, scbActor.isSimDisabledInternally());
+ scene->removeFromRigidActorList(actor.getRigidActorArrayIndex());
+}
+
+void NpScene::removeRigidStatic(NpRigidStatic& actor, bool wakeOnLostTouch, bool removeFromAggregate)
+{
+ removeActorT(actor, actor.getScbRigidStaticFast(), this, wakeOnLostTouch, removeFromAggregate);
+}
+
+void NpScene::removeRigidDynamic(NpRigidDynamic& body, bool wakeOnLostTouch, bool removeFromAggregate)
+{
+ removeActorT(body, body.getScbBodyFast(), this, wakeOnLostTouch, removeFromAggregate);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::addArticulation(PxArticulation& articulation)
+{
+ PX_PROFILE_ZONE("API.addArticulation", getContextId());
+ NP_WRITE_CHECK(this);
+
+ PX_CHECK_AND_RETURN(articulation.getNbLinks()>0, "PxScene::addArticulation: empty articulations may not be added to simulation.");
+ PX_SIMD_GUARD;
+
+ if (this->getFlags() & PxSceneFlag::eENABLE_GPU_DYNAMICS)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addArticulation(): Articulations are not currently supported when PxSceneFlag::eENABLE_GPU_DYNAMICS is set!");
+ return;
+ }
+
+ Scb::Articulation& art = static_cast<NpArticulation&>(articulation).getArticulation();
+ Scb::ControlState::Enum cs = art.getControlState();
+ if ((cs == Scb::ControlState::eNOT_IN_SCENE) || ((cs == Scb::ControlState::eREMOVE_PENDING) && (art.getScbScene()->getPxScene() == this)))
+ addArticulationInternal(articulation);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addArticulation(): Articulation already assigned to a scene. Call will be ignored!");
+}
+
+void NpScene::addArticulationInternal(PxArticulation& articulation)
+{
+ NpArticulation& npa = static_cast<NpArticulation&>(articulation);
+
+ // Add root link first
+ PxU32 nbLinks = npa.getNbLinks();
+ PX_ASSERT(nbLinks > 0);
+ NpArticulationLink* rootLink = npa.getLinks()[0];
+
+#if PX_CHECKED
+ checkPositionSanity(*rootLink, rootLink->getGlobalPose(), "PxScene::addArticulation or PxScene::addAggregate");
+#endif
+ if(rootLink->getMass()==0)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::addArticulation(): Articulation link with zero mass added to scene; defaulting mass to 1");
+ rootLink->setMass(1.0f);
+ }
+
+ PxVec3 inertia0 = rootLink->getMassSpaceInertiaTensor();
+ if(inertia0.x == 0.0f || inertia0.y == 0.0f || inertia0.z == 0.0f)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::addArticulation(): Articulation link with zero moment of inertia added to scene; defaulting inertia to (1,1,1)");
+ rootLink->setMassSpaceInertiaTensor(PxVec3(1.0f, 1.0f, 1.0f));
+ }
+
+ bool linkTriggersWakeUp = !rootLink->getScbBodyFast().checkSleepReadinessBesidesWakeCounter();
+
+ addArticulationLinkBody(*rootLink);
+
+ // Add articulation
+ Scb::Articulation& scbArt = npa.getArticulation();
+ mScene.addArticulation(scbArt);
+
+ addArticulationLinkConstraint(*rootLink);
+
+ // Add links & joints
+ PX_ALLOCA(linkStack, NpArticulationLink*, nbLinks);
+ linkStack[0] = rootLink;
+ PxU32 curLink = 0;
+ PxU32 stackSize = 1;
+ while(curLink < (nbLinks-1))
+ {
+ PX_ASSERT(curLink < stackSize);
+ NpArticulationLink* l = linkStack[curLink];
+ NpArticulationLink*const* children = l->getChildren();
+
+ for(PxU32 i=0; i < l->getNbChildren(); i++)
+ {
+ NpArticulationLink* child = children[i];
+
+#if PX_CHECKED
+ checkPositionSanity(*child, child->getGlobalPose(), "PxScene::addArticulation");
+#endif
+ if(child->getMass()==0)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::addArticulation(): Articulation link with zero mass added to scene; defaulting mass to 1");
+ child->setMass(1.0f);
+ }
+
+ PxVec3 inertia = child->getMassSpaceInertiaTensor();
+ if(inertia.x == 0.0f || inertia.y == 0.0f || inertia.z == 0.0f)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::addArticulation(): Articulation link with zero moment of inertia added to scene; defaulting inertia to (1,1,1)");
+ child->setMassSpaceInertiaTensor(PxVec3(1.0f, 1.0f, 1.0f));
+ }
+
+ linkTriggersWakeUp = linkTriggersWakeUp || (!child->getScbBodyFast().checkSleepReadinessBesidesWakeCounter());
+
+ addArticulationLink(*child); // Adds joint too
+
+ linkStack[stackSize] = child;
+ stackSize++;
+ }
+
+ curLink++;
+ }
+
+ if ((scbArt.getWakeCounter() == 0.0f) && linkTriggersWakeUp)
+ {
+ // this is for the buffered insert case, where the articulation needs to wake up, if one of the links triggers activation.
+ npa.wakeUpInternal(true, false);
+ }
+
+ mArticulations.insert(&npa);
+}
+
+void NpScene::removeArticulation(PxArticulation& articulation, bool wakeOnLostTouch)
+{
+ PX_PROFILE_ZONE("API.removeArticulation", getContextId());
+ NP_WRITE_CHECK(this);
+
+ if (removeFromSceneCheck(this, articulation.getScene(), "PxScene::removeArticulation(): Articulation"))
+ {
+ removeArticulationInternal(articulation, wakeOnLostTouch, true);
+ }
+}
+
+void NpScene::removeArticulationInternal(PxArticulation& articulation, bool wakeOnLostTouch, bool removeFromAggregate)
+{
+ NpArticulation& npa = static_cast<NpArticulation&>(articulation);
+
+ PxU32 nbLinks = npa.getNbLinks();
+ PX_ASSERT(nbLinks > 0);
+
+ if(removeFromAggregate && articulation.getAggregate())
+ {
+ static_cast<NpAggregate*>(articulation.getAggregate())->removeArticulationAndReinsert(articulation, false);
+ PX_ASSERT(!articulation.getAggregate());
+ }
+
+ //!!!AL
+ // Inefficient. We might want to introduce a LL method to kill the whole LL articulation together with all joints in one go, then
+ // the order of removing the links/joints does not matter anymore.
+
+ // Remove links & joints
+ PX_ALLOCA(linkStack, NpArticulationLink*, nbLinks);
+ linkStack[0] = npa.getLinks()[0];
+ PxU32 curLink = 0, stackSize = 1;
+
+ while(curLink < (nbLinks-1))
+ {
+ PX_ASSERT(curLink < stackSize);
+ NpArticulationLink* l = linkStack[curLink];
+ NpArticulationLink*const* children = l->getChildren();
+
+ for(PxU32 i=0; i < l->getNbChildren(); i++)
+ {
+ linkStack[stackSize] = children[i];
+ stackSize++;
+ }
+
+ curLink++;
+ }
+
+ PxRigidBodyFlags flag;
+ for(PxI32 j=PxI32(nbLinks); j-- > 0; )
+ {
+ flag |=linkStack[j]->getScbBodyFast().getScBody().getCore().mFlags;
+ removeArticulationLink(*linkStack[j], wakeOnLostTouch);
+ }
+
+ if (flag & PxRigidBodyFlag::eENABLE_SPECULATIVE_CCD)
+ {
+ IG::NodeIndex index = npa.getScbArticulation().getScArticulation().getIslandNodeIndex();
+ if (index.isValid())
+ mScene.getScScene().resetSpeculativeCCDArticulationLink(index.index());
+ }
+ // Remove articulation
+ mScene.removeArticulation(npa.getArticulation());
+
+
+ removeFromArticulationList(articulation);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::addArticulationLinkBody(NpArticulationLink& link)
+{
+ mScene.addActor(link.getScbBodyFast(), false, NULL);
+ link.getShapeManager().setupAllSceneQuery(this, link, false);
+}
+
+void NpScene::addArticulationLinkConstraint(NpArticulationLink& link)
+{
+ NpArticulationJoint* j = static_cast<NpArticulationJoint*>(link.getInboundJoint());
+ if (j)
+ mScene.addArticulationJoint(j->getScbArticulationJoint());
+
+ link.addConstraintsToScene();
+}
+
+void NpScene::addArticulationLink(NpArticulationLink& link)
+{
+ addArticulationLinkBody(link);
+ addArticulationLinkConstraint(link);
+}
+
+void NpScene::removeArticulationLink(NpArticulationLink& link, bool wakeOnLostTouch)
+{
+ NpArticulationJoint* j = static_cast<NpArticulationJoint*>(link.getInboundJoint());
+
+ link.removeConstraintsFromScene();
+ link.getShapeManager().teardownAllSceneQuery(getSceneQueryManagerFast());
+
+ if (j)
+ mScene.removeArticulationJoint(j->getScbArticulationJoint());
+
+ mScene.removeActor(link.getScbBodyFast(), wakeOnLostTouch, false);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// PX_AGGREGATE
+
+void NpScene::addAggregate(PxAggregate& aggregate)
+{
+ PX_PROFILE_ZONE("API.addAggregate", getContextId());
+ NP_WRITE_CHECK(this);
+ PX_SIMD_GUARD;
+
+ NpAggregate& np = static_cast<NpAggregate&>(aggregate);
+
+ const PxU32 nb = np.getCurrentSizeFast();
+#if PX_CHECKED
+ for(PxU32 i=0;i<nb;i++)
+ {
+ PxRigidStatic* a = np.getActorFast(i)->is<PxRigidStatic>();
+ if(a && !static_cast<NpRigidStatic*>(a)->checkConstraintValidity())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addAggregate(): Aggregate contains an actor with an invalid constraint!");
+ return;
+ }
+ }
+#endif
+
+ Scb::Aggregate& agg = np.getScbAggregate();
+ Scb::ControlState::Enum cs = agg.getControlState();
+ if ((cs == Scb::ControlState::eNOT_IN_SCENE) || ((cs == Scb::ControlState::eREMOVE_PENDING) && (agg.getScbScene()->getPxScene() == this)))
+ {
+ mScene.addAggregate(agg);
+
+ for(PxU32 i=0;i<nb;i++)
+ {
+ PX_ASSERT(np.getActorFast(i));
+ np.addActorInternal(*np.getActorFast(i), *this);
+ }
+
+ mAggregates.insert(&aggregate);
+ }
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addAggregate(): Aggregate already assigned to a scene. Call will be ignored!");
+}
+
+void NpScene::removeAggregate(PxAggregate& aggregate, bool wakeOnLostTouch)
+{
+ PX_PROFILE_ZONE("API.removeAggregate", getContextId());
+ NP_WRITE_CHECK(this);
+ if(!removeFromSceneCheck(this, aggregate.getScene(), "PxScene::removeAggregate(): Aggregate"))
+ return;
+
+ NpAggregate& np = static_cast<NpAggregate&>(aggregate);
+ if(np.getScene()!=this)
+ return;
+
+ const PxU32 nb = np.getCurrentSizeFast();
+ for(PxU32 j=0;j<nb;j++)
+ {
+ PxActor* a = np.getActorFast(j);
+ PX_ASSERT(a);
+
+ if (a->getType() != PxActorType::eARTICULATION_LINK)
+ {
+ Scb::Actor& scb = NpActor::getScbFromPxActor(*a);
+
+ np.getScbAggregate().removeActor(scb, false); // This is only here to make sure the aggregateID gets set to invalid on sync
+
+ removeActorInternal(*a, wakeOnLostTouch, false);
+ }
+ else if (a->getScene())
+ {
+ NpArticulationLink& al = static_cast<NpArticulationLink&>(*a);
+ NpArticulation& npArt = al.getRoot();
+ NpArticulationLink* const* links = npArt.getLinks();
+ for(PxU32 i=0; i < npArt.getNbLinks(); i++)
+ {
+ np.getScbAggregate().removeActor(links[i]->getScbActorFast(), false); // This is only here to make sure the aggregateID gets set to invalid on sync
+ }
+
+ removeArticulationInternal(npArt, wakeOnLostTouch, false);
+ }
+ }
+
+ mScene.removeAggregate(np.getScbAggregate());
+
+ removeFromAggregateList(aggregate);
+}
+
+PxU32 NpScene::getNbAggregates() const
+{
+ NP_READ_CHECK(this);
+ return mAggregates.size();
+}
+
+PxU32 NpScene::getAggregates(PxAggregate** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(this);
+ return Cm::getArrayOfPointers(userBuffer, bufferSize, startIndex, mAggregates.getEntries(), mAggregates.size());
+}
+
+//~PX_AGGREGATE
+
+void NpScene::addCollection(const PxCollection& collection)
+{
+ PX_PROFILE_ZONE("API.addCollection", getContextId());
+ const Cm::Collection& col = static_cast<const Cm::Collection&>(collection);
+
+ PxU32 nb = col.internalGetNbObjects();
+#if PX_CHECKED
+ for(PxU32 i=0;i<nb;i++)
+ {
+ PxRigidStatic* a = col.internalGetObject(i)->is<PxRigidStatic>();
+ if(a && !static_cast<NpRigidStatic*>(a)->checkConstraintValidity())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::addCollection(): collection contains an actor with an invalid constraint!");
+ return;
+ }
+ }
+#endif
+
+ Ps::Array<PxActor*> actorsToInsert;
+ actorsToInsert.reserve(nb);
+
+ struct Local
+ {
+ static void addActorIfNeeded(PxActor* actor, Ps::Array<PxActor*>& actorArray)
+ {
+ if(actor->getAggregate())
+ return; // The actor will be added when the aggregate is added
+ actorArray.pushBack(actor);
+ }
+ };
+
+ for(PxU32 i=0;i<nb;i++)
+ {
+ PxBase* s = col.internalGetObject(i);
+ const PxType serialType = s->getConcreteType();
+
+ //NpArticulationLink, NpArticulationJoint are added with the NpArticulation
+ //Actors and Articulations that are members of an Aggregate are added with the NpAggregate
+
+ if(serialType==PxConcreteType::eRIGID_DYNAMIC)
+ {
+ NpRigidDynamic* np = static_cast<NpRigidDynamic*>(s);
+ // if pruner structure exists for the actor, actor will be added with the pruner structure
+ if(!np->getShapeManager().getPruningStructure())
+ Local::addActorIfNeeded(np, actorsToInsert);
+ }
+ else if(serialType==PxConcreteType::eRIGID_STATIC)
+ {
+ NpRigidStatic* np = static_cast<NpRigidStatic*>(s);
+ // if pruner structure exists for the actor, actor will be added with the pruner structure
+ if(!np->getShapeManager().getPruningStructure())
+ Local::addActorIfNeeded(np, actorsToInsert);
+ }
+ else if(serialType==PxConcreteType::eSHAPE)
+ {
+ }
+#if PX_USE_CLOTH_API
+ else if (serialType==PxConcreteType::eCLOTH)
+ {
+ NpCloth* np = static_cast<NpCloth*>(s);
+ Local::addActorIfNeeded(np, actorsToInsert);
+ }
+#endif
+#if PX_USE_PARTICLE_SYSTEM_API
+ else if(serialType==PxConcreteType::ePARTICLE_SYSTEM)
+ {
+ NpParticleSystem* np = static_cast<NpParticleSystem*>(s);
+ Local::addActorIfNeeded(np, actorsToInsert);
+ }
+ else if(serialType==PxConcreteType::ePARTICLE_FLUID)
+ {
+ NpParticleFluid* np = static_cast<NpParticleFluid*>(s);
+ Local::addActorIfNeeded(np, actorsToInsert);
+ }
+#endif
+ else if(serialType==PxConcreteType::eARTICULATION)
+ {
+ NpArticulation* np = static_cast<NpArticulation*>(s);
+ if(!np->getAggregate()) // The actor will be added when the aggregate is added
+ addArticulation(*np);
+ }
+ else if(serialType==PxConcreteType::eAGGREGATE)
+ {
+ NpAggregate* np = static_cast<NpAggregate*>(s);
+ addAggregate(*np);
+ }
+ else if(serialType == PxConcreteType::ePRUNING_STRUCTURE)
+ {
+ PxPruningStructure* ps = static_cast<PxPruningStructure*>(s);
+ addActors(*ps);
+ }
+ }
+
+ if(!actorsToInsert.empty())
+ addActorsInternal(&actorsToInsert[0], actorsToInsert.size(), NULL);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxU32 NpScene::getNbActors(PxActorTypeFlags types) const
+{
+ NP_READ_CHECK(this);
+ PxU32 nbActors = 0;
+
+ if (types & PxActorTypeFlag::eRIGID_STATIC)
+ {
+ for(PxU32 i=mRigidActors.size(); i--;)
+ {
+ if (mRigidActors[i]->is<PxRigidStatic>())
+ nbActors++;
+ }
+ }
+
+ if (types & PxActorTypeFlag::eRIGID_DYNAMIC)
+ {
+ for(PxU32 i=mRigidActors.size(); i--;)
+ {
+ if (mRigidActors[i]->is<PxRigidDynamic>())
+ nbActors++;
+ }
+ }
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ if (types & PxActorTypeFlag::ePARTICLE_SYSTEM)
+ {
+ PxParticleBase*const* particles = mPxParticleBaseSet.getEntries();
+ const PxU32 particleBaseCount = mPxParticleBaseSet.size();
+ for(PxU32 i=0; i < particleBaseCount; i++)
+ {
+ if (particles[i]->is<PxParticleSystem>())
+ nbActors++;
+ }
+ }
+
+ if (types & PxActorTypeFlag::ePARTICLE_FLUID)
+ {
+ PxParticleBase*const* particles = mPxParticleBaseSet.getEntries();
+ const PxU32 particleBaseCount = mPxParticleBaseSet.size();
+ for(PxU32 i=0; i < particleBaseCount; i++)
+ {
+ if (particles[i]->is<PxParticleFluid>())
+ nbActors++;
+ }
+ }
+#endif
+
+#if PX_USE_CLOTH_API
+ if (types & PxActorTypeFlag::eCLOTH)
+ {
+ nbActors += mPxCloths.size();
+ }
+#endif
+
+ return nbActors;
+}
+
+PxU32 NpScene::getActors(PxActorTypeFlags types, PxActor** buffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(this);
+
+ PxU32 writeCount = 0;
+ PxU32 virtualIndex = 0; // PT: virtual index of actor, continuous across different actor containers.
+
+ if(types & (PxActorTypeFlag::eRIGID_STATIC | PxActorTypeFlag::eRIGID_DYNAMIC))
+ {
+ const PxU32 size = mRigidActors.size();
+ for(PxU32 i=0; (i < size) && (writeCount < bufferSize); i++)
+ {
+ if ((types & PxActorTypeFlag::eRIGID_STATIC ) && mRigidActors[i]->is<PxRigidStatic>())
+ {
+ if (virtualIndex >= startIndex)
+ buffer[writeCount++] = mRigidActors[i];
+ virtualIndex++;
+ }
+ else if ((types & PxActorTypeFlag::eRIGID_DYNAMIC) && mRigidActors[i]->is<PxRigidDynamic>())
+ {
+ if (virtualIndex >= startIndex)
+ buffer[writeCount++] = mRigidActors[i];
+ virtualIndex++;
+ }
+ }
+ }
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ if (types & (PxActorTypeFlag::ePARTICLE_SYSTEM | PxActorTypeFlag::ePARTICLE_FLUID))
+ {
+ const PxU32 size = mPxParticleBaseSet.size();
+ PxParticleBase*const* particles = mPxParticleBaseSet.getEntries();
+ for(PxU32 i=0; (i < size) && (writeCount < bufferSize); i++)
+ {
+ if ((types & PxActorTypeFlag::ePARTICLE_SYSTEM ) && particles[i]->is<PxParticleSystem>())
+ {
+ if (virtualIndex >= startIndex)
+ buffer[writeCount++] = particles[i];
+ virtualIndex++;
+ }
+ else if ((types & PxActorTypeFlag::ePARTICLE_FLUID) && particles[i]->is<PxParticleFluid>())
+ {
+ if (virtualIndex >= startIndex)
+ buffer[writeCount++] = particles[i];
+ virtualIndex++;
+ }
+ }
+ }
+
+#endif
+
+#if PX_USE_CLOTH_API
+ if (types & PxActorTypeFlag::eCLOTH)
+ {
+ const PxU32 size = mPxCloths.size();
+ PxCloth*const* clothList = mPxCloths.getEntries();
+ for(PxU32 i=0; (i < size) && (writeCount < bufferSize); i++)
+ {
+ if(virtualIndex>=startIndex)
+ buffer[writeCount++] = clothList[i];
+ virtualIndex++;
+ }
+ }
+#endif
+
+ return writeCount;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PX_DEPRECATED const PxActiveTransform* NpScene::getActiveTransforms(PxU32& nbTransformsOut, PxClientID client)
+{
+ NP_READ_CHECK(this);
+ return mScene.getActiveTransforms(nbTransformsOut, client);
+}
+
+PxActor** NpScene::getActiveActors(PxU32& nbActorsOut, PxClientID client)
+{
+ NP_READ_CHECK(this);
+ return mScene.getActiveActors(nbActorsOut, client);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxU32 NpScene::getNbArticulations() const
+{
+ NP_READ_CHECK(this);
+ return mArticulations.size();
+}
+
+PxU32 NpScene::getArticulations(PxArticulation** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(this);
+ return Cm::getArrayOfPointers(userBuffer, bufferSize, startIndex, mArticulations.getEntries(), mArticulations.size());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxU32 NpScene::getNbConstraints() const
+{
+ NP_READ_CHECK(this);
+ return mConstraints.size();
+}
+
+PxU32 NpScene::getConstraints(PxConstraint** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(this);
+ return Cm::getArrayOfPointers(userBuffer, bufferSize, startIndex, mConstraints.getEntries(), mConstraints.size());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+const PxRenderBuffer& NpScene::getRenderBuffer()
+{
+ if (getSimulationStage() != Sc::SimulationStage::eCOMPLETE)
+ {
+ // will be reading the Sc::Scene renderable which is getting written
+ // during the sim, hence, avoid call while simulation is running.
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxScene::getRenderBuffer() not allowed while simulation is running.");
+ }
+
+ return mRenderBuffer;
+}
+
+void NpScene::visualize()
+{
+ NP_READ_CHECK(this);
+
+ mRenderBuffer.clear(); // clear last frame visualizations
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+ if(getVisualizationParameter(PxVisualizationParameter::eSCALE) == 0.0f)
+ return;
+
+ Cm::RenderOutput out(mRenderBuffer);
+
+ // Visualize scene axis
+ const PxReal worldAxes = getVisualizationParameter(PxVisualizationParameter::eWORLD_AXES);
+ if (worldAxes != 0)
+ out << Cm::DebugBasis(PxVec3(worldAxes));
+
+ // Visualize articulations
+ for(PxU32 i=0;i<mArticulations.size();i++)
+ static_cast<NpArticulation *>(mArticulations.getEntries()[i])->visualize(out, this);
+
+ // Visualize rigid actors and rigid bodies
+ PxRigidActor*const* rigidActors = mRigidActors.begin();
+ const PxU32 rigidActorCount = mRigidActors.size();
+
+#if PX_USE_CLOTH_API
+ // Visualize cloths
+ for(PxU32 i=0;i<mPxCloths.size();i++)
+ static_cast<NpCloth*>(mPxCloths.getEntries()[i])->visualize(out, this);
+#endif
+
+ for(PxU32 i=0; i < rigidActorCount; i++)
+ {
+ PxRigidActor* a = rigidActors[i];
+ if (a->getType() == PxActorType::eRIGID_DYNAMIC)
+ static_cast<NpRigidDynamic*>(a)->visualize(out, this);
+ else
+ static_cast<NpRigidStatic*>(a)->visualize(out, this);
+ }
+
+ // Visualize pruning structures
+ const bool visStatic = getVisualizationParameter(PxVisualizationParameter::eCOLLISION_STATIC) != 0.0f;
+ const bool visDynamic = getVisualizationParameter(PxVisualizationParameter::eCOLLISION_DYNAMIC) != 0.0f;
+ //flushQueryUpdates(); // DE7834
+ if(visStatic && mSQManager.get(PruningIndex::eSTATIC).pruner())
+ mSQManager.get(PruningIndex::eSTATIC).pruner()->visualize(out, PxU32(PxDebugColor::eARGB_BLUE));
+ if(visDynamic && mSQManager.get(PruningIndex::eDYNAMIC).pruner())
+ mSQManager.get(PruningIndex::eDYNAMIC).pruner()->visualize(out, PxU32(PxDebugColor::eARGB_RED));
+
+ if(getVisualizationParameter(PxVisualizationParameter::eMBP_REGIONS) != 0.0f)
+ {
+ out << PxTransform(PxIdentity);
+
+ const PxU32 nbRegions = mScene.getNbBroadPhaseRegions();
+ for(PxU32 i=0;i<nbRegions;i++)
+ {
+ PxBroadPhaseRegionInfo info;
+ mScene.getBroadPhaseRegions(&info, 1, i);
+
+ if(info.active)
+ out << PxU32(PxDebugColor::eARGB_YELLOW);
+ else
+ out << PxU32(PxDebugColor::eARGB_BLACK);
+ out << Cm::DebugBox(info.region.bounds);
+ }
+ }
+
+#if PX_SUPPORT_PVD
+ mScene.getScenePvdClient().visualize(mRenderBuffer);
+#endif
+#endif
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::getSimulationStatistics(PxSimulationStatistics& s) const
+{
+ NP_READ_CHECK(this);
+
+ if (getSimulationStage() == Sc::SimulationStage::eCOMPLETE)
+ {
+#if PX_ENABLE_SIM_STATS
+ mScene.getStats(s);
+#else
+ PX_UNUSED(s);
+#endif
+ }
+ else
+ {
+ //will be reading data that is getting written during the sim, hence, avoid call while simulation is running.
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::getSimulationStatistics() not allowed while simulation is running. Call will be ignored.");
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+//Multiclient
+
+PxClientID NpScene::createClient()
+{
+ NP_WRITE_CHECK(this);
+
+ PX_CHECK_AND_RETURN_NULL(mNbClients < PX_MAX_CLIENTS, "PxScene::createClient: Maximum number of clients reached! No new client created.");
+ mNbClients++; //track this just for error checking
+ return mScene.createClient();
+}
+
+void NpScene::setClientBehaviorFlags(PxClientID client, PxClientBehaviorFlags clientBehaviorFlags)
+{
+ NP_WRITE_CHECK(this);
+
+ PX_CHECK_AND_RETURN(client < mNbClients, "PxScene::setClientBehaviorFlags: bad clientID! Please create clientIDs with PxScene::createClient().");
+ mScene.setClientBehaviorFlags(client, clientBehaviorFlags);
+}
+
+PxClientBehaviorFlags NpScene::getClientBehaviorFlags(PxClientID client) const
+{
+ NP_READ_CHECK(this);
+ PX_CHECK_AND_RETURN_VAL(client < mNbClients, "PxScene::getClientBehaviorFlags: bad clientID! Please create clientIDs with PxScene::createClient().", PxClientBehaviorFlags());
+ return mScene.getClientBehaviorFlags(client);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+//FrictionModel
+
+void NpScene::setFrictionType(PxFrictionType::Enum frictionType)
+{
+ NP_WRITE_CHECK(this);
+ PX_CHECK_AND_RETURN(!mHasSimulatedOnce, "PxScene::setFrictionType: This flag can only be set before calling Simulate() or Collide() for the first time");
+ mScene.setFrictionType(frictionType);
+}
+
+PxFrictionType::Enum NpScene::getFrictionType() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getFrictionType();
+}
+
+#if PX_USE_CLOTH_API
+
+///////////////////////////////////////////////////////////////////////////////
+
+//Cloth
+
+void NpScene::setClothInterCollisionDistance(PxF32 distance)
+{
+ NP_WRITE_CHECK(this);
+ PX_CHECK_AND_RETURN(distance >= 0.0f, "PxScene::setClothInterCollisionDistance: distance must be non-negative.");
+ mScene.setClothInterCollisionDistance(distance);
+}
+
+PxF32 NpScene::getClothInterCollisionDistance() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getClothInterCollisionDistance();
+}
+
+void NpScene::setClothInterCollisionStiffness(PxF32 stiffness)
+{
+ NP_WRITE_CHECK(this);
+ PX_CHECK_AND_RETURN(stiffness >= 0.0f, "PxScene::setClothInterCollisionStiffness: stiffness must be non-negative.");
+ return mScene.setClothInterCollisionStiffness(stiffness);
+}
+
+PxF32 NpScene::getClothInterCollisionStiffness() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getClothInterCollisionStiffness();
+}
+
+void NpScene::setClothInterCollisionNbIterations(PxU32 nbIterations)
+{
+ NP_WRITE_CHECK(this);
+ mScene.setClothInterCollisionNbIterations(nbIterations);
+}
+
+PxU32 NpScene::getClothInterCollisionNbIterations() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getClothInterCollisionNbIterations();
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Callbacks
+
+void NpScene::setSimulationEventCallback(PxSimulationEventCallback* callback, PxClientID client)
+{
+ NP_WRITE_CHECK(this);
+ mScene.setSimulationEventCallback(callback, client);
+}
+
+PxSimulationEventCallback* NpScene::getSimulationEventCallback(PxClientID client) const
+{
+ NP_READ_CHECK(this);
+ return mScene.getSimulationEventCallback(client);
+}
+
+void NpScene::setContactModifyCallback(PxContactModifyCallback* callback)
+{
+ NP_WRITE_CHECK(this);
+ mScene.setContactModifyCallback(callback);
+}
+
+PxContactModifyCallback* NpScene::getContactModifyCallback() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getContactModifyCallback();
+}
+
+void NpScene::setCCDContactModifyCallback(PxCCDContactModifyCallback* callback)
+{
+ NP_WRITE_CHECK(this);
+ mScene.setCCDContactModifyCallback(callback);
+}
+
+PxCCDContactModifyCallback* NpScene::getCCDContactModifyCallback() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getCCDContactModifyCallback();
+}
+
+void NpScene::setBroadPhaseCallback(PxBroadPhaseCallback* callback, PxClientID client)
+{
+ NP_WRITE_CHECK(this);
+ mScene.setBroadPhaseCallback(callback, client);
+}
+
+PxBroadPhaseCallback* NpScene::getBroadPhaseCallback(PxClientID client) const
+{
+ NP_READ_CHECK(this);
+ return mScene.getBroadPhaseCallback(client);
+}
+
+void NpScene::setCCDMaxPasses(PxU32 ccdMaxPasses)
+{
+ NP_WRITE_CHECK(this);
+ mScene.setCCDMaxPasses(ccdMaxPasses);
+}
+
+PxU32 NpScene::getCCDMaxPasses() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getCCDMaxPasses();
+}
+
+PxBroadPhaseType::Enum NpScene::getBroadPhaseType() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getBroadPhaseType();
+}
+
+bool NpScene::getBroadPhaseCaps(PxBroadPhaseCaps& caps) const
+{
+ NP_READ_CHECK(this);
+ return mScene.getBroadPhaseCaps(caps);
+}
+
+PxU32 NpScene::getNbBroadPhaseRegions() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getNbBroadPhaseRegions();
+}
+
+PxU32 NpScene::getBroadPhaseRegions(PxBroadPhaseRegionInfo* userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(this);
+ return mScene.getBroadPhaseRegions(userBuffer, bufferSize, startIndex);
+}
+
+PxU32 NpScene::addBroadPhaseRegion(const PxBroadPhaseRegion& region, bool populateRegion)
+{
+ PX_PROFILE_ZONE("BroadPhase.addBroadPhaseRegion", getContextId());
+
+ NP_WRITE_CHECK(this);
+
+ PX_CHECK_MSG(region.bounds.isValid(), "PxScene::addBroadPhaseRegion(): invalid bounds provided!");
+ if(region.bounds.isEmpty())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxScene::addBroadPhaseRegion(): region bounds are empty. Call will be ignored.");
+ return 0xffffffff;
+ }
+
+ return mScene.addBroadPhaseRegion(region, populateRegion);
+}
+
+bool NpScene::removeBroadPhaseRegion(PxU32 handle)
+{
+ NP_WRITE_CHECK(this);
+ return mScene.removeBroadPhaseRegion(handle);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Filtering
+void NpScene::setFilterShaderData(const void* data, PxU32 dataSize)
+{
+ NP_WRITE_CHECK(this);
+
+ PX_CHECK_AND_RETURN(( ((dataSize == 0) && (data == NULL)) ||
+ ((dataSize > 0) && (data != NULL)) ), "PxScene::setFilterShaderData(): data pointer must not be NULL unless the specified data size is 0 too and vice versa.");
+
+ mScene.setFilterShaderData(data, dataSize);
+}
+
+const void* NpScene::getFilterShaderData() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getFilterShaderData();
+}
+
+PxU32 NpScene::getFilterShaderDataSize() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getFilterShaderDataSize();
+}
+
+PxSimulationFilterShader NpScene::getFilterShader() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getFilterShader();
+}
+
+PxSimulationFilterCallback* NpScene::getFilterCallback() const
+{
+ NP_READ_CHECK(this);
+ return mScene.getFilterCallback();
+}
+
+void NpScene::resetFiltering(PxActor& actor)
+{
+ NP_WRITE_CHECK(this);
+
+ PX_CHECK_AND_RETURN(NpActor::getAPIScene(actor) && (NpActor::getAPIScene(actor) == this), "PxScene::resetFiltering(): actor not in scene!");
+
+ switch(actor.getConcreteType())
+ {
+ case PxConcreteType::eRIGID_STATIC:
+ {
+ NpRigidStatic& npStatic = static_cast<NpRigidStatic&>(actor);
+ npStatic.resetFiltering(npStatic.getScbRigidStaticFast(), NULL, 0);
+ }
+ break;
+
+ case PxConcreteType::eRIGID_DYNAMIC:
+ {
+ NpRigidDynamic& npDynamic = static_cast<NpRigidDynamic&>(actor);
+ if (npDynamic.resetFiltering(npDynamic.getScbBodyFast(), NULL, 0))
+ npDynamic.wakeUpInternal();
+ }
+ break;
+
+ case PxConcreteType::eARTICULATION_LINK:
+ {
+ NpArticulationLink& npLink = static_cast<NpArticulationLink&>(actor);
+ if (npLink.resetFiltering(npLink.getScbBodyFast(), NULL, 0))
+ npLink.getRoot().wakeUpInternal(false, true);
+ }
+ break;
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ case PxConcreteType::ePARTICLE_SYSTEM:
+ {
+ NpParticleSystem& npSystem = static_cast<NpParticleSystem&>(actor);
+ npSystem.getScbParticleSystem().resetFiltering();
+ }
+ break;
+
+ case PxConcreteType::ePARTICLE_FLUID:
+ {
+ NpParticleFluid& npFluid = static_cast<NpParticleFluid&>(actor);
+ npFluid.getScbParticleSystem().resetFiltering();
+ }
+ break;
+#endif
+
+ default:
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxScene::resetFiltering(): only PxParticleBase and PxRigidActor support this operation!");
+ }
+}
+
+void NpScene::resetFiltering(PxRigidActor& actor, PxShape*const* shapes, PxU32 shapeCount)
+{
+ NP_WRITE_CHECK(this);
+ PX_CHECK_AND_RETURN(NpActor::getAPIScene(actor) && (NpActor::getAPIScene(actor) == this), "PxScene::resetFiltering(): actor not in scene!");
+ PX_SIMD_GUARD;
+
+ switch(actor.getConcreteType())
+ {
+ case PxConcreteType::eRIGID_STATIC:
+ {
+ NpRigidStatic& npStatic = static_cast<NpRigidStatic&>(actor);
+ npStatic.resetFiltering(npStatic.getScbRigidStaticFast(), shapes, shapeCount);
+ }
+ break;
+
+ case PxConcreteType::eRIGID_DYNAMIC:
+ {
+ NpRigidDynamic& npDynamic = static_cast<NpRigidDynamic&>(actor);
+ if (npDynamic.resetFiltering(npDynamic.getScbBodyFast(), shapes, shapeCount))
+ npDynamic.wakeUpInternal();
+ }
+ break;
+
+ case PxConcreteType::eARTICULATION_LINK:
+ {
+ NpArticulationLink& npLink = static_cast<NpArticulationLink&>(actor);
+ if (npLink.resetFiltering(npLink.getScbBodyFast(), shapes, shapeCount))
+ npLink.getRoot().wakeUpInternal(false, true);
+ }
+ break;
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxPhysics& NpScene::getPhysics()
+{
+ return NpPhysics::getInstance();
+}
+
+void NpScene::updateDirtyShaders()
+{
+ PX_PROFILE_ZONE("Sim.updateDirtyShaders", getContextId());
+ // this should continue to be done in the Np layer even after SC has taken over
+ // all vital simulation functions, because it needs to complete before simulate()
+ // returns to the application
+
+ // However, the implementation needs fixing so that it does work proportional to
+ // the number of dirty shaders
+
+ PxConstraint*const* constraints = mConstraints.getEntries();
+ for(PxU32 i=0;i<mConstraints.size();i++)
+ {
+ static_cast<NpConstraint*>(constraints[i])->updateConstants();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void NpScene::simulateOrCollide(PxReal elapsedTime, physx::PxBaseTask* completionTask, void* scratchBlock, PxU32 scratchBlockSize, bool controlSimulation, const char* invalidCallMsg, Sc::SimulationStage::Enum simStage)
+{
+ PX_SIMD_GUARD;
+
+ {
+ // write guard must end before simulation kicks off worker threads
+ // otherwise the simulation callbacks could overlap with this function
+ // and perform API reads,triggering an error
+ NP_WRITE_CHECK(this);
+
+ PX_PROFILE_START_CROSSTHREAD("Basic.simulate", getContextId());
+
+ if(getSimulationStage() != Sc::SimulationStage::eCOMPLETE)
+ {
+ //fetchResult doesn't get called
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, invalidCallMsg);
+ return;
+ }
+
+ PX_CHECK_AND_RETURN(elapsedTime > 0, "PxScene::collide/simulate: The elapsed time must be positive!");
+
+ PX_CHECK_AND_RETURN((reinterpret_cast<size_t>(scratchBlock)&15) == 0, "PxScene::simulate: scratch block must be 16-byte aligned!");
+
+ PX_CHECK_AND_RETURN((scratchBlockSize&16383) == 0, "PxScene::simulate: scratch block size must be a multiple of 16K");
+
+#if PX_SUPPORT_PVD
+ //signal the frame is starting.
+ mScene.getScenePvdClient().frameStart(elapsedTime);
+#endif
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+ visualize();
+#endif
+
+ updateDirtyShaders();
+
+#if PX_SUPPORT_PVD
+ mScene.getScenePvdClient().updateJoints();
+#endif
+
+ mScene.getScScene().setScratchBlock(scratchBlock, scratchBlockSize);
+
+ mElapsedTime = elapsedTime;
+ if (simStage == Sc::SimulationStage::eCOLLIDE)
+ mScene.getScScene().setElapsedTime(elapsedTime);
+
+ mControllingSimulation = controlSimulation;
+
+ //sync all the material events
+ NpPhysics& physics = static_cast<NpPhysics&>(this->getPhysics());
+ NpMaterialManager& manager = physics.getMaterialManager();
+ NpMaterial** materials = manager.getMaterials();
+ mScene.updateLowLevelMaterial(materials);
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ mScene.preSimulateUpdateAppThread(elapsedTime);
+#endif
+
+ setSimulationStage(simStage);
+ mScene.setPhysicsBuffering(true);
+ mHasSimulatedOnce = true;
+ }
+
+ {
+ PX_PROFILE_ZONE("Sim.taskFrameworkSetup", getContextId());
+
+ if (controlSimulation)
+ {
+ {
+ PX_PROFILE_ZONE("Sim.resetDependencies", getContextId());
+ // Only reset dependencies, etc if we own the TaskManager. Will be false
+ // when an NpScene is controlled by an APEX scene.
+ mTaskManager->resetDependencies();
+ }
+ mTaskManager->startSimulation();
+ }
+
+ if (simStage == Sc::SimulationStage::eCOLLIDE)
+ {
+ mCollisionCompletion.setContinuation(*mTaskManager, completionTask);
+ mSceneCollide.setContinuation(&mCollisionCompletion);
+ //Initialize scene completion task
+ mSceneCompletion.setContinuation(*mTaskManager, NULL);
+ }
+ else
+ {
+ mSceneCompletion.setContinuation(*mTaskManager, completionTask);
+ mSceneExecution.setContinuation(*mTaskManager, &mSceneCompletion);
+ }
+
+#if PX_SUPPORT_GPU_PHYSX
+ //workaround to prevent premature launching of gpu launch task
+ if (PxGpuDispatcher* gpuDispatcher = getGpuDispatcher())
+ {
+ //GPU pre-launch task must complete before scene completion can run
+ gpuDispatcher->addPreLaunchDependent(mSceneCompletion);
+ }
+#endif
+
+ if (simStage == Sc::SimulationStage::eCOLLIDE)
+ {
+ mCollisionCompletion.removeReference();
+ mSceneCollide.removeReference();
+ }
+ else
+ {
+ mSceneCompletion.removeReference();
+ mSceneExecution.removeReference();
+ }
+ }
+}
+
+void NpScene::simulate(PxReal elapsedTime, physx::PxBaseTask* completionTask, void* scratchBlock, PxU32 scratchBlockSize, bool controlSimulation)
+{
+ simulateOrCollide( elapsedTime, completionTask, scratchBlock, scratchBlockSize, controlSimulation,
+ "PxScene::simulate: Simulation is still processing last simulate call, you should call fetchResults()!", Sc::SimulationStage::eADVANCE);
+}
+
+void NpScene::advance( physx::PxBaseTask* completionTask)
+{
+ NP_WRITE_CHECK(this);
+ //issue error if advance() doesn't get called between fetchCollision() and fetchResult()
+ if(getSimulationStage() != Sc::SimulationStage::eFETCHCOLLIDE)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::advance: advance() called illegally! advance() needed to be called after fetchCollision() and before fetchResult()!!");
+ return;
+ }
+
+ //apply buffering for forces, velocities, kinematic targets and wake-up events
+ mScene.syncWriteThroughProperties();
+
+ //if mSimulateStage == eFETCHCOLLIDE, which means collide() has been kicked off and finished running, we can run advance() safely
+ {
+ //change the mSimulateStaget to eADVANCE to indicate the next stage to run is fetchResult()
+ setSimulationStage(Sc::SimulationStage::eADVANCE);
+
+ {
+ PX_PROFILE_ZONE("Sim.taskFrameworkSetup", getContextId());
+
+ mSceneCompletion.setDependent(completionTask);
+ mSceneAdvance.setContinuation(*mTaskManager, &mSceneCompletion);
+ mSceneCompletion.removeReference();
+ mSceneAdvance.removeReference();
+ }
+ }
+}
+
+void NpScene::collide(PxReal elapsedTime, physx::PxBaseTask* completionTask, void* scratchBlock, PxU32 scratchBlockSize, bool controlSimulation)
+{
+ simulateOrCollide( elapsedTime,
+ completionTask,
+ scratchBlock,
+ scratchBlockSize,
+ controlSimulation,
+ "PxScene::collide: collide() called illegally! If it isn't the first frame, collide() needed to be called between fetchResults() and fetchCollision(). Otherwise, collide() needed to be called before fetchCollision()",
+ Sc::SimulationStage::eCOLLIDE);
+}
+
+bool NpScene::checkResultsInternal(bool block)
+{
+ PX_PROFILE_ZONE("Basic.checkResults", getContextId());
+ return mPhysicsDone.wait(block ? Ps::Sync::waitForever : 0);
+}
+
+bool NpScene::checkCollisionInternal(bool block)
+{
+ PX_PROFILE_ZONE("Basic.checkCollision", getContextId());
+ return mCollisionDone.wait(block ? Ps::Sync::waitForever : 0);
+}
+
+bool NpScene::checkResults(bool block)
+{
+ return checkResultsInternal(block);
+}
+
+bool NpScene::checkCollision(bool block)
+{
+ return checkCollisionInternal(block);
+}
+
+void NpScene::fireOutOfBoundsCallbacks()
+{
+ PX_PROFILE_ZONE("Sim.fireOutOfBoundsCallbacks", getContextId());
+
+ // Fire broad-phase callbacks
+ {
+ Sc::Scene& scene = mScene.getScScene();
+ using namespace physx::Sc;
+
+ bool outputWarning = scene.fireOutOfBoundsCallbacks();
+
+ // Aggregates
+ {
+ void** outAgg = scene.getOutOfBoundsAggregates();
+ const PxU32 nbOut1 = scene.getNbOutOfBoundsAggregates();
+
+ for(PxU32 i=0;i<nbOut1;i++)
+ {
+ PxAggregate* px = reinterpret_cast<PxAggregate*>(outAgg[i]);
+ NpAggregate* np = static_cast<NpAggregate*>(px);
+ if(np->getScbAggregate().getControlState()==Scb::ControlState::eREMOVE_PENDING)
+ continue;
+
+ // PT: used to avoid calling the callback twice for the same client
+ bool flags[PX_MAX_CLIENTS];
+ PxMemZero(flags, PX_MAX_CLIENTS*sizeof(bool));
+
+ PxU32 nbActors = np->getCurrentSizeFast();
+ for(PxU32 j=0;j<nbActors;j++)
+ {
+ PxActor* pxActor = np->getActorFast(j);
+ const PxClientID clientID = pxActor->getOwnerClient();
+ if(!flags[clientID])
+ {
+ flags[clientID] = true;
+ PxBroadPhaseCallback* cb = scene.getBroadPhaseCallback(clientID);
+ if(cb)
+ {
+ cb->onObjectOutOfBounds(*px);
+ }
+ else
+ {
+ outputWarning = true;
+ }
+ }
+ }
+ }
+ scene.clearOutOfBoundsAggregates();
+ }
+
+ if(outputWarning)
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "At least one object is out of the broadphase bounds. To manage those objects, define a PxBroadPhaseCallback for each used client.");
+ }
+}
+
+bool NpScene::fetchCollision(bool block)
+{
+ if(getSimulationStage() != Sc::SimulationStage::eCOLLIDE)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::fetchCollision: fetchCollision() should be called after collide() and before advance()!");
+ return false;
+ }
+
+ //if collision isn't finish running (and block is false), then return false
+ if(!checkCollisionInternal(block))
+ return false;
+
+ // take write check *after* collision() finished, otherwise
+ // we will block fetchCollision() from using the API
+ NP_WRITE_CHECK_NOREENTRY(this);
+
+ setSimulationStage(Sc::SimulationStage::eFETCHCOLLIDE);
+
+ return true;
+}
+
+class SqRefFinder: public Sc::SqRefFinder
+{
+public:
+ PxU32 find(const PxRigidBody * body, const PxShape* shape)
+ {
+ Sq::PrunerData prunerdata = NpActor::getShapeManager(*body)->findSceneQueryData(*static_cast<const NpShape*>(shape));
+ return Sq::getPrunerHandle(prunerdata);
+ }
+private:
+};
+
+// The order of the following operations is important!
+// 1. Process object deletions which were carried out while the simulation was running (since these effect contact and trigger reports)
+// 2. Write contact reports to global stream (taking pending deletions into account), clear some simulation buffers (deleted objects etc.), ...
+// 3. Send reports which have to be done before the data is synced (contact & trigger reports etc.) such that the user gets the old state.
+// 4. Mark the simulation as not running internally to allow reading data which should not be read otherwise
+// 5. Synchronize the simulation and user state
+// 6. Fire callbacks which need to reflect the synchronized object state
+
+void NpScene::fetchResultsPreContactCallbacks()
+{
+#if PX_SUPPORT_PVD
+ mScene.getScenePvdClient().updateContacts();
+#endif
+
+ mScene.prepareOutOfBoundsCallbacks();
+ mScene.processPendingRemove();
+ mScene.endSimulation();
+
+ {
+ PX_PROFILE_ZONE("Sim.fireCallbacksPreSync", getContextId());
+ fireOutOfBoundsCallbacks(); // fire out-of-bounds callbacks
+ mScene.fireBrokenConstraintCallbacks();
+ mScene.fireTriggerCallbacks();
+ }
+}
+
+void NpScene::fetchResultsPostContactCallbacks()
+{
+ mScene.postCallbacksPreSync();
+ mScene.setPhysicsBuffering(false); // Clear the buffering flag to allow buffered writes to execute immediately. Once collision detection is running, buffering is automatically forced on
+ mScene.syncEntireScene(NULL); // double buffering
+
+ SqRefFinder sqRefFinder;
+ mScene.getScScene().syncSceneQueryBounds(mSQManager.getDynamicBoundsSync(), sqRefFinder);
+
+ mSQManager.afterSync(!(getFlagsFast()&PxSceneFlag::eSUPPRESS_EAGER_SCENE_QUERY_REFIT));
+
+#if PX_DEBUG && 0
+ mSQManager.validateSimUpdates();
+#endif
+
+#if PX_SUPPORT_PVD
+ mScene.getScenePvdClient().updateSceneQueries();
+
+ getSingleSqCollector().clear();
+ getBatchedSqCollector().clear();
+#endif
+
+ // fire sleep and wake-up events
+ // we do this after buffer-swapping so that the events have the new state
+ {
+ PX_PROFILE_ZONE("Sim.fireCallbacksPostSync", getContextId());
+ mScene.fireCallBacksPostSync();
+ }
+
+ mScene.postReportsCleanup();
+
+ // build the list of active transforms
+ {
+ PX_PROFILE_ZONE("Sim.buildActiveTransforms", getContextId());
+ if (mScene.getFlags() & PxSceneFlag::eENABLE_ACTIVETRANSFORMS)
+ mScene.buildActiveTransforms();
+ if (mScene.getFlags() & PxSceneFlag::eENABLE_ACTIVE_ACTORS)
+ mScene.buildActiveActors();
+ }
+
+ mRenderBuffer.append(mScene.getScScene().getRenderBuffer());
+
+ PX_ASSERT(getSimulationStage() != Sc::SimulationStage::eCOMPLETE);
+ if (mControllingSimulation)
+ {
+ mTaskManager->stopSimulation();
+ }
+
+ setSimulationStage(Sc::SimulationStage::eCOMPLETE);
+
+ mPhysicsDone.reset(); // allow Physics to run again
+ mCollisionDone.reset();
+}
+
+bool NpScene::fetchResults(bool block, PxU32* errorState)
+{
+ if(getSimulationStage() != Sc::SimulationStage::eADVANCE)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::fetchResults: fetchResults() called illegally! It must be called after advance() or simulate()");
+ return false;
+ }
+
+ if(!checkResultsInternal(block))
+ return false;
+
+ {
+ PX_SIMD_GUARD;
+
+ // take write check *after* simulation has finished, otherwise
+ // we will block simulation callbacks from using the API
+ // disallow re-entry to detect callbacks making write calls
+ NP_WRITE_CHECK_NOREENTRY(this);
+
+ // we use cross thread profile here, to show the event in cross thread view
+ // PT: TODO: why do we want to show it in the cross thread view?
+ PX_PROFILE_START_CROSSTHREAD("Basic.fetchResults", getContextId());
+ PX_PROFILE_ZONE("Sim.fetchResults", getContextId());
+
+ fetchResultsPreContactCallbacks();
+
+ {
+ // PT: TODO: why a cross-thread event here?
+ PX_PROFILE_START_CROSSTHREAD("Basic.processCallbacks", getContextId());
+ mScene.fireQueuedContactCallbacks();
+ PX_PROFILE_STOP_CROSSTHREAD("Basic.processCallbacks", getContextId());
+ }
+
+ fetchResultsPostContactCallbacks();
+
+ PX_PROFILE_STOP_CROSSTHREAD("Basic.fetchResults", getContextId());
+ PX_PROFILE_STOP_CROSSTHREAD("Basic.simulate", getContextId());
+
+ if(errorState)
+ *errorState = mScene.getScScene().getErrorState();
+ }
+
+#if PX_SUPPORT_PVD
+ mScene.getScenePvdClient().frameEnd();
+#endif
+ return true;
+}
+
+bool NpScene::fetchResultsStart(const PxContactPairHeader*& contactPairs, PxU32& nbContactPairs, bool block)
+{
+ if (getSimulationStage() != Sc::SimulationStage::eADVANCE)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PXScene::fetchResultsStart: fetchResultsStart() called illegally! It must be called after advance() or simulate()");
+ return false;
+ }
+
+ if (!checkResultsInternal(block))
+ return false;
+
+ PX_SIMD_GUARD;
+ NP_WRITE_CHECK(this);
+
+ // we use cross thread profile here, to show the event in cross thread view
+ PX_PROFILE_START_CROSSTHREAD("Basic.fetchResults", getContextId());
+ PX_PROFILE_ZONE("Sim.fetchResultsStart", getContextId());
+
+ fetchResultsPreContactCallbacks();
+ const Ps::Array<PxContactPairHeader>& pairs = mScene.getQueuedContactPairHeaders();
+ nbContactPairs = pairs.size();
+ contactPairs = pairs.begin();
+
+ mBetweenFetchResults = true;
+ return true;
+}
+
+void NpContactCallbackTask::setData(NpScene* scene, const PxContactPairHeader* contactPairHeaders, const uint32_t nbContactPairHeaders)
+{
+ mScene = scene;
+ mContactPairHeaders = contactPairHeaders;
+ mNbContactPairHeaders = nbContactPairHeaders;
+}
+
+void NpContactCallbackTask::run()
+{
+ mScene->lockRead();
+ for (uint32_t i = 0; i < mNbContactPairHeaders; ++i)
+ {
+ const physx::PxContactPairHeader& pairHeader = mContactPairHeaders[i];
+ physx::PxRigidActor* aActor = pairHeader.actors[0];
+ physx::PxRigidActor* bActor = pairHeader.actors[1];
+
+ physx::PxClientID clientActor0 = aActor->getOwnerClient();
+ physx::PxClientID clientActor1 = bActor->getOwnerClient();
+
+ physx::PxSimulationEventCallback* aCallback = mScene->getSimulationEventCallback(clientActor0);
+ physx::PxSimulationEventCallback* bCallback = mScene->getSimulationEventCallback(clientActor1);
+
+ uint8_t actor0ClientBehaviorFlags = aActor->getClientBehaviorFlags();//aPair->getActorAClientBehavior();
+ uint8_t actor1ClientBehaviorFlags = bActor->getClientBehaviorFlags();
+
+ if (aCallback &&
+ (
+ (clientActor0 == clientActor1) //easy common case: the same client owns both shapes
+ || ( //else actor1 has a different owner -- see if we can still send this pair to the client of actor0:
+ (actor0ClientBehaviorFlags & physx::PxClientBehaviorFlag::eREPORT_FOREIGN_OBJECTS_TO_CONTACT_NOTIFY)//this client accepts foreign objects
+ && (actor1ClientBehaviorFlags & physx::PxActorClientBehaviorFlag::eREPORT_TO_FOREIGN_CLIENTS_CONTACT_NOTIFY)//this actor can be sent to foreign client
+ )
+ ))
+ aCallback->onContact(pairHeader, pairHeader.pairs, pairHeader.nbPairs);
+
+ if (
+ (clientActor0 != clientActor1) //don't call the same client twice
+ && bCallback
+ && (actor1ClientBehaviorFlags & physx::PxClientBehaviorFlag::eREPORT_FOREIGN_OBJECTS_TO_CONTACT_NOTIFY)//this client accepts foreign objects
+ && (actor0ClientBehaviorFlags & physx::PxActorClientBehaviorFlag::eREPORT_TO_FOREIGN_CLIENTS_CONTACT_NOTIFY)//this actor can be sent to foreign client
+ )
+ bCallback->onContact(pairHeader, pairHeader.pairs, pairHeader.nbPairs);
+ }
+ mScene->unlockRead();
+}
+
+void NpScene::processCallbacks(physx::PxBaseTask* continuation)
+{
+ PX_PROFILE_START_CROSSTHREAD("Basic.processCallbacks", getContextId());
+ PX_PROFILE_ZONE("Sim.processCallbacks", getContextId());
+ //ML: because Apex destruction callback isn't thread safe so that we make this run single thread first
+ const Ps::Array<PxContactPairHeader>& pairs = mScene.getQueuedContactPairHeaders();
+ const PxU32 nbPairs = pairs.size();
+ const PxContactPairHeader* contactPairs = pairs.begin();
+ const PxU32 nbToProcess = 256;
+
+ Cm::FlushPool* flushPool = mScene.getScScene().getFlushPool();
+
+ for (PxU32 i = 0; i < nbPairs; i += nbToProcess)
+ {
+ NpContactCallbackTask* task = PX_PLACEMENT_NEW(flushPool->allocate(sizeof(NpContactCallbackTask)), NpContactCallbackTask)();
+ task->setData(this, contactPairs+i, PxMin(nbToProcess, nbPairs - i));
+ task->setContinuation(continuation);
+ task->removeReference();
+ }
+}
+
+void NpScene::fetchResultsFinish(PxU32* errorState)
+{
+ {
+ PX_SIMD_GUARD;
+ PX_PROFILE_STOP_CROSSTHREAD("Basic.processCallbacks", getContextId());
+ PX_PROFILE_ZONE("Basic.fetchResultsFinish", getContextId());
+
+ mBetweenFetchResults = false;
+ NP_WRITE_CHECK(this);
+
+ fetchResultsPostContactCallbacks();
+
+ if (errorState)
+ *errorState = mScene.getScScene().getErrorState();
+
+ PX_PROFILE_STOP_CROSSTHREAD("Basic.fetchResults", getContextId());
+ PX_PROFILE_STOP_CROSSTHREAD("Basic.simulate", getContextId());
+ }
+
+#if PX_SUPPORT_PVD
+ mScene.getScenePvdClient().frameEnd();
+#endif
+}
+
+void NpScene::flushSimulation(bool sendPendingReports)
+{
+ PX_PROFILE_ZONE("API.flushSimulation", getContextId());
+ NP_WRITE_CHECK_NOREENTRY(this);
+ PX_SIMD_GUARD;
+
+ if (getSimulationStage() != Sc::SimulationStage::eCOMPLETE)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxScene::flushSimulation(): This call is not allowed while the simulation is running. Call will be ignored");
+ return;
+ }
+
+ mScene.flush(sendPendingReports);
+ mSQManager.flushMemory();
+
+ //!!! TODO: Shrink all NpObject lists?
+}
+
+void NpScene::flushQueryUpdates()
+{
+ // DS: how do we profile const methods??????
+ PX_PROFILE_ZONE("API.flushQueryUpdates", getContextId());
+ NP_READ_CHECK(this);
+ PX_SIMD_GUARD;
+
+ if (getSimulationStage() != Sc::SimulationStage::eCOMPLETE)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxScene::flushQueryUpdates(): This call is not allowed while the simulation is running. Call will be ignored");
+ return;
+ }
+
+ mSQManager.flushUpdates();
+}
+
+/*
+Replaces finishRun() with the addition of appropriate thread sync(pulled out of PhysicsThread())
+
+Note: this function can be called from the application thread or the physics thread, depending on the
+scene flags.
+*/
+void NpScene::executeScene(PxBaseTask* continuation)
+{
+ mScene.simulate(mElapsedTime, continuation);
+}
+
+void NpScene::executeCollide(PxBaseTask* continuation)
+{
+ mScene.collide(mElapsedTime, continuation);
+}
+
+void NpScene::executeAdvance(PxBaseTask* continuation)
+{
+ mScene.advance(mElapsedTime, continuation);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::addMaterial(const NpMaterial& mat)
+{
+ mScene.addMaterial(mat.getScMaterial());
+}
+
+void NpScene::updateMaterial(const NpMaterial& mat)
+{
+ //PxU32 index = mat.getTableIndex();
+ mScene.updateMaterial(mat.getScMaterial());
+}
+
+void NpScene::removeMaterial(const NpMaterial& mat)
+{
+ //PxU32 index = mat.getTableIndex();
+ mScene.removeMaterial(mat.getScMaterial());
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpScene::setDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2, const PxDominanceGroupPair& dominance)
+{
+ NP_WRITE_CHECK(this);
+ PX_CHECK_AND_RETURN((group1 < PX_MAX_DOMINANCE_GROUP && group2 < PX_MAX_DOMINANCE_GROUP),
+ "PxScene::setDominanceGroupPair: invalid params! Groups must be <= 31!");
+ //can't change matrix diagonal
+ PX_CHECK_AND_RETURN(group1 != group2, "PxScene::setDominanceGroupPair: invalid params! Groups must be unequal! Can't change matrix diagonal!");
+ PX_CHECK_AND_RETURN(
+ ((dominance.dominance0) == 1.0f && (dominance.dominance1 == 1.0f))
+ || ((dominance.dominance0) == 1.0f && (dominance.dominance1 == 0.0f))
+ || ((dominance.dominance0) == 0.0f && (dominance.dominance1 == 1.0f))
+ , "PxScene::setDominanceGroupPair: invalid params! dominance must be one of (1,1), (1,0), or (0,1)!");
+
+ mScene.setDominanceGroupPair(group1, group2, dominance);
+}
+
+PxDominanceGroupPair NpScene::getDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2) const
+{
+ NP_READ_CHECK(this);
+ PX_CHECK_AND_RETURN_VAL((group1 < PX_MAX_DOMINANCE_GROUP && group2 < PX_MAX_DOMINANCE_GROUP),
+ "PxScene::getDominanceGroupPair: invalid params! Groups must be <= 31!", PxDominanceGroupPair(PxU8(1u), PxU8(1u)));
+ return mScene.getDominanceGroupPair(group1, group2);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+void NpScene::addParticleSystem(NpParticleSystem& system)
+{
+ PX_PROFILE_ZONE("API.addParticleSystem", getContextId());
+
+ PX_CHECK_AND_RETURN(mScene.getScScene().getParticleContext(), "PxRegisterParticles needs to be called before scene creation. PxParticleSystem not added to scene.");
+ mScene.addParticleSystem(system.getScbParticleSystem());
+ mPxParticleBaseSet.insert(&system);
+
+ updatePhysXIndicator();
+}
+
+void NpScene::removeParticleSystem(NpParticleSystem& system)
+{
+ PX_PROFILE_ZONE("API.removeParticleSystem", getContextId());
+ PX_ASSERT(system.getNpScene() == this);
+
+ PX_CHECK_AND_RETURN(mScene.getScScene().getParticleContext(), "PxRegisterParticles needs to be called before scene creation. PxParticleFluid not added to scene.");
+ mScene.removeParticleSystem(system.getScbParticleSystem(), false);
+ removeFromParticleBaseList(system);
+
+ updatePhysXIndicator();
+}
+
+void NpScene::addParticleFluid(NpParticleFluid& fluid)
+{
+ PX_PROFILE_ZONE("API.addParticleFluid", getContextId());
+ mScene.addParticleSystem(fluid.getScbParticleSystem());
+ mPxParticleBaseSet.insert(&fluid);
+
+ updatePhysXIndicator();
+}
+
+void NpScene::removeParticleFluid(NpParticleFluid& fluid)
+{
+ PX_PROFILE_ZONE("API.removeParticleFluid", getContextId());
+ PX_ASSERT(fluid.getNpScene() == this);
+
+ mScene.removeParticleSystem(fluid.getScbParticleSystem(), false);
+ removeFromParticleBaseList(fluid);
+
+ updatePhysXIndicator();
+}
+
+#endif // PX_USE_PARTICLE_SYSTEM_API
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_USE_CLOTH_API
+
+void NpScene::addCloth(NpCloth& cloth)
+{
+ PX_PROFILE_ZONE("API.addCloth", getContextId());
+ mScene.addCloth(cloth.getScbCloth());
+ mPxCloths.insert(&cloth);
+
+ updatePhysXIndicator();
+}
+
+void NpScene::removeCloth(NpCloth& cloth)
+{
+ PX_PROFILE_ZONE("API.removeCloth", getContextId());
+ PX_ASSERT(NpActor::getAPIScene(cloth) == this);
+
+ mScene.removeCloth(cloth.getScbCloth());
+ removeFromClothList(cloth);
+
+ updatePhysXIndicator();
+}
+
+#endif // PX_USE_CLOTH_API
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_SUPPORT_GPU_PHYSX
+
+void NpScene::updatePhysXIndicator()
+{
+ Ps::IntBool isGpu = 0;
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ PxParticleBase*const* particleBaseList = mPxParticleBaseSet.getEntries();
+ for (PxU32 i = 0; !isGpu && i < mPxParticleBaseSet.size(); i++)
+ {
+ NpParticleSystem* particles = (NpParticleSystem*)particleBaseList[i]->is<PxParticleSystem>();
+ NpParticleFluid* fluid = (NpParticleFluid*)particleBaseList[i]->is<PxParticleFluid>();
+
+ isGpu |= particles && particles->getScbParticleSystem().getScParticleSystem().isGpu();
+ isGpu |= fluid && fluid->getScbParticleSystem().getScParticleSystem().isGpu();
+ }
+#endif
+
+#if PX_USE_CLOTH_API
+ PxCloth*const* clothList = mPxCloths.getEntries();
+ for (PxU32 i = 0; !isGpu && i < mPxCloths.size(); i++)
+ {
+ NpCloth* pCloth = (NpCloth*)clothList[i]->is<PxCloth>();
+ isGpu = pCloth->getScbCloth().getScCloth().isGpu();
+ }
+#endif
+
+ mPhysXIndicator.setIsGpu(isGpu != 0);
+}
+#endif //PX_SUPPORT_GPU_PHYSX
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxVolumeCache* NpScene::createVolumeCache(PxU32 maxStaticShapes, PxU32 maxDynamicShapes)
+{
+ NpVolumeCache* cache = PX_NEW(NpVolumeCache)(&mSQManager, maxStaticShapes, maxDynamicShapes);
+ mVolumeCaches.insert(cache);
+ return cache;
+}
+
+void NpScene::releaseVolumeCache(NpVolumeCache* volumeCache)
+{
+ bool found = mVolumeCaches.erase(volumeCache); PX_UNUSED(found);
+ PX_ASSERT_WITH_MESSAGE(found, "volume cache not found in releaseVolumeCache");
+ PX_DELETE(static_cast<NpVolumeCache*>(volumeCache));
+}
+
+void NpScene::setDynamicTreeRebuildRateHint(PxU32 dynamicTreeRebuildRateHint)
+{
+ PX_CHECK_AND_RETURN((dynamicTreeRebuildRateHint >= 4), "PxScene::setDynamicTreeRebuildRateHint(): Param has to be >= 4!");
+ mSQManager.setDynamicTreeRebuildRateHint(dynamicTreeRebuildRateHint);
+}
+
+PxU32 NpScene::getDynamicTreeRebuildRateHint() const
+{
+ NP_READ_CHECK(this);
+ return mSQManager.getDynamicTreeRebuildRateHint();
+}
+
+void NpScene::forceDynamicTreeRebuild(bool rebuildStaticStructure, bool rebuildDynamicStructure)
+{
+ PX_PROFILE_ZONE("API.forceDynamicTreeRebuild", getContextId());
+ NP_WRITE_CHECK(this);
+ PX_SIMD_GUARD;
+ mSQManager.forceDynamicTreeRebuild(rebuildStaticStructure, rebuildDynamicStructure);
+}
+
+void NpScene::setSolverBatchSize(PxU32 solverBatchSize)
+{
+ NP_WRITE_CHECK(this);
+ mScene.setSolverBatchSize(solverBatchSize);
+}
+
+PxU32 NpScene::getSolverBatchSize(void) const
+{
+ NP_READ_CHECK(this);
+ // get from our local copy
+ return mScene.getSolverBatchSize();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool NpScene::setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value)
+{
+ NP_WRITE_CHECK(this);
+ PX_CHECK_AND_RETURN_VAL(PxIsFinite(value), "PxScene::setVisualizationParameter: value is not valid.", false);
+
+ if (param >= PxVisualizationParameter::eNUM_VALUES)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "setVisualizationParameter: parameter out of range.");
+ return false;
+ }
+ else if (value < 0.0f)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "setVisualizationParameter: value must be larger or equal to 0.");
+ return false;
+ }
+ else
+ {
+ mScene.setVisualizationParameter(param, value);
+ return true;
+ }
+}
+
+PxReal NpScene::getVisualizationParameter(PxVisualizationParameter::Enum param) const
+{
+ if (param < PxVisualizationParameter::eNUM_VALUES)
+ return mScene.getVisualizationParameter(param);
+ else
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "getVisualizationParameter: param is not an enum.");
+
+ return 0.0f;
+}
+
+void NpScene::setVisualizationCullingBox(const PxBounds3& box)
+{
+ NP_WRITE_CHECK(this);
+ PX_CHECK_MSG(box.isValid(), "PxScene::setVisualizationCullingBox(): invalid bounds provided!");
+ mScene.setVisualizationCullingBox(box);
+}
+
+const PxBounds3& NpScene::getVisualizationCullingBox() const
+{
+ NP_READ_CHECK(this);
+ const PxBounds3& bounds = mScene.getVisualizationCullingBox();
+ PX_ASSERT(bounds.isValid());
+ return bounds;
+}
+
+void NpScene::setNbContactDataBlocks(PxU32 numBlocks)
+{
+ PX_CHECK_AND_RETURN((getSimulationStage() == Sc::SimulationStage::eCOMPLETE),
+ "PxScene::setNbContactDataBlock: This call is not allowed while the simulation is running. Call will be ignored!");
+
+ mScene.getScScene().setNbContactDataBlocks(numBlocks);
+}
+
+PxU32 NpScene::getNbContactDataBlocksUsed() const
+{
+ PX_CHECK_AND_RETURN_VAL((getSimulationStage() == Sc::SimulationStage::eCOMPLETE),
+ "PxScene::getNbContactDataBlocksUsed: This call is not allowed while the simulation is running. Returning 0.", 0);
+
+ return mScene.getScScene().getNbContactDataBlocksUsed();
+}
+
+PxU32 NpScene::getMaxNbContactDataBlocksUsed() const
+{
+ PX_CHECK_AND_RETURN_VAL((getSimulationStage() == Sc::SimulationStage::eCOMPLETE),
+ "PxScene::getMaxNbContactDataBlocksUsed: This call is not allowed while the simulation is running. Returning 0.", 0);
+
+ return mScene.getScScene().getMaxNbContactDataBlocksUsed();
+}
+
+PxU32 NpScene::getTimestamp() const
+{
+ return mScene.getScScene().getTimeStamp();
+}
+
+PxU32 NpScene::getSceneQueryStaticTimestamp() const
+{
+ return mSQManager.get(PruningIndex::eSTATIC).timestamp();
+}
+
+PxCpuDispatcher* NpScene::getCpuDispatcher() const
+{
+ return getTaskManager()->getCpuDispatcher();
+}
+
+PxGpuDispatcher* NpScene::getGpuDispatcher() const
+{
+ return getTaskManager()->getGpuDispatcher();
+}
+
+PxPruningStructureType::Enum NpScene::getStaticStructure() const
+{
+ return mSQManager.get(PruningIndex::eSTATIC).type();
+}
+
+PxPruningStructureType::Enum NpScene::getDynamicStructure() const
+{
+ return mSQManager.get(PruningIndex::eDYNAMIC).type();
+}
+
+PxReal NpScene::getFrictionOffsetThreshold() const
+{
+ return mScene.getScScene().getFrictionOffsetThreshold();
+}
+
+PxU32 NpScene::getContactReportStreamBufferSize() const
+{
+ return mScene.getScScene().getDefaultContactReportStreamBufferSize();
+}
+
+#if PX_CHECKED
+void NpScene::checkPositionSanity(const PxRigidActor& a, const PxTransform& pose, const char* fnName) const
+{
+ if(!mSanityBounds.contains(pose.p))
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "%s: actor pose for %lp is outside sanity bounds\n", fnName, &a);
+}
+#endif
+
+namespace
+{
+ struct ThreadReadWriteCount
+ {
+ PxU8 readDepth; // depth of re-entrant reads
+ PxU8 writeDepth; // depth of re-entrant writes
+
+ PxU8 readLockDepth; // depth of read-locks
+ PxU8 writeLockDepth; // depth of write-locks
+ };
+}
+
+#if NP_ENABLE_THREAD_CHECKS
+
+NpScene::StartWriteResult::Enum NpScene::startWrite(bool allowReentry)
+{
+ PX_COMPILE_TIME_ASSERT(sizeof(ThreadReadWriteCount) == 4);
+
+ if (mScene.getFlags() & PxSceneFlag::eREQUIRE_RW_LOCK)
+ {
+ ThreadReadWriteCount localCounts = PxUnionCast<ThreadReadWriteCount>(TlsGet(mThreadReadWriteDepth));
+
+ if (mBetweenFetchResults)
+ return StartWriteResult::eIN_FETCHRESULTS;
+
+ // ensure we already have the write lock
+ return localCounts.writeLockDepth > 0 ? StartWriteResult::eOK : StartWriteResult::eNO_LOCK;
+ }
+
+ {
+ ThreadReadWriteCount localCounts = PxUnionCast<ThreadReadWriteCount>(TlsGet(mThreadReadWriteDepth));
+ StartWriteResult::Enum result;
+
+ if (mBetweenFetchResults)
+ result = StartWriteResult::eIN_FETCHRESULTS;
+
+ // check we are the only thread reading (allows read->write order on a single thread) and no other threads are writing
+ else if (mConcurrentReadCount != localCounts.readDepth || mConcurrentWriteCount != localCounts.writeDepth)
+ result = StartWriteResult::eRACE_DETECTED;
+
+ else
+ result = StartWriteResult::eOK;
+
+ // increment shared write counter
+ Ps::atomicIncrement(&mConcurrentWriteCount);
+
+ // in the normal case (re-entry is allowed) then we simply increment
+ // the writeDepth by 1, otherwise (re-entry is not allowed) increment
+ // by 2 to force subsequent writes to fail by creating a mismatch between
+ // the concurrent write counter and the local counter, any value > 1 will do
+ localCounts.writeDepth += allowReentry ? 1 : 2;
+ TlsSet(mThreadReadWriteDepth, PxUnionCast<void*>(localCounts));
+
+ if (result != StartWriteResult::eOK)
+ Ps::atomicIncrement(&mConcurrentErrorCount);
+
+ return result;
+ }
+}
+
+void NpScene::stopWrite(bool allowReentry)
+{
+ if (!(mScene.getFlags() & PxSceneFlag::eREQUIRE_RW_LOCK))
+ {
+ Ps::atomicDecrement(&mConcurrentWriteCount);
+
+ // decrement depth of writes for this thread
+ ThreadReadWriteCount localCounts = PxUnionCast<ThreadReadWriteCount>(TlsGet(mThreadReadWriteDepth));
+
+ // see comment in startWrite()
+ if (allowReentry)
+ localCounts.writeDepth--;
+ else
+ localCounts.writeDepth-=2;
+
+ TlsSet(mThreadReadWriteDepth, PxUnionCast<void*>(localCounts));
+ }
+}
+
+bool NpScene::startRead() const
+{
+ if (mScene.getFlags() & PxSceneFlag::eREQUIRE_RW_LOCK)
+ {
+ ThreadReadWriteCount localCounts = PxUnionCast<ThreadReadWriteCount>(TlsGet(mThreadReadWriteDepth));
+
+ // ensure we already have the write or read lock
+ return localCounts.writeLockDepth > 0 || localCounts.readLockDepth > 0;
+ }
+ else
+ {
+ Ps::atomicIncrement(&mConcurrentReadCount);
+
+ // update current threads read depth
+ ThreadReadWriteCount localCounts = PxUnionCast<ThreadReadWriteCount>(TlsGet(mThreadReadWriteDepth));
+ localCounts.readDepth++;
+ TlsSet(mThreadReadWriteDepth, PxUnionCast<void*>(localCounts));
+
+ // success if the current thread is already performing a write (API re-entry) or no writes are in progress
+ bool success = (localCounts.writeDepth > 0 || mConcurrentWriteCount == 0);
+
+ if (!success)
+ Ps::atomicIncrement(&mConcurrentErrorCount);
+
+ return success;
+ }
+}
+
+void NpScene::stopRead() const
+{
+ if (!(mScene.getFlags() & PxSceneFlag::eREQUIRE_RW_LOCK))
+ {
+ Ps::atomicDecrement(&mConcurrentReadCount);
+
+ // update local threads read depth
+ ThreadReadWriteCount localCounts = PxUnionCast<ThreadReadWriteCount>(TlsGet(mThreadReadWriteDepth));
+ localCounts.readDepth--;
+ TlsSet(mThreadReadWriteDepth, PxUnionCast<void*>(localCounts));
+ }
+}
+
+#else
+
+NpScene::StartWriteResult::Enum NpScene::startWrite(bool) { PX_ASSERT(0); return NpScene::StartWriteResult::eOK; }
+void NpScene::stopWrite(bool) {}
+
+bool NpScene::startRead() const { PX_ASSERT(0); return false; }
+void NpScene::stopRead() const {}
+
+#endif // NP_ENABLE_THREAD_CHECKS
+
+void NpScene::lockRead(const char* /*file*/, PxU32 /*line*/)
+{
+ // increment this threads read depth
+ ThreadReadWriteCount localCounts = PxUnionCast<ThreadReadWriteCount>(TlsGet(mThreadReadWriteDepth));
+ localCounts.readLockDepth++;
+ TlsSet(mThreadReadWriteDepth, PxUnionCast<void*>(localCounts));
+
+ // if we are the current writer then do nothing (allow reading from threads with write ownership)
+ if (mCurrentWriter == Thread::getId())
+ return;
+
+ // only lock on first read
+ if (localCounts.readLockDepth == 1)
+ mRWLock.lockReader();
+}
+
+void NpScene::unlockRead()
+{
+ // increment this threads read depth
+ ThreadReadWriteCount localCounts = PxUnionCast<ThreadReadWriteCount>(TlsGet(mThreadReadWriteDepth));
+ if (localCounts.readLockDepth < 1)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::unlockRead() called without matching call to PxScene::lockRead(), behaviour will be undefined.");
+ return;
+ }
+ localCounts.readLockDepth--;
+ TlsSet(mThreadReadWriteDepth, PxUnionCast<void*>(localCounts));
+
+ // if we are the current writer then do nothing (allow reading from threads with write ownership)
+ if (mCurrentWriter == Thread::getId())
+ return;
+
+ // only unlock on last read
+ if (localCounts.readLockDepth == 0)
+ mRWLock.unlockReader();
+}
+
+void NpScene::lockWrite(const char* file, PxU32 line)
+{
+ // increment this threads write depth
+ ThreadReadWriteCount localCounts = PxUnionCast<ThreadReadWriteCount>(TlsGet(mThreadReadWriteDepth));
+ if (localCounts.writeLockDepth == 0 && localCounts.readLockDepth > 0)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, file?file:__FILE__, file?int(line):__LINE__, "PxScene::lockWrite() detected after a PxScene::lockRead(), lock upgrading is not supported, behaviour will be undefined.");
+ return;
+ }
+ localCounts.writeLockDepth++;
+ TlsSet(mThreadReadWriteDepth, PxUnionCast<void*>(localCounts));
+
+ // only lock on first call
+ if (localCounts.writeLockDepth == 1)
+ mRWLock.lockWriter();
+
+ PX_ASSERT(mCurrentWriter == 0 || mCurrentWriter == Thread::getId());
+
+ // set ourselves as the current writer
+ mCurrentWriter = Thread::getId();
+}
+
+void NpScene::unlockWrite()
+{
+ // increment this thread's write depth
+ ThreadReadWriteCount localCounts = PxUnionCast<ThreadReadWriteCount>(TlsGet(mThreadReadWriteDepth));
+ if (localCounts.writeLockDepth < 1)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxScene::unlockWrite() called without matching call to PxScene::lockWrite(), behaviour will be undefined.");
+ return;
+ }
+ localCounts.writeLockDepth--;
+ TlsSet(mThreadReadWriteDepth, PxUnionCast<void*>(localCounts));
+
+ PX_ASSERT(mCurrentWriter == Thread::getId());
+
+ if (localCounts.writeLockDepth == 0)
+ {
+ mCurrentWriter = 0;
+ mRWLock.unlockWriter();
+ }
+}
+
+PxReal NpScene::getWakeCounterResetValue() const
+{
+ NP_READ_CHECK(this);
+
+ return getWakeCounterResetValueInteral();
+}
+
+static PX_FORCE_INLINE void shiftRigidActor(PxRigidActor* a, const PxVec3& shift)
+{
+ PxActorType::Enum t = a->getType();
+ if (t == PxActorType::eRIGID_DYNAMIC)
+ {
+ NpRigidDynamic* rd = static_cast<NpRigidDynamic*>(a);
+ rd->getScbBodyFast().onOriginShift(shift);
+ }
+ else if (t == PxActorType::eRIGID_STATIC)
+ {
+ NpRigidStatic* rs = static_cast<NpRigidStatic*>(a);
+ rs->getScbRigidStaticFast().onOriginShift(shift);
+ }
+ else
+ {
+ PX_ASSERT(t == PxActorType::eARTICULATION_LINK);
+ NpArticulationLink* al = static_cast<NpArticulationLink*>(a);
+ al->getScbBodyFast().onOriginShift(shift);
+ }
+}
+
+void NpScene::shiftOrigin(const PxVec3& shift)
+{
+ PX_PROFILE_ZONE("API.shiftOrigin", getContextId());
+ NP_WRITE_CHECK(this);
+
+ if(mScene.isPhysicsBuffering())
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxScene::shiftOrigin() not allowed while simulation is running. Call will be ignored.");
+ return;
+ }
+
+ PX_SIMD_GUARD;
+
+ const PxU32 prefetchLookAhead = 4;
+ PxU32 rigidCount = mRigidActors.size();
+ PxRigidActor*const* rigidActors = mRigidActors.begin();
+ PxU32 batchIterCount = rigidCount / prefetchLookAhead;
+
+ PxU32 idx = 0;
+ for(PxU32 i=0; i < batchIterCount; i++)
+ {
+ // prefetch elements for next batch
+ if (i < (batchIterCount-1))
+ {
+ Ps::prefetchLine(rigidActors[idx + prefetchLookAhead]);
+ Ps::prefetchLine(reinterpret_cast<PxU8*>(rigidActors[idx + prefetchLookAhead]) + 128); // for the buffered pose
+ Ps::prefetchLine(rigidActors[idx + prefetchLookAhead + 1]);
+ Ps::prefetchLine(reinterpret_cast<PxU8*>(rigidActors[idx + prefetchLookAhead + 1]) + 128);
+ Ps::prefetchLine(rigidActors[idx + prefetchLookAhead + 2]);
+ Ps::prefetchLine(reinterpret_cast<PxU8*>(rigidActors[idx + prefetchLookAhead + 2]) + 128);
+ Ps::prefetchLine(rigidActors[idx + prefetchLookAhead + 3]);
+ Ps::prefetchLine(reinterpret_cast<PxU8*>(rigidActors[idx + prefetchLookAhead + 3]) + 128);
+ }
+ else
+ {
+ for(PxU32 k=(idx + prefetchLookAhead); k < rigidCount; k++)
+ {
+ Ps::prefetchLine(rigidActors[k]);
+ Ps::prefetchLine(reinterpret_cast<PxU8*>(rigidActors[k]) + 128);
+ }
+ }
+
+ for(PxU32 j=idx; j < (idx + prefetchLookAhead); j++)
+ {
+ shiftRigidActor(rigidActors[j], shift);
+ }
+
+ idx += prefetchLookAhead;
+ }
+ // process remaining objects
+ for(PxU32 i=idx; i < rigidCount; i++)
+ {
+ shiftRigidActor(rigidActors[i], shift);
+ }
+
+ PxArticulation*const* articulations = mArticulations.getEntries();
+ for(PxU32 i=0; i < mArticulations.size(); i++)
+ {
+ NpArticulation* np = static_cast<NpArticulation*>(articulations[i]);
+ NpArticulationLink*const* links = np->getLinks();
+
+ for(PxU32 j=0; j < np->getNbLinks(); j++)
+ {
+ shiftRigidActor(links[j], shift);
+ }
+ }
+
+
+ mScene.shiftOrigin(shift);
+
+
+ //
+ // shift scene query related data structures
+ //
+ mSQManager.shiftOrigin(shift);
+
+ Ps::HashSet<NpVolumeCache*>::Iterator it = mVolumeCaches.getIterator();
+ while (!it.done())
+ {
+ NpVolumeCache* cache = (*it);
+ cache->onOriginShift(shift);
+ ++it;
+ }
+
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+ //
+ // debug visualization
+ //
+ mRenderBuffer.shift(-shift);
+#endif
+}
+
+#if PX_SUPPORT_PVD
+PxPvdSceneClient* NpScene::getScenePvdClient()
+{
+ return &mScene.getScenePvdClient();
+}
+#else
+PxPvdSceneClient* NpScene::getScenePvdClient()
+{
+ return NULL;
+}
+#endif
+
+PxBatchQuery* NpScene::createBatchQuery(const PxBatchQueryDesc& desc)
+{
+ PX_PROFILE_ZONE("API.createBatchQuery", getContextId());
+ PX_CHECK_AND_RETURN_NULL(desc.isValid(),"Supplied PxBatchQueryDesc is not valid. createBatchQuery returns NULL.");
+
+ NpBatchQuery* bq = PX_NEW(NpBatchQuery)(*this, desc);
+ mBatchQueries.pushBack(bq);
+ return bq;
+}
+
+void NpScene::releaseBatchQuery(PxBatchQuery* sq)
+{
+ PX_PROFILE_ZONE("API.releaseBatchQuery", getContextId());
+ NpBatchQuery* npsq = static_cast<NpBatchQuery*>(sq);
+ bool found = mBatchQueries.findAndReplaceWithLast(npsq);
+ PX_UNUSED(found); PX_ASSERT(found);
+ PX_DELETE_AND_RESET(npsq);
+}
diff --git a/PhysX_3.4/Source/PhysX/src/NpScene.h b/PhysX_3.4/Source/PhysX/src/NpScene.h
new file mode 100644
index 00000000..892e0f99
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpScene.h
@@ -0,0 +1,544 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_SCENE
+#define PX_PHYSICS_NP_SCENE
+
+#include "foundation/PxProfiler.h"
+#include "PsUserAllocated.h"
+#include "PsSync.h"
+#include "PsArray.h"
+#include "PsThread.h"
+#include "PsHashSet.h"
+#include "PxPhysXConfig.h"
+
+#if PX_SUPPORT_GPU_PHYSX
+#include "device/PhysXIndicator.h"
+#endif
+
+#include "NpSceneQueries.h"
+
+namespace physx
+{
+
+class PhysicsThread;
+class PxBatchQueryDesc;
+class NpMaterial;
+class NpVolumeCache;
+class NpScene;
+
+namespace Sc
+{
+ class Joint;
+ class ConstraintBreakEvent;
+}
+
+namespace Sq
+{
+ class SceneQueryManager;
+}
+
+class NpObjectFactory;
+class NpRigidStatic;
+class NpRigidDynamic;
+class NpParticleSystem;
+class NpParticleFluid;
+class NpConstraint;
+class NpArticulationLink;
+class NpCloth;
+class NpShapeManager;
+class NpBatchQuery;
+
+class PxBatchQuery;
+
+enum NpProfileZones
+{
+ NpScene_checkResults,
+ NpScene_reportContacts,
+ NpScene_reportProfiling,
+ NpScene_reportTriggers,
+ NpScene_stats,
+
+ NpPrNumZones
+};
+
+
+class NpContactCallbackTask : public physx::PxLightCpuTask
+{
+ NpScene* mScene;
+ const PxContactPairHeader* mContactPairHeaders;
+ uint32_t mNbContactPairHeaders;
+
+public:
+
+ void setData(NpScene* scene, const PxContactPairHeader* contactPairHeaders, const uint32_t nbContactPairHeaders);
+
+ virtual void run();
+
+ virtual const char* getName() const
+ {
+ return "NpContactCallbackTask";
+ }
+};
+
+class NpScene : public NpSceneQueries, public Ps::UserAllocated
+{
+ //virtual interfaces:
+
+ PX_NOCOPY(NpScene)
+ public:
+
+ virtual void release();
+
+ virtual void setFlag(PxSceneFlag::Enum flag, bool value);
+ virtual PxSceneFlags getFlags() const;
+
+ // implement PxScene:
+
+ virtual void setGravity(const PxVec3&);
+ virtual PxVec3 getGravity() const;
+
+ virtual void setBounceThresholdVelocity(const PxReal t);
+ virtual PxReal getBounceThresholdVelocity() const;
+
+ virtual PxReal getFrictionOffsetThreshold() const;
+
+ virtual void setLimits(const PxSceneLimits& limits);
+ virtual PxSceneLimits getLimits() const;
+
+ virtual void addActor(PxActor& actor);
+ virtual void removeActor(PxActor& actor, bool wakeOnLostTouch);
+
+ virtual PxU32 getNbConstraints() const;
+ virtual PxU32 getConstraints(PxConstraint** buffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+
+ virtual void addArticulation(PxArticulation&);
+ virtual void removeArticulation(PxArticulation&, bool wakeOnLostTouch);
+ virtual PxU32 getNbArticulations() const;
+ virtual PxU32 getArticulations(PxArticulation** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+
+// PX_AGGREGATE
+ virtual void addAggregate(PxAggregate&);
+ virtual void removeAggregate(PxAggregate&, bool wakeOnLostTouch);
+ virtual PxU32 getNbAggregates() const;
+ virtual PxU32 getAggregates(PxAggregate** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+//~PX_AGGREGATE
+
+ virtual void addCollection(const PxCollection& collection);
+
+ // Groups
+ virtual void setDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2, const PxDominanceGroupPair& dominance);
+ virtual PxDominanceGroupPair getDominanceGroupPair(PxDominanceGroup group1, PxDominanceGroup group2) const;
+
+ // Actors
+ virtual PxU32 getNbActors(PxActorTypeFlags types) const;
+ virtual PxU32 getActors(PxActorTypeFlags types, PxActor** buffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+ virtual const PxActiveTransform* getActiveTransforms(PxU32& nbTransformsOut, PxClientID client);
+ virtual PxActor** getActiveActors(PxU32& nbActorsOut, PxClientID client);
+
+ // Run
+ virtual void getSimulationStatistics(PxSimulationStatistics& s) const;
+
+ // Multiclient
+ virtual PxClientID createClient();
+ virtual void setClientBehaviorFlags(PxClientID client, PxClientBehaviorFlags clientBehaviorFlags);
+ virtual PxClientBehaviorFlags getClientBehaviorFlags(PxClientID client) const;
+
+ // FrictionModel
+ virtual void setFrictionType(PxFrictionType::Enum frictionType);
+ virtual PxFrictionType::Enum getFrictionType() const;
+
+#if PX_USE_CLOTH_API
+ // Cloth
+ virtual void setClothInterCollisionDistance(PxF32 distance);
+ virtual PxF32 getClothInterCollisionDistance() const;
+ virtual void setClothInterCollisionStiffness(PxF32 stiffness);
+ virtual PxF32 getClothInterCollisionStiffness() const;
+ virtual void setClothInterCollisionNbIterations(PxU32 nbIterations);
+ virtual PxU32 getClothInterCollisionNbIterations() const;
+#endif
+
+ // Callbacks
+ virtual void setSimulationEventCallback(PxSimulationEventCallback* callback, PxClientID client);
+ virtual PxSimulationEventCallback* getSimulationEventCallback(PxClientID client) const;
+ virtual void setContactModifyCallback(PxContactModifyCallback* callback);
+ virtual PxContactModifyCallback* getContactModifyCallback() const;
+ virtual void setCCDContactModifyCallback(PxCCDContactModifyCallback* callback);
+ virtual PxCCDContactModifyCallback* getCCDContactModifyCallback() const;
+ virtual void setBroadPhaseCallback(PxBroadPhaseCallback* callback, PxClientID client);
+ virtual PxBroadPhaseCallback* getBroadPhaseCallback(PxClientID client) const;
+
+ //CCD passes
+ virtual void setCCDMaxPasses(PxU32 ccdMaxPasses);
+ virtual PxU32 getCCDMaxPasses() const;
+
+ // Collision filtering
+ virtual void setFilterShaderData(const void* data, PxU32 dataSize);
+ virtual const void* getFilterShaderData() const;
+ virtual PxU32 getFilterShaderDataSize() const;
+ virtual PxSimulationFilterShader getFilterShader() const;
+ virtual PxSimulationFilterCallback* getFilterCallback() const;
+ virtual void resetFiltering(PxActor& actor);
+ virtual void resetFiltering(PxRigidActor& actor, PxShape*const* shapes, PxU32 shapeCount);
+
+ // Get Physics SDK
+ virtual PxPhysics& getPhysics();
+
+ // new API methods
+ virtual void simulate(PxReal elapsedTime, physx::PxBaseTask* completionTask, void* scratchBlock, PxU32 scratchBlockSize, bool controlSimulation);
+ virtual void advance(physx::PxBaseTask* completionTask);
+ virtual void collide(PxReal elapsedTime, physx::PxBaseTask* completionTask, void* scratchBlock, PxU32 scratchBlockSize, bool controlSimulation = true);
+ virtual bool checkResults(bool block);
+ virtual bool checkCollision(bool block);
+ virtual bool fetchCollision(bool block);
+ virtual bool fetchResults(bool block, PxU32* errorState);
+ virtual bool fetchResultsStart(const PxContactPairHeader*& contactPairs, PxU32& nbContactPairs, bool block = false);
+ virtual void processCallbacks(physx::PxBaseTask* continuation);
+ virtual void fetchResultsFinish(PxU32* errorState = 0);
+
+
+
+ virtual void flush(bool sendPendingReports) { flushSimulation(sendPendingReports); }
+ virtual void flushSimulation(bool sendPendingReports);
+ virtual void flushQueryUpdates();
+ virtual const PxRenderBuffer& getRenderBuffer();
+
+ virtual PxBatchQuery* createBatchQuery(const PxBatchQueryDesc& desc);
+ void releaseBatchQuery(PxBatchQuery* bq);
+ virtual PxVolumeCache* createVolumeCache(PxU32 maxStaticShapes, PxU32 maxDynamicShapes);
+ void releaseVolumeCache(NpVolumeCache* cache);
+ virtual void setDynamicTreeRebuildRateHint(PxU32 dynamicTreeRebuildRateHint);
+ virtual PxU32 getDynamicTreeRebuildRateHint() const;
+ virtual void forceDynamicTreeRebuild(bool rebuildStaticStructure, bool rebuildDynamicStructure);
+
+ virtual void setSolverBatchSize(PxU32 solverBatchSize);
+ virtual PxU32 getSolverBatchSize(void) const;
+
+ virtual bool setVisualizationParameter(PxVisualizationParameter::Enum param, PxReal value);
+ virtual PxReal getVisualizationParameter(PxVisualizationParameter::Enum param) const;
+
+ virtual void setVisualizationCullingBox(const PxBounds3& box);
+ virtual const PxBounds3& getVisualizationCullingBox() const;
+
+ virtual PxTaskManager* getTaskManager() { return mTaskManager; }
+ void checkBeginWrite() const {}
+
+ virtual void setNbContactDataBlocks(PxU32 numBlocks);
+ virtual PxU32 getNbContactDataBlocksUsed() const;
+ virtual PxU32 getMaxNbContactDataBlocksUsed() const;
+
+ virtual PxU32 getContactReportStreamBufferSize() const;
+
+ virtual PxU32 getTimestamp() const;
+ virtual PxU32 getSceneQueryStaticTimestamp() const;
+
+ virtual PxCpuDispatcher* getCpuDispatcher() const;
+ virtual PxGpuDispatcher* getGpuDispatcher() const;
+
+ virtual PxPruningStructureType::Enum getStaticStructure() const;
+ virtual PxPruningStructureType::Enum getDynamicStructure() const;
+
+ virtual PxBroadPhaseType::Enum getBroadPhaseType() const;
+ virtual bool getBroadPhaseCaps(PxBroadPhaseCaps& caps) const;
+ virtual PxU32 getNbBroadPhaseRegions() const;
+ virtual PxU32 getBroadPhaseRegions(PxBroadPhaseRegionInfo* userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+ virtual PxU32 addBroadPhaseRegion(const PxBroadPhaseRegion& region, bool populateRegion);
+ virtual bool removeBroadPhaseRegion(PxU32 handle);
+
+ virtual void addActors(PxActor*const* actors, PxU32 nbActors);
+ virtual void addActors(const PxPruningStructure& prunerStructure);
+ virtual void removeActors(PxActor*const* actors, PxU32 nbActors, bool wakeOnLostTouch);
+
+ virtual void lockRead(const char* file=NULL, PxU32 line=0);
+ virtual void unlockRead();
+
+ virtual void lockWrite(const char* file=NULL, PxU32 line=0);
+ virtual void unlockWrite();
+
+ virtual PxReal getWakeCounterResetValue() const;
+
+ virtual void shiftOrigin(const PxVec3& shift);
+
+ virtual PxPvdSceneClient* getScenePvdClient();
+
+ //internal public methods:
+ public:
+ NpScene(const PxSceneDesc& desc);
+ ~NpScene();
+
+ PX_FORCE_INLINE PxTaskManager* getTaskManager() const { return mTaskManager; }
+
+ PX_FORCE_INLINE Sc::SimulationStage::Enum getSimulationStage() const { return mScene.getSimulationStage(); }
+ PX_FORCE_INLINE void setSimulationStage(Sc::SimulationStage::Enum stage) { mScene.setSimulationStage(stage); }
+
+ void addActorInternal(PxActor& actor);
+ void removeActorInternal(PxActor& actor, bool wakeOnLostTouch, bool removeFromAggregate);
+ void addActorsInternal(PxActor*const* PX_RESTRICT actors, PxU32 nbActors, const Sq::PruningStructure* ps = NULL);
+
+ void addArticulationInternal(PxArticulation&);
+ void removeArticulationInternal(PxArticulation&, bool wakeOnLostTouch, bool removeFromAggregate);
+ // materials
+ void addMaterial(const NpMaterial& mat);
+ void updateMaterial(const NpMaterial& mat);
+ void removeMaterial(const NpMaterial& mat);
+
+ void executeScene(PxBaseTask* continuation);
+ void executeCollide(PxBaseTask* continuation);
+ void executeAdvance(PxBaseTask* continuation);
+ void constraintBreakEventNotify(PxConstraint *const *constraints, PxU32 count);
+
+ bool loadFromDesc(const PxSceneDesc&);
+
+ void removeFromRigidActorList(const PxU32&);
+ PX_FORCE_INLINE void removeFromArticulationList(PxArticulation&);
+ PX_FORCE_INLINE void removeFromAggregateList(PxAggregate&);
+
+ PX_FORCE_INLINE void addToConstraintList(PxConstraint&);
+ PX_FORCE_INLINE void removeFromConstraintList(PxConstraint&);
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ PX_FORCE_INLINE void removeFromParticleBaseList(PxParticleBase&);
+#endif
+
+ void addArticulationLink(NpArticulationLink& link);
+ void addArticulationLinkBody(NpArticulationLink& link);
+ void addArticulationLinkConstraint(NpArticulationLink& link);
+ void removeArticulationLink(NpArticulationLink& link, bool wakeOnLostTouch);
+
+ struct StartWriteResult
+ {
+ enum Enum { eOK, eNO_LOCK, eIN_FETCHRESULTS, eRACE_DETECTED };
+ };
+
+ StartWriteResult::Enum startWrite(bool allowReentry);
+ void stopWrite(bool allowReentry);
+
+ bool startRead() const;
+ void stopRead() const;
+
+ PxU32 getReadWriteErrorCount() const { return PxU32(mConcurrentErrorCount); }
+
+#if PX_CHECKED
+ void checkPositionSanity(const PxRigidActor& a, const PxTransform& pose, const char* fnName) const;
+#endif
+
+#if PX_USE_CLOTH_API
+ void addCloth(NpCloth&);
+ void removeCloth(NpCloth&);
+#endif
+
+#if PX_SUPPORT_GPU_PHYSX
+ void updatePhysXIndicator();
+#else
+ PX_FORCE_INLINE void updatePhysXIndicator() {}
+#endif
+
+ PX_FORCE_INLINE PxReal getWakeCounterResetValueInteral() const { return mScene.getWakeCounterResetValue(); }
+
+private:
+ bool checkResultsInternal(bool block);
+ bool checkCollisionInternal(bool block);
+ void simulateOrCollide(PxReal elapsedTime, physx::PxBaseTask* completionTask, void* scratchBlock, PxU32 scratchBlockSize, bool controlSimulation, const char* invalidCallMsg, Sc::SimulationStage::Enum simStage);
+
+ void addRigidStatic(NpRigidStatic& , bool hasPrunerStructure = false);
+ void removeRigidStatic(NpRigidStatic&, bool wakeOnLostTouch, bool removeFromAggregate);
+ void addRigidDynamic(NpRigidDynamic& , bool hasPrunerStructure = false);
+ void removeRigidDynamic(NpRigidDynamic&, bool wakeOnLostTouch, bool removeFromAggregate);
+
+ bool addRigidActorsInternal(PxU32 nbActors, PxActor** PX_RESTRICT actors);
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ void addParticleSystem(NpParticleSystem&);
+ void removeParticleSystem(NpParticleSystem&);
+ void addParticleFluid(NpParticleFluid&);
+ void removeParticleFluid(NpParticleFluid&);
+#endif
+
+#if PX_USE_CLOTH_API
+ PX_FORCE_INLINE void removeFromClothList(PxCloth&);
+#endif
+
+ void visualize();
+
+ void updateDirtyShaders();
+
+ void fireOutOfBoundsCallbacks();
+ void fetchResultsPreContactCallbacks();
+ void fetchResultsPostContactCallbacks();
+
+
+
+ void updateScbStateAndSetupSq(const PxRigidActor& rigidActor, Scb::Actor& actor, NpShapeManager& shapeManager, bool actorDynamic, const PxBounds3* bounds, bool hasPrunerStructure);
+ PX_FORCE_INLINE void updateScbStateAndSetupSq(const PxRigidActor& rigidActor, Scb::Body& body, NpShapeManager& shapeManager, bool actorDynamic, const PxBounds3* bounds, bool hasPrunerStructure);
+
+ Cm::RenderBuffer mRenderBuffer;
+
+ Ps::CoalescedHashSet<PxConstraint*> mConstraints;
+ Ps::Array<PxRigidActor*> mRigidActors; // no hash set used because it would be quite a bit slower when adding a large number of actors
+ Ps::CoalescedHashSet<PxArticulation*> mArticulations;
+ Ps::CoalescedHashSet<PxAggregate*> mAggregates;
+ Ps::HashSet<NpVolumeCache*> mVolumeCaches;
+ Ps::Array<NpBatchQuery*> mBatchQueries;
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ Ps::CoalescedHashSet<PxParticleBase*> mPxParticleBaseSet;
+#endif
+
+#if PX_USE_CLOTH_API
+ Ps::CoalescedHashSet<PxCloth*> mPxCloths;
+#endif
+
+ PxBounds3 mSanityBounds;
+#if PX_SUPPORT_GPU_PHYSX
+ PhysXIndicator mPhysXIndicator;
+#endif
+
+ Ps::Sync mPhysicsDone; // physics thread signals this when update ready
+ Ps::Sync mCollisionDone; // physics thread signals this when all collisions ready
+
+
+ //legacy timing settings:
+ PxReal mElapsedTime; //needed to transfer the elapsed time param from the user to the sim thread.
+
+ PxU32 mNbClients; // Tracks reserved clients for multiclient support.
+ Ps::Array<PxU32> mClientBehaviorFlags;// Tracks behavior bits for clients.
+
+
+ struct SceneCompletion : public Cm::Task
+ {
+ SceneCompletion(Ps::Sync& sync) : mSync(sync){}
+ virtual void runInternal() {}
+ //ML: As soon as mSync.set is called, and the scene is shutting down,
+ //the scene may be deleted. That means this running task may also be deleted.
+ //As such, we call mSync.set() inside release() to avoid a crash because the v-table on this
+ //task might be deleted between the call to runInternal() and release() in the worker thread.
+ virtual void release()
+ {
+ //We cache the continuation pointer because this class may be deleted
+ //as soon as mSync.set() is called if the application releases the scene.
+ PxBaseTask* c = mCont;
+ //once mSync.set(), fetchResults() will be allowed to run.
+ mSync.set();
+ //Call the continuation task that we cached above. If we use mCont or
+ //any other member variable of this class, there is a small chance
+ //that the variables might have become corrupted if the class
+ //was deleted.
+ if(c) c->removeReference();
+ }
+ virtual const char* getName() const { return "NpScene.completion"; }
+
+ // //This method just is called in the split sim approach as a way to set continuation after the task has been initialized
+ void setDependent(PxBaseTask* task){PX_ASSERT(mCont == NULL); mCont = task; if(task)task->addReference();}
+ Ps::Sync& mSync;
+ private:
+ SceneCompletion& operator=(const SceneCompletion&);
+ };
+
+ typedef Cm::DelegateTask<NpScene, &NpScene::executeScene> SceneExecution;
+ typedef Cm::DelegateTask<NpScene, &NpScene::executeCollide> SceneCollide;
+ typedef Cm::DelegateTask<NpScene, &NpScene::executeAdvance> SceneAdvance;
+
+
+ PxTaskManager* mTaskManager;
+ SceneCompletion mSceneCompletion;
+ SceneCompletion mCollisionCompletion;
+ SceneExecution mSceneExecution;
+ SceneCollide mSceneCollide;
+ SceneAdvance mSceneAdvance;
+ bool mControllingSimulation;
+
+ PxU32 mSimThreadStackSize;
+
+ volatile PxI32 mConcurrentWriteCount;
+ mutable volatile PxI32 mConcurrentReadCount;
+ mutable volatile PxI32 mConcurrentErrorCount;
+
+ // TLS slot index, keeps track of re-entry depth for this thread
+ PxU32 mThreadReadWriteDepth;
+ Ps::Thread::Id mCurrentWriter;
+ Ps::ReadWriteLock mRWLock;
+
+ bool mHasSimulatedOnce;
+ bool mBetweenFetchResults;
+};
+
+
+PX_FORCE_INLINE void NpScene::addToConstraintList(PxConstraint& constraint)
+{
+ mConstraints.insert(&constraint);
+}
+
+
+PX_FORCE_INLINE void NpScene::removeFromConstraintList(PxConstraint& constraint)
+{
+ const bool exists = mConstraints.erase(&constraint);
+ PX_ASSERT(exists);
+ PX_UNUSED(exists);
+}
+
+
+PX_FORCE_INLINE void NpScene::removeFromArticulationList(PxArticulation& articulation)
+{
+ const bool exists = mArticulations.erase(&articulation);
+ PX_ASSERT(exists);
+ PX_UNUSED(exists);
+}
+
+
+PX_FORCE_INLINE void NpScene::removeFromAggregateList(PxAggregate& aggregate)
+{
+ const bool exists = mAggregates.erase(&aggregate);
+ PX_ASSERT(exists);
+ PX_UNUSED(exists);
+}
+
+
+#if PX_USE_PARTICLE_SYSTEM_API
+PX_FORCE_INLINE void NpScene::removeFromParticleBaseList(PxParticleBase& p)
+{
+ const bool exists = mPxParticleBaseSet.erase(&p);
+ PX_ASSERT(exists);
+ PX_UNUSED(exists);
+}
+#endif
+
+
+#if PX_USE_CLOTH_API
+PX_FORCE_INLINE void NpScene::removeFromClothList(PxCloth& cloth)
+{
+ const bool exists = mPxCloths.erase(&cloth);
+ PX_ASSERT(exists);
+ PX_UNUSED(exists);
+}
+#endif // PX_USE_CLOTH_API
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpSceneQueries.cpp b/PhysX_3.4/Source/PhysX/src/NpSceneQueries.cpp
new file mode 100644
index 00000000..afadf740
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpSceneQueries.cpp
@@ -0,0 +1,836 @@
+// 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 "GuIntersectionRayBox.h"
+#include "PxGeometryQuery.h"
+#include "NpRigidDynamic.h"
+#include "NpQueryShared.h"
+#include "SqPruner.h"
+#include "GuBounds.h"
+#include "GuIntersectionRay.h"
+
+// Synchronous scene queries
+
+using namespace physx;
+using namespace Sq;
+using namespace Gu;
+
+#if PX_SUPPORT_PVD
+#include "NpPvdSceneQueryCollector.h"
+#endif
+
+namespace local
+{
+ // helper class to encapsulate Scb::Actor and Shape together with PxActorShape
+ struct ActorShape : PxActorShape
+ {
+ const Scb::Shape* scbShape;
+ const Scb::Actor* scbActor;
+
+ ActorShape() : PxActorShape() {}
+
+ ActorShape(PxRigidActor* eaActor, PxShape* eaShape, Scb::Shape* sShape, Scb::Actor* sActor) : PxActorShape(eaActor, eaShape)
+ {
+ scbShape = sShape;
+ scbActor = sActor;
+ }
+ };
+
+ // fill the helper actor shape
+ static PX_FORCE_INLINE void populate(const PrunerPayload& payload, ActorShape& as)
+ {
+ Scb::Shape* localShape = reinterpret_cast<Scb::Shape*>(payload.data[0]);
+ Scb::Actor* localActor = reinterpret_cast<Scb::Actor*>(payload.data[1]);
+
+ as.scbShape = localShape;
+ as.scbActor = localActor;
+
+ as.actor = static_cast<PxRigidActor*>(static_cast<const Sc::RigidCore&>(localActor->getActorCore()).getPxActor());
+ as.shape = localShape->getScShape().getPxShape();
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool NpSceneQueries::raycast(
+ const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
+ PxHitCallback<PxRaycastHit>& hits, PxHitFlags hitFlags, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ const PxQueryCache* cache) const
+{
+ PX_PROFILE_ZONE("SceneQuery.raycast", getContextId());
+ NP_READ_CHECK(this);
+ PX_SIMD_GUARD;
+
+ MultiQueryInput input(origin, unitDir, distance);
+ return multiQuery<PxRaycastHit>(input, hits, hitFlags, cache, filterData, filterCall, NULL);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool NpSceneQueries::overlap(
+ const PxGeometry& geometry, const PxTransform& pose, PxOverlapCallback& hits,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall) const
+{
+ PX_PROFILE_ZONE("SceneQuery.overlap", getContextId());
+ NP_READ_CHECK(this);
+ PX_SIMD_GUARD;
+
+ MultiQueryInput input(&geometry, &pose);
+ // we are not supporting cache for overlaps for some reason
+ return multiQuery<PxOverlapHit>(input, hits, PxHitFlags(), NULL, filterData, filterCall, NULL);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+bool NpSceneQueries::sweep(
+ const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
+ PxHitCallback<PxSweepHit>& hits, PxHitFlags hitFlags, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ const PxQueryCache* cache, const PxReal inflation) const
+{
+ PX_PROFILE_ZONE("SceneQuery.sweep", getContextId());
+ NP_READ_CHECK(this);
+ PX_SIMD_GUARD;
+
+#if PX_CHECKED
+ if(!PxGeometryQuery::isValid(geometry))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Provided geometry is not valid");
+ return false;
+ }
+#endif // PX_CHECKED
+
+
+ if((hitFlags & PxHitFlag::ePRECISE_SWEEP) && (hitFlags & PxHitFlag::eMTD))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " Precise sweep doesn't support MTD. Perform MTD with default sweep");
+ hitFlags &= ~PxHitFlag::ePRECISE_SWEEP;
+ }
+
+ if((hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP) && (hitFlags & PxHitFlag::eMTD))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " eMTD cannot be used in conjunction with eASSUME_NO_INITIAL_OVERLAP. eASSUME_NO_INITIAL_OVERLAP will be ignored");
+ hitFlags &= ~PxHitFlag::eASSUME_NO_INITIAL_OVERLAP;
+ }
+
+ PxReal realInflation = inflation;
+ if((hitFlags & PxHitFlag::ePRECISE_SWEEP)&& inflation > 0.f)
+ {
+ realInflation = 0.f;
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, " Precise sweep doesn't support inflation, inflation will be overwritten to be zero");
+ }
+ MultiQueryInput input(&geometry, &pose, unitDir, distance, realInflation);
+ return multiQuery<PxSweepHit>(input, hits, hitFlags, cache, filterData, filterCall, NULL);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+//========================================================================================================================
+
+static PX_FORCE_INLINE bool applyAllPreFiltersSQ(
+ const local::ActorShape* as, PxQueryHitType::Enum& hitType, const PxQueryFlags& inFilterFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ const NpSceneQueries& scene, BatchQueryFilterData* bfd, PxHitFlags& queryFlags, PxU32 /*maxNbTouches*/)
+{
+ if(!applyClientFilter(as->scbActor, filterData, scene))
+ return false;
+
+ // AP: the !bfd clause is here because there's no other way to pass data to BQ pre/post filter shaders
+ // For normal query the data can be passed with inherited callback instance
+ // So if for BQ SPU filter shader the user tries to pass data via FD, the equation will always cut it out
+ // AP scaffold TODO: once SPU is officially phased out we can remove the !bfd clause, fix broken UTs (that are wrong)
+ // and also remove support for filter shaders
+ if(!bfd && !applyFilterEquation(*as->scbShape, filterData.data))
+ return false;
+
+ if((inFilterFlags & PxQueryFlag::ePREFILTER) && (filterCall || bfd))
+ {
+ PxHitFlags outQueryFlags = queryFlags;
+
+ if(filterCall)
+ hitType = filterCall->preFilter(filterData.data, as->shape, as->actor, outQueryFlags);
+ else if(bfd->preFilterShader)
+ hitType = bfd->preFilterShader(
+ filterData.data, as->scbShape->getScShape().getQueryFilterData(),
+ bfd->filterShaderData, bfd->filterShaderDataSize, outQueryFlags);
+
+ // AP: at this point the callback might return eTOUCH but the touch buffer can be empty, the hit will be discarded
+ //PX_CHECK_MSG(hitType == PxQueryHitType::eTOUCH ? maxNbTouches > 0 : true,
+ // "SceneQuery: preFilter returned eTOUCH but empty touch buffer was provided, hit discarded.");
+
+ queryFlags = (queryFlags & ~PxHitFlag::eMODIFIABLE_FLAGS) | (outQueryFlags & PxHitFlag::eMODIFIABLE_FLAGS);
+ }
+ // test passed, continue to return as;
+ return true;
+}
+
+//========================================================================================================================
+// performs a single geometry query for any HitType (PxSweepHit, PxOverlapHit, PxRaycastHit)
+template<typename HitType>
+struct GeomQueryAny
+{
+ static PX_FORCE_INLINE PxU32 geomHit(
+ const NpSceneQueries& sceneQueries, const MultiQueryInput& input, const ShapeData& sd,
+ const PxGeometry& sceneGeom, const PxTransform& pose, PxHitFlags hitFlags,
+ PxU32 maxHits, HitType* hits, const PxReal shrunkMaxDistance, PxBounds3* precomputedBounds)
+ {
+ const PxGeometry& geom0 = *input.geometry;
+ const PxTransform& pose0 = *input.pose;
+ const PxGeometry& geom1 = sceneGeom;
+ const PxTransform& pose1 = pose;
+
+ // Handle raycasts
+ if(HitTypeSupport<HitType>::IsRaycast)
+ {
+ // the test for mesh AABB is archived in //sw/physx/dev/apokrovsky/graveyard/sqMeshAABBTest.cpp
+ // TODO: investigate performance impact (see US12801)
+ PX_CHECK_AND_RETURN_VAL(input.getDir().isFinite(), "PxScene::raycast(): rayDir is not valid.", 0);
+ PX_CHECK_AND_RETURN_VAL(input.getOrigin().isFinite(), "PxScene::raycast(): rayOrigin is not valid.", 0);
+ PX_CHECK_AND_RETURN_VAL(pose1.isValid(), "PxScene::raycast(): pose is not valid.", 0);
+ PX_CHECK_AND_RETURN_VAL(shrunkMaxDistance >= 0.0f, "PxScene::raycast(): maxDist is negative.", 0);
+ PX_CHECK_AND_RETURN_VAL(PxIsFinite(shrunkMaxDistance), "PxScene::raycast(): maxDist is not valid.", 0);
+ PX_CHECK_AND_RETURN_VAL(PxAbs(input.getDir().magnitudeSquared()-1)<1e-4f,
+ "PxScene::raycast(): ray direction must be unit vector.", 0);
+
+ // PT: TODO: investigate perf difference
+ const RaycastFunc func = sceneQueries.mCachedRaycastFuncs[geom1.getType()];
+ return func(geom1, pose1, input.getOrigin(), input.getDir(), shrunkMaxDistance,
+ hitFlags, maxHits, reinterpret_cast<PxRaycastHit*>(hits));
+ }
+ // Handle sweeps
+ else if(HitTypeSupport<HitType>::IsSweep)
+ {
+ PX_ASSERT(precomputedBounds != NULL);
+ // b0 = query shape bounds
+ // b1 = scene shape bounds
+ // AP: Here we clip the sweep to bounds with sum of extents. This is needed for GJK stability.
+ // because sweep is equivalent to a raycast vs a scene shape with inflated bounds.
+ // This also may (or may not) provide an optimization for meshes because top level of rtree has multiple boxes
+ // and there is no bounds test for the whole mesh elsewhere
+ PxBounds3 b0 = *precomputedBounds, b1;
+ // compute the scene geometry bounds
+ Gu::computeBounds(b1, sceneGeom, pose, 0.0f, NULL, 1.0f, false);
+ const PxVec3 combExt = (b0.getExtents() + b1.getExtents())*1.01f;
+
+ PxF32 tnear, tfar;
+ if(!intersectRayAABB2(-combExt, combExt, b0.getCenter() - b1.getCenter(), input.getDir(), shrunkMaxDistance, tnear, tfar)) // returns (tnear<tfar)
+ if(tnear>tfar) // this second test is needed because shrunkMaxDistance can be 0 for 0 length sweep
+ return 0;
+ PX_ASSERT(input.getDir().isNormalized());
+ // tfar is now the t where the ray exits the AABB. input.getDir() is normalized
+
+ const PxVec3& unitDir = input.getDir();
+ PxSweepHit& sweepHit = reinterpret_cast<PxSweepHit&>(hits[0]);
+
+ // if we don't start inside the AABB box, offset the start pos, because of precision issues with large maxDist
+ const bool offsetPos = (tnear > GU_RAY_SURFACE_OFFSET);
+ const PxReal offset = offsetPos ? (tnear - GU_RAY_SURFACE_OFFSET) : 0.0f;
+ const PxVec3 offsetVec(offsetPos ? (unitDir*offset) : PxVec3(0.0f));
+ // we move the geometry we sweep against, so that we avoid the Gu::Capsule/Box recomputation
+ const PxTransform pose1Offset(pose1.p - offsetVec, pose1.q);
+
+ const PxReal distance = PxMin(tfar, shrunkMaxDistance) - offset;
+ const PxReal inflation = input.inflation;
+ PX_CHECK_AND_RETURN_VAL(pose0.isValid(), "PxScene::sweep(): pose0 is not valid.", 0);
+ PX_CHECK_AND_RETURN_VAL(pose1Offset.isValid(), "PxScene::sweep(): pose1 is not valid.", 0);
+ PX_CHECK_AND_RETURN_VAL(unitDir.isFinite(), "PxScene::sweep(): unitDir is not valid.", 0);
+ PX_CHECK_AND_RETURN_VAL(PxIsFinite(distance), "PxScene::sweep(): distance is not valid.", 0);
+ PX_CHECK_AND_RETURN_VAL((distance >= 0.0f && !(hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP)) || distance > 0.0f,
+ "PxScene::sweep(): sweep distance must be >=0 or >0 with eASSUME_NO_INITIAL_OVERLAP.", 0);
+
+ PxU32 retVal = 0;
+ const GeomSweepFuncs& sf = sceneQueries.mCachedSweepFuncs;
+ switch(geom0.getType())
+ {
+ case PxGeometryType::eSPHERE:
+ {
+ const PxSphereGeometry& sphereGeom = static_cast<const PxSphereGeometry&>(geom0);
+ // PT: TODO: technically this capsule with 0.0 half-height is invalid ("isValid" returns false)
+ const PxCapsuleGeometry capsuleGeom(sphereGeom.radius, 0.0f);
+ const Capsule worldCapsule(pose0.p, pose0.p, sphereGeom.radius); // AP: precompute?
+ const bool precise = hitFlags & PxHitFlag::ePRECISE_SWEEP;
+ const SweepCapsuleFunc func = precise ? sf.preciseCapsuleMap[geom1.getType()] : sf.capsuleMap[geom1.getType()];
+ retVal = PxU32(func(geom1, pose1Offset, capsuleGeom, pose0, worldCapsule, unitDir, distance, sweepHit, hitFlags, inflation));
+ }
+ break;
+
+ case PxGeometryType::eCAPSULE:
+ {
+ const bool precise = hitFlags & PxHitFlag::ePRECISE_SWEEP;
+ const SweepCapsuleFunc func = precise ? sf.preciseCapsuleMap[geom1.getType()] : sf.capsuleMap[geom1.getType()];
+ retVal = PxU32(func(geom1, pose1Offset, static_cast<const PxCapsuleGeometry&>(geom0), pose0, sd.getGuCapsule(), unitDir, distance, sweepHit, hitFlags, inflation));
+ }
+ break;
+
+ case PxGeometryType::eBOX:
+ {
+ const bool precise = hitFlags & PxHitFlag::ePRECISE_SWEEP;
+ const SweepBoxFunc func = precise ? sf.preciseBoxMap[geom1.getType()] : sf.boxMap[geom1.getType()];
+ retVal = PxU32(func(geom1, pose1Offset, static_cast<const PxBoxGeometry&>(geom0), pose0, sd.getGuBox(), unitDir, distance, sweepHit, hitFlags, inflation));
+ }
+ break;
+
+ case PxGeometryType::eCONVEXMESH:
+ {
+ const PxConvexMeshGeometry& convexGeom = static_cast<const PxConvexMeshGeometry&>(geom0);
+ const SweepConvexFunc func = sf.convexMap[geom1.getType()];
+ retVal = PxU32(func(geom1, pose1Offset, convexGeom, pose0, unitDir, distance, sweepHit, hitFlags, inflation));
+ }
+ break;
+ case PxGeometryType::ePLANE:
+ case PxGeometryType::eTRIANGLEMESH:
+ case PxGeometryType::eHEIGHTFIELD:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxScene::sweep(): first geometry object parameter must be sphere, capsule, box or convex geometry.");
+ break;
+ }
+ if (retVal)
+ {
+ // we need to offset the distance back
+ sweepHit.distance += offset;
+ // we need to offset the hit position back as we moved the geometry we sweep against
+ sweepHit.position += offsetVec;
+ }
+ return retVal;
+ }
+ // Handle overlaps
+ else if(HitTypeSupport<HitType>::IsOverlap)
+ {
+ const GeomOverlapTable* overlapFuncs = sceneQueries.mCachedOverlapFuncs;
+ return PxU32(Gu::overlap(geom0, pose0, geom1, pose1, overlapFuncs));
+ }
+ else
+ {
+ PX_ALWAYS_ASSERT_MESSAGE("Unexpected template expansion in GeomQueryAny::geomHit");
+ return 0;
+ }
+ }
+};
+
+// struct to access protected data members in the public PxHitCallback API
+template<typename HitType>
+struct MultiQueryCallback : public PrunerCallback
+{
+ const NpSceneQueries& mScene;
+ const MultiQueryInput& mInput;
+ PxHitCallback<HitType>& mHitCall;
+ const PxHitFlags mHitFlags;
+ const PxQueryFilterData& mFilterData;
+ PxQueryFilterCallback* mFilterCall;
+ PxReal mShrunkDistance;
+ BatchQueryFilterData* mBfd; // only not NULL for batch queries
+ const PxHitFlags mMeshAnyHitFlags;
+ bool mReportTouchesAgain;
+ bool mFarBlockFound; // this is to prevent repeated searches for far block
+ bool mNoBlock;
+ const bool mAnyHit;
+ bool mIsCached; // is this call coming as a callback from the pruner or a single item cached callback?
+
+ // The reason we need these bounds is because we need to know combined(inflated shape) bounds to clip the sweep path
+ // to be tolerable by GJK precision issues. This test is done for (queryShape vs touchedShapes)
+ // So it makes sense to cache the bounds for sweep query shape, otherwise we'd have to recompute them every time
+ // Currently only used for sweeps.
+ PxBounds3 mQueryShapeBounds;
+ bool mQueryShapeBoundsValid;
+ const ShapeData* mShapeData;
+
+ MultiQueryCallback(
+ const NpSceneQueries& scene, const MultiQueryInput& input, bool anyHit, PxHitCallback<HitType>& hitCall, PxHitFlags hitFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall, PxReal shrunkDistance, BatchQueryFilterData* aBfd) :
+ mScene (scene),
+ mInput (input),
+ mHitCall (hitCall),
+ mHitFlags (hitFlags),
+ mFilterData (filterData),
+ mFilterCall (filterCall),
+ mShrunkDistance (shrunkDistance),
+ mBfd (aBfd),
+ mMeshAnyHitFlags ((hitFlags.isSet(PxHitFlag::eMESH_ANY) || anyHit) ? PxHitFlag::eMESH_ANY : PxHitFlag::eDISTANCE),
+ mReportTouchesAgain (true),
+ mFarBlockFound (filterData.flags & PxQueryFlag::eNO_BLOCK),
+ mNoBlock (filterData.flags & PxQueryFlag::eNO_BLOCK),
+ mAnyHit (anyHit),
+ mIsCached (false),
+ mQueryShapeBoundsValid (false),
+ mShapeData (NULL)
+ {
+ }
+
+ virtual PxAgain invoke(PxReal& aDist, const PrunerPayload& aPayload)
+ {
+ const PxU32 tempCount = 1;
+ HitType tempBuf[tempCount];
+
+ // PT: TODO: do we need actorShape.actor/actorShape.shape immediately?
+ local::ActorShape actorShape;
+ local::populate(aPayload, actorShape);
+
+ const PxQueryFlags filterFlags = mFilterData.flags;
+
+ // for no filter callback, default to eTOUCH for MULTIPLE, eBLOCK otherwise
+ // also always treat as eBLOCK if currently tested shape is cached
+ // Using eRESERVED flag as a special condition to default to eTOUCH hits while only looking for a single blocking hit
+ // from a nested query (see other comments containing #LABEL1)
+ PxQueryHitType::Enum shapeHitType =
+ ((mHitCall.maxNbTouches || (mFilterData.flags & PxQueryFlag::eRESERVED)) && !mIsCached)
+ ? PxQueryHitType::eTOUCH
+ : PxQueryHitType::eBLOCK;
+
+ // apply pre-filter
+ PxHitFlags filteredHitFlags = mHitFlags;
+ if(!mIsCached) // don't run filters on single item cache
+ if(!applyAllPreFiltersSQ(&actorShape, shapeHitType/*in&out*/, filterFlags, mFilterData, mFilterCall,
+ mScene, mBfd, filteredHitFlags, mHitCall.maxNbTouches))
+ return true; // skip this shape from reporting if prefilter said to do so
+ if(shapeHitType == PxQueryHitType::eNONE)
+ return true;
+
+ PX_ASSERT(actorShape.actor && actorShape.shape);
+ const Scb::Shape* shape = actorShape.scbShape;
+ const Scb::Actor* actor = actorShape.scbActor;
+
+ // compute the global pose for the cached shape and actor
+ PX_ALIGN(16, PxTransform) globalPose;
+ NpActor::getGlobalPose(globalPose, *shape, *actor);
+
+ const PxGeometry& shapeGeom = shape->getGeometry();
+
+ // Here we decide whether to use the user provided buffer in place or a local stack buffer
+ // see if we have more room left in the callback results buffer than in the parent stack buffer
+ // if so get subHits in-place in the hit buffer instead of the parent stack buffer
+ // nbTouches is the number of accumulated touch hits so far
+ // maxNbTouches is the size of the user buffer
+ PxU32 maxSubHits1 = mHitCall.maxNbTouches - mHitCall.nbTouches; // how much room is left in the user buffer
+ HitType* subHits1 = mHitCall.touches + mHitCall.nbTouches; // pointer to the first free hit in the user buffer
+ if(mHitCall.nbTouches >= mHitCall.maxNbTouches)
+ // if there's no room left in the user buffer, use a stack buffer
+ {
+ // tried using 64 here - causes check stack code to get generated on xbox, perhaps because of guard page
+ // need this buffer in case the input buffer is full but we still want to correctly merge results from later hits
+ maxSubHits1 = tempCount;
+ subHits1 = reinterpret_cast<HitType*>(tempBuf);
+ }
+
+ // limit number of hits to 1 for meshes if eMESH_MULTIPLE wasn't specified. this tells geomQuery to only look for a closest hit
+ if(shapeGeom.getType() == PxGeometryType::eTRIANGLEMESH && !(filteredHitFlags & PxHitFlag::eMESH_MULTIPLE))
+ maxSubHits1 = 1; // required to only receive 1 hit to pass UTs
+ // call the geometry specific intersection template
+ PxU32 nbSubHits = GeomQueryAny<HitType>::geomHit(
+ mScene, mInput, *mShapeData, shapeGeom, globalPose,
+ filteredHitFlags | mMeshAnyHitFlags,
+ maxSubHits1, subHits1, mShrunkDistance, mQueryShapeBoundsValid ? &mQueryShapeBounds : NULL);
+
+ // ------------------------- iterate over geometry subhits -----------------------------------
+ for (PxU32 iSubHit = 0; iSubHit < nbSubHits; iSubHit++)
+ {
+ HitType& hit = subHits1[iSubHit];
+ hit.actor = actorShape.actor;
+ hit.shape = actorShape.shape;
+
+ // some additional processing only for sweep hits with initial overlap
+ if(HitTypeSupport<HitType>::IsSweep && HITDIST(hit) == 0.0f && !(filteredHitFlags & PxHitFlag::eMTD))
+ // PT: necessary as some leaf routines are called with reversed params, thus writing +unitDir there.
+ // AP: apparently still necessary to also do in Gu because Gu can be used standalone (without SQ)
+ reinterpret_cast<PxSweepHit&>(hit).normal = -mInput.getDir();
+
+ // start out with hitType for this cached shape set to a pre-filtered hit type
+ PxQueryHitType::Enum hitType = shapeHitType;
+
+ // run the post-filter if specified in filterFlags and filterCall is non-NULL
+ if(!mIsCached && (mFilterCall || mBfd) && (filterFlags & PxQueryFlag::ePOSTFILTER))
+ {
+ if(mFilterCall)
+ hitType = mFilterCall->postFilter(mFilterData.data, hit);
+ else if(mBfd->postFilterShader)
+ hitType = mBfd->postFilterShader(
+ mFilterData.data, actorShape.scbShape->getScShape().getQueryFilterData(),
+ mBfd->filterShaderData, mBfd->filterShaderDataSize, hit);
+ }
+
+ // early out on any hit if eANY_HIT was specified, regardless of hit type
+ if(mAnyHit && hitType != PxQueryHitType::eNONE)
+ {
+ // block or touch qualifies for qType=ANY type hit => return it as blocking according to spec. Ignore eNONE.
+ mHitCall.block = hit;
+ mHitCall.hasBlock = true;
+ return false; // found a hit for ANY qType, can early exit now
+ }
+
+ if(mNoBlock)
+ hitType = PxQueryHitType::eTOUCH;
+
+ PX_WARN_ONCE_IF(HitTypeSupport<HitType>::IsOverlap && hitType == PxQueryHitType::eBLOCK,
+ "eBLOCK returned from user filter for overlap() query. This may cause undesired behavior. "
+ "Consider using PxQueryFlag::eNO_BLOCK for overlap queries.");
+
+ if(hitType == PxQueryHitType::eTOUCH)
+ {
+ // -------------------------- handle eTOUCH hits ---------------------------------
+ // for qType=multiple, store the hit. For other qTypes ignore it.
+ // <= is important for initially overlapping sweeps
+ #if PX_CHECKED
+ if(mHitCall.maxNbTouches == 0 && !mBfd && !mFilterData.flags.isSet(PxQueryFlag::eRESERVED))
+ // issue a warning if eTOUCH was returned by the prefilter, we have 0 touch buffer and not a batch query
+ // not doing for BQ because the touches buffer can be overflown and thats ok by spec
+ // eRESERVED to avoid a warning from nested callback (closest blocking hit recursive search)
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "User filter returned PxQueryHitType::eTOUCH but the touches buffer was empty. Hit was discarded.");
+ #endif
+
+ if(mHitCall.maxNbTouches && mReportTouchesAgain && HITDIST(hit) <= mShrunkDistance)
+ {
+ // Buffer full: need to find the closest blocking hit, clip touch hits and flush the buffer
+ if(mHitCall.nbTouches == mHitCall.maxNbTouches)
+ {
+ // issue a second nested query just looking for the closest blocking hit
+ // could do better perf-wise by saving traversal state (start looking for blocking from this point)
+ // but this is not a perf critical case because users can provide a bigger buffer
+ // that covers non-degenerate cases
+ // far block search doesn't apply to overlaps because overlaps don't work with blocking hits
+ if(HitTypeSupport<HitType>::IsOverlap == 0)
+ {
+ // AP: the use of eRESERVED is a bit tricky, see other comments containing #LABEL1
+ PxQueryFilterData fd1 = mFilterData; fd1.flags |= PxQueryFlag::eRESERVED;
+ PxHitBuffer<HitType> buf1; // create a temp callback buffer for a single blocking hit
+ if(!mFarBlockFound && mHitCall.maxNbTouches > 0 && mScene.NpSceneQueries::multiQuery<HitType>(
+ mInput, buf1, mHitFlags, NULL, fd1, mFilterCall, mBfd))
+ {
+ mHitCall.block = buf1.block;
+ mHitCall.hasBlock = true;
+ mHitCall.nbTouches =
+ clipHitsToNewMaxDist<HitType>(mHitCall.touches, mHitCall.nbTouches, HITDIST(buf1.block));
+ mShrunkDistance = HITDIST(buf1.block);
+ aDist = mShrunkDistance;
+ }
+ mFarBlockFound = true;
+ }
+ if(mHitCall.nbTouches == mHitCall.maxNbTouches)
+ {
+ mReportTouchesAgain = mHitCall.processTouches(mHitCall.touches, mHitCall.nbTouches);
+ if(!mReportTouchesAgain)
+ return false; // optimization - buffer is full
+ else
+ mHitCall.nbTouches = 0; // reset nbTouches so we can continue accumulating again
+ }
+ }
+
+ //if(hitCall.nbTouches < hitCall.maxNbTouches) // can be true if maxNbTouches is 0
+ mHitCall.touches[mHitCall.nbTouches++] = hit;
+ } // if(hitCall.maxNbTouches && reportTouchesAgain && HITDIST(hit) <= shrunkDistance)
+ } // if(hitType == PxQueryHitType::eTOUCH)
+ else if(hitType == PxQueryHitType::eBLOCK)
+ {
+ // -------------------------- handle eBLOCK hits ----------------------------------
+ // only eBLOCK qualifies as a closest hit candidate => compare against best distance and store
+ // <= is needed for eTOUCH hits to be recorded correctly vs same eBLOCK distance for overlaps
+ if(HITDIST(hit) <= mShrunkDistance)
+ {
+ if(HitTypeSupport<HitType>::IsOverlap == 0)
+ {
+ mShrunkDistance = HITDIST(hit);
+ aDist = mShrunkDistance;
+ }
+ mHitCall.block = hit;
+ mHitCall.hasBlock = true;
+ }
+ } // if(hitType == eBLOCK)
+ else {
+ PX_ASSERT(hitType == PxQueryHitType::eNONE);
+ }
+ } // for iSubHit
+ return true;
+ }
+
+private:
+ MultiQueryCallback<HitType>& operator=(const MultiQueryCallback<HitType>&);
+};
+
+//========================================================================================================================
+#if PX_SUPPORT_PVD
+template<typename HitType>
+struct CapturePvdOnReturn : public PxHitCallback<HitType>
+{
+ // copy the arguments of multiQuery into a struct, this is strictly for PVD recording
+ const NpSceneQueries* mSQ;
+ const MultiQueryInput& mInput;
+ PxHitFlags mHitFlags; // PT: TODO: this is not used!
+ const PxQueryCache* mCache; // PT: TODO: this is not used!
+ const PxQueryFilterData& mFilterData;
+ PxQueryFilterCallback* mFilterCall; // PT: TODO: this is not used!
+ BatchQueryFilterData* mBFD; // PT: TODO: check if this is sometimes not NULL
+ Ps::Array<HitType> mAllHits;
+ PxHitCallback<HitType>& mParentCallback;
+
+ CapturePvdOnReturn(
+ const NpSceneQueries* sq, const MultiQueryInput& input, PxHitFlags hitFlags,
+ const PxQueryCache* cache, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ BatchQueryFilterData* bfd, PxHitCallback<HitType>& parentCallback) :
+ PxHitCallback<HitType> (parentCallback.touches, parentCallback.maxNbTouches),
+ mSQ (sq),
+ mInput (input),
+ mHitFlags (hitFlags),
+ mCache (cache),
+ mFilterData (filterData),
+ mFilterCall (filterCall),
+ mBFD (bfd),
+ mParentCallback (parentCallback)
+ {}
+
+ virtual PxAgain processTouches(const HitType* hits, PxU32 nbHits)
+ {
+ const PxAgain again = mParentCallback.processTouches(hits, nbHits);
+ for(PxU32 i=0; i<nbHits; i++)
+ mAllHits.pushBack(hits[i]);
+ return again;
+ }
+
+ ~CapturePvdOnReturn()
+ {
+ const physx::Vd::ScbScenePvdClient& pvdClient = mSQ->getScene().getScenePvdClient();
+ if(!(pvdClient.isConnected() && (pvdClient.getScenePvdFlags() & PxPvdSceneFlag::eTRANSMIT_SCENEQUERIES)))
+ return;
+
+ physx::Vd::PvdSceneQueryCollector& collector = mBFD ? mSQ->getBatchedSqCollector() : mSQ->getSingleSqCollector();
+
+ if(mParentCallback.nbTouches)
+ {
+ for(PxU32 i = 0; i < mParentCallback.nbTouches; i++)
+ mAllHits.pushBack(mParentCallback.touches[i]);
+ }
+
+ if(mParentCallback.hasBlock)
+ mAllHits.pushBack(mParentCallback.block);
+
+ // PT: TODO: why do we need reinterpret_casts below?
+ if(HitTypeSupport<HitType>::IsRaycast)
+ collector.raycast (mInput.getOrigin(), mInput.getDir(), mInput.maxDistance, reinterpret_cast<PxRaycastHit*>(mAllHits.begin()), mAllHits.size(), mFilterData, this->maxNbTouches!=0);
+ else if(HitTypeSupport<HitType>::IsOverlap)
+ collector.overlapMultiple (*mInput.geometry, *mInput.pose, reinterpret_cast<PxOverlapHit*>(mAllHits.begin()), mAllHits.size(), mFilterData);
+ else if(HitTypeSupport<HitType>::IsSweep)
+ collector.sweep (*mInput.geometry, *mInput.pose, mInput.getDir(), mInput.maxDistance, reinterpret_cast<PxSweepHit*>(mAllHits.begin()), mAllHits.size(), mFilterData, this->maxNbTouches!=0);
+ }
+
+private:
+ CapturePvdOnReturn<HitType>& operator=(const CapturePvdOnReturn<HitType>&);
+};
+#endif // PX_SUPPORT_PVD
+
+//========================================================================================================================
+template<typename HitType>
+struct IssueCallbacksOnReturn
+{
+ PxHitCallback<HitType>& hits;
+ PxAgain again; // query was stopped by previous processTouches. This means that nbTouches is still non-zero
+ // but we don't need to issue processTouches again
+ PX_FORCE_INLINE IssueCallbacksOnReturn(PxHitCallback<HitType>& aHits) : hits(aHits)
+ {
+ again = true;
+ }
+
+ ~IssueCallbacksOnReturn()
+ {
+ if(again)
+ // only issue processTouches if query wasn't stopped
+ // this is because nbTouches doesn't get reset to 0 in this case (according to spec)
+ // and the touches in touches array were already processed by the callback
+ {
+ if(hits.hasBlock && hits.nbTouches)
+ hits.nbTouches = clipHitsToNewMaxDist<HitType>(hits.touches, hits.nbTouches, HITDIST(hits.block));
+ if(hits.nbTouches)
+ {
+ bool again_ = hits.processTouches(hits.touches, hits.nbTouches);
+ if(again_)
+ hits.nbTouches = 0;
+ }
+ }
+ hits.finalizeQuery();
+ }
+
+private:
+ IssueCallbacksOnReturn<HitType>& operator=(const IssueCallbacksOnReturn<HitType>&);
+};
+
+#undef HITDIST
+
+//========================================================================================================================
+template<typename HitType>
+bool NpSceneQueries::multiQuery(
+ const MultiQueryInput& input, PxHitCallback<HitType>& hits, PxHitFlags hitFlags, const PxQueryCache* cache,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall, BatchQueryFilterData* bfd) const
+{
+ const bool anyHit = (filterData.flags & PxQueryFlag::eANY_HIT) == PxQueryFlag::eANY_HIT;
+
+ PxI32 retval = 0; PX_UNUSED(retval);
+
+ if(HitTypeSupport<HitType>::IsRaycast == 0)
+ {
+ PX_CHECK_AND_RETURN_VAL(input.pose != NULL, "NpSceneQueries::overlap/sweep pose is NULL.", 0);
+ PX_CHECK_AND_RETURN_VAL(input.pose->isValid(), "NpSceneQueries::overlap/sweep pose is not valid.", 0);
+ }
+ else
+ {
+ PX_CHECK_AND_RETURN_VAL(input.getOrigin().isFinite(), "NpSceneQueries::raycast pose is not valid.", 0);
+ }
+
+ if(HitTypeSupport<HitType>::IsOverlap == 0)
+ {
+ PX_CHECK_AND_RETURN_VAL(input.getDir().isFinite(), "NpSceneQueries multiQuery input check: unitDir is not valid.", 0);
+ PX_CHECK_AND_RETURN_VAL(input.getDir().isNormalized(), "NpSceneQueries multiQuery input check: direction must be normalized", 0);
+ }
+
+ if(HitTypeSupport<HitType>::IsRaycast)
+ {
+ PX_CHECK_AND_RETURN_VAL(input.maxDistance > 0.0f, "NpSceneQueries::multiQuery input check: distance cannot be negative or zero", 0);
+ }
+
+ if(HitTypeSupport<HitType>::IsOverlap && !anyHit)
+ {
+ PX_CHECK_AND_RETURN_VAL(hits.maxNbTouches > 0, "PxScene::overlap() and PxBatchQuery::overlap() calls without eANY_HIT flag require a touch hit buffer for return results.", 0);
+ }
+
+ if(HitTypeSupport<HitType>::IsSweep)
+ {
+ PX_CHECK_AND_RETURN_VAL(input.maxDistance >= 0.0f, "NpSceneQueries multiQuery input check: distance cannot be negative", 0);
+ PX_CHECK_AND_RETURN_VAL(input.maxDistance != 0.0f || !(hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP),
+ "NpSceneQueries multiQuery input check: zero-length sweep only valid without the PxHitFlag::eASSUME_NO_INITIAL_OVERLAP flag", 0);
+ }
+
+ PX_CHECK_MSG(!cache || (cache && cache->shape && cache->actor), "Raycast cache specified but shape or actor pointer is NULL!");
+ const PrunerData cacheData = cache ? NpActor::getShapeManager(*cache->actor)->findSceneQueryData(*static_cast<NpShape*>(cache->shape)) : SQ_INVALID_PRUNER_DATA;
+
+ // this function is logically const for the SDK user, as flushUpdates() will not have an API-visible effect on this object
+ // internally however, flushUpdates() changes the states of the Pruners in mSQManager
+ // because here is the only place we need this, const_cast instead of making SQM mutable
+ const_cast<NpSceneQueries*>(this)->mSQManager.flushUpdates();
+
+#if PX_SUPPORT_PVD
+ CapturePvdOnReturn<HitType> pvdCapture(this, input, hitFlags, cache, filterData, filterCall, bfd, hits);
+#endif
+
+ IssueCallbacksOnReturn<HitType> cbr(hits); // destructor will execute callbacks on return from this function
+ hits.hasBlock = false;
+ hits.nbTouches = 0;
+
+ PxReal shrunkDistance = HitTypeSupport<HitType>::IsOverlap ? PX_MAX_REAL : input.maxDistance; // can be progressively shrunk as we go over the list of shapes
+ if(HitTypeSupport<HitType>::IsSweep)
+ shrunkDistance = PxMin(shrunkDistance, PX_MAX_SWEEP_DISTANCE);
+ MultiQueryCallback<HitType> pcb(*this, input, anyHit, hits, hitFlags, filterData, filterCall, shrunkDistance, bfd);
+
+ if(cacheData!=SQ_INVALID_PRUNER_DATA && hits.maxNbTouches == 0) // don't use cache for queries that can return touch hits
+ {
+ // this block is only executed for single shape cache
+ const PrunerPayload& cachedPayload = mSQManager.getPayload(cacheData);
+ pcb.mIsCached = true;
+ PxReal dummyDist;
+
+ PxAgain againAfterCache;
+ if(HitTypeSupport<HitType>::IsSweep)
+ {
+ // AP: for sweeps we cache the bounds because we need to know them for the test to clip the sweep to bounds
+ // otherwise GJK becomes unstable. The bounds can be used multiple times so this is an optimization.
+ const ShapeData sd(*input.geometry, *input.pose, input.inflation);
+ pcb.mQueryShapeBounds = sd.getPrunerInflatedWorldAABB();
+ pcb.mQueryShapeBoundsValid = true;
+ pcb.mShapeData = &sd;
+ againAfterCache = pcb.invoke(dummyDist, cachedPayload);
+ pcb.mShapeData = NULL;
+ } else
+ againAfterCache = pcb.invoke(dummyDist, cachedPayload);
+ pcb.mIsCached = false;
+ if(!againAfterCache) // if PxAgain result for cached shape was false (abort query), return here
+ return hits.hasAnyHits();
+ }
+
+ const Pruner* staticPruner = mSQManager.get(PruningIndex::eSTATIC).pruner();
+ const Pruner* dynamicPruner = mSQManager.get(PruningIndex::eDYNAMIC).pruner();
+
+ const PxU32 doStatics = filterData.flags & PxQueryFlag::eSTATIC;
+ const PxU32 doDynamics = filterData.flags & PxQueryFlag::eDYNAMIC;
+
+ if(HitTypeSupport<HitType>::IsRaycast)
+ {
+ bool again = doStatics ? staticPruner->raycast(input.getOrigin(), input.getDir(), pcb.mShrunkDistance, pcb) : true;
+ if(!again)
+ return hits.hasAnyHits();
+
+ if(doDynamics)
+ again = dynamicPruner->raycast(input.getOrigin(), input.getDir(), pcb.mShrunkDistance, pcb);
+
+ cbr.again = again; // update the status to avoid duplicate processTouches()
+ return hits.hasAnyHits();
+ }
+ else if(HitTypeSupport<HitType>::IsOverlap)
+ {
+ PX_ASSERT(input.geometry);
+
+ const ShapeData sd(*input.geometry, *input.pose, input.inflation);
+ pcb.mShapeData = &sd;
+ PxAgain again = doStatics ? staticPruner->overlap(sd, pcb) : true;
+ if(!again) // && (filterData.flags & PxQueryFlag::eANY_HIT))
+ return hits.hasAnyHits();
+
+ if(doDynamics)
+ again = dynamicPruner->overlap(sd, pcb);
+
+ cbr.again = again; // update the status to avoid duplicate processTouches()
+ return hits.hasAnyHits();
+ }
+ else
+ {
+ PX_ASSERT(HitTypeSupport<HitType>::IsSweep);
+ PX_ASSERT(input.geometry);
+
+ const ShapeData sd(*input.geometry, *input.pose, input.inflation);
+ pcb.mQueryShapeBounds = sd.getPrunerInflatedWorldAABB();
+ pcb.mQueryShapeBoundsValid = true;
+ pcb.mShapeData = &sd;
+ PxAgain again = doStatics ? staticPruner->sweep(sd, input.getDir(), pcb.mShrunkDistance, pcb) : true;
+ if(!again)
+ return hits.hasAnyHits();
+
+ if(doDynamics)
+ again = dynamicPruner->sweep(sd, input.getDir(), pcb.mShrunkDistance, pcb);
+
+ cbr.again = again; // update the status to avoid duplicate processTouches()
+ return hits.hasAnyHits();
+ }
+}
+
+
+// explicit instantiations for multiQuery to fix link errors on android
+#if !PX_WINDOWS_FAMILY
+#define TMQ(hittype) \
+ template bool NpSceneQueries::multiQuery<hittype>( \
+ const MultiQueryInput& input, PxHitCallback<hittype>& hits, PxHitFlags hitFlags, \
+ const PxQueryCache* cache, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall, \
+ BatchQueryFilterData* bfd) const;
+
+TMQ(PxRaycastHit)
+TMQ(PxOverlapHit)
+TMQ(PxSweepHit)
+
+#undef TMQ
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpSceneQueries.h b/PhysX_3.4/Source/PhysX/src/NpSceneQueries.h
new file mode 100644
index 00000000..3071e43f
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpSceneQueries.h
@@ -0,0 +1,211 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef PX_PHYSICS_NP_SCENEQUERIES
+#define PX_PHYSICS_NP_SCENEQUERIES
+
+#include "PxScene.h"
+#include "PxQueryReport.h"
+#include "PsIntrinsics.h"
+#include "CmPhysXCommon.h"
+#include "SqSceneQueryManager.h"
+#include "GuTriangleMesh.h"
+#include "GuRaycastTests.h"
+#include "GuSweepTests.h"
+#include "GuOverlapTests.h"
+#include "ScbScene.h"
+
+#if PX_SUPPORT_PVD
+#include "NpPvdSceneQueryCollector.h"
+#endif
+
+namespace physx { namespace Sq {
+
+ struct QueryID { enum Enum {
+ QUERY_RAYCAST_ANY_OBJECT,
+ QUERY_RAYCAST_CLOSEST_OBJECT,
+ QUERY_RAYCAST_ALL_OBJECTS,
+
+ QUERY_OVERLAP_SPHERE_ALL_OBJECTS,
+ QUERY_OVERLAP_AABB_ALL_OBJECTS,
+ QUERY_OVERLAP_OBB_ALL_OBJECTS,
+ QUERY_OVERLAP_CAPSULE_ALL_OBJECTS,
+ QUERY_OVERLAP_CONVEX_ALL_OBJECTS,
+
+ QUERY_LINEAR_OBB_SWEEP_CLOSEST_OBJECT,
+ QUERY_LINEAR_CAPSULE_SWEEP_CLOSEST_OBJECT,
+ QUERY_LINEAR_CONVEX_SWEEP_CLOSEST_OBJECT
+ }; };
+}
+
+struct MultiQueryInput
+{
+ const PxVec3* rayOrigin; // only valid for raycasts
+ const PxVec3* unitDir; // only valid for raycasts and sweeps
+ PxReal maxDistance; // only valid for raycasts and sweeps
+ const PxGeometry* geometry; // only valid for overlaps and sweeps
+ const PxTransform* pose; // only valid for overlaps and sweeps
+ PxReal inflation; // only valid for sweeps
+
+ // Raycast constructor
+ MultiQueryInput(const PxVec3& aRayOrigin, const PxVec3& aUnitDir, PxReal aMaxDist)
+ {
+ Ps::prefetchLine(&aRayOrigin);
+ Ps::prefetchLine(&aUnitDir);
+ rayOrigin = &aRayOrigin;
+ unitDir = &aUnitDir;
+ maxDistance = aMaxDist;
+ geometry = NULL;
+ pose = NULL;
+ inflation = 0.0f;
+ }
+
+ // Overlap constructor
+ MultiQueryInput(const PxGeometry* aGeometry, const PxTransform* aPose)
+ {
+ Ps::prefetchLine(aGeometry);
+ Ps::prefetchLine(aPose);
+ geometry = aGeometry;
+ pose = aPose;
+ inflation = 0.0f;
+ rayOrigin = unitDir = NULL;
+ }
+
+ // Sweep constructor
+ MultiQueryInput(
+ const PxGeometry* aGeometry, const PxTransform* aPose,
+ const PxVec3& aUnitDir, const PxReal aMaxDist, const PxReal aInflation)
+ {
+ Ps::prefetchLine(aGeometry);
+ Ps::prefetchLine(aPose);
+ Ps::prefetchLine(&aUnitDir);
+ rayOrigin = NULL;
+ maxDistance = aMaxDist;
+ unitDir = &aUnitDir;
+ geometry = aGeometry;
+ pose = aPose;
+ inflation = aInflation;
+ }
+
+ PX_FORCE_INLINE const PxVec3& getDir() const { PX_ASSERT(unitDir); return *unitDir; }
+ PX_FORCE_INLINE const PxVec3& getOrigin() const { PX_ASSERT(rayOrigin); return *rayOrigin; }
+};
+
+struct BatchQueryFilterData
+{
+ void* filterShaderData;
+ PxU32 filterShaderDataSize;
+ PxBatchQueryPreFilterShader preFilterShader;
+ PxBatchQueryPostFilterShader postFilterShader;
+ #if PX_SUPPORT_PVD
+ Vd::PvdSceneQueryCollector* collector; // gets set to bq collector
+ #endif
+ BatchQueryFilterData(void* fsData, PxU32 fsSize, PxBatchQueryPreFilterShader preFs, PxBatchQueryPostFilterShader postFs)
+ : filterShaderData(fsData), filterShaderDataSize(fsSize), preFilterShader(preFs), postFilterShader(postFs)
+ {
+ #if PX_SUPPORT_PVD
+ collector = NULL;
+ #endif
+ }
+};
+
+class PxGeometry;
+
+class NpSceneQueries : public PxScene
+{
+ PX_NOCOPY(NpSceneQueries)
+
+public:
+ NpSceneQueries(const PxSceneDesc& desc);
+ ~NpSceneQueries();
+
+ template<typename QueryHit>
+ bool multiQuery(
+ const MultiQueryInput& in,
+ PxHitCallback<QueryHit>& hits, PxHitFlags hitFlags, const PxQueryCache* cache,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ BatchQueryFilterData* bqFd) const;
+
+ // Synchronous scene queries
+ virtual bool raycast(
+ const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, // Ray data
+ PxRaycastCallback& hitCall, PxHitFlags hitFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ const PxQueryCache* cache) const;
+
+ virtual bool sweep(
+ const PxGeometry& geometry, const PxTransform& pose, // GeomObject data
+ const PxVec3& unitDir, const PxReal distance, // Ray data
+ PxSweepCallback& hitCall, PxHitFlags hitFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ const PxQueryCache* cache, const PxReal inflation) const;
+
+ virtual bool overlap(
+ const PxGeometry& geometry, const PxTransform& transform, // GeomObject data
+ PxOverlapCallback& hitCall,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall) const;
+
+ PX_FORCE_INLINE PxU64 getContextId() const { return PxU64(reinterpret_cast<size_t>(this)); }
+ PX_FORCE_INLINE Scb::Scene& getScene() { return mScene; }
+ PX_FORCE_INLINE const Scb::Scene& getScene() const { return mScene; }
+ PX_FORCE_INLINE PxU32 getFlagsFast() const { return mScene.getFlags(); }
+ PX_FORCE_INLINE Sq::SceneQueryManager& getSceneQueryManagerFast() { return mSQManager; }
+
+ Scb::Scene mScene;
+ Sq::SceneQueryManager mSQManager;
+
+ const Gu::GeomRaycastTable& mCachedRaycastFuncs;
+ const Gu::GeomSweepFuncs& mCachedSweepFuncs;
+ const Gu::GeomOverlapTable* mCachedOverlapFuncs;
+
+#if PX_SUPPORT_PVD
+public:
+ //Scene query and hits for pvd, collected in current frame
+ mutable Vd::PvdSceneQueryCollector mSingleSqCollector;
+ mutable Vd::PvdSceneQueryCollector mBatchedSqCollector;
+
+PX_FORCE_INLINE Vd::PvdSceneQueryCollector& getSingleSqCollector() const {return mSingleSqCollector;}
+PX_FORCE_INLINE Vd::PvdSceneQueryCollector& getBatchedSqCollector() const {return mBatchedSqCollector;}
+#endif // PX_SUPPORT_PVD
+};
+
+namespace Sq { class AABBPruner; class AABBTreeRuntimeNode; class AABBTree; }
+
+#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
+
+#if PX_VC
+ #pragma warning(pop)
+#endif
+
+} // namespace physx, sq
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpSerializerAdapter.cpp b/PhysX_3.4/Source/PhysX/src/NpSerializerAdapter.cpp
new file mode 100644
index 00000000..c8e2b2be
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpSerializerAdapter.cpp
@@ -0,0 +1,207 @@
+// 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 "GuHeightField.h"
+#include "GuConvexMesh.h"
+#include "GuTriangleMesh.h"
+#include "GuTriangleMeshBV4.h"
+#include "GuTriangleMeshRTree.h"
+#include "NpClothFabric.h"
+#include "NpCloth.h"
+#include "NpParticleSystem.h"
+#include "NpParticleFluid.h"
+
+#include "NpRigidStatic.h"
+#include "NpRigidDynamic.h"
+#include "NpArticulation.h"
+#include "NpArticulationLink.h"
+#include "NpArticulationJoint.h"
+#include "NpMaterial.h"
+#include "NpAggregate.h"
+#include "GuHeightFieldData.h"
+
+#include "SqPruningStructure.h"
+
+#include "PxBase.h"
+#include "PxSerialFramework.h"
+#include "PxSerializer.h"
+#include "PxPhysicsSerialization.h"
+
+namespace physx
+{
+ using namespace physx::Gu;
+
+ template<>
+ void PxSerializerDefaultAdapter<NpRigidDynamic>::exportData(PxBase& obj, PxSerializationContext& s) const
+ {
+ PxU32 classSize = sizeof(NpRigidDynamic);
+ NpRigidDynamic& dynamic = static_cast<NpRigidDynamic&>(obj);
+
+ PxsBodyCore serialCore;
+ size_t address = dynamic.getScbBodyFast().getScBody().getSerialCore(serialCore);
+ PxU32 offset = PxU32(address - reinterpret_cast<size_t>(&dynamic));
+ PX_ASSERT(offset + sizeof(serialCore) <= classSize);
+ s.writeData(&dynamic, offset);
+ s.writeData(&serialCore, sizeof(serialCore));
+ void* tail = reinterpret_cast<PxU8*>(&dynamic) + offset + sizeof(serialCore);
+ s.writeData(tail, classSize - offset - sizeof(serialCore));
+ }
+
+ template<>
+ void PxSerializerDefaultAdapter<NpRigidDynamic>::registerReferences(PxBase& obj, PxSerializationContext& s) const
+ {
+ NpRigidDynamic& dynamic = static_cast<NpRigidDynamic&>(obj);
+
+ s.registerReference(obj, PX_SERIAL_REF_KIND_PXBASE, size_t(&obj));
+
+ struct RequiresCallback : public PxProcessPxBaseCallback
+ {
+ RequiresCallback(physx::PxSerializationContext& c) : context(c) {}
+ RequiresCallback& operator=(const RequiresCallback&) { PX_ASSERT(0); return *this; } //PX_NOCOPY doesn't work for local classes
+ void process(PxBase& base)
+ {
+ context.registerReference(base, PX_SERIAL_REF_KIND_PXBASE, size_t(&base));
+ }
+ PxSerializationContext& context;
+ };
+
+ RequiresCallback callback(s);
+ dynamic.requires(callback);
+ }
+
+ template<>
+ void PxSerializerDefaultAdapter<NpShape>::registerReferences(PxBase& obj, PxSerializationContext& s) const
+ {
+ NpShape& shape = static_cast<NpShape&>(obj);
+
+ s.registerReference(obj, PX_SERIAL_REF_KIND_PXBASE, size_t(&obj));
+
+ struct RequiresCallback : public PxProcessPxBaseCallback
+ {
+ RequiresCallback(physx::PxSerializationContext& c) : context(c) {}
+ RequiresCallback &operator=(const RequiresCallback&) { PX_ASSERT(0); return *this; } //PX_NOCOPY doesn't work for local classes
+ void process(PxBase& base)
+ {
+ PxMaterial* pxMaterial = base.is<PxMaterial>();
+ if (!pxMaterial)
+ {
+ context.registerReference(base, PX_SERIAL_REF_KIND_PXBASE, size_t(&base));
+ }
+ else
+ {
+ //ideally we would move this part to ScShapeCore but we don't yet have a MaterialManager available there.
+ PxU32 index = static_cast<NpMaterial*>(pxMaterial)->getHandle();
+ context.registerReference(base, PX_SERIAL_REF_KIND_MATERIAL_IDX, size_t(index));
+ }
+ }
+ PxSerializationContext& context;
+ };
+
+ RequiresCallback callback(s);
+ shape.requires(callback);
+ }
+
+ template<>
+ bool PxSerializerDefaultAdapter<NpConstraint>::isSubordinate() const
+ {
+ return true;
+ }
+
+ template<>
+ bool PxSerializerDefaultAdapter<NpArticulationJoint>::isSubordinate() const
+ {
+ return true;
+ }
+
+ template<>
+ bool PxSerializerDefaultAdapter<NpArticulationLink>::isSubordinate() const
+ {
+ return true;
+ }
+}
+
+using namespace physx;
+
+void PxRegisterPhysicsSerializers(PxSerializationRegistry& sr)
+{
+ sr.registerSerializer(PxConcreteType::eCONVEX_MESH, PX_NEW_SERIALIZER_ADAPTER(ConvexMesh));
+ sr.registerSerializer(PxConcreteType::eTRIANGLE_MESH_BVH33, PX_NEW_SERIALIZER_ADAPTER(RTreeTriangleMesh));
+ sr.registerSerializer(PxConcreteType::eTRIANGLE_MESH_BVH34, PX_NEW_SERIALIZER_ADAPTER(BV4TriangleMesh));
+ sr.registerSerializer(PxConcreteType::eHEIGHTFIELD, PX_NEW_SERIALIZER_ADAPTER(HeightField));
+ sr.registerSerializer(PxConcreteType::eRIGID_DYNAMIC, PX_NEW_SERIALIZER_ADAPTER(NpRigidDynamic));
+ sr.registerSerializer(PxConcreteType::eRIGID_STATIC, PX_NEW_SERIALIZER_ADAPTER(NpRigidStatic));
+ sr.registerSerializer(PxConcreteType::eSHAPE, PX_NEW_SERIALIZER_ADAPTER(NpShape));
+ sr.registerSerializer(PxConcreteType::eMATERIAL, PX_NEW_SERIALIZER_ADAPTER(NpMaterial));
+ sr.registerSerializer(PxConcreteType::eCONSTRAINT, PX_NEW_SERIALIZER_ADAPTER(NpConstraint));
+ sr.registerSerializer(PxConcreteType::eAGGREGATE, PX_NEW_SERIALIZER_ADAPTER(NpAggregate));
+ sr.registerSerializer(PxConcreteType::eARTICULATION, PX_NEW_SERIALIZER_ADAPTER(NpArticulation));
+ sr.registerSerializer(PxConcreteType::eARTICULATION_LINK, PX_NEW_SERIALIZER_ADAPTER(NpArticulationLink));
+ sr.registerSerializer(PxConcreteType::eARTICULATION_JOINT, PX_NEW_SERIALIZER_ADAPTER(NpArticulationJoint));
+ sr.registerSerializer(PxConcreteType::ePRUNING_STRUCTURE, PX_NEW_SERIALIZER_ADAPTER(Sq::PruningStructure));
+
+#if PX_USE_CLOTH_API
+ sr.registerSerializer(PxConcreteType::eCLOTH, PX_NEW_SERIALIZER_ADAPTER(NpCloth));
+ sr.registerSerializer(PxConcreteType::eCLOTH_FABRIC, PX_NEW_SERIALIZER_ADAPTER(NpClothFabric));
+#endif
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ sr.registerSerializer(PxConcreteType::ePARTICLE_SYSTEM, PX_NEW_SERIALIZER_ADAPTER(NpParticleSystem));
+ sr.registerSerializer(PxConcreteType::ePARTICLE_FLUID, PX_NEW_SERIALIZER_ADAPTER(NpParticleFluid));
+#endif
+
+}
+
+
+void PxUnregisterPhysicsSerializers(PxSerializationRegistry& sr)
+{
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eCONVEX_MESH));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eTRIANGLE_MESH_BVH33));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eTRIANGLE_MESH_BVH34));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eHEIGHTFIELD));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eRIGID_DYNAMIC));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eRIGID_STATIC));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eSHAPE));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eMATERIAL));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eCONSTRAINT));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eAGGREGATE));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eARTICULATION));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eARTICULATION_LINK));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eARTICULATION_JOINT));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::ePRUNING_STRUCTURE));
+
+#if PX_USE_CLOTH_API
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eCLOTH));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::eCLOTH_FABRIC));
+#endif
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::ePARTICLE_SYSTEM));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxConcreteType::ePARTICLE_FLUID));
+#endif
+}
diff --git a/PhysX_3.4/Source/PhysX/src/NpShape.cpp b/PhysX_3.4/Source/PhysX/src/NpShape.cpp
new file mode 100644
index 00000000..eafbd852
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpShape.cpp
@@ -0,0 +1,851 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "NpCast.h"
+#include "GuConvexMesh.h"
+#include "GuTriangleMesh.h"
+#include "ScbNpDeps.h"
+#include "GuBounds.h"
+
+using namespace physx;
+using namespace Sq;
+
+namespace physx
+{
+ extern bool gUnifiedHeightfieldCollision;
+}
+
+static PX_FORCE_INLINE void updatePvdProperties(const Scb::Shape& shape)
+{
+#if PX_SUPPORT_PVD
+ Scb::Scene* scbScene = shape.getScbSceneForAPI();
+ if(scbScene)
+ scbScene->getScenePvdClient().updatePvdProperties(&shape);
+#else
+ PX_UNUSED(shape);
+#endif
+}
+
+NpShape::NpShape(const PxGeometry& geometry, PxShapeFlags shapeFlags, const PxU16* materialIndices, PxU16 materialCount, bool isExclusive)
+: PxShape (PxConcreteType::eSHAPE, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+, mActor (NULL)
+, mShape (geometry, shapeFlags, materialIndices, materialCount, isExclusive)
+, mName (NULL)
+, mExclusiveAndActorCount (isExclusive ? EXCLUSIVE_MASK : 0)
+{
+ PX_ASSERT(mShape.getScShape().getPxShape() == static_cast<PxShape*>(this));
+
+ PxShape::userData = NULL;
+
+ incMeshRefCount();
+}
+
+NpShape::~NpShape()
+{
+ decMeshRefCount();
+
+ PxU32 nbMaterials = mShape.getNbMaterials();
+ for (PxU32 i=0; i < nbMaterials; i++)
+ {
+ NpMaterial* mat = static_cast<NpMaterial*>(mShape.getMaterial(i));
+ mat->decRefCount();
+ }
+}
+
+void NpShape::onRefCountZero()
+{
+ NpFactory::getInstance().onShapeRelease(this);
+ // see NpShape.h for ref counting semantics for shapes
+ NpDestroy(getScbShape());
+}
+
+// PX_SERIALIZATION
+
+NpShape::NpShape(PxBaseFlags baseFlags) : PxShape(baseFlags), mShape(PxEmpty)
+{
+ mExclusiveAndActorCount &= EXCLUSIVE_MASK;
+}
+
+void NpShape::exportExtraData(PxSerializationContext& stream)
+{
+ getScbShape().getScShape().exportExtraData(stream);
+ stream.writeName(mName);
+}
+
+void NpShape::importExtraData(PxDeserializationContext& context)
+{
+ getScbShape().getScShape().importExtraData(context);
+ context.readName(mName);
+}
+
+void NpShape::requires(PxProcessPxBaseCallback& c)
+{
+ //meshes
+ PxBase* mesh = NULL;
+ switch(mShape.getGeometryType())
+ {
+ case PxGeometryType::eCONVEXMESH:
+ mesh = static_cast<const PxConvexMeshGeometry&>(mShape.getGeometry()).convexMesh;
+ break;
+ case PxGeometryType::eHEIGHTFIELD:
+ mesh = static_cast<const PxHeightFieldGeometry&>(mShape.getGeometry()).heightField;
+ break;
+ case PxGeometryType::eTRIANGLEMESH:
+ mesh = static_cast<const PxTriangleMeshGeometry&>(mShape.getGeometry()).triangleMesh;
+ break;
+ case PxGeometryType::eSPHERE:
+ case PxGeometryType::ePLANE:
+ case PxGeometryType::eCAPSULE:
+ case PxGeometryType::eBOX:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ break;
+ }
+
+ if(mesh)
+ c.process(*mesh);
+
+ //material
+ PxU32 nbMaterials = mShape.getNbMaterials();
+ for (PxU32 i=0; i < nbMaterials; i++)
+ {
+ NpMaterial* mat = static_cast<NpMaterial*>(mShape.getMaterial(i));
+ c.process(*mat);
+ }
+}
+
+void NpShape::resolveReferences(PxDeserializationContext& context)
+{
+ // getMaterials() only works after material indices have been patched.
+ // in order to get to the new material indices, we need access to the new materials.
+ // this only leaves us with the option of acquiring the material through the context given an old material index (we do have the mapping)
+ {
+ PxU32 nbIndices = mShape.getScShape().getNbMaterialIndices();
+ const PxU16* indices = mShape.getScShape().getMaterialIndices();
+
+ for (PxU32 i=0; i < nbIndices; i++)
+ {
+ PxBase* base = context.resolveReference(PX_SERIAL_REF_KIND_MATERIAL_IDX, size_t(indices[i]));
+ PX_ASSERT(base && base->is<PxMaterial>());
+
+ NpMaterial& material = *static_cast<NpMaterial*>(base);
+ getScbShape().getScShape().resolveMaterialReference(i, PxU16(material.getHandle()));
+ }
+ }
+
+ context.translatePxBase(mActor);
+
+ getScbShape().getScShape().resolveReferences(context);
+
+
+ incMeshRefCount();
+
+ // Increment materials' refcounts in a second pass. Works better in case of failure above.
+ PxU32 nbMaterials = mShape.getNbMaterials();
+ for (PxU32 i=0; i < nbMaterials; i++)
+ {
+ NpMaterial* mat = static_cast<NpMaterial*>(mShape.getMaterial(i));
+ mat->incRefCount();
+ }
+}
+
+NpShape* NpShape::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpShape* obj = new (address) NpShape(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpShape);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+void NpShape::acquireReference()
+{
+ incRefCount();
+}
+
+void NpShape::release()
+{
+ PX_CHECK_AND_RETURN(getRefCount() > 1 || getActorCount() == 0, "PxShape::release: last reference to a shape released while still attached to an actor!");
+ NP_WRITE_CHECK(getOwnerScene());
+ releaseInternal();
+}
+
+void NpShape::releaseInternal()
+{
+ decRefCount();
+}
+
+Sc::RigidCore& NpShape::getScRigidObjectExclusive() const
+{
+ const PxType actorType = mActor->getConcreteType();
+
+ if (actorType == PxConcreteType::eRIGID_DYNAMIC)
+ return static_cast<NpRigidDynamic&>(*mActor).getScbBodyFast().getScBody();
+ else if (actorType == PxConcreteType::eARTICULATION_LINK)
+ return static_cast<NpArticulationLink&>(*mActor).getScbBodyFast().getScBody();
+ else
+ return static_cast<NpRigidStatic&>(*mActor).getScbRigidStaticFast().getScStatic();
+}
+
+PxGeometryType::Enum NpShape::getGeometryType() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getGeometryType();
+}
+
+void NpShape::setGeometry(const PxGeometry& g)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setGeometry: shared shapes attached to actors are not writable.");
+ PX_SIMD_GUARD;
+
+ // PT: fixes US2117
+ if(g.getType() != getGeometryTypeFast())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxShape::setGeometry(): Invalid geometry type. Changing the type of the shape is not supported.");
+ return;
+ }
+
+#if PX_CHECKED
+ bool isValid = false;
+ switch(g.getType())
+ {
+ case PxGeometryType::eSPHERE:
+ isValid = static_cast<const PxSphereGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::ePLANE:
+ isValid = static_cast<const PxPlaneGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eCAPSULE:
+ isValid = static_cast<const PxCapsuleGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eBOX:
+ isValid = static_cast<const PxBoxGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eCONVEXMESH:
+ isValid = static_cast<const PxConvexMeshGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eTRIANGLEMESH:
+ isValid = static_cast<const PxTriangleMeshGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eHEIGHTFIELD:
+ isValid = static_cast<const PxHeightFieldGeometry&>(g).isValid();
+ break;
+
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ break;
+ }
+
+ if(!isValid)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxShape::setGeometry(): Invalid geometry!");
+ return;
+ }
+#endif
+
+ decMeshRefCount();
+
+ mShape.setGeometry(g);
+
+ incMeshRefCount();
+
+ if((mShape.getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE) && mActor)
+ {
+ PX_ASSERT(mActor);
+
+ NpScene* scene = NpActor::getOwnerScene(*mActor);
+ NpShapeManager* shapeManager = NpActor::getShapeManager(*mActor);
+ if(scene)
+ {
+ const PrunerData sqData = shapeManager->findSceneQueryData(*this);
+ scene->getSceneQueryManagerFast().markForUpdate(sqData);
+ }
+
+ // invalidate the pruning structure if the actor bounds changed
+ if (shapeManager->getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxShape::setGeometry: Shape is a part of pruning structure, pruning structure is now invalid!");
+ shapeManager->getPruningStructure()->invalidate(mActor);
+ }
+ }
+}
+
+PxGeometryHolder NpShape::getGeometry() const
+{
+ PX_COMPILE_TIME_ASSERT(sizeof(Gu::GeometryUnion)>=sizeof(PxGeometryHolder));
+ return reinterpret_cast<const PxGeometryHolder&>(mShape.getGeometry());
+}
+
+template<class T>
+static PX_FORCE_INLINE bool getGeometryT(const NpShape* npShape, PxGeometryType::Enum type, T& geom)
+{
+ NP_READ_CHECK(npShape->getOwnerScene());
+
+ if(npShape->getGeometryTypeFast() != type)
+ return false;
+
+ geom = static_cast<const T&>(npShape->getScbShape().getGeometry());
+ return true;
+}
+
+bool NpShape::getBoxGeometry(PxBoxGeometry& g) const { return getGeometryT(this, PxGeometryType::eBOX, g); }
+bool NpShape::getSphereGeometry(PxSphereGeometry& g) const { return getGeometryT(this, PxGeometryType::eSPHERE, g); }
+bool NpShape::getCapsuleGeometry(PxCapsuleGeometry& g) const { return getGeometryT(this, PxGeometryType::eCAPSULE, g); }
+bool NpShape::getPlaneGeometry(PxPlaneGeometry& g) const { return getGeometryT(this, PxGeometryType::ePLANE, g); }
+bool NpShape::getConvexMeshGeometry(PxConvexMeshGeometry& g) const { return getGeometryT(this, PxGeometryType::eCONVEXMESH, g); }
+bool NpShape::getTriangleMeshGeometry(PxTriangleMeshGeometry& g) const { return getGeometryT(this, PxGeometryType::eTRIANGLEMESH, g); }
+bool NpShape::getHeightFieldGeometry(PxHeightFieldGeometry& g) const { return getGeometryT(this, PxGeometryType::eHEIGHTFIELD, g); }
+
+PxRigidActor* NpShape::getActor() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mActor;
+}
+
+void NpShape::setLocalPose(const PxTransform& newShape2Actor)
+{
+ PX_CHECK_AND_RETURN(newShape2Actor.isSane(), "PxShape::setLocalPose: pose is not valid.");
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setLocalPose: shared shapes attached to actors are not writable.");
+ NP_WRITE_CHECK(getOwnerScene());
+
+ mShape.setShape2Actor(newShape2Actor.getNormalized());
+
+ if(mShape.getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE && mActor)
+ {
+ NpScene* scene = NpActor::getAPIScene(*mActor);
+ NpShapeManager* shapeManager = NpActor::getShapeManager(*mActor);
+ if(scene)
+ {
+ const PrunerData sqData = shapeManager->findSceneQueryData(*this);
+ scene->getSceneQueryManagerFast().markForUpdate(sqData);
+ }
+
+ // invalidate the pruning structure if the actor bounds changed
+ if (shapeManager->getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxShape::setLocalPose: Shape is a part of pruning structure, pruning structure is now invalid!");
+ shapeManager->getPruningStructure()->invalidate(mActor);
+ }
+ }
+}
+
+PxTransform NpShape::getLocalPose() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getShape2Actor();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpShape::setSimulationFilterData(const PxFilterData& data)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setSimulationFilterData: shared shapes attached to actors are not writable.");
+ mShape.setSimulationFilterData(data);
+}
+
+PxFilterData NpShape::getSimulationFilterData() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mShape.getSimulationFilterData();
+}
+
+void NpShape::setQueryFilterData(const PxFilterData& data)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setQueryFilterData: shared shapes attached to actors are not writable.");
+
+ mShape.getScShape().setQueryFilterData(data); // PT: this one doesn't need double-buffering
+
+ updatePvdProperties(mShape);
+}
+
+PxFilterData NpShape::getQueryFilterData() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return getQueryFilterDataFast();
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void NpShape::setMaterials(PxMaterial*const* materials, PxU16 materialCount)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setMaterials: shared shapes attached to actors are not writable.");
+
+#if PX_CHECKED
+ if (!NpShape::checkMaterialSetup(mShape.getGeometry(), "PxShape::setMaterials()", materials, materialCount))
+ return;
+#endif
+
+ PxU32 oldMaterialCount = mShape.getNbMaterials();
+ PX_ALLOCA(oldMaterials, PxMaterial*, oldMaterialCount);
+ PxU32 tmp = mShape.getMaterials(oldMaterials, oldMaterialCount);
+ PX_ASSERT(tmp == oldMaterialCount);
+ PX_UNUSED(tmp);
+
+ if (mShape.setMaterials(materials, materialCount))
+ {
+ for(PxU32 i=0; i < materialCount; i++)
+ static_cast<NpMaterial*>(materials[i])->incRefCount();
+
+ for(PxU32 i=0; i < oldMaterialCount; i++)
+ static_cast<NpMaterial*>(oldMaterials[i])->decRefCount();
+ }
+}
+
+PxU16 NpShape::getNbMaterials() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getNbMaterials();
+}
+
+PxU32 NpShape::getMaterials(PxMaterial** userBuffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getMaterials(userBuffer, bufferSize, startIndex);
+}
+
+PxMaterial* NpShape::getMaterialFromInternalFaceIndex(PxU32 faceIndex) const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ bool isHf = (getGeometryType() == PxGeometryType::eHEIGHTFIELD);
+ bool isMesh = (getGeometryType() == PxGeometryType::eTRIANGLEMESH);
+ if( faceIndex == 0xFFFFffff && (isHf || isMesh) )
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxShape::getMaterialFromInternalFaceIndex received 0xFFFFffff as input - returning NULL.");
+ return NULL;
+ }
+
+ PxMaterialTableIndex hitMatTableId = 0;
+
+ if(isHf)
+ {
+ PxHeightFieldGeometry hfGeom;
+ getHeightFieldGeometry(hfGeom);
+
+ hitMatTableId = hfGeom.heightField->getTriangleMaterialIndex(faceIndex);
+ }
+ else if(isMesh)
+ {
+ PxTriangleMeshGeometry triGeo;
+ getTriangleMeshGeometry(triGeo);
+
+ Gu::TriangleMesh* tm = static_cast<Gu::TriangleMesh*>(triGeo.triangleMesh);
+ if(tm->hasPerTriangleMaterials())
+ hitMatTableId = triGeo.triangleMesh->getTriangleMaterialIndex(faceIndex);
+ }
+
+ return getMaterial(hitMatTableId);
+}
+
+void NpShape::setContactOffset(PxReal contactOffset)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+
+ PX_CHECK_AND_RETURN(PxIsFinite(contactOffset), "PxShape::setContactOffset: invalid float");
+ PX_CHECK_AND_RETURN((contactOffset >= 0.0f && contactOffset > mShape.getRestOffset()), "PxShape::setContactOffset: contactOffset should be positive, and greater than restOffset!");
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setContactOffset: shared shapes attached to actors are not writable.");
+
+ mShape.setContactOffset(contactOffset);
+}
+
+PxReal NpShape::getContactOffset() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getContactOffset();
+}
+
+void NpShape::setRestOffset(PxReal restOffset)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(PxIsFinite(restOffset), "PxShape::setRestOffset: invalid float");
+ PX_CHECK_AND_RETURN((restOffset < mShape.getContactOffset()), "PxShape::setRestOffset: restOffset should be less than contactOffset!");
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setRestOffset: shared shapes attached to actors are not writable.");
+
+ mShape.setRestOffset(restOffset);
+}
+
+PxReal NpShape::getRestOffset() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mShape.getRestOffset();
+}
+
+void NpShape::setFlagsInternal(PxShapeFlags inFlags)
+{
+ const bool hasMeshTypeGeom = mShape.getGeometryType() == PxGeometryType::eTRIANGLEMESH || mShape.getGeometryType() == PxGeometryType::eHEIGHTFIELD;
+
+ if(hasMeshTypeGeom && (inFlags & PxShapeFlag::eTRIGGER_SHAPE))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxShape::setFlag(s): triangle mesh and heightfield triggers are not supported!");
+ return;
+ }
+
+ if((inFlags & PxShapeFlag::eSIMULATION_SHAPE) && (inFlags & PxShapeFlag::eTRIGGER_SHAPE))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxShape::setFlag(s): shapes cannot simultaneously be trigger shapes and simulation shapes.");
+ return;
+ }
+
+ const PxShapeFlags oldFlags = mShape.getFlags();
+
+ const bool oldIsSimShape = oldFlags & PxShapeFlag::eSIMULATION_SHAPE;
+ const bool isSimShape = inFlags & PxShapeFlag::eSIMULATION_SHAPE;
+
+ if(mActor)
+ {
+ const PxType type = mActor->getConcreteType();
+
+ // PT: US5732 - support kinematic meshes
+ bool isKinematic = false;
+ if(type==PxConcreteType::eRIGID_DYNAMIC)
+ {
+ PxRigidDynamic* rigidDynamic = static_cast<PxRigidDynamic*>(mActor);
+ isKinematic = rigidDynamic->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC;
+ }
+
+ if((type != PxConcreteType::eRIGID_STATIC) && !isKinematic && isSimShape && !oldIsSimShape && (hasMeshTypeGeom || mShape.getGeometryType() == PxGeometryType::ePLANE))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxShape::setFlag(s): triangle mesh, heightfield and plane shapes can only be simulation shapes if part of a PxRigidStatic!");
+ return;
+ }
+ }
+
+ const bool oldHasSceneQuery = oldFlags & PxShapeFlag::eSCENE_QUERY_SHAPE;
+ const bool hasSceneQuery = inFlags & PxShapeFlag::eSCENE_QUERY_SHAPE;
+
+ mShape.setFlags(inFlags);
+
+ if(oldHasSceneQuery != hasSceneQuery && mActor)
+ {
+ NpScene* npScene = getAPIScene();
+ NpShapeManager* shapeManager = NpActor::getShapeManager(*mActor);
+ if(npScene)
+ {
+ if(hasSceneQuery)
+ shapeManager->setupSceneQuery(npScene->getSceneQueryManagerFast(), *mActor, *this);
+ else
+ shapeManager->teardownSceneQuery(npScene->getSceneQueryManagerFast(), *this);
+ }
+
+ // invalidate the pruning structure if the actor bounds changed
+ if(shapeManager->getPruningStructure())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxShape::setFlag: Shape is a part of pruning structure, pruning structure is now invalid!");
+ shapeManager->getPruningStructure()->invalidate(mActor);
+ }
+ }
+}
+
+void NpShape::setFlag(PxShapeFlag::Enum flag, bool value)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setFlag: shared shapes attached to actors are not writable.");
+ PX_SIMD_GUARD;
+
+ PxShapeFlags shapeFlags = mShape.getFlags();
+ shapeFlags = value ? shapeFlags | flag : shapeFlags & ~flag;
+
+ setFlagsInternal(shapeFlags);
+}
+
+void NpShape::setFlags( PxShapeFlags inFlags )
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_SIMD_GUARD;
+
+ setFlagsInternal(inFlags);
+}
+
+PxShapeFlags NpShape::getFlags() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return mShape.getFlags();
+}
+
+bool NpShape::isExclusive() const
+{
+ NP_READ_CHECK(getOwnerScene());
+ return (mExclusiveAndActorCount & EXCLUSIVE_MASK) != 0;
+}
+
+void NpShape::onActorAttach(PxRigidActor& actor)
+{
+ incRefCount();
+ if(isExclusiveFast())
+ mActor = &actor;
+ Ps::atomicIncrement(&mExclusiveAndActorCount);
+}
+
+void NpShape::onActorDetach()
+{
+ PX_ASSERT(getActorCount() > 0);
+ Ps::atomicDecrement(&mExclusiveAndActorCount);
+ if(isExclusiveFast())
+ mActor = NULL;
+ decRefCount();
+}
+
+void NpShape::setName(const char* debugName)
+{
+ NP_WRITE_CHECK(getOwnerScene());
+ PX_CHECK_AND_RETURN(isWritable(), "PxShape::setName: shared shapes attached to actors are not writable.");
+
+ mName = debugName;
+
+ updatePvdProperties(mShape);
+}
+
+const char* NpShape::getName() const
+{
+ NP_READ_CHECK(getOwnerScene());
+
+ return mName;
+}
+
+NpScene* NpShape::getOwnerScene() const
+{
+ return mActor ? NpActor::getOwnerScene(*mActor) : NULL;
+}
+
+NpScene* NpShape::getAPIScene() const
+{
+ // gets called when we update SQ structures due to a write - in which case there must be an actor
+ PX_ASSERT(mActor);
+ return NpActor::getAPIScene(*mActor);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+namespace physx
+{
+Sc::RigidCore* NpShapeGetScRigidObjectFromScbSLOW(const Scb::Shape &scb)
+{
+ const NpShape* np = getNpShape(&scb);
+ return np->NpShape::getActor() ? &np->getScRigidObjectExclusive() : NULL;
+}
+
+size_t NpShapeGetScPtrOffset()
+{
+ const size_t offset = size_t(&(reinterpret_cast<NpShape*>(0)->getScbShape().getScShape()));
+ return offset;
+}
+
+void NpShapeIncRefCount(Scb::Shape& scb)
+{
+ NpShape* np = const_cast<NpShape*>(getNpShape(&scb));
+ np->incRefCount();
+}
+
+void NpShapeDecRefCount(Scb::Shape& scb)
+{
+ NpShape* np = const_cast<NpShape*>(getNpShape(&scb));
+ np->decRefCount();
+}
+}
+
+// see NpConvexMesh.h, NpHeightField.h, NpTriangleMesh.h for details on how ref counting works
+// for meshes
+Cm::RefCountable* NpShape::getMeshRefCountable()
+{
+ switch(mShape.getGeometryType())
+ {
+ case PxGeometryType::eCONVEXMESH:
+ return static_cast<Gu::ConvexMesh*>(
+ static_cast<const PxConvexMeshGeometry&>(mShape.getGeometry()).convexMesh);
+
+ case PxGeometryType::eHEIGHTFIELD:
+ return static_cast<Gu::HeightField*>(
+ static_cast<const PxHeightFieldGeometry&>(mShape.getGeometry()).heightField);
+
+ case PxGeometryType::eTRIANGLEMESH:
+ return static_cast<Gu::TriangleMesh*>(
+ static_cast<const PxTriangleMeshGeometry&>(mShape.getGeometry()).triangleMesh);
+
+ case PxGeometryType::eSPHERE:
+ case PxGeometryType::ePLANE:
+ case PxGeometryType::eCAPSULE:
+ case PxGeometryType::eBOX:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ break;
+ }
+ return NULL;
+}
+
+bool NpShape::isWritable()
+{
+ // a shape is writable if it's exclusive, or it's not connected to any actors (which is true if the ref count is 1 and the user ref is not released.)
+ return isExclusiveFast() || (getRefCount()==1 && (mBaseFlags & PxBaseFlag::eIS_RELEASABLE));
+}
+
+void NpShape::incMeshRefCount()
+{
+ Cm::RefCountable* npMesh = getMeshRefCountable();
+ if(npMesh)
+ npMesh->incRefCount();
+}
+
+void NpShape::decMeshRefCount()
+{
+ Cm::RefCountable* npMesh = getMeshRefCountable();
+ if(npMesh)
+ npMesh->decRefCount();
+}
+
+bool NpShape::checkMaterialSetup(const PxGeometry& geom, const char* errorMsgPrefix, PxMaterial*const* materials, PxU16 materialCount)
+{
+ for(PxU32 i=0; i<materialCount; ++i)
+ {
+ if(!materials[i])
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "material pointer %d is NULL!", i);
+ return false;
+ }
+ }
+
+ // check that simple shapes don't get assigned multiple materials
+ if (materialCount > 1 && (geom.getType() != PxGeometryType::eHEIGHTFIELD) && (geom.getType() != PxGeometryType::eTRIANGLEMESH))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "%s: multiple materials defined for single material geometry!", errorMsgPrefix);
+ return false;
+ }
+
+ // verify we provide all materials required
+ if (materialCount > 1 && (geom.getType() == PxGeometryType::eTRIANGLEMESH))
+ {
+ const PxTriangleMeshGeometry& meshGeom = static_cast<const PxTriangleMeshGeometry&>(geom);
+ const PxTriangleMesh& mesh = *meshGeom.triangleMesh;
+ if(mesh.getTriangleMaterialIndex(0) != 0xffff)
+ {
+ for(PxU32 i = 0; i < mesh.getNbTriangles(); i++)
+ {
+ const PxMaterialTableIndex meshMaterialIndex = mesh.getTriangleMaterialIndex(i);
+ if(meshMaterialIndex >= materialCount)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "%s: PxTriangleMesh material indices reference more materials than provided!", errorMsgPrefix);
+ break;
+ }
+ }
+ }
+ }
+ if (materialCount > 1 && (geom.getType() == PxGeometryType::eHEIGHTFIELD))
+ {
+ const PxHeightFieldGeometry& meshGeom = static_cast<const PxHeightFieldGeometry&>(geom);
+ const PxHeightField& mesh = *meshGeom.heightField;
+ if(mesh.getTriangleMaterialIndex(0) != 0xffff)
+ {
+ const PxU32 nbTris = (mesh.getNbColumns() - 1)*(mesh.getNbColumns() - 1)*2;
+ for(PxU32 i = 0; i < nbTris; i++)
+ {
+ const PxMaterialTableIndex meshMaterialIndex = mesh.getTriangleMaterialIndex(i);
+ if(meshMaterialIndex >= materialCount)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "%s: PxHeightField material indices reference more materials than provided!", errorMsgPrefix);
+ break;
+ }
+ }
+ }
+ }
+
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+#include "GuDebug.h"
+
+void NpShape::visualize(Cm::RenderOutput& out, const PxRigidActor& actor)
+{
+ NpScene* npScene = NpActor::getOwnerScene(actor);
+ PX_ASSERT(npScene);
+
+ const PxReal scale = npScene->getVisualizationParameter(PxVisualizationParameter::eSCALE);
+ if(!scale) return;
+
+ const PxTransform absPose = actor.getGlobalPose() * mShape.getShape2Actor();
+
+ if(npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_AABBS))
+ out << PxU32(PxDebugColor::eARGB_YELLOW) << PxMat44(PxIdentity) << Cm::DebugBox(Gu::computeBounds(mShape.getGeometry(), absPose, !gUnifiedHeightfieldCollision));
+
+ const PxReal collisionAxes = scale * npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_AXES);
+ if(collisionAxes != 0.0f)
+ out << PxMat44(absPose) << Cm::DebugBasis(PxVec3(collisionAxes), 0xcf0000, 0x00cf00, 0x0000cf);
+
+ if( npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_SHAPES) ||
+ npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_FNORMALS) ||
+ npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_EDGES))
+ {
+ const PxBounds3& cullbox = npScene->getVisualizationCullingBox();
+
+ const PxReal fscale = scale * npScene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_FNORMALS);
+
+ // Pack bool params into bit mask.
+ PxU64 mask = 0;
+
+ #define SET_MASK(mask, param) (mask |= (PxU64(!!npScene->getVisualizationParameter(param))) << param)
+
+ SET_MASK(mask, PxVisualizationParameter::eCULL_BOX);
+ SET_MASK(mask, PxVisualizationParameter::eCOLLISION_FNORMALS);
+ SET_MASK(mask, PxVisualizationParameter::eCOLLISION_EDGES);
+ SET_MASK(mask, PxVisualizationParameter::eCOLLISION_SHAPES);
+
+ Sc::ShapeCore& shape = mShape.getScShape();
+ const PxU32 numMaterials = shape.getNbMaterialIndices();
+ Gu::Debug::visualize(getGeometryFast().getGeometry(), out, absPose, cullbox, mask, fscale, numMaterials);
+ }
+}
+
+#endif // PX_ENABLE_DEBUG_VISUALIZATION
diff --git a/PhysX_3.4/Source/PhysX/src/NpShape.h b/PhysX_3.4/Source/PhysX/src/NpShape.h
new file mode 100644
index 00000000..fb2b4e2a
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpShape.h
@@ -0,0 +1,216 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_SHAPE
+#define PX_PHYSICS_NP_SHAPE
+
+#include "PxShape.h"
+#include "buffering/ScbShape.h"
+#include "PxMetaData.h"
+
+namespace physx
+{
+
+struct NpInternalShapeFlag
+{
+ enum Enum
+ {
+ eEXCLUSIVE = (1<<0)
+ };
+};
+
+/**
+\brief collection of set bits defined in PxShapeFlag.
+
+@see PxShapeFlag
+*/
+typedef PxFlags<NpInternalShapeFlag::Enum,PxU8> NpInternalShapeFlags;
+PX_FLAGS_OPERATORS(NpInternalShapeFlag::Enum,PxU8)
+
+
+class NpScene;
+class NpShapeManager;
+
+namespace Scb
+{
+ class Scene;
+ class RigidObject;
+}
+
+namespace Sc
+{
+ class MaterialCore;
+}
+
+class NpShape : public PxShape, public Ps::UserAllocated, public Cm::RefCountable
+{
+//= 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
+ NpShape(PxBaseFlags baseFlags);
+ virtual void exportExtraData(PxSerializationContext& stream);
+ void importExtraData(PxDeserializationContext& context);
+ virtual void requires(PxProcessPxBaseCallback& c);
+ void resolveReferences(PxDeserializationContext& context);
+ static NpShape* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ NpShape(const PxGeometry& geometry,
+ PxShapeFlags shapeFlags,
+ const PxU16* materialIndices,
+ PxU16 materialCount,
+ bool isExclusive);
+
+ virtual ~NpShape();
+
+ //---------------------------------------------------------------------------------
+ // PxShape implementation
+ //---------------------------------------------------------------------------------
+ virtual void release(); //!< call to release from actor
+ virtual void acquireReference();
+
+ virtual PxGeometryType::Enum getGeometryType() const;
+
+ virtual void setGeometry(const PxGeometry&);
+ virtual PxGeometryHolder getGeometry() const;
+ virtual bool getBoxGeometry(PxBoxGeometry&) const;
+ virtual bool getSphereGeometry(PxSphereGeometry&) const;
+ virtual bool getCapsuleGeometry(PxCapsuleGeometry&) const;
+ virtual bool getPlaneGeometry(PxPlaneGeometry&) const;
+ virtual bool getConvexMeshGeometry(PxConvexMeshGeometry& g) const;
+ virtual bool getTriangleMeshGeometry(PxTriangleMeshGeometry& g) const;
+ virtual bool getHeightFieldGeometry(PxHeightFieldGeometry& g) const;
+
+ virtual PxRigidActor* getActor() const;
+
+ virtual void setLocalPose(const PxTransform& pose);
+ virtual PxTransform getLocalPose() const;
+
+ virtual void setSimulationFilterData(const PxFilterData& data);
+ virtual PxFilterData getSimulationFilterData() const;
+ virtual void setQueryFilterData(const PxFilterData& data);
+ virtual PxFilterData getQueryFilterData() const;
+
+ virtual void setMaterials(PxMaterial*const* materials, PxU16 materialCount);
+ virtual PxU16 getNbMaterials() const;
+ virtual PxU32 getMaterials(PxMaterial** userBuffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+ virtual PxMaterial* getMaterialFromInternalFaceIndex(PxU32 faceIndex) const;
+
+ virtual void setContactOffset(PxReal);
+ virtual PxReal getContactOffset() const;
+
+ virtual void setRestOffset(PxReal);
+ virtual PxReal getRestOffset() const;
+
+ virtual void setFlag(PxShapeFlag::Enum flag, bool value);
+ virtual void setFlags( PxShapeFlags inFlags );
+ virtual PxShapeFlags getFlags() const;
+
+ virtual bool isExclusive() const;
+
+ virtual void setName(const char* debugName);
+ virtual const char* getName() const;
+
+ //---------------------------------------------------------------------------------
+ // RefCountable implementation
+ //---------------------------------------------------------------------------------
+
+ // Ref counting for shapes works like this:
+ // * for exclusive shapes the actor has a counted reference
+ // * for shared shapes, each actor has a counted reference, and the user has a counted reference
+ // * for either kind, each instance of the shape in a scene (i.e. each shapeSim) causes the reference count to be incremented by 1.
+ // Because these semantics aren't clear to users, this reference count should not be exposed in the API
+
+ virtual void onRefCountZero();
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+
+ void setFlagsInternal( PxShapeFlags inFlags );
+
+ PX_FORCE_INLINE PxShapeFlags getFlagsFast() const { return mShape.getFlags(); }
+ PX_FORCE_INLINE PxShapeFlags getFlagsUnbuffered() const { return mShape.getScShape().getFlags(); }
+ PX_FORCE_INLINE PxGeometryType::Enum getGeometryTypeFast() const { return mShape.getGeometryType(); }
+ PX_FORCE_INLINE const Gu::GeometryUnion& getGeometryFast() const { return mShape.getGeometryUnion(); }
+ PX_FORCE_INLINE const PxTransform& getLocalPoseFast() const { return mShape.getShape2Actor(); }
+ PX_FORCE_INLINE PxU32 getActorCount() const { return PxU32(mExclusiveAndActorCount & ACTOR_COUNT_MASK); }
+ PX_FORCE_INLINE PxI32 isExclusiveFast() const { return mExclusiveAndActorCount & EXCLUSIVE_MASK; }
+
+ PX_FORCE_INLINE const PxFilterData& getQueryFilterDataFast() const
+ {
+ return mShape.getScShape().getQueryFilterData(); // PT: this one doesn't need double-buffering
+ }
+
+ PX_FORCE_INLINE const Scb::Shape& getScbShape() const { return mShape; }
+ PX_FORCE_INLINE Scb::Shape& getScbShape() { return mShape; }
+
+ PX_INLINE PxMaterial* getMaterial(PxU32 index) const { return mShape.getMaterial(index); }
+ static bool checkMaterialSetup(const PxGeometry& geom, const char* errorMsgPrefix, PxMaterial*const* materials, PxU16 materialCount);
+
+ void onActorAttach(PxRigidActor& actor);
+ void onActorDetach();
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+public:
+ virtual void visualize(Cm::RenderOutput& out, const PxRigidActor& owner);
+#endif
+
+ // These methods are used only for sync'ing, and may only be called on exclusive shapes since only exclusive shapes have buffering
+ Sc::RigidCore& getScRigidObjectExclusive() const;
+ void releaseInternal();
+
+ NpScene* getOwnerScene() const; // same distinctions as for NpActor
+private:
+ NpScene* getAPIScene() const;
+
+ void incMeshRefCount();
+ void decMeshRefCount();
+ Cm::RefCountable* getMeshRefCountable();
+ bool isWritable();
+
+ PxRigidActor* mActor; // Auto-resolving refs breaks DLL loading for some reason
+ Scb::Shape mShape;
+ const char* mName;
+
+ static const PxI32 EXCLUSIVE_MASK = 0x80000000;
+ static const PxI32 ACTOR_COUNT_MASK = 0x7fffffff;
+
+ volatile PxI32 mExclusiveAndActorCount;
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp b/PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp
new file mode 100644
index 00000000..ab2d6d8b
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpShapeManager.cpp
@@ -0,0 +1,309 @@
+// 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 "NpShapeManager.h"
+#include "NpFactory.h"
+#include "ScbRigidObject.h"
+#include "NpActor.h"
+#include "SqSceneQueryManager.h"
+#include "SqPruningStructure.h"
+#include "NpScene.h"
+#include "NpPtrTableStorageManager.h"
+#include "GuBounds.h"
+#include "CmUtils.h"
+
+using namespace physx;
+using namespace Sq;
+
+namespace physx
+{
+ extern bool gUnifiedHeightfieldCollision;
+}
+
+static PX_FORCE_INLINE bool isSceneQuery(const NpShape& shape) { return shape.getFlagsFast() & PxShapeFlag::eSCENE_QUERY_SHAPE; }
+
+NpShapeManager::NpShapeManager()
+ : mPruningStructure(NULL)
+{
+}
+
+// PX_SERIALIZATION
+NpShapeManager::NpShapeManager(const PxEMPTY) :
+ mShapes (PxEmpty),
+ mSceneQueryData (PxEmpty)
+{
+}
+
+NpShapeManager::~NpShapeManager()
+{
+ PX_ASSERT(!mPruningStructure);
+ Cm::PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager();
+ mShapes.clear(sm);
+ mSceneQueryData.clear(sm);
+}
+
+void NpShapeManager::exportExtraData(PxSerializationContext& stream)
+{
+ mShapes.exportExtraData(stream);
+ mSceneQueryData.exportExtraData(stream);
+}
+
+void NpShapeManager::importExtraData(PxDeserializationContext& context)
+{
+ mShapes.importExtraData(context);
+ mSceneQueryData.importExtraData(context);
+}
+//~PX_SERIALIZATION
+
+void NpShapeManager::attachShape(NpShape& shape, PxRigidActor& actor)
+{
+ PX_ASSERT(!mPruningStructure);
+
+ Cm::PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager();
+
+ const PxU32 index = getNbShapes();
+ mShapes.add(&shape, sm);
+ mSceneQueryData.add(reinterpret_cast<void*>(size_t(SQ_INVALID_PRUNER_DATA)), sm);
+
+ NpScene* scene = NpActor::getAPIScene(actor);
+ if(scene && isSceneQuery(shape))
+ setupSceneQuery(scene->getSceneQueryManagerFast(), actor, index);
+
+ Scb::RigidObject& ro = static_cast<Scb::RigidObject&>(NpActor::getScbFromPxActor(actor));
+ ro.onShapeAttach(shape.getScbShape());
+
+ PX_ASSERT(!shape.isExclusive() || shape.getActor()==NULL);
+ shape.onActorAttach(actor);
+}
+
+void NpShapeManager::detachShape(NpShape& s, PxRigidActor& actor, bool wakeOnLostTouch)
+{
+ PX_ASSERT(!mPruningStructure);
+
+ Cm::PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager();
+
+ const PxU32 index = mShapes.find(&s);
+ PX_ASSERT(index!=0xffffffff);
+
+ Scb::RigidObject& ro = static_cast<Scb::RigidObject&>(NpActor::getScbFromPxActor(actor));
+
+ NpScene* scene = NpActor::getAPIScene(actor);
+ if(scene && isSceneQuery(s))
+ scene->getSceneQueryManagerFast().removePrunerShape(getPrunerData(index));
+
+ Scb::Shape& scbShape = s.getScbShape();
+ ro.onShapeDetach(scbShape, wakeOnLostTouch, (s.getRefCount() == 1));
+ mShapes.replaceWithLast(index, sm);
+ mSceneQueryData.replaceWithLast(index, sm);
+
+ s.onActorDetach();
+}
+
+bool NpShapeManager::shapeIsAttached(NpShape& s) const
+{
+ return mShapes.find(&s)!=0xffffffff;
+}
+
+void NpShapeManager::detachAll(NpScene* scene)
+{
+ // assumes all SQ data has been released, which is currently the responsbility of the owning actor
+ const PxU32 nbShapes = getNbShapes();
+ NpShape*const *shapes = getShapes();
+
+ if(scene)
+ teardownAllSceneQuery(scene->getSceneQueryManagerFast());
+
+ // actor cleanup in Scb/Sc will remove any outstanding references corresponding to sim objects, so we don't need to do that here.
+ for(PxU32 i=0;i<nbShapes;i++)
+ shapes[i]->onActorDetach();
+
+ Cm::PtrTableStorageManager& sm = NpFactory::getInstance().getPtrTableStorageManager();
+
+ mShapes.clear(sm);
+ mSceneQueryData.clear(sm);
+}
+
+PxU32 NpShapeManager::getShapes(PxShape** buffer, PxU32 bufferSize, PxU32 startIndex) const
+{
+ return Cm::getArrayOfPointers(buffer, bufferSize, startIndex, getShapes(), getNbShapes());
+}
+
+PxBounds3 NpShapeManager::getWorldBounds(const PxRigidActor& actor) const
+{
+ PxBounds3 bounds(PxBounds3::empty());
+
+ const PxU32 nbShapes = getNbShapes();
+ PxTransform actorPose = actor.getGlobalPose();
+ NpShape*const* PX_RESTRICT shapes = getShapes();
+
+ for(PxU32 i=0;i<nbShapes;i++)
+ bounds.include(Gu::computeBounds(shapes[i]->getScbShape().getGeometry(), actorPose * shapes[i]->getLocalPoseFast(), !physx::gUnifiedHeightfieldCollision));
+
+ return bounds;
+}
+
+void NpShapeManager::clearShapesOnRelease(Scb::Scene& s, PxRigidActor& r)
+{
+ PX_ASSERT(static_cast<Scb::RigidObject&>(NpActor::getScbFromPxActor(r)).isSimDisabledInternally());
+
+ const PxU32 nbShapes = getNbShapes();
+ NpShape*const* PX_RESTRICT shapes = getShapes();
+
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ Scb::Shape& scbShape = shapes[i]->getScbShape();
+ scbShape.checkUpdateOnRemove<false>(&s);
+#if PX_SUPPORT_PVD
+ s.getScenePvdClient().releasePvdInstance(&scbShape, r);
+#else
+ PX_UNUSED(r);
+#endif
+ }
+}
+
+void NpShapeManager::releaseExclusiveUserReferences()
+{
+ // when the factory is torn down, release any shape owner refs that are still outstanding
+ const PxU32 nbShapes = getNbShapes();
+ NpShape*const* PX_RESTRICT shapes = getShapes();
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ if(shapes[i]->isExclusiveFast() && shapes[i]->getRefCount()>1)
+ shapes[i]->release();
+ }
+}
+
+void NpShapeManager::setupSceneQuery(SceneQueryManager& sqManager, const PxRigidActor& actor, const NpShape& shape)
+{
+ PX_ASSERT(shape.getFlags() & PxShapeFlag::eSCENE_QUERY_SHAPE);
+ const PxU32 index = mShapes.find(&shape);
+ PX_ASSERT(index!=0xffffffff);
+ setupSceneQuery(sqManager, actor, index);
+}
+
+void NpShapeManager::teardownSceneQuery(SceneQueryManager& sqManager, const NpShape& shape)
+{
+ const PxU32 index = mShapes.find(&shape);
+ PX_ASSERT(index!=0xffffffff);
+ teardownSceneQuery(sqManager, index);
+}
+
+void NpShapeManager::setupAllSceneQuery(NpScene* scene, const PxRigidActor& actor, bool hasPrunerStructure, const PxBounds3* bounds)
+{
+ PX_ASSERT(scene); // shouldn't get here unless we're in a scene
+ SceneQueryManager& sqManager = scene->getSceneQueryManagerFast();
+
+ const PxU32 nbShapes = getNbShapes();
+ NpShape*const *shapes = getShapes();
+
+ const PxType actorType = actor.getConcreteType();
+ const bool isDynamic = actorType == PxConcreteType::eRIGID_DYNAMIC || actorType == PxConcreteType::eARTICULATION_LINK;
+
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ if(isSceneQuery(*shapes[i]))
+ setPrunerData(i, sqManager.addPrunerShape(*shapes[i], actor, isDynamic, bounds ? bounds + i : NULL, hasPrunerStructure));
+ }
+}
+
+void NpShapeManager::teardownAllSceneQuery(SceneQueryManager& sqManager)
+{
+ NpShape*const *shapes = getShapes();
+ const PxU32 nbShapes = getNbShapes();
+
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ if(isSceneQuery(*shapes[i]))
+ sqManager.removePrunerShape(getPrunerData(i));
+
+ setPrunerData(i, SQ_INVALID_PRUNER_DATA);
+ }
+}
+
+void NpShapeManager::markAllSceneQueryForUpdate(SceneQueryManager& sqManager)
+{
+ const PxU32 nbShapes = getNbShapes();
+
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ const PrunerData data = getPrunerData(i);
+ if(data!=SQ_INVALID_PRUNER_DATA)
+ sqManager.markForUpdate(data);
+ }
+}
+
+Sq::PrunerData NpShapeManager::findSceneQueryData(const NpShape& shape) const
+{
+ const PxU32 index = mShapes.find(&shape);
+ PX_ASSERT(index!=0xffffffff);
+
+ return getPrunerData(index);
+}
+
+//
+// internal methods
+//
+
+void NpShapeManager::setupSceneQuery(SceneQueryManager& sqManager, const PxRigidActor& actor, PxU32 index)
+{
+ const PxType actorType = actor.getConcreteType();
+ const bool isDynamic = actorType == PxConcreteType::eRIGID_DYNAMIC || actorType == PxConcreteType::eARTICULATION_LINK;
+ setPrunerData(index, sqManager.addPrunerShape(*(getShapes()[index]), actor, isDynamic));
+}
+
+void NpShapeManager::teardownSceneQuery(SceneQueryManager& sqManager, PxU32 index)
+{
+ sqManager.removePrunerShape(getPrunerData(index));
+ setPrunerData(index, SQ_INVALID_PRUNER_DATA);
+}
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+void NpShapeManager::visualize(Cm::RenderOutput& out, NpScene* scene, const PxRigidActor& actor)
+{
+ const PxU32 nbShapes = getNbShapes();
+ NpShape*const* PX_RESTRICT shapes = getShapes();
+ PxTransform actorPose = actor.getGlobalPose();
+
+ const bool visualizeCompounds = (nbShapes>1) && scene->getVisualizationParameter(PxVisualizationParameter::eCOLLISION_COMPOUNDS)!=0.0f;
+
+ PxBounds3 compoundBounds(PxBounds3::empty());
+ for(PxU32 i=0;i<nbShapes;i++)
+ {
+ Scb::Shape& shape = shapes[i]->getScbShape();
+ if(shape.getFlags() & PxShapeFlag::eVISUALIZATION)
+ {
+ shapes[i]->visualize(out, actor);
+ if(visualizeCompounds)
+ compoundBounds.include(Gu::computeBounds(shape.getGeometry(), actorPose*shapes[i]->getLocalPose(), !physx::gUnifiedHeightfieldCollision));
+ }
+ }
+ if(visualizeCompounds && !compoundBounds.isEmpty())
+ out << PxU32(PxDebugColor::eARGB_MAGENTA) << PxMat44(PxIdentity) << Cm::DebugBox(compoundBounds);
+}
+#endif // PX_ENABLE_DEBUG_VISUALIZATION
diff --git a/PhysX_3.4/Source/PhysX/src/NpShapeManager.h b/PhysX_3.4/Source/PhysX/src/NpShapeManager.h
new file mode 100644
index 00000000..d7d22ea6
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpShapeManager.h
@@ -0,0 +1,126 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_SHAPE_MANAGER
+#define PX_PHYSICS_NP_SHAPE_MANAGER
+
+#include "NpShape.h"
+#include "CmPtrTable.h"
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+#include "CmRenderOutput.h"
+#endif
+
+namespace physx
+{
+
+namespace Sq
+{
+ typedef size_t PrunerData;
+ class SceneQueryManager;
+ class PruningStructure;
+}
+
+class NpScene;
+
+class NpShapeManager : 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:
+// PX_SERIALIZATION
+ static void getBinaryMetaData(PxOutputStream& stream);
+ NpShapeManager(const PxEMPTY);
+ void exportExtraData(PxSerializationContext& stream);
+ void importExtraData(PxDeserializationContext& context);
+//~PX_SERIALIZATION
+ NpShapeManager();
+ ~NpShapeManager();
+
+ PX_FORCE_INLINE PxU32 getNbShapes() const { return mShapes.getCount(); }
+ PX_FORCE_INLINE NpShape* const* getShapes() const { return reinterpret_cast<NpShape*const*>(mShapes.getPtrs()); }
+ PxU32 getShapes(PxShape** buffer, PxU32 bufferSize, PxU32 startIndex=0) const;
+
+ void attachShape(NpShape& shape, PxRigidActor& actor);
+ void detachShape(NpShape& s, PxRigidActor &actor, bool wakeOnLostTouch);
+ bool shapeIsAttached(NpShape& s) const;
+ void detachAll(NpScene *scene);
+
+ void teardownSceneQuery(Sq::SceneQueryManager& sqManager, const NpShape& shape);
+ void setupSceneQuery(Sq::SceneQueryManager& sqManager, const PxRigidActor& actor, const NpShape& shape);
+
+ PX_FORCE_INLINE void setPrunerData(PxU32 index, Sq::PrunerData data)
+ {
+ PX_ASSERT(index<getNbShapes());
+ mSceneQueryData.getPtrs()[index] = reinterpret_cast<void*>(data);
+ }
+
+ PX_FORCE_INLINE Sq::PrunerData getPrunerData(PxU32 index) const
+ {
+ PX_ASSERT(index<getNbShapes());
+ return Sq::PrunerData(mSceneQueryData.getPtrs()[index]);
+ }
+
+ void setupAllSceneQuery(NpScene* scene, const PxRigidActor& actor, bool hasPrunerStructure, const PxBounds3* bounds=NULL);
+ void teardownAllSceneQuery(Sq::SceneQueryManager& sqManager);
+ void markAllSceneQueryForUpdate(Sq::SceneQueryManager& shapeManager);
+
+ Sq::PrunerData findSceneQueryData(const NpShape& shape) const;
+
+ PxBounds3 getWorldBounds(const PxRigidActor&) const;
+
+ PX_FORCE_INLINE void setPruningStructure(Sq::PruningStructure* ps) { mPruningStructure = ps; }
+ PX_FORCE_INLINE Sq::PruningStructure* getPruningStructure() const { return mPruningStructure; }
+
+ void clearShapesOnRelease(Scb::Scene& s, PxRigidActor&);
+ void releaseExclusiveUserReferences();
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+ void visualize(Cm::RenderOutput& out, NpScene* scene, const PxRigidActor& actor);
+#endif
+ // for batching
+ PX_FORCE_INLINE const Cm::PtrTable& getShapeTable() const { return mShapes; }
+protected:
+ void setupSceneQuery(Sq::SceneQueryManager& sqManager, const PxRigidActor& actor, PxU32 index);
+ void teardownSceneQuery(Sq::SceneQueryManager& sqManager, PxU32 index);
+
+ // PT: TODO: revisit this. We don't need two arrays.
+ Cm::PtrTable mShapes;
+ Cm::PtrTable mSceneQueryData; // 1-1 correspondence with shapes - TODO: allocate on scene insertion or combine with the shape array for better caching
+ Sq::PruningStructure* mPruningStructure; // Shape scene query data are pre-build in pruning structure
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/NpSpatialIndex.cpp b/PhysX_3.4/Source/PhysX/src/NpSpatialIndex.cpp
new file mode 100644
index 00000000..bda0b2ff
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpSpatialIndex.cpp
@@ -0,0 +1,221 @@
+// 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 "NpSpatialIndex.h"
+#include "PsFPU.h"
+#include "SqPruner.h"
+#include "PxBoxGeometry.h"
+#include "PsFoundation.h"
+#include "GuBounds.h"
+
+using namespace physx;
+using namespace Sq;
+using namespace Gu;
+
+NpSpatialIndex::NpSpatialIndex()
+: mPendingUpdates(false)
+{
+ mPruner = createAABBPruner(true);
+}
+
+NpSpatialIndex::~NpSpatialIndex()
+{
+ PX_DELETE(mPruner);
+}
+
+PxSpatialIndexItemId NpSpatialIndex::insert(PxSpatialIndexItem& item,
+ const PxBounds3& bounds)
+{
+ PX_SIMD_GUARD;
+ PX_CHECK_AND_RETURN_VAL(bounds.isValid(), "PxSpatialIndex::insert: bounds are not valid.", PX_SPATIAL_INDEX_INVALID_ITEM_ID);
+
+ PrunerHandle output;
+ PrunerPayload payload;
+ payload.data[0] = reinterpret_cast<size_t>(&item);
+ mPruner->addObjects(&output, &bounds, &payload);
+ mPendingUpdates = true;
+ return output;
+}
+
+void NpSpatialIndex::update(PxSpatialIndexItemId id,
+ const PxBounds3& bounds)
+{
+ PX_SIMD_GUARD;
+ PX_CHECK_AND_RETURN(bounds.isValid(), "PxSpatialIndex::update: bounds are not valid.");
+
+ mPruner->updateObjects(&id, &bounds);
+ mPendingUpdates = true;
+}
+
+void NpSpatialIndex::remove(PxSpatialIndexItemId id)
+{
+ PX_SIMD_GUARD;
+
+ mPruner->removeObjects(&id);
+ mPendingUpdates = true;
+}
+
+PxBounds3 NpSpatialIndex::getBounds(PxSpatialIndexItemId /*id*/) const
+{
+ return PxBounds3();
+}
+
+namespace
+{
+ struct OverlapCallback: public PrunerCallback
+ {
+ OverlapCallback(PxSpatialOverlapCallback& callback) : mUserCallback(callback) {}
+
+ virtual PxAgain invoke(PxReal& /*distance*/, const PrunerPayload& userData)
+ {
+ PxSpatialIndexItem& item = *reinterpret_cast<PxSpatialIndexItem*>(userData.data[0]);
+ return mUserCallback.onHit(item);
+ }
+
+ PxSpatialOverlapCallback &mUserCallback;
+ private:
+ OverlapCallback& operator=(const OverlapCallback&);
+ };
+
+ struct LocationCallback: public PrunerCallback
+ {
+ LocationCallback(PxSpatialLocationCallback& callback) : mUserCallback(callback) {}
+
+ virtual PxAgain invoke(PxReal& distance, const PrunerPayload& userData)
+ {
+ PxReal oldDistance = distance, shrunkDistance = distance;
+ PxSpatialIndexItem& item = *reinterpret_cast<PxSpatialIndexItem*>(userData.data[0]);
+ PxAgain result = mUserCallback.onHit(item, distance, shrunkDistance);
+
+ if(shrunkDistance>distance)
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxSpatialLocationCallback: distance may not be extended.");
+
+ if(!result)
+ return false;
+
+ distance = PxMin(oldDistance, distance);
+ return true;
+ }
+
+ PxSpatialLocationCallback& mUserCallback;
+
+ private:
+ LocationCallback& operator=(const LocationCallback&);
+ };
+}
+
+void NpSpatialIndex::flushUpdates() const
+{
+ if(mPendingUpdates)
+ mPruner->commit();
+ mPendingUpdates = false;
+}
+
+void NpSpatialIndex::overlap(const PxBounds3& aabb,
+ PxSpatialOverlapCallback& callback) const
+{
+ PX_SIMD_GUARD;
+ PX_CHECK_AND_RETURN(aabb.isValid(), "PxSpatialIndex::overlap: aabb is not valid.");
+
+ flushUpdates();
+ OverlapCallback cb(callback);
+ PxBoxGeometry boxGeom(aabb.getExtents());
+ PxTransform xf(aabb.getCenter());
+ ShapeData shapeData(boxGeom, xf, 0.0f); // temporary rvalue not compatible with PX_NOCOPY
+ mPruner->overlap(shapeData, cb);
+}
+
+void NpSpatialIndex::raycast(const PxVec3& origin,
+ const PxVec3& unitDir,
+ PxReal maxDist,
+ PxSpatialLocationCallback& callback) const
+{
+ PX_SIMD_GUARD;
+
+ PX_CHECK_AND_RETURN(origin.isFinite(), "PxSpatialIndex::raycast: origin is not valid.");
+ PX_CHECK_AND_RETURN(unitDir.isFinite() && unitDir.isNormalized(), "PxSpatialIndex::raycast: unitDir is not valid.");
+ PX_CHECK_AND_RETURN(maxDist > 0.0f, "PxSpatialIndex::raycast: distance must be positive");
+
+ flushUpdates();
+ LocationCallback cb(callback);
+ mPruner->raycast(origin, unitDir, maxDist, cb);
+}
+
+void NpSpatialIndex::sweep(const PxBounds3& aabb,
+ const PxVec3& unitDir,
+ PxReal maxDist,
+ PxSpatialLocationCallback& callback) const
+{
+ PX_SIMD_GUARD;
+
+ PX_CHECK_AND_RETURN(aabb.isValid(), "PxSpatialIndex::sweep: aabb is not valid.");
+ PX_CHECK_AND_RETURN(unitDir.isFinite() && unitDir.isNormalized(), "PxSpatialIndex::sweep: unitDir is not valid.");
+ PX_CHECK_AND_RETURN(maxDist > 0.0f, "PxSpatialIndex::sweep: distance must be positive");
+
+ flushUpdates();
+ LocationCallback cb(callback);
+ PxBoxGeometry boxGeom(aabb.getExtents());
+ PxTransform xf(aabb.getCenter());
+ ShapeData shapeData(boxGeom, xf, 0.0f); // temporary rvalue not compatible with PX_NOCOPY
+ mPruner->sweep(shapeData, unitDir, maxDist, cb);
+}
+
+
+void NpSpatialIndex::rebuildFull()
+{
+ PX_SIMD_GUARD;
+
+ mPruner->purge();
+ mPruner->commit();
+ mPendingUpdates = false;
+}
+
+void NpSpatialIndex::setIncrementalRebuildRate(PxU32 rate)
+{
+ mPruner->setRebuildRateHint(rate);
+}
+
+void NpSpatialIndex::rebuildStep()
+{
+ PX_SIMD_GUARD;
+ mPruner->buildStep();
+ mPendingUpdates = true;
+}
+
+void NpSpatialIndex::release()
+{
+ delete this;
+}
+
+
+PxSpatialIndex* physx::PxCreateSpatialIndex()
+{
+ return PX_NEW(NpSpatialIndex)();
+}
+
diff --git a/PhysX_3.4/Source/PhysX/src/NpSpatialIndex.h b/PhysX_3.4/Source/PhysX/src/NpSpatialIndex.h
new file mode 100644
index 00000000..4d46f006
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpSpatialIndex.h
@@ -0,0 +1,92 @@
+// 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 NP_SPATIALINDEX
+#define NP_SPATIALINDEX
+
+#include "PxSpatialIndex.h"
+#include "PsUserAllocated.h"
+#include "CmPhysXCommon.h"
+
+namespace physx
+{
+namespace Sq
+{
+ class IncrementalPruner;
+}
+
+class NpSpatialIndex: public PxSpatialIndex, public Ps::UserAllocated
+{
+public:
+ NpSpatialIndex();
+ ~NpSpatialIndex();
+
+ virtual PxSpatialIndexItemId insert(PxSpatialIndexItem& item,
+ const PxBounds3& bounds);
+
+ virtual void update(PxSpatialIndexItemId id,
+ const PxBounds3& bounds);
+
+ virtual void remove(PxSpatialIndexItemId id);
+
+ virtual PxBounds3 getBounds(PxSpatialIndexItemId id) const;
+
+ virtual void overlap(const PxBounds3& aabb,
+ PxSpatialOverlapCallback& callback) const;
+
+ virtual void raycast(const PxVec3& origin,
+ const PxVec3& unitDir,
+ PxReal maxDist,
+ PxSpatialLocationCallback& callback) const;
+
+ virtual void sweep(const PxBounds3& aabb,
+ const PxVec3& unitDir,
+ PxReal maxDist,
+ PxSpatialLocationCallback& callback) const;
+
+ virtual void flush() { flushUpdates(); }
+ virtual void rebuildFull();
+ virtual void setIncrementalRebuildRate(PxU32 rate);
+ virtual void rebuildStep();
+ virtual void release();
+private:
+
+ // const so that we can call it from const methods
+ void flushUpdates() const;
+
+ mutable bool mPendingUpdates;
+ Sq::IncrementalPruner* mPruner;
+};
+
+
+}
+#endif
+
+
diff --git a/PhysX_3.4/Source/PhysX/src/NpVolumeCache.cpp b/PhysX_3.4/Source/PhysX/src/NpVolumeCache.cpp
new file mode 100644
index 00000000..35b7e5d9
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpVolumeCache.cpp
@@ -0,0 +1,806 @@
+// 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 "NpVolumeCache.h"
+#include "SqSceneQueryManager.h"
+#include "GuBounds.h"
+#include "PxRigidActor.h"
+#include "GuRaycastTests.h"
+#include "PxGeometryQuery.h"
+#include "GuIntersectionRayBox.h"
+#include "NpQueryShared.h"
+#include "NpSceneQueries.h"
+#include "PsFoundation.h"
+
+namespace physx {
+
+using namespace Sq;
+using namespace Gu;
+
+static PX_FORCE_INLINE NpScene* getNpScene(SceneQueryManager* sqm)
+{
+ return const_cast<NpScene*>(getNpScene(&sqm->getScene()));
+}
+
+//========================================================================================================================
+NpVolumeCache::NpVolumeCache(Sq::SceneQueryManager* sqm, PxU32 maxStaticShapes, PxU32 maxDynamicShapes)
+ : mSQManager(sqm)
+{
+ mCacheVolume.any() = InvalidGeometry();
+ mMaxShapeCount[0] = maxStaticShapes;
+ mMaxShapeCount[1] = maxDynamicShapes;
+ mIsInvalid[0] = mIsInvalid[1] = true;
+ mCache[0].reserve(maxStaticShapes);
+ mCache[1].reserve(maxDynamicShapes);
+}
+
+//========================================================================================================================
+NpVolumeCache::~NpVolumeCache()
+{
+}
+
+//========================================================================================================================
+void NpVolumeCache::invalidate()
+{
+ mCacheVolume.any() = InvalidGeometry();
+ mCache[0].clear();
+ mCache[1].clear();
+ mIsInvalid[0] = mIsInvalid[1] = true;
+}
+
+//========================================================================================================================
+void NpVolumeCache::release()
+{
+ getNpScene(mSQManager)->releaseVolumeCache(this);
+}
+
+//========================================================================================================================
+PxI32 NpVolumeCache::getNbCachedShapes()
+{
+ if(!isValid())
+ return -1;
+ return PxI32(mCache[0].size()+mCache[1].size());
+}
+
+//========================================================================================================================
+bool NpVolumeCache::isValid() const
+{
+ if(mIsInvalid[0] || mIsInvalid[1])
+ return false;
+
+ return mSQManager->get(PruningIndex::eSTATIC).timestamp() == mStaticTimestamp && mSQManager->get(PruningIndex::eDYNAMIC).timestamp() == mDynamicTimestamp;
+}
+
+//========================================================================================================================
+bool NpVolumeCache::isValid(PxU32 isDynamic) const
+{
+ if(mIsInvalid[isDynamic])
+ return false;
+
+ return isDynamic ?
+ (mSQManager->get(PruningIndex::eDYNAMIC).timestamp() == mDynamicTimestamp) : (mSQManager->get(PruningIndex::eSTATIC).timestamp() == mStaticTimestamp);
+}
+
+//========================================================================================================================
+// PT: TODO: replace this with just holder.storeAny() when/if we can support convexes
+static PX_INLINE bool geometryToHolder(const PxGeometry& geometry, PxGeometryHolder& holder)
+{
+ holder.any() = geometry; // this just copies the type, so that later holder.box() etc don't assert. Awkward but works.
+ switch ( geometry.getType() )
+ {
+ case PxGeometryType::eBOX:
+ holder.box() = static_cast<const PxBoxGeometry&>( geometry );
+ break;
+ case PxGeometryType::eSPHERE:
+ holder.sphere() = static_cast<const PxSphereGeometry&>( geometry );
+ break;
+ case PxGeometryType::eCAPSULE:
+ holder.capsule() = static_cast<const PxCapsuleGeometry&>( geometry );
+ break;
+ // convexes are not supported for now. The rationale is unknown utility
+ // and we need to correctly handle refcounts on a convex mesh (and write unit tests for that)
+ //case PxGeometryType::eCONVEXMESH:
+ // holder.convexMesh() = static_cast<const PxConvexMeshGeometry&>( geometry );
+ // break;
+ case PxGeometryType::ePLANE:
+ case PxGeometryType::eCONVEXMESH:
+ case PxGeometryType::eTRIANGLEMESH:
+ case PxGeometryType::eHEIGHTFIELD:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ holder.any() = InvalidGeometry();
+ return false;
+ }
+
+ return true;
+}
+
+//========================================================================================================================
+PxVolumeCache::FillStatus NpVolumeCache::fill(const PxGeometry& cacheVolume, const PxTransform& pose)
+{
+ PX_CHECK_AND_RETURN_VAL(pose.isSane(), "Invalid pose in PxVolumeCache::fill()", FILL_UNSUPPORTED_GEOMETRY_TYPE);
+
+ // save the cache volume pose into a cache pose
+ mCachePose = pose;
+
+ // save the provided geometry arg in mCacheVolume
+ // try to convert geometry to holder, if fails mark the cache as invalid and notify the user about unsupported geometry type
+ if(!geometryToHolder(cacheVolume, mCacheVolume))
+ {
+ physx::shdfnd::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxVolumeCache::fill(): unsupported cache volume geometry type.");
+ mIsInvalid[0] = mIsInvalid[1] = true;
+ return FILL_UNSUPPORTED_GEOMETRY_TYPE;
+ }
+
+ mIsInvalid[0] = mIsInvalid[1] = true; // invalidate the cache due to volume change
+
+ FillStatus status0 = fillInternal(0);
+ FillStatus status1 = fillInternal(1);
+
+ PX_COMPILE_TIME_ASSERT(FILL_OK < FILL_OVER_MAX_COUNT && FILL_OVER_MAX_COUNT < FILL_UNSUPPORTED_GEOMETRY_TYPE);
+ PX_COMPILE_TIME_ASSERT(FILL_UNSUPPORTED_GEOMETRY_TYPE < FILL_OUT_OF_MEMORY);
+ return PxMax(status0, status1);
+}
+
+//========================================================================================================================
+PxVolumeCache::FillStatus NpVolumeCache::fillInternal(PxU32 isDynamic, const PxOverlapHit* prefilledBuffer, PxI32 prefilledCount)
+{
+ PX_ASSERT(isDynamic == 0 || isDynamic == 1);
+ PX_CHECK_AND_RETURN_VAL(mCachePose.isValid(), "PxVolumeCache::fillInternal: pose is not valid.", FILL_UNSUPPORTED_GEOMETRY_TYPE);
+
+ // allocate a buffer for temp results from SQ overlap call (or use prefilledBuffer)
+ const PxU32 maxStackHits = 64;
+ PxOverlapHit* hitBuffer = const_cast<PxOverlapHit*>(prefilledBuffer);
+ bool hitBufferAlloca = false;
+ if(prefilledBuffer == NULL)
+ {
+ if(mMaxShapeCount[isDynamic]+1 <= maxStackHits) // try allocating on the stack first if we can
+ {
+ hitBuffer = reinterpret_cast<PxOverlapHit*>(PxAlloca((mMaxShapeCount[isDynamic]+1) * sizeof(PxOverlapHit)));
+ hitBufferAlloca = true;
+ }
+ else
+ {
+ hitBuffer = reinterpret_cast<PxOverlapHit*>(physx::shdfnd::TempAllocator().allocate(
+ sizeof(PxOverlapHit) * (mMaxShapeCount[isDynamic]+1), __FILE__, __LINE__));
+ if(hitBuffer == NULL)
+ {
+ mIsInvalid[isDynamic] = true;
+ physx::shdfnd::getFoundation().error(physx::PxErrorCode::eOUT_OF_MEMORY, __FILE__, __LINE__,
+ "PxVolumeCache::fill(): Fallback memory allocation failed, mMaxShapeCount = %d. Try reducing the cache size.",
+ mMaxShapeCount[isDynamic]);
+ return FILL_OUT_OF_MEMORY;
+ }
+ }
+ }
+
+ // clear current cache
+ mCache[isDynamic].resize(0);
+
+ // query the scene
+ PxI32 resultCount = prefilledCount;
+ PxQueryFilterData fd(isDynamic ? PxQueryFlag::eDYNAMIC : PxQueryFlag::eSTATIC);
+ PxOverlapBuffer sqBuffer(hitBuffer, mMaxShapeCount[isDynamic]+1); // one extra element so we can detect overflow in a single callback
+ if(!prefilledBuffer)
+ {
+ getNpScene(mSQManager)->overlap(mCacheVolume.any(), mCachePose, sqBuffer, fd, NULL);
+ resultCount = PxI32(sqBuffer.getNbAnyHits());
+ }
+
+ if(resultCount > PxI32(mMaxShapeCount[isDynamic]))
+ {
+ // cache overflow - deallocate the temp buffer
+ if(!hitBufferAlloca && hitBuffer != prefilledBuffer)
+ physx::shdfnd::TempAllocator().deallocate(hitBuffer);
+ mIsInvalid[isDynamic] = true;
+ return FILL_OVER_MAX_COUNT;
+ }
+
+ // fill the cache
+ PX_ASSERT(resultCount <= PxI32(mMaxShapeCount[isDynamic]));
+ for (PxI32 iHit = 0; iHit < resultCount; iHit++)
+ {
+ PxActorShape as;
+ as.actor = hitBuffer[iHit].actor;
+ as.shape = hitBuffer[iHit].shape;
+ PX_ASSERT(as.actor && as.shape);
+ mCache[isDynamic].pushBack(as);
+ }
+
+ // timestamp the cache
+ if(isDynamic)
+ mDynamicTimestamp = mSQManager->get(PruningIndex::eDYNAMIC).timestamp();
+ else
+ mStaticTimestamp = mSQManager->get(PruningIndex::eSTATIC).timestamp();
+
+ // clear the invalid flag
+ mIsInvalid[isDynamic] = false;
+
+ if(!hitBufferAlloca && hitBuffer != prefilledBuffer)
+ physx::shdfnd::TempAllocator().deallocate(hitBuffer);
+
+ return FILL_OK;
+}
+
+//========================================================================================================================
+bool NpVolumeCache::getCacheVolume(PxGeometryHolder& resultVolume, PxTransform& resultPose)
+{
+ resultVolume = mCacheVolume;
+ resultPose = mCachePose;
+
+ return isValid();
+}
+
+//========================================================================================================================
+struct NpVolumeCacheSqCallback : PxOverlapCallback
+{
+ NpVolumeCache* cache;
+ NpVolumeCache::Iterator& iter;
+ PxU32 isDynamic;
+ PxActorShape* reportBuf;
+ bool reportedOverMaxCount;
+
+ NpVolumeCacheSqCallback(
+ NpVolumeCache* cache_, NpVolumeCache::Iterator& iter_,
+ PxU32 isDynamic_, PxOverlapHit* hits, PxActorShape* reportBuf_, PxU32 maxHits)
+ : PxOverlapCallback(hits, maxHits), cache(cache_), iter(iter_), isDynamic(isDynamic_),
+ reportBuf(reportBuf_), reportedOverMaxCount(false)
+ {}
+
+ virtual PxAgain processTouches(const PxOverlapHit* buffer, PxU32 nbHits)
+ {
+ // at this point we know that the callback's buffer capacity exceeds the cache max shape count by 1
+ // so if nbHits is within shape count it means there will be no more callbacks.
+
+ if(!reportedOverMaxCount && nbHits <= cache->mMaxShapeCount[isDynamic])
+ {
+ // if actual overlapCount is under cache capacity, fill the cache
+ if(const_cast<NpVolumeCache*>(cache)->fillInternal(isDynamic, buffer, PxI32(nbHits)) != PxVolumeCache::FILL_OK)
+ // we shouldn't really end up here because we already checked all possible bad conditions fill() could return
+ // so the only way to end up here is if this is an error condition that should already be logged from inside fillInternal
+ return false;
+ // At this point the cache should be valid and within the user specified capacity
+ PX_ASSERT(cache->isValid(isDynamic));
+ // break out of the loop, this will fall through to return the results from cache via iterator
+
+ return false;
+ } else
+ {
+ // reroute to the user
+ // copy into a temp buffer for iterator reporting
+ for (PxU32 j = 0; j < PxU32(nbHits); j++)
+ {
+ reportBuf[j].actor = buffer[j].actor;
+ reportBuf[j].shape = buffer[j].shape;
+ }
+
+ // invoke the iterator
+ iter.processShapes(nbHits, reportBuf);
+ reportedOverMaxCount = true;
+ return true;
+ }
+ }
+
+private:
+ NpVolumeCacheSqCallback& operator=(const NpVolumeCacheSqCallback&);
+};
+
+void NpVolumeCache::forEach(Iterator& iter)
+{
+ if(mCacheVolume.getType() == PxGeometryType::eINVALID)
+ return; // The volume wasn't set, do nothing. No results fed to the iterator.
+
+ // keep track of whether we reported over max count shapes via callback to the user, per static/dynamic type
+ bool reportedOverMaxCount[2] = { false, false };
+ // will be set to true if cache was overflown inside of callback
+ // if this flag stays at false, it means the cache was be filled and validated/timestamped
+
+ for (PxU32 isDynamic = 0; isDynamic <= 1; isDynamic++)
+ {
+ if(isValid(isDynamic))
+ continue;
+
+ const PxU32 maxShapeCount = mMaxShapeCount[isDynamic];
+
+ // retrieve all the shapes overlapping with the current cache volume from the scene
+ // using currentTryShapeCount size temp buffer
+ PxQueryFilterData fd(isDynamic ? PxQueryFlag::eDYNAMIC : PxQueryFlag::eSTATIC);
+
+ // allocate a local hit buffer, either on the stack or from temp allocator, just big enough to hold #hits=max cached shapes
+ PxOverlapHit* localBuffer;
+ PxActorShape* reportBuffer;
+ const PxU32 maxStackShapes = 65;
+ if(maxShapeCount+1 <= maxStackShapes)
+ {
+ localBuffer = reinterpret_cast<PxOverlapHit*>(PxAlloca(maxStackShapes * (sizeof(PxOverlapHit) + sizeof(PxActorShape))));
+ reportBuffer = static_cast<PxActorShape*>(localBuffer + maxStackShapes);
+ } else
+ {
+ localBuffer = reinterpret_cast<PxOverlapHit*>(physx::shdfnd::TempAllocator().allocate(
+ (sizeof(PxOverlapHit) + sizeof(PxActorShape)) * (maxShapeCount+1), __FILE__, __LINE__));
+ reportBuffer = static_cast<PxActorShape*>(localBuffer + maxShapeCount+1);
+ }
+
+ // +1 shape so we can tell inside of single callback if we blew the buffer
+ NpVolumeCacheSqCallback cacheSqCallback(this, iter, isDynamic, localBuffer, reportBuffer, maxShapeCount+1);
+
+ // execute the overlap query to get all touching shapes. will be processed in cb.processTouches()
+ getNpScene(mSQManager)->overlap(mCacheVolume.any(), mCachePose, cacheSqCallback, fd, NULL);
+ reportedOverMaxCount[isDynamic] = cacheSqCallback.reportedOverMaxCount;
+
+ if(maxShapeCount >= maxStackShapes) // release the local hit buffer if not on the stack
+ physx::shdfnd::TempAllocator().deallocate(localBuffer);
+
+ } // for (isDynamic)
+
+ // report all cached shapes via the iterator callback, any shapes previously over capacity were already reported
+ // if so reportedOverMaxCount is set to true at this point for statics and/or dynamics correspondingly
+ if(!reportedOverMaxCount[0] && mCache[0].size() > 0)
+ iter.processShapes(mCache[0].size(), mCache[0].begin());
+ if(!reportedOverMaxCount[1] && mCache[1].size() > 0)
+ iter.processShapes(mCache[1].size(), mCache[1].begin());
+ iter.finalizeQuery();
+}
+
+//========================================================================================================================
+void NpVolumeCache::setMaxNbStaticShapes(PxU32 maxCount)
+{
+ if(maxCount < mCache[0].size())
+ {
+ mIsInvalid[0] = true;
+ mCache[0].clear();
+ }
+ mMaxShapeCount[0] = maxCount;
+ mCache[0].reserve(maxCount);
+}
+
+//========================================================================================================================
+PxU32 NpVolumeCache::getMaxNbStaticShapes()
+{
+ return mMaxShapeCount[0];
+}
+
+//========================================================================================================================
+void NpVolumeCache::setMaxNbDynamicShapes(PxU32 maxCount)
+{
+ if(maxCount < mCache[1].size())
+ {
+ mIsInvalid[1] = true;
+ mCache[1].clear();
+ }
+ mMaxShapeCount[1] = maxCount;
+ mCache[1].reserve(maxCount);
+}
+
+//========================================================================================================================
+PxU32 NpVolumeCache::getMaxNbDynamicShapes()
+{
+ return mMaxShapeCount[1];
+}
+
+//========================================================================================================================
+ static PX_FORCE_INLINE PxActorShape* applyAllPreFiltersVC(
+ PxActorShape* as, PxQueryHitType::Enum& hitType, const PxQueryFlags& inFilterFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall, const NpScene& scene, PxHitFlags& hitFlags)
+{
+ if(!applyClientFilter(as->actor, filterData, scene))
+ return NULL;
+
+ if(!applyFilterEquation(static_cast<NpShape*>(as->shape)->getScbShape(), filterData.data))
+ return NULL;
+
+ if(filterCall && (inFilterFlags & PxQueryFlag::ePREFILTER))
+ {
+ PxHitFlags outHitFlags = hitFlags;
+
+ hitType = filterCall->preFilter(filterData.data, as->shape, as->actor, outHitFlags);
+
+ hitFlags = (hitFlags & ~PxHitFlag::eMODIFIABLE_FLAGS) | (outHitFlags & PxHitFlag::eMODIFIABLE_FLAGS);
+ }
+ return as;
+}
+
+// performs a single geometry query for any HitType (PxSweepHit, PxOverlapHit, PxRaycastHit)
+template<typename HitType>
+struct GeomQueryAny
+{
+ static PX_INLINE PxU32 geomHit(
+ const MultiQueryInput& input,
+ const PxGeometry& geom, const PxTransform& pose, PxHitFlags outputFlags,
+ PxU32 maxHits, HitType* hits, PxReal& shrunkMaxDistance)
+ {
+ if(HitTypeSupport<HitType>::IsRaycast)
+ {
+ // for meshes test against the mesh AABB
+ if(0 && geom.getType() == PxGeometryType::eTRIANGLEMESH)
+ {
+ PxBounds3 bounds;
+ computeBounds(bounds, geom, pose, 0.0f, NULL, 1.0f, false);
+ PxF32 tnear, tfar;
+ if(!intersectRayAABB2(
+ bounds.minimum, bounds.maximum, *input.rayOrigin, *input.unitDir, shrunkMaxDistance, tnear, tfar))
+ return 0;
+ }
+ // perform a raycast against the cached shape
+ return PxGeometryQuery::raycast(
+ input.getOrigin(), input.getDir(), geom, pose, shrunkMaxDistance, outputFlags,
+ maxHits, reinterpret_cast<PxRaycastHit*>(hits));
+ }
+ else if(HitTypeSupport<HitType>::IsSweep)
+ {
+ PxU32 result = PxU32(PxGeometryQuery::sweep(
+ input.getDir(), input.maxDistance, *input.geometry, *input.pose, geom, pose, reinterpret_cast<PxSweepHit&>(hits[0]), outputFlags));
+ return result;
+ }
+ else if(HitTypeSupport<HitType>::IsOverlap)
+ {
+ PxU32 result = PxU32(PxGeometryQuery::overlap(*input.geometry, *input.pose, geom, pose));
+ return result;
+ }
+ else
+ {
+ PX_ALWAYS_ASSERT_MESSAGE("Unexpected template expansion in GeomQueryAny::geomHit");
+ return 0;
+ }
+ }
+};
+
+// performs a cache volume query for any HitType (PxSweepHit, PxOverlapHit, PxRaycastHit)
+template<typename HitType>
+struct SceneQueryAny
+{
+ static PX_INLINE bool doQuery(
+ PxScene* scene, const MultiQueryInput& input, PxHitCallback<HitType>& hitCall, PxHitFlags hitFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall)
+ {
+ if(HitTypeSupport<HitType>::IsRaycast)
+ {
+ PX_ASSERT(sizeof(HitType) == sizeof(PxRaycastHit));
+ scene->raycast(input.getOrigin(), input.getDir(), input.maxDistance,
+ reinterpret_cast<PxRaycastCallback&>(hitCall), hitFlags, filterData, filterCall, NULL);
+ return hitCall.hasAnyHits();
+ }
+ else if(HitTypeSupport<HitType>::IsSweep)
+ {
+ PX_ASSERT(sizeof(HitType) == sizeof(PxSweepHit));
+ scene->sweep(*input.geometry, *input.pose, input.getDir(), input.maxDistance,
+ reinterpret_cast<PxSweepCallback&>(hitCall), hitFlags, filterData, filterCall, NULL);
+ return hitCall.hasAnyHits();
+ }
+ else if(HitTypeSupport<HitType>::IsOverlap)
+ {
+ PX_ASSERT(sizeof(HitType) == sizeof(PxOverlapHit));
+ scene->overlap(*input.geometry, *input.pose, reinterpret_cast<PxOverlapCallback&>(hitCall), filterData, filterCall);
+ return hitCall.hasAnyHits();
+ }
+ else
+ {
+ PX_ALWAYS_ASSERT_MESSAGE("Unexpected template expansion in SceneQueryAny::doQuery");
+ return false;
+ }
+ }
+};
+
+//========================================================================================================================
+template<typename HitType>
+PX_FORCE_INLINE void makeHitSafe(HitType& hit) // hit can contain NaNs (due to uninitialized mem allocation) which cannot be copied
+{
+ if(HitTypeSupport<HitType>::IsRaycast == 1 || HitTypeSupport<HitType>::IsSweep == 1)
+ {
+#if PX_VC
+#pragma warning(push)
+#pragma warning(disable : 4946) // reinterpret_cast used between related classes
+ // happens if the template param inherits from PxLocationHit
+#endif
+ PxLocationHit& hit1 = reinterpret_cast<PxLocationHit&>(hit);
+#if PX_VC
+#pragma warning(pop)
+#endif
+ if(!(hit1.flags & PxHitFlag::eDISTANCE))
+ hit1.distance = 0.0f;
+ if(!(hit1.flags & PxHitFlag::ePOSITION))
+ hit1.position = PxVec3(0.0f);
+ if(!(hit1.flags & PxHitFlag::eNORMAL))
+ hit1.normal = PxVec3(0.0f);
+ }
+ if(HitTypeSupport<HitType>::IsRaycast == 1 && !(reinterpret_cast<PxRaycastHit&>(hit).flags & PxHitFlag::eUV) )
+ {
+ reinterpret_cast<PxRaycastHit&>(hit).u = 0.0f;
+ reinterpret_cast<PxRaycastHit&>(hit).v = 0.0f;
+ }
+}
+
+//========================================================================================================================
+template<typename HitType>
+bool NpVolumeCache::multiQuery(
+ const MultiQueryInput& input, PxHitCallback<HitType>& hitCall, PxHitFlags hitFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall, PxF32 inflation) const
+{
+
+ if(HitTypeSupport<HitType>::IsRaycast == 0)
+ {
+ PX_CHECK_AND_RETURN_VAL(input.pose->isValid(), "sweepInputCheck: pose is not valid.", 0);
+ }
+ if(HitTypeSupport<HitType>::IsOverlap == 0)
+ {
+ PX_CHECK_AND_RETURN_VAL(input.getDir().isFinite(), "PxVolumeCache multiQuery input check: unitDir is not valid.", 0);
+ PX_CHECK_AND_RETURN_VAL(input.getDir().isNormalized(), "PxVolumeCache multiQuery input check: direction must be normalized", 0);
+ }
+ if(HitTypeSupport<HitType>::IsRaycast)
+ {
+ PX_CHECK_AND_RETURN_VAL(input.maxDistance > 0.0f, "PxVolumeCache multiQuery input check: distance cannot be negative or zero", 0);
+ }
+ if(HitTypeSupport<HitType>::IsSweep)
+ {
+ PX_CHECK_AND_RETURN_VAL(input.maxDistance >= 0.0f, "NpSceneQueries multiQuery input check: distance cannot be negative", 0);
+ PX_CHECK_AND_RETURN_VAL(input.maxDistance != 0.0f || !(hitFlags & PxHitFlag::eASSUME_NO_INITIAL_OVERLAP),
+ "PxVolumeCache multiQuery input check: zero-length sweep only valid without the PxHitFlag::eASSUME_NO_INITIAL_OVERLAP flag", 0);
+ }
+
+ hitCall.hasBlock = false;
+ hitCall.nbTouches = 0;
+
+ const PxQueryFlags filterFlags = filterData.flags;
+
+ // refill the cache if invalid
+ for(PxU32 isDynamic = 0; isDynamic <= 1; isDynamic++)
+ {
+ if(!isValid(isDynamic) && ((isDynamic+1) & PxU32(filterFlags)) != 0) // isDynamic+1 = 1 for static, 2 for dynamic
+ // check for overflow or unspecified cache volume&transform, fall back to scene query on overflow (or invalid voltype)
+ if(const_cast<NpVolumeCache*>(this)->fillInternal(isDynamic) == FILL_OVER_MAX_COUNT
+ || mCacheVolume.getType() == PxGeometryType::eINVALID)
+ {
+ // fall back to full scene query with input flags if we blow the cache on either static or dynamic for now
+ if(mCacheVolume.getType() == PxGeometryType::eINVALID)
+ Ps::getFoundation().error(PxErrorCode::ePERF_WARNING, __FILE__, __LINE__,
+ "PxVolumeCache: unspecified volume geometry. Reverting to uncached scene query.");
+ return SceneQueryAny<HitType>::doQuery(
+ getNpScene(mSQManager), input, hitCall, hitFlags, filterData, filterCall);
+ }
+ }
+
+ // cache is now valid and there was no overflow
+ PX_ASSERT_WITH_MESSAGE(isValid() ,"PxVolumeCache became invalid inside of a scene read call.");
+
+ const PxU32 cacheSize[2] = { mCache[0].size(), mCache[1].size() };
+
+ // early out if the cache is empty and valid
+ if(cacheSize[0] == 0 && cacheSize[1] == 0)
+ return 0;
+
+ PxReal shrunkDistance = HitTypeSupport<HitType>::IsOverlap ? PX_MAX_REAL : input.maxDistance; // can be progressively shrunk as we go over the list of shapes
+ const NpScene& scene = *getNpScene(mSQManager);
+ HitType* subHits = NULL;
+
+ // make sure to deallocate the temp buffer when we return
+ struct FreeSubhits
+ {
+ HitType* toFree;
+ PX_FORCE_INLINE FreeSubhits() { toFree = NULL; }
+ PX_FORCE_INLINE ~FreeSubhits() { if (toFree) physx::shdfnd::TempAllocator().deallocate(toFree); }
+ } ds;
+
+ // allocate from temp storage rather than from the stack if we are over some shape count
+ PxU32 maxMaxShapeCount = PxMax(mMaxShapeCount[0], mMaxShapeCount[1]); // max size buffer for statics and dynamics
+ if(maxMaxShapeCount < 128) // somewhat arbitrary
+ subHits = reinterpret_cast<HitType*>(PxAlloca(sizeof(HitType)*maxMaxShapeCount));
+ else
+ ds.toFree = subHits = reinterpret_cast<HitType*>(physx::shdfnd::TempAllocator().allocate(sizeof(HitType)*maxMaxShapeCount, __FILE__, __LINE__));
+
+ const bool noBlock = (filterFlags & PxQueryFlag::eNO_BLOCK);
+
+ // for statics & dynamics
+ for(PxU32 isDynamic = 0; isDynamic <= 1; isDynamic++)
+ // iterate over all the cached shapes
+ for(PxU32 iCachedShape = 0; iCachedShape < cacheSize[isDynamic]; iCachedShape++)
+ {
+ PxActorShape* as = &mCache[isDynamic][iCachedShape];
+
+ const PxU32 actorFlag = (PxU32(as->actor->is<PxRigidDynamic>() != NULL) + 1); // 1 for static, 2 for dynamic
+ PX_COMPILE_TIME_ASSERT(PxQueryFlag::eSTATIC == 1);
+ PX_COMPILE_TIME_ASSERT(PxQueryFlag::eDYNAMIC == 2);
+ if((actorFlag & PxU32(filterFlags)) == 0) // filter the actor according to the input static/dynamic filter
+ continue;
+
+ // for no filter callback, default to eTOUCH for MULTIPLE, eBLOCK otherwise
+ PxQueryHitType::Enum shapeHitType = hitCall.maxNbTouches ? PxQueryHitType::eTOUCH : PxQueryHitType::eBLOCK;
+
+ // apply pre-filter
+ PxHitFlags queryFlags = hitFlags;
+ as = applyAllPreFiltersVC(as, shapeHitType, filterFlags, filterData, filterCall, scene, hitFlags);
+ if(!as || shapeHitType == PxQueryHitType::eNONE)
+ continue;
+ PX_ASSERT(as->actor && as->shape);
+
+ NpShape* shape = static_cast<NpShape*>(as->shape);
+
+ // compute the global pose for the cached shape and actor
+ PX_ALIGN(16, PxTransform) globalPose;
+ NpActor::getGlobalPose(globalPose, *shape, *as->actor);
+
+ const GeometryUnion& cachedShapeGeom = shape->getGeometryFast();
+
+ // call the geometry specific intersection template
+ PxU32 nbSubHits = GeomQueryAny<HitType>::geomHit(
+ input, cachedShapeGeom.getGeometry(), globalPose, queryFlags,
+ // limit number of hits to 1 for meshes if eMESH_MULTIPLE wasn't specified.
+ //this tells geomQuery to only look for a closest hit
+ (cachedShapeGeom.getType() == PxGeometryType::eTRIANGLEMESH && !(hitFlags & PxHitFlag::eMESH_MULTIPLE)) ? 1 : maxMaxShapeCount,
+ subHits, shrunkDistance);
+
+ // iterate over geometry subhits
+ for(PxU32 iSubHit = 0; iSubHit < nbSubHits; iSubHit++)
+ {
+ HitType& hit = subHits[iSubHit];
+ hit.actor = as->actor;
+ hit.shape = as->shape;
+ makeHitSafe<HitType>(hit);
+
+ // some additional processing only for sweep hits with initial overlap
+ if(HitTypeSupport<HitType>::IsSweep && HITDIST(hit) == 0.0f)
+ // PT: necessary as some leaf routines are called with reversed params, thus writing +unitDir there.
+ reinterpret_cast<PxSweepHit&>(hit).normal = -input.getDir();
+
+ // start out with hitType for this cached shape set to a pre-filtered hit type
+ PxQueryHitType::Enum hitType = shapeHitType;
+
+ // run the post-filter if specified in filterFlags and filterCall is non-NULL
+ if(filterCall && (filterFlags & PxQueryFlag::ePOSTFILTER))
+ hitType = filterCall->postFilter(filterData.data, hit);
+
+ // -------------------------- handle eANY_HIT hits ---------------------------------
+ if(filterFlags & PxQueryFlag::eANY_HIT && hitType != PxQueryHitType::eNONE)
+ {
+ hitCall.block = hit;
+ hitCall.finalizeQuery();
+ return (hitCall.hasBlock = true);
+ }
+
+ if(noBlock)
+ hitType = PxQueryHitType::eTOUCH;
+
+ if(hitType == PxQueryHitType::eTOUCH)
+ {
+ // -------------------------- handle eTOUCH hits ---------------------------------
+ // for MULTIPLE hits (hitCall.touches != NULL), store the hit. For other qTypes ignore it.
+ if(hitCall.maxNbTouches && HITDIST(hit) <= shrunkDistance)
+ {
+ // Buffer full: need to find the closest blocking hit, clip touch hits and flush the buffer
+ if(hitCall.nbTouches == hitCall.maxNbTouches)
+ {
+ // issue a second nested query just looking for the closest blocking hit
+ // could do better perf-wise by saving traversal state (start looking for blocking from this point)
+ // but this is not a perf critical case because users can provide a bigger buffer
+ // that covers non-degenerate cases
+ PxHitBuffer<HitType> buf1;
+ if(multiQuery<HitType>(input, buf1, hitFlags, filterData, filterCall, inflation))
+ {
+ hitCall.block = buf1.block;
+ hitCall.hasBlock = true;
+ hitCall.nbTouches =
+ clipHitsToNewMaxDist<HitType>(hitCall.touches, hitCall.nbTouches, HITDIST(buf1.block));
+ }
+
+ if(hitCall.nbTouches == hitCall.maxNbTouches)
+ {
+ PxAgain again = hitCall.processTouches(hitCall.touches, hitCall.maxNbTouches);
+ if(!again) // early exit opportunity
+ {
+ hitCall.finalizeQuery();
+ return hitCall.hasBlock;
+ } else
+ hitCall.nbTouches = 0; // reset nbTouches so we can continue accumulating again
+ }
+
+ } // if(hitCall.nbTouches == hitCall.maxNbTouches)
+
+ hitCall.touches[hitCall.nbTouches++] = hit;
+ } // if(hitCall.maxNbTouches && hit.dist <= shrunkDist)
+ }
+ else if(hitType == PxQueryHitType::eBLOCK)
+ {
+ // -------------------------- handle eBLOCK hits ---------------------------------
+ // former SINGLE and MULTIPLE cases => update blocking hit distance
+ // only eBLOCK qualifies as a closest hit candidate for "single" query
+ // => compare against the best distance and store
+ if(HITDIST(hit) <= shrunkDistance)
+ {
+ shrunkDistance = HITDIST(hit);
+ hitCall.block = hit;
+ hitCall.hasBlock = true;
+ }
+ } else
+ {
+ PX_ASSERT(hitType == PxQueryHitType::eNONE);
+ }
+ } // for iSubHit
+ } // for isDynamic, for iCachedShape
+
+ // clip any unreported touch hits to block.distance and report via callback
+ if(hitCall.hasBlock && hitCall.nbTouches)
+ hitCall.nbTouches = clipHitsToNewMaxDist(hitCall.touches, hitCall.nbTouches, HITDIST(hitCall.block));
+ if(hitCall.nbTouches)
+ {
+ bool again = hitCall.processTouches(hitCall.touches, hitCall.nbTouches);
+ if(again)
+ hitCall.nbTouches = 0;
+ }
+ hitCall.finalizeQuery();
+
+ return hitCall.hasBlock;
+}
+
+#undef HITDIST
+
+//========================================================================================================================
+bool NpVolumeCache::raycast(
+ const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, PxRaycastCallback& hitCall, PxHitFlags hitFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall) const
+{
+ PX_SIMD_GUARD;
+
+ MultiQueryInput input(origin, unitDir, distance);
+ bool result = multiQuery<PxRaycastHit>(input, hitCall, hitFlags, filterData, filterCall);
+ return result;
+}
+
+//=======================================================================================================================
+bool NpVolumeCache::sweep(
+ const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
+ PxSweepCallback& hitCall, PxHitFlags hitFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall, const PxReal inflation) const
+{
+ PX_SIMD_GUARD;
+
+ MultiQueryInput input(&geometry, &pose, unitDir, distance, 0.0f);
+ bool result = multiQuery<PxSweepHit>(input, hitCall, hitFlags, filterData, filterCall, inflation);
+ return result;
+}
+
+//========================================================================================================================
+bool NpVolumeCache::overlap(
+ const PxGeometry& geometry, const PxTransform& transform,
+ PxOverlapCallback& hitCall, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall) const
+{
+ PX_SIMD_GUARD;
+
+ MultiQueryInput input(&geometry, &transform);
+ bool result = multiQuery<PxOverlapHit>(input, hitCall, PxHitFlags(), filterData, filterCall);
+ return result;
+}
+
+//========================================================================================================================
+void NpVolumeCache::onOriginShift(const PxVec3& shift)
+{
+ mCachePose.p -= shift;
+}
+
+} // namespace physx
diff --git a/PhysX_3.4/Source/PhysX/src/NpVolumeCache.h b/PhysX_3.4/Source/PhysX/src/NpVolumeCache.h
new file mode 100644
index 00000000..a7038c21
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpVolumeCache.h
@@ -0,0 +1,111 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_VOLUMECACHE
+#define PX_PHYSICS_NP_VOLUMECACHE
+
+#include "PxVolumeCache.h"
+#include "PsUserAllocated.h"
+#include "CmPhysXCommon.h"
+#include "PsArray.h"
+
+namespace physx
+{
+
+ struct MultiQueryInput;
+
+namespace Sq { class SceneQueryManager; }
+
+
+// internal implementation for PxVolumeCache
+class NpVolumeCache : public PxVolumeCache, public Ps::UserAllocated
+{
+public:
+ NpVolumeCache(Sq::SceneQueryManager* sqm, PxU32 maxNbStatic, PxU32 maxNbDynamic);
+ virtual ~NpVolumeCache();
+ virtual bool isValid() const;
+ bool isValid(PxU32 isDynamic) const;
+
+ virtual FillStatus fill(const PxGeometry& cacheVolume, const PxTransform& pose);
+ FillStatus fillInternal(PxU32 isDynamic, const PxOverlapHit* buffer = NULL, PxI32 count = 0);
+
+ virtual bool getCacheVolume(PxGeometryHolder& resultVolume, PxTransform& resultPose);
+ virtual PxI32 getNbCachedShapes();
+
+ virtual void invalidate();
+ virtual void release();
+
+ virtual void forEach(Iterator& iter);
+
+ virtual void setMaxNbStaticShapes(PxU32 maxCount);
+ virtual PxU32 getMaxNbStaticShapes();
+ virtual void setMaxNbDynamicShapes(PxU32 maxCount);
+ virtual PxU32 getMaxNbDynamicShapes();
+
+ template<typename HitType>
+ bool multiQuery(
+ const MultiQueryInput& multiInput, // type specific input data
+ PxHitCallback<HitType>& hitCall, PxHitFlags hitFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ PxF32 inflation = 0.0f) const;
+
+ virtual bool raycast(
+ const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
+ PxRaycastCallback& hitCall, PxHitFlags hitFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall) const;
+
+ virtual bool sweep(
+ const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
+ PxSweepCallback& hitCall, PxHitFlags hitFlags,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ const PxReal inflation) const;
+
+ virtual bool overlap(
+ const PxGeometry& geometry, const PxTransform& pose,
+ PxOverlapCallback& hitCall, const PxQueryFilterData& filterData,
+ PxQueryFilterCallback* filterCall) const;
+
+
+ void onOriginShift(const PxVec3& shift);
+
+
+ PxGeometryHolder mCacheVolume;
+ PxTransform mCachePose;
+ PxU32 mMaxShapeCount[2];
+ Sq::SceneQueryManager* mSQManager;
+ mutable Ps::Array<PxActorShape> mCache[2]; // AP todo: improve memory management, could we have one allocation for both?
+ PxU32 mStaticTimestamp;
+ PxU32 mDynamicTimestamp;
+ bool mIsInvalid[2]; // invalid for reasons other than timestamp, such as overflow on previous fill
+};
+
+}
+
+#endif // PX_PHYSICS_NP_SCENE
diff --git a/PhysX_3.4/Source/PhysX/src/NpWriteCheck.cpp b/PhysX_3.4/Source/PhysX/src/NpWriteCheck.cpp
new file mode 100644
index 00000000..6c132150
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpWriteCheck.cpp
@@ -0,0 +1,92 @@
+// 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 "NpWriteCheck.h"
+
+#include "NpScene.h"
+
+using namespace physx;
+
+NpWriteCheck::NpWriteCheck(NpScene* scene, const char* functionName, bool allowReentry)
+: mScene(scene), mName(functionName), mAllowReentry(allowReentry), mErrorCount(0)
+{
+ if (mScene)
+ {
+ switch (mScene->startWrite(mAllowReentry))
+ {
+ case NpScene::StartWriteResult::eOK:
+ break;
+ case NpScene::StartWriteResult::eNO_LOCK:
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "An API write call (%s) was made from thread %d but PxScene::lockWrite() was not called first, note that "
+ "when PxSceneFlag::eREQUIRE_RW_LOCK is enabled all API reads and writes must be "
+ "wrapped in the appropriate locks.", mName, PxU32(Ps::Thread::getId()));
+ break;
+ case NpScene::StartWriteResult::eRACE_DETECTED:
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Concurrent API write call or overlapping API read and write call detected during %s from thread %d! "
+ "Note that write operations to the SDK must be sequential, i.e., no overlap with "
+ "other write or read calls, else the resulting behavior is undefined. "
+ "Also note that API writes during a callback function are not permitted.", mName, PxU32(Ps::Thread::getId()));
+ break;
+
+ case NpScene::StartWriteResult::eIN_FETCHRESULTS:
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Illegal write call detected in %s from thread %d during split fetchResults! "
+ "Note that write operations to the SDK are not permitted between the start of fetchResultsStart() and end of fetchResultsFinish(). "
+ "Behavior will be undefined. ", mName, PxU32(Ps::Thread::getId()));
+ break;
+ }
+
+ // Record the NpScene read/write error counter which is
+ // incremented any time a NpScene::startWrite/startRead fails
+ // (see destructor for additional error checking based on this count)
+ mErrorCount = mScene->getReadWriteErrorCount();
+ }
+}
+
+
+NpWriteCheck::~NpWriteCheck()
+{
+ if (mScene)
+ {
+ // By checking if the NpScene::mConcurrentErrorCount has been incremented
+ // we can detect if an erroneous read/write was performed during
+ // this objects lifetime. In this case we also print this function's
+ // details so that the user can see which two API calls overlapped
+ if (mScene->getReadWriteErrorCount() != mErrorCount && !(mScene->getScene().getFlags() & PxSceneFlag::eREQUIRE_RW_LOCK))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Leaving %s on thread %d, an overlapping API read or write by another thread was detected.", mName, PxU32(Ps::Thread::getId()));
+ }
+
+ mScene->stopWrite(mAllowReentry);
+ }
+}
diff --git a/PhysX_3.4/Source/PhysX/src/NpWriteCheck.h b/PhysX_3.4/Source/PhysX/src/NpWriteCheck.h
new file mode 100644
index 00000000..937209bd
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/NpWriteCheck.h
@@ -0,0 +1,79 @@
+// 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 NP_WRITE_CHECK_H
+#define NP_WRITE_CHECK_H
+
+#include "foundation/PxSimpleTypes.h"
+
+namespace physx
+{
+
+class NpScene;
+
+// RAII wrapper around the PxScene::startWrite() method, note that this
+// object does not acquire any scene locks, it is an error checking only mechanism
+class NpWriteCheck
+{
+public:
+ NpWriteCheck(NpScene* scene, const char* functionName, bool allowReentry=true);
+ ~NpWriteCheck();
+
+private:
+
+ NpScene* mScene;
+ const char* mName;
+ bool mAllowReentry;
+ PxU32 mErrorCount;
+};
+
+#if PX_DEBUG || PX_CHECKED
+ // Creates a scoped write check object that detects whether appropriate scene locks
+ // have been acquired and checks if reads/writes overlap, this macro should typically
+ // be placed at the beginning of any non-const API methods that are not multi-thread safe.
+ // By default re-entrant write calls by the same thread are allowed, the error conditions
+ // checked can be summarized as:
+
+ // 1. PxSceneFlag::eREQUIRE_RW_LOCK was specified but PxScene::lockWrite() was not yet called
+ // 2. Other threads were already reading, or began reading during the object lifetime
+ // 3. Other threads were already writing, or began writing during the object lifetime
+ #define NP_WRITE_CHECK(npScenePtr) NpWriteCheck npWriteCheck(npScenePtr, __FUNCTION__);
+
+ // Creates a scoped write check object that disallows re-entrant writes, this is used by
+ // the NpScene::simulate method to detect when callbacks make write calls to the API
+ #define NP_WRITE_CHECK_NOREENTRY(npScenePtr) NpWriteCheck npWriteCheck(npScenePtr, __FUNCTION__, false);
+#else
+ #define NP_WRITE_CHECK(npScenePtr)
+ #define NP_WRITE_CHECK_NOREENTRY(npScenePtr)
+#endif
+
+}
+
+#endif // NP_WRITE_CHECK_H
diff --git a/PhysX_3.4/Source/PhysX/src/PvdMetaDataBindingData.h b/PhysX_3.4/Source/PhysX/src/PvdMetaDataBindingData.h
new file mode 100644
index 00000000..add3fcfe
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/PvdMetaDataBindingData.h
@@ -0,0 +1,82 @@
+// 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_META_DATA_PVD_BINDING_DATA_H
+#define PX_META_DATA_PVD_BINDING_DATA_H
+#if PX_SUPPORT_PVD
+#include "foundation/PxSimpleTypes.h"
+#include "PsArray.h"
+#include "PsHashSet.h"
+#include "PsHashMap.h"
+
+namespace physx
+{
+namespace Vd
+{
+using namespace physx::shdfnd;
+
+typedef HashSet<const PxRigidActor*> OwnerActorsValueType;
+typedef HashMap<const PxShape*, OwnerActorsValueType*> OwnerActorsMap;
+
+struct PvdMetaDataBindingData : public UserAllocated
+{
+ Array<PxU8> mTempU8Array;
+ Array<PxActor*> mActors;
+ Array<PxArticulation*> mArticulations;
+ Array<PxArticulationLink*> mArticulationLinks;
+ HashSet<PxActor*> mSleepingActors;
+ OwnerActorsMap mOwnerActorsMap;
+
+ PvdMetaDataBindingData()
+ : mTempU8Array(PX_DEBUG_EXP("TempU8Array"))
+ , mActors(PX_DEBUG_EXP("PxActor"))
+ , mArticulations(PX_DEBUG_EXP("Articulations"))
+ , mArticulationLinks(PX_DEBUG_EXP("ArticulationLinks"))
+ , mSleepingActors(PX_DEBUG_EXP("SleepingActors"))
+ {
+ }
+
+ template <typename TDataType>
+ TDataType* allocateTemp(PxU32 numItems)
+ {
+ mTempU8Array.resize(numItems * sizeof(TDataType));
+ if(numItems)
+ return reinterpret_cast<TDataType*>(mTempU8Array.begin());
+ else
+ return NULL;
+ }
+
+ DataRef<const PxU8> tempToRef()
+ {
+ return DataRef<const PxU8>(mTempU8Array.begin(), mTempU8Array.size());
+ }
+};
+}
+}
+#endif // PX_SUPPORT_PVD
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/PvdMetaDataPvdBinding.cpp b/PhysX_3.4/Source/PhysX/src/PvdMetaDataPvdBinding.cpp
new file mode 100644
index 00000000..33951453
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/PvdMetaDataPvdBinding.cpp
@@ -0,0 +1,2416 @@
+// 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.
+
+// suppress LNK4221
+#include "foundation/PxPreprocessor.h"
+PX_DUMMY_SYMBOL
+
+#if PX_SUPPORT_PVD
+
+#include "foundation/PxSimpleTypes.h"
+#include "foundation/Px.h"
+
+#include "PxMetaDataObjects.h"
+#include "PxPvdDataStream.h"
+#include "PxScene.h"
+#include "ScBodyCore.h"
+#include "PvdMetaDataExtensions.h"
+#include "PvdMetaDataPropertyVisitor.h"
+#include "PvdMetaDataDefineProperties.h"
+#include "PvdMetaDataBindingData.h"
+#include "PxRigidDynamic.h"
+#include "PxArticulation.h"
+#include "PxArticulationLink.h"
+#include "NpScene.h"
+#include "NpPhysics.h"
+
+#include "gpu/PxParticleGpu.h"
+#include "PvdTypeNames.h"
+#include "PvdMetaDataPvdBinding.h"
+
+using namespace physx;
+using namespace Sc;
+using namespace Vd;
+using namespace Sq;
+
+namespace physx
+{
+namespace Vd
+{
+
+struct NameValuePair
+{
+ const char* mName;
+ PxU32 mValue;
+};
+
+static const NameValuePair g_physx_Sq_SceneQueryID__EnumConversion[] = {
+ { "QUERY_RAYCAST_ANY_OBJECT", PxU32(QueryID::QUERY_RAYCAST_ANY_OBJECT) },
+ { "QUERY_RAYCAST_CLOSEST_OBJECT", PxU32(QueryID::QUERY_RAYCAST_CLOSEST_OBJECT) },
+ { "QUERY_RAYCAST_ALL_OBJECTS", PxU32(QueryID::QUERY_RAYCAST_ALL_OBJECTS) },
+ { "QUERY_OVERLAP_SPHERE_ALL_OBJECTS", PxU32(QueryID::QUERY_OVERLAP_SPHERE_ALL_OBJECTS) },
+ { "QUERY_OVERLAP_AABB_ALL_OBJECTS", PxU32(QueryID::QUERY_OVERLAP_AABB_ALL_OBJECTS) },
+ { "QUERY_OVERLAP_OBB_ALL_OBJECTS", PxU32(QueryID::QUERY_OVERLAP_OBB_ALL_OBJECTS) },
+ { "QUERY_OVERLAP_CAPSULE_ALL_OBJECTS", PxU32(QueryID::QUERY_OVERLAP_CAPSULE_ALL_OBJECTS) },
+ { "QUERY_OVERLAP_CONVEX_ALL_OBJECTS", PxU32(QueryID::QUERY_OVERLAP_CONVEX_ALL_OBJECTS) },
+ { "QUERY_LINEAR_OBB_SWEEP_CLOSEST_OBJECT", PxU32(QueryID::QUERY_LINEAR_OBB_SWEEP_CLOSEST_OBJECT) },
+ { "QUERY_LINEAR_CAPSULE_SWEEP_CLOSEST_OBJECT", PxU32(QueryID::QUERY_LINEAR_CAPSULE_SWEEP_CLOSEST_OBJECT) },
+ { "QUERY_LINEAR_CONVEX_SWEEP_CLOSEST_OBJECT", PxU32(QueryID::QUERY_LINEAR_CONVEX_SWEEP_CLOSEST_OBJECT) },
+ { NULL, 0 }
+};
+
+struct SceneQueryIDConvertor
+{
+ const NameValuePair* NameConversion;
+ SceneQueryIDConvertor() : NameConversion(g_physx_Sq_SceneQueryID__EnumConversion)
+ {
+ }
+};
+
+PvdMetaDataBinding::PvdMetaDataBinding() : mBindingData(PX_NEW(PvdMetaDataBindingData)())
+{
+}
+
+PvdMetaDataBinding::~PvdMetaDataBinding()
+{
+ for(OwnerActorsMap::Iterator iter = mBindingData->mOwnerActorsMap.getIterator(); !iter.done(); iter++)
+ {
+ iter->second->~OwnerActorsValueType();
+ PX_FREE(iter->second);
+ }
+
+ PX_DELETE(mBindingData);
+ mBindingData = NULL;
+}
+
+template <typename TDataType, typename TValueType, typename TClassType>
+inline void definePropertyStruct(PvdDataStream& inStream, const char* pushName = NULL)
+{
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ PvdClassInfoValueStructDefine definitionObj(helper);
+ bool doPush = pushName && *pushName;
+ if(doPush)
+ definitionObj.pushName(pushName);
+ visitAllPvdProperties<TDataType>(definitionObj);
+ if(doPush)
+ definitionObj.popName();
+ helper.addPropertyMessage(getPvdNamespacedNameForType<TClassType>(), getPvdNamespacedNameForType<TValueType>(), sizeof(TValueType));
+}
+
+template <typename TDataType>
+inline void createClassAndDefineProperties(PvdDataStream& inStream)
+{
+ inStream.createClass<TDataType>();
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<TDataType>());
+ visitAllPvdProperties<TDataType>(definitionObj);
+}
+
+template <typename TDataType, typename TParentType>
+inline void createClassDeriveAndDefineProperties(PvdDataStream& inStream)
+{
+ inStream.createClass<TDataType>();
+ inStream.deriveClass<TParentType, TDataType>();
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<TDataType>());
+ visitInstancePvdProperties<TDataType>(definitionObj);
+}
+
+template <typename TDataType, typename TConvertSrc, typename TConvertData>
+inline void defineProperty(PvdDataStream& inStream, const char* inPropertyName, const char* semantic)
+{
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ // PxEnumTraits< TValueType > filterFlagsEnum;
+ TConvertSrc filterFlagsEnum;
+ const TConvertData* convertor = filterFlagsEnum.NameConversion;
+
+ for(; convertor->mName != NULL; ++convertor)
+ helper.addNamedValue(convertor->mName, convertor->mValue);
+
+ inStream.createProperty<TDataType, PxU32>(inPropertyName, semantic, PropertyType::Scalar, helper.getNamedValues());
+ helper.clearNamedValues();
+}
+
+template <typename TDataType, typename TConvertSrc, typename TConvertData>
+inline void definePropertyFlags(PvdDataStream& inStream, const char* inPropertyName)
+{
+ defineProperty<TDataType, TConvertSrc, TConvertData>(inStream, inPropertyName, "Bitflag");
+}
+template <typename TDataType, typename TConvertSrc, typename TConvertData>
+inline void definePropertyEnums(PvdDataStream& inStream, const char* inPropertyName)
+{
+ defineProperty<TDataType, TConvertSrc, TConvertData>(inStream, inPropertyName, "Enumeration Value");
+}
+
+static PX_FORCE_INLINE void registerPvdRaycast(PvdDataStream& inStream)
+{
+ inStream.createClass<PvdRaycast>();
+ definePropertyEnums<PvdRaycast, SceneQueryIDConvertor, NameValuePair>(inStream, "type");
+ inStream.createProperty<PvdRaycast, PxFilterData>("filterData");
+ definePropertyFlags<PvdRaycast, PxEnumTraits<physx::PxQueryFlag::Enum>, PxU32ToName>(inStream, "filterFlags");
+ inStream.createProperty<PvdRaycast, PxVec3>("origin");
+ inStream.createProperty<PvdRaycast, PxVec3>("unitDir");
+ inStream.createProperty<PvdRaycast, PxF32>("distance");
+ inStream.createProperty<PvdRaycast, String>("hits_arrayName");
+ inStream.createProperty<PvdRaycast, PxU32>("hits_baseIndex");
+ inStream.createProperty<PvdRaycast, PxU32>("hits_count");
+}
+
+static PX_FORCE_INLINE void registerPvdSweep(PvdDataStream& inStream)
+{
+ inStream.createClass<PvdSweep>();
+ definePropertyEnums<PvdSweep, SceneQueryIDConvertor, NameValuePair>(inStream, "type");
+ definePropertyFlags<PvdSweep, PxEnumTraits<physx::PxQueryFlag::Enum>, PxU32ToName>(inStream, "filterFlags");
+ inStream.createProperty<PvdSweep, PxVec3>("unitDir");
+ inStream.createProperty<PvdSweep, PxF32>("distance");
+ inStream.createProperty<PvdSweep, String>("geom_arrayName");
+ inStream.createProperty<PvdSweep, PxU32>("geom_baseIndex");
+ inStream.createProperty<PvdSweep, PxU32>("geom_count");
+ inStream.createProperty<PvdSweep, String>("pose_arrayName");
+ inStream.createProperty<PvdSweep, PxU32>("pose_baseIndex");
+ inStream.createProperty<PvdSweep, PxU32>("pose_count");
+ inStream.createProperty<PvdSweep, String>("filterData_arrayName");
+ inStream.createProperty<PvdSweep, PxU32>("filterData_baseIndex");
+ inStream.createProperty<PvdSweep, PxU32>("filterData_count");
+ inStream.createProperty<PvdSweep, String>("hits_arrayName");
+ inStream.createProperty<PvdSweep, PxU32>("hits_baseIndex");
+ inStream.createProperty<PvdSweep, PxU32>("hits_count");
+}
+
+static PX_FORCE_INLINE void registerPvdOverlap(PvdDataStream& inStream)
+{
+ inStream.createClass<PvdOverlap>();
+ definePropertyEnums<PvdOverlap, SceneQueryIDConvertor, NameValuePair>(inStream, "type");
+ inStream.createProperty<PvdOverlap, PxFilterData>("filterData");
+ definePropertyFlags<PvdOverlap, PxEnumTraits<physx::PxQueryFlag::Enum>, PxU32ToName>(inStream, "filterFlags");
+ inStream.createProperty<PvdOverlap, PxTransform>("pose");
+ inStream.createProperty<PvdOverlap, String>("geom_arrayName");
+ inStream.createProperty<PvdOverlap, PxU32>("geom_baseIndex");
+ inStream.createProperty<PvdOverlap, PxU32>("geom_count");
+ inStream.createProperty<PvdOverlap, String>("hits_arrayName");
+ inStream.createProperty<PvdOverlap, PxU32>("hits_baseIndex");
+ inStream.createProperty<PvdOverlap, PxU32>("hits_count");
+}
+
+static PX_FORCE_INLINE void registerPvdSqHit(PvdDataStream& inStream)
+{
+ inStream.createClass<PvdSqHit>();
+ inStream.createProperty<PvdSqHit, ObjectRef>("Shape");
+ inStream.createProperty<PvdSqHit, ObjectRef>("Actor");
+ inStream.createProperty<PvdSqHit, PxU32>("FaceIndex");
+ definePropertyFlags<PvdSqHit, PxEnumTraits<physx::PxHitFlag::Enum>, PxU32ToName>(inStream, "Flags");
+ inStream.createProperty<PvdSqHit, PxVec3>("Impact");
+ inStream.createProperty<PvdSqHit, PxVec3>("Normal");
+ inStream.createProperty<PvdSqHit, PxF32>("Distance");
+ inStream.createProperty<PvdSqHit, PxF32>("U");
+ inStream.createProperty<PvdSqHit, PxF32>("V");
+}
+
+void PvdMetaDataBinding::registerSDKProperties(PvdDataStream& inStream)
+{
+ if (inStream.isClassExist<PxPhysics>())
+ return;
+ // PxPhysics
+ {
+ inStream.createClass<PxPhysics>();
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<PxPhysics>());
+ helper.pushName("TolerancesScale");
+ visitAllPvdProperties<PxTolerancesScale>(definitionObj);
+ helper.popName();
+ inStream.createProperty<PxPhysics, ObjectRef>("Scenes", "children", PropertyType::Array);
+ inStream.createProperty<PxPhysics, ObjectRef>("SharedShapes", "children", PropertyType::Array);
+ inStream.createProperty<PxPhysics, ObjectRef>("Materials", "children", PropertyType::Array);
+ inStream.createProperty<PxPhysics, ObjectRef>("HeightFields", "children", PropertyType::Array);
+ inStream.createProperty<PxPhysics, ObjectRef>("ConvexMeshes", "children", PropertyType::Array);
+ inStream.createProperty<PxPhysics, ObjectRef>("TriangleMeshes", "children", PropertyType::Array);
+ inStream.createProperty<PxPhysics, ObjectRef>("ClothFabrics", "children", PropertyType::Array);
+ inStream.createProperty<PxPhysics, PxU32>("Version.Major");
+ inStream.createProperty<PxPhysics, PxU32>("Version.Minor");
+ inStream.createProperty<PxPhysics, PxU32>("Version.Bugfix");
+ inStream.createProperty<PxPhysics, String>("Version.Build");
+ definePropertyStruct<PxTolerancesScale, PxTolerancesScaleGeneratedValues, PxPhysics>(inStream, "TolerancesScale");
+ }
+ { // PxGeometry
+ inStream.createClass<PxGeometry>();
+ inStream.createProperty<PxGeometry, ObjectRef>("Shape", "parents", PropertyType::Scalar);
+ }
+ { // PxBoxGeometry
+ createClassDeriveAndDefineProperties<PxBoxGeometry, PxGeometry>(inStream);
+ definePropertyStruct<PxBoxGeometry, PxBoxGeometryGeneratedValues, PxBoxGeometry>(inStream);
+ }
+ { // PxSphereGeometry
+ createClassDeriveAndDefineProperties<PxSphereGeometry, PxGeometry>(inStream);
+ definePropertyStruct<PxSphereGeometry, PxSphereGeometryGeneratedValues, PxSphereGeometry>(inStream);
+ }
+ { // PxCapsuleGeometry
+ createClassDeriveAndDefineProperties<PxCapsuleGeometry, PxGeometry>(inStream);
+ definePropertyStruct<PxCapsuleGeometry, PxCapsuleGeometryGeneratedValues, PxCapsuleGeometry>(inStream);
+ }
+ { // PxPlaneGeometry
+ createClassDeriveAndDefineProperties<PxPlaneGeometry, PxGeometry>(inStream);
+ }
+ { // PxConvexMeshGeometry
+ createClassDeriveAndDefineProperties<PxConvexMeshGeometry, PxGeometry>(inStream);
+ definePropertyStruct<PxConvexMeshGeometry, PxConvexMeshGeometryGeneratedValues, PxConvexMeshGeometry>(inStream);
+ }
+ { // PxTriangleMeshGeometry
+ createClassDeriveAndDefineProperties<PxTriangleMeshGeometry, PxGeometry>(inStream);
+ definePropertyStruct<PxTriangleMeshGeometry, PxTriangleMeshGeometryGeneratedValues, PxTriangleMeshGeometry>(inStream);
+ }
+ { // PxHeightFieldGeometry
+ createClassDeriveAndDefineProperties<PxHeightFieldGeometry, PxGeometry>(inStream);
+ definePropertyStruct<PxHeightFieldGeometry, PxHeightFieldGeometryGeneratedValues, PxHeightFieldGeometry>(inStream);
+ }
+
+ // PxScene
+ {
+ // PT: TODO: why inline this for PvdContact but do PvdRaycast/etc in separate functions?
+ { // contact information
+ inStream.createClass<PvdContact>();
+ inStream.createProperty<PvdContact, PxVec3>("Point");
+ inStream.createProperty<PvdContact, PxVec3>("Axis");
+ inStream.createProperty<PvdContact, ObjectRef>("Shapes[0]");
+ inStream.createProperty<PvdContact, ObjectRef>("Shapes[1]");
+ inStream.createProperty<PvdContact, PxF32>("Separation");
+ inStream.createProperty<PvdContact, PxF32>("NormalForce");
+ inStream.createProperty<PvdContact, PxU32>("InternalFaceIndex[0]");
+ inStream.createProperty<PvdContact, PxU32>("InternalFaceIndex[1]");
+ inStream.createProperty<PvdContact, bool>("NormalForceValid");
+ }
+
+ registerPvdSqHit(inStream);
+ registerPvdRaycast(inStream);
+ registerPvdSweep(inStream);
+ registerPvdOverlap(inStream);
+
+ inStream.createClass<PxScene>();
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<PxScene>());
+ visitAllPvdProperties<PxSceneDesc>(definitionObj);
+ helper.pushName("SimulationStatistics");
+ visitAllPvdProperties<PxSimulationStatistics>(definitionObj);
+ helper.popName();
+ inStream.createProperty<PxScene, ObjectRef>("Physics", "parents", PropertyType::Scalar);
+ inStream.createProperty<PxScene, PxU32>("Timestamp");
+ inStream.createProperty<PxScene, PxReal>("SimulateElapsedTime");
+ definePropertyStruct<PxSceneDesc, PxSceneDescGeneratedValues, PxScene>(inStream);
+ definePropertyStruct<PxSimulationStatistics, PxSimulationStatisticsGeneratedValues, PxScene>(inStream, "SimulationStatistics");
+ inStream.createProperty<PxScene, PvdContact>("Contacts", "", PropertyType::Array);
+
+ inStream.createProperty<PxScene, PvdOverlap>("SceneQueries.Overlaps", "", PropertyType::Array);
+ inStream.createProperty<PxScene, PvdSweep>("SceneQueries.Sweeps", "", PropertyType::Array);
+ inStream.createProperty<PxScene, PvdSqHit>("SceneQueries.Hits", "", PropertyType::Array);
+ inStream.createProperty<PxScene, PvdRaycast>("SceneQueries.Raycasts", "", PropertyType::Array);
+ inStream.createProperty<PxScene, PxTransform>("SceneQueries.PoseList", "", PropertyType::Array);
+ inStream.createProperty<PxScene, PxFilterData>("SceneQueries.FilterDataList", "", PropertyType::Array);
+ inStream.createProperty<PxScene, ObjectRef>("SceneQueries.GeometryList", "", PropertyType::Array);
+
+ inStream.createProperty<PxScene, PvdOverlap>("BatchedQueries.Overlaps", "", PropertyType::Array);
+ inStream.createProperty<PxScene, PvdSweep>("BatchedQueries.Sweeps", "", PropertyType::Array);
+ inStream.createProperty<PxScene, PvdSqHit>("BatchedQueries.Hits", "", PropertyType::Array);
+ inStream.createProperty<PxScene, PvdRaycast>("BatchedQueries.Raycasts", "", PropertyType::Array);
+ inStream.createProperty<PxScene, PxTransform>("BatchedQueries.PoseList", "", PropertyType::Array);
+ inStream.createProperty<PxScene, PxFilterData>("BatchedQueries.FilterDataList", "", PropertyType::Array);
+ inStream.createProperty<PxScene, ObjectRef>("BatchedQueries.GeometryList", "", PropertyType::Array);
+
+ inStream.createProperty<PxScene, ObjectRef>("RigidStatics", "children", PropertyType::Array);
+ inStream.createProperty<PxScene, ObjectRef>("RigidDynamics", "children", PropertyType::Array);
+ inStream.createProperty<PxScene, ObjectRef>("Articulations", "children", PropertyType::Array);
+ inStream.createProperty<PxScene, ObjectRef>("ParticleSystems", "children", PropertyType::Array);
+ inStream.createProperty<PxScene, ObjectRef>("ParticleFluids", "children", PropertyType::Array);
+ inStream.createProperty<PxScene, ObjectRef>("Cloths", "children", PropertyType::Array);
+ inStream.createProperty<PxScene, ObjectRef>("Joints", "children", PropertyType::Array);
+ inStream.createProperty<PxScene, ObjectRef>("Aggregates", "children", PropertyType::Array);
+ }
+ // PxMaterial
+ {
+ createClassAndDefineProperties<PxMaterial>(inStream);
+ definePropertyStruct<PxMaterial, PxMaterialGeneratedValues, PxMaterial>(inStream);
+ inStream.createProperty<PxMaterial, ObjectRef>("Physics", "parents", PropertyType::Scalar);
+ }
+ // PxHeightField
+ {
+ {
+ inStream.createClass<PxHeightFieldSample>();
+ inStream.createProperty<PxHeightFieldSample, PxU16>("Height");
+ inStream.createProperty<PxHeightFieldSample, PxU8>("MaterialIndex[0]");
+ inStream.createProperty<PxHeightFieldSample, PxU8>("MaterialIndex[1]");
+ }
+
+ inStream.createClass<PxHeightField>();
+ // It is important the PVD fields match the RepX fields, so this has
+ // to be hand coded.
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<PxHeightField>());
+ visitAllPvdProperties<PxHeightFieldDesc>(definitionObj);
+ inStream.createProperty<PxHeightField, PxHeightFieldSample>("Samples", "", PropertyType::Array);
+ inStream.createProperty<PxHeightField, ObjectRef>("Physics", "parents", PropertyType::Scalar);
+ definePropertyStruct<PxHeightFieldDesc, PxHeightFieldDescGeneratedValues, PxHeightField>(inStream);
+ }
+ // PxConvexMesh
+ {
+ { // hull polygon data.
+ inStream.createClass<PvdHullPolygonData>();
+ inStream.createProperty<PvdHullPolygonData, PxU16>("NumVertices");
+ inStream.createProperty<PvdHullPolygonData, PxU16>("IndexBase");
+ }
+ inStream.createClass<PxConvexMesh>();
+ inStream.createProperty<PxConvexMesh, PxF32>("Mass");
+ inStream.createProperty<PxConvexMesh, PxMat33>("LocalInertia");
+ inStream.createProperty<PxConvexMesh, PxVec3>("LocalCenterOfMass");
+ inStream.createProperty<PxConvexMesh, PxVec3>("Points", "", PropertyType::Array);
+ inStream.createProperty<PxConvexMesh, PvdHullPolygonData>("HullPolygons", "", PropertyType::Array);
+ inStream.createProperty<PxConvexMesh, PxU8>("PolygonIndexes", "", PropertyType::Array);
+ inStream.createProperty<PxConvexMesh, ObjectRef>("Physics", "parents", PropertyType::Scalar);
+ }
+ // PxTriangleMesh
+ {
+ inStream.createClass<PxTriangleMesh>();
+ inStream.createProperty<PxTriangleMesh, PxVec3>("Points", "", PropertyType::Array);
+ inStream.createProperty<PxTriangleMesh, PxU32>("NbTriangles", "", PropertyType::Scalar);
+ inStream.createProperty<PxTriangleMesh, PxU32>("Triangles", "", PropertyType::Array);
+ inStream.createProperty<PxTriangleMesh, PxU16>("MaterialIndices", "", PropertyType::Array);
+ inStream.createProperty<PxTriangleMesh, ObjectRef>("Physics", "parents", PropertyType::Scalar);
+ }
+ { // PxShape
+ createClassAndDefineProperties<PxShape>(inStream);
+ definePropertyStruct<PxShape, PxShapeGeneratedValues, PxShape>(inStream);
+ inStream.createProperty<PxShape, ObjectRef>("Geometry", "children");
+ inStream.createProperty<PxShape, ObjectRef>("Materials", "children", PropertyType::Array);
+ inStream.createProperty<PxShape, ObjectRef>("Actor", "parents");
+ }
+ // PxActor
+ {
+ createClassAndDefineProperties<PxActor>(inStream);
+ inStream.createProperty<PxActor, ObjectRef>("Scene", "parents");
+ }
+ // PxRigidActor
+ {
+ createClassDeriveAndDefineProperties<PxRigidActor, PxActor>(inStream);
+ inStream.createProperty<PxRigidActor, ObjectRef>("Shapes", "children", PropertyType::Array);
+ inStream.createProperty<PxRigidActor, ObjectRef>("Joints", "children", PropertyType::Array);
+ }
+ // PxRigidStatic
+ {
+ createClassDeriveAndDefineProperties<PxRigidStatic, PxRigidActor>(inStream);
+ definePropertyStruct<PxRigidStatic, PxRigidStaticGeneratedValues, PxRigidStatic>(inStream);
+ }
+ { // PxRigidBody
+ createClassDeriveAndDefineProperties<PxRigidBody, PxRigidActor>(inStream);
+ }
+ // PxRigidDynamic
+ {
+ createClassDeriveAndDefineProperties<PxRigidDynamic, PxRigidBody>(inStream);
+ // If anyone adds a 'getKinematicTarget' to PxRigidDynamic you can remove the line
+ // below (after the code generator has run).
+ inStream.createProperty<PxRigidDynamic, PxTransform>("KinematicTarget");
+ definePropertyStruct<PxRigidDynamic, PxRigidDynamicGeneratedValues, PxRigidDynamic>(inStream);
+ // Manually define the update struct.
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ /*struct PxRigidDynamicUpdateBlock
+ {
+ Transform GlobalPose;
+ Float3 LinearVelocity;
+ Float3 AngularVelocity;
+ PxU8 IsSleeping;
+ PxU8 padding[3];
+ };
+ */
+ helper.pushName("GlobalPose");
+ helper.addPropertyMessageArg<PxTransform>(PX_OFFSET_OF_RT(PxRigidDynamicUpdateBlock, GlobalPose));
+ helper.popName();
+ helper.pushName("LinearVelocity");
+ helper.addPropertyMessageArg<PxVec3>(PX_OFFSET_OF_RT(PxRigidDynamicUpdateBlock, LinearVelocity));
+ helper.popName();
+ helper.pushName("AngularVelocity");
+ helper.addPropertyMessageArg<PxVec3>(PX_OFFSET_OF_RT(PxRigidDynamicUpdateBlock, AngularVelocity));
+ helper.popName();
+ helper.pushName("IsSleeping");
+ helper.addPropertyMessageArg<bool>(PX_OFFSET_OF_RT(PxRigidDynamicUpdateBlock, IsSleeping));
+ helper.popName();
+ helper.addPropertyMessage<PxRigidDynamic, PxRigidDynamicUpdateBlock>();
+ }
+ { // PxArticulation
+ createClassAndDefineProperties<PxArticulation>(inStream);
+ inStream.createProperty<PxArticulation, ObjectRef>("Scene", "parents");
+ inStream.createProperty<PxArticulation, ObjectRef>("Links", "children", PropertyType::Array);
+ definePropertyStruct<PxArticulation, PxArticulationGeneratedValues, PxArticulation>(inStream);
+ }
+ { // PxArticulationLink
+ createClassDeriveAndDefineProperties<PxArticulationLink, PxRigidBody>(inStream);
+ inStream.createProperty<PxArticulationLink, ObjectRef>("Parent", "parents");
+ inStream.createProperty<PxArticulationLink, ObjectRef>("Links", "children", PropertyType::Array);
+ inStream.createProperty<PxArticulationLink, ObjectRef>("InboundJoint", "children");
+ definePropertyStruct<PxArticulationLink, PxArticulationLinkGeneratedValues, PxArticulationLink>(inStream);
+
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ /*struct PxArticulationLinkUpdateBlock
+ {
+ Transform GlobalPose;
+ Float3 LinearVelocity;
+ Float3 AngularVelocity;
+ };
+ */
+ helper.pushName("GlobalPose");
+ helper.addPropertyMessageArg<PxTransform>(PX_OFFSET_OF(PxArticulationLinkUpdateBlock, GlobalPose));
+ helper.popName();
+ helper.pushName("LinearVelocity");
+ helper.addPropertyMessageArg<PxVec3>(PX_OFFSET_OF(PxArticulationLinkUpdateBlock, LinearVelocity));
+ helper.popName();
+ helper.pushName("AngularVelocity");
+ helper.addPropertyMessageArg<PxVec3>(PX_OFFSET_OF(PxArticulationLinkUpdateBlock, AngularVelocity));
+ helper.popName();
+ helper.addPropertyMessage<PxArticulationLink, PxArticulationLinkUpdateBlock>();
+ }
+ { // PxArticulationJoint
+ createClassAndDefineProperties<PxArticulationJoint>(inStream);
+ inStream.createProperty<PxArticulationJoint, ObjectRef>("Link", "parents");
+ definePropertyStruct<PxArticulationJoint, PxArticulationJointGeneratedValues, PxArticulationJoint>(inStream);
+ }
+ { // PxConstraint
+ createClassAndDefineProperties<PxConstraint>(inStream);
+ definePropertyStruct<PxConstraint, PxConstraintGeneratedValues, PxConstraint>(inStream);
+ }
+#if PX_USE_PARTICLE_SYSTEM_API
+ { // PxParticleBase
+ createClassDeriveAndDefineProperties<PxParticleBase, PxActor>(inStream);
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<PxParticleBase>());
+ visitParticleSystemBufferProperties(makePvdPropertyFilter(definitionObj));
+ }
+ { // PxParticleSystem
+ createClassDeriveAndDefineProperties<PxParticleSystem, PxParticleBase>(inStream);
+ inStream.createProperty<PxParticleSystem, PxU32>("NbParticles");
+ inStream.createProperty<PxParticleSystem, PxU32>("ValidParticleRange");
+ inStream.createProperty<PxParticleSystem, PxU32>("ValidParticleBitmap", "", PropertyType::Array);
+ definePropertyStruct<PxParticleSystem, PxParticleSystemGeneratedValues, PxParticleSystem>(inStream);
+ }
+ { // PxParticleFluid
+ createClassDeriveAndDefineProperties<PxParticleFluid, PxParticleBase>(inStream);
+ inStream.createProperty<PxParticleFluid, PxU32>("NbParticles");
+ inStream.createProperty<PxParticleFluid, PxU32>("ValidParticleRange");
+ inStream.createProperty<PxParticleFluid, PxU32>("ValidParticleBitmap", "", PropertyType::Array);
+ PvdPropertyDefinitionHelper& helper(inStream.getPropertyDefinitionHelper());
+ PvdClassInfoDefine definitionObj(helper, getPvdNamespacedNameForType<PxParticleFluid>());
+ visitParticleFluidBufferProperties(makePvdPropertyFilter(definitionObj));
+ definePropertyStruct<PxParticleFluid, PxParticleFluidGeneratedValues, PxParticleFluid>(inStream);
+ }
+#endif
+#if PX_USE_CLOTH_API
+ { // PxClothFabricPhase
+ createClassAndDefineProperties<PxClothFabricPhase>(inStream);
+ }
+ { // PxClothFabric
+ createClassAndDefineProperties<PxClothFabric>(inStream);
+ definePropertyStruct<PxClothFabric, PxClothFabricGeneratedValues, PxClothFabric>(inStream);
+ inStream.createProperty<PxClothFabric, ObjectRef>("Physics", "parents");
+ inStream.createProperty<PxClothFabric, ObjectRef>("Cloths", "children", PropertyType::Array);
+ inStream.createProperty<PxClothFabric, PxClothFabricPhase>("Phases", "", PropertyType::Array);
+ }
+ { // PxCloth
+ { // PxClothParticle
+ createClassAndDefineProperties<PxClothParticle>(inStream);
+ }
+ { // PxClothStretchConfig
+ createClassAndDefineProperties<PxClothStretchConfig>(inStream);
+ }
+ { // PxClothTetherConstraintConfig
+ createClassAndDefineProperties<PxClothTetherConfig>(inStream);
+ }
+ { // PvdPositionAndRadius
+ inStream.createClass<PvdPositionAndRadius>();
+ inStream.createProperty<PvdPositionAndRadius, PxVec3>("Position");
+ inStream.createProperty<PvdPositionAndRadius, PxF32>("Radius");
+ }
+ createClassDeriveAndDefineProperties<PxCloth, PxActor>(inStream);
+ definePropertyStruct<PxCloth, PxClothGeneratedValues, PxCloth>(inStream);
+ inStream.createProperty<PxCloth, ObjectRef>("Fabric");
+ inStream.createProperty<PxCloth, PxClothParticle>("ParticleBuffer", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PxClothParticle>("ParticleAccelerations", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PvdPositionAndRadius>("MotionConstraints", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PvdPositionAndRadius>("CollisionSpheres", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PvdPositionAndRadius>("SeparationConstraints", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PxU32>("CollisionSpherePairs", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PvdPositionAndRadius>("CollisionPlanes", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PxU32>("CollisionConvexMasks", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PxVec3>("CollisionTriangles", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PxU32>("VirtualParticles", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PxVec3>("VirtualParticleWeights", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PxU32>("SelfCollisionIndices", "", PropertyType::Array);
+ inStream.createProperty<PxCloth, PxVec4>("RestPositions", "", PropertyType::Array);
+ }
+#endif
+ {
+ // PxAggregate
+ createClassAndDefineProperties<PxAggregate>(inStream);
+ inStream.createProperty<PxAggregate, ObjectRef>("Scene", "parents");
+ definePropertyStruct<PxAggregate, PxAggregateGeneratedValues, PxAggregate>(inStream);
+ inStream.createProperty<PxAggregate, ObjectRef>("Actors", "children", PropertyType::Array);
+ inStream.createProperty<PxAggregate, ObjectRef>("Articulations", "children", PropertyType::Array);
+ }
+}
+
+template <typename TClassType, typename TValueType, typename TDataType>
+static void doSendAllProperties(PvdDataStream& inStream, const TDataType* inDatatype, const void* instanceId)
+{
+ TValueType theValues(inDatatype);
+ inStream.setPropertyMessage(instanceId, theValues);
+}
+
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxPhysics& inPhysics)
+{
+ PxTolerancesScale theScale(inPhysics.getTolerancesScale());
+ doSendAllProperties<PxPhysics, PxTolerancesScaleGeneratedValues>(inStream, &theScale, &inPhysics);
+ inStream.setPropertyValue(&inPhysics, "Version.Major", PxU32(PX_PHYSICS_VERSION_MAJOR));
+ inStream.setPropertyValue(&inPhysics, "Version.Minor", PxU32(PX_PHYSICS_VERSION_MINOR));
+ inStream.setPropertyValue(&inPhysics, "Version.Bugfix", PxU32(PX_PHYSICS_VERSION_BUGFIX));
+
+#if PX_CHECKED
+#if defined(NDEBUG)
+ // This is a checked build
+ String buildType = "Checked";
+#elif defined(_DEBUG)
+ // This is a debug build
+ String buildType = "Debug";
+#endif
+#elif PX_PROFILE
+ String buildType = "Profile";
+#elif defined(NDEBUG)
+ // This is a release build
+ String buildType = "Release";
+#endif
+ inStream.setPropertyValue(&inPhysics, "Version.Build", buildType);
+}
+
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxScene& inScene)
+{
+ PxPhysics& physics(const_cast<PxScene&>(inScene).getPhysics());
+ PxTolerancesScale theScale;
+ PxSceneDesc theDesc(theScale);
+
+ {
+ theDesc.gravity = inScene.getGravity();
+
+ theDesc.simulationEventCallback = inScene.getSimulationEventCallback(PX_DEFAULT_CLIENT);
+ theDesc.contactModifyCallback = inScene.getContactModifyCallback();
+ theDesc.ccdContactModifyCallback = inScene.getCCDContactModifyCallback();
+
+ theDesc.filterShaderData = inScene.getFilterShaderData();
+ theDesc.filterShaderDataSize = inScene.getFilterShaderDataSize();
+ theDesc.filterShader = inScene.getFilterShader();
+ theDesc.filterCallback = inScene.getFilterCallback();
+
+ theDesc.broadPhaseType = inScene.getBroadPhaseType();
+ theDesc.broadPhaseCallback = inScene.getBroadPhaseCallback();
+
+ theDesc.limits = inScene.getLimits();
+
+ theDesc.frictionType = inScene.getFrictionType();
+
+ theDesc.bounceThresholdVelocity = inScene.getBounceThresholdVelocity();
+
+ theDesc.frictionOffsetThreshold = inScene.getFrictionOffsetThreshold();
+
+ theDesc.flags = inScene.getFlags();
+
+ theDesc.cpuDispatcher = inScene.getCpuDispatcher();
+ theDesc.gpuDispatcher = inScene.getGpuDispatcher();
+
+ theDesc.staticStructure = inScene.getStaticStructure();
+ theDesc.dynamicStructure = inScene.getDynamicStructure();
+ theDesc.dynamicTreeRebuildRateHint = inScene.getDynamicTreeRebuildRateHint();
+
+ theDesc.userData = inScene.userData;
+
+ theDesc.solverBatchSize = inScene.getSolverBatchSize();
+
+ // theDesc.nbContactDataBlocks = inScene.getNbContactDataBlocksUsed();
+ // theDesc.maxNbContactDataBlocks = inScene.getMaxNbContactDataBlocksUsed();
+
+ theDesc.contactReportStreamBufferSize = inScene.getContactReportStreamBufferSize();
+
+ theDesc.ccdMaxPasses = inScene.getCCDMaxPasses();
+
+ // theDesc.simulationOrder = inScene.getSimulationOrder();
+
+ theDesc.wakeCounterResetValue = inScene.getWakeCounterResetValue();
+ }
+
+ PxSceneDescGeneratedValues theValues(&theDesc);
+ inStream.setPropertyMessage(&inScene, theValues);
+ // Create parent/child relationship.
+ inStream.setPropertyValue(&inScene, "Physics", reinterpret_cast<const void*>(&physics));
+ inStream.pushBackObjectRef(&physics, "Scenes", &inScene);
+}
+
+void PvdMetaDataBinding::sendBeginFrame(PvdDataStream& inStream, const PxScene* inScene, PxReal simulateElapsedTime)
+{
+ inStream.beginSection(inScene, "frame");
+ inStream.setPropertyValue(inScene, "Timestamp", inScene->getTimestamp());
+ inStream.setPropertyValue(inScene, "SimulateElapsedTime", simulateElapsedTime);
+}
+
+template <typename TDataType>
+struct NullConverter
+{
+ void operator()(TDataType& data, const TDataType& src)
+ {
+ data = src;
+ }
+};
+
+template <typename TTargetType, PxU32 T_NUM_ITEMS, typename TSourceType = TTargetType,
+ typename Converter = NullConverter<TTargetType> >
+class ScopedPropertyValueSender
+{
+ TTargetType mStack[T_NUM_ITEMS];
+ TTargetType* mCur;
+ const TTargetType* mEnd;
+ PvdDataStream& mStream;
+
+ public:
+ ScopedPropertyValueSender(PvdDataStream& inStream, const void* inObj, String name)
+ : mCur(mStack), mEnd(&mStack[T_NUM_ITEMS]), mStream(inStream)
+ {
+ mStream.beginSetPropertyValue(inObj, name, getPvdNamespacedNameForType<TTargetType>());
+ }
+
+ ~ScopedPropertyValueSender()
+ {
+ if(mStack != mCur)
+ {
+ PxU32 size = sizeof(TTargetType) * PxU32(mCur - mStack);
+ mStream.appendPropertyValueData(DataRef<const PxU8>(reinterpret_cast<PxU8*>(mStack), size));
+ }
+ mStream.endSetPropertyValue();
+ }
+
+ void append(const TSourceType& data)
+ {
+ Converter()(*mCur, data);
+ if(mCur < mEnd - 1)
+ ++mCur;
+ else
+ {
+ mStream.appendPropertyValueData(DataRef<const PxU8>(reinterpret_cast<PxU8*>(mStack), sizeof mStack));
+ mCur = mStack;
+ }
+ }
+
+ private:
+ ScopedPropertyValueSender& operator=(const ScopedPropertyValueSender&);
+};
+
+void PvdMetaDataBinding::sendContacts(PvdDataStream& inStream, const PxScene& inScene)
+{
+ inStream.setPropertyValue(&inScene, "Contacts", DataRef<const PxU8>(), getPvdNamespacedNameForType<PvdContact>());
+}
+
+struct PvdContactConverter
+{
+ void operator()(PvdContact& data, const Sc::Contact& src)
+ {
+ data.point = src.point;
+ data.axis = src.normal;
+ data.shape0 = src.shape0;
+ data.shape1 = src.shape1;
+ data.separation = src.separation;
+ data.normalForce = src.normalForce;
+ data.internalFaceIndex0 = src.faceIndex0;
+ data.internalFaceIndex1 = src.faceIndex1;
+ data.normalForceAvailable = src.normalForceAvailable;
+ }
+};
+
+void PvdMetaDataBinding::sendContacts(PvdDataStream& inStream, const PxScene& inScene, Array<Contact>& inContacts)
+{
+ ScopedPropertyValueSender<PvdContact, 32, Sc::Contact, PvdContactConverter> sender(inStream, &inScene, "Contacts");
+
+ for(PxU32 i = 0; i < inContacts.size(); i++)
+ {
+ sender.append(inContacts[i]);
+ }
+}
+
+void PvdMetaDataBinding::sendStats(PvdDataStream& inStream, const PxScene* inScene, void* triMeshCacheStats)
+{
+ PxSimulationStatistics theStats;
+ inScene->getSimulationStatistics(theStats);
+
+ PX_UNUSED(triMeshCacheStats);
+#if PX_SUPPORT_GPU_PHYSX
+ if(triMeshCacheStats)
+ {
+ // gpu triangle mesh cache stats
+ PxTriangleMeshCacheStatistics* tmp = static_cast<PxTriangleMeshCacheStatistics*>(triMeshCacheStats);
+ theStats.particlesGpuMeshCacheSize = tmp->bytesTotal;
+ theStats.particlesGpuMeshCacheUsed = tmp->bytesUsed;
+ theStats.particlesGpuMeshCacheHitrate = tmp->percentageHitrate;
+ }
+#endif
+
+ PxSimulationStatisticsGeneratedValues values(&theStats);
+ inStream.setPropertyMessage(inScene, values);
+}
+
+void PvdMetaDataBinding::sendEndFrame(PvdDataStream& inStream, const PxScene* inScene)
+{
+ //flush other client
+ inStream.endSection(inScene, "frame");
+}
+
+template <typename TDataType>
+void addPhysicsGroupProperty(PvdDataStream& inStream, const char* groupName, const TDataType& inData, const PxPhysics& ownerPhysics)
+{
+ inStream.setPropertyValue(&inData, "Physics", reinterpret_cast<const void*>(&ownerPhysics));
+ inStream.pushBackObjectRef(&ownerPhysics, groupName, &inData);
+ // Buffer type objects *have* to be flushed directly out once created else scene creation doesn't work.
+}
+
+template <typename TDataType>
+void removePhysicsGroupProperty(PvdDataStream& inStream, const char* groupName, const TDataType& inData, const PxPhysics& ownerPhysics)
+{
+ inStream.removeObjectRef(&ownerPhysics, groupName, &inData);
+ inStream.destroyInstance(&inData);
+}
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxMaterial& inMaterial, const PxPhysics& ownerPhysics)
+{
+ inStream.createInstance(&inMaterial);
+ sendAllProperties(inStream, inMaterial);
+ addPhysicsGroupProperty(inStream, "Materials", inMaterial, ownerPhysics);
+}
+
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxMaterial& inMaterial)
+{
+ PxMaterialGeneratedValues values(&inMaterial);
+ inStream.setPropertyMessage(&inMaterial, values);
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxMaterial& inMaterial, const PxPhysics& ownerPhysics)
+{
+ removePhysicsGroupProperty(inStream, "Materials", inMaterial, ownerPhysics);
+}
+
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxHeightField& inData)
+{
+ PxHeightFieldDesc theDesc;
+ // Save the height field to desc.
+ theDesc.nbRows = inData.getNbRows();
+ theDesc.nbColumns = inData.getNbColumns();
+ theDesc.format = inData.getFormat();
+ theDesc.samples.stride = inData.getSampleStride();
+ theDesc.samples.data = NULL;
+ theDesc.thickness = inData.getThickness();
+ theDesc.convexEdgeThreshold = inData.getConvexEdgeThreshold();
+ theDesc.flags = inData.getFlags();
+
+ PxU32 theCellCount = inData.getNbRows() * inData.getNbColumns();
+ PxU32 theSampleStride = sizeof(PxHeightFieldSample);
+ PxU32 theSampleBufSize = theCellCount * theSampleStride;
+ mBindingData->mTempU8Array.resize(theSampleBufSize);
+ PxHeightFieldSample* theSamples = reinterpret_cast<PxHeightFieldSample*>(mBindingData->mTempU8Array.begin());
+ inData.saveCells(theSamples, theSampleBufSize);
+ theDesc.samples.data = theSamples;
+ PxHeightFieldDescGeneratedValues values(&theDesc);
+ inStream.setPropertyMessage(&inData, values);
+ PxHeightFieldSample* theSampleData = reinterpret_cast<PxHeightFieldSample*>(mBindingData->mTempU8Array.begin());
+ inStream.setPropertyValue(&inData, "Samples", theSampleData, theCellCount);
+}
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxHeightField& inData, const PxPhysics& ownerPhysics)
+{
+ inStream.createInstance(&inData);
+ sendAllProperties(inStream, inData);
+ addPhysicsGroupProperty(inStream, "HeightFields", inData, ownerPhysics);
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxHeightField& inData, const PxPhysics& ownerPhysics)
+{
+ removePhysicsGroupProperty(inStream, "HeightFields", inData, ownerPhysics);
+}
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxConvexMesh& inData, const PxPhysics& ownerPhysics)
+{
+ inStream.createInstance(&inData);
+ PxReal mass;
+ PxMat33 localInertia;
+ PxVec3 localCom;
+ inData.getMassInformation(mass, reinterpret_cast<PxMat33&>(localInertia), localCom);
+ inStream.setPropertyValue(&inData, "Mass", mass);
+ inStream.setPropertyValue(&inData, "LocalInertia", localInertia);
+ inStream.setPropertyValue(&inData, "LocalCenterOfMass", localCom);
+
+ // update arrays:
+ // vertex Array:
+ {
+ const PxVec3* vertexPtr = inData.getVertices();
+ const PxU32 numVertices = inData.getNbVertices();
+ inStream.setPropertyValue(&inData, "Points", vertexPtr, numVertices);
+ }
+
+ // HullPolyArray:
+ PxU16 maxIndices = 0;
+ {
+
+ PxU32 numPolygons = inData.getNbPolygons();
+ PvdHullPolygonData* tempData = mBindingData->allocateTemp<PvdHullPolygonData>(numPolygons);
+ // Get the polygon data stripping the plane equations
+ for(PxU32 index = 0; index < numPolygons; index++)
+ {
+ PxHullPolygon curOut;
+ inData.getPolygonData(index, curOut);
+ maxIndices = PxMax(maxIndices, PxU16(curOut.mIndexBase + curOut.mNbVerts));
+ tempData[index].mIndexBase = curOut.mIndexBase;
+ tempData[index].mNumVertices = curOut.mNbVerts;
+ }
+ inStream.setPropertyValue(&inData, "HullPolygons", tempData, numPolygons);
+ }
+
+ // poly index Array:
+ {
+ const PxU8* indices = inData.getIndexBuffer();
+ inStream.setPropertyValue(&inData, "PolygonIndexes", indices, maxIndices);
+ }
+ addPhysicsGroupProperty(inStream, "ConvexMeshes", inData, ownerPhysics);
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxConvexMesh& inData, const PxPhysics& ownerPhysics)
+{
+ removePhysicsGroupProperty(inStream, "ConvexMeshes", inData, ownerPhysics);
+}
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxTriangleMesh& inData, const PxPhysics& ownerPhysics)
+{
+ inStream.createInstance(&inData);
+ bool hasMatIndex = inData.getTriangleMaterialIndex(0) != 0xffff;
+ // update arrays:
+ // vertex Array:
+ {
+ const PxVec3* vertexPtr = inData.getVertices();
+ const PxU32 numVertices = inData.getNbVertices();
+ inStream.setPropertyValue(&inData, "Points", vertexPtr, numVertices);
+ }
+
+ // index Array:
+ {
+ const bool has16BitIndices = inData.getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES ? true : false;
+ const PxU32 numTriangles = inData.getNbTriangles();
+
+ inStream.setPropertyValue(&inData, "NbTriangles", numTriangles);
+
+ const PxU32 numIndexes = numTriangles * 3;
+ const PxU8* trianglePtr = reinterpret_cast<const PxU8*>(inData.getTriangles());
+ // We declared this type as a 32 bit integer above.
+ // PVD will automatically unsigned-extend data that is smaller than the target type.
+ if(has16BitIndices)
+ inStream.setPropertyValue(&inData, "Triangles", reinterpret_cast<const PxU16*>(trianglePtr), numIndexes);
+ else
+ inStream.setPropertyValue(&inData, "Triangles", reinterpret_cast<const PxU32*>(trianglePtr), numIndexes);
+ }
+
+ // material Array:
+ if(hasMatIndex)
+ {
+ PxU32 numMaterials = inData.getNbTriangles();
+ PxU16* matIndexData = mBindingData->allocateTemp<PxU16>(numMaterials);
+ for(PxU32 m = 0; m < numMaterials; m++)
+ matIndexData[m] = inData.getTriangleMaterialIndex(m);
+ inStream.setPropertyValue(&inData, "MaterialIndices", matIndexData, numMaterials);
+ }
+ addPhysicsGroupProperty(inStream, "TriangleMeshes", inData, ownerPhysics);
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxTriangleMesh& inData, const PxPhysics& ownerPhysics)
+{
+ removePhysicsGroupProperty(inStream, "TriangleMeshes", inData, ownerPhysics);
+}
+
+template <typename TDataType>
+void PvdMetaDataBinding::registrarPhysicsObject(PvdDataStream&, const TDataType&, PsPvd*)
+{
+}
+
+template <>
+void PvdMetaDataBinding::registrarPhysicsObject<PxConvexMeshGeometry>(PvdDataStream& inStream, const PxConvexMeshGeometry& geom, PsPvd* pvd)
+{
+ if(pvd->registerObject(geom.convexMesh))
+ createInstance(inStream, *geom.convexMesh, PxGetPhysics());
+}
+
+template <>
+void PvdMetaDataBinding::registrarPhysicsObject<PxTriangleMeshGeometry>(PvdDataStream& inStream, const PxTriangleMeshGeometry& geom, PsPvd* pvd)
+{
+ if(pvd->registerObject(geom.triangleMesh))
+ createInstance(inStream, *geom.triangleMesh, PxGetPhysics());
+}
+
+template <>
+void PvdMetaDataBinding::registrarPhysicsObject<PxHeightFieldGeometry>(PvdDataStream& inStream, const PxHeightFieldGeometry& geom, PsPvd* pvd)
+{
+ if(pvd->registerObject(geom.heightField))
+ createInstance(inStream, *geom.heightField, PxGetPhysics());
+}
+
+template <typename TGeneratedValuesType, typename TGeomType>
+void sendGeometry(PvdMetaDataBinding& metaBind, PvdDataStream& inStream, const PxShape& inShape, const TGeomType& geom, PsPvd* pvd)
+{
+ const void* geomInst = (reinterpret_cast<const PxU8*>(&inShape)) + 4;
+ inStream.createInstance(getPvdNamespacedNameForType<TGeomType>(), geomInst);
+ metaBind.registrarPhysicsObject<TGeomType>(inStream, geom, pvd);
+ TGeneratedValuesType values(&geom);
+ inStream.setPropertyMessage(geomInst, values);
+ inStream.setPropertyValue(&inShape, "Geometry", geomInst);
+ inStream.setPropertyValue(geomInst, "Shape", reinterpret_cast<const void*>(&inShape));
+}
+
+void setGeometry(PvdMetaDataBinding& metaBind, PvdDataStream& inStream, const PxShape& inObj, PsPvd* pvd)
+{
+ switch(inObj.getGeometryType())
+ {
+#define SEND_PVD_GEOM_TYPE(enumType, geomType, valueType) \
+ case PxGeometryType::enumType: \
+ { \
+ Px##geomType geom; \
+ inObj.get##geomType(geom); \
+ sendGeometry<valueType>(metaBind, inStream, inObj, geom, pvd); \
+ } \
+ break;
+ SEND_PVD_GEOM_TYPE(eSPHERE, SphereGeometry, PxSphereGeometryGeneratedValues);
+ // Plane geometries don't have any properties, so this avoids using a property
+ // struct for them.
+ case PxGeometryType::ePLANE:
+ {
+ PxPlaneGeometry geom;
+ inObj.getPlaneGeometry(geom);
+ const void* geomInst = (reinterpret_cast<const PxU8*>(&inObj)) + 4;
+ inStream.createInstance(getPvdNamespacedNameForType<PxPlaneGeometry>(), geomInst);
+ inStream.setPropertyValue(&inObj, "Geometry", geomInst);
+ inStream.setPropertyValue(geomInst, "Shape", reinterpret_cast<const void*>(&inObj));
+ }
+ break;
+ SEND_PVD_GEOM_TYPE(eCAPSULE, CapsuleGeometry, PxCapsuleGeometryGeneratedValues);
+ SEND_PVD_GEOM_TYPE(eBOX, BoxGeometry, PxBoxGeometryGeneratedValues);
+ SEND_PVD_GEOM_TYPE(eCONVEXMESH, ConvexMeshGeometry, PxConvexMeshGeometryGeneratedValues);
+ SEND_PVD_GEOM_TYPE(eTRIANGLEMESH, TriangleMeshGeometry, PxTriangleMeshGeometryGeneratedValues);
+ SEND_PVD_GEOM_TYPE(eHEIGHTFIELD, HeightFieldGeometry, PxHeightFieldGeometryGeneratedValues);
+#undef SEND_PVD_GEOM_TYPE
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ PX_ASSERT(false);
+ break;
+ }
+}
+
+void setMaterials(PvdMetaDataBinding& metaBing, PvdDataStream& inStream, const PxShape& inObj, PsPvd* pvd, PvdMetaDataBindingData* mBindingData)
+{
+ PxU32 numMaterials = inObj.getNbMaterials();
+ PxMaterial** materialPtr = mBindingData->allocateTemp<PxMaterial*>(numMaterials);
+ inObj.getMaterials(materialPtr, numMaterials);
+ for(PxU32 idx = 0; idx < numMaterials; ++idx)
+ {
+ if(pvd->registerObject(materialPtr[idx]))
+ metaBing.createInstance(inStream, *materialPtr[idx], PxGetPhysics());
+ inStream.pushBackObjectRef(&inObj, "Materials", materialPtr[idx]);
+ }
+}
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxShape& inObj, const PxRigidActor& owner, PsPvd* pvd)
+{
+ if(!inStream.isInstanceValid(&owner))
+ return;
+
+ const OwnerActorsMap::Entry* entry = mBindingData->mOwnerActorsMap.find(&inObj);
+ if(entry != NULL)
+ {
+ if(!mBindingData->mOwnerActorsMap[&inObj]->contains(&owner))
+ mBindingData->mOwnerActorsMap[&inObj]->insert(&owner);
+ }
+ else
+ {
+ OwnerActorsValueType* data = reinterpret_cast<OwnerActorsValueType*>(
+ PX_ALLOC(sizeof(OwnerActorsValueType), "mOwnerActorsMapValue")); //( 1 );
+ OwnerActorsValueType* actors = PX_PLACEMENT_NEW(data, OwnerActorsValueType);
+ actors->insert(&owner);
+
+ mBindingData->mOwnerActorsMap.insert(&inObj, actors);
+ }
+
+ if(inStream.isInstanceValid(&inObj))
+ {
+ inStream.pushBackObjectRef(&owner, "Shapes", &inObj);
+ return;
+ }
+
+ inStream.createInstance(&inObj);
+ inStream.pushBackObjectRef(&owner, "Shapes", &inObj);
+ inStream.setPropertyValue(&inObj, "Actor", reinterpret_cast<const void*>(&owner));
+ sendAllProperties(inStream, inObj);
+ setGeometry(*this, inStream, inObj, pvd);
+ setMaterials(*this, inStream, inObj, pvd, mBindingData);
+ if(!inObj.isExclusive())
+ inStream.pushBackObjectRef(&owner.getScene()->getPhysics(), "SharedShapes", &inObj);
+}
+
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxShape& inObj)
+{
+ PxShapeGeneratedValues values(&inObj);
+ inStream.setPropertyMessage(&inObj, values);
+}
+
+void PvdMetaDataBinding::releaseAndRecreateGeometry(PvdDataStream& inStream, const PxShape& inObj, PxPhysics& /*ownerPhysics*/, PsPvd* pvd)
+{
+ const void* geomInst = (reinterpret_cast<const PxU8*>(&inObj)) + 4;
+ inStream.destroyInstance(geomInst);
+ // Quick fix for HF modify, PxConvexMesh and PxTriangleMesh need recook, they should always be new if modified
+ if(inObj.getGeometryType() == PxGeometryType::eHEIGHTFIELD)
+ {
+ PxHeightFieldGeometry hfGeom;
+ inObj.getHeightFieldGeometry(hfGeom);
+ if(inStream.isInstanceValid(hfGeom.heightField))
+ sendAllProperties(inStream, *hfGeom.heightField);
+ }
+
+ setGeometry(*this, inStream, inObj, pvd);
+
+ // Need update actor cause PVD takes actor-shape as a pair.
+ {
+ PxRigidActor* actor = inObj.getActor();
+ if(actor != NULL)
+ {
+
+ if(const PxRigidStatic* rgS = actor->is<PxRigidStatic>())
+ sendAllProperties(inStream, *rgS);
+ else if(const PxRigidDynamic* rgD = actor->is<PxRigidDynamic>())
+ sendAllProperties(inStream, *rgD);
+ }
+ }
+}
+
+void PvdMetaDataBinding::updateMaterials(PvdDataStream& inStream, const PxShape& inObj, PsPvd* pvd)
+{
+ // Clear the shape's materials array.
+ inStream.setPropertyValue(&inObj, "Materials", DataRef<const PxU8>(), getPvdNamespacedNameForType<ObjectRef>());
+ setMaterials(*this, inStream, inObj, pvd, mBindingData);
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxShape& inObj, const PxRigidActor& owner)
+{
+ if(inStream.isInstanceValid(&inObj))
+ {
+ inStream.removeObjectRef(&owner, "Shapes", &inObj);
+
+ bool bDestroy = true;
+ const OwnerActorsMap::Entry* entry0 = mBindingData->mOwnerActorsMap.find(&inObj);
+ if(entry0 != NULL)
+ {
+ entry0->second->erase(&owner);
+ if(entry0->second->size() > 0)
+ bDestroy = false;
+ else
+ {
+ mBindingData->mOwnerActorsMap[&inObj]->~OwnerActorsValueType();
+ PX_FREE(mBindingData->mOwnerActorsMap[&inObj]);
+ mBindingData->mOwnerActorsMap.erase(&inObj);
+ }
+ }
+
+ if(bDestroy)
+ {
+ if(!inObj.isExclusive())
+ inStream.removeObjectRef(&PxGetPhysics(), "SharedShapes", &inObj);
+
+ const void* geomInst = (reinterpret_cast<const PxU8*>(&inObj)) + 4;
+ inStream.destroyInstance(geomInst);
+ inStream.destroyInstance(&inObj);
+
+ const OwnerActorsMap::Entry* entry = mBindingData->mOwnerActorsMap.find(&inObj);
+ if(entry != NULL)
+ {
+ entry->second->~OwnerActorsValueType();
+ PX_FREE(entry->second);
+ mBindingData->mOwnerActorsMap.erase(&inObj);
+ }
+ }
+ }
+}
+
+template <typename TDataType>
+void addSceneGroupProperty(PvdDataStream& inStream, const char* groupName, const TDataType& inObj, const PxScene& inScene)
+{
+ inStream.createInstance(&inObj);
+ inStream.pushBackObjectRef(&inScene, groupName, &inObj);
+ inStream.setPropertyValue(&inObj, "Scene", reinterpret_cast<const void*>(&inScene));
+}
+
+template <typename TDataType>
+void removeSceneGroupProperty(PvdDataStream& inStream, const char* groupName, const TDataType& inObj, const PxScene& inScene)
+{
+ inStream.removeObjectRef(&inScene, groupName, &inObj);
+ inStream.destroyInstance(&inObj);
+}
+
+void sendShapes(PvdMetaDataBinding& binding, PvdDataStream& inStream, const PxRigidActor& inObj, PsPvd* pvd)
+{
+ InlineArray<PxShape*, 5> shapeData;
+ PxU32 nbShapes = inObj.getNbShapes();
+ shapeData.resize(nbShapes);
+ inObj.getShapes(shapeData.begin(), nbShapes);
+ for(PxU32 idx = 0; idx < nbShapes; ++idx)
+ binding.createInstance(inStream, *shapeData[idx], inObj, pvd);
+}
+
+void releaseShapes(PvdMetaDataBinding& binding, PvdDataStream& inStream, const PxRigidActor& inObj)
+{
+ InlineArray<PxShape*, 5> shapeData;
+ PxU32 nbShapes = inObj.getNbShapes();
+ shapeData.resize(nbShapes);
+ inObj.getShapes(shapeData.begin(), nbShapes);
+ for(PxU32 idx = 0; idx < nbShapes; ++idx)
+ binding.destroyInstance(inStream, *shapeData[idx], inObj);
+}
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxRigidStatic& inObj, const PxScene& ownerScene, PsPvd* pvd)
+{
+ addSceneGroupProperty(inStream, "RigidStatics", inObj, ownerScene);
+ sendAllProperties(inStream, inObj);
+ sendShapes(*this, inStream, inObj, pvd);
+}
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxRigidStatic& inObj)
+{
+ PxRigidStaticGeneratedValues values(&inObj);
+ inStream.setPropertyMessage(&inObj, values);
+}
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxRigidStatic& inObj, const PxScene& ownerScene)
+{
+ releaseShapes(*this, inStream, inObj);
+ removeSceneGroupProperty(inStream, "RigidStatics", inObj, ownerScene);
+}
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxRigidDynamic& inObj, const PxScene& ownerScene, PsPvd* pvd)
+{
+ addSceneGroupProperty(inStream, "RigidDynamics", inObj, ownerScene);
+ sendAllProperties(inStream, inObj);
+ sendShapes(*this, inStream, inObj, pvd);
+}
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxRigidDynamic& inObj)
+{
+ PxRigidDynamicGeneratedValues values(&inObj);
+ inStream.setPropertyMessage(&inObj, values);
+}
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxRigidDynamic& inObj, const PxScene& ownerScene)
+{
+ releaseShapes(*this, inStream, inObj);
+ removeSceneGroupProperty(inStream, "RigidDynamics", inObj, ownerScene);
+}
+
+void addChild(PvdDataStream& inStream, const void* inParent, const PxArticulationLink& inChild)
+{
+ inStream.pushBackObjectRef(inParent, "Links", &inChild);
+ inStream.setPropertyValue(&inChild, "Parent", inParent);
+}
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxArticulation& inObj, const PxScene& ownerScene, PsPvd* pvd)
+{
+ addSceneGroupProperty(inStream, "Articulations", inObj, ownerScene);
+ sendAllProperties(inStream, inObj);
+ PxU32 numLinks = inObj.getNbLinks();
+ mBindingData->mArticulationLinks.resize(numLinks);
+ inObj.getLinks(mBindingData->mArticulationLinks.begin(), numLinks);
+ // From Dilip Sequiera:
+ /*
+ No, there can only be one root, and in all the code I wrote (which is not 100% of the HL code for
+ articulations), the index of a child is always > the index of the parent.
+ */
+
+ // Create all the links
+ for(PxU32 idx = 0; idx < numLinks; ++idx)
+ {
+ if(!inStream.isInstanceValid(mBindingData->mArticulationLinks[idx]))
+ createInstance(inStream, *mBindingData->mArticulationLinks[idx], pvd);
+ }
+
+ // Setup the link graph
+ for(PxU32 idx = 0; idx < numLinks; ++idx)
+ {
+ PxArticulationLink* link = mBindingData->mArticulationLinks[idx];
+ if(idx == 0)
+ addChild(inStream, &inObj, *link);
+
+ PxU32 numChildren = link->getNbChildren();
+ PxArticulationLink** children = mBindingData->allocateTemp<PxArticulationLink*>(numChildren);
+ link->getChildren(children, numChildren);
+ for(PxU32 i = 0; i < numChildren; ++i)
+ addChild(inStream, link, *children[i]);
+ }
+}
+
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxArticulation& inObj)
+{
+ PxArticulationGeneratedValues values(&inObj);
+ inStream.setPropertyMessage(&inObj, values);
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxArticulation& inObj, const PxScene& ownerScene)
+{
+ removeSceneGroupProperty(inStream, "Articulations", inObj, ownerScene);
+}
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxArticulationLink& inObj, PsPvd* pvd)
+{
+ inStream.createInstance(&inObj);
+ PxArticulationJoint* joint(inObj.getInboundJoint());
+ if(joint)
+ {
+ inStream.createInstance(joint);
+ inStream.setPropertyValue(&inObj, "InboundJoint", reinterpret_cast<const void*>(joint));
+ inStream.setPropertyValue(joint, "Link", reinterpret_cast<const void*>(&inObj));
+ sendAllProperties(inStream, *joint);
+ }
+ sendAllProperties(inStream, inObj);
+ sendShapes(*this, inStream, inObj, pvd);
+}
+
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxArticulationLink& inObj)
+{
+ PxArticulationLinkGeneratedValues values(&inObj);
+ inStream.setPropertyMessage(&inObj, values);
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxArticulationLink& inObj)
+{
+ PxArticulationJoint* joint(inObj.getInboundJoint());
+ if(joint)
+ inStream.destroyInstance(joint);
+ releaseShapes(*this, inStream, inObj);
+ inStream.destroyInstance(&inObj);
+}
+// These are created as part of the articulation link's creation process, so outside entities don't need to
+// create them.
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxArticulationJoint& inObj)
+{
+ PxArticulationJointGeneratedValues values(&inObj);
+ inStream.setPropertyMessage(&inObj, values);
+}
+
+void PvdMetaDataBinding::originShift(PvdDataStream& inStream, const PxScene* inScene, PxVec3 shift)
+{
+ inStream.originShift(inScene, shift);
+}
+
+template <typename TReadDataType>
+struct ParticleFluidUpdater
+{
+ TReadDataType& mData;
+ Array<PxU8>& mTempU8Array;
+ PvdDataStream& mStream;
+ const void* mInstanceId;
+ PxU32 mRdFlags;
+ ParticleFluidUpdater(TReadDataType& d, PvdDataStream& s, const void* id, PxU32 flags, Array<PxU8>& tempArray)
+ : mData(d), mTempU8Array(tempArray), mStream(s), mInstanceId(id), mRdFlags(flags)
+ {
+ }
+
+ template <PxU32 TKey, typename TObjectType, typename TPropertyType, PxU32 TEnableFlag>
+ void handleBuffer(const PxBufferPropertyInfo<TKey, TObjectType, PxStrideIterator<const TPropertyType>, TEnableFlag>& inProp, NamespacedName datatype)
+ {
+ PxU32 nbValidParticles = mData.nbValidParticles;
+ PxU32 validParticleRange = mData.validParticleRange;
+ PxStrideIterator<const TPropertyType> iterator(inProp.get(&mData));
+ const PxU32* validParticleBitmap = mData.validParticleBitmap;
+
+ if(nbValidParticles == 0 || iterator.ptr() == NULL || inProp.isEnabled(mRdFlags) == false)
+ return;
+
+ // setup the pvd array
+ DataRef<const PxU8> propData;
+ mTempU8Array.resize(nbValidParticles * sizeof(TPropertyType));
+ TPropertyType* tmpArray = reinterpret_cast<TPropertyType*>(mTempU8Array.begin());
+ propData = DataRef<const PxU8>(mTempU8Array.begin(), mTempU8Array.size());
+ if(nbValidParticles == validParticleRange)
+ {
+ for(PxU32 idx = 0; idx < nbValidParticles; ++idx)
+ tmpArray[idx] = iterator[idx];
+ }
+ else
+ {
+ PxU32 tIdx = 0;
+ // iterate over bitmap and send all valid particles
+ for(PxU32 w = 0; w <= (validParticleRange - 1) >> 5; w++)
+ {
+ for(PxU32 b = validParticleBitmap[w]; b; b &= b - 1)
+ {
+ tmpArray[tIdx++] = iterator[w << 5 | Ps::lowestSetBit(b)];
+ }
+ }
+ PX_ASSERT(tIdx == nbValidParticles);
+ }
+ mStream.setPropertyValue(mInstanceId, inProp.mName, propData, datatype);
+ }
+ template <PxU32 TKey, typename TObjectType, typename TPropertyType, PxU32 TEnableFlag>
+ void handleBuffer(const PxBufferPropertyInfo<TKey, TObjectType, PxStrideIterator<const TPropertyType>, TEnableFlag>& inProp)
+ {
+ handleBuffer(inProp, getPvdNamespacedNameForType<TPropertyType>());
+ }
+
+ template <PxU32 TKey, typename TObjectType, typename TEnumType, typename TStorageType, PxU32 TEnableFlag>
+ void handleFlagsBuffer(const PxBufferPropertyInfo<TKey, TObjectType, PxStrideIterator<const PxFlags<TEnumType, TStorageType> >, TEnableFlag>& inProp, const PxU32ToName*)
+ {
+ handleBuffer(inProp, getPvdNamespacedNameForType<TStorageType>());
+ }
+
+ private:
+ ParticleFluidUpdater& operator=(const ParticleFluidUpdater&);
+};
+
+#if PX_USE_PARTICLE_SYSTEM_API
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxParticleSystem& inObj, const PxScene& ownerScene)
+{
+ addSceneGroupProperty(inStream, "ParticleSystems", inObj, ownerScene);
+ sendAllProperties(inStream, inObj);
+ PxParticleReadData* readData(const_cast<PxParticleSystem&>(inObj).lockParticleReadData());
+ if(readData)
+ {
+ PxU32 readFlags = inObj.getParticleReadDataFlags();
+ sendArrays(inStream, inObj, *readData, readFlags);
+ readData->unlock();
+ }
+}
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxParticleSystem& inObj)
+{
+ PxParticleSystemGeneratedValues values(&inObj);
+ inStream.setPropertyMessage(&inObj, values);
+}
+
+void PvdMetaDataBinding::sendArrays(PvdDataStream& inStream, const PxParticleSystem& inObj, PxParticleReadData& inData, PxU32 inFlags)
+{
+ inStream.setPropertyValue(&inObj, "NbParticles", inData.nbValidParticles);
+ inStream.setPropertyValue(&inObj, "ValidParticleRange", inData.validParticleRange);
+ if(inData.validParticleRange > 0)
+ inStream.setPropertyValue(&inObj, "ValidParticleBitmap", inData.validParticleBitmap, (inData.validParticleRange >> 5) + 1);
+
+ ParticleFluidUpdater<PxParticleReadData> theUpdater(inData, inStream, static_cast<const PxActor*>(&inObj), inFlags, mBindingData->mTempU8Array);
+ visitParticleSystemBufferProperties(makePvdPropertyFilter(theUpdater));
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxParticleSystem& inObj, const PxScene& ownerScene)
+{
+ removeSceneGroupProperty(inStream, "ParticleSystems", inObj, ownerScene);
+}
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxParticleFluid& inObj, const PxScene& ownerScene)
+{
+ addSceneGroupProperty(inStream, "ParticleFluids", inObj, ownerScene);
+ sendAllProperties(inStream, inObj);
+ PxParticleFluidReadData* readData(const_cast<PxParticleFluid&>(inObj).lockParticleFluidReadData());
+ if(readData)
+ {
+ PxU32 readFlags = inObj.getParticleReadDataFlags();
+ sendArrays(inStream, inObj, *readData, readFlags);
+ readData->unlock();
+ }
+}
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxParticleFluid& inObj)
+{
+ PxParticleFluidGeneratedValues values(&inObj);
+ inStream.setPropertyMessage(&inObj, values);
+}
+
+void PvdMetaDataBinding::sendArrays(PvdDataStream& inStream, const PxParticleFluid& inObj, PxParticleFluidReadData& inData, PxU32 inFlags)
+{
+ inStream.setPropertyValue(&inObj, "NbParticles", inData.nbValidParticles);
+ inStream.setPropertyValue(&inObj, "ValidParticleRange", inData.validParticleRange);
+ if(inData.validParticleRange > 0)
+ inStream.setPropertyValue(&inObj, "ValidParticleBitmap", inData.validParticleBitmap, (inData.validParticleRange >> 5) + 1);
+
+ ParticleFluidUpdater<PxParticleFluidReadData> theUpdater(inData, inStream, static_cast<const PxActor*>(&inObj), inFlags, mBindingData->mTempU8Array);
+ visitParticleSystemBufferProperties(makePvdPropertyFilter(theUpdater));
+ visitParticleFluidBufferProperties(makePvdPropertyFilter(theUpdater));
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxParticleFluid& inObj, const PxScene& ownerScene)
+{
+ removeSceneGroupProperty(inStream, "ParticleFluids", inObj, ownerScene);
+}
+#endif // PX_USE_PARTICLE_SYSTEM_API
+
+template <typename TBlockType, typename TActorType, typename TOperator>
+void updateActor(PvdDataStream& inStream, TActorType** actorGroup, PxU32 numActors, TOperator sleepingOp, PvdMetaDataBindingData& bindingData)
+{
+ TBlockType theBlock;
+ if(numActors == 0)
+ return;
+ for(PxU32 idx = 0; idx < numActors; ++idx)
+ {
+ TActorType* theActor(actorGroup[idx]);
+ bool sleeping = sleepingOp(theActor, theBlock);
+ bool wasSleeping = bindingData.mSleepingActors.contains(theActor);
+
+ if(sleeping == false || sleeping != wasSleeping)
+ {
+ theBlock.GlobalPose = theActor->getGlobalPose();
+ theBlock.AngularVelocity = theActor->getAngularVelocity();
+ theBlock.LinearVelocity = theActor->getLinearVelocity();
+ inStream.sendPropertyMessageFromGroup(theActor, theBlock);
+ if(sleeping != wasSleeping)
+ {
+ if(sleeping)
+ bindingData.mSleepingActors.insert(theActor);
+ else
+ bindingData.mSleepingActors.erase(theActor);
+ }
+ }
+ }
+}
+
+struct RigidDynamicUpdateOp
+{
+ bool operator()(PxRigidDynamic* actor, PxRigidDynamicUpdateBlock& block)
+ {
+ bool sleeping = actor->isSleeping();
+ block.IsSleeping = sleeping;
+ return sleeping;
+ }
+};
+
+struct ArticulationLinkUpdateOp
+{
+ bool sleeping;
+ ArticulationLinkUpdateOp(bool s) : sleeping(s)
+ {
+ }
+ bool operator()(PxArticulationLink*, PxArticulationLinkUpdateBlock&)
+ {
+ return sleeping;
+ }
+};
+
+void PvdMetaDataBinding::updateDynamicActorsAndArticulations(PvdDataStream& inStream, const PxScene* inScene, PvdVisualizer* linkJointViz)
+{
+ PX_COMPILE_TIME_ASSERT(sizeof(PxRigidDynamicUpdateBlock) == 14 * 4);
+ {
+ PxU32 actorCount = inScene->getNbActors(PxActorTypeFlag::eRIGID_DYNAMIC);
+ if(actorCount)
+ {
+ inStream.beginPropertyMessageGroup<PxRigidDynamicUpdateBlock>();
+ mBindingData->mActors.resize(actorCount);
+ PxActor** theActors = mBindingData->mActors.begin();
+ inScene->getActors(PxActorTypeFlag::eRIGID_DYNAMIC, theActors, actorCount);
+ updateActor<PxRigidDynamicUpdateBlock>(inStream, reinterpret_cast<PxRigidDynamic**>(theActors), actorCount, RigidDynamicUpdateOp(), *mBindingData);
+ inStream.endPropertyMessageGroup();
+ }
+ }
+ {
+ PxU32 articulationCount = inScene->getNbArticulations();
+ if(articulationCount)
+ {
+ mBindingData->mArticulations.resize(articulationCount);
+ PxArticulation** firstArticulation = mBindingData->mArticulations.begin();
+ PxArticulation** lastArticulation = firstArticulation + articulationCount;
+ inScene->getArticulations(firstArticulation, articulationCount);
+ inStream.beginPropertyMessageGroup<PxArticulationLinkUpdateBlock>();
+ for(; firstArticulation < lastArticulation; ++firstArticulation)
+ {
+ PxU32 linkCount = (*firstArticulation)->getNbLinks();
+ bool sleeping = (*firstArticulation)->isSleeping();
+ if(linkCount)
+ {
+ mBindingData->mArticulationLinks.resize(linkCount);
+ PxArticulationLink** theLink = mBindingData->mArticulationLinks.begin();
+ (*firstArticulation)->getLinks(theLink, linkCount);
+ updateActor<PxArticulationLinkUpdateBlock>(inStream, theLink, linkCount, ArticulationLinkUpdateOp(sleeping), *mBindingData);
+ if(linkJointViz)
+ {
+ for(PxU32 idx = 0; idx < linkCount; ++idx)
+ linkJointViz->visualize(*theLink[idx]);
+ }
+ }
+ }
+ inStream.endPropertyMessageGroup();
+ firstArticulation = mBindingData->mArticulations.begin();
+ for(; firstArticulation < lastArticulation; ++firstArticulation)
+ inStream.setPropertyValue(*firstArticulation, "IsSleeping", (*firstArticulation)->isSleeping());
+ }
+ }
+}
+
+template <typename TObjType>
+struct CollectionOperator
+{
+ Array<PxU8>& mTempArray;
+ const TObjType& mObject;
+ PvdDataStream& mStream;
+
+ CollectionOperator(Array<PxU8>& ary, const TObjType& obj, PvdDataStream& stream)
+ : mTempArray(ary), mObject(obj), mStream(stream)
+ {
+ }
+ void pushName(const char*)
+ {
+ }
+ void popName()
+ {
+ }
+ template <typename TAccessor>
+ void simpleProperty(PxU32 /*key*/, const TAccessor&)
+ {
+ }
+ template <typename TAccessor>
+ void flagsProperty(PxU32 /*key*/, const TAccessor&, const PxU32ToName*)
+ {
+ }
+
+ template <typename TColType, typename TDataType, typename TCollectionProp>
+ void handleCollection(const TCollectionProp& prop, NamespacedName dtype, PxU32 countMultiplier = 1)
+ {
+ PxU32 count = prop.size(&mObject);
+ mTempArray.resize(count * sizeof(TDataType));
+ TColType* start = reinterpret_cast<TColType*>(mTempArray.begin());
+ prop.get(&mObject, start, count * countMultiplier);
+ mStream.setPropertyValue(&mObject, prop.mName, DataRef<const PxU8>(mTempArray.begin(), mTempArray.size()), dtype);
+ }
+ template <PxU32 TKey, typename TObject, typename TColType>
+ void handleCollection(const PxReadOnlyCollectionPropertyInfo<TKey, TObject, TColType>& prop)
+ {
+ handleCollection<TColType, TColType>(prop, getPvdNamespacedNameForType<TColType>());
+ }
+ // Enumerations or bitflags.
+ template <PxU32 TKey, typename TObject, typename TColType>
+ void handleCollection(const PxReadOnlyCollectionPropertyInfo<TKey, TObject, TColType>& prop, const PxU32ToName*)
+ {
+ PX_COMPILE_TIME_ASSERT(sizeof(TColType) == sizeof(PxU32));
+ handleCollection<TColType, PxU32>(prop, getPvdNamespacedNameForType<PxU32>());
+ }
+
+ private:
+ CollectionOperator& operator=(const CollectionOperator&);
+};
+
+#if PX_USE_CLOTH_API
+struct PxClothFabricCollectionOperator : CollectionOperator<PxClothFabric>
+{
+ PxClothFabricCollectionOperator(Array<PxU8>& ary, const PxClothFabric& obj, PvdDataStream& stream)
+ : CollectionOperator<PxClothFabric>(ary, obj, stream)
+ {
+ }
+
+ template <PxU32 TKey, typename TObject, typename TColType>
+ void handleCollection(const PxReadOnlyCollectionPropertyInfo<TKey, TObject, TColType>& prop)
+ {
+ // CollectionOperator<PxClothFabric>::handleCollection<TColType,TColType>( prop,
+ // getPvdNamespacedNameForType<TColType>(), sizeof( TColType ) );
+
+ // have to duplicate here because the cloth api expects buffer sizes
+ // in the number of elements, not the number of bytes
+ PxU32 count = prop.size(&mObject);
+ mTempArray.resize(count * sizeof(TColType));
+ TColType* start = reinterpret_cast<TColType*>(mTempArray.begin());
+ prop.get(&mObject, start, count);
+ mStream.setPropertyValue(&mObject, prop.mName, DataRef<const PxU8>(mTempArray.begin(), mTempArray.size()), getPvdNamespacedNameForType<TColType>());
+ }
+
+ // Enumerations or bitflags.
+ template <PxU32 TKey, typename TObject, typename TColType>
+ void handleCollection(const PxReadOnlyCollectionPropertyInfo<TKey, TObject, TColType>& prop, const PxU32ToName*)
+ {
+ PX_COMPILE_TIME_ASSERT(sizeof(TColType) == sizeof(PxU32));
+ CollectionOperator<PxClothFabric>::handleCollection<TColType, PxU32>(prop, getPvdNamespacedNameForType<PxU32>());
+ }
+
+ private:
+ PxClothFabricCollectionOperator& operator=(const PxClothFabricCollectionOperator&);
+};
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxClothFabric& fabric, const PxPhysics& ownerPhysics)
+{
+ inStream.createInstance(&fabric);
+ addPhysicsGroupProperty(inStream, "ClothFabrics", fabric, ownerPhysics);
+ sendAllProperties(inStream, fabric);
+}
+
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxClothFabric& fabric)
+{
+ PxClothFabricCollectionOperator op(mBindingData->mTempU8Array, fabric, inStream);
+ visitInstancePvdProperties<PxClothFabric>(op);
+
+ PxClothFabricGeneratedValues values(&fabric);
+ inStream.setPropertyMessage(&fabric, values);
+
+ PxU32 count = fabric.getNbPhases();
+ PxClothFabricPhase* phases = mBindingData->allocateTemp<PxClothFabricPhase>(count);
+ if(count)
+ fabric.getPhases(phases, count);
+ inStream.setPropertyValue(&fabric, "Phases", DataRef<const PxU8>(reinterpret_cast<PxU8*>(phases), sizeof(PxClothFabricPhase) * count), getPvdNamespacedNameForType<PxClothFabricPhase>());
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxClothFabric& fabric, const PxPhysics& ownerPhysics)
+{
+ removePhysicsGroupProperty(inStream, "ClothFabrics", fabric, ownerPhysics);
+}
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxCloth& cloth, const PxScene& ownerScene, PsPvd* pvd)
+{
+ addSceneGroupProperty(inStream, "Cloths", cloth, ownerScene);
+ PxClothFabric* fabric = cloth.getFabric();
+ if(fabric != NULL)
+ {
+ if(pvd->registerObject(fabric))
+ createInstance(inStream, *fabric, PxGetPhysics());
+ inStream.setPropertyValue(&cloth, "Fabric", reinterpret_cast<const void*>(fabric));
+ inStream.pushBackObjectRef(fabric, "Cloths", &cloth);
+ }
+ sendAllProperties(inStream, cloth);
+}
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxCloth& cloth)
+{
+ sendSimpleProperties(inStream, cloth);
+ sendParticleAccelerations(inStream, cloth);
+ sendMotionConstraints(inStream, cloth);
+ sendCollisionSpheres(inStream, cloth);
+ sendCollisionSpheres(inStream, cloth, true);
+ sendCollisionTriangles(inStream, cloth);
+ sendVirtualParticles(inStream, cloth);
+ sendSeparationConstraints(inStream, cloth);
+ sendSelfCollisionIndices(inStream, cloth);
+ sendRestPositions(inStream, cloth);
+}
+void PvdMetaDataBinding::sendSimpleProperties(PvdDataStream& inStream, const PxCloth& cloth)
+{
+ PxClothGeneratedValues values(&cloth);
+ inStream.setPropertyMessage(&cloth, values);
+}
+void PvdMetaDataBinding::sendMotionConstraints(PvdDataStream& inStream, const PxCloth& cloth)
+{
+ PxU32 count = cloth.getNbMotionConstraints();
+ PxClothParticleMotionConstraint* constraints = mBindingData->allocateTemp<PxClothParticleMotionConstraint>(count);
+ if(count)
+ cloth.getMotionConstraints(constraints);
+ inStream.setPropertyValue(&cloth, "MotionConstraints", mBindingData->tempToRef(), getPvdNamespacedNameForType<PvdPositionAndRadius>());
+}
+
+void PvdMetaDataBinding::sendRestPositions(PvdDataStream& inStream, const PxCloth& cloth)
+{
+ PxU32 count = cloth.getNbRestPositions();
+ PxVec4* positions = mBindingData->allocateTemp<PxVec4>(count);
+ if(count)
+ cloth.getRestPositions(positions);
+ inStream.setPropertyValue(&cloth, "RestPositions", mBindingData->tempToRef(), getPvdNamespacedNameForType<PxVec4>());
+}
+
+void PvdMetaDataBinding::sendParticleAccelerations(PvdDataStream& inStream, const PxCloth& cloth)
+{
+ PxU32 count = cloth.getNbParticleAccelerations();
+ PxVec4* accelerations = mBindingData->allocateTemp<PxVec4>(count);
+ if(count)
+ cloth.getParticleAccelerations(accelerations);
+ inStream.setPropertyValue(&cloth, "ParticleAccelerations", mBindingData->tempToRef(), getPvdNamespacedNameForType<PxVec4>());
+}
+
+void PvdMetaDataBinding::sendSelfCollisionIndices(PvdDataStream& inStream, const PxCloth& cloth)
+{
+ PxU32 count = cloth.getNbSelfCollisionIndices();
+ PxU32* selfCollisionIndices = mBindingData->allocateTemp<PxU32>(count);
+ if(count)
+ cloth.getSelfCollisionIndices(selfCollisionIndices);
+ inStream.setPropertyValue(&cloth, "SelfCollisionIndices", mBindingData->tempToRef(), getPvdNamespacedNameForType<PxU32>());
+}
+
+void PvdMetaDataBinding::sendCollisionSpheres(PvdDataStream& inStream, const PxCloth& cloth, bool sendPairs)
+{
+ PxU32 numSpheres = cloth.getNbCollisionSpheres();
+ PxU32 numIndices = 2 * cloth.getNbCollisionCapsules();
+ PxU32 numPlanes = cloth.getNbCollisionPlanes();
+ PxU32 numConvexes = cloth.getNbCollisionConvexes();
+ PxU32 numTriangles = cloth.getNbCollisionTriangles();
+
+ PxU32 sphereBytes = numSpheres * sizeof(PxClothCollisionSphere);
+ PxU32 pairBytes = numIndices * sizeof(PxU32);
+ PxU32 planesBytes = numPlanes * sizeof(PxClothCollisionPlane);
+ PxU32 convexBytes = numConvexes * sizeof(PxU32);
+ PxU32 triangleBytes = numTriangles * sizeof(PxClothCollisionTriangle);
+
+ mBindingData->mTempU8Array.resize(sphereBytes + pairBytes + planesBytes + convexBytes + triangleBytes);
+ PxU8* bufferStart = mBindingData->mTempU8Array.begin();
+ PxClothCollisionSphere* spheresBuffer = reinterpret_cast<PxClothCollisionSphere*>(mBindingData->mTempU8Array.begin());
+ PxU32* indexBuffer = reinterpret_cast<PxU32*>(spheresBuffer + numSpheres);
+ PxClothCollisionPlane* planeBuffer = reinterpret_cast<PxClothCollisionPlane*>(indexBuffer + numIndices);
+ PxU32* convexBuffer = reinterpret_cast<PxU32*>(planeBuffer + numPlanes);
+ PxClothCollisionTriangle* trianglesBuffer = reinterpret_cast<PxClothCollisionTriangle*>(convexBuffer + numConvexes);
+
+ cloth.getCollisionData(spheresBuffer, indexBuffer, planeBuffer, convexBuffer, trianglesBuffer);
+ inStream.setPropertyValue(&cloth, "CollisionSpheres", DataRef<const PxU8>(bufferStart, sphereBytes), getPvdNamespacedNameForType<PvdPositionAndRadius>());
+ if(sendPairs)
+ inStream.setPropertyValue(&cloth, "CollisionSpherePairs", DataRef<const PxU8>(bufferStart + sphereBytes, pairBytes), getPvdNamespacedNameForType<PxU32>());
+}
+
+// begin code to generate triangle mesh from cloth convex planes
+
+namespace
+{
+PxReal det(PxVec4 v0, PxVec4 v1, PxVec4 v2, PxVec4 v3)
+{
+ const PxVec3& d0 = reinterpret_cast<const PxVec3&>(v0);
+ const PxVec3& d1 = reinterpret_cast<const PxVec3&>(v1);
+ const PxVec3& d2 = reinterpret_cast<const PxVec3&>(v2);
+ const PxVec3& d3 = reinterpret_cast<const PxVec3&>(v3);
+
+ return v0.w * d1.cross(d2).dot(d3) - v1.w * d0.cross(d2).dot(d3) + v2.w * d0.cross(d1).dot(d3) -
+ v3.w * d0.cross(d1).dot(d2);
+}
+
+PxVec3 intersect(PxVec4 p0, PxVec4 p1, PxVec4 p2)
+{
+ const PxVec3& d0 = reinterpret_cast<const PxVec3&>(p0);
+ const PxVec3& d1 = reinterpret_cast<const PxVec3&>(p1);
+ const PxVec3& d2 = reinterpret_cast<const PxVec3&>(p2);
+
+ return (p0.w * d1.cross(d2) + p1.w * d2.cross(d0) + p2.w * d0.cross(d1)) / d0.dot(d2.cross(d1));
+}
+
+const PxU16 sInvalid = PxU16(-1);
+
+// restriction: only supports a single patch per vertex.
+struct HalfedgeMesh
+{
+ struct Halfedge
+ {
+ Halfedge(PxU16 vertex = sInvalid, PxU16 face = sInvalid, PxU16 next = sInvalid, PxU16 prev = sInvalid)
+ : mVertex(vertex), mFace(face), mNext(next), mPrev(prev)
+ {
+ }
+
+ PxU16 mVertex; // to
+ PxU16 mFace; // left
+ PxU16 mNext; // ccw
+ PxU16 mPrev; // cw
+ };
+
+ PxU16 findHalfedge(PxU16 v0, PxU16 v1)
+ {
+ PxU16 h = mVertices[v0], start = h;
+ while(h != sInvalid && mHalfedges[h].mVertex != v1)
+ {
+ h = mHalfedges[PxU32(h ^ 1)].mNext;
+ if(h == start)
+ return sInvalid;
+ }
+ return h;
+ }
+
+ void connect(PxU16 h0, PxU16 h1)
+ {
+ mHalfedges[h0].mNext = h1;
+ mHalfedges[h1].mPrev = h0;
+ }
+
+ void addTriangle(PxU16 v0, PxU16 v1, PxU16 v2)
+ {
+ // add new vertices
+ PxU16 n = PxU16(PxMax(v0, PxMax(v1, v2)) + 1);
+ if(mVertices.size() < n)
+ mVertices.resize(n, sInvalid);
+
+ // collect halfedges, prev and next of triangle
+ PxU16 verts[] = { v0, v1, v2 };
+ PxU16 handles[3], prev[3], next[3];
+ for(PxU16 i = 0; i < 3; ++i)
+ {
+ PxU16 j = PxU16((i + 1) % 3);
+ PxU16 h = findHalfedge(verts[i], verts[j]);
+ if(h == sInvalid)
+ {
+ // add new edge
+ h = Ps::to16(mHalfedges.size());
+ mHalfedges.pushBack(Halfedge(verts[j]));
+ mHalfedges.pushBack(Halfedge(verts[i]));
+ }
+ handles[i] = h;
+ prev[i] = mHalfedges[h].mPrev;
+ next[i] = mHalfedges[h].mNext;
+ }
+
+ // patch connectivity
+ for(PxU16 i = 0; i < 3; ++i)
+ {
+ PxU16 j = PxU16((i + 1) % 3);
+
+ mHalfedges[handles[i]].mFace = Ps::to16(mFaces.size());
+
+ // connect prev and next
+ connect(handles[i], handles[j]);
+
+ if(next[j] == sInvalid) // new next edge, connect opposite
+ connect(PxU16(handles[j] ^ 1), next[i] != sInvalid ? next[i] : PxU16(handles[i] ^ 1));
+
+ if(prev[i] == sInvalid) // new prev edge, connect opposite
+ connect(prev[j] != sInvalid ? prev[j] : PxU16(handles[j] ^ 1), PxU16(handles[i] ^ 1));
+
+ // prev is boundary, update middle vertex
+ if(mHalfedges[PxU32(handles[i] ^ 1)].mFace == sInvalid)
+ mVertices[verts[j]] = PxU16(handles[i] ^ 1);
+ }
+
+ mFaces.pushBack(handles[2]);
+ }
+
+ PxU16 removeTriangle(PxU16 f)
+ {
+ PxU16 result = sInvalid;
+
+ for(PxU16 i = 0, h = mFaces[f]; i < 3; ++i)
+ {
+ PxU16 v0 = mHalfedges[PxU32(h ^ 1)].mVertex;
+ PxU16 v1 = mHalfedges[PxU32(h)].mVertex;
+
+ mHalfedges[h].mFace = sInvalid;
+
+ if(mHalfedges[PxU32(h ^ 1)].mFace == sInvalid) // was boundary edge, remove
+ {
+ // update halfedge connectivity
+ connect(mHalfedges[h].mPrev, mHalfedges[PxU32(h ^ 1)].mNext);
+ connect(mHalfedges[PxU32(h ^ 1)].mPrev, mHalfedges[h].mNext);
+
+ // update vertex boundary or delete
+ mVertices[v0] = mVertices[v0] == h ? sInvalid : mHalfedges[PxU32(h ^ 1)].mNext;
+ mVertices[v1] = mVertices[v1] == (h ^ 1) ? sInvalid : mHalfedges[h].mNext;
+ }
+ else
+ {
+ mVertices[v0] = h; // update vertex boundary
+ result = v1;
+ }
+
+ h = mHalfedges[h].mNext;
+ }
+
+ mFaces[f] = sInvalid;
+ return result;
+ }
+
+ // true if vertex v is in front of face f
+ bool visible(PxU16 v, PxU16 f)
+ {
+ PxU16 h = mFaces[f];
+ if(h == sInvalid)
+ return false;
+
+ PxU16 v0 = mHalfedges[h].mVertex;
+ h = mHalfedges[h].mNext;
+ PxU16 v1 = mHalfedges[h].mVertex;
+ h = mHalfedges[h].mNext;
+ PxU16 v2 = mHalfedges[h].mVertex;
+ h = mHalfedges[h].mNext;
+
+ return det(mPoints[v], mPoints[v0], mPoints[v1], mPoints[v2]) < 0.0f;
+ }
+
+ shdfnd::Array<Halfedge> mHalfedges;
+ shdfnd::Array<PxU16> mVertices; // vertex -> (boundary) halfedge
+ shdfnd::Array<PxU16> mFaces; // face -> halfedge
+ shdfnd::Array<PxVec4> mPoints;
+};
+}
+
+struct ConvexMeshBuilder
+{
+ ConvexMeshBuilder(const PxVec4* planes) : mPlanes(planes)
+ {
+ }
+
+ void operator()(PxU32 mask, float scale = 1.0f);
+
+ const PxVec4* mPlanes;
+ shdfnd::Array<PxVec3> mVertices;
+ shdfnd::Array<PxU16> mIndices;
+};
+
+void ConvexMeshBuilder::operator()(PxU32 planeMask, float scale)
+{
+ PxU16 numPlanes = Ps::to16(shdfnd::bitCount(planeMask));
+
+ if(numPlanes == 1)
+ {
+ PxTransform t = PxTransformFromPlaneEquation(reinterpret_cast<const PxPlane&>(mPlanes[lowestSetBit(planeMask)]));
+
+ if(!t.isValid())
+ return;
+
+ const PxU16 indices[] = { 0, 1, 2, 0, 2, 3 };
+ const PxVec3 vertices[] = { PxVec3(0.0f, scale, scale), PxVec3(0.0f, -scale, scale),
+ PxVec3(0.0f, -scale, -scale), PxVec3(0.0f, scale, -scale) };
+
+ PxU16 baseIndex = Ps::to16(mVertices.size());
+
+ for(PxU32 i = 0; i < 4; ++i)
+ mVertices.pushBack(t.transform(vertices[i]));
+
+ for(PxU32 i = 0; i < 6; ++i)
+ mIndices.pushBack(PxU16(indices[i] + baseIndex));
+
+ return;
+ }
+
+ if(numPlanes < 4)
+ return; // todo: handle degenerate cases
+
+ HalfedgeMesh mesh;
+
+ // gather points (planes, that is)
+ mesh.mPoints.reserve(numPlanes);
+ for(; planeMask; planeMask &= planeMask - 1)
+ mesh.mPoints.pushBack(mPlanes[shdfnd::lowestSetBit(planeMask)]);
+
+ // initialize to tetrahedron
+ mesh.addTriangle(0, 1, 2);
+ mesh.addTriangle(0, 3, 1);
+ mesh.addTriangle(1, 3, 2);
+ mesh.addTriangle(2, 3, 0);
+
+ // flip if inside-out
+ if(mesh.visible(3, 0))
+ shdfnd::swap(mesh.mPoints[0], mesh.mPoints[1]);
+
+ // iterate through remaining points
+ for(PxU16 i = 4; i < mesh.mPoints.size(); ++i)
+ {
+ // remove any visible triangle
+ PxU16 v0 = sInvalid;
+ for(PxU16 j = 0; j < mesh.mFaces.size(); ++j)
+ {
+ if(mesh.visible(i, j))
+ v0 = PxMin(v0, mesh.removeTriangle(j));
+ }
+
+ if(v0 == sInvalid)
+ continue;
+
+ // tesselate hole
+ PxU16 start = v0;
+ do
+ {
+ PxU16 h = mesh.mVertices[v0];
+ PxU16 v1 = mesh.mHalfedges[h].mVertex;
+ mesh.addTriangle(v0, v1, i);
+ v0 = v1;
+ } while(v0 != start);
+ }
+
+ // convert triangles to vertices (intersection of 3 planes)
+ shdfnd::Array<PxU32> face2Vertex(mesh.mFaces.size());
+ for(PxU32 i = 0; i < mesh.mFaces.size(); ++i)
+ {
+ face2Vertex[i] = mVertices.size();
+
+ PxU16 h = mesh.mFaces[i];
+ if(h == sInvalid)
+ continue;
+
+ PxU16 v0 = mesh.mHalfedges[h].mVertex;
+ h = mesh.mHalfedges[h].mNext;
+ PxU16 v1 = mesh.mHalfedges[h].mVertex;
+ h = mesh.mHalfedges[h].mNext;
+ PxU16 v2 = mesh.mHalfedges[h].mVertex;
+
+ mVertices.pushBack(intersect(mesh.mPoints[v0], mesh.mPoints[v1], mesh.mPoints[v2]));
+ }
+
+ // convert vertices to polygons (face one-ring)
+ for(PxU32 i = 0; i < mesh.mVertices.size(); ++i)
+ {
+ PxU16 h = mesh.mVertices[i];
+ if(h == sInvalid)
+ continue;
+
+ PxU16 v0 = Ps::to16(face2Vertex[mesh.mHalfedges[h].mFace]);
+ h = PxU16(mesh.mHalfedges[h].mPrev ^ 1);
+ PxU16 v1 = Ps::to16(face2Vertex[mesh.mHalfedges[h].mFace]);
+
+ while(true)
+ {
+ h = PxU16(mesh.mHalfedges[h].mPrev ^ 1);
+ PxU16 v2 = Ps::to16(face2Vertex[mesh.mHalfedges[h].mFace]);
+
+ if(v0 == v2)
+ break;
+
+ mIndices.pushBack(v0);
+ mIndices.pushBack(v2);
+ mIndices.pushBack(v1);
+
+ v1 = v2;
+ }
+ }
+}
+
+void PvdMetaDataBinding::sendCollisionTriangles(PvdDataStream& inStream, const PxCloth& cloth)
+{
+ PxU32 numSpheres = cloth.getNbCollisionSpheres();
+ PxU32 numIndices = 2 * cloth.getNbCollisionCapsules();
+ PxU32 numPlanes = cloth.getNbCollisionPlanes();
+ PxU32 numConvexes = cloth.getNbCollisionConvexes();
+ PxU32 numTriangles = cloth.getNbCollisionTriangles();
+
+ PxU32 sphereBytes = numSpheres * sizeof(PxClothCollisionSphere);
+ PxU32 pairBytes = numIndices * sizeof(PxU32);
+ PxU32 planesBytes = numPlanes * sizeof(PxClothCollisionPlane);
+ PxU32 convexBytes = numConvexes * sizeof(PxU32);
+ PxU32 triangleBytes = numTriangles * sizeof(PxClothCollisionTriangle);
+
+ mBindingData->mTempU8Array.resize(sphereBytes + pairBytes + planesBytes + convexBytes + triangleBytes);
+ PxU8* bufferStart = mBindingData->mTempU8Array.begin();
+ PxClothCollisionSphere* spheresBuffer = reinterpret_cast<PxClothCollisionSphere*>(mBindingData->mTempU8Array.begin());
+ PxU32* indexBuffer = reinterpret_cast<PxU32*>(spheresBuffer + numSpheres);
+ PxClothCollisionPlane* planeBuffer = reinterpret_cast<PxClothCollisionPlane*>(indexBuffer + numIndices);
+ PxU32* convexBuffer = reinterpret_cast<PxU32*>(planeBuffer + numPlanes);
+ PxClothCollisionTriangle* trianglesBuffer = reinterpret_cast<PxClothCollisionTriangle*>(convexBuffer + numConvexes);
+
+ cloth.getCollisionData(spheresBuffer, indexBuffer, planeBuffer, convexBuffer, trianglesBuffer);
+
+ inStream.setPropertyValue(&cloth, "CollisionPlanes", DataRef<const PxU8>(bufferStart + sphereBytes + pairBytes, planesBytes), getPvdNamespacedNameForType<PvdPositionAndRadius>());
+ inStream.setPropertyValue(&cloth, "CollisionConvexMasks", DataRef<const PxU8>(bufferStart + sphereBytes + pairBytes + planesBytes, convexBytes), getPvdNamespacedNameForType<PxU32>());
+ inStream.setPropertyValue(&cloth, "CollisionTriangles", DataRef<const PxU8>(bufferStart + sphereBytes + pairBytes + planesBytes + convexBytes, triangleBytes), getPvdNamespacedNameForType<PxVec3>());
+}
+
+void PvdMetaDataBinding::sendVirtualParticles(PvdDataStream& inStream, const PxCloth& cloth)
+{
+ PxU32 numParticles = cloth.getNbVirtualParticles();
+ PxU32 numWeights = cloth.getNbVirtualParticleWeights();
+ PxU32 numIndexes = numParticles * 4;
+ PxU32 numIndexBytes = numIndexes * sizeof(PxU32);
+ PxU32 numWeightBytes = numWeights * sizeof(PxVec3);
+
+ mBindingData->mTempU8Array.resize(PxMax(numIndexBytes, numWeightBytes));
+ PxU8* dataStart = mBindingData->mTempU8Array.begin();
+
+ PxU32* indexStart = reinterpret_cast<PxU32*>(dataStart);
+ if(numIndexes)
+ cloth.getVirtualParticles(indexStart);
+ inStream.setPropertyValue(&cloth, "VirtualParticles", DataRef<const PxU8>(dataStart, numIndexBytes), getPvdNamespacedNameForType<PxU32>());
+
+ PxVec3* weightStart = reinterpret_cast<PxVec3*>(dataStart);
+ if(numWeights)
+ cloth.getVirtualParticleWeights(weightStart);
+ inStream.setPropertyValue(&cloth, "VirtualParticleWeights", DataRef<const PxU8>(dataStart, numWeightBytes), getPvdNamespacedNameForType<PxVec3>());
+}
+void PvdMetaDataBinding::sendSeparationConstraints(PvdDataStream& inStream, const PxCloth& cloth)
+{
+ PxU32 count = cloth.getNbSeparationConstraints();
+ PxU32 byteSize = count * sizeof(PxClothParticleSeparationConstraint);
+ mBindingData->mTempU8Array.resize(byteSize);
+ if(count)
+ cloth.getSeparationConstraints(reinterpret_cast<PxClothParticleSeparationConstraint*>(mBindingData->mTempU8Array.begin()));
+ inStream.setPropertyValue(&cloth, "SeparationConstraints", mBindingData->tempToRef(), getPvdNamespacedNameForType<PvdPositionAndRadius>());
+}
+#endif // PX_USE_CLOTH_API
+
+// per frame update
+
+#if PX_USE_CLOTH_API
+
+void PvdMetaDataBinding::updateCloths(PvdDataStream& inStream, const PxScene& inScene)
+{
+ PxU32 actorCount = inScene.getNbActors(PxActorTypeFlag::eCLOTH);
+ if(actorCount == 0)
+ return;
+ mBindingData->mActors.resize(actorCount);
+ PxActor** theActors = mBindingData->mActors.begin();
+ inScene.getActors(PxActorTypeFlag::eCLOTH, theActors, actorCount);
+ PX_COMPILE_TIME_ASSERT(sizeof(PxClothParticle) == sizeof(PxVec3) + sizeof(PxF32));
+ for(PxU32 idx = 0; idx < actorCount; ++idx)
+ {
+ PxCloth* theCloth = static_cast<PxCloth*>(theActors[idx]);
+ bool isSleeping = theCloth->isSleeping();
+ bool wasSleeping = mBindingData->mSleepingActors.contains(theCloth);
+ if(isSleeping == false || isSleeping != wasSleeping)
+ {
+ PxClothParticleData* theData = theCloth->lockParticleData();
+ if(theData != NULL)
+ {
+ PxU32 numBytes = sizeof(PxClothParticle) * theCloth->getNbParticles();
+ inStream.setPropertyValue(theCloth, "ParticleBuffer", DataRef<const PxU8>(reinterpret_cast<const PxU8*>(theData->particles), numBytes), getPvdNamespacedNameForType<PxClothParticle>());
+ theData->unlock();
+ }
+ }
+ if(isSleeping != wasSleeping)
+ {
+ inStream.setPropertyValue(theCloth, "IsSleeping", isSleeping);
+ if(isSleeping)
+ mBindingData->mSleepingActors.insert(theActors[idx]);
+ else
+ mBindingData->mSleepingActors.erase(theActors[idx]);
+ }
+ }
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxCloth& cloth, const PxScene& ownerScene)
+{
+ PxClothFabric* fabric = cloth.getFabric();
+ if(fabric)
+ inStream.removeObjectRef(fabric, "Cloths", &cloth);
+ removeSceneGroupProperty(inStream, "Cloths", cloth, ownerScene);
+}
+
+#endif // PX_USE_CLOTH_API
+
+#define ENABLE_AGGREGATE_PVD_SUPPORT 1
+#ifdef ENABLE_AGGREGATE_PVD_SUPPORT
+
+void PvdMetaDataBinding::createInstance(PvdDataStream& inStream, const PxAggregate& inObj, const PxScene& ownerScene)
+{
+ addSceneGroupProperty(inStream, "Aggregates", inObj, ownerScene);
+ sendAllProperties(inStream, inObj);
+}
+
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream& inStream, const PxAggregate& inObj)
+{
+ PxAggregateGeneratedValues values(&inObj);
+ inStream.setPropertyMessage(&inObj, values);
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream& inStream, const PxAggregate& inObj, const PxScene& ownerScene)
+{
+ removeSceneGroupProperty(inStream, "Aggregates", inObj, ownerScene);
+}
+
+template <bool bPushBack>
+class ChangeOjectRefCmd : public PvdDataStream::PvdCommand
+{
+ ChangeOjectRefCmd& operator=(const ChangeOjectRefCmd&)
+ {
+ PX_ASSERT(0);
+ return *this;
+ } // PX_NOCOPY doesn't work for local classes
+ public:
+ const void* instance;
+ String propName;
+ const void* propObj;
+
+ ChangeOjectRefCmd(const void* inInst, String inName, const void* inObj)
+ : instance(inInst), propName(inName), propObj(inObj)
+ {
+ }
+
+ // Assigned is needed for copying
+ ChangeOjectRefCmd(const ChangeOjectRefCmd& other)
+ : instance(other.instance), propName(other.propName), propObj(other.propObj)
+ {
+ }
+
+ virtual bool canRun(PvdInstanceDataStream& inStream)
+ {
+ PX_ASSERT(inStream.isInstanceValid(instance));
+ return inStream.isInstanceValid(propObj);
+ }
+ virtual void run(PvdInstanceDataStream& inStream)
+ {
+ if(!inStream.isInstanceValid(instance))
+ return;
+
+ if(bPushBack)
+ {
+ if(inStream.isInstanceValid(propObj))
+ inStream.pushBackObjectRef(instance, propName, propObj);
+ }
+ else
+ {
+ // the called function will assert if propobj is already removed
+ inStream.removeObjectRef(instance, propName, propObj);
+ }
+ }
+};
+
+template <class Command>
+void changeAggregateSubActors(PvdDataStream& inStream, const PxAggregate& inObj, const PxActor& inActor)
+{
+ const PxArticulationLink* link = inActor.is<PxArticulationLink>();
+ String propName = NULL;
+ const void* object = NULL;
+ if(link == NULL)
+ {
+ propName = "Actors";
+ object = &inActor;
+ }
+ else if(link->getInboundJoint() == NULL)
+ {
+ propName = "Articulations";
+ object = &link->getArticulation();
+ }
+ else
+ return;
+
+ Command* cmd = PX_PLACEMENT_NEW(inStream.allocateMemForCmd(sizeof(Command)), Command)(&inObj, propName, object);
+
+ if(cmd->canRun(inStream))
+ cmd->run(inStream);
+ else
+ inStream.pushPvdCommand(*cmd);
+}
+void PvdMetaDataBinding::detachAggregateActor(PvdDataStream& inStream, const PxAggregate& inObj, const PxActor& inActor)
+{
+ typedef ChangeOjectRefCmd<false> RemoveOjectRefCmd;
+ changeAggregateSubActors<RemoveOjectRefCmd>(inStream, inObj, inActor);
+}
+
+void PvdMetaDataBinding::attachAggregateActor(PvdDataStream& inStream, const PxAggregate& inObj, const PxActor& inActor)
+{
+ typedef ChangeOjectRefCmd<true> PushbackOjectRefCmd;
+ changeAggregateSubActors<PushbackOjectRefCmd>(inStream, inObj, inActor);
+}
+#else
+void PvdMetaDataBinding::createInstance(PvdDataStream&, const PxAggregate&, const PxScene&, ObjectRegistrar&)
+{
+}
+
+void PvdMetaDataBinding::sendAllProperties(PvdDataStream&, const PxAggregate&)
+{
+}
+
+void PvdMetaDataBinding::destroyInstance(PvdDataStream&, const PxAggregate&, const PxScene&)
+{
+}
+
+void PvdMetaDataBinding::detachAggregateActor(PvdDataStream&, const PxAggregate&, const PxActor&)
+{
+}
+
+void PvdMetaDataBinding::attachAggregateActor(PvdDataStream&, const PxAggregate&, const PxActor&)
+{
+}
+#endif
+
+template <typename TDataType>
+void sendSceneArray(PvdDataStream& inStream, const PxScene& inScene, const Ps::Array<TDataType>& inArray, const char* propName)
+{
+ if(0 == inArray.size())
+ inStream.setPropertyValue(&inScene, propName, DataRef<const PxU8>(), getPvdNamespacedNameForType<TDataType>());
+ else
+ {
+ ScopedPropertyValueSender<TDataType, 32> sender(inStream, &inScene, propName);
+ for(PxU32 i = 0; i < inArray.size(); ++i)
+ sender.append(inArray[i]);
+ }
+}
+
+void sendSceneArray(PvdDataStream& inStream, const PxScene& inScene, const Ps::Array<PvdSqHit>& inArray, const char* propName)
+{
+ if(0 == inArray.size())
+ inStream.setPropertyValue(&inScene, propName, DataRef<const PxU8>(), getPvdNamespacedNameForType<PvdSqHit>());
+ else
+ {
+ ScopedPropertyValueSender<PvdSqHit, 32> sender(inStream, &inScene, propName);
+ for(PxU32 i = 0; i < inArray.size(); ++i)
+ {
+ if(!inStream.isInstanceValid(inArray[i].mShape) || !inStream.isInstanceValid(inArray[i].mActor))
+ {
+ PvdSqHit hit = inArray[i];
+ hit.mShape = NULL;
+ hit.mActor = NULL;
+ sender.append(hit);
+ }
+ else
+ sender.append(inArray[i]);
+ }
+ }
+}
+void PvdMetaDataBinding::sendSceneQueries(PvdDataStream& inStream, const PxScene& inScene, PsPvd* pvd)
+{
+ if(!inStream.isConnected())
+ return;
+
+ const physx::NpScene& scene = static_cast<const NpScene&>(inScene);
+
+ for(PxU32 i = 0; i < 2; i++)
+ {
+ PvdSceneQueryCollector& collector = ((i == 0) ? scene.getSingleSqCollector() : scene.getBatchedSqCollector());
+ Ps::Mutex::ScopedLock lock(collector.getLock());
+
+ String propName = collector.getArrayName(collector.mPvdSqHits);
+ sendSceneArray(inStream, inScene, collector.mPvdSqHits, propName);
+
+ propName = collector.getArrayName(collector.mPoses);
+ sendSceneArray(inStream, inScene, collector.mPoses, propName);
+
+ propName = collector.getArrayName(collector.mFilterData);
+ sendSceneArray(inStream, inScene, collector.mFilterData, propName);
+
+ const Ps::Array<PxGeometryHolder>& geometriesToDestroy = collector.getPrevFrameGeometries();
+ propName = collector.getArrayName(geometriesToDestroy);
+ for(PxU32 k = 0; k < geometriesToDestroy.size(); ++k)
+ {
+ const PxGeometryHolder& inObj = geometriesToDestroy[k];
+ inStream.removeObjectRef(&inScene, propName, &inObj);
+ inStream.destroyInstance(&inObj);
+ }
+ const Ps::Array<PxGeometryHolder>& geometriesToCreate = collector.getCurrentFrameGeometries();
+ for(PxU32 k = 0; k < geometriesToCreate.size(); ++k)
+ {
+ const PxGeometry& geometry = geometriesToCreate[k].any();
+ switch(geometry.getType())
+ {
+#define SEND_PVD_GEOM_TYPE(enumType, TGeomType, TValueType) \
+ case enumType: \
+ { \
+ const TGeomType& inObj = static_cast<const TGeomType&>(geometry); \
+ inStream.createInstance(getPvdNamespacedNameForType<TGeomType>(), &inObj); \
+ registrarPhysicsObject<TGeomType>(inStream, inObj, pvd); \
+ TValueType values(&inObj); \
+ inStream.setPropertyMessage(&inObj, values); \
+ inStream.pushBackObjectRef(&inScene, propName, &inObj); \
+ } \
+ break;
+ SEND_PVD_GEOM_TYPE(PxGeometryType::eBOX, PxBoxGeometry, PxBoxGeometryGeneratedValues)
+ SEND_PVD_GEOM_TYPE(PxGeometryType::eSPHERE, PxSphereGeometry, PxSphereGeometryGeneratedValues)
+ SEND_PVD_GEOM_TYPE(PxGeometryType::eCAPSULE, PxCapsuleGeometry, PxCapsuleGeometryGeneratedValues)
+ SEND_PVD_GEOM_TYPE(PxGeometryType::eCONVEXMESH, PxConvexMeshGeometry, PxConvexMeshGeometryGeneratedValues)
+#undef SEND_PVD_GEOM_TYPE
+ case PxGeometryType::ePLANE:
+ case PxGeometryType::eTRIANGLEMESH:
+ case PxGeometryType::eHEIGHTFIELD:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ PX_ALWAYS_ASSERT_MESSAGE("unsupported scene query geometry type");
+ break;
+ }
+ }
+ collector.prepareNextFrameGeometries();
+
+ propName = collector.getArrayName(collector.mAccumulatedRaycastQueries);
+ sendSceneArray(inStream, inScene, collector.mAccumulatedRaycastQueries, propName);
+
+ propName = collector.getArrayName(collector.mAccumulatedOverlapQueries);
+ sendSceneArray(inStream, inScene, collector.mAccumulatedOverlapQueries, propName);
+
+ propName = collector.getArrayName(collector.mAccumulatedSweepQueries);
+ sendSceneArray(inStream, inScene, collector.mAccumulatedSweepQueries, propName);
+ }
+}
+}
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/PvdMetaDataPvdBinding.h b/PhysX_3.4/Source/PhysX/src/PvdMetaDataPvdBinding.h
new file mode 100644
index 00000000..f76cb2f9
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/PvdMetaDataPvdBinding.h
@@ -0,0 +1,188 @@
+// 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_META_DATA_PVD_BINDING_H
+#define PX_META_DATA_PVD_BINDING_H
+
+#if PX_SUPPORT_PVD
+
+#include "PxPhysXConfig.h"
+#include "PsArray.h"
+
+namespace physx
+{
+ namespace pvdsdk
+ {
+ class PsPvd;
+ class PvdDataStream;
+ struct PvdMetaDataBindingData;
+ }
+}
+
+namespace physx
+{
+
+namespace Sc
+{
+struct Contact;
+struct ClothBulkData;
+}
+
+namespace Vd
+{
+
+using namespace physx::pvdsdk;
+
+class PvdVisualizer
+{
+ protected:
+ virtual ~PvdVisualizer()
+ {
+ }
+
+ public:
+ virtual void visualize(PxArticulationLink& link) = 0;
+};
+
+class PvdMetaDataBinding
+{
+ PvdMetaDataBindingData* mBindingData;
+
+ public:
+ PvdMetaDataBinding();
+ ~PvdMetaDataBinding();
+ void registerSDKProperties(PvdDataStream& inStream);
+
+ void sendAllProperties(PvdDataStream& inStream, const PxPhysics& inPhysics);
+
+ void sendAllProperties(PvdDataStream& inStream, const PxScene& inScene);
+ // per frame update
+ void sendBeginFrame(PvdDataStream& inStream, const PxScene* inScene, PxReal simulateElapsedTime);
+ void sendContacts(PvdDataStream& inStream, const PxScene& inScene, shdfnd::Array<Sc::Contact>& inContacts);
+ void sendContacts(PvdDataStream& inStream, const PxScene& inScene);
+ void sendSceneQueries(PvdDataStream& inStream, const PxScene& inScene, PsPvd* pvd);
+ void sendStats(PvdDataStream& inStream, const PxScene* inScene, void* triMeshCacheStats);
+ void sendEndFrame(PvdDataStream& inStream, const PxScene* inScene);
+
+ void createInstance(PvdDataStream& inStream, const PxMaterial& inMaterial, const PxPhysics& ownerPhysics);
+ void sendAllProperties(PvdDataStream& inStream, const PxMaterial& inMaterial);
+ void destroyInstance(PvdDataStream& inStream, const PxMaterial& inMaterial, const PxPhysics& ownerPhysics);
+
+ void createInstance(PvdDataStream& inStream, const PxHeightField& inData, const PxPhysics& ownerPhysics);
+ void sendAllProperties(PvdDataStream& inStream, const PxHeightField& inData);
+ void destroyInstance(PvdDataStream& inStream, const PxHeightField& inData, const PxPhysics& ownerPhysics);
+
+ void createInstance(PvdDataStream& inStream, const PxConvexMesh& inData, const PxPhysics& ownerPhysics);
+ void destroyInstance(PvdDataStream& inStream, const PxConvexMesh& inData, const PxPhysics& ownerPhysics);
+
+ void createInstance(PvdDataStream& inStream, const PxTriangleMesh& inData, const PxPhysics& ownerPhysics);
+ void destroyInstance(PvdDataStream& inStream, const PxTriangleMesh& inData, const PxPhysics& ownerPhysics);
+
+ void createInstance(PvdDataStream& inStream, const PxRigidStatic& inObj, const PxScene& ownerScene, PsPvd* pvd);
+ void sendAllProperties(PvdDataStream& inStream, const PxRigidStatic& inObj);
+ void destroyInstance(PvdDataStream& inStream, const PxRigidStatic& inObj, const PxScene& ownerScene);
+
+ void createInstance(PvdDataStream& inStream, const PxRigidDynamic& inObj, const PxScene& ownerScene, PsPvd* pvd);
+ void sendAllProperties(PvdDataStream& inStream, const PxRigidDynamic& inObj);
+ void destroyInstance(PvdDataStream& inStream, const PxRigidDynamic& inObj, const PxScene& ownerScene);
+
+ void createInstance(PvdDataStream& inStream, const PxArticulation& inObj, const PxScene& ownerScene, PsPvd* pvd);
+ void sendAllProperties(PvdDataStream& inStream, const PxArticulation& inObj);
+ void destroyInstance(PvdDataStream& inStream, const PxArticulation& inObj, const PxScene& ownerScene);
+
+ void createInstance(PvdDataStream& inStream, const PxArticulationLink& inObj, PsPvd* pvd);
+ void sendAllProperties(PvdDataStream& inStream, const PxArticulationLink& inObj);
+ void destroyInstance(PvdDataStream& inStream, const PxArticulationLink& inObj);
+
+ void createInstance(PvdDataStream& inStream, const PxShape& inObj, const PxRigidActor& owner, PsPvd* pvd);
+ void sendAllProperties(PvdDataStream& inStream, const PxShape& inObj);
+ void releaseAndRecreateGeometry(PvdDataStream& inStream, const PxShape& inObj, PxPhysics& ownerPhysics, PsPvd* pvd);
+ void updateMaterials(PvdDataStream& inStream, const PxShape& inObj, PsPvd* pvd);
+ void destroyInstance(PvdDataStream& inStream, const PxShape& inObj, const PxRigidActor& owner);
+
+ // These are created as part of the articulation link's creation process, so outside entities don't need to
+ // create them.
+ void sendAllProperties(PvdDataStream& inStream, const PxArticulationJoint& inObj);
+
+ // per frame update
+ void updateDynamicActorsAndArticulations(PvdDataStream& inStream, const PxScene* inScene, PvdVisualizer* linkJointViz);
+
+ // Origin Shift
+ void originShift(PvdDataStream& inStream, const PxScene* inScene, PxVec3 shift);
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ void createInstance(PvdDataStream& inStream, const PxParticleSystem& inObj, const PxScene& ownerScene);
+ void sendAllProperties(PvdDataStream& inStream, const PxParticleSystem& inObj);
+ // per frame update
+ void sendArrays(PvdDataStream& inStream, const PxParticleSystem& inObj, PxParticleReadData& inData, PxU32 inFlags);
+ void destroyInstance(PvdDataStream& inStream, const PxParticleSystem& inObj, const PxScene& ownerScene);
+
+ void createInstance(PvdDataStream& inStream, const PxParticleFluid& inObj, const PxScene& ownerScene);
+ void sendAllProperties(PvdDataStream& inStream, const PxParticleFluid& inObj);
+ // per frame update
+ void sendArrays(PvdDataStream& inStream, const PxParticleFluid& inObj, PxParticleFluidReadData& inData,
+ PxU32 inFlags);
+ void destroyInstance(PvdDataStream& inStream, const PxParticleFluid& inObj, const PxScene& ownerScene);
+#endif
+
+#if PX_USE_CLOTH_API
+ void createInstance(PvdDataStream& inStream, const PxClothFabric& fabric, const PxPhysics& ownerPhysics);
+ void sendAllProperties(PvdDataStream& inStream, const PxClothFabric& fabric);
+ void destroyInstance(PvdDataStream& inStream, const PxClothFabric& fabric, const PxPhysics& ownerPhysics);
+
+ void createInstance(PvdDataStream& inStream, const PxCloth& cloth, const PxScene& ownerScene, PsPvd* pvd);
+ void sendAllProperties(PvdDataStream& inStream, const PxCloth& cloth);
+ void sendSimpleProperties(PvdDataStream& inStream, const PxCloth& cloth);
+ void sendMotionConstraints(PvdDataStream& inStream, const PxCloth& cloth);
+ void sendCollisionSpheres(PvdDataStream& inStream, const PxCloth& cloth, bool sendPairs = true);
+ void sendCollisionTriangles(PvdDataStream& inStream, const PxCloth& cloth);
+ void sendVirtualParticles(PvdDataStream& inStream, const PxCloth& cloth);
+ void sendSeparationConstraints(PvdDataStream& inStream, const PxCloth& cloth);
+ void sendRestPositions(PvdDataStream& inStream, const PxCloth& cloth);
+ void sendSelfCollisionIndices(PvdDataStream& inStream, const PxCloth& cloth);
+ void sendParticleAccelerations(PvdDataStream& inStream, const PxCloth& cloth);
+ // per frame update
+ void updateCloths(PvdDataStream& inStream, const PxScene& inScene);
+ void destroyInstance(PvdDataStream& inStream, const PxCloth& cloth, const PxScene& ownerScene);
+#endif
+
+ void createInstance(PvdDataStream& inStream, const PxAggregate& inObj, const PxScene& ownerScene);
+ void sendAllProperties(PvdDataStream& inStream, const PxAggregate& inObj);
+ void destroyInstance(PvdDataStream& inStream, const PxAggregate& inObj, const PxScene& ownerScene);
+ void detachAggregateActor(PvdDataStream& inStream, const PxAggregate& inObj, const PxActor& inActor);
+ void attachAggregateActor(PvdDataStream& inStream, const PxAggregate& inObj, const PxActor& inActor);
+
+ template <typename TDataType>
+ void registrarPhysicsObject(PvdDataStream&, const TDataType&, PsPvd*);
+};
+}
+}
+
+#endif
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/PvdPhysicsClient.cpp b/PhysX_3.4/Source/PhysX/src/PvdPhysicsClient.cpp
new file mode 100644
index 00000000..cd73cf60
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/PvdPhysicsClient.cpp
@@ -0,0 +1,243 @@
+// 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.
+
+// PX_DUMMY_SYMBOL
+
+#if PX_SUPPORT_PVD
+
+#include "pvd/PxPvdTransport.h"
+#include "PxPhysics.h"
+#include "PxPvdClient.h"
+#include "PxPvdDataStream.h"
+#include "PxPvdObjectModelBaseTypes.h"
+#include "PvdPhysicsClient.h"
+#include "PvdTypeNames.h"
+
+using namespace physx;
+using namespace physx::Vd;
+
+PvdPhysicsClient::PvdPhysicsClient(PsPvd* pvd)
+: mPvd(pvd), mPvdDataStream(NULL), mIsConnected(false)
+{
+}
+
+PvdPhysicsClient::~PvdPhysicsClient()
+{
+ mPvd->removeClient(this);
+}
+
+PvdDataStream* PvdPhysicsClient::getDataStream()
+{
+ return mPvdDataStream;
+}
+
+PvdMetaDataBinding* PvdPhysicsClient::getMetaDataBinding()
+{
+ return &mMetaDataBinding;
+}
+
+PvdUserRenderer* PvdPhysicsClient::getUserRender()
+{
+ PX_ASSERT(0);
+ return NULL;
+}
+
+bool PvdPhysicsClient::isConnected() const
+{
+ return mIsConnected;
+}
+
+void PvdPhysicsClient::onPvdConnected()
+{
+ if(mIsConnected || !mPvd)
+ return;
+
+ mIsConnected = true;
+ mPvdDataStream = PvdDataStream::create(mPvd);
+ sendEntireSDK();
+}
+
+void PvdPhysicsClient::onPvdDisconnected()
+{
+ if(!mIsConnected)
+ return;
+ mIsConnected = false;
+
+ mPvdDataStream->release();
+ mPvdDataStream = NULL;
+}
+
+void PvdPhysicsClient::flush()
+{
+}
+
+void PvdPhysicsClient::sendEntireSDK()
+{
+ PxPhysics& physics = PxGetPhysics();
+
+ mMetaDataBinding.registerSDKProperties(*mPvdDataStream);
+ mPvdDataStream->createInstance(&physics);
+
+ mPvdDataStream->setIsTopLevelUIElement(&physics, true);
+ mMetaDataBinding.sendAllProperties(*mPvdDataStream, physics);
+
+#define SEND_BUFFER_GROUP(type, name) \
+ { \
+ physx::shdfnd::Array<type*> buffers; \
+ PxU32 numBuffers = physics.getNb##name(); \
+ buffers.resize(numBuffers); \
+ physics.get##name(buffers.begin(), numBuffers); \
+ for(PxU32 i = 0; i < numBuffers; i++) \
+ { \
+ if(mPvd->registerObject(buffers[i])) \
+ createPvdInstance(buffers[i]); \
+ } \
+ }
+
+ SEND_BUFFER_GROUP(PxMaterial, Materials);
+ SEND_BUFFER_GROUP(PxTriangleMesh, TriangleMeshes);
+ SEND_BUFFER_GROUP(PxConvexMesh, ConvexMeshes);
+ SEND_BUFFER_GROUP(PxHeightField, HeightFields);
+
+#if PX_USE_CLOTH_API
+ SEND_BUFFER_GROUP(PxClothFabric, ClothFabrics);
+#endif
+}
+
+void PvdPhysicsClient::destroyPvdInstance(const PxPhysics* physics)
+{
+ if(mPvdDataStream)
+ mPvdDataStream->destroyInstance(physics);
+}
+
+void PvdPhysicsClient::createPvdInstance(const PxTriangleMesh* triMesh)
+{
+ mMetaDataBinding.createInstance(*mPvdDataStream, *triMesh, PxGetPhysics());
+}
+
+void PvdPhysicsClient::destroyPvdInstance(const PxTriangleMesh* triMesh)
+{
+ mMetaDataBinding.destroyInstance(*mPvdDataStream, *triMesh, PxGetPhysics());
+}
+
+void PvdPhysicsClient::createPvdInstance(const PxConvexMesh* convexMesh)
+{
+ mMetaDataBinding.createInstance(*mPvdDataStream, *convexMesh, PxGetPhysics());
+}
+
+void PvdPhysicsClient::destroyPvdInstance(const PxConvexMesh* convexMesh)
+{
+ mMetaDataBinding.destroyInstance(*mPvdDataStream, *convexMesh, PxGetPhysics());
+}
+
+void PvdPhysicsClient::createPvdInstance(const PxHeightField* heightField)
+{
+ mMetaDataBinding.createInstance(*mPvdDataStream, *heightField, PxGetPhysics());
+}
+
+void PvdPhysicsClient::destroyPvdInstance(const PxHeightField* heightField)
+{
+ mMetaDataBinding.destroyInstance(*mPvdDataStream, *heightField, PxGetPhysics());
+}
+
+void PvdPhysicsClient::createPvdInstance(const PxMaterial* mat)
+{
+ mMetaDataBinding.createInstance(*mPvdDataStream, *mat, PxGetPhysics());
+}
+
+void PvdPhysicsClient::updatePvdProperties(const PxMaterial* mat)
+{
+ mMetaDataBinding.sendAllProperties(*mPvdDataStream, *mat);
+}
+
+void PvdPhysicsClient::destroyPvdInstance(const PxMaterial* mat)
+{
+ mMetaDataBinding.destroyInstance(*mPvdDataStream, *mat, PxGetPhysics());
+}
+
+#if PX_USE_CLOTH_API
+void PvdPhysicsClient::createPvdInstance(const PxClothFabric* fabric)
+{
+ mMetaDataBinding.createInstance(*mPvdDataStream, *fabric, PxGetPhysics());
+ // Physics level buffer object update, must be flushed immediatedly.
+}
+
+void PvdPhysicsClient::destroyPvdInstance(const PxClothFabric* fabric)
+{
+ mMetaDataBinding.destroyInstance(*mPvdDataStream, *fabric, PxGetPhysics());
+ // Physics level buffer object update, must be flushed immediatedly.
+}
+#endif
+
+void PvdPhysicsClient::onGuMeshFactoryBufferRelease(const PxBase* object, PxType typeID)
+{
+ if(!mIsConnected || !mPvd)
+ return;
+
+ if(mPvd->unRegisterObject(object))
+ {
+ switch(typeID)
+ {
+ case PxConcreteType::eHEIGHTFIELD:
+ destroyPvdInstance(static_cast<const PxHeightField*>(object));
+ break;
+
+ case PxConcreteType::eCONVEX_MESH:
+ destroyPvdInstance(static_cast<const PxConvexMesh*>(object));
+ break;
+
+ case PxConcreteType::eTRIANGLE_MESH_BVH33:
+ case PxConcreteType::eTRIANGLE_MESH_BVH34:
+ destroyPvdInstance(static_cast<const PxTriangleMesh*>(object));
+ break;
+
+ default:
+ break;
+ }
+ }
+}
+#if PX_USE_CLOTH_API
+void PvdPhysicsClient::onNpFactoryBufferRelease(PxClothFabric& data)
+{
+ if(!mIsConnected || !mPvd)
+ return;
+ if(mPvd->unRegisterObject(&data))
+ destroyPvdInstance(&data);
+}
+#endif
+
+void PvdPhysicsClient::reportError(PxErrorCode::Enum code, const char* message, const char* file, int line)
+{
+ if(mIsConnected)
+ {
+ mPvdDataStream->sendErrorMessage(code, message, file, PxU32(line));
+ }
+}
+
+#endif // PX_SUPPORT_PVD
diff --git a/PhysX_3.4/Source/PhysX/src/PvdPhysicsClient.h b/PhysX_3.4/Source/PhysX/src/PvdPhysicsClient.h
new file mode 100644
index 00000000..36ac4b81
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/PvdPhysicsClient.h
@@ -0,0 +1,103 @@
+// 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 PVD_PHYSICS_CLIENT_H
+#define PVD_PHYSICS_CLIENT_H
+#if PX_SUPPORT_PVD
+#include "foundation/PxErrorCallback.h"
+#include "PxPvdClient.h"
+#include "PvdMetaDataPvdBinding.h"
+#include "NpFactory.h"
+#include "PsHashMap.h"
+#include "PsMutex.h"
+#include "PsPvd.h"
+
+namespace physx
+{
+class PxProfileMemoryEventBuffer;
+
+namespace Vd
+{
+
+class PvdPhysicsClient : public PvdClient, public PxErrorCallback, public NpFactoryListener, public shdfnd::UserAllocated
+{
+ PX_NOCOPY(PvdPhysicsClient)
+ public:
+ PvdPhysicsClient(PsPvd* pvd);
+ virtual ~PvdPhysicsClient();
+
+ bool isConnected() const;
+ void onPvdConnected();
+ void onPvdDisconnected();
+ void flush();
+
+ PsPvd* getPsPvd();
+ physx::pvdsdk::PvdDataStream* getDataStream();
+ PvdMetaDataBinding* getMetaDataBinding();
+ PvdUserRenderer* getUserRender();
+
+ void sendEntireSDK();
+ void destroyPvdInstance(const PxPhysics* physics);
+
+ // NpFactoryListener
+ virtual void onGuMeshFactoryBufferRelease(const PxBase* object, PxType typeID);
+#if PX_USE_CLOTH_API
+ virtual void onNpFactoryBufferRelease(PxClothFabric& data);
+#endif
+ /// NpFactoryListener
+
+ // PxErrorCallback
+ void reportError(PxErrorCode::Enum code, const char* message, const char* file, int line);
+
+ private:
+ void createPvdInstance(const PxTriangleMesh* triMesh);
+ void destroyPvdInstance(const PxTriangleMesh* triMesh);
+ void createPvdInstance(const PxConvexMesh* convexMesh);
+ void destroyPvdInstance(const PxConvexMesh* convexMesh);
+ void createPvdInstance(const PxHeightField* heightField);
+ void destroyPvdInstance(const PxHeightField* heightField);
+ void createPvdInstance(const PxMaterial* mat);
+ void destroyPvdInstance(const PxMaterial* mat);
+ void updatePvdProperties(const PxMaterial* mat);
+#if PX_USE_CLOTH_API
+ void createPvdInstance(const PxClothFabric* fabric);
+ void destroyPvdInstance(const PxClothFabric* fabric);
+#endif
+
+ PsPvd* mPvd;
+ PvdDataStream* mPvdDataStream;
+ PvdMetaDataBinding mMetaDataBinding;
+ bool mIsConnected;
+};
+
+} // namespace Vd
+} // namespace physx
+
+#endif // PX_SUPPORT_PVD
+#endif // PVD_PHYSICS_CLIENT_H
diff --git a/PhysX_3.4/Source/PhysX/src/PvdTypeNames.h b/PhysX_3.4/Source/PhysX/src/PvdTypeNames.h
new file mode 100644
index 00000000..0b5abe17
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/PvdTypeNames.h
@@ -0,0 +1,189 @@
+// 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 PVD_TYPE_NAMES_H
+#define PVD_TYPE_NAMES_H
+#if PX_SUPPORT_PVD
+#include "PxPhysicsAPI.h"
+#include "PxPvdObjectModelBaseTypes.h"
+#include "PxMetaDataObjects.h"
+#include "PxHeightFieldSample.h"
+
+namespace physx
+{
+namespace Vd
+{
+struct PvdSqHit;
+struct PvdRaycast;
+struct PvdOverlap;
+struct PvdSweep;
+
+struct PvdHullPolygonData
+{
+ PxU16 mNumVertices;
+ PxU16 mIndexBase;
+ PvdHullPolygonData(PxU16 numVert, PxU16 idxBase) : mNumVertices(numVert), mIndexBase(idxBase)
+ {
+ }
+};
+
+
+struct PxArticulationLinkUpdateBlock
+{
+ PxTransform GlobalPose;
+ PxVec3 LinearVelocity;
+ PxVec3 AngularVelocity;
+};
+struct PxRigidDynamicUpdateBlock : public PxArticulationLinkUpdateBlock
+{
+ bool IsSleeping;
+};
+
+struct PvdContact
+{
+ PxVec3 point;
+ PxVec3 axis;
+ const void* shape0;
+ const void* shape1;
+ PxF32 separation;
+ PxF32 normalForce;
+ PxU32 internalFaceIndex0;
+ PxU32 internalFaceIndex1;
+ bool normalForceAvailable;
+};
+
+struct PvdPositionAndRadius
+{
+ PxVec3 position;
+ PxF32 radius;
+};
+
+} //Vd
+} //physx
+
+namespace physx
+{
+namespace pvdsdk
+{
+
+#define DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(type) DEFINE_PVD_TYPE_NAME_MAP(physx::type, "physx3", #type)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxPhysics)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxScene)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxTolerancesScale)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxTolerancesScaleGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSceneDescGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSceneDesc)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSimulationStatistics)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSimulationStatisticsGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxMaterial)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxMaterialGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxHeightField)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxHeightFieldDesc)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxHeightFieldDescGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxTriangleMesh)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxConvexMesh)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxActor)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRigidActor)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRigidBody)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRigidDynamic)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRigidDynamicGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRigidStatic)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRigidStaticGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxShape)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxShapeGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxGeometry)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxBoxGeometry)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxPlaneGeometry)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxCapsuleGeometry)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSphereGeometry)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxHeightFieldGeometry)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxTriangleMeshGeometry)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxConvexMeshGeometry)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxBoxGeometryGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxPlaneGeometryGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxCapsuleGeometryGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSphereGeometryGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxHeightFieldGeometryGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxTriangleMeshGeometryGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxConvexMeshGeometryGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxHeightFieldSample)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxConstraint)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxConstraintGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxArticulation)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxArticulationGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxArticulationLink)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxArticulationLinkGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxArticulationJoint)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxArticulationJointGeneratedValues)
+#if PX_USE_PARTICLE_SYSTEM_API
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxParticleBase)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxParticleSystem)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxParticleSystemGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxParticleFluid)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxParticleFluidGeneratedValues)
+#endif
+
+#if PX_USE_CLOTH_API
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxClothFabric)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxClothFabricPhase)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxClothFabricPhaseGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxClothFabricGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxCloth)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxClothGeneratedValues)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxClothParticle)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxClothStretchConfig)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxClothTetherConfig)
+#endif
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxAggregate)
+DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxAggregateGeneratedValues)
+
+#undef DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP
+
+#define DEFINE_NATIVE_PVD_TYPE_MAP(type) DEFINE_PVD_TYPE_NAME_MAP(physx::Vd::type, "physx3", #type)
+DEFINE_NATIVE_PVD_TYPE_MAP(PvdHullPolygonData)
+DEFINE_NATIVE_PVD_TYPE_MAP(PxRigidDynamicUpdateBlock)
+DEFINE_NATIVE_PVD_TYPE_MAP(PxArticulationLinkUpdateBlock)
+DEFINE_NATIVE_PVD_TYPE_MAP(PvdContact)
+DEFINE_NATIVE_PVD_TYPE_MAP(PvdRaycast)
+DEFINE_NATIVE_PVD_TYPE_MAP(PvdSweep)
+DEFINE_NATIVE_PVD_TYPE_MAP(PvdOverlap)
+DEFINE_NATIVE_PVD_TYPE_MAP(PvdSqHit)
+DEFINE_NATIVE_PVD_TYPE_MAP(PvdPositionAndRadius)
+
+#undef DEFINE_NATIVE_PVD_TYPE_MAP
+
+
+DEFINE_PVD_TYPE_ALIAS(physx::PxFilterData, U32Array4)
+
+
+}
+}
+
+#endif
+
+#endif
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
diff --git a/PhysX_3.4/Source/PhysX/src/cloth/NpCloth.cpp b/PhysX_3.4/Source/PhysX/src/cloth/NpCloth.cpp
new file mode 100644
index 00000000..45b6beed
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/cloth/NpCloth.cpp
@@ -0,0 +1,1342 @@
+// 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 "NpCloth.h"
+#include "NpClothFabric.h"
+#include "NpScene.h"
+#include "NpPhysics.h"
+
+using namespace physx;
+
+// PX_SERIALIZATION
+NpCloth::NpCloth(PxBaseFlags baseFlags) : NpClothT(baseFlags), mCloth(PxEmpty), mParticleData(*this)
+{
+}
+//~PX_SERIALIZATION
+
+NpCloth::NpCloth(const PxTransform& globalPose, NpClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags) :
+ NpClothT(PxConcreteType::eCLOTH, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE, NULL, NULL),
+ mCloth(globalPose, fabric.getScClothFabric(), particles, flags),
+ mClothFabric(&fabric),
+ mParticleData(*this)
+{
+ fabric.incRefCount();
+}
+
+NpCloth::~NpCloth()
+{
+ // ScClothCore deletion is buffered, but ScClothFabricCore is not
+ // make sure we don't have a dangling pointer in ScClothCore.
+ if(1 == mClothFabric->getRefCount())
+ mCloth.resetFabric();
+
+ mClothFabric->decRefCount();
+}
+
+// PX_SERIALIZATION
+void NpCloth::resolveReferences(PxDeserializationContext& context)
+{
+ context.translatePxBase(mClothFabric);
+ mClothFabric->incRefCount();
+
+ // pass fabric down to Scb
+ mCloth.resolveReferences(mClothFabric->getScClothFabric());
+}
+
+void NpCloth::requires(PxProcessPxBaseCallback& c)
+{
+ c.process(*mClothFabric);
+}
+
+NpCloth* NpCloth::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpCloth* obj = new (address) NpCloth(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpCloth);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+void NpCloth::release()
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ NpPhysics::getInstance().notifyDeletionListenersUserRelease(this, userData);
+
+// PX_AGGREGATE
+ // initially no support for aggregates
+ //NpClothT::release(); // PT: added for PxAggregate
+//~PX_AGGREGATE
+
+ NpScene* npScene = NpActor::getAPIScene(*this);
+ if(npScene) // scene is 0 after scheduling for remove
+ npScene->removeCloth(*this);
+
+ mCloth.destroy();
+}
+
+
+PxActorType::Enum NpCloth::getType() const
+{
+ return PxActorType::eCLOTH;
+}
+
+
+PxClothFabric* NpCloth::getFabric() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ Sc::ClothFabricCore* scFabric = mCloth.getFabric();
+
+ size_t scOffset = reinterpret_cast<size_t>(&(reinterpret_cast<NpClothFabric*>(0)->getScClothFabric()));
+ return reinterpret_cast<NpClothFabric*>(reinterpret_cast<char*>(scFabric)-scOffset);
+}
+
+
+void NpCloth::setParticles(const PxClothParticle* currentParticles, const PxClothParticle* previousParticles)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+#if PX_CHECKED
+ if (currentParticles)
+ PX_CHECK_AND_RETURN(checkParticles(mCloth.getNbParticles(), currentParticles), "PxCloth::setParticles: values must be finite and inverse weight must not be negative");
+ if (previousParticles)
+ PX_CHECK_AND_RETURN(checkParticles(mCloth.getNbParticles(), previousParticles), "PxCloth::setParticles: values must be finite and inverse weight must not be negative");
+#endif
+
+ mCloth.setParticles(currentParticles, previousParticles);
+}
+
+PxU32 NpCloth::getNbParticles() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getNbParticles();
+}
+
+void NpCloth::setMotionConstraints(const PxClothParticleMotionConstraint* motionConstraints)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN(checkMotionConstraints(mCloth.getNbParticles(), motionConstraints), "PxCloth::setMotionConstraints: values must be finite and radius must not be negative");
+#endif
+
+ mCloth.setMotionConstraints(motionConstraints);
+ sendPvdMotionConstraints();
+}
+
+
+bool NpCloth::getMotionConstraints(PxClothParticleMotionConstraint* motionConstraintsBuffer) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_MSG(motionConstraintsBuffer || !getNbMotionConstraints(), "PxCloth::getMotionConstraints: no motion constraint buffer provided!");
+
+ return mCloth.getMotionConstraints(motionConstraintsBuffer);
+}
+
+PxU32 NpCloth::getNbMotionConstraints() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getNbMotionConstraints();
+}
+
+void NpCloth::setMotionConstraintConfig(const PxClothMotionConstraintConfig& config)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN((config.scale >= 0.0f), "PxCloth::setMotionConstraintConfig: scale must not be negative!");
+
+ mCloth.setMotionConstraintConfig(config);
+ sendPvdSimpleProperties();
+}
+
+
+PxClothMotionConstraintConfig NpCloth::getMotionConstraintConfig() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getMotionConstraintConfig();
+}
+
+void NpCloth::setSeparationConstraints(const PxClothParticleSeparationConstraint* separationConstraints)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN(checkSeparationConstraints(mCloth.getNbParticles(), separationConstraints), "PxCloth::setSeparationConstraints: values must be finite and radius must not be negative");
+#endif
+
+ mCloth.setSeparationConstraints(separationConstraints);
+ sendPvdSeparationConstraints();
+}
+
+
+bool NpCloth::getSeparationConstraints(PxClothParticleSeparationConstraint* separationConstraintsBuffer) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_MSG(separationConstraintsBuffer || !getNbSeparationConstraints(), "PxCloth::getSeparationConstraints: no separation constraint buffer provided!");
+
+ return mCloth.getSeparationConstraints(separationConstraintsBuffer);
+}
+
+PxU32 NpCloth::getNbSeparationConstraints() const
+{
+ return mCloth.getNbSeparationConstraints();
+}
+
+void NpCloth::clearInterpolation()
+{
+ return mCloth.clearInterpolation();
+}
+
+void NpCloth::setParticleAccelerations(const PxVec4* particleAccelerations)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN(checkParticleAccelerations(mCloth.getNbParticles(), particleAccelerations), "PxCloth::setParticleAccelerations: values must be finite");
+#endif
+
+ mCloth.setParticleAccelerations(particleAccelerations);
+
+ //TODO: PVD support for particle accelerations
+ //sendPvdParticleAccelerations();
+}
+
+
+bool NpCloth::getParticleAccelerations(PxVec4* particleAccelerationsBuffer) const
+{
+ PX_CHECK_MSG(particleAccelerationsBuffer, "PxCloth::getParticleAccelerations: no particle accelerations buffer provided!");
+
+ return mCloth.getParticleAccelerations(particleAccelerationsBuffer);
+}
+
+PxU32 NpCloth::getNbParticleAccelerations() const
+{
+ return mCloth.getNbParticleAccelerations();
+}
+
+
+void NpCloth::addCollisionSphere(const PxClothCollisionSphere& sphere)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(mCloth.getNbCollisionSpheres() < 32, "PxCloth::addCollisionSphere: more than 32 spheres is not supported");
+ PX_CHECK_AND_RETURN(checkCollisionSpheres(1, &sphere), "PxCloth::addCollisionSphere: position must be finite and radius must not be negative");
+
+ mCloth.addCollisionSphere(sphere);
+}
+void NpCloth::removeCollisionSphere(PxU32 index)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.removeCollisionSphere(index);
+}
+void NpCloth::setCollisionSpheres(const PxClothCollisionSphere* spheresBuffer, PxU32 count)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN(count <= 32, "PxCloth::setCollisionSpheres: more than 32 spheres is not supported");
+ PX_CHECK_AND_RETURN(checkCollisionSpheres(count, spheresBuffer), "PxCloth::setCollisionSpheres: positions must be finite and radius must not be negative");
+#endif
+
+ mCloth.setCollisionSpheres(spheresBuffer, count);
+ sendPvdCollisionSpheres();
+}
+PxU32 NpCloth::getNbCollisionSpheres() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getNbCollisionSpheres();
+}
+
+void NpCloth::getCollisionData(PxClothCollisionSphere* spheresBuffer, PxU32* capsulesBuffer,
+ PxClothCollisionPlane* planesBuffer, PxU32* convexesBuffer, PxClothCollisionTriangle* trianglesBuffer) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.getCollisionData(spheresBuffer, capsulesBuffer, planesBuffer, convexesBuffer, trianglesBuffer);
+}
+
+
+void NpCloth::addCollisionCapsule(PxU32 first, PxU32 second)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(mCloth.getNbCollisionCapsules() < 32, "PxCloth::addCollisionCapsule: more than 32 capsules is not supported");
+
+ mCloth.addCollisionCapsule(first, second);
+
+ sendPvdCollisionCapsules();
+}
+void NpCloth::removeCollisionCapsule(PxU32 index)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.removeCollisionCapsule(index);
+
+ sendPvdCollisionCapsules();
+}
+PxU32 NpCloth::getNbCollisionCapsules() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getNbCollisionCapsules();
+}
+
+void NpCloth::addCollisionTriangle(const PxClothCollisionTriangle& triangle)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.addCollisionTriangle(triangle);
+ sendPvdCollisionTriangles();
+}
+void NpCloth::removeCollisionTriangle(PxU32 index)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.removeCollisionTriangle(index);
+ sendPvdCollisionTriangles();
+}
+void NpCloth::setCollisionTriangles(const PxClothCollisionTriangle* trianglesBuffer, PxU32 count)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.setCollisionTriangles(trianglesBuffer, count);
+ sendPvdCollisionTriangles();
+}
+PxU32 NpCloth::getNbCollisionTriangles() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getNbCollisionTriangles();
+}
+
+void NpCloth::addCollisionPlane(const PxClothCollisionPlane& plane)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(mCloth.getNbCollisionPlanes() < 32, "PxCloth::addCollisionPlane: more than 32 planes is not supported");
+
+ mCloth.addCollisionPlane(plane);
+ sendPvdCollisionTriangles();
+}
+void NpCloth::removeCollisionPlane(PxU32 index)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.removeCollisionPlane(index);
+ sendPvdCollisionTriangles();
+}
+void NpCloth::setCollisionPlanes(const PxClothCollisionPlane* planesBuffer, PxU32 count)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(count <= 32, "PxCloth::setCollisionPlanes: more than 32 planes is not supported");
+
+ mCloth.setCollisionPlanes(planesBuffer, count);
+ sendPvdCollisionTriangles();
+}
+PxU32 NpCloth::getNbCollisionPlanes() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getNbCollisionPlanes();
+}
+
+void NpCloth::addCollisionConvex(PxU32 mask)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.addCollisionConvex(mask);
+ sendPvdCollisionTriangles();
+}
+void NpCloth::removeCollisionConvex(PxU32 index)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.removeCollisionConvex(index);
+ sendPvdCollisionTriangles();
+}
+PxU32 NpCloth::getNbCollisionConvexes() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getNbCollisionConvexes();
+}
+
+void NpCloth::setVirtualParticles(PxU32 numParticles, const PxU32* indices, PxU32 numWeights, const PxVec3* weights)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_MSG(indices, "PxCloth::setVirtualParticles: no triangle vertex and weight index buffer provided!");
+ PX_CHECK_MSG(weights, "PxCloth::setVirtualParticles: no triangle vertex weight buffer provided!");
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN(checkVirtualParticles(mCloth.getNbParticles(), numParticles, indices, numWeights, weights),
+ "PxCloth::setVirtualParticles: out of range value detected");
+#endif
+
+ mCloth.setVirtualParticles(numParticles, indices, numWeights, weights);
+ sendPvdVirtualParticles();
+}
+
+
+PxU32 NpCloth::getNbVirtualParticles() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getNbVirtualParticles();
+}
+
+
+void NpCloth::getVirtualParticles(PxU32* indicesBuffer) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_MSG(indicesBuffer, "PxCloth::getVirtualParticles: no triangle vertex and weight index buffer provided!");
+
+ mCloth.getVirtualParticles(indicesBuffer);
+}
+
+
+PxU32 NpCloth::getNbVirtualParticleWeights() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getNbVirtualParticleWeights();
+}
+
+
+void NpCloth::getVirtualParticleWeights(PxVec3* weightsBuffer) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_MSG(weightsBuffer, "PxCloth::getVirtualParticleWeights: no triangle vertex weight buffer provided!");
+
+ mCloth.getVirtualParticleWeights(weightsBuffer);
+}
+
+
+void NpCloth::setGlobalPose(const PxTransform& pose)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(pose.isSane(), "PxCloth::setGlobalPose: invalid transform!");
+
+ mCloth.setGlobalPose(pose.getNormalized());
+ sendPvdSimpleProperties();
+}
+
+
+PxTransform NpCloth::getGlobalPose() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getGlobalPose();
+}
+
+
+void NpCloth::setTargetPose(const PxTransform& pose)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(pose.isSane(), "PxCloth::setTargetPose: invalid transform!");
+
+ mCloth.setTargetPose(pose.getNormalized());
+ sendPvdSimpleProperties();
+}
+
+
+void NpCloth::setExternalAcceleration(PxVec3 acceleration)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(acceleration.isFinite(), "PxCloth::setExternalAcceleration: invalid values!");
+
+ mCloth.setExternalAcceleration(acceleration);
+ sendPvdSimpleProperties();
+}
+
+
+PxVec3 NpCloth::getExternalAcceleration() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getExternalAcceleration();
+}
+
+namespace
+{
+#if PX_CHECKED
+ bool isInRange(const PxVec3 vec, float low, float high)
+ {
+ return vec.x >= low && vec.x <= high
+ && vec.y >= low && vec.y <= high
+ && vec.z >= low && vec.z <= high;
+ }
+#endif
+}
+
+void NpCloth::setLinearInertiaScale(PxVec3 scale)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(isInRange(scale, 0.0f, 1.0f), "PxCloth::setLinearInertiaScale: scale value has to be between 0 and 1!");
+
+ mCloth.setLinearInertiaScale(scale);
+ sendPvdSimpleProperties();
+}
+
+
+PxVec3 NpCloth::getLinearInertiaScale() const
+{
+ return mCloth.getLinearInertiaScale();
+}
+
+void NpCloth::setAngularInertiaScale(PxVec3 scale)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(isInRange(scale, 0.0f, 1.0f), "PxCloth::setAngularInertiaScale: scale value has to be between 0 and 1!");
+
+ mCloth.setAngularInertiaScale(scale);
+ sendPvdSimpleProperties();
+}
+
+
+PxVec3 NpCloth::getAngularInertiaScale() const
+{
+ return mCloth.getAngularInertiaScale();
+}
+
+void NpCloth::setCentrifugalInertiaScale(PxVec3 scale)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(isInRange(scale, 0.0f, 1.0f), "PxCloth::setCentrifugalInertiaScale: scale value has to be between 0 and 1!");
+
+ mCloth.setCentrifugalInertiaScale(scale);
+ sendPvdSimpleProperties();
+}
+
+
+PxVec3 NpCloth::getCentrifugalInertiaScale() const
+{
+ return mCloth.getCentrifugalInertiaScale();
+}
+
+void NpCloth::setInertiaScale(float scale)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(scale >= 0.0f && scale <= 1.0f, "PxCloth::setInertiaScale: scale value has to be between 0 and 1!");
+
+ mCloth.setLinearInertiaScale(PxVec3(scale));
+ mCloth.setAngularInertiaScale(PxVec3(scale));
+ sendPvdSimpleProperties();
+}
+
+void NpCloth::setDampingCoefficient(PxVec3 dampingCoefficient)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(isInRange(dampingCoefficient, 0.0f, 1.0f), "PxCloth::setDampingCoefficient: damping coefficient has to be between 0 and 1!");
+
+ mCloth.setDampingCoefficient(dampingCoefficient);
+ sendPvdSimpleProperties();
+}
+
+
+PxVec3 NpCloth::getDampingCoefficient() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getDampingCoefficient();
+}
+
+
+void NpCloth::setFrictionCoefficient(PxReal frictionCoefficient)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(frictionCoefficient >= 0.0f || frictionCoefficient <= 1.0f, "PxCloth::setFrictionCoefficient: friction coefficient has to be between 0 and 1!");
+
+ mCloth.setFrictionCoefficient(frictionCoefficient);
+ sendPvdSimpleProperties();
+}
+
+PxReal NpCloth::getFrictionCoefficient() const
+{
+ return mCloth.getFrictionCoefficient();
+}
+
+void NpCloth::setLinearDragCoefficient(PxVec3 dragCoefficient)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(isInRange(dragCoefficient, 0.0f, 1.0f), "PxCloth::setLinearDragCoefficient: damping coefficient has to be between 0 and 1!");
+
+ mCloth.setLinearDragCoefficient(dragCoefficient);
+ sendPvdSimpleProperties();
+}
+
+
+PxVec3 NpCloth::getLinearDragCoefficient() const
+{
+ return mCloth.getLinearDragCoefficient();
+}
+
+void NpCloth::setAngularDragCoefficient(PxVec3 dragCoefficient)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(isInRange(dragCoefficient, 0.0f, 1.0f), "PxCloth::setAngularDragCoefficient: damping coefficient has to be between 0 and 1!");
+
+ mCloth.setAngularDragCoefficient(dragCoefficient);
+ sendPvdSimpleProperties();
+}
+
+
+PxVec3 NpCloth::getAngularDragCoefficient() const
+{
+ return mCloth.getAngularDragCoefficient();
+}
+
+void NpCloth::setDragCoefficient(float coefficient)
+{
+ setLinearDragCoefficient(PxVec3(coefficient));
+ setAngularDragCoefficient(PxVec3(coefficient));
+}
+
+void NpCloth::setCollisionMassScale(PxReal scalingCoefficient)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(scalingCoefficient >= 0.0f, "PxCloth::setCollisionMassScale: scaling coefficient has to be greater or equal than 0!");
+
+ mCloth.setCollisionMassScale(scalingCoefficient);
+}
+
+
+PxReal NpCloth::getCollisionMassScale() const
+{
+ return mCloth.getCollisionMassScale();
+}
+
+void NpCloth::setSelfCollisionDistance(PxReal distance)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(distance >= 0.0f, "PxCloth::setSelfCollisionDistance: distance has to be greater or equal than 0!");
+
+ mCloth.setSelfCollisionDistance(distance);
+}
+PxReal NpCloth::getSelfCollisionDistance() const
+{
+ return mCloth.getSelfCollisionDistance();
+}
+void NpCloth::setSelfCollisionStiffness(PxReal stiffness)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(stiffness >= 0.0f, "PxCloth::setSelfCollisionStiffness: stiffness has to be greater or equal than 0!");
+
+ mCloth.setSelfCollisionStiffness(stiffness);
+}
+PxReal NpCloth::getSelfCollisionStiffness() const
+{
+ return mCloth.getSelfCollisionStiffness();
+}
+
+void NpCloth::setSelfCollisionIndices(const PxU32* indices, PxU32 nbIndices)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.setSelfCollisionIndices(indices, nbIndices);
+
+ sendPvdSelfCollisionIndices();
+}
+
+bool NpCloth::getSelfCollisionIndices(PxU32* indices) const
+{
+ return mCloth.getSelfCollisionIndices(indices);
+}
+
+PxU32 NpCloth::getNbSelfCollisionIndices() const
+{
+ return mCloth.getNbSelfCollisionIndices();
+}
+
+void NpCloth::setRestPositions(const PxVec4* restPositions)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.setRestPositions(restPositions);
+
+ sendPvdRestPositions();
+}
+
+bool NpCloth::getRestPositions(PxVec4* restPositions) const
+{
+ return mCloth.getRestPositions(restPositions);
+}
+
+PxU32 NpCloth::getNbRestPositions() const
+{
+ return mCloth.getNbRestPositions();
+}
+
+void NpCloth::setSolverFrequency(PxReal frequency)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(frequency > 0.0f, "PxCloth::setSolverFrequency: solver fequency has to be positive!");
+
+ mCloth.setSolverFrequency(frequency);
+ sendPvdSimpleProperties();
+}
+
+
+PxReal NpCloth::getSolverFrequency() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getSolverFrequency();
+}
+
+void NpCloth::setStiffnessFrequency(PxReal frequency)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(frequency > 0.0f, "PxCloth::setStiffnessFrequency: solver fequency has to be positive!");
+
+ mCloth.setStiffnessFrequency(frequency);
+ sendPvdSimpleProperties();
+}
+
+
+PxReal NpCloth::getStiffnessFrequency() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getStiffnessFrequency();
+}
+
+void NpCloth::setStretchConfig(PxClothFabricPhaseType::Enum type, const PxClothStretchConfig& config)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_MSG(config.stiffness >= 0.0f, "PxCloth::setStretchConfig: stiffness must not be negative!");
+ PX_CHECK_MSG(config.stiffnessMultiplier >= 0.0f, "PxCloth::setStretchConfig: stiffnessMultiplier must not be negative!");
+ PX_CHECK_MSG(config.compressionLimit >= 0.0f, "PxCloth::setStretchConfig: compressionLimit must not be negative!");
+ PX_CHECK_MSG(config.compressionLimit <= 1.0f, "PxCloth::setStretchConfig: compressionLimit must not be larger than 1!");
+ PX_CHECK_MSG(config.stretchLimit >= 1.0f, "PxCloth::setStretchConfig: stretchLimit must not be smaller than 1!");
+
+ mCloth.setStretchConfig(type, config);
+ sendPvdSimpleProperties();
+}
+
+void NpCloth::setTetherConfig(const PxClothTetherConfig& config)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_MSG(config.stiffness >= 0.0f, "PxCloth::setTetherConfig: stiffness must not be negative!");
+
+ mCloth.setTetherConfig(config);
+ sendPvdSimpleProperties();
+}
+
+PxClothStretchConfig NpCloth::getStretchConfig(PxClothFabricPhaseType::Enum type) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mCloth.getStretchConfig(type);
+}
+
+PxClothTetherConfig NpCloth::getTetherConfig() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mCloth.getTetherConfig();
+}
+
+void NpCloth::setClothFlags(PxClothFlags flags)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.setClothFlags(flags);
+ sendPvdSimpleProperties();
+
+ NpScene* scene = NpActor::getAPIScene(*this);
+ if (scene)
+ scene->updatePhysXIndicator();
+}
+
+void NpCloth::setClothFlag(PxClothFlag::Enum flag, bool val)
+{
+ PxClothFlags flags = mCloth.getClothFlags();
+ setClothFlags(val ? flags | flag : flags & ~flag);
+}
+
+
+PxClothFlags NpCloth::getClothFlags() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getClothFlags();
+}
+
+void NpCloth::setWindVelocity(PxVec3 value)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ mCloth.setWindVelocity(value);
+ sendPvdSimpleProperties();
+}
+
+PxVec3 NpCloth::getWindVelocity() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getWindVelocity();
+}
+
+void NpCloth::setWindDrag(PxReal value)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(value >= 0.0f, "PxCloth::setWindDrag: value has to be non-negative!");
+
+ mCloth.setDragCoefficient(value);
+ sendPvdSimpleProperties();
+}
+
+PxReal NpCloth::getWindDrag() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getDragCoefficient();
+}
+
+void NpCloth::setWindLift(PxReal value)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN(value >= 0.0f, "PxCloth::setWindLift: value has to be non-negative!");
+
+ mCloth.setLiftCoefficient(value);
+ sendPvdSimpleProperties();
+}
+
+PxReal NpCloth::getWindLift() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getLiftCoefficient();
+}
+
+
+bool NpCloth::isSleeping() const
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+ PX_UNUSED(scene);
+
+ NP_READ_CHECK(scene);
+ PX_CHECK_AND_RETURN_VAL(scene, "PxCloth::isSleeping: cloth must be in a scene.", true);
+
+ return mCloth.isSleeping();
+}
+
+
+PxReal NpCloth::getSleepLinearVelocity() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getSleepLinearVelocity();
+}
+
+
+void NpCloth::setSleepLinearVelocity(PxReal threshold)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_MSG(threshold >= 0.0f, "PxCloth::setSleepLinearVelocity: threshold must not be negative!");
+
+ mCloth.setSleepLinearVelocity(threshold);
+ sendPvdSimpleProperties();
+}
+
+
+void NpCloth::setWakeCounter(PxReal wakeCounterValue)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(PxIsFinite(wakeCounterValue), "PxCloth::setWakeCounter: invalid float.");
+ PX_CHECK_AND_RETURN(wakeCounterValue>=0.0f, "PxCloth::setWakeCounter: wakeCounterValue must be non-negative!");
+
+ mCloth.setWakeCounter(wakeCounterValue);
+}
+
+
+PxReal NpCloth::getWakeCounter() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getWakeCounter();
+}
+
+
+void NpCloth::wakeUp()
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+ PX_UNUSED(scene);
+
+ NP_WRITE_CHECK(scene);
+ PX_CHECK_AND_RETURN(scene, "PxCloth::wakeUp: cloth must be in a scene.");
+
+ mCloth.wakeUp();
+}
+
+
+void NpCloth::putToSleep()
+{
+ NpScene* scene = NpActor::getOwnerScene(*this);
+ PX_UNUSED(scene);
+
+ NP_WRITE_CHECK(scene);
+ PX_CHECK_AND_RETURN(scene, "PxCloth::putToSleep: cloth must be in a scene.");
+
+ mCloth.putToSleep();
+}
+
+
+PxClothParticleData* NpCloth::lockParticleData(PxDataAccessFlags flags)
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ if(!mParticleData.tryLock(flags))
+ {
+ shdfnd::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "PxClothParticleData access through PxCloth::lockParticleData() while its still locked by last call.");
+ return 0;
+ }
+
+ mCloth.getParticleData(mParticleData);
+ return &mParticleData;
+}
+
+PxClothParticleData* NpCloth::lockParticleData() const
+{
+ return const_cast<NpCloth*>(this)->lockParticleData(PxDataAccessFlag::eREADABLE);
+}
+
+void NpCloth::unlockParticleData()
+{
+ mCloth.getScCloth().unlockParticleData();
+}
+
+PxReal NpCloth::getPreviousTimeStep() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ return mCloth.getPreviousTimeStep();
+}
+
+
+PxBounds3 NpCloth::getWorldBounds(float inflation) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ const PxBounds3 bounds = mCloth.getWorldBounds();
+ PX_ASSERT(bounds.isValid());
+
+ // PT: unfortunately we can't just scale the min/max vectors, we need to go through center/extents.
+ const PxVec3 center = bounds.getCenter();
+ const PxVec3 inflatedExtents = bounds.getExtents() * inflation;
+ return PxBounds3::centerExtents(center, inflatedExtents);
+}
+
+void NpCloth::setSimulationFilterData(const PxFilterData& data)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ mCloth.setSimulationFilterData(data);
+}
+
+PxFilterData NpCloth::getSimulationFilterData() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mCloth.getSimulationFilterData();
+}
+
+void NpCloth::setContactOffset(PxReal offset)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ mCloth.setContactOffset(offset);
+}
+
+PxReal NpCloth::getContactOffset() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mCloth.getContactOffset();
+}
+
+void NpCloth::setRestOffset(PxReal offset)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ mCloth.setRestOffset(offset);
+}
+
+PxReal NpCloth::getRestOffset() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return mCloth.getRestOffset();
+}
+
+#if PX_CHECKED
+bool NpCloth::checkParticles(PxU32 numParticles, const PxClothParticle* particles)
+{
+ for (PxU32 i = 0; i < numParticles; ++i)
+ {
+ if(!particles[i].pos.isFinite())
+ return false;
+ if(!PxIsFinite(particles[i].invWeight) || (particles[i].invWeight < 0.0f))
+ return false;
+ }
+ return true;
+}
+
+bool NpCloth::checkMotionConstraints(PxU32 numConstraints, const PxClothParticleMotionConstraint* constraints)
+{
+ if(!constraints)
+ return true;
+
+ for (PxU32 i = 0; i < numConstraints; ++i)
+ {
+ if(!constraints[i].pos.isFinite())
+ return false;
+ if(!PxIsFinite(constraints[i].radius) || (constraints[i].radius < 0.0f))
+ return false;
+ }
+ return true;
+}
+
+
+bool NpCloth::checkSeparationConstraints(PxU32 numConstraints, const PxClothParticleSeparationConstraint* constraints)
+{
+ if(!constraints)
+ return true;
+
+ for (PxU32 i = 0; i < numConstraints; ++i)
+ {
+ if(!constraints[i].pos.isFinite())
+ return false;
+ if(!PxIsFinite(constraints[i].radius) || (constraints[i].radius < 0.0f))
+ return false;
+ }
+ return true;
+}
+
+bool NpCloth::checkParticleAccelerations(PxU32 numParticles, const PxVec4* accelerations)
+{
+ if(!accelerations)
+ return true;
+
+ for (PxU32 i = 0; i < numParticles; ++i)
+ {
+ if(!accelerations[i].isFinite())
+ return false;
+ }
+ return true;
+}
+
+bool NpCloth::checkCollisionSpheres(PxU32 numSpheres, const PxClothCollisionSphere* spheres)
+{
+ for (PxU32 i = 0; i < numSpheres; ++i)
+ {
+ if(!spheres[i].pos.isFinite())
+ return false;
+ if(!PxIsFinite(spheres[i].radius) || (spheres[i].radius < 0.0f))
+ return false;
+ }
+ return true;
+}
+
+bool NpCloth::checkCollisionSpherePairs(PxU32 numSpheres, PxU32 numPairs, const PxU32* pairIndices)
+{
+ for (PxU32 i = 0; i < numPairs; ++i)
+ {
+ if ((pairIndices[2*i] >= numSpheres) || (pairIndices[2*i + 1] >= numSpheres))
+ return false;
+ }
+ return true;
+}
+
+bool NpCloth::checkVirtualParticles(PxU32 numParticles, PxU32 numVParticles, const PxU32* indices, PxU32 numWeights, const PxVec3* weights)
+{
+ for (PxU32 i = 0; i < numVParticles; ++i)
+ {
+ if ((indices[4*i] >= numParticles) ||
+ (indices[4*i + 1] >= numParticles) ||
+ (indices[4*i + 2] >= numParticles) ||
+ (indices[4*i + 3] >= numWeights))
+ return false;
+ }
+ for (PxU32 i = 0; i < numWeights; ++i)
+ {
+ if(!weights[i].isFinite())
+ return false;
+ }
+ return true;
+}
+#endif
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+void NpCloth::visualize(Cm::RenderOutput& out, NpScene* scene)
+{
+ PxClothParticleData* readData = lockParticleData();
+ if (!readData)
+ return;
+
+ NpClothFabric* fabric = static_cast<NpClothFabric*> (getFabric());
+
+ PxU32 nbSets = fabric->getNbSets();
+ PxU32 nbPhases = fabric->getNbPhases();
+ PxU32 nbIndices = fabric->getNbParticleIndices();
+
+ shdfnd::Array<PxU32> sets(nbSets);
+ shdfnd::Array<PxClothFabricPhase> phases(nbPhases);
+ shdfnd::Array<PxU32> indices(nbIndices);
+
+ fabric->getSets(&sets[0], nbSets);
+ fabric->getPhases(&phases[0], nbPhases);
+ fabric->getParticleIndices(&indices[0], nbIndices);
+
+ const PxU32 lineColor[] =
+ {
+ PxU32(PxDebugColor::eARGB_RED),
+ PxU32(PxDebugColor::eARGB_GREEN),
+ PxU32(PxDebugColor::eARGB_BLUE),
+ PxU32(PxDebugColor::eARGB_YELLOW),
+ PxU32(PxDebugColor::eARGB_MAGENTA)
+ };
+
+ PxU32 colorIndex = 0;
+
+ const PxClothParticle* particles = readData->particles;
+ const PxTransform xform = getGlobalPose();
+
+ out << Cm::RenderOutput::LINES;
+
+ for (PxU32 p=0; p < nbPhases; ++p)
+ {
+ PxClothFabricPhaseType::Enum phaseType = fabric->getPhaseType(p);
+
+ float scale = 0.0f;
+
+ // check if visualization requested
+ switch(phaseType)
+ {
+ case PxClothFabricPhaseType::eVERTICAL:
+ scale = scene->getVisualizationParameter(PxVisualizationParameter::eCLOTH_VERTICAL);
+ break;
+ case PxClothFabricPhaseType::eHORIZONTAL:
+ scale = scene->getVisualizationParameter(PxVisualizationParameter::eCLOTH_HORIZONTAL);
+ break;
+ case PxClothFabricPhaseType::eBENDING:
+ scale = scene->getVisualizationParameter(PxVisualizationParameter::eCLOTH_BENDING);
+ break;
+ case PxClothFabricPhaseType::eSHEARING:
+ scale = scene->getVisualizationParameter(PxVisualizationParameter::eCLOTH_SHEARING);
+ break;
+ case PxClothFabricPhaseType::eINVALID:
+ case PxClothFabricPhaseType::eCOUNT:
+ break;
+ }
+
+ if (scale == 0.0f)
+ continue;
+
+ out << lineColor[colorIndex];
+
+ PxU32 set = phases[p].setIndex;
+
+ // draw one set at a time
+ PxU32 iIt = set ? 2*sets[set-1] : 0;
+ PxU32 iEnd = 2*sets[set];
+
+ // iterate over constraints
+ while (iIt < iEnd)
+ {
+ PxU32 i0 = indices[iIt++];
+ PxU32 i1 = indices[iIt++];
+
+ // ideally we would know the mesh normals here and bias off
+ // the surface slightly but scaling slightly around the center helps
+ out << xform.transform(particles[i0].pos);
+ out << xform.transform(particles[i1].pos);
+ }
+
+ colorIndex = (colorIndex+1)%5;
+ }
+
+ // draw virtual particles
+ if (scene->getVisualizationParameter(PxVisualizationParameter::eCLOTH_VIRTUAL_PARTICLES) > 0.0f)
+ {
+ PxU32 nbVirtualParticles = getNbVirtualParticles();
+
+ if (nbVirtualParticles)
+ {
+ out << Cm::RenderOutput::POINTS;
+ out << PxU32(PxDebugColor::eARGB_WHITE);
+
+ shdfnd::Array<PxU32> vpIndices(nbVirtualParticles*4);
+ getVirtualParticles(&vpIndices[0]);
+
+ // get weights table
+ PxU32 nbVirtualParticleWeights = getNbVirtualParticleWeights();
+ shdfnd::Array<PxVec3> vpWeights(nbVirtualParticleWeights);
+ getVirtualParticleWeights(&vpWeights[0]);
+
+ for (PxU32 i=0; i < nbVirtualParticles; ++i)
+ {
+ PxU32 i0 = vpIndices[i*4+0];
+ PxU32 i1 = vpIndices[i*4+1];
+ PxU32 i2 = vpIndices[i*4+2];
+
+ PxVec3 v0 = xform.transform(readData->particles[i0].pos);
+ PxVec3 v1 = xform.transform(readData->particles[i1].pos);
+ PxVec3 v2 = xform.transform(readData->particles[i2].pos);
+
+ PxVec3 weights = vpWeights[vpIndices[i*4+3]];
+
+ out << (v0*weights.x + v1*weights.y + v2*weights.z);
+ }
+ }
+ }
+
+ readData->unlock();
+}
+
+#endif
+
+#if PX_SUPPORT_PVD
+namespace
+{
+ Vd::ScbScenePvdClient* getScenePvdClient( Scb::Scene* scene )
+ {
+ if(scene )
+ {
+ Vd::ScbScenePvdClient& pvdClient = scene->getScenePvdClient();
+ if(pvdClient.checkPvdDebugFlag())
+ return &pvdClient;
+ }
+ return NULL;
+ }
+}
+#endif
+
+void NpCloth::sendPvdSimpleProperties()
+{
+#if PX_SUPPORT_PVD
+ Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() );
+ if ( pvdClient ) pvdClient->sendSimpleProperties( &mCloth );
+#endif
+}
+
+void NpCloth::sendPvdMotionConstraints()
+{
+#if PX_SUPPORT_PVD
+ Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() );
+ if ( pvdClient ) pvdClient->sendMotionConstraints( &mCloth );
+#endif
+}
+
+void NpCloth::sendPvdSelfCollisionIndices()
+{
+#if PX_SUPPORT_PVD
+ Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() );
+ if ( pvdClient ) pvdClient->sendSelfCollisionIndices( &mCloth );
+#endif
+}
+
+void NpCloth::sendPvdRestPositions()
+{
+#if PX_SUPPORT_PVD
+ Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() );
+ if ( pvdClient ) pvdClient->sendRestPositions( &mCloth );
+#endif
+}
+
+void NpCloth::sendPvdSeparationConstraints()
+{
+#if PX_SUPPORT_PVD
+ Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() );
+ if ( pvdClient ) pvdClient->sendSeparationConstraints( &mCloth );
+#endif
+}
+
+void NpCloth::sendPvdCollisionSpheres()
+{
+#if PX_SUPPORT_PVD
+ Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() );
+ if ( pvdClient ) pvdClient->sendCollisionSpheres( &mCloth );
+#endif
+}
+
+void NpCloth::sendPvdCollisionCapsules()
+{
+#if PX_SUPPORT_PVD
+ Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() );
+ if ( pvdClient ) pvdClient->sendCollisionCapsules( &mCloth );
+#endif
+}
+
+void NpCloth::sendPvdCollisionTriangles()
+{
+#if PX_SUPPORT_PVD
+ Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() );
+ if ( pvdClient ) pvdClient->sendCollisionTriangles( &mCloth );
+#endif
+}
+
+void NpCloth::sendPvdVirtualParticles()
+{
+#if PX_SUPPORT_PVD
+ Vd::ScbScenePvdClient* pvdClient = getScenePvdClient( mCloth.getScbSceneForAPI() );
+ if ( pvdClient ) pvdClient->sendVirtualParticles( &mCloth );
+#endif
+}
+
+#endif // PX_USE_CLOTH_API
diff --git a/PhysX_3.4/Source/PhysX/src/cloth/NpCloth.h b/PhysX_3.4/Source/PhysX/src/cloth/NpCloth.h
new file mode 100644
index 00000000..14a98b93
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/cloth/NpCloth.h
@@ -0,0 +1,269 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_CLOTH
+#define PX_PHYSICS_NP_CLOTH
+
+#include "PxPhysXConfig.h"
+
+#if PX_USE_CLOTH_API
+
+#include "PxCloth.h"
+#include "NpActorTemplate.h"
+#include "ScbCloth.h"
+
+
+namespace physx
+{
+class NpClothFabric;
+
+typedef NpActorTemplate<PxCloth> NpClothT;
+
+class NpCloth : public NpClothT
+{
+//= 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
+ NpCloth(PxBaseFlags baseFlags);
+ virtual void requires(PxProcessPxBaseCallback& c);
+ virtual void exportExtraData(PxSerializationContext& stream) { mCloth.exportExtraData(stream); }
+ void importExtraData(PxDeserializationContext& context) { mCloth.importExtraData(context); }
+ void resolveReferences(PxDeserializationContext& context);
+ static NpCloth* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ NpCloth(const PxTransform& globalPose, NpClothFabric& fabric, const PxClothParticle* particles, PxClothFlags flags);
+ virtual ~NpCloth();
+ NpCloth &operator=(const NpCloth &);
+
+ //---------------------------------------------------------------------------------
+ // PxCloth implementation
+ //---------------------------------------------------------------------------------
+ virtual void release();
+
+ virtual PxActorType::Enum getType() const;
+
+ virtual PxClothFabric* getFabric() const;
+
+ virtual void setParticles(const PxClothParticle* currentParticles, const PxClothParticle* previousParticles);
+ virtual PxU32 getNbParticles() const;
+
+ virtual void setMotionConstraints(const PxClothParticleMotionConstraint* motionConstraints);
+ virtual bool getMotionConstraints(PxClothParticleMotionConstraint* motionConstraintsBuffer) const;
+ virtual PxU32 getNbMotionConstraints() const;
+
+ virtual void setMotionConstraintConfig(const PxClothMotionConstraintConfig& config);
+ virtual PxClothMotionConstraintConfig getMotionConstraintConfig() const;
+
+ virtual void setSeparationConstraints(const PxClothParticleSeparationConstraint* separationConstraints);
+ virtual bool getSeparationConstraints(PxClothParticleSeparationConstraint* separationConstraintsBuffer) const;
+ virtual PxU32 getNbSeparationConstraints() const;
+
+ virtual void clearInterpolation();
+
+ virtual void setParticleAccelerations(const PxVec4* particleAccelerations);
+ virtual bool getParticleAccelerations(PxVec4* particleAccelerationsBuffer) const;
+ virtual PxU32 getNbParticleAccelerations() const;
+
+ virtual void addCollisionSphere(const PxClothCollisionSphere& sphere);
+ virtual void removeCollisionSphere(PxU32 index);
+ virtual void setCollisionSpheres(const PxClothCollisionSphere* spheresBuffer, PxU32 count);
+ virtual PxU32 getNbCollisionSpheres() const;
+
+ virtual void getCollisionData(PxClothCollisionSphere* spheresBuffer, PxU32* capsulesBuffer,
+ PxClothCollisionPlane* planesBuffer, PxU32* convexesBuffer, PxClothCollisionTriangle* trianglesBuffer) const;
+
+ virtual void addCollisionCapsule(PxU32 first, PxU32 second);
+ virtual void removeCollisionCapsule(PxU32 index);
+ virtual PxU32 getNbCollisionCapsules() const;
+
+ virtual void addCollisionTriangle(const PxClothCollisionTriangle& triangle);
+ virtual void removeCollisionTriangle(PxU32 index);
+ virtual void setCollisionTriangles(const PxClothCollisionTriangle* trianglesBuffer, PxU32 count);
+ virtual PxU32 getNbCollisionTriangles() const;
+
+ virtual void addCollisionPlane(const PxClothCollisionPlane& plane);
+ virtual void removeCollisionPlane(PxU32 index);
+ virtual void setCollisionPlanes(const PxClothCollisionPlane* planesBuffer, PxU32 count);
+ virtual PxU32 getNbCollisionPlanes() const;
+
+ virtual void addCollisionConvex(PxU32 mask);
+ virtual void removeCollisionConvex(PxU32 index);
+ virtual PxU32 getNbCollisionConvexes() const;
+
+ virtual void setVirtualParticles(PxU32 numParticles, const PxU32* indices, PxU32 numWeights, const PxVec3* weights);
+
+ virtual PxU32 getNbVirtualParticles() const;
+ virtual void getVirtualParticles(PxU32* indicesBuffer) const;
+
+ virtual PxU32 getNbVirtualParticleWeights() const;
+ virtual void getVirtualParticleWeights(PxVec3* weightsBuffer) const;
+
+ virtual void setGlobalPose(const PxTransform& pose);
+ virtual PxTransform getGlobalPose() const;
+
+ virtual void setTargetPose(const PxTransform& pose);
+
+ virtual void setExternalAcceleration(PxVec3 acceleration);
+ virtual PxVec3 getExternalAcceleration() const;
+
+ virtual void setLinearInertiaScale(PxVec3 scale);
+ virtual PxVec3 getLinearInertiaScale() const;
+ virtual void setAngularInertiaScale(PxVec3 scale);
+ virtual PxVec3 getAngularInertiaScale() const;
+ virtual void setCentrifugalInertiaScale(PxVec3 scale);
+ virtual PxVec3 getCentrifugalInertiaScale() const;
+ virtual void setInertiaScale(float);
+
+ virtual void setDampingCoefficient(PxVec3 dampingCoefficient);
+ virtual PxVec3 getDampingCoefficient() const;
+
+ virtual void setFrictionCoefficient(PxReal frictionCoefficient);
+ virtual PxReal getFrictionCoefficient() const;
+
+ virtual void setLinearDragCoefficient(PxVec3 dampingCoefficient);
+ virtual PxVec3 getLinearDragCoefficient() const;
+ virtual void setAngularDragCoefficient(PxVec3 dampingCoefficient);
+ virtual PxVec3 getAngularDragCoefficient() const;
+ virtual void setDragCoefficient(float);
+
+ virtual void setCollisionMassScale(PxReal scalingCoefficient);
+ virtual PxReal getCollisionMassScale() const;
+
+ virtual void setSelfCollisionDistance(PxReal distance);
+ virtual PxReal getSelfCollisionDistance() const;
+ virtual void setSelfCollisionStiffness(PxReal stiffness);
+ virtual PxReal getSelfCollisionStiffness() const;
+
+ virtual void setSelfCollisionIndices(const PxU32* indices, PxU32 nbIndices);
+ virtual bool getSelfCollisionIndices(PxU32* indices) const;
+ virtual PxU32 getNbSelfCollisionIndices() const;
+
+ virtual void setRestPositions(const PxVec4* restPositions);
+ virtual bool getRestPositions(PxVec4* restPositions) const;
+ virtual PxU32 getNbRestPositions() const;
+
+ virtual void setSolverFrequency(PxReal);
+ virtual PxReal getSolverFrequency() const;
+
+ virtual void setStiffnessFrequency(PxReal);
+ virtual PxReal getStiffnessFrequency() const;
+
+ virtual void setStretchConfig(PxClothFabricPhaseType::Enum type, const PxClothStretchConfig& config);
+ virtual PxClothStretchConfig getStretchConfig(PxClothFabricPhaseType::Enum type) const;
+
+ virtual void setTetherConfig(const PxClothTetherConfig& config);
+ virtual PxClothTetherConfig getTetherConfig() const;
+
+ virtual void setClothFlags(PxClothFlags flags);
+ virtual void setClothFlag(PxClothFlag::Enum flag, bool val);
+ virtual PxClothFlags getClothFlags() const;
+
+ virtual PxVec3 getWindVelocity() const;
+ virtual void setWindVelocity(PxVec3);
+ virtual PxReal getWindDrag() const;
+ virtual void setWindDrag(PxReal);
+ virtual PxReal getWindLift() const;
+ virtual void setWindLift(PxReal);
+
+ virtual bool isSleeping() const;
+ virtual PxReal getSleepLinearVelocity() const;
+ virtual void setSleepLinearVelocity(PxReal threshold);
+ virtual void setWakeCounter(PxReal wakeCounterValue);
+ virtual PxReal getWakeCounter() const;
+ virtual void wakeUp();
+ virtual void putToSleep();
+
+ virtual PxClothParticleData* lockParticleData(PxDataAccessFlags);
+ virtual PxClothParticleData* lockParticleData() const;
+
+
+ virtual PxReal getPreviousTimeStep() const;
+
+ virtual PxBounds3 getWorldBounds(float inflation=1.01f) const;
+
+ virtual void setSimulationFilterData(const PxFilterData& data);
+ virtual PxFilterData getSimulationFilterData() const;
+
+ virtual void setContactOffset(PxReal);
+ virtual PxReal getContactOffset() const;
+ virtual void setRestOffset(PxReal);
+ virtual PxReal getRestOffset() const;
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+public:
+
+ PX_FORCE_INLINE Scb::Cloth& getScbCloth() { return mCloth; }
+ PX_FORCE_INLINE const Scb::Cloth& getScbCloth() const { return mCloth; }
+
+#if PX_CHECKED
+ static bool checkParticles(PxU32 numParticles, const PxClothParticle* particles);
+ static bool checkMotionConstraints(PxU32 numConstraints, const PxClothParticleMotionConstraint* constraints);
+ static bool checkSeparationConstraints(PxU32 numConstraints, const PxClothParticleSeparationConstraint* constraints);
+ static bool checkParticleAccelerations(PxU32 numParticles, const PxVec4* accelerations);
+ static bool checkCollisionSpheres(PxU32 numSpheres, const PxClothCollisionSphere* spheres);
+ static bool checkCollisionSpherePairs(PxU32 numSpheres, PxU32 numPairs, const PxU32* pairIndices);
+ static bool checkVirtualParticles(PxU32 numParticles, PxU32 numVParticles, const PxU32* indices, PxU32 numWeights, const PxVec3* weights);
+#endif
+
+#if PX_ENABLE_DEBUG_VISUALIZATION
+ virtual void visualize(Cm::RenderOutput& out, NpScene* scene);
+#endif
+
+ void unlockParticleData();
+
+
+private:
+
+ void sendPvdSimpleProperties();
+ void sendPvdMotionConstraints();
+ void sendPvdSeparationConstraints();
+ void sendPvdCollisionSpheres();
+ void sendPvdCollisionCapsules();
+ void sendPvdCollisionTriangles();
+ void sendPvdVirtualParticles();
+ void sendPvdSelfCollisionIndices();
+ void sendPvdRestPositions();
+ Scb::Cloth mCloth;
+ NpClothFabric* mClothFabric;
+ NpClothParticleData mParticleData;
+};
+
+}
+
+#endif // PX_USE_CLOTH_API
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/cloth/NpClothFabric.cpp b/PhysX_3.4/Source/PhysX/src/cloth/NpClothFabric.cpp
new file mode 100644
index 00000000..49e33ca2
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/cloth/NpClothFabric.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 "PxPhysXConfig.h"
+
+#if PX_USE_CLOTH_API
+
+#include "foundation/PxAssert.h"
+
+#include "NpClothFabric.h"
+#include "NpFactory.h"
+#include "NpPhysics.h"
+
+#include "GuSerialize.h"
+#include "CmPhysXCommon.h"
+#include "CmUtils.h"
+
+using namespace physx;
+
+void NpClothFabric::exportExtraData(PxSerializationContext& stream)
+{
+ mFabric.exportExtraData(stream);
+}
+
+
+void NpClothFabric::importExtraData(PxDeserializationContext& context)
+{
+ mFabric.importExtraData(context);
+}
+
+NpClothFabric* NpClothFabric::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpClothFabric* obj = new (address) NpClothFabric(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpClothFabric);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+
+NpClothFabric::NpClothFabric()
+: PxClothFabric(PxConcreteType::eCLOTH_FABRIC, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+{
+}
+
+
+NpClothFabric::~NpClothFabric()
+{
+}
+
+
+void NpClothFabric::release()
+{
+ decRefCount();
+}
+
+
+void NpClothFabric::onRefCountZero()
+{
+ if(NpFactory::getInstance().removeClothFabric(*this))
+ {
+ if(getBaseFlags() & PxBaseFlag::eOWNS_MEMORY)
+ NpFactory::getInstance().releaseClothFabricToPool(*this);
+ else
+ this->~NpClothFabric();
+ NpPhysics::getInstance().notifyDeletionListenersMemRelease(this, NULL);
+ return;
+ }
+
+ // PT: if we reach this point, we didn't find the cloth fabric in the Physics object => don't delete!
+ // This prevents deleting the object twice.
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "NpClothFabric: double deletion detected!");
+}
+
+
+PxU32 NpClothFabric::getReferenceCount() const
+{
+ return getRefCount();
+}
+
+
+void NpClothFabric::acquireReference()
+{
+ incRefCount();
+}
+
+/**
+ Load cloth fabric data from the given stream.
+
+ @param[in] stream input stream to load fabric data from
+ @return true if loading was successful
+
+ @sa For cooker implementation, see ClothFabricBuilder.cpp in PhysXCooking/src
+ */
+bool NpClothFabric::load(PxInputStream& stream)
+{
+ return mFabric.load(stream);
+}
+
+bool NpClothFabric::load(const PxClothFabricDesc& desc)
+{
+ return mFabric.load(desc);
+}
+
+PxU32 NpClothFabric::getNbParticles() const
+{
+ return getScClothFabric().getNbParticles();
+}
+
+PxU32 NpClothFabric::getNbPhases() const
+{
+ return getScClothFabric().getNbPhases();
+}
+
+PxU32 NpClothFabric::getNbSets() const
+{
+ return getScClothFabric().getNbSets();
+}
+
+PxU32 NpClothFabric::getNbParticleIndices() const
+{
+ return getScClothFabric().getNbParticleIndices();
+}
+
+PxU32 NpClothFabric::getNbRestvalues() const
+{
+ return getScClothFabric().getNbRestvalues();
+}
+
+PxU32 NpClothFabric::getNbTethers() const
+{
+ return getScClothFabric().getNbTethers();
+}
+
+PxU32 NpClothFabric::getPhases(PxClothFabricPhase* userPhaseIndexBuffer, PxU32 bufferSize) const
+{
+ return getScClothFabric().getPhases(userPhaseIndexBuffer, bufferSize);
+}
+
+PxU32 NpClothFabric::getSets(PxU32* userSetBuffer, PxU32 bufferSize) const
+{
+ return getScClothFabric().getSets(userSetBuffer, bufferSize);
+}
+
+PxU32 NpClothFabric::getParticleIndices(PxU32* userParticleIndexBuffer, PxU32 bufferSize) const
+{
+ return getScClothFabric().getParticleIndices(userParticleIndexBuffer, bufferSize);
+}
+
+PxU32 NpClothFabric::getRestvalues(PxReal* userRestvalueBuffer, PxU32 bufferSize) const
+{
+ return getScClothFabric().getRestvalues(userRestvalueBuffer, bufferSize);
+}
+
+PxU32 NpClothFabric::getTetherAnchors(PxU32* userAnchorBuffer, PxU32 bufferSize) const
+{
+ return getScClothFabric().getTetherAnchors(userAnchorBuffer, bufferSize);
+}
+
+PxU32 NpClothFabric::getTetherLengths(PxReal* userLengthBuffer, PxU32 bufferSize) const
+{
+ return getScClothFabric().getTetherLengths(userLengthBuffer, bufferSize);
+}
+
+PxClothFabricPhaseType::Enum NpClothFabric::getPhaseType(PxU32 phaseIndex) const
+{
+ return getScClothFabric().getPhaseType(phaseIndex);
+}
+
+void NpClothFabric::scaleRestlengths(PxReal scale)
+{
+ mFabric.scaleRestlengths(scale);
+}
+
+#endif // PX_USE_CLOTH_API
+
diff --git a/PhysX_3.4/Source/PhysX/src/cloth/NpClothFabric.h b/PhysX_3.4/Source/PhysX/src/cloth/NpClothFabric.h
new file mode 100644
index 00000000..7c8d06d0
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/cloth/NpClothFabric.h
@@ -0,0 +1,112 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_CLOTH_FABRIC
+#define PX_PHYSICS_NP_CLOTH_FABRIC
+
+#include "PxPhysXConfig.h"
+
+#if PX_USE_CLOTH_API
+
+#include "PsUserAllocated.h"
+#include "CmPhysXCommon.h"
+#include "CmRefCountable.h"
+#include "PxClothFabric.h"
+#include "PsArray.h"
+#include "ScClothFabricCore.h" // for the people asking: Why is it ok to use Sc directly here? Because there is no double buffering for fabrics (they are like meshes)
+#include "PxSerialFramework.h"
+
+namespace physx
+{
+
+class NpClothFabric : public PxClothFabric, public Ps::UserAllocated, public Cm::RefCountable
+{
+//= 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
+ NpClothFabric(PxBaseFlags baseFlags) : PxClothFabric(baseFlags), Cm::RefCountable(PxEmpty), mFabric(PxEmpty) {}
+ virtual void onRefCountZero();
+ virtual void exportExtraData(PxSerializationContext&);
+ void importExtraData(PxDeserializationContext&);
+ static NpClothFabric* createObject(PxU8*& address, PxDeserializationContext&);
+ static void getBinaryMetaData(PxOutputStream& stream);
+ void resolveReferences(PxDeserializationContext&) {}
+ virtual void requires(PxProcessPxBaseCallback&){}
+//~PX_SERIALIZATION
+ NpClothFabric();
+
+ bool load(PxInputStream& stream);
+ bool load(const PxClothFabricDesc& desc);
+
+// PxClothFabric
+ virtual void release();
+
+ virtual PxU32 getNbParticles() const;
+ virtual PxU32 getNbPhases() const;
+ virtual PxU32 getNbSets() const;
+ virtual PxU32 getNbParticleIndices() const;
+ virtual PxU32 getNbRestvalues() const;
+ virtual PxU32 getNbTethers() const;
+
+ virtual PxU32 getPhases(PxClothFabricPhase* userPhaseIndexBuffer, PxU32 bufferSize) const;
+ virtual PxU32 getSets(PxU32* userSetBuffer, PxU32 bufferSize) const;
+ virtual PxU32 getParticleIndices(PxU32* userParticleIndexBuffer, PxU32 bufferSize) const;
+ virtual PxU32 getRestvalues(PxReal* userRestvalueBuffer, PxU32 bufferSize) const;
+
+ virtual PxU32 getTetherAnchors(PxU32* userAnchorBuffer, PxU32 bufferSize) const;
+ virtual PxU32 getTetherLengths(PxReal* userLengthBuffer, PxU32 bufferSize) const;
+
+ PxClothFabricPhaseType::Enum getPhaseType(PxU32 phaseIndex) const;
+
+ virtual void scaleRestlengths(PxReal scale);
+
+ virtual PxU32 getReferenceCount() const;
+ virtual void acquireReference();
+ //~PxClothFabric
+
+ PX_FORCE_INLINE Sc::ClothFabricCore& getScClothFabric() { return mFabric; }
+ PX_FORCE_INLINE const Sc::ClothFabricCore& getScClothFabric() const { return mFabric; }
+
+ virtual ~NpClothFabric();
+
+protected:
+
+ Sc::ClothFabricCore mFabric; // Internal layer object
+};
+
+}
+
+#endif // PX_USE_CLOTH_API
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/cloth/NpClothParticleData.cpp b/PhysX_3.4/Source/PhysX/src/cloth/NpClothParticleData.cpp
new file mode 100644
index 00000000..78f51680
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/cloth/NpClothParticleData.cpp
@@ -0,0 +1,65 @@
+// 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 "NpClothParticleData.h"
+#include "NpCloth.h"
+
+using namespace physx;
+
+void NpClothParticleData::unlock()
+{
+ PX_ASSERT(mNbLocks);
+
+ if(!mFlags.isSet(PxDataAccessFlag::eDEVICE))
+ {
+ if (mFlags.isSet(PxDataAccessFlag::eWRITABLE))
+ mCloth.setParticles(particles, previousParticles);
+ mCloth.unlockParticleData();
+ }
+ mFlags.clear(PxDataAccessFlag::eWRITABLE);
+ mFlags.clear(PxDataAccessFlag::eDEVICE);
+
+ --mNbLocks;
+}
+
+bool NpClothParticleData::tryLock( PxDataAccessFlags flags )
+{
+ flags |= mFlags;
+ if((flags.isSet(PxDataAccessFlag::eWRITABLE) || flags.isSet(PxDataAccessFlag::eDEVICE)) && mNbLocks)
+ return false;
+
+ mFlags = flags;
+ ++mNbLocks;
+ return true;
+}
+
+#endif // PX_USE_CLOTH_API
diff --git a/PhysX_3.4/Source/PhysX/src/cloth/NpClothParticleData.h b/PhysX_3.4/Source/PhysX/src/cloth/NpClothParticleData.h
new file mode 100644
index 00000000..1668fb35
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/cloth/NpClothParticleData.h
@@ -0,0 +1,74 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_CLOTH_READ_DATA
+#define PX_PHYSICS_NP_CLOTH_READ_DATA
+
+#include "PxPhysXConfig.h"
+
+#if PX_USE_CLOTH_API
+
+#include "PxClothParticleData.h"
+#include "PsUserAllocated.h"
+
+namespace physx
+{
+
+class NpCloth;
+
+class NpClothParticleData : public PxClothParticleData, public shdfnd::UserAllocated
+{
+public:
+
+ NpClothParticleData(NpCloth& cloth)
+ : mCloth(cloth), mNbLocks(0), mFlags(PxDataAccessFlag::eREADABLE)
+ {}
+
+ virtual ~NpClothParticleData()
+ {}
+
+ // implementation for PxLockedData
+ virtual PxDataAccessFlags getDataAccessFlags() { return mFlags; }
+ virtual void unlock();
+
+ bool tryLock(PxDataAccessFlags);
+
+private:
+ NpClothParticleData& operator=(const NpClothParticleData&);
+ NpCloth& mCloth;
+ PxU32 mNbLocks;
+ PxDataAccessFlags mFlags;
+};
+
+}
+
+#endif // PX_USE_CLOTH_API
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/device/PhysXIndicator.h b/PhysX_3.4/Source/PhysX/src/device/PhysXIndicator.h
new file mode 100644
index 00000000..2f6777ff
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/device/PhysXIndicator.h
@@ -0,0 +1,56 @@
+// 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 __PHYSXINDICATOR_H__
+#define __PHYSXINDICATOR_H__
+
+#include "foundation/PxPreprocessor.h"
+
+namespace physx
+{
+ struct NvPhysXToDrv_Data_V1_;
+
+ class PhysXIndicator
+ {
+ public:
+ PhysXIndicator(bool isGpu = false);
+ ~PhysXIndicator();
+
+ void setIsGpu(bool isGpu);
+
+ private:
+ void updateCounter(int delta);
+
+ NvPhysXToDrv_Data_V1_* mPhysXDataPtr;
+ void* mFileHandle;
+ bool mIsGpu;
+ };
+}
+
+#endif // __PHYSXINDICATOR_H__
diff --git a/PhysX_3.4/Source/PhysX/src/device/linux/PhysXIndicatorLinux.cpp b/PhysX_3.4/Source/PhysX/src/device/linux/PhysXIndicatorLinux.cpp
new file mode 100644
index 00000000..e60569f9
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/device/linux/PhysXIndicatorLinux.cpp
@@ -0,0 +1,51 @@
+// 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 "PhysXIndicator.h"
+#include "nvPhysXtoDrv.h"
+
+physx::PhysXIndicator::PhysXIndicator(bool isGpu)
+: mPhysXDataPtr(0), mFileHandle(0), mIsGpu(isGpu)
+{
+
+}
+
+physx::PhysXIndicator::~PhysXIndicator()
+{
+}
+
+void physx::PhysXIndicator::setIsGpu(bool isGpu)
+{
+ PX_UNUSED(isGpu);
+}
+
+PX_INLINE void physx::PhysXIndicator::updateCounter(int delta)
+{
+ PX_UNUSED(delta);
+}
diff --git a/PhysX_3.4/Source/PhysX/src/device/nvPhysXtoDrv.h b/PhysX_3.4/Source/PhysX/src/device/nvPhysXtoDrv.h
new file mode 100644
index 00000000..830193c5
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/device/nvPhysXtoDrv.h
@@ -0,0 +1,93 @@
+// 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 __NVPHYSXTODRV_H__
+#define __NVPHYSXTODRV_H__
+
+// The puprose of this interface is to provide graphics drivers with information
+// about PhysX state to draw PhysX visual indicator
+
+// We share information between modules using a memory section object. PhysX creates
+// such object, graphics drivers try to open it. The name of the object has
+// fixed part (NvPhysXToDrv_SectionName) followed by the process id. This allows
+// each process to have its own communication channel.
+
+namespace physx
+{
+
+#define NvPhysXToDrv_SectionName "PH71828182845_"
+
+// Vista apps cannot create stuff in Global\\ namespace when NOT elevated, so use local scope
+#define NvPhysXToDrv_Build_SectionName(PID, buf) sprintf(buf, NvPhysXToDrv_SectionName "%x", static_cast<unsigned int>(PID))
+#define NvPhysXToDrv_Build_SectionNameXP(PID, buf) sprintf(buf, "Global\\" NvPhysXToDrv_SectionName "%x", static_cast<unsigned int>(PID))
+
+typedef struct NvPhysXToDrv_Header_
+{
+ int signature; // header interface signature
+ int version; // version of the interface
+ int size; // size of the structure
+ int reserved; // reserved, must be zero
+} NvPhysXToDrv_Header;
+
+// this structure describes layout of data in the shared memory section
+typedef struct NvPhysXToDrv_Data_V1_
+{
+ NvPhysXToDrv_Header header; // keep this member first in all versions of the interface.
+
+ int bCpuPhysicsPresent; // nonzero if cpu physics is initialized
+ int bGpuPhysicsPresent; // nonzero if gpu physics is initialized
+
+} NvPhysXToDrv_Data_V1;
+
+// some random magic number as our interface signature
+#define NvPhysXToDrv_Header_Signature 0xA7AB
+
+// use the macro to setup the header to the latest version of the interface
+// update the macro when a new verson of the interface is added
+#define NvPhysXToDrv_Header_Init(header) \
+{ \
+ header.signature = NvPhysXToDrv_Header_Signature; \
+ header.version = 1; \
+ header.size = sizeof(NvPhysXToDrv_Data_V1); \
+ header.reserved = 0; \
+}
+
+// validate the header against all known interface versions
+// add validation checks when new interfaces are added
+#define NvPhysXToDrv_Header_Validate(header, curVersion) \
+ ( \
+ (header.signature == NvPhysXToDrv_Header_Signature) && \
+ (header.version == curVersion) && \
+ (curVersion == 1) && \
+ (header.size == sizeof(NvPhysXToDrv_Data_V1)) \
+ )
+
+}
+
+#endif // __NVPHYSXTODRV_H__
diff --git a/PhysX_3.4/Source/PhysX/src/device/windows/PhysXIndicatorWindows.cpp b/PhysX_3.4/Source/PhysX/src/device/windows/PhysXIndicatorWindows.cpp
new file mode 100644
index 00000000..92d43f5a
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/device/windows/PhysXIndicatorWindows.cpp
@@ -0,0 +1,131 @@
+// 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 "PhysXIndicator.h"
+#include "nvPhysXtoDrv.h"
+
+#pragma warning (push)
+#pragma warning (disable : 4668) //'symbol' is not defined as a preprocessor macro, replacing with '0' for 'directives'
+#include <windows.h>
+#pragma warning (pop)
+
+#include <stdio.h>
+
+#if _MSC_VER >= 1800
+#include <VersionHelpers.h>
+#endif
+
+// Scope-based to indicate to NV driver that CPU PhysX is happening
+physx::PhysXIndicator::PhysXIndicator(bool isGpu)
+: mPhysXDataPtr(0), mFileHandle(0), mIsGpu(isGpu)
+{
+ // Get the windows version (we can only create Global\\ namespace objects in XP)
+ /**
+ Operating system Version number
+ ---------------- --------------
+ Windows 7 6.1
+ Windows Server 2008 R2 6.1
+ Windows Server 2008 6.0
+ Windows Vista 6.0
+ Windows Server 2003 R2 5.2
+ Windows Server 2003 5.2
+ Windows XP 5.1
+ Windows 2000 5.0
+ **/
+
+ char configName[128];
+
+#if _MSC_VER >= 1800
+ if (!IsWindowsVistaOrGreater())
+#else
+ OSVERSIONINFOEX windowsVersionInfo;
+ windowsVersionInfo.dwOSVersionInfoSize = sizeof (windowsVersionInfo);
+ GetVersionEx((LPOSVERSIONINFO)&windowsVersionInfo);
+
+ if (windowsVersionInfo.dwMajorVersion < 6)
+#endif
+ NvPhysXToDrv_Build_SectionNameXP(GetCurrentProcessId(), configName);
+ else
+ NvPhysXToDrv_Build_SectionName(GetCurrentProcessId(), configName);
+
+ mFileHandle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
+ PAGE_READWRITE, 0, sizeof(NvPhysXToDrv_Data_V1), configName);
+
+ if (!mFileHandle || mFileHandle == INVALID_HANDLE_VALUE)
+ return;
+
+ bool alreadyExists = ERROR_ALREADY_EXISTS == GetLastError();
+
+ mPhysXDataPtr = (physx::NvPhysXToDrv_Data_V1*)MapViewOfFile(mFileHandle,
+ FILE_MAP_READ|FILE_MAP_WRITE, 0, 0, sizeof(NvPhysXToDrv_Data_V1));
+
+ if(!mPhysXDataPtr)
+ return;
+
+ if (!alreadyExists)
+ {
+ mPhysXDataPtr->bCpuPhysicsPresent = 0;
+ mPhysXDataPtr->bGpuPhysicsPresent = 0;
+ }
+
+ updateCounter(1);
+
+ // init header last to prevent race conditions
+ // this must be done because the driver may have already created the shared memory block,
+ // thus alreadyExists may be true, even if PhysX hasn't been initialized
+ NvPhysXToDrv_Header_Init(mPhysXDataPtr->header);
+}
+
+physx::PhysXIndicator::~PhysXIndicator()
+{
+ if(mPhysXDataPtr)
+ {
+ updateCounter(-1);
+ UnmapViewOfFile(mPhysXDataPtr);
+ }
+
+ if(mFileHandle && mFileHandle != INVALID_HANDLE_VALUE)
+ CloseHandle(mFileHandle);
+}
+
+void physx::PhysXIndicator::setIsGpu(bool isGpu)
+{
+ if(!mPhysXDataPtr)
+ return;
+
+ updateCounter(-1);
+ mIsGpu = isGpu;
+ updateCounter(1);
+}
+
+PX_INLINE void physx::PhysXIndicator::updateCounter(int delta)
+{
+ (mIsGpu ? mPhysXDataPtr->bGpuPhysicsPresent
+ : mPhysXDataPtr->bCpuPhysicsPresent) += delta;
+}
diff --git a/PhysX_3.4/Source/PhysX/src/gpu/NpPhysicsGpu.cpp b/PhysX_3.4/Source/PhysX/src/gpu/NpPhysicsGpu.cpp
new file mode 100644
index 00000000..2ed19c55
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/gpu/NpPhysicsGpu.cpp
@@ -0,0 +1,291 @@
+// 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 "NpPhysicsGpu.h"
+
+#if PX_SUPPORT_GPU_PHYSX
+
+#include "NpPhysics.h"
+#include "PxvGlobals.h"
+#include "PxPhysXGpu.h"
+#include "PxParticleGpu.h"
+#include "NpScene.h"
+
+using namespace physx;
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+Ps::Array<NpPhysicsGpu::MeshMirror>::Iterator NpPhysicsGpu::findMeshMirror(const void* meshAddress)
+{
+ Ps::Array<MeshMirror>::Iterator i = mMeshMirrors.begin();
+ while (i != mMeshMirrors.end() && i->meshAddress != meshAddress)
+ i++;
+
+ return i;
+}
+
+Ps::Array<NpPhysicsGpu::MeshMirror>::Iterator NpPhysicsGpu::findMeshMirror(const void* meshAddress, PxCudaContextManager& ctx)
+{
+ Ps::Array<MeshMirror>::Iterator i = mMeshMirrors.begin();
+ while (i != mMeshMirrors.end() && (i->meshAddress != meshAddress || i->ctx != &ctx))
+ i++;
+
+ return i;
+}
+
+PxPhysXGpu* NpPhysicsGpu::getPhysXGpu(bool createIfNeeded, const char* functionName, bool doWarn)
+{
+ PxPhysXGpu* physXGpu = PxvGetPhysXGpu(createIfNeeded);
+
+ if (!physXGpu && doWarn)
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "%s, GPU implementation not available.", functionName);
+
+ return physXGpu;
+}
+
+bool NpPhysicsGpu::checkNewMirror(const void* meshPtr, PxCudaContextManager& ctx, const char* functionName)
+{
+ Ps::Array<MeshMirror>::Iterator it = findMeshMirror(meshPtr, ctx);
+ if (it == mMeshMirrors.end())
+ return true;
+
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "%s has no effect. Mirror already exists.", functionName);
+ return false;
+}
+
+bool NpPhysicsGpu::checkMirrorExists(Ps::Array<MeshMirror>::Iterator it, const char* functionName)
+{
+ if (it != mMeshMirrors.end())
+ return true;
+
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "%s has no effect. Mirror doesn't exist.", functionName);
+ return false;
+}
+
+bool NpPhysicsGpu::checkMirrorHandle(PxU32 mirrorHandle, const char* functionName)
+{
+ if (mirrorHandle != PX_INVALID_U32)
+ return true;
+
+ Ps::getFoundation().error(PxErrorCode::eOUT_OF_MEMORY, __FILE__, __LINE__, "%s failed.", functionName);
+ return false;
+}
+
+void NpPhysicsGpu::addMeshMirror(const void* meshPtr, PxU32 mirrorHandle, PxCudaContextManager& ctx)
+{
+ MeshMirror& meshMirror = mMeshMirrors.insert();
+ meshMirror.meshAddress = meshPtr;
+ meshMirror.ctx = &ctx;
+ meshMirror.mirrorHandle = mirrorHandle;
+}
+
+void NpPhysicsGpu::releaseMeshMirror(const void* meshPtr, const char* functionName, PxCudaContextManager* ctx)
+{
+ PxPhysXGpu* physXGpu = getPhysXGpu(false, functionName, ctx != NULL);
+ if (!physXGpu)
+ return;
+
+ if (ctx)
+ {
+ Ps::Array<MeshMirror>::Iterator mirrorIt = findMeshMirror(meshPtr, *ctx);
+ if (!checkMirrorExists(mirrorIt, functionName))
+ return;
+
+ physXGpu->releaseMirror(mirrorIt->mirrorHandle);
+ mMeshMirrors.replaceWithLast(mirrorIt);
+ }
+ else
+ {
+ //remove all mesh mirrors for all contexts.
+ Ps::Array<MeshMirror>::Iterator mirrorIt;
+ while ((mirrorIt = findMeshMirror(meshPtr)) != mMeshMirrors.end())
+ {
+ physXGpu->releaseMirror(mirrorIt->mirrorHandle);
+ mMeshMirrors.replaceWithLast(mirrorIt);
+ }
+ }
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+
+bool NpPhysicsGpu::createTriangleMeshMirror(const PxTriangleMesh& triangleMesh, PxCudaContextManager& contextManager)
+{
+ const char* functionName = "PxParticleGpu::createTriangleMeshMirror()";
+ PxPhysXGpu* physXGpu = getPhysXGpu(true, functionName);
+ if (!physXGpu)
+ return false;
+
+ const void* meshPtr = (const void*)&triangleMesh;
+ if (!checkNewMirror(meshPtr, contextManager, functionName))
+ return true;
+
+ PxU32 mirrorHandle = physXGpu->createTriangleMeshMirror(triangleMesh, contextManager);
+ if (!checkMirrorHandle(mirrorHandle, functionName))
+ return false;
+
+ addMeshMirror(meshPtr, mirrorHandle, contextManager);
+ return true;
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+void NpPhysicsGpu::releaseTriangleMeshMirror(const PxTriangleMesh& triangleMesh, PxCudaContextManager* contextManager)
+{
+ releaseMeshMirror((const void*)&triangleMesh, "PxParticleGpu::releaseTriangleMeshMirror()", contextManager);
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+bool NpPhysicsGpu::createHeightFieldMirror(const PxHeightField& heightField, PxCudaContextManager& contextManager)
+{
+ const char* functionName = "PxParticleGpu::createHeightFieldMirror()";
+ PxPhysXGpu* physXGpu = getPhysXGpu(true, functionName);
+ if (!physXGpu)
+ return false;
+
+ const void* meshPtr = (const void*)&heightField;
+ if (!checkNewMirror(meshPtr, contextManager, functionName))
+ return true;
+
+ PxU32 mirrorHandle = physXGpu->createHeightFieldMirror(heightField, contextManager);
+ if (!checkMirrorHandle(mirrorHandle, functionName))
+ return false;
+
+ addMeshMirror(meshPtr, mirrorHandle, contextManager);
+ return true;
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+void NpPhysicsGpu::releaseHeightFieldMirror(const PxHeightField& heightField, PxCudaContextManager* contextManager)
+{
+ releaseMeshMirror((const void*)&heightField, "PxParticleGpu::releaseHeightFieldMirror()", contextManager);
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+bool NpPhysicsGpu::createConvexMeshMirror(const PxConvexMesh& convexMesh, PxCudaContextManager& contextManager)
+{
+ const char* functionName = "PxParticleGpu::createConvexMeshMirror()";
+ PxPhysXGpu* physXGpu = getPhysXGpu(true, functionName);
+ if (!physXGpu)
+ return false;
+
+ const void* meshPtr = (const void*)&convexMesh;
+ if (!checkNewMirror(meshPtr, contextManager, functionName))
+ return true;
+
+ PxU32 mirrorHandle = physXGpu->createConvexMeshMirror(convexMesh, contextManager);
+ if (!checkMirrorHandle(mirrorHandle, functionName))
+ return false;
+
+ addMeshMirror(meshPtr, mirrorHandle, contextManager);
+ return true;
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+void NpPhysicsGpu::releaseConvexMeshMirror(const PxConvexMesh& convexMesh, PxCudaContextManager* contextManager)
+{
+ releaseMeshMirror((const void*)&convexMesh, "PxParticleGpu::releaseConvexMeshMirror()", contextManager);
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+namespace
+{
+ PxSceneGpu* getSceneGpu(const PxScene& scene)
+ {
+#if PX_SUPPORT_GPU_PHYSX
+ return ((NpScene*)&scene)->mScene.getScScene().getSceneGpu(true);
+#else
+ return NULL;
+#endif
+ }
+}
+
+void NpPhysicsGpu::setExplicitCudaFlushCountHint(const class PxScene& scene, PxU32 cudaFlushCount)
+{
+ const char* functionName = "PxParticleGpu::setExplicitCudaFlushCountHint()";
+ PxPhysXGpu* physXGpu = getPhysXGpu(true, functionName);
+ if (physXGpu)
+ {
+ PxSceneGpu* gpuScene = getSceneGpu(scene);
+ PX_ASSERT(gpuScene);
+ physXGpu->setExplicitCudaFlushCountHint((PxgSceneGpu&)(*gpuScene), cudaFlushCount);
+ }
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+bool NpPhysicsGpu::setTriangleMeshCacheSizeHint(const class PxScene& scene, PxU32 size)
+{
+ const char* functionName = "PxParticleGpu::setTriangleMeshCacheSizeHint()";
+ PxPhysXGpu* physXGpu = getPhysXGpu(true, functionName);
+ if (physXGpu)
+ {
+ PxSceneGpu* gpuScene = getSceneGpu(scene);
+ PX_ASSERT(gpuScene);
+ return physXGpu->setTriangleMeshCacheSizeHint((PxgSceneGpu&)(*gpuScene), size);
+ }
+ return false;
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+PxTriangleMeshCacheStatistics NpPhysicsGpu::getTriangleMeshCacheStatistics(const class PxScene& scene)
+{
+ PxTriangleMeshCacheStatistics stats;
+
+ const char* functionName = "PxParticleGpu::getTriangleMeshCacheStatistics()";
+ PxPhysXGpu* physXGpu = getPhysXGpu(true, functionName);
+ if (physXGpu)
+ {
+ PxSceneGpu* gpuScene = getSceneGpu(scene);
+ PX_ASSERT(gpuScene);
+ stats = physXGpu->getTriangleMeshCacheStatistics((PxgSceneGpu&)(*gpuScene));
+ }
+ return stats;
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+NpPhysicsGpu::NpPhysicsGpu(NpPhysics& npPhysics) : mMeshMirrors(PX_DEBUG_EXP("NpPhysicsGpu:mMeshMirrors")), mNpPhysics(npPhysics)
+{}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+NpPhysicsGpu::~NpPhysicsGpu()
+{}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+#endif // PX_SUPPORT_GPU_PHYSX
diff --git a/PhysX_3.4/Source/PhysX/src/gpu/NpPhysicsGpu.h b/PhysX_3.4/Source/PhysX/src/gpu/NpPhysicsGpu.h
new file mode 100644
index 00000000..5f3ceb6e
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/gpu/NpPhysicsGpu.h
@@ -0,0 +1,101 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_PHYSICS_GPU
+#define PX_PHYSICS_NP_PHYSICS_GPU
+
+#include "PxPhysXCommonConfig.h"
+#include "PxPhysXConfig.h"
+
+#if PX_SUPPORT_GPU_PHYSX
+
+#include "CmPhysXCommon.h"
+#include "PsArray.h"
+
+namespace physx
+{
+ class PxCudaContextManager;
+}
+
+namespace physx
+{
+
+ struct PxTriangleMeshCacheStatistics;
+
+ class NpPhysicsGpu
+ {
+ public:
+
+ bool createTriangleMeshMirror(const class PxTriangleMesh& triangleMesh, physx::PxCudaContextManager& contextManager);
+ void releaseTriangleMeshMirror(const class PxTriangleMesh& triangleMesh, physx::PxCudaContextManager* contextManager = NULL);
+
+ bool createHeightFieldMirror(const class PxHeightField& heightField, physx::PxCudaContextManager& contextManager);
+ void releaseHeightFieldMirror(const class PxHeightField& heightField, physx::PxCudaContextManager* contextManager = NULL);
+
+ bool createConvexMeshMirror(const class PxConvexMesh& convexMesh, physx::PxCudaContextManager& contextManager);
+ void releaseConvexMeshMirror(const class PxConvexMesh& convexMesh, physx::PxCudaContextManager* contextManager = NULL);
+
+ void setExplicitCudaFlushCountHint(const class PxScene& scene, PxU32 cudaFlushCount);
+ bool setTriangleMeshCacheSizeHint(const class PxScene& scene, PxU32 size);
+ PxTriangleMeshCacheStatistics getTriangleMeshCacheStatistics(const class PxScene& scene);
+
+ NpPhysicsGpu(class NpPhysics& npPhysics);
+ virtual ~NpPhysicsGpu();
+
+ private:
+
+ NpPhysicsGpu& operator=(const NpPhysicsGpu&);
+
+ struct MeshMirror
+ {
+ PxU32 mirrorHandle;
+ physx::PxCudaContextManager* ctx;
+ const void* meshAddress;
+ };
+
+ Ps::Array<MeshMirror>::Iterator findMeshMirror(const void* meshAddress);
+ Ps::Array<MeshMirror>::Iterator findMeshMirror(const void* meshAddress, physx::PxCudaContextManager& ctx);
+ class PxPhysXGpu* getPhysXGpu(bool createIfNeeded, const char* functionName, bool doWarn = true);
+ bool checkNewMirror(const void* meshPtr, physx::PxCudaContextManager& ctx, const char* functionName);
+ bool checkMirrorExists(Ps::Array<MeshMirror>::Iterator it, const char* functionName);
+ bool checkMirrorHandle(PxU32 mirrorHandle, const char* functionName);
+ void addMeshMirror(const void* meshPtr, PxU32 mirrorHandle, physx::PxCudaContextManager& ctx);
+ void removeMeshMirror(const void* meshPtr, PxU32 mirrorHandle);
+ void releaseMeshMirror(const void* meshPtr, const char* functionName, physx::PxCudaContextManager* ctx);
+
+ Ps::Array<MeshMirror> mMeshMirrors;
+ class NpPhysics& mNpPhysics;
+ };
+
+}
+
+#endif
+#endif
+
diff --git a/PhysX_3.4/Source/PhysX/src/gpu/PxGpu.cpp b/PhysX_3.4/Source/PhysX/src/gpu/PxGpu.cpp
new file mode 100644
index 00000000..7b8611b9
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/gpu/PxGpu.cpp
@@ -0,0 +1,68 @@
+// 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.
+
+#include "PxPhysXConfig.h"
+
+#if PX_SUPPORT_GPU_PHYSX
+
+#include "PxGpu.h"
+
+namespace physx
+{
+ //forward declare stuff from PxPhysXGpuModuleLoader.cpp
+ void PxLoadPhysxGPUModule(const char* appGUID);
+ typedef physx::PxCudaContextManager* (PxCreateCudaContextManager_FUNC)(physx::PxFoundation& foundation, const physx::PxCudaContextManagerDesc& desc);
+ typedef int (PxGetSuggestedCudaDeviceOrdinal_FUNC)(physx::PxErrorCallback& errc);
+ extern PxCreateCudaContextManager_FUNC* g_PxCreateCudaContextManager_Func;
+ extern PxGetSuggestedCudaDeviceOrdinal_FUNC* g_PxGetSuggestedCudaDeviceOrdinal_Func;
+
+} // end physx namespace
+
+physx::PxCudaContextManager* PxCreateCudaContextManager(physx::PxFoundation& foundation, const physx::PxCudaContextManagerDesc& desc)
+{
+ if (!physx::g_PxCreateCudaContextManager_Func)
+ physx::PxLoadPhysxGPUModule(desc.appGUID);
+
+ if (physx::g_PxCreateCudaContextManager_Func)
+ return physx::g_PxCreateCudaContextManager_Func(foundation, desc);
+ else
+ return NULL;
+}
+
+int PxGetSuggestedCudaDeviceOrdinal(physx::PxErrorCallback& errc)
+{
+ if (!physx::g_PxGetSuggestedCudaDeviceOrdinal_Func)
+ physx::PxLoadPhysxGPUModule(NULL);
+
+ if (physx::g_PxGetSuggestedCudaDeviceOrdinal_Func)
+ return physx::g_PxGetSuggestedCudaDeviceOrdinal_Func(errc);
+ else
+ return -1;
+}
+
+#endif // PX_SUPPORT_GPU_PHYSX
+
diff --git a/PhysX_3.4/Source/PhysX/src/gpu/PxParticleDeviceExclusive.cpp b/PhysX_3.4/Source/PhysX/src/gpu/PxParticleDeviceExclusive.cpp
new file mode 100644
index 00000000..69ae7456
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/gpu/PxParticleDeviceExclusive.cpp
@@ -0,0 +1,130 @@
+// 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
+#if PX_SUPPORT_GPU_PHYSX
+
+#include "PxParticleDeviceExclusive.h"
+#include "NpParticleSystem.h"
+#include "NpParticleFluid.h"
+
+using namespace physx;
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+void PxParticleDeviceExclusive::enable(PxParticleBase& particleBase)
+{
+ if (particleBase.is<PxParticleSystem>())
+ static_cast<NpParticleSystem*>(particleBase.is<PxParticleSystem>())->enableDeviceExclusiveModeGpu();
+ else if (particleBase.is<PxParticleFluid>())
+ static_cast<NpParticleFluid*>(particleBase.is<PxParticleFluid>())->enableDeviceExclusiveModeGpu();
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+bool PxParticleDeviceExclusive::isEnabled(PxParticleBase& particleBase)
+{
+ if (particleBase.is<PxParticleSystem>())
+ return static_cast<NpParticleSystem*>(particleBase.is<PxParticleSystem>())->isDeviceExclusiveModeEnabledGpu();
+ else if (particleBase.is<PxParticleFluid>())
+ return static_cast<NpParticleFluid*>(particleBase.is<PxParticleFluid>())->isDeviceExclusiveModeEnabledGpu();
+
+ return false;
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+void PxParticleDeviceExclusive::getReadWriteCudaBuffers(PxParticleBase& particleBase, PxCudaReadWriteParticleBuffers& buffers)
+{
+ if (particleBase.is<PxParticleSystem>())
+ static_cast<NpParticleSystem*>(particleBase.is<PxParticleSystem>())->getReadWriteCudaBuffersGpu(buffers);
+ else if (particleBase.is<PxParticleFluid>())
+ static_cast<NpParticleFluid*>(particleBase.is<PxParticleFluid>())->getReadWriteCudaBuffersGpu(buffers);
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+void PxParticleDeviceExclusive::setValidParticleRange(PxParticleBase& particleBase, PxU32 validParticleRange)
+{
+ if (particleBase.is<PxParticleSystem>())
+ static_cast<NpParticleSystem*>(particleBase.is<PxParticleSystem>())->setValidParticleRangeGpu(validParticleRange);
+ else if (particleBase.is<PxParticleFluid>())
+ static_cast<NpParticleFluid*>(particleBase.is<PxParticleFluid>())->setValidParticleRangeGpu(validParticleRange);
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+void PxParticleDeviceExclusive::setFlags(PxParticleBase& particleBase, PxParticleDeviceExclusiveFlags flags)
+{
+ if (particleBase.is<PxParticleSystem>())
+ static_cast<NpParticleSystem*>(particleBase.is<PxParticleSystem>())->setDeviceExclusiveModeFlagsGpu(reinterpret_cast<PxU32&>(flags));
+ else if (particleBase.is<PxParticleFluid>())
+ static_cast<NpParticleFluid*>(particleBase.is<PxParticleFluid>())->setDeviceExclusiveModeFlagsGpu(reinterpret_cast<PxU32&>(flags));
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+class physx::PxBaseTask* PxParticleDeviceExclusive::getLaunchTask(class PxParticleBase& particleBase)
+{
+ if (particleBase.is<PxParticleSystem>())
+ return static_cast<NpParticleSystem*>(particleBase.is<PxParticleSystem>())->getLaunchTaskGpu();
+ else if (particleBase.is<PxParticleFluid>())
+ return static_cast<NpParticleFluid*>(particleBase.is<PxParticleFluid>())->getLaunchTaskGpu();
+
+ return NULL;
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+void PxParticleDeviceExclusive::addLaunchTaskDependent(class PxParticleBase& particleBase, class physx::PxBaseTask& dependent)
+{
+ if (particleBase.is<PxParticleSystem>())
+ static_cast<NpParticleSystem*>(particleBase.is<PxParticleSystem>())->addLaunchTaskDependentGpu(dependent);
+ else if (particleBase.is<PxParticleFluid>())
+ static_cast<NpParticleFluid*>(particleBase.is<PxParticleFluid>())->addLaunchTaskDependentGpu(dependent);
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+CUstream PxParticleDeviceExclusive::getCudaStream(class PxParticleBase& particleBase)
+{
+ if (particleBase.is<PxParticleSystem>())
+ return (CUstream)static_cast<NpParticleSystem*>(particleBase.is<PxParticleSystem>())->getCudaStreamGpu();
+ else if (particleBase.is<PxParticleFluid>())
+ return (CUstream)static_cast<NpParticleFluid*>(particleBase.is<PxParticleFluid>())->getCudaStreamGpu();
+
+ return NULL;
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+#endif // PX_SUPPORT_GPU_PHYSX
+#endif // PX_USE_PARTICLE_SYSTEM_API
diff --git a/PhysX_3.4/Source/PhysX/src/gpu/PxParticleGpu.cpp b/PhysX_3.4/Source/PhysX/src/gpu/PxParticleGpu.cpp
new file mode 100644
index 00000000..a2793b95
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/gpu/PxParticleGpu.cpp
@@ -0,0 +1,89 @@
+// 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 "PxParticleGpu.h"
+
+#if PX_SUPPORT_GPU_PHYSX
+
+#include "NpPhysics.h"
+#include "NpPhysicsGpu.h"
+
+using namespace physx;
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+bool PxParticleGpu::createTriangleMeshMirror(const class PxTriangleMesh& triangleMesh, PxCudaContextManager& contextManager)
+{
+ return NpPhysics::getInstance().getNpPhysicsGpu().createTriangleMeshMirror(triangleMesh, contextManager);
+}
+
+void PxParticleGpu::releaseTriangleMeshMirror(const class PxTriangleMesh& triangleMesh, PxCudaContextManager* contextManager)
+{
+ NpPhysics::getInstance().getNpPhysicsGpu().releaseTriangleMeshMirror(triangleMesh, contextManager);
+}
+
+bool PxParticleGpu::createHeightFieldMirror(const class PxHeightField& heightField, PxCudaContextManager& contextManager)
+{
+ return NpPhysics::getInstance().getNpPhysicsGpu().createHeightFieldMirror(heightField, contextManager);
+}
+
+void PxParticleGpu::releaseHeightFieldMirror(const class PxHeightField& heightField, PxCudaContextManager* contextManager)
+{
+ NpPhysics::getInstance().getNpPhysicsGpu().releaseHeightFieldMirror(heightField, contextManager);
+}
+
+bool PxParticleGpu::createConvexMeshMirror(const class PxConvexMesh& convexMesh, PxCudaContextManager& contextManager)
+{
+ return NpPhysics::getInstance().getNpPhysicsGpu().createConvexMeshMirror(convexMesh, contextManager);
+}
+
+void PxParticleGpu::releaseConvexMeshMirror(const class PxConvexMesh& convexMesh, PxCudaContextManager* contextManager)
+{
+ NpPhysics::getInstance().getNpPhysicsGpu().releaseConvexMeshMirror(convexMesh, contextManager);
+}
+
+void PxParticleGpu::setExplicitCudaFlushCountHint(const class PxScene& scene, PxU32 cudaFlushCount)
+{
+ NpPhysics::getInstance().getNpPhysicsGpu().setExplicitCudaFlushCountHint(scene, cudaFlushCount);
+}
+
+bool PxParticleGpu::setTriangleMeshCacheSizeHint(const class PxScene& scene, PxU32 size)
+{
+ return NpPhysics::getInstance().getNpPhysicsGpu().setTriangleMeshCacheSizeHint(scene, size);
+}
+
+PxTriangleMeshCacheStatistics PxParticleGpu::getTriangleMeshCacheStatistics(const class PxScene& scene)
+{
+ return NpPhysics::getInstance().getNpPhysicsGpu().getTriangleMeshCacheStatistics(scene);
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+#endif // PX_SUPPORT_GPU_PHYSX
diff --git a/PhysX_3.4/Source/PhysX/src/gpu/PxPhysXGpuModuleLoader.cpp b/PhysX_3.4/Source/PhysX/src/gpu/PxPhysXGpuModuleLoader.cpp
new file mode 100644
index 00000000..1d5f7388
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/gpu/PxPhysXGpuModuleLoader.cpp
@@ -0,0 +1,141 @@
+// 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.
+
+#include "PxPhysXConfig.h"
+
+#if PX_SUPPORT_GPU_PHYSX
+
+#include "foundation/Px.h"
+#include "PsFoundation.h"
+#include "PxPhysics.h"
+
+#include "cudamanager/PxCudaContextManager.h"
+
+#define STRINGIFY(x) #x
+#define GETSTRING(x) STRINGIFY(x)
+
+#if PX_X86
+#define PLATFORM_SUB_STR "x86"
+#elif PX_X64
+#define PLATFORM_SUB_STR "x64"
+#endif
+
+#if defined(PX_PHYSX_DLL_NAME_POSTFIX)
+#define CONFIG_SUB_STR GETSTRING(PX_PHYSX_DLL_NAME_POSTFIX)
+#else
+#define CONFIG_SUB_STR
+#endif
+
+#if PX_WINDOWS
+
+#include "windows/PsWindowsInclude.h"
+#include "windows/CmWindowsModuleUpdateLoader.h"
+static const char* gPhysXGpuLibraryName = "PhysX3Gpu" CONFIG_SUB_STR "_" PLATFORM_SUB_STR ".dll";
+
+#elif PX_LINUX
+
+#include <dlfcn.h>
+static const char* gPhysXGpuLibraryName = "./libPhysX3Gpu" CONFIG_SUB_STR "_" PLATFORM_SUB_STR ".so";
+
+#endif // PX_LINUX
+
+#undef GETSTRING
+#undef STRINGIFY
+
+namespace physx
+{
+#if PX_VC
+#pragma warning(disable: 4191) //'operator/operation' : unsafe conversion from 'type of expression' to 'type required'
+#endif
+
+ class PxFoundation;
+ class PxPhysXGpu;
+
+ typedef physx::PxPhysXGpu* (PxCreatePhysXGpu_FUNC)();
+ typedef physx::PxCudaContextManager* (PxCreateCudaContextManager_FUNC)(physx::PxFoundation& foundation, const physx::PxCudaContextManagerDesc& desc);
+ typedef int (PxGetSuggestedCudaDeviceOrdinal_FUNC)(physx::PxErrorCallback& errc);
+
+ PxCreatePhysXGpu_FUNC* g_PxCreatePhysXGpu_Func = NULL;
+ PxCreateCudaContextManager_FUNC* g_PxCreateCudaContextManager_Func = NULL;
+ PxGetSuggestedCudaDeviceOrdinal_FUNC* g_PxGetSuggestedCudaDeviceOrdinal_Func = NULL;
+
+#if PX_WINDOWS
+
+#define DEFAULT_PHYSX_GPU_GUID "D79FA4BF-177C-4841-8091-4375D311D6A3"
+
+ void PxLoadPhysxGPUModule(const char* appGUID)
+ {
+ static HMODULE s_library;
+
+ if (s_library == NULL)
+ s_library = GetModuleHandle(gPhysXGpuLibraryName);
+
+ if (s_library == NULL)
+ {
+ Cm::CmModuleUpdateLoader moduleLoader(UPDATE_LOADER_DLL_NAME);
+ s_library = moduleLoader.LoadModule(gPhysXGpuLibraryName, appGUID == NULL ? DEFAULT_PHYSX_GPU_GUID : appGUID);
+ }
+
+ if (s_library)
+ {
+ g_PxCreatePhysXGpu_Func = (PxCreatePhysXGpu_FUNC*)GetProcAddress(s_library, "PxCreatePhysXGpu");
+ g_PxCreateCudaContextManager_Func = (PxCreateCudaContextManager_FUNC*)GetProcAddress(s_library, "PxCreateCudaContextManager");
+ g_PxGetSuggestedCudaDeviceOrdinal_Func = (PxGetSuggestedCudaDeviceOrdinal_FUNC*)GetProcAddress(s_library, "PxGetSuggestedCudaDeviceOrdinal");
+ }
+ }
+
+#elif PX_LINUX
+
+ void PxLoadPhysxGPUModule(const char*)
+ {
+ static void* s_library;
+
+ if (s_library == NULL)
+ {
+ // load libcuda.so here since gcc configured with --as-needed won't link to it
+ // if there is no call from the binary to it.
+ void* hLibCuda = dlopen("libcuda.so", RTLD_NOW | RTLD_GLOBAL);
+ if (hLibCuda)
+ {
+ s_library = dlopen(gPhysXGpuLibraryName, RTLD_NOW);
+ }
+ }
+
+ // no UpdateLoader
+ if (s_library)
+ {
+ *reinterpret_cast<void**>(&g_PxCreatePhysXGpu_Func) = dlsym(s_library, "PxCreatePhysXGpu");
+ *reinterpret_cast<void**>(&g_PxCreateCudaContextManager_Func) = dlsym(s_library, "PxCreateCudaContextManager");
+ *reinterpret_cast<void**>(&g_PxGetSuggestedCudaDeviceOrdinal_Func) = dlsym(s_library, "PxGetSuggestedCudaDeviceOrdinal");
+ }
+ }
+
+#endif // PX_LINUX
+
+} // end physx namespace
+
+#endif // PX_SUPPORT_GPU_PHYSX \ No newline at end of file
diff --git a/PhysX_3.4/Source/PhysX/src/gpu/PxPhysXIndicatorDeviceExclusive.cpp b/PhysX_3.4/Source/PhysX/src/gpu/PxPhysXIndicatorDeviceExclusive.cpp
new file mode 100644
index 00000000..4c32a1dc
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/gpu/PxPhysXIndicatorDeviceExclusive.cpp
@@ -0,0 +1,50 @@
+// 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"
+#include "PxPhysXIndicatorDeviceExclusive.h"
+#include "NpPhysics.h"
+
+using namespace physx;
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+void PxPhysXIndicatorDeviceExclusive::registerPhysXIndicatorGpuClient(class PxPhysics& physics)
+{
+ static_cast<NpPhysics*>(&physics)->registerPhysXIndicatorGpuClient();
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
+
+void PxPhysXIndicatorDeviceExclusive::unregisterPhysXIndicatorGpuClient(class PxPhysics& physics)
+{
+ static_cast<NpPhysics*>(&physics)->unregisterPhysXIndicatorGpuClient();
+}
+
+//-------------------------------------------------------------------------------------------------------------------//
diff --git a/PhysX_3.4/Source/PhysX/src/particles/NpParticleBaseTemplate.h b/PhysX_3.4/Source/PhysX/src/particles/NpParticleBaseTemplate.h
new file mode 100644
index 00000000..001d3cbd
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/particles/NpParticleBaseTemplate.h
@@ -0,0 +1,925 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_PARTICLESYSTEM_TEMPLATE
+#define PX_PHYSICS_NP_PARTICLESYSTEM_TEMPLATE
+
+#include "PxPhysXConfig.h"
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+#include "NpActorTemplate.h"
+#include "PxParticleSystem.h"
+#include "ScbParticleSystem.h"
+#include "NpWriteCheck.h"
+#include "NpReadCheck.h"
+#include "PtParticleData.h"
+#include "NpScene.h"
+
+#if PX_SUPPORT_GPU_PHYSX
+#include "PxParticleDeviceExclusive.h"
+#endif
+
+namespace physx
+{
+
+template<class APIClass, class LeafClass>
+class NpParticleBaseTemplate : public NpActorTemplate<APIClass>
+{
+public:
+// PX_SERIALIZATION
+ NpParticleBaseTemplate(PxBaseFlags baseFlags) : NpActorTemplate<APIClass>(baseFlags), mParticleSystem(PxEmpty) {}
+//~PX_SERIALIZATION
+ NpParticleBaseTemplate<APIClass, LeafClass>(PxType, PxBaseFlags, const PxActorType::Enum&, PxU32, bool);
+ virtual ~NpParticleBaseTemplate();
+
+ //---------------------------------------------------------------------------------
+ // PxParticleSystemActor implementation
+ //---------------------------------------------------------------------------------
+ virtual void release();
+
+ virtual PxActorType::Enum getType() const { return PxActorType::ePARTICLE_SYSTEM; }
+
+ virtual bool createParticles(const PxParticleCreationData& creationData);
+ virtual void releaseParticles(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer);
+ virtual void releaseParticles();
+ virtual void setPositions(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& positionBuffer);
+ virtual void setVelocities(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& velocityBuffer);
+ virtual void setRestOffsets(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxF32>& restOffsetBuffer);
+ virtual void addForces(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& forceBuffer, PxForceMode::Enum forceMode);
+ virtual PxParticleReadData* lockParticleReadData(PxDataAccessFlags flags);
+ virtual PxParticleReadData* lockParticleReadData();
+
+ virtual PxReal getDamping() const;
+ virtual void setDamping(PxReal);
+ virtual PxVec3 getExternalAcceleration() const;
+ virtual void setExternalAcceleration(const PxVec3&);
+
+ virtual PxReal getParticleMass() const;
+ virtual void setParticleMass(PxReal);
+ virtual PxReal getRestitution() const;
+ virtual void setRestitution(PxReal);
+ virtual PxReal getDynamicFriction() const;
+ virtual void setDynamicFriction(PxReal);
+ virtual PxReal getStaticFriction() const;
+ virtual void setStaticFriction(PxReal);
+
+ virtual void setSimulationFilterData(const PxFilterData& data);
+ virtual PxFilterData getSimulationFilterData() const;
+ virtual void resetFiltering();
+
+ virtual void setParticleBaseFlag(PxParticleBaseFlag::Enum flag, bool value);
+ virtual PxParticleBaseFlags getParticleBaseFlags() const;
+
+ virtual PxParticleReadDataFlags getParticleReadDataFlags() const;
+ virtual void setParticleReadDataFlag(PxParticleReadDataFlag::Enum, bool);
+
+ virtual PxU32 getMaxParticles() const;
+
+ virtual PxReal getMaxMotionDistance() const;
+ virtual void setMaxMotionDistance(PxReal);
+ virtual PxReal getRestOffset() const;
+ virtual void setRestOffset(PxReal);
+ virtual PxReal getContactOffset() const;
+ virtual void setContactOffset(PxReal);
+ virtual PxReal getGridSize() const;
+ virtual void setGridSize(PxReal);
+
+ virtual void getProjectionPlane(PxVec3& normal, PxReal& d) const;
+ virtual void setProjectionPlane(const PxVec3& normal, PxReal d);
+
+ virtual PxBounds3 getWorldBounds(float inflation=1.01f) const;
+
+ typedef NpActorTemplate<APIClass> ActorTemplateClass;
+
+ //---------------------------------------------------------------------------------
+ // Miscellaneous
+ //---------------------------------------------------------------------------------
+ PX_INLINE Scb::Actor& getScbActor() const { return const_cast<Scb::ParticleSystem&>(mParticleSystem); }
+
+ PX_INLINE const Scb::ParticleSystem& getScbParticleSystem() const { return mParticleSystem; }
+ PX_INLINE Scb::ParticleSystem& getScbParticleSystem() { return mParticleSystem; }
+ PX_INLINE NpScene* getNpScene() const { return NpActor::getAPIScene(*this); }
+
+#if PX_SUPPORT_GPU_PHYSX
+ // Helper for reporting error conditions.
+ class PxParticleDeviceExclusiveAccess* getDeviceExclusiveAccessGpu(const char* callerName) const;
+
+ void enableDeviceExclusiveModeGpu();
+ bool isDeviceExclusiveModeEnabledGpu() const;
+ void getReadWriteCudaBuffersGpu(struct PxCudaReadWriteParticleBuffers& buffers) const;
+ void setValidParticleRangeGpu(PxU32 validParticleRange);
+ void setDeviceExclusiveModeFlagsGpu(PxU32 flags);
+ PxBaseTask* getLaunchTaskGpu() const;
+ void addLaunchTaskDependentGpu(class physx::PxBaseTask& dependent);
+ size_t getCudaStreamGpu() const;
+#endif
+
+private:
+ bool checkAllocatedIndices(PxU32 numIndices, const PxStrideIterator<const PxU32>& indices);
+ bool checkFreeIndices(PxU32 numIndices, const PxStrideIterator<const PxU32>& indices);
+
+//private:
+public: // PT: sorry, needs to be accessible to serialization macro
+ Scb::ParticleSystem mParticleSystem;
+};
+
+
+template<class APIClass, class LeafClass>
+NpParticleBaseTemplate<APIClass, LeafClass>::NpParticleBaseTemplate(PxType concreteType, PxBaseFlags baseFlags, const PxActorType::Enum& actorType, PxU32 maxParticles, bool perParticleRestOffset)
+: ActorTemplateClass(concreteType, baseFlags, NULL, NULL)
+, mParticleSystem(actorType, maxParticles, perParticleRestOffset)
+{
+ // don't ref Scb actor here, it hasn't been assigned yet
+}
+
+
+template<class APIClass, class LeafClass>
+NpParticleBaseTemplate<APIClass, LeafClass>::~NpParticleBaseTemplate()
+{
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::release()
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ NpPhysics::getInstance().notifyDeletionListenersUserRelease(this, this->userData);
+
+// PX_AGGREGATE
+ ActorTemplateClass::release(); // PT: added for PxAggregate
+//~PX_AGGREGATE
+
+ NpScene* npScene = NpActor::getAPIScene(*this);
+ if (npScene)
+ {
+ npScene->removeFromParticleBaseList(*this);
+ npScene->getScene().removeParticleSystem(static_cast<LeafClass&>(*this).getScbParticleSystem(), true);
+ }
+ mParticleSystem.destroy();
+}
+
+#if PX_CHECKED
+namespace
+{
+ bool checkUniqueIndices(PxU32 numIndices, const PxStrideIterator<const PxU32>& indices)
+ {
+ Cm::BitMap bitmap;
+ PxU32 i = 0;
+ for (; i != numIndices; ++i)
+ {
+ PxU32 index = indices[i];
+ if (bitmap.boundedTest(index))
+ break;
+ bitmap.growAndSet(index);
+ }
+
+ if (i != numIndices)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxParticleBase::releaseParticles(): indexBuffer contains duplicate particle index %d.", indices[i]);
+ return false;
+ }
+ return true;
+ }
+
+ bool checkVectors(PxU32 numVectors, const PxStrideIterator<const PxVec3>& vectors)
+ {
+ for (PxU32 i = 0; i < numVectors; ++i)
+ {
+ if(!vectors[i].isFinite())
+ return false;
+ }
+ return true;
+ }
+
+ bool checkRestOffsets(PxU32 numParticles, const PxStrideIterator<const PxF32>& restOffsetBuffer, PxF32 restOffset)
+ {
+ for (PxU32 i = 0; i < numParticles; ++i)
+ {
+ if (restOffsetBuffer[i] < 0.0f || restOffsetBuffer[i] > restOffset)
+ return false;
+ }
+ return true;
+ }
+
+ bool checkRestOffset(Pt::ParticleData& standaloneData, PxF32 restOffset)
+ {
+ const PxF32* restOffsetBuffer = standaloneData.getRestOffsetBuffer();
+ PxU32 numParticles = standaloneData.getMaxParticles();
+ for (PxU32 i = 0; i < numParticles; ++i)
+ {
+ if (restOffsetBuffer[i] > restOffset)
+ return false;
+ }
+ return true;
+ }
+}
+#endif // PX_CHECKED
+
+//----------------------------------------------------------------------------//
+
+template<class APIClass, class LeafClass>
+bool NpParticleBaseTemplate<APIClass, LeafClass>::checkAllocatedIndices(PxU32 numIndices, const PxStrideIterator<const PxU32>& indices)
+{
+ const Cm::BitMap& map = mParticleSystem.getParticleMap();
+ PxU32 maxParticles = getMaxParticles();
+
+ for (PxU32 i = 0; i < numIndices; ++i)
+ {
+ PxU32 index = indices[i];
+
+ if (index >= maxParticles)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "Operation on particle index %d not in valid range [0, %d]", index, getMaxParticles() - 1);
+ return false;
+ }
+
+ if (!map.boundedTest(index))
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "Operation on invalid particle with index %d", index);
+ return false;
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------//
+
+template<class APIClass, class LeafClass>
+bool NpParticleBaseTemplate<APIClass, LeafClass>::checkFreeIndices(PxU32 numIndices, const PxStrideIterator<const PxU32>& indices)
+{
+ const Cm::BitMap& map = mParticleSystem.getParticleMap();
+ PxU32 maxParticles = getMaxParticles();
+
+ for (PxU32 i = 0; i < numIndices; ++i)
+ {
+ PxU32 index = indices[i];
+
+ if (index >= maxParticles)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "Provided particle index %d is not in valid range [0, %d]", index, getMaxParticles() - 1);
+ return false;
+ }
+
+ if (map.boundedTest(index))
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "Provided particle index %d is already in use", index);
+ return false;
+ }
+ }
+ return true;
+}
+
+//----------------------------------------------------------------------------//
+
+template<class APIClass, class LeafClass>
+bool NpParticleBaseTemplate<APIClass, LeafClass>::createParticles(const PxParticleCreationData& creationData)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PX_CHECK_AND_RETURN_NULL(creationData.isValid(), "PxParticleCreationData submitted with PxParticleBase::createParticles() invalid.");
+ if (creationData.numParticles == 0)
+ return true;
+
+ bool supportsPerParticleRestOffset = getScbParticleSystem().getFlags() & PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET;
+ bool perParticleRestOffset = creationData.restOffsetBuffer.ptr() != NULL;
+
+ PX_UNUSED(supportsPerParticleRestOffset);
+ PX_UNUSED(perParticleRestOffset);
+
+ PX_CHECK_AND_RETURN_NULL(!perParticleRestOffset || supportsPerParticleRestOffset, "PxParticleCreationData.restOffsetBuffer set but PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET not set.")
+ PX_CHECK_AND_RETURN_NULL(!supportsPerParticleRestOffset || perParticleRestOffset, "PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET set, but PxParticleCreationData.restOffsetBuffer not set.")
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN_NULL(checkFreeIndices(creationData.numParticles, creationData.indexBuffer), "PxParticleBase::createParticles: failed");
+ PX_CHECK_AND_RETURN_NULL(checkUniqueIndices(creationData.numParticles, creationData.indexBuffer), "PxParticleBase::createParticles: failed");
+
+ if (perParticleRestOffset)
+ PX_CHECK_AND_RETURN_NULL(checkRestOffsets(creationData.numParticles, creationData.restOffsetBuffer, getScbParticleSystem().getRestOffset()),
+ "PxParticleCreationData.restOffsetBuffer: offsets must be in range [0.0f, restOffset].");
+
+ PX_CHECK_AND_RETURN_NULL(checkVectors(creationData.numParticles, creationData.positionBuffer), "PxParticleBase::createParticles: position vectors shoule be finite");
+
+ bool perParticleVelocity = creationData.velocityBuffer.ptr() != NULL;
+ if(perParticleVelocity)
+ {
+ PX_CHECK_AND_RETURN_NULL(checkVectors(creationData.numParticles, creationData.velocityBuffer), "PxParticleBase::createParticles: velocity vectors shoule be finite");
+ }
+#endif
+
+ return getScbParticleSystem().createParticles(creationData);
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::releaseParticles(PxU32 numParticles, const PxStrideIterator<const PxU32>& indices)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ if (numParticles == 0)
+ return;
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN(indices.ptr() && indices.stride() != 0, "PxParticleBase::releaseParticles: invalid index buffer");
+ PX_CHECK_AND_RETURN(checkAllocatedIndices(numParticles, indices), "PxParticleBase::releaseParticles: failed");
+ PX_CHECK_AND_RETURN(checkUniqueIndices(numParticles, indices), "PxParticleBase::releaseParticles: failed");
+#endif
+
+ getScbParticleSystem().releaseParticles(numParticles, indices);
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::releaseParticles()
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ getScbParticleSystem().releaseParticles();
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setPositions(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& positionBuffer)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ if (numParticles == 0)
+ return;
+
+ PX_CHECK_AND_RETURN(indexBuffer.ptr() && indexBuffer.stride() != 0, "PxParticleBase::setPositions: invalid index buffer");
+ PX_CHECK_AND_RETURN(positionBuffer.ptr(), "PxParticleBase::setPositions: invalid position buffer");
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN(checkAllocatedIndices(numParticles, indexBuffer), "PxParticleBase::setPositions: failed");
+ PX_CHECK_AND_RETURN(checkVectors(numParticles, positionBuffer), "PxParticleBase::setPositions: position vectors shoule be finite");
+#endif
+
+ getScbParticleSystem().setPositions(numParticles, indexBuffer, positionBuffer);
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setVelocities(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& velocityBuffer)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ if (numParticles == 0)
+ return;
+
+ PX_CHECK_AND_RETURN(indexBuffer.ptr() && indexBuffer.stride() != 0, "PxParticleBase::setVelocities: invalid index buffer");
+ PX_CHECK_AND_RETURN(velocityBuffer.ptr(), "PxParticleBase::setVelocities: invalid velocity buffer");
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN(checkAllocatedIndices(numParticles, indexBuffer), "PxParticleBase::setVelocities: failed");
+ PX_CHECK_AND_RETURN(checkVectors(numParticles, velocityBuffer), "PxParticleBase::setVelocities: velocity vectors shoule be finite");
+#endif
+ getScbParticleSystem().setVelocities(numParticles, indexBuffer, velocityBuffer);
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setRestOffsets(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxF32>& restOffsetBuffer)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ if (numParticles == 0)
+ return;
+
+ PX_CHECK_AND_RETURN(indexBuffer.ptr() && indexBuffer.stride() != 0, "PxParticleBase::setRestOffsets: invalid index buffer");
+ PX_CHECK_AND_RETURN(restOffsetBuffer.ptr(), "PxParticleBase::restOffsets: invalid restOffset buffer");
+
+ PX_CHECK_AND_RETURN(getScbParticleSystem().getFlags() & PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET, "PxParticleBase::setRestOffsets: PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET not set");
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN(checkAllocatedIndices(numParticles, indexBuffer), "PxParticleBase::setRestOffsets: failed");
+ PX_CHECK_AND_RETURN(checkRestOffsets(numParticles, restOffsetBuffer, getScbParticleSystem().getRestOffset()),
+ "PxParticleBase::restOffsets: offsets must be in range [0.0f, restOffset].");
+#endif
+ getScbParticleSystem().setRestOffsets(numParticles, indexBuffer, restOffsetBuffer);
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::addForces(PxU32 numParticles, const PxStrideIterator<const PxU32>& indexBuffer,
+ const PxStrideIterator<const PxVec3>& forceBuffer, PxForceMode::Enum forceMode)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ if (!getNpScene())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Attempt to add forces on particle system which isn't assigned to any scene.");
+ return;
+ }
+
+ if (numParticles == 0)
+ return;
+
+ PX_CHECK_AND_RETURN(indexBuffer.ptr() && indexBuffer.stride() != 0, "PxParticleBase::addForces: invalid index buffer");
+ PX_CHECK_AND_RETURN(forceBuffer.ptr(), "PxParticleBase::addForces: invalid force buffer");
+
+#if PX_CHECKED
+ PX_CHECK_AND_RETURN(checkAllocatedIndices(numParticles, indexBuffer), "PxParticleBase::addForces: failed");
+ PX_CHECK_AND_RETURN(checkVectors(numParticles, forceBuffer), "PxParticleBase::addForces: force vectors shoule be finite");
+#endif
+
+ getScbParticleSystem().addForces(numParticles, indexBuffer, forceBuffer, forceMode);
+}
+
+template<class APIClass, class LeafClass>
+PxParticleReadData* NpParticleBaseTemplate<APIClass, LeafClass>::lockParticleReadData(PxDataAccessFlags flags)
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().lockParticleReadData(flags);
+}
+
+template<class APIClass, class LeafClass>
+PxParticleReadData* NpParticleBaseTemplate<APIClass, LeafClass>::lockParticleReadData()
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().lockParticleReadData(PxDataAccessFlag::eREADABLE);
+}
+
+
+template<class APIClass, class LeafClass>
+PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getDamping() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getDamping();
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setDamping(PxReal d)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(d >= 0.0f,"Damping is not allowed to be negative, PxParticleBase::setDamping() ignored.");
+ getScbParticleSystem().setDamping(d);
+}
+
+
+template<class APIClass, class LeafClass>
+PxVec3 NpParticleBaseTemplate<APIClass, LeafClass>::getExternalAcceleration() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getExternalAcceleration();
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setExternalAcceleration(const PxVec3& a)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ getScbParticleSystem().setExternalAcceleration(a);
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::getProjectionPlane(PxVec3& normal, PxReal& d) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ PxPlane p = getScbParticleSystem().getProjectionPlane();
+ normal = p.n;
+ d = p.d;
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setProjectionPlane(const PxVec3& normal, PxReal d)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(!normal.isZero(),"Plane normal needs to be non zero, PxParticleBase::setProjectionPlane() ignored.");
+
+ PxPlane p(normal, d);
+ getScbParticleSystem().setProjectionPlane(p);
+}
+
+
+template<class APIClass, class LeafClass>
+PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getParticleMass() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getParticleMass();
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setParticleMass(PxReal m)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(m > 0.0f, "ParticleMass needs to be positive, PxParticleBase::setParticleMass() ignored.");
+ getScbParticleSystem().setParticleMass(m);
+}
+
+
+template<class APIClass, class LeafClass>
+PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getRestitution() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getRestitution();
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setRestitution(PxReal r)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(r >= 0.0f && r <= 1.0f,"Restitution needs to be in [0,1], PxParticleBase::setRestitution() ignored.");
+ getScbParticleSystem().setRestitution(r);
+}
+
+
+template<class APIClass, class LeafClass>
+PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getDynamicFriction() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getDynamicFriction();
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setDynamicFriction(PxReal a)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(a >= 0.0f && a <= 1.0f,"Dynamic Friction needs to be in [0,1], PxParticleBase::setDynamicFriction() ignored.");
+ getScbParticleSystem().setDynamicFriction(a);
+}
+
+
+template<class APIClass, class LeafClass>
+PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getStaticFriction() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getStaticFriction();
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setStaticFriction(PxReal a)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(a >= 0.0f,"Static Friction needs to be positive, PxParticleBase::setStaticFriction() ignored.");
+ getScbParticleSystem().setStaticFriction(a);
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setSimulationFilterData(const PxFilterData& data)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ getScbParticleSystem().setSimulationFilterData(data);
+}
+
+
+template<class APIClass, class LeafClass>
+PxFilterData NpParticleBaseTemplate<APIClass, LeafClass>::getSimulationFilterData() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getSimulationFilterData();
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::resetFiltering()
+{
+ physx::shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_INFO, __FILE__, __LINE__, "PxParticleBase::resetFiltering: This method has been deprecated!");
+
+ NpScene* scene = NpActor::getOwnerScene(*this);
+ if (scene)
+ scene->resetFiltering(*this);
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setParticleBaseFlag(PxParticleBaseFlag::Enum flag, bool value)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ // flags that are generally immutable
+ if (flag == PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET flag is not modifiable. Operation ignored.");
+ return;
+ }
+
+ PxParticleBaseFlags flags = getScbParticleSystem().getFlags();
+ if(value)
+ flags |= flag;
+ else
+ flags &= ~flag;
+
+ getScbParticleSystem().setFlags(flags);
+
+ if (getNpScene())
+ getNpScene()->updatePhysXIndicator();
+}
+
+
+template<class APIClass, class LeafClass>
+PxParticleBaseFlags NpParticleBaseTemplate<APIClass, LeafClass>::getParticleBaseFlags() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getFlags();
+}
+
+template<class APIClass, class LeafClass>
+PxParticleReadDataFlags NpParticleBaseTemplate<APIClass, LeafClass>::getParticleReadDataFlags() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getParticleReadDataFlags();
+}
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setParticleReadDataFlag(PxParticleReadDataFlag::Enum flag, bool value)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"PxParticleReadDataFlag immutable when the particle system is part of a scene.");
+ PxParticleReadDataFlags flags = getScbParticleSystem().getParticleReadDataFlags();
+
+ PX_CHECK_AND_RETURN(!(flag == PxParticleReadDataFlag::eREST_OFFSET_BUFFER && value)
+ || (getScbParticleSystem().getFlags() & PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET),
+ "PxParticleReadDataFlag::eREST_OFFSET_BUFFER not supported without specifying per particle rest offsets on calling "
+ "PxPhysics::createParticleSystem or PxPhysics::createParticleFluid.");
+
+ if(value)
+ flags |= flag;
+ else
+ flags &= ~flag;
+
+ getScbParticleSystem().setParticleReadDataFlags(flags);
+}
+
+template<class APIClass, class LeafClass>
+PxU32 NpParticleBaseTemplate<APIClass, LeafClass>::getMaxParticles() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getMaxParticles();
+}
+
+
+template<class APIClass, class LeafClass>
+PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getMaxMotionDistance() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getMaxMotionDistance();
+}
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setMaxMotionDistance(PxReal d)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(d >= 0.0f,"MaxMotionDistance needs to be positive, PxParticleBase::setMaxMotionDistance() ignored.");
+ PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"MaxMotionDistance immutable when the particle system is part of a scene.");
+ getScbParticleSystem().setMaxMotionDistance(d);
+}
+
+template<class APIClass, class LeafClass>
+PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getRestOffset() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getRestOffset();
+}
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setRestOffset(PxReal r)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(r >= 0.0f,"RestOffset needs to be positive, PxParticleBase::setRestOffset() ignored.");
+ PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"RestOffset immutable when the particle system is part of a scene.");
+#if PX_CHECKED
+ if(getParticleBaseFlags() & PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET)
+ {
+ Pt::ParticleData* standaloneData = getScbParticleSystem().getScParticleSystem().obtainStandaloneData();
+ PX_ASSERT(standaloneData);
+ bool pass = checkRestOffset(*standaloneData, r);
+ getScbParticleSystem().getScParticleSystem().returnStandaloneData(standaloneData);
+ PX_CHECK_AND_RETURN(pass, "PxParticleBase::restOffset: offset must be larger than each perParticle restOffset.");
+ }
+#endif
+ getScbParticleSystem().setRestOffset(r);
+}
+
+template<class APIClass, class LeafClass>
+PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getContactOffset() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getContactOffset();
+}
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setContactOffset(PxReal c)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(c >= 0.0f,"ContactOffset needs to be positive, PxParticleBase::setContactOffset() ignored.");
+ PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"ContactOffset immutable when the particle system is part of a scene.");
+ getScbParticleSystem().setContactOffset(c);
+}
+
+template<class APIClass, class LeafClass>
+PxReal NpParticleBaseTemplate<APIClass, LeafClass>::getGridSize() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ return getScbParticleSystem().getGridSize();
+}
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setGridSize(PxReal g)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+ PX_CHECK_AND_RETURN(g >= 0.0f,"GridSize needs to be positive, PxParticleBase::setGridSize() ignored.");
+ PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"GridSize immutable when the particle system is part of a scene.");
+ getScbParticleSystem().setGridSize(g);
+}
+
+template<class APIClass, class LeafClass>
+PxBounds3 NpParticleBaseTemplate<APIClass, LeafClass>::getWorldBounds(float inflation) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+ const PxBounds3 bounds = getScbParticleSystem().getWorldBounds();
+ PX_ASSERT(bounds.isValid());
+
+ // PT: unfortunately we can't just scale the min/max vectors, we need to go through center/extents.
+ const PxVec3 center = bounds.getCenter();
+ const PxVec3 inflatedExtents = bounds.getExtents() * inflation;
+ return PxBounds3::centerExtents(center, inflatedExtents);
+}
+
+
+#if PX_SUPPORT_GPU_PHYSX
+
+template<class APIClass, class LeafClass>
+PxParticleDeviceExclusiveAccess* NpParticleBaseTemplate<APIClass, LeafClass>::getDeviceExclusiveAccessGpu(const char* callerName) const
+{
+ PxParticleDeviceExclusiveAccess* access = NULL;
+ if (getNpScene() && (getParticleBaseFlags() & PxParticleBaseFlag::eGPU))
+ {
+ access = getScbParticleSystem().getDeviceExclusiveAccessGpu();
+ }
+
+ if (!access)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "%s is only allowed to be called if the particle system is in device exclusive mode. "
+ "Please refer to PxParticleDeviceExclusive::enable and PxParticleDeviceExclusive::isEnabled.", callerName);
+ }
+
+ return access;
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::enableDeviceExclusiveModeGpu()
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ if (!getNpScene())
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxParticleDeviceExclusive::enable is not allowed to be called if the particle system is not in a scene.");
+ return;
+ }
+
+ if (!(getParticleBaseFlags() & PxParticleBaseFlag::eGPU))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxParticleDeviceExclusive::enable is not allowed for non PxParticleBaseFlag::eGPU particle systems.");
+ return;
+ }
+
+ getScbParticleSystem().enableDeviceExclusiveModeGpu();
+}
+
+
+template<class APIClass, class LeafClass>
+bool NpParticleBaseTemplate<APIClass, LeafClass>::isDeviceExclusiveModeEnabledGpu() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ if (!getNpScene() || !(getParticleBaseFlags() & PxParticleBaseFlag::eGPU))
+ {
+ return false;
+ }
+
+ return getScbParticleSystem().getDeviceExclusiveAccessGpu() != NULL;
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::getReadWriteCudaBuffersGpu(PxCudaReadWriteParticleBuffers& buffers) const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::getReadWriteCudaBuffers");
+ if (access)
+ {
+ access->getReadWriteCudaBuffers(buffers);
+ }
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setValidParticleRangeGpu(PxU32 validParticleRange)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::setValidParticleRange");
+ if (access)
+ {
+ access->setValidParticleRange(validParticleRange);
+ }
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::setDeviceExclusiveModeFlagsGpu(PxU32 flags)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::setFlags");
+ if (access)
+ {
+ access->setFlags(flags);
+ }
+}
+
+
+template<class APIClass, class LeafClass>
+physx::PxBaseTask* NpParticleBaseTemplate<APIClass, LeafClass>::getLaunchTaskGpu() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::getLaunchTask");
+ if (access)
+ {
+ return access->getLaunchTask();
+ }
+ return NULL;
+}
+
+
+template<class APIClass, class LeafClass>
+void NpParticleBaseTemplate<APIClass, LeafClass>::addLaunchTaskDependentGpu(class physx::PxBaseTask& dependent)
+{
+ NP_WRITE_CHECK(NpActor::getOwnerScene(*this));
+
+ PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::addLaunchTaskDependent");
+ if (access)
+ {
+ access->addLaunchTaskDependent(dependent);
+ }
+}
+
+
+template<class APIClass, class LeafClass>
+size_t NpParticleBaseTemplate<APIClass, LeafClass>::getCudaStreamGpu() const
+{
+ NP_READ_CHECK(NpActor::getOwnerScene(*this));
+
+ PxParticleDeviceExclusiveAccess* access = getDeviceExclusiveAccessGpu("PxParticleDeviceExclusive::getCudaStream");
+ if (access)
+ {
+ return access->getCudaStream();
+ }
+ return 0;
+}
+
+
+#endif
+}
+
+#endif // PX_USE_PARTICLE_SYSTEM_API
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/particles/NpParticleFluid.cpp b/PhysX_3.4/Source/PhysX/src/particles/NpParticleFluid.cpp
new file mode 100644
index 00000000..2e68e1b2
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/particles/NpParticleFluid.cpp
@@ -0,0 +1,132 @@
+// 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 "NpParticleFluid.h"
+#include "ScbParticleSystem.h"
+#include "NpWriteCheck.h"
+#include "NpReadCheck.h"
+
+using namespace physx;
+
+NpParticleFluid::NpParticleFluid(PxU32 maxParticles, bool perParticleRestOffset)
+: ParticleSystemTemplateClass(PxConcreteType::ePARTICLE_FLUID, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE, PxActorType::ePARTICLE_FLUID, maxParticles, perParticleRestOffset)
+{}
+
+NpParticleFluid::~NpParticleFluid()
+{
+}
+
+// PX_SERIALIZATION
+NpParticleFluid* NpParticleFluid::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpParticleFluid* obj = new (address) NpParticleFluid(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpParticleFluid);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+PxParticleFluidReadData* NpParticleFluid::lockParticleFluidReadData(PxDataAccessFlags flags)
+{
+ return static_cast<PxParticleFluidReadData*>(lockParticleReadData(flags));
+}
+
+PxParticleFluidReadData* NpParticleFluid::lockParticleFluidReadData()
+{
+ return static_cast<PxParticleFluidReadData*>(lockParticleReadData());
+}
+
+void* NpParticleFluid::is(PxActorType::Enum type)
+{
+ if (type == PxActorType::ePARTICLE_FLUID)
+ return reinterpret_cast<void*>(static_cast<PxParticleFluid*>(this));
+ else
+ return NULL;
+}
+
+
+const void* NpParticleFluid::is(PxActorType::Enum type) const
+{
+ if (type == PxActorType::ePARTICLE_FLUID)
+ return reinterpret_cast<const void*>(static_cast<const PxParticleFluid*>(this));
+ else
+ return NULL;
+}
+
+
+PxReal NpParticleFluid::getStiffness() const
+{
+ NP_READ_CHECK(getNpScene());
+ return getScbParticleSystem().getStiffness();
+}
+
+
+void NpParticleFluid::setStiffness(PxReal s)
+{
+ NP_WRITE_CHECK(getNpScene());
+ PX_CHECK_AND_RETURN(s > 0.0f,"Stiffness needs to be positive, PxParticleFluid::setStiffness() ignored.");
+ getScbParticleSystem().setStiffness(s);
+}
+
+
+PxReal NpParticleFluid::getViscosity() const
+{
+ NP_READ_CHECK(getNpScene());
+ return getScbParticleSystem().getViscosity();
+}
+
+
+void NpParticleFluid::setViscosity(PxReal v)
+{
+ NP_WRITE_CHECK(getNpScene());
+ PX_CHECK_AND_RETURN(v > 0.0f,"Viscosity needs to be positive, PxParticleFluid::setViscosity() ignored.");
+ getScbParticleSystem().setViscosity(v);
+}
+
+
+PxReal NpParticleFluid::getRestParticleDistance() const
+{
+ NP_READ_CHECK(getNpScene());
+ return getScbParticleSystem().getRestParticleDistance();
+}
+
+void NpParticleFluid::setRestParticleDistance(PxReal r)
+{
+ NP_WRITE_CHECK(getNpScene());
+ PX_CHECK_AND_RETURN(r > 0.0f,"RestParticleDistance needs to be positive, PxParticleFluid::setRestParticleDistance() ignored.");
+ PX_CHECK_AND_RETURN(!getScbParticleSystem().getScParticleSystem().getSim(),"RestParticleDistance immutable when the particle system is part of a scene.");
+ getScbParticleSystem().setRestParticleDistance(r);
+}
+
+#endif // PX_USE_PARTICLE_SYSTEM_API
diff --git a/PhysX_3.4/Source/PhysX/src/particles/NpParticleFluid.h b/PhysX_3.4/Source/PhysX/src/particles/NpParticleFluid.h
new file mode 100644
index 00000000..da2f8234
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/particles/NpParticleFluid.h
@@ -0,0 +1,94 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_PARTICLEFLUID
+#define PX_PHYSICS_NP_PARTICLEFLUID
+
+#include "PxPhysXConfig.h"
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+#include "NpParticleSystem.h"
+
+namespace physx
+{
+
+class NpParticleFluid;
+
+typedef NpParticleBaseTemplate<PxParticleFluid, NpParticleFluid> NpParticleFluidT;
+class NpParticleFluid : public NpParticleFluidT
+{
+//= 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
+ NpParticleFluid(PxBaseFlags baseFlags) : NpParticleFluidT(baseFlags) {}
+ virtual void requires(PxProcessPxBaseCallback&){}
+ virtual void exportExtraData(PxSerializationContext& stream) { mParticleSystem.exportExtraData(stream); }
+ void importExtraData(PxDeserializationContext& context) { mParticleSystem.importExtraData(context); }
+ static NpParticleFluid* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ NpParticleFluid(PxU32 maxParticles, bool perParticleRestOffset);
+ virtual ~NpParticleFluid();
+
+ //---------------------------------------------------------------------------------
+ // PxParticleFluid implementation
+ //---------------------------------------------------------------------------------
+ virtual PxActorType::Enum getType() const { return PxActorType::ePARTICLE_FLUID; }
+
+ virtual void* is(PxActorType::Enum type);
+ virtual const void* is(PxActorType::Enum type) const;
+
+ virtual PxParticleFluidReadData* lockParticleFluidReadData(PxDataAccessFlags flags);
+ virtual PxParticleFluidReadData* lockParticleFluidReadData();
+
+ virtual PxReal getStiffness() const;
+ virtual void setStiffness(PxReal);
+ virtual PxReal getViscosity() const;
+ virtual void setViscosity(PxReal);
+
+ virtual PxReal getRestParticleDistance() const;
+ virtual void setRestParticleDistance(PxReal);
+
+private:
+ typedef NpParticleBaseTemplate<PxParticleFluid, NpParticleFluid> ParticleSystemTemplateClass;
+
+};
+
+}
+
+#endif // PX_USE_PARTICLE_SYSTEM_API
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/particles/NpParticleFluidReadData.h b/PhysX_3.4/Source/PhysX/src/particles/NpParticleFluidReadData.h
new file mode 100644
index 00000000..a9cec5d5
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/particles/NpParticleFluidReadData.h
@@ -0,0 +1,85 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_PARTICLE_FLUID_READ_DATA
+#define PX_PHYSICS_NP_PARTICLE_FLUID_READ_DATA
+
+#include "PxParticleFluidReadData.h"
+#include "PsFoundation.h"
+
+namespace physx
+{
+
+class NpParticleFluidReadData : public PxParticleFluidReadData, public Ps::UserAllocated
+{
+public:
+
+ NpParticleFluidReadData() :
+ mIsLocked(false),
+ mFlags(PxDataAccessFlag::eREADABLE)
+ {
+ strncpy(mLastLockedName, "UNDEFINED", sBufferLength);
+ }
+
+ virtual ~NpParticleFluidReadData()
+ {}
+
+ // implementation for PxLockedData
+ virtual void setDataAccessFlags(PxDataAccessFlags flags) { mFlags = flags; }
+ virtual PxDataAccessFlags getDataAccessFlags() { return mFlags; }
+
+ virtual void unlock() { unlockFast(); }
+
+ // internal methods
+ void unlockFast() { mIsLocked = false; }
+
+ void lock(const char* callerName)
+ {
+ if (mIsLocked)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__, "PxParticleReadData access through %s while its still locked by last call of %s.", callerName, mLastLockedName);
+ PX_ALWAYS_ASSERT_MESSAGE("PxParticleReadData access violation");
+ }
+ strncpy(mLastLockedName, callerName, sBufferLength);
+ mLastLockedName[sBufferLength-1]=0;
+ mIsLocked = true;
+ }
+
+private:
+
+ static const PxU32 sBufferLength = 128;
+ bool mIsLocked;
+ char mLastLockedName[sBufferLength];
+ PxDataAccessFlags mFlags;
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/particles/NpParticleSystem.cpp b/PhysX_3.4/Source/PhysX/src/particles/NpParticleSystem.cpp
new file mode 100644
index 00000000..e93dd763
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/particles/NpParticleSystem.cpp
@@ -0,0 +1,70 @@
+// 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 "NpParticleSystem.h"
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+#include "PsFoundation.h"
+#include "NpPhysics.h"
+
+#include "NpScene.h"
+#include "NpWriteCheck.h"
+
+#include "PsArray.h"
+
+using namespace physx;
+
+NpParticleSystem::NpParticleSystem(PxU32 maxParticles, bool perParticleRestOffset)
+: ParticleSystemTemplateClass(PxConcreteType::ePARTICLE_SYSTEM, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE, PxActorType::ePARTICLE_SYSTEM, maxParticles, perParticleRestOffset)
+{}
+
+NpParticleSystem::~NpParticleSystem()
+{}
+
+// PX_SERIALIZATION
+NpParticleSystem* NpParticleSystem::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ NpParticleSystem* obj = new (address) NpParticleSystem(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(NpParticleSystem);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+//~PX_SERIALIZATION
+
+void NpParticleSystem::setParticleReadDataFlag(PxParticleReadDataFlag::Enum flag, bool val)
+{
+ NP_WRITE_CHECK(getNpScene());
+ PX_CHECK_AND_RETURN( flag != PxParticleReadDataFlag::eDENSITY_BUFFER,
+ "ParticleSystem has unsupported PxParticleReadDataFlag::eDENSITY_BUFFER set.");
+ NpParticleSystemT::setParticleReadDataFlag(flag, val);
+}
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/particles/NpParticleSystem.h b/PhysX_3.4/Source/PhysX/src/particles/NpParticleSystem.h
new file mode 100644
index 00000000..8ff947e8
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/particles/NpParticleSystem.h
@@ -0,0 +1,95 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PX_PHYSICS_NP_PARTICLESYSTEM
+#define PX_PHYSICS_NP_PARTICLESYSTEM
+
+#include "PxPhysXConfig.h"
+
+#if PX_USE_PARTICLE_SYSTEM_API
+
+#include "particles/PxParticleSystem.h"
+#include "NpParticleBaseTemplate.h"
+
+#include "ScbParticleSystem.h"
+
+// PX_SERIALIZATION
+#include "PxSerialFramework.h"
+//~PX_SERIALIZATION
+
+namespace physx
+{
+
+class NpScene;
+class NpParticleSystem;
+
+namespace Scb
+{
+ class ParticleSystem;
+}
+
+typedef NpParticleBaseTemplate<PxParticleSystem, NpParticleSystem> NpParticleSystemT;
+class NpParticleSystem : public NpParticleSystemT
+{
+//= 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
+ NpParticleSystem(PxBaseFlags baseFlags) : NpParticleSystemT(baseFlags) {}
+ virtual void requires(PxProcessPxBaseCallback&) {}
+ virtual void exportExtraData(PxSerializationContext& stream) { mParticleSystem.exportExtraData(stream); }
+ void importExtraData(PxDeserializationContext& context) { mParticleSystem.importExtraData(context); }
+ static NpParticleSystem* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+
+//~PX_SERIALIZATION
+ NpParticleSystem(PxU32 maxParticles, bool perParticleRestOffset);
+ virtual ~NpParticleSystem();
+
+ virtual void setParticleReadDataFlag(PxParticleReadDataFlag::Enum flag, bool val);
+
+ //---------------------------------------------------------------------------------
+ // PxParticleSystem implementation
+ //---------------------------------------------------------------------------------
+ virtual PxActorType::Enum getType() const { return PxActorType::ePARTICLE_SYSTEM; }
+
+private:
+ typedef NpParticleBaseTemplate<PxParticleSystem, NpParticleSystem> ParticleSystemTemplateClass;
+};
+
+}
+
+#endif // PX_USE_PARTICLE_SYSTEM_API
+
+#endif
diff --git a/PhysX_3.4/Source/PhysX/src/windows/NpWindowsDelayLoadHook.cpp b/PhysX_3.4/Source/PhysX/src/windows/NpWindowsDelayLoadHook.cpp
new file mode 100644
index 00000000..9bd62808
--- /dev/null
+++ b/PhysX_3.4/Source/PhysX/src/windows/NpWindowsDelayLoadHook.cpp
@@ -0,0 +1,82 @@
+// 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 "windows/PxWindowsDelayLoadHook.h"
+#include "windows/PsWindowsInclude.h"
+#include "windows/CmWindowsLoadLibrary.h"
+
+// Prior to Visual Studio 2015 Update 3, these hooks were non-const.
+#define DELAYIMP_INSECURE_WRITABLE_HOOKS
+#include <delayimp.h>
+
+static const physx::PxDelayLoadHook* gDelayLoadHook = NULL;
+
+void physx::PxSetPhysXDelayLoadHook(const physx::PxDelayLoadHook* hook)
+{
+ gDelayLoadHook = hook;
+}
+
+using namespace physx;
+
+#pragma comment(lib, "delayimp")
+
+FARPROC WINAPI delayHook(unsigned dliNotify, PDelayLoadInfo pdli)
+{
+ switch (dliNotify) {
+ case dliStartProcessing :
+ break;
+
+ case dliNotePreLoadLibrary :
+ {
+ return Cm::physXCommonDliNotePreLoadLibrary(pdli->szDll,gDelayLoadHook);
+ }
+ break;
+
+ case dliNotePreGetProcAddress :
+ break;
+
+ case dliFailLoadLib :
+ break;
+
+ case dliFailGetProc :
+ break;
+
+ case dliNoteEndProcessing :
+ break;
+
+ default :
+
+ return NULL;
+ }
+
+ return NULL;
+}
+
+PfnDliHook __pfnDliNotifyHook2 = delayHook;