aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/PhysXExtensions/src
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/PhysXExtensions/src
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/PhysXExtensions/src')
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtBroadPhase.cpp74
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtClothFabricCooker.cpp648
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtClothGeodesicTetherCooker.cpp1022
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtClothMeshQuadifier.cpp441
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtClothSimpleTetherCooker.cpp141
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtCollection.cpp252
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtConstraintHelper.h378
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtConvexMeshExt.cpp91
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.cpp106
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.h79
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.cpp564
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.h207
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtD6JointSolverPrep.cpp232
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.cpp236
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.h111
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultErrorCallback.cpp104
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultSimulationFilterShader.cpp386
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultStreams.cpp193
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.cpp215
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.h162
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJointSolverPrep.cpp111
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtExtensions.cpp212
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.cpp173
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.h135
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJointSolverPrep.cpp69
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtInertiaTensor.h404
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.cpp134
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.h500
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtJointMetaDataExtensions.h65
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtMetaData.cpp447
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtParticleExt.cpp356
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtPlatform.h39
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.cpp219
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.h155
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJointSolverPrep.cpp81
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.cpp164
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.h188
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtPxStringTable.cpp99
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtRaycastCCD.cpp305
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.cpp287
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.h184
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJointSolverPrep.cpp117
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtRigidBodyExt.cpp648
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtSceneQueryExt.cpp197
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtSerialization.h44
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtSharedQueueEntryPool.h156
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtSimpleFactory.cpp385
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtSmoothNormals.cpp145
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.cpp228
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.h151
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJointSolverPrep.cpp87
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtTaskQueueHelper.h66
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/ExtTriangleMeshExt.cpp183
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp305
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinarySerialization.cpp402
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.cpp156
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.h182
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.cpp63
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.h44
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Common.h43
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Convert.cpp1434
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Error.cpp92
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.cpp840
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.h186
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.cpp451
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.h112
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.cpp90
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.h45
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.cpp94
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.h303
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/File/SnFile.h85
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.cpp151
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.h50
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialization.cpp433
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.cpp287
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.h91
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnJointRepXSerializer.cpp137
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnPxStreamOperators.h134
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX1_0Defaults.h245
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_1Defaults.h274
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_2Defaults.h313
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCollection.h173
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.cpp1158
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.h156
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXSerializerImpl.h90
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.cpp444
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.h53
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnSimpleXmlWriter.h257
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlDeserializer.h188
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlImpl.h242
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryAllocator.h129
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPool.h373
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPoolStreams.h173
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlReader.h130
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerialization.cpp834
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerializer.h117
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSimpleXmlWriter.h215
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlStringToType.h275
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorReader.h889
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorWriter.h765
-rw-r--r--PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlWriter.h57
101 files changed, 26136 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtBroadPhase.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtBroadPhase.cpp
new file mode 100644
index 00000000..0e079323
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtBroadPhase.cpp
@@ -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.
+
+
+#include "foundation/PxBounds3.h"
+#include "PxBroadPhaseExt.h"
+#include "PsFoundation.h"
+#include "CmPhysXCommon.h"
+
+using namespace physx;
+
+PxU32 PxBroadPhaseExt::createRegionsFromWorldBounds(PxBounds3* regions, const PxBounds3& globalBounds, PxU32 nbSubdiv, PxU32 upAxis)
+{
+ PX_CHECK_MSG(globalBounds.isValid(), "PxBroadPhaseExt::createRegionsFromWorldBounds(): invalid bounds provided!");
+ PX_CHECK_MSG(upAxis<3, "PxBroadPhaseExt::createRegionsFromWorldBounds(): invalid up-axis provided!");
+
+ const PxVec3& min = globalBounds.minimum;
+ const PxVec3& max = globalBounds.maximum;
+ const float dx = (max.x - min.x) / float(nbSubdiv);
+ const float dy = (max.y - min.y) / float(nbSubdiv);
+ const float dz = (max.z - min.z) / float(nbSubdiv);
+ PxU32 nbRegions = 0;
+ PxVec3 currentMin, currentMax;
+ for(PxU32 j=0;j<nbSubdiv;j++)
+ {
+ for(PxU32 i=0;i<nbSubdiv;i++)
+ {
+ if(upAxis==0)
+ {
+ currentMin = PxVec3(min.x, min.y + dy * float(i), min.z + dz * float(j));
+ currentMax = PxVec3(max.x, min.y + dy * float(i+1), min.z + dz * float(j+1));
+ }
+ else if(upAxis==1)
+ {
+ currentMin = PxVec3(min.x + dx * float(i), min.y, min.z + dz * float(j));
+ currentMax = PxVec3(min.x + dx * float(i+1), max.y, min.z + dz * float(j+1));
+ }
+ else if(upAxis==2)
+ {
+ currentMin = PxVec3(min.x + dx * float(i), min.y + dy * float(j), min.z);
+ currentMax = PxVec3(min.x + dx * float(i+1), min.y + dy * float(j+1), max.z);
+ }
+
+ regions[nbRegions++] = PxBounds3(currentMin, currentMax);
+ }
+ }
+ return nbRegions;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtClothFabricCooker.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothFabricCooker.cpp
new file mode 100644
index 00000000..f59f26b2
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothFabricCooker.cpp
@@ -0,0 +1,648 @@
+// 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/PxVec4.h"
+#include "foundation/PxIO.h"
+#include "foundation/PxStrideIterator.h"
+#include "extensions/PxClothFabricCooker.h"
+#include "extensions/PxClothTetherCooker.h"
+#include "PxPhysics.h"
+#include "PsFoundation.h"
+#include "PsArray.h"
+#include "PsHashMap.h"
+#include "PsSort.h"
+
+using namespace physx;
+
+struct physx::PxFabricCookerImpl
+{
+ bool cook(const PxClothMeshDesc& desc, PxVec3 gravity, bool useGeodesicTether);
+
+ PxClothFabricDesc getDescriptor() const;
+ void save(PxOutputStream& stream, bool platformMismatch) const;
+
+public:
+ PxU32 mNumParticles;
+
+ shdfnd::Array<PxClothFabricPhase> mPhases;
+ shdfnd::Array<PxU32> mSets; // with 0 prefix
+ shdfnd::Array<PxReal> mRestvalues;
+ shdfnd::Array<PxU32> mIndices;
+
+ shdfnd::Array<PxU32> mTetherAnchors;
+ shdfnd::Array<PxReal> mTetherLengths;
+
+ shdfnd::Array<PxU32> mTriangles;
+};
+
+PxClothFabricCooker::PxClothFabricCooker(const PxClothMeshDesc& desc, const PxVec3& gravity, bool useGeodesicTether)
+: mImpl(new PxFabricCookerImpl())
+{
+ mImpl->cook(desc, gravity, useGeodesicTether);
+}
+
+PxClothFabricCooker::~PxClothFabricCooker()
+{
+ delete mImpl;
+}
+
+PxClothFabricDesc PxClothFabricCooker::getDescriptor() const
+{
+ return mImpl->getDescriptor();
+}
+
+void PxClothFabricCooker::save(PxOutputStream& stream, bool platformMismatch) const
+{
+ mImpl->save(stream, platformMismatch);
+}
+
+
+PxClothFabric* physx::PxClothFabricCreate( PxPhysics& physics, const PxClothMeshDesc& desc, const PxVec3& gravity, bool useGeodesicTether )
+{
+ PxFabricCookerImpl impl;
+
+ if(!impl.cook(desc, gravity, useGeodesicTether))
+ return 0;
+
+ return physics.createClothFabric(impl.getDescriptor());
+}
+
+namespace
+{
+ // calculate the inclusive prefix sum, equivalent of std::partial_sum
+ template <typename T>
+ void prefixSum(const T* first, const T* last, T* dest)
+ {
+ if (first != last)
+ {
+ *(dest++) = *(first++);
+ for (; first != last; ++first, ++dest)
+ *dest = *(dest-1) + *first;
+ }
+ }
+
+ template <typename T>
+ void gatherAdjacencies(shdfnd::Array<PxU32>& valency, shdfnd::Array<PxU32>& adjacencies,
+ const PxBoundedData& triangles, const PxBoundedData& quads)
+ {
+ // count number of edges per vertex
+ PxStrideIterator<const T> tIt, qIt;
+ tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride);
+ for(PxU32 i=0; i<triangles.count; ++i, ++tIt, ++qIt)
+ {
+ for(PxU32 j=0; j<3; ++j)
+ valency[tIt.ptr()[j]] += 2;
+ }
+ qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride);
+ for(PxU32 i=0; i<quads.count; ++i, ++tIt, ++qIt)
+ {
+ for(PxU32 j=0; j<4; ++j)
+ valency[qIt.ptr()[j]] += 2;
+ }
+
+ prefixSum(valency.begin(), valency.end(), valency.begin());
+ adjacencies.resize(valency.back());
+
+ // gather adjacent vertices
+ tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride);
+ for(PxU32 i=0; i<triangles.count; ++i, ++tIt)
+ {
+ for(PxU32 j=0; j<3; ++j)
+ {
+ adjacencies[--valency[tIt.ptr()[j]]] = tIt.ptr()[(j+1)%3];
+ adjacencies[--valency[tIt.ptr()[j]]] = tIt.ptr()[(j+2)%3];
+ }
+ }
+ qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride);
+ for(PxU32 i=0; i<quads.count; ++i, ++qIt)
+ {
+ for(PxU32 j=0; j<4; ++j)
+ {
+ adjacencies[--valency[qIt.ptr()[j]]] = qIt.ptr()[(j+1)%4];
+ adjacencies[--valency[qIt.ptr()[j]]] = qIt.ptr()[(j+3)%4];
+ }
+ }
+ }
+
+ template <typename T>
+ void gatherTriangles(shdfnd::Array<PxU32>& indices, const PxBoundedData& triangles, const PxBoundedData& quads)
+ {
+ indices.reserve(triangles.count * 3 + quads.count * 6);
+
+ PxStrideIterator<const T> tIt, qIt;
+ tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride);
+ for (PxU32 i = 0; i<triangles.count; ++i, ++tIt, ++qIt)
+ {
+ for (PxU32 j = 0; j<3; ++j)
+ indices.pushBack(tIt.ptr()[j]);
+ }
+ qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride);
+ for (PxU32 i = 0; i<quads.count; ++i, ++tIt, ++qIt)
+ {
+ indices.pushBack(qIt.ptr()[0]);
+ indices.pushBack(qIt.ptr()[1]);
+ indices.pushBack(qIt.ptr()[2]);
+ indices.pushBack(qIt.ptr()[2]);
+ indices.pushBack(qIt.ptr()[3]);
+ indices.pushBack(qIt.ptr()[0]);
+ }
+ }
+
+
+ struct Edge
+ {
+ Edge() : mStretching(0.0f), mBending(0.0f), mShearing(0.0f) {}
+
+ void classify()
+ {
+ mStretching += 0.1f;
+ }
+
+ // classify v0-v2 edge based on alternative v0-v1-v2 path
+ void classify(const PxVec4& v0, const PxVec4& v1, const PxVec4& v2)
+ {
+ const PxVec3& p0 = reinterpret_cast<const PxVec3&>(v0);
+ const PxVec3& p1 = reinterpret_cast<const PxVec3&>(v1);
+ const PxVec3& p2 = reinterpret_cast<const PxVec3&>(v2);
+
+ PxReal area = (p1-p0).cross(p2-p1).magnitude();
+ // triangle height / base length
+ // 1.0 = quad edge, 0.2 = quad diagonal + quad edge,
+ PxReal ratio = area / (p2-p0).magnitudeSquared();
+
+ // 0.5 = quad diagonal
+ mShearing += PxMax(0.0f, 0.15f - fabsf(0.45f - ratio));
+ // 0.0 = collinear points
+ mBending += PxMax(0.0f, 0.1f - ratio) * 3;
+ }
+
+ PxReal mStretching;
+ PxReal mBending;
+ PxReal mShearing;
+ };
+
+ typedef shdfnd::Pair<PxU32, PxU32> Pair;
+ typedef shdfnd::Pair<Pair, PxClothFabricPhaseType::Enum> Entry;
+
+ // maintain heap status after elements have been pushed (heapify)
+ template<typename T>
+ void pushHeap(shdfnd::Array<T> &heap, const T &value)
+ {
+ heap.pushBack(value);
+ T* begin = heap.begin();
+ T* end = heap.end();
+
+ if (end <= begin)
+ return;
+
+ PxU32 current = PxU32(end - begin) - 1;
+ while (current > 0)
+ {
+ const PxU32 parent = (current - 1) / 2;
+ if (!(begin[parent] < begin[current]))
+ break;
+
+ shdfnd::swap(begin[parent], begin[current]);
+ current = parent;
+ }
+ }
+
+ // pop one element from the heap
+ template<typename T>
+ T popHeap(shdfnd::Array<T> &heap)
+ {
+ T* begin = heap.begin();
+ T* end = heap.end();
+
+ shdfnd::swap(begin[0], end[-1]); // exchange elements
+
+ // shift down
+ end--;
+
+ PxU32 current = 0;
+ while (begin + (current * 2 + 1) < end)
+ {
+ PxU32 child = current * 2 + 1;
+ if (begin + child + 1 < end && begin[child] < begin[child + 1])
+ ++child;
+
+ if (!(begin[current] < begin[child]))
+ break;
+
+ shdfnd::swap(begin[current], begin[child]);
+ current = child;
+ }
+
+ return heap.popBack();
+ }
+
+ // ---------------------------------------------------------------------------------------
+ // Heap element to sort constraint based on graph color count
+ struct ConstraintGraphColorCount
+ {
+ ConstraintGraphColorCount(PxU32 cid, PxU32 count)
+ : constraint(cid), colorCount(count) {}
+
+ PxU32 constraint;
+ PxU32 colorCount;
+
+ bool operator < (const ConstraintGraphColorCount& c) const
+ {
+ return colorCount < c.colorCount;
+ }
+ };
+
+ struct ConstraintSorter
+ {
+ public:
+
+ ConstraintSorter(PxU32* constraints_) : constraints(constraints_) {}
+
+ bool operator()(PxU32 i, PxU32 j) const
+ {
+ PxU32 ci = i*2;
+ PxU32 cj = j*2;
+
+ if (constraints[ci] == constraints[cj])
+ return constraints[ci+1] < constraints[cj+1];
+ else
+ return constraints[ci] < constraints[cj];
+ }
+
+ PxU32* constraints;
+ };
+
+} // anonymous namespace
+
+bool PxFabricCookerImpl::cook(const PxClothMeshDesc& desc, PxVec3 gravity, bool useGeodesicTether)
+{
+ if(!desc.isValid())
+ {
+ shdfnd::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxFabricCookerImpl::cook: desc.isValid() failed!");
+ return false;
+ }
+
+ gravity = gravity.getNormalized();
+
+ mNumParticles = desc.points.count;
+
+ // assemble points
+ shdfnd::Array<PxVec4> particles;
+ particles.reserve(mNumParticles);
+ PxStrideIterator<const PxVec3> pIt(reinterpret_cast<const PxVec3*>(desc.points.data), desc.points.stride);
+ PxStrideIterator<const PxReal> wIt(reinterpret_cast<const PxReal*>(desc.invMasses.data), desc.invMasses.stride);
+ for(PxU32 i=0; i<mNumParticles; ++i)
+ particles.pushBack(PxVec4(*pIt++, wIt.ptr() ? *wIt++ : 1.0f));
+
+ // build adjacent vertex list
+ shdfnd::Array<PxU32> valency(mNumParticles+1, 0);
+ shdfnd::Array<PxU32> adjacencies;
+ if (desc.flags & PxMeshFlag::e16_BIT_INDICES)
+ {
+ gatherTriangles<PxU16>(mTriangles, desc.triangles, desc.quads);
+ gatherAdjacencies<PxU16>(valency, adjacencies, desc.triangles, desc.quads);
+ }
+ else
+ {
+ gatherTriangles<PxU32>(mTriangles, desc.triangles, desc.quads);
+ gatherAdjacencies<PxU32>(valency, adjacencies, desc.triangles, desc.quads);
+ }
+
+ // build unique neighbors from adjacencies
+ shdfnd::Array<PxU32> mark(valency.size(), 0);
+ shdfnd::Array<PxU32> neighbors; neighbors.reserve(adjacencies.size());
+ for(PxU32 i=1, j=0; i<valency.size(); ++i)
+ {
+ for(; j<valency[i]; ++j)
+ {
+ PxU32 k = adjacencies[j];
+ if(mark[k] != i)
+ {
+ mark[k] = i;
+ neighbors.pushBack(k);
+ }
+ }
+ valency[i] = neighbors.size();
+ }
+
+ // build map of unique edges and classify
+ shdfnd::HashMap<Pair, Edge> edges;
+ for(PxU32 i=0; i<mNumParticles; ++i)
+ {
+ PxReal wi = particles[i].w;
+ // iterate all neighbors
+ PxU32 jlast = valency[i+1];
+ for(PxU32 j=valency[i]; j<jlast; ++j)
+ {
+ // add 1-ring edge
+ PxU32 m = neighbors[j];
+ if(wi + particles[m].w > 0.0f)
+ edges[Pair(PxMin(i, m), PxMax(i, m))].classify();
+
+ // iterate all neighbors of neighbor
+ PxU32 klast = valency[m+1];
+ for(PxU32 k=valency[m]; k<klast; ++k)
+ {
+ PxU32 n = neighbors[k];
+ if(n != i && wi + particles[n].w > 0.0f)
+ {
+ // add 2-ring edge
+ edges[Pair(PxMin(i, n), PxMax(i, n))].classify(
+ particles[i], particles[m], particles[n]);
+ }
+ }
+ }
+ }
+
+ // copy classified edges to constraints array
+ // build histogram of constraints per vertex
+ shdfnd::Array<Entry> constraints;
+ constraints.reserve(edges.size());
+ valency.resize(0); valency.resize(mNumParticles+1, 0);
+
+ const PxReal sqrtHalf = PxSqrt(0.4f);
+ for(shdfnd::HashMap<Pair, Edge>::Iterator eIt = edges.getIterator(); !eIt.done(); ++eIt)
+ {
+ const Edge& edge = eIt->second;
+ const Pair& pair = eIt->first;
+ if((edge.mStretching + edge.mBending + edge.mShearing) > 0.0f)
+ {
+ PxClothFabricPhaseType::Enum type = PxClothFabricPhaseType::eINVALID;
+ if(edge.mBending > PxMax(edge.mStretching, edge.mShearing))
+ type = PxClothFabricPhaseType::eBENDING;
+ else if(edge.mShearing > PxMax(edge.mStretching, edge.mBending))
+ type = PxClothFabricPhaseType::eSHEARING;
+ else
+ {
+ PxVec4 diff = particles[pair.first]-particles[pair.second];
+ PxReal dot = gravity.dot(reinterpret_cast<const PxVec3&>(diff).getNormalized());
+ type = fabsf(dot) < sqrtHalf ? PxClothFabricPhaseType::eHORIZONTAL : PxClothFabricPhaseType::eVERTICAL;
+ }
+ ++valency[pair.first];
+ ++valency[pair.second];
+ constraints.pushBack(Entry(pair, type));
+ }
+ }
+
+ prefixSum(valency.begin(), valency.end(), valency.begin());
+
+ PxU32 numConstraints = constraints.size();
+
+ // build adjacent constraint list
+ adjacencies.resize(0); adjacencies.resize(valency.back(), 0);
+ for(PxU32 i=0; i<numConstraints; ++i)
+ {
+ adjacencies[--valency[constraints[i].first.first]] = i;
+ adjacencies[--valency[constraints[i].first.second]] = i;
+ }
+
+ shdfnd::Array<PxU32>::ConstIterator aFirst = adjacencies.begin();
+ shdfnd::Array<PxU32> colors(numConstraints, numConstraints); // constraint -> color, initialily not colored
+ mark.resize(0); mark.resize(numConstraints+1, PX_MAX_U32); // color -> constraint index
+ shdfnd::Array<PxU32> adjColorCount(numConstraints, 0); // # of neighbors that are already colored
+
+ shdfnd::Array<ConstraintGraphColorCount> constraintHeap;
+ constraintHeap.reserve(numConstraints); // set of constraints to color (added in edge distance order)
+
+ // Do graph coloring based on edge distance.
+ // For each constraint, we add its uncolored neighbors to the heap
+ // ,and we pick the constraint with most colored neighbors from the heap.
+ for(;;)
+ {
+ PxU32 constraint = 0;
+ while ( (constraint < numConstraints) && (colors[constraint] != numConstraints))
+ constraint++; // start with the first uncolored constraint
+
+ if (constraint >= numConstraints)
+ break;
+
+ constraintHeap.clear();
+ pushHeap(constraintHeap, ConstraintGraphColorCount(constraint, adjColorCount[constraint]));
+ PxClothFabricPhaseType::Enum type = constraints[constraint].second;
+
+ while (!constraintHeap.empty())
+ {
+ ConstraintGraphColorCount heapItem = popHeap(constraintHeap);
+ constraint = heapItem.constraint;
+ if (colors[constraint] != numConstraints)
+ continue; // skip if already colored
+
+ const Pair& pair = constraints[constraint].first;
+ for(PxU32 j=0; j<2; ++j)
+ {
+ PxU32 index = j ? pair.first : pair.second;
+ if(particles[index].w == 0.0f)
+ continue; // don't mark adjacent particles if attached
+
+ for(shdfnd::Array<PxU32>::ConstIterator aIt = aFirst + valency[index], aEnd = aFirst + valency[index+1]; aIt != aEnd; ++aIt)
+ {
+ PxU32 adjacentConstraint = *aIt;
+ if ((constraints[adjacentConstraint].second != type) || (adjacentConstraint == constraint))
+ continue;
+
+ mark[colors[adjacentConstraint]] = constraint;
+ ++adjColorCount[adjacentConstraint];
+ pushHeap(constraintHeap, ConstraintGraphColorCount(adjacentConstraint, adjColorCount[adjacentConstraint]));
+ }
+ }
+
+ // find smallest color with matching type
+ PxU32 color = 0;
+ while((color < mPhases.size() && mPhases[color].phaseType != type) || mark[color] == constraint)
+ ++color;
+
+ // create a new color set
+ if(color == mPhases.size())
+ {
+ PxClothFabricPhase phase(type, mPhases.size());
+ mPhases.pushBack(phase);
+ mSets.pushBack(0);
+ }
+
+ colors[constraint] = color;
+ ++mSets[color];
+ }
+ }
+
+#if 0 // PX_DEBUG
+ printf("set[%u] = ", mSets.size());
+ for(PxU32 i=0; i<mSets.size(); ++i)
+ printf("%u ", mSets[i]);
+#endif
+
+ prefixSum(mSets.begin(), mSets.end(), mSets.begin());
+
+#if 0 // PX_DEBUG
+ printf(" = %u\n", mSets.back());
+#endif
+
+ // write indices and rest lengths
+ // convert mSets to exclusive sum
+ PxU32 back = mSets.back();
+ mSets.pushBack(back);
+ mIndices.resize(numConstraints*2);
+ mRestvalues.resize(numConstraints);
+ for(PxU32 i=0; i<numConstraints; ++i)
+ {
+ PxU32 first = constraints[i].first.first;
+ PxU32 second = constraints[i].first.second;
+
+ PxU32 index = --mSets[colors[i]];
+
+ mIndices[2*index ] = first;
+ mIndices[2*index+1] = second;
+
+ PxVec4 diff = particles[second] - particles[first];
+ mRestvalues[index] = reinterpret_cast<
+ const PxVec3&>(diff).magnitude();
+ }
+
+ // reorder constraints and rest values for more efficient cache access (linear)
+ shdfnd::Array<PxU32> newIndices(mIndices.size());
+ shdfnd::Array<PxF32> newRestValues(mRestvalues.size());
+
+ // sort each constraint set in vertex order
+ for (PxU32 i=0; i < mSets.size()-1; ++i)
+ {
+ // create a re-ordering list
+ shdfnd::Array<PxU32> reorder(mSets[i+1]-mSets[i]);
+
+ for (PxU32 r=0; r < reorder.size(); ++r)
+ reorder[r] = r;
+
+ const PxU32 indicesOffset = mSets[i]*2;
+ const PxU32 restOffset = mSets[i];
+
+ ConstraintSorter predicate(&mIndices[indicesOffset]);
+ shdfnd::sort(&reorder[0], reorder.size(), predicate);
+
+ for (PxU32 r=0; r < reorder.size(); ++r)
+ {
+ newIndices[indicesOffset + r*2] = mIndices[indicesOffset + reorder[r]*2];
+ newIndices[indicesOffset + r*2+1] = mIndices[indicesOffset + reorder[r]*2+1];
+ newRestValues[restOffset + r] = mRestvalues[restOffset + reorder[r]];
+ }
+ }
+
+ mIndices = newIndices;
+ mRestvalues = newRestValues;
+
+ PX_ASSERT(mIndices.size() == mRestvalues.size()*2);
+ PX_ASSERT(mRestvalues.size() == mSets.back());
+
+#if 0 // PX_DEBUG
+ for (PxU32 i = 1; i < mSets.size(); i++)
+ {
+ PxClothFabricPhase phase = mPhases[i-1];
+ printf("%d : type %d, size %d\n",
+ i-1, phase.phaseType, mSets[i] - mSets[i-1]);
+ }
+#endif
+
+ if (useGeodesicTether)
+ {
+ PxClothGeodesicTetherCooker tetherCooker(desc);
+ if (tetherCooker.getCookerStatus() == 0)
+ {
+ PxU32 numTethersPerParticle = tetherCooker.getNbTethersPerParticle();
+ PxU32 tetherSize = mNumParticles * numTethersPerParticle;
+ mTetherAnchors.resize(tetherSize);
+ mTetherLengths.resize(tetherSize);
+ tetherCooker.getTetherData(mTetherAnchors.begin(), mTetherLengths.begin());
+ }
+ else
+ useGeodesicTether = false;
+ }
+
+ if (!useGeodesicTether)
+ {
+ PxClothSimpleTetherCooker tetherCooker(desc);
+ mTetherAnchors.resize(mNumParticles);
+ mTetherLengths.resize(mNumParticles);
+ tetherCooker.getTetherData(mTetherAnchors.begin(), mTetherLengths.begin());
+ }
+
+ return true;
+}
+
+physx::PxClothFabricDesc physx::PxFabricCookerImpl::getDescriptor() const
+{
+ PxClothFabricDesc result;
+
+ result.nbParticles = mNumParticles;
+ result.nbPhases = mPhases.size();
+ result.phases = mPhases.begin();
+ result.nbSets = mSets.size()-1;
+ result.sets = mSets.begin()+1;
+ result.restvalues = mRestvalues.begin();
+ result.indices = mIndices.begin();
+ result.nbTethers = mTetherAnchors.size();
+ result.tetherAnchors = mTetherAnchors.begin();
+ result.tetherLengths = mTetherLengths.begin();
+ result.nbTriangles = mTriangles.size() / 3;
+ result.triangles = mTriangles.begin();
+
+ return result;
+}
+
+void physx::PxFabricCookerImpl::save( PxOutputStream& stream, bool /*platformMismatch*/ ) const
+{
+ // version 1 is equivalent to 0x030300 and 0x030301 (PX_PHYSICS_VERSION of 3.3.0 and 3.3.1).
+ // If the stream format changes, the loader code in ScClothFabricCore.cpp
+ // and the version number need to change too.
+ PxU32 version = 1;
+ stream.write(&version, sizeof(PxU32));
+
+ PxClothFabricDesc desc = getDescriptor();
+
+ // write explicit sizes, others are implicit
+ stream.write(&mNumParticles, sizeof(PxU32));
+ stream.write(&desc.nbPhases, sizeof(PxU32));
+ stream.write(&desc.nbSets, sizeof(PxU32));
+ stream.write(&desc.nbTethers, sizeof(PxU32));
+
+ PxU32 nbConstraints = desc.sets[desc.nbSets-1];
+
+ // write actual data
+ PX_COMPILE_TIME_ASSERT(sizeof(PxClothFabricPhaseType::Enum) == sizeof(PxU32));
+ stream.write(desc.phases, desc.nbPhases*sizeof(PxClothFabricPhase));
+ stream.write(desc.sets, desc.nbSets*sizeof(PxU32));
+
+ stream.write(desc.restvalues, nbConstraints*sizeof(PxReal));
+ stream.write(desc.indices, nbConstraints*2*sizeof(PxU32));
+
+ stream.write(desc.tetherAnchors, desc.nbTethers*sizeof(PxU32));
+ stream.write(desc.tetherLengths, desc.nbTethers*sizeof(PxReal));
+}
+
+#endif //PX_USE_CLOTH_API
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtClothGeodesicTetherCooker.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothGeodesicTetherCooker.cpp
new file mode 100644
index 00000000..c4338f53
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothGeodesicTetherCooker.cpp
@@ -0,0 +1,1022 @@
+// 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/PxVec4.h"
+#include "foundation/PxMemory.h"
+#include "foundation/PxStrideIterator.h"
+#include "extensions/PxClothTetherCooker.h"
+
+// from shared foundation
+#include <PsFoundation.h>
+#include <PsSort.h>
+#include <Ps.h>
+#include <PsMathUtils.h>
+#include "PsArray.h"
+
+using namespace physx;
+
+
+namespace
+{
+ // calculate the inclusive prefix sum, equivalent of std::partial_sum
+ template <typename T>
+ void prefixSum(const T* first, const T* last, T* dest)
+ {
+ if (first != last)
+ {
+ *(dest++) = *(first++);
+ for (; first != last; ++first, ++dest)
+ *dest = *(dest-1) + *first;
+ }
+ }
+
+ template <typename T>
+ void gatherAdjacencies(shdfnd::Array<PxU32>& valency, shdfnd::Array<PxU32>& adjacencies,
+ const PxBoundedData& triangles, const PxBoundedData& quads)
+ {
+ // count number of edges per vertex
+ PxStrideIterator<const T> tIt, qIt;
+ tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride);
+ for(PxU32 i=0; i<triangles.count; ++i, ++tIt, ++qIt)
+ {
+ for(PxU32 j=0; j<3; ++j)
+ valency[tIt.ptr()[j]] += 2;
+ }
+ qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride);
+ for(PxU32 i=0; i<quads.count; ++i, ++tIt, ++qIt)
+ {
+ for(PxU32 j=0; j<4; ++j)
+ valency[qIt.ptr()[j]] += 2;
+ }
+
+ prefixSum(valency.begin(), valency.end(), valency.begin());
+ adjacencies.resize(valency.back());
+
+ // gather adjacent vertices
+ tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride);
+ for(PxU32 i=0; i<triangles.count; ++i, ++tIt)
+ {
+ for(PxU32 j=0; j<3; ++j)
+ {
+ adjacencies[--valency[tIt.ptr()[j]]] = tIt.ptr()[(j+1)%3];
+ adjacencies[--valency[tIt.ptr()[j]]] = tIt.ptr()[(j+2)%3];
+ }
+ }
+ qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride);
+ for(PxU32 i=0; i<quads.count; ++i, ++qIt)
+ {
+ for(PxU32 j=0; j<4; ++j)
+ {
+ adjacencies[--valency[qIt.ptr()[j]]] = qIt.ptr()[(j+1)%4];
+ adjacencies[--valency[qIt.ptr()[j]]] = qIt.ptr()[(j+3)%4];
+ }
+ }
+ }
+
+ template <typename T>
+ void gatherIndices(shdfnd::Array<PxU32>& indices,
+ const PxBoundedData& triangles, const PxBoundedData& quads)
+ {
+ PxStrideIterator<const T> tIt, qIt;
+
+ indices.reserve(triangles.count * 3 + quads.count * 6);
+
+ tIt = PxMakeIterator(reinterpret_cast<const T*>(triangles.data), triangles.stride);
+ for(PxU32 i=0; i<triangles.count; ++i, ++tIt)
+ {
+ indices.pushBack(tIt.ptr()[0]);
+ indices.pushBack(tIt.ptr()[1]);
+ indices.pushBack(tIt.ptr()[2]);
+ }
+ qIt = PxMakeIterator(reinterpret_cast<const T*>(quads.data), quads.stride);
+ for(PxU32 i=0; i<quads.count; ++i, ++qIt)
+ {
+ indices.pushBack(qIt.ptr()[0]);
+ indices.pushBack(qIt.ptr()[1]);
+ indices.pushBack(qIt.ptr()[2]);
+ indices.pushBack(qIt.ptr()[0]);
+ indices.pushBack(qIt.ptr()[2]);
+ indices.pushBack(qIt.ptr()[3]);
+ }
+ }
+
+ // maintain heap status after elements have been pushed (heapify)
+ template<typename T>
+ void pushHeap(shdfnd::Array<T> &heap, const T &value)
+ {
+ heap.pushBack(value);
+ T* begin = heap.begin();
+ T* end = heap.end();
+
+ if (end <= begin)
+ return;
+
+ PxU32 current = PxU32(end - begin) - 1;
+ while (current > 0)
+ {
+ const PxU32 parent = (current - 1) / 2;
+ if (!(begin[parent] < begin[current]))
+ break;
+
+ shdfnd::swap(begin[parent], begin[current]);
+ current = parent;
+ }
+ }
+
+ // pop one element from the heap
+ template<typename T>
+ T popHeap(shdfnd::Array<T> &heap)
+ {
+ T* begin = heap.begin();
+ T* end = heap.end();
+
+ shdfnd::swap(begin[0], end[-1]); // exchange elements
+
+ // shift down
+ end--;
+
+ PxU32 current = 0;
+ while (begin + (current * 2 + 1) < end)
+ {
+ PxU32 child = current * 2 + 1;
+ if (begin + child + 1 < end && begin[child] < begin[child + 1])
+ ++child;
+
+ if (!(begin[current] < begin[child]))
+ break;
+
+ shdfnd::swap(begin[current], begin[child]);
+ current = child;
+ }
+
+ return heap.popBack();
+ }
+
+ // ---------------------------------------------------------------------------------------
+ struct VertexDistanceCount
+ {
+ VertexDistanceCount(int vert, float dist, int count)
+ : vertNr(vert), distance(dist), edgeCount(count) {}
+
+ int vertNr;
+ float distance;
+ int edgeCount;
+ bool operator < (const VertexDistanceCount& v) const
+ {
+ return v.distance < distance;
+ }
+ };
+
+ // ---------------------------------------------------------------------------------------
+ struct PathIntersection
+ {
+ PxU32 vertOrTriangle;
+ PxU32 index; // vertex id or triangle edge id
+ float s; // only used for edge intersection
+ float distance; // computed distance
+
+ public:
+ PathIntersection() {}
+
+ PathIntersection(PxU32 vort, PxU32 in_index, float in_distance, float in_s = 0.0f)
+ : vertOrTriangle(vort), index(in_index), s(in_s), distance(in_distance)
+ {
+ }
+ };
+
+ //---------------------------------------------------------------------------------------
+ struct VertTriangle
+ {
+ VertTriangle(int vert, int triangle)
+ : mVertIndex(vert), mTriangleIndex(triangle)
+ {
+ }
+
+ bool operator<(const VertTriangle &vt) const
+ {
+ return mVertIndex == vt.mVertIndex ?
+ mTriangleIndex < vt.mTriangleIndex : mVertIndex < vt.mVertIndex;
+ }
+
+ int mVertIndex;
+ int mTriangleIndex;
+ };
+
+ // ---------------------------------------------------------------------------------------
+ struct MeshEdge
+ {
+ MeshEdge(int v0, int v1, int halfEdgeIndex)
+ : mFromVertIndex(v0), mToVertIndex(v1), mHalfEdgeIndex(halfEdgeIndex)
+ {
+ if(mFromVertIndex > mToVertIndex)
+ shdfnd::swap(mFromVertIndex, mToVertIndex);
+ }
+
+ bool operator<(const MeshEdge& e) const
+ {
+ return mFromVertIndex == e.mFromVertIndex ?
+ mToVertIndex < e.mToVertIndex : mFromVertIndex < e.mFromVertIndex;
+ }
+
+ bool operator==(const MeshEdge& e) const
+ {
+ return mFromVertIndex == e.mFromVertIndex
+ && mToVertIndex == e.mToVertIndex;
+ }
+
+ int mFromVertIndex, mToVertIndex;
+ int mHalfEdgeIndex;
+ };
+
+ // check if the edge is following triangle order or not
+ bool checkEdgeOrientation(const MeshEdge &e, const shdfnd::Array<PxU32> &indices)
+ {
+ int offset0 = e.mHalfEdgeIndex % 3;
+ int offset1 = (offset0 < 2) ? 1 : -2;
+
+ int v0 = int(indices[PxU32(e.mHalfEdgeIndex)]);
+ int v1 = int(indices[PxU32(e.mHalfEdgeIndex + offset1)]);
+
+ if ((e.mFromVertIndex == v0) && (e.mToVertIndex == v1))
+ return true;
+
+ return false;
+ }
+
+ // check if two index pairs represent same edge regardless of order.
+ inline bool checkEdge(int ei0, int ei1, int ej0, int ej1)
+ {
+ return ( (ei0 == ej0) && (ei1 == ej1) ) ||
+ ( (ei0 == ej1) && (ei1 == ej0) );
+ }
+
+ // compute ray edge intersection
+ bool intersectRayEdge(const PxVec3 &O, const PxVec3 &D, const PxVec3 &A, const PxVec3 &B, float &s, float &t)
+ {
+ // point on edge P = A + s * AB
+ // point on ray R = o + t * d
+ // for this two points to intersect, we have
+ // |AB -d| | s t | = o - A
+ const float eps = 1e-4;
+
+ PxVec3 OA = O - A;
+ PxVec3 AB = B - A;
+
+ float a = AB.dot(AB), b = -AB.dot(D);
+ float c = b, d = D.dot(D);
+
+ float e = AB.dot(OA);
+ float f = -D.dot(OA);
+
+ float det = a * d - b * c;
+ if (PxAbs(det) < eps) // coplanar case
+ return false;
+
+ float inv_det = 1.0f / det;
+
+ s = (d * inv_det) * e + (-b * inv_det) * f;
+ t = (-c * inv_det) * e + (a * inv_det) * f;
+
+ return true;
+ }
+}
+
+
+struct physx::PxClothGeodesicTetherCookerImpl
+{
+
+ PxClothGeodesicTetherCookerImpl(const PxClothMeshDesc& desc);
+
+ PxU32 getCookerStatus() const;
+ PxU32 getNbTethersPerParticle() const;
+ void getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const;
+
+public:
+ // input
+ const PxClothMeshDesc& mDesc;
+
+ // internal variables
+ PxU32 mNumParticles;
+ shdfnd::Array<PxVec3> mVertices;
+ shdfnd::Array<PxU32> mIndices;
+ shdfnd::Array<PxU8> mAttached;
+ shdfnd::Array<PxU32> mFirstVertTriAdj;
+ shdfnd::Array<PxU32> mVertTriAdjs;
+ shdfnd::Array<PxU32> mTriNeighbors; // needs changing for non-manifold support
+
+ // error status
+ PxU32 mCookerStatus;
+
+ // output
+ shdfnd::Array<PxU32> mTetherAnchors;
+ shdfnd::Array<PxReal> mTetherLengths;
+
+protected:
+ void createTetherData(const PxClothMeshDesc &desc);
+ int computeVertexIntersection(PxU32 parent, PxU32 src, PathIntersection &path);
+ int computeEdgeIntersection(PxU32 parent, PxU32 edge, float in_s, PathIntersection &path);
+ float computeGeodesicDistance(PxU32 i, PxU32 parent, int &errorCode);
+ PxU32 findTriNeighbors();
+ void findVertTriNeighbors();
+
+private:
+ PxClothGeodesicTetherCookerImpl& operator=(const PxClothGeodesicTetherCookerImpl&);
+};
+
+PxClothGeodesicTetherCooker::PxClothGeodesicTetherCooker(const PxClothMeshDesc& desc)
+: mImpl(new PxClothGeodesicTetherCookerImpl(desc))
+{
+}
+
+PxClothGeodesicTetherCooker::~PxClothGeodesicTetherCooker()
+{
+ delete mImpl;
+}
+
+PxU32 PxClothGeodesicTetherCooker::getCookerStatus() const
+{
+ return mImpl->getCookerStatus();
+}
+
+PxU32 PxClothGeodesicTetherCooker::getNbTethersPerParticle() const
+{
+ return mImpl->getNbTethersPerParticle();
+}
+
+void PxClothGeodesicTetherCooker::getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const
+{
+ mImpl->getTetherData(userTetherAnchors, userTetherLengths);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+PxClothGeodesicTetherCookerImpl::PxClothGeodesicTetherCookerImpl(const PxClothMeshDesc &desc)
+ :mDesc(desc),
+ mCookerStatus(0)
+{
+ createTetherData(desc);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void PxClothGeodesicTetherCookerImpl::createTetherData(const PxClothMeshDesc &desc)
+{
+ mNumParticles = desc.points.count;
+
+ if (!desc.invMasses.data)
+ return;
+
+ // assemble points
+ mVertices.resize(mNumParticles);
+ mAttached.resize(mNumParticles);
+ PxStrideIterator<const PxVec3> pIt(reinterpret_cast<const PxVec3*>(desc.points.data), desc.points.stride);
+ PxStrideIterator<const PxReal> wIt(reinterpret_cast<const PxReal*>(desc.invMasses.data), desc.invMasses.stride);
+ for(PxU32 i=0; i<mNumParticles; ++i)
+ {
+ mVertices[i] = *pIt++;
+ mAttached[i] = PxU8(wIt.ptr() ? (*wIt++ == 0.0f) : 0);
+ }
+
+ // build triangle indices
+ if(desc.flags & PxMeshFlag::e16_BIT_INDICES)
+ gatherIndices<PxU16>(mIndices, desc.triangles, desc.quads);
+ else
+ gatherIndices<PxU32>(mIndices, desc.triangles, desc.quads);
+
+ // build vertex-triangle adjacencies
+ findVertTriNeighbors();
+
+ // build triangle-triangle adjacencies
+ mCookerStatus = findTriNeighbors();
+ if (mCookerStatus != 0)
+ return;
+
+ // build adjacent vertex list
+ shdfnd::Array<PxU32> valency(mNumParticles+1, 0);
+ shdfnd::Array<PxU32> adjacencies;
+ if(desc.flags & PxMeshFlag::e16_BIT_INDICES)
+ gatherAdjacencies<PxU16>(valency, adjacencies, desc.triangles, desc.quads);
+ else
+ gatherAdjacencies<PxU32>(valency, adjacencies, desc.triangles, desc.quads);
+
+ // build unique neighbors from adjacencies
+ shdfnd::Array<PxU32> mark(valency.size(), 0);
+ shdfnd::Array<PxU32> neighbors; neighbors.reserve(adjacencies.size());
+ for(PxU32 i=1, j=0; i<valency.size(); ++i)
+ {
+ for(; j<valency[i]; ++j)
+ {
+ PxU32 k = adjacencies[j];
+ if(mark[k] != i)
+ {
+ mark[k] = i;
+ neighbors.pushBack(k);
+ }
+ }
+ valency[i] = neighbors.size();
+ }
+
+ // create islands of attachment points
+ shdfnd::Array<PxU32> vertexIsland(mNumParticles);
+ shdfnd::Array<VertexDistanceCount> vertexIslandHeap;
+
+ // put all the attachments in heap
+ for (PxU32 i = 0; i < mNumParticles; ++i)
+ {
+ // we put each attached point with large distance so that
+ // we can prioritize things that are added during mesh traversal.
+ vertexIsland[i] = PxU32(-1);
+ if (mAttached[i])
+ vertexIslandHeap.pushBack(VertexDistanceCount(int(i), FLT_MAX, 0));
+ }
+ PxU32 attachedCnt = vertexIslandHeap.size();
+
+ // no attached vertices
+ if (vertexIslandHeap.empty())
+ return;
+
+ // identify islands of attached vertices
+ shdfnd::Array<PxU32> islandIndices;
+ shdfnd::Array<PxU32> islandFirst;
+ PxU32 islandCnt = 0;
+ PxU32 islandIndexCnt = 0;
+
+ islandIndices.reserve(attachedCnt);
+ islandFirst.reserve(attachedCnt+1);
+
+ // while the island heap is not empty
+ while (!vertexIslandHeap.empty())
+ {
+ // pop vi from heap
+ VertexDistanceCount vi = popHeap(vertexIslandHeap);
+
+ // new cluster
+ if (vertexIsland[PxU32(vi.vertNr)] == PxU32(-1))
+ {
+ islandFirst.pushBack(islandIndexCnt++);
+ vertexIsland[PxU32(vi.vertNr)] = islandCnt++;
+ vi.distance = 0;
+ islandIndices.pushBack(PxU32(vi.vertNr));
+ }
+
+ // for each adjacent vj that's not visited
+ const PxU32 begin = PxU32(valency[PxU32(vi.vertNr)]);
+ const PxU32 end = PxU32(valency[PxU32(vi.vertNr + 1)]);
+ for (PxU32 j = begin; j < end; ++j)
+ {
+ const PxU32 vj = neighbors[j];
+
+ // do not expand unattached vertices
+ if (!mAttached[vj])
+ continue;
+
+ // already visited
+ if (vertexIsland[vj] != PxU32(-1))
+ continue;
+
+ islandIndices.pushBack(vj);
+ islandIndexCnt++;
+ vertexIsland[vj] = vertexIsland[PxU32(vi.vertNr)];
+ pushHeap(vertexIslandHeap, VertexDistanceCount(int(vj), vi.distance + 1.0f, 0));
+ }
+ }
+
+ islandFirst.pushBack(islandIndexCnt);
+
+ PX_ASSERT(islandCnt == (islandFirst.size() - 1));
+
+ /////////////////////////////////////////////////////////
+ PxU32 bufferSize = mNumParticles * islandCnt;
+ PX_ASSERT(bufferSize > 0);
+
+ shdfnd::Array<float> vertexDistanceBuffer(bufferSize, PX_MAX_F32);
+ shdfnd::Array<PxU32> vertexParentBuffer(bufferSize, 0);
+ shdfnd::Array<VertexDistanceCount> vertexHeap;
+
+ // now process each island
+ for (PxU32 i = 0; i < islandCnt; i++)
+ {
+ vertexHeap.clear();
+ float* vertexDistance = &vertexDistanceBuffer[0] + (i * mNumParticles);
+ PxU32* vertexParent = &vertexParentBuffer[0] + (i * mNumParticles);
+
+ // initialize parent and distance
+ for (PxU32 j = 0; j < mNumParticles; ++j)
+ {
+ vertexParent[j] = j;
+ vertexDistance[j] = PX_MAX_F32;
+ }
+
+ // put all the attached vertices in this island to heap
+ const PxU32 beginIsland = islandFirst[i];
+ const PxU32 endIsland = islandFirst[i+1];
+ for (PxU32 j = beginIsland; j < endIsland; j++)
+ {
+ PxU32 vj = islandIndices[j];
+ vertexDistance[vj] = 0.0f;
+ vertexHeap.pushBack(VertexDistanceCount(int(vj), 0.0f, 0));
+ }
+
+ // no attached vertices in this island (error?)
+ PX_ASSERT(vertexHeap.empty() == false);
+ if (vertexHeap.empty())
+ continue;
+
+ // while heap is not empty
+ while (!vertexHeap.empty())
+ {
+ // pop vi from heap
+ VertexDistanceCount vi = popHeap(vertexHeap);
+
+ // obsolete entry ( we already found better distance)
+ if (vi.distance > vertexDistance[vi.vertNr])
+ continue;
+
+ // for each adjacent vj that's not visited
+ const PxI32 begin = PxI32(valency[PxU32(vi.vertNr)]);
+ const PxI32 end = PxI32(valency[PxU32(vi.vertNr + 1)]);
+ for (PxI32 j = begin; j < end; ++j)
+ {
+ const PxI32 vj = PxI32(neighbors[PxU32(j)]);
+ PxVec3 edge = mVertices[PxU32(vj)] - mVertices[PxU32(vi.vertNr)];
+ const PxF32 edgeLength = edge.magnitude();
+ float newDistance = vi.distance + edgeLength;
+
+ if (newDistance < vertexDistance[vj])
+ {
+ vertexDistance[vj] = newDistance;
+ vertexParent[vj] = vertexParent[vi.vertNr];
+
+ pushHeap(vertexHeap, VertexDistanceCount(vj, newDistance, 0));
+ }
+ }
+ }
+ }
+
+ const PxU32 maxTethersPerParticle = 4; // max tethers
+ const PxU32 nbTethersPerParticle = (islandCnt > maxTethersPerParticle) ? maxTethersPerParticle : islandCnt;
+
+ PxU32 nbTethers = nbTethersPerParticle * mNumParticles;
+ mTetherAnchors.resize(nbTethers);
+ mTetherLengths.resize(nbTethers);
+
+ // now process the parent and distance and add to fibers
+ for (PxU32 i = 0; i < mNumParticles; i++)
+ {
+ // we use the heap to sort out N-closest island
+ vertexHeap.clear();
+ for (PxU32 j = 0; j < islandCnt; j++)
+ {
+ int parent = int(vertexParentBuffer[j * mNumParticles + i]);
+ float edgeDistance = vertexDistanceBuffer[j * mNumParticles + i];
+ pushHeap(vertexHeap, VertexDistanceCount(parent, edgeDistance, 0));
+ }
+
+ // take out N-closest island from the heap
+ for (PxU32 j = 0; j < nbTethersPerParticle; j++)
+ {
+ VertexDistanceCount vi = popHeap(vertexHeap);
+ PxU32 parent = PxU32(vi.vertNr);
+ float distance = 0.0f;
+
+ if (parent != i)
+ {
+ float euclideanDistance = (mVertices[i] - mVertices[parent]).magnitude();
+ float dijkstraDistance = vi.distance;
+ int errorCode = 0;
+ float geodesicDistance = computeGeodesicDistance(i,parent, errorCode);
+ if (errorCode < 0)
+ geodesicDistance = dijkstraDistance;
+ distance = PxMax(euclideanDistance, geodesicDistance);
+ }
+
+ PxU32 tetherLoc = j * mNumParticles + i;
+ mTetherAnchors[ tetherLoc ] = parent;
+ mTetherLengths[ tetherLoc ] = distance;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+PxU32 PxClothGeodesicTetherCookerImpl::getCookerStatus() const
+{
+ return mCookerStatus;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+PxU32 PxClothGeodesicTetherCookerImpl::getNbTethersPerParticle() const
+{
+ return mTetherAnchors.size() / mNumParticles;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void
+PxClothGeodesicTetherCookerImpl::getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const
+{
+ PxMemCopy(userTetherAnchors, mTetherAnchors.begin(), mTetherAnchors.size() * sizeof(PxU32));
+ PxMemCopy(userTetherLengths, mTetherLengths.begin(), mTetherLengths.size() * sizeof(PxReal));
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// find triangle-triangle adjacency (return non-zero if there is an error)
+PxU32 PxClothGeodesicTetherCookerImpl::findTriNeighbors()
+{
+ shdfnd::Array<MeshEdge> edges;
+
+ mTriNeighbors.resize(mIndices.size(), PxU32(-1));
+
+ // assemble all edges
+ PxU32 numTriangles = mIndices.size() / 3;
+ for (PxU32 i = 0; i < numTriangles; ++i)
+ {
+ PxU32 i0 = mIndices[3 * i];
+ PxU32 i1 = mIndices[3 * i + 1];
+ PxU32 i2 = mIndices[3 * i + 2];
+ edges.pushBack(MeshEdge(int(i0), int(i1), int(3*i)));
+ edges.pushBack(MeshEdge(int(i1), int(i2), int(3*i+1)));
+ edges.pushBack(MeshEdge(int(i2), int(i0), int(3*i+2)));
+ }
+
+ shdfnd::sort(edges.begin(), edges.size());
+
+ int numEdges = int(edges.size());
+ for(int i=0; i < numEdges; )
+ {
+ const MeshEdge& e0 = edges[PxU32(i)];
+ bool orientation0 = checkEdgeOrientation(e0, mIndices);
+
+ int j = i;
+ while(++i < numEdges && edges[PxU32(i)] == e0)
+ ;
+
+ if(i - j > 2)
+ return 1; // non-manifold
+
+ while(++j < i)
+ {
+ const MeshEdge& e1 = edges[PxU32(j)];
+ bool orientation1 = checkEdgeOrientation(e1, mIndices);
+ mTriNeighbors[PxU32(e0.mHalfEdgeIndex)] = PxU32(e1.mHalfEdgeIndex/3);
+ mTriNeighbors[PxU32(e1.mHalfEdgeIndex)] = PxU32(e0.mHalfEdgeIndex/3);
+
+ if (orientation0 == orientation1)
+ return 2; // bad winding
+ }
+ }
+
+ return 0;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// find vertex triangle adjacency information
+void PxClothGeodesicTetherCookerImpl::findVertTriNeighbors()
+{
+ shdfnd::Array<VertTriangle> vertTriangles;
+ vertTriangles.reserve(mIndices.size());
+
+ int numTriangles = int(mIndices.size() / 3);
+ for (int i = 0; i < numTriangles; ++i)
+ {
+ vertTriangles.pushBack(VertTriangle(int(mIndices[PxU32(3*i)]), i));
+ vertTriangles.pushBack(VertTriangle(int(mIndices[PxU32(3*i+1)]), i));
+ vertTriangles.pushBack(VertTriangle(int(mIndices[PxU32(3*i+2)]), i));
+ }
+
+ shdfnd::sort(vertTriangles.begin(), vertTriangles.size(), shdfnd::Less<VertTriangle>());
+ mFirstVertTriAdj.resize(mNumParticles);
+ mVertTriAdjs.reserve(mIndices.size());
+
+ for (PxU32 i = 0; i < PxU32(vertTriangles.size()); )
+ {
+ int v = vertTriangles[i].mVertIndex;
+
+ mFirstVertTriAdj[PxU32(v)] = i;
+
+ while ((i < mIndices.size()) && (vertTriangles[i].mVertIndex == v))
+ {
+ int t = vertTriangles[i].mTriangleIndex;
+ mVertTriAdjs.pushBack(PxU32(t));
+ i++;
+ }
+ }
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// compute intersection of a ray from a source vertex in direction toward parent
+int PxClothGeodesicTetherCookerImpl::computeVertexIntersection(PxU32 parent, PxU32 src, PathIntersection &path)
+{
+ if (src == parent)
+ {
+ path = PathIntersection(true, src, 0.0);
+ return 0;
+ }
+
+ float maxdot = -1.0f;
+ int closestVert = -1;
+
+ // gradient is toward the parent vertex
+ PxVec3 g = (mVertices[parent] - mVertices[src]).getNormalized();
+
+ // for every triangle incident on this vertex, we intersect against opposite edge of the triangle
+ PxU32 sfirst = mFirstVertTriAdj[src];
+ PxU32 slast = (src < (PxU32(mNumParticles-1))) ? mFirstVertTriAdj[src+1] : PxU32(mVertTriAdjs.size());
+ for (PxU32 adj = sfirst; adj < slast; adj++)
+ {
+ PxU32 tid = mVertTriAdjs[adj];
+
+ PxU32 i0 = mIndices[tid*3];
+ PxU32 i1 = mIndices[tid*3+1];
+ PxU32 i2 = mIndices[tid*3+2];
+
+ int eid = 0;
+ if (i0 == src) eid = 1;
+ else if (i1 == src) eid = 2;
+ else if (i2 == src) eid = 0;
+ else continue; // error
+
+ // reshuffle so that src is located at i2
+ i0 = mIndices[tid*3 + eid];
+ i1 = mIndices[tid*3 + (eid+1)%3];
+ i2 = src;
+
+ PxVec3 p0 = mVertices[i0];
+ PxVec3 p1 = mVertices[i1];
+ PxVec3 p2 = mVertices[i2];
+
+ // check if we hit source immediately from this triangle
+ if (i0 == parent)
+ {
+ path = PathIntersection(true, parent, (p0 - p2).magnitude());
+ return 1;
+ }
+
+ if (i1 == parent)
+ {
+ path = PathIntersection(true, parent, (p1 - p2).magnitude());
+ return 1;
+ }
+
+ // ray direction is the gradient projected on the plane of this triangle
+ PxVec3 n = ((p0 - p2).cross(p1 - p2)).getNormalized();
+ PxVec3 d = (g - g.dot(n) * n).getNormalized();
+
+ // find intersection of ray (p2, d) against the edge (p0,p1)
+ float s, t;
+ bool result = intersectRayEdge(p2, d, p0, p1, s, t);
+ if (result == false)
+ continue;
+
+ // t should be positive, otherwise we just hit the triangle in opposite direction, so ignore
+ const float eps = 1e-5;
+ if (t > -eps)
+ {
+ PxVec3 ip; // intersection point
+ if (( s > -eps ) && (s < (1.0f + eps)))
+ {
+ // if intersection point is too close to each vertex, we record a vertex intersection
+ if ( ( s < eps) || (s > (1.0f-eps)))
+ {
+ path.vertOrTriangle = true;
+ path.index = (s < eps) ? i0 : i1;
+ path.distance = (p2 - mVertices[path.index]).magnitude();
+ }
+ else // found an edge instersection
+ {
+ ip = p0 + s * (p1 - p0);
+ path = PathIntersection(false, tid*3 + eid, (p2 - ip).magnitude(), s);
+ }
+ return 1;
+ }
+ }
+
+ // for fall back (see below)
+ PxVec3 d0 = (p0 - p2).getNormalized();
+ PxVec3 d1 = (p1 - p2).getNormalized();
+ float d0dotg = d0.dot(d);
+ float d1dotg = d1.dot(d);
+
+ if (d0dotg > maxdot)
+ {
+ closestVert = int(i0);
+ maxdot = d0dotg;
+ }
+ if (d1dotg > maxdot)
+ {
+ closestVert = int(i1);
+ maxdot = d1dotg;
+ }
+ } // end for (PxU32 adj = sfirst...
+
+ // Fall back to use greedy (Dijkstra-like) path selection.
+ // This happens as triangles are curved and we may not find intersection on any triangle.
+ // In this case, we choose a vertex closest to the gradient direction.
+ if (closestVert > 0)
+ {
+ path = PathIntersection(true, PxU32(closestVert), (mVertices[src] - mVertices[PxU32(closestVert)]).magnitude());
+ return 1;
+ }
+
+ // Error, (possibly dangling vertex)
+ return -1;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// compute intersection of a ray from a source vertex in direction toward parent
+int PxClothGeodesicTetherCookerImpl::computeEdgeIntersection(PxU32 parent, PxU32 edge, float in_s, PathIntersection &path)
+{
+ int tid = int(edge / 3);
+ int eid = int(edge % 3);
+
+ PxU32 e0 = mIndices[PxU32(tid*3 + eid)];
+ PxU32 e1 = mIndices[PxU32(tid*3 + (eid+1)%3)];
+
+ PxVec3 v0 = mVertices[e0];
+ PxVec3 v1 = mVertices[e1];
+
+ PxVec3 v = v0 + in_s * (v1 - v0);
+ PxVec3 g = mVertices[parent] - v;
+
+ PxU32 triNbr = mTriNeighbors[edge];
+
+ if (triNbr == PxU32(-1)) // boundary edge
+ {
+ float dir = g.dot(v1-v0);
+ PxU32 vid = (dir > 0) ? e1 : e0;
+ path = PathIntersection(true, vid, (mVertices[vid] - v).magnitude());
+ return 1;
+ }
+
+ PxU32 i0 = mIndices[triNbr*3];
+ PxU32 i1 = mIndices[triNbr*3+1];
+ PxU32 i2 = mIndices[triNbr*3+2];
+
+ // vertex is sorted s.t i0,i1 contains the edge point
+ if ( checkEdge(int(i0), int(i1), int(e0), int(e1))) {
+ eid = 0;
+ }
+ else if ( checkEdge(int(i1), int(i2), int(e0), int(e1))) {
+ eid = 1;
+ PxU32 tmp = i2;
+ i2 = i0;
+ i0 = i1;
+ i1 = tmp;
+ }
+ else if ( checkEdge(int(i2), int(i0), int(e0), int(e1)))
+ {
+ eid = 2;
+ PxU32 tmp = i0;
+ i0 = i2;
+ i2 = i1;
+ i1 = tmp;
+ }
+
+ // we hit the parent
+ if (i2 == parent)
+ {
+ path = PathIntersection(true, i2, (mVertices[i2] - v).magnitude());
+ return 1;
+ }
+
+ PxVec3 p0 = mVertices[i0];
+ PxVec3 p1 = mVertices[i1];
+ PxVec3 p2 = mVertices[i2];
+
+ // project gradient vector on the plane of the triangle
+ PxVec3 n = ((p0 - p2).cross(p1 - p2)).getNormalized();
+ g = (g - g.dot(n) * n).getNormalized();
+
+ float s = 0.0f, t = 0.0f;
+ const float eps = 1e-5;
+ PxVec3 ip;
+
+ // intersect against edge form p2 to p0
+ if (intersectRayEdge(v, g, p2, p0, s, t) && ( s >= -eps) && ( s <= (1.0f+eps) ) && (t > -eps))
+ {
+ if ( ( s < eps) || (s > (1.0f-eps)))
+ {
+ path.vertOrTriangle = true;
+ path.index = (s < eps) ? i2 : i0;
+ path.distance = (mVertices[path.index] - v).magnitude();
+ }
+ else
+ {
+ ip = p2 + s * (p0 - p2);
+ path = PathIntersection(false, triNbr*3 + (eid + 2) % 3, (ip - v).magnitude(), s);
+
+ }
+
+ return 1;
+ }
+
+ // intersect against edge form p1 to p2
+ if (intersectRayEdge(v, g, p1, p2, s, t) && ( s >= -eps) && ( s <= (1.0f+eps) ) && (t > -eps))
+ {
+ if ( ( s < eps) || (s > (1.0f-eps)))
+ {
+ path.vertOrTriangle = true;
+ path.index = (s < eps) ? i1 : i2;
+ path.distance = (mVertices[path.index] - v).magnitude();
+ }
+ else
+ {
+ ip = p1 + s * (p2 - p1);
+ path = PathIntersection(false, triNbr*3 + (eid + 1) % 3, (ip - v).magnitude(), s);
+ }
+
+ return 1;
+ }
+
+ // fallback to pick closer vertex when no edges intersect
+ float dir = g.dot(v1-v0);
+ path.vertOrTriangle = true;
+ path.index = (dir > 0) ? e1 : e0;
+ path.distance = (mVertices[path.index] - v).magnitude();
+
+ return 1;
+}
+
+
+///////////////////////////////////////////////////////////////////////////////
+// compute geodesic distance and path from vertex i to its parent
+float PxClothGeodesicTetherCookerImpl::computeGeodesicDistance(PxU32 i, PxU32 parent, int &errorCode)
+{
+ if (i == parent)
+ return 0.0f;
+
+ PathIntersection path;
+
+ errorCode = 0;
+
+ // find intial intersection
+ int status = computeVertexIntersection(parent, i, path);
+ if (status < 0)
+ {
+ errorCode = -1;
+ return 0;
+ }
+
+ int pathcnt = 0;
+ float geodesicDistance = 0;
+
+ while (status > 0)
+ {
+ geodesicDistance += path.distance;
+
+ if (path.vertOrTriangle)
+ status = computeVertexIntersection(parent, path.index, path);
+ else
+ status = computeEdgeIntersection(parent, path.index, path.s, path);
+
+ // cannot find valid path
+ if (status < 0)
+ {
+ errorCode = -2;
+ return 0.0f;
+ }
+
+ // possibly cycles, too many path
+ if (pathcnt > 1000)
+ {
+ errorCode = -3;
+ return 0.0f;
+ }
+
+ pathcnt++;
+ }
+
+ return geodesicDistance;
+}
+
+
+
+
+#endif //PX_USE_CLOTH_API
+
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtClothMeshQuadifier.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothMeshQuadifier.cpp
new file mode 100644
index 00000000..cb2392d3
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothMeshQuadifier.cpp
@@ -0,0 +1,441 @@
+// 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/PxStrideIterator.h"
+#include "extensions/PxClothMeshQuadifier.h"
+
+// from shared foundation
+#include <PsFoundation.h>
+#include <PsSort.h>
+#include <Ps.h>
+#include <PsMathUtils.h>
+#include <PsArray.h>
+
+using namespace physx;
+
+struct physx::PxClothMeshQuadifierImpl
+{
+ PxClothMeshQuadifierImpl(const PxClothMeshDesc& desc);
+ PxClothMeshDesc getDescriptor() const;
+
+public:
+ PxClothMeshDesc mDesc;
+ shdfnd::Array<PxU32> mQuads;
+ shdfnd::Array<PxU32> mTriangles;
+};
+
+PxClothMeshQuadifier::PxClothMeshQuadifier(const PxClothMeshDesc& desc)
+: mImpl(new PxClothMeshQuadifierImpl(desc))
+{
+}
+
+PxClothMeshQuadifier::~PxClothMeshQuadifier()
+{
+ delete mImpl;
+}
+
+PxClothMeshDesc PxClothMeshQuadifier::getDescriptor() const
+{
+ return mImpl->getDescriptor();
+}
+
+namespace
+{
+ struct UniqueEdge
+ {
+ PX_FORCE_INLINE bool operator()(const UniqueEdge& e1, const UniqueEdge& e2) const
+ {
+ return e1 < e2;
+ }
+
+ PX_FORCE_INLINE bool operator==(const UniqueEdge& other) const
+ {
+ return vertex0 == other.vertex0 && vertex1 == other.vertex1;
+ }
+ PX_FORCE_INLINE bool operator<(const UniqueEdge& other) const
+ {
+ if (vertex0 != other.vertex0)
+ {
+ return vertex0 < other.vertex0;
+ }
+
+ return vertex1 < other.vertex1;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ UniqueEdge()
+ : vertex0(0), vertex1(0), vertex2(0), vertex3(0xffffffff),
+ maxAngle(0.0f), isQuadDiagonal(false), isUsed(false) {}
+
+ UniqueEdge(PxU32 v0, PxU32 v1, PxU32 v2)
+ : vertex0(PxMin(v0, v1)), vertex1(PxMax(v0, v1)), vertex2(v2), vertex3(0xffffffff),
+ maxAngle(0.0f), isQuadDiagonal(false), isUsed(false) {}
+
+
+ PxU32 vertex0, vertex1;
+ PxU32 vertex2, vertex3;
+ PxF32 maxAngle;
+ bool isQuadDiagonal;
+ bool isUsed;
+ };
+
+ struct SortHiddenEdges
+ {
+ SortHiddenEdges(shdfnd::Array<UniqueEdge>& uniqueEdges) : mUniqueEdges(uniqueEdges) {}
+
+ bool operator()(PxU32 a, PxU32 b) const
+ {
+ return mUniqueEdges[a].maxAngle < mUniqueEdges[b].maxAngle;
+ }
+
+ private:
+ SortHiddenEdges& operator=(const SortHiddenEdges&);
+ shdfnd::Array<UniqueEdge>& mUniqueEdges;
+ };
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ template <typename T>
+ void copyIndices(const PxClothMeshDesc &desc, shdfnd::Array<PxU32> &triangles, shdfnd::Array<PxU32> &quads)
+ {
+ triangles.resize(desc.triangles.count*3);
+ PxStrideIterator<const T> tIt = PxMakeIterator(reinterpret_cast<const T*>(desc.triangles.data), desc.triangles.stride);
+ for(PxU32 i=0; i<desc.triangles.count; ++i, ++tIt)
+ for(PxU32 j=0; j<3; ++j)
+ triangles[i*3+j] = tIt.ptr()[j];
+
+ quads.resize(desc.quads.count*4);
+ PxStrideIterator<const T> qIt = PxMakeIterator(reinterpret_cast<const T*>(desc.quads.data), desc.quads.stride);
+ for(PxU32 i=0; i<desc.quads.count; ++i, ++qIt)
+ for(PxU32 j=0; j<4; ++j)
+ quads[i*4+j] = qIt.ptr()[j];
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ void computeUniqueEdges(shdfnd::Array<UniqueEdge> &uniqueEdges, const PxVec3* positions, const shdfnd::Array<PxU32>& triangles)
+ {
+ uniqueEdges.resize(0);
+ uniqueEdges.reserve(triangles.size());
+
+ PxU32 indexMap[3][3] = { { 0, 1, 2 }, { 1, 2, 0 }, { 0, 2, 1 } };
+
+ const PxF32 rightAngle = PxCos(shdfnd::degToRad(85.0f));
+
+ for(PxU32 i=0; i<triangles.size(); i+=3)
+ {
+ UniqueEdge edges[3];
+ PxF32 edgeLengths[3];
+ PxF32 edgeAngles[3];
+
+ for (PxU32 j = 0; j < 3; j++)
+ {
+ edges[j] = UniqueEdge(triangles[i+indexMap[j][0]], triangles[i+indexMap[j][1]], triangles[i+indexMap[j][2]]);
+ edgeLengths[j] = (positions[edges[j].vertex0] - positions[edges[j].vertex1]).magnitude();
+ const PxVec3 v1 = positions[edges[j].vertex2] - positions[edges[j].vertex0];
+ const PxVec3 v2 = positions[edges[j].vertex2] - positions[edges[j].vertex1];
+ edgeAngles[j] = PxAbs(v1.dot(v2)) / (v1.magnitude() * v2.magnitude());
+ }
+
+ // find the longest edge
+ PxU32 longest = 0;
+ for (PxU32 j = 1; j < 3; j++)
+ {
+ if (edgeLengths[j] > edgeLengths[longest])
+ longest = j;
+ }
+
+ // check it's angle
+ if (edgeAngles[longest] < rightAngle)
+ edges[longest].isQuadDiagonal = true;
+
+ for (PxU32 j = 0; j < 3; j++)
+ uniqueEdges.pushBack(edges[j]);
+ }
+
+ shdfnd::sort(uniqueEdges.begin(), uniqueEdges.size(), UniqueEdge(0, 0, 0));
+
+ PxU32 writeIndex = 0, readStart = 0, readEnd = 0;
+ PxU32 numQuadEdges = 0;
+ while (readEnd < uniqueEdges.size())
+ {
+ while (readEnd < uniqueEdges.size() && uniqueEdges[readStart] == uniqueEdges[readEnd])
+ readEnd++;
+
+ const PxU32 count = readEnd - readStart;
+
+ UniqueEdge uniqueEdge = uniqueEdges[readStart];
+
+ if (count == 2)
+ // know the other diagonal
+ uniqueEdge.vertex3 = uniqueEdges[readStart + 1].vertex2;
+ else
+ uniqueEdge.isQuadDiagonal = false;
+
+ for (PxU32 i = 1; i < count; i++)
+ uniqueEdge.isQuadDiagonal &= uniqueEdges[readStart + i].isQuadDiagonal;
+
+ numQuadEdges += uniqueEdge.isQuadDiagonal ? 1 : 0;
+
+ uniqueEdges[writeIndex] = uniqueEdge;
+
+ writeIndex++;
+ readStart = readEnd;
+ }
+
+ uniqueEdges.resize(writeIndex, UniqueEdge(0, 0, 0));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////
+ PxU32 findUniqueEdge(const shdfnd::Array<UniqueEdge> &uniqueEdges, PxU32 index1, PxU32 index2)
+ {
+ UniqueEdge searchFor(index1, index2, 0);
+
+ PxU32 curMin = 0;
+ PxU32 curMax = uniqueEdges.size();
+ while (curMax > curMin)
+ {
+ PxU32 middle = (curMin + curMax) >> 1;
+
+ const UniqueEdge& probe = uniqueEdges[middle];
+ if (probe < searchFor)
+ curMin = middle + 1;
+ else
+ curMax = middle;
+ }
+
+ return curMin;
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ void refineUniqueEdges(shdfnd::Array<UniqueEdge> &uniqueEdges, const PxVec3* positions)
+ {
+ shdfnd::Array<PxU32> hideEdges;
+ hideEdges.reserve(uniqueEdges.size());
+
+ for (PxU32 i = 0; i < uniqueEdges.size(); i++)
+ {
+ UniqueEdge& uniqueEdge = uniqueEdges[i];
+ uniqueEdge.maxAngle = 0.0f;
+ uniqueEdge.isQuadDiagonal = false; // just to be sure
+
+ if (uniqueEdge.vertex3 != 0xffffffff)
+ {
+ PxU32 indices[4] = { uniqueEdge.vertex0, uniqueEdge.vertex2, uniqueEdge.vertex1, uniqueEdge.vertex3 };
+
+ // compute max angle of the quad
+ for (PxU32 j = 0; j < 4; j++)
+ {
+ PxVec3 e0 = positions[indices[ j + 0 ]] - positions[indices[(j + 1) % 4]];
+ PxVec3 e1 = positions[indices[(j + 1) % 4]] - positions[indices[(j + 2) % 4]];
+
+ PxF32 cosAngle = PxAbs(e0.dot(e1)) / (e0.magnitude() * e1.magnitude());
+ uniqueEdge.maxAngle = PxMax(uniqueEdge.maxAngle, cosAngle);
+ }
+
+ hideEdges.pushBack(i);
+ }
+ }
+
+ shdfnd::sort(hideEdges.begin(), hideEdges.size(), SortHiddenEdges(uniqueEdges));
+
+ const PxF32 maxAngle = PxSin(shdfnd::degToRad(60.0f));
+
+ PxU32 numHiddenEdges = 0;
+
+ for (PxU32 i = 0; i < hideEdges.size(); i++)
+ {
+ UniqueEdge& uniqueEdge = uniqueEdges[hideEdges[i]];
+
+ // find some stop criterion
+ if (uniqueEdge.maxAngle > maxAngle)
+ break;
+
+ // check if all four adjacent edges are still visible?
+ PxU32 indices[5] = { uniqueEdge.vertex0, uniqueEdge.vertex2, uniqueEdge.vertex1, uniqueEdge.vertex3, uniqueEdge.vertex0 };
+
+ PxU32 numVisible = 0;
+ for (PxU32 j = 0; j < 4; j++)
+ {
+ const PxU32 edgeIndex = findUniqueEdge(uniqueEdges, indices[j], indices[j + 1]);
+ PX_ASSERT(edgeIndex < uniqueEdges.size());
+
+ numVisible += uniqueEdges[edgeIndex].isQuadDiagonal ? 0 : 1;
+ }
+
+ if (numVisible == 4)
+ {
+ uniqueEdge.isQuadDiagonal = true;
+ numHiddenEdges++;
+ }
+ }
+ }
+
+
+ // calculate the inclusive prefix sum, equivalent of std::partial_sum
+ template <typename T>
+ void prefixSum(const T* first, const T* last, T* dest)
+ {
+ if (first != last)
+ {
+ *(dest++) = *(first++);
+ for (; first != last; ++first, ++dest)
+ *dest = *(dest-1) + *first;
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+ void quadifyTriangles(const shdfnd::Array<UniqueEdge> &uniqueEdges, shdfnd::Array<PxU32>& triangles, shdfnd::Array<PxU32> &quads)
+ {
+ shdfnd::Array<PxU32> valency(uniqueEdges.size()+1, 0); // edge valency
+ shdfnd::Array<PxU32> adjacencies; // adjacency from unique edge to triangles
+ PxU32 numTriangles = triangles.size() / 3;
+
+ // compute edge valency w.r.t triangles
+ for(PxU32 i=0; i<numTriangles; ++i)
+ {
+ for (PxU32 j=0; j < 3; j++)
+ {
+ PxU32 uniqueEdgeIndex = findUniqueEdge(uniqueEdges, triangles[i*3+j], triangles[i*3+(j+1)%3]);
+ ++valency[uniqueEdgeIndex];
+ }
+ }
+
+ // compute adjacency from each edge to triangle, the value also encodes which side of the triangle this edge belongs to
+ prefixSum(valency.begin(), valency.end(), valency.begin());
+ adjacencies.resize(valency.back());
+ for(PxU32 i=0; i<numTriangles; ++i)
+ {
+ for (PxU32 j=0; j < 3; j++)
+ {
+ PxU32 uniqueEdgeIndex = findUniqueEdge(uniqueEdges, triangles[i*3+j], triangles[i*3+(j+1)%3]);
+ adjacencies[--valency[uniqueEdgeIndex]] = i*3+j;
+ }
+ }
+
+ // now go through unique edges that are identified as diagonal, and build a quad out of two adjacent triangles
+ shdfnd::Array<PxU32> mark(numTriangles, 0);
+ for (PxU32 i = 0; i < uniqueEdges.size(); i++)
+ {
+ const UniqueEdge& edge = uniqueEdges[i];
+ if (edge.isQuadDiagonal)
+ {
+ PxU32 vi = valency[i];
+ if ((valency[i+1]-vi) != 2)
+ continue; // we do not quadify around non-manifold edges
+
+ PxU32 adj0 = adjacencies[vi], adj1 = adjacencies[vi+1];
+ PxU32 tid0 = adj0 / 3, tid1 = adj1 / 3;
+ PxU32 eid0 = adj0 % 3, eid1 = adj1 % 3;
+
+ quads.pushBack(triangles[tid0 * 3 + eid0]);
+ quads.pushBack(triangles[tid1 * 3 + (eid1+2)%3]);
+ quads.pushBack(triangles[tid0 * 3 + (eid0+1)%3]);
+ quads.pushBack(triangles[tid0 * 3 + (eid0+2)%3]);
+
+ mark[tid0] = 1;
+ mark[tid1] = 1;
+#if 0 // PX_DEBUG
+ printf("Deleting %d, %d, %d - %d, %d, %d, creating %d, %d, %d, %d\n",
+ triangles[tid0*3],triangles[tid0*3+1],triangles[tid0*3+2],
+ triangles[tid1*3],triangles[tid1*3+1],triangles[tid1*3+2],
+ v0,v3,v1,v2);
+#endif
+ }
+ }
+
+ // add remaining triangles that are not marked as already quadified
+ shdfnd::Array<PxU32> oldTriangles = triangles;
+ triangles.resize(0);
+ for (PxU32 i = 0; i < numTriangles; i++)
+ {
+ if (mark[i]) continue;
+
+ triangles.pushBack(oldTriangles[i*3]);
+ triangles.pushBack(oldTriangles[i*3+1]);
+ triangles.pushBack(oldTriangles[i*3+2]);
+ }
+ }
+
+} // namespace
+
+
+///////////////////////////////////////////////////////////////////////////////
+PxClothMeshQuadifierImpl::PxClothMeshQuadifierImpl(const PxClothMeshDesc &desc)
+ :mDesc(desc)
+{
+ shdfnd::Array<PxVec3> particles(desc.points.count);
+ PxStrideIterator<const PxVec3> pIt(reinterpret_cast<const PxVec3*>(desc.points.data), desc.points.stride);
+ for(PxU32 i=0; i<desc.points.count; ++i)
+ particles[i] = *pIt++;
+
+ // copy triangle indices
+ if(desc.flags & PxMeshFlag::e16_BIT_INDICES)
+ copyIndices<PxU16>(desc, mTriangles, mQuads);
+ else
+ copyIndices<PxU32>(desc, mTriangles, mQuads);
+
+ shdfnd::Array<UniqueEdge> uniqueEdges;
+
+ computeUniqueEdges(uniqueEdges, particles.begin(), mTriangles);
+
+ refineUniqueEdges(uniqueEdges, particles.begin());
+
+// printf("before %d triangles, %d quads\n", mTriangles.size()/3, mQuads.size()/4);
+ quadifyTriangles(uniqueEdges, mTriangles, mQuads);
+
+// printf("after %d triangles, %d quads\n", mTriangles.size()/3, mQuads.size()/4);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+PxClothMeshDesc
+PxClothMeshQuadifierImpl::getDescriptor() const
+{
+ // copy points and other data
+ PxClothMeshDesc desc = mDesc;
+
+ // for now use only 32 bit for temporary indices out of quadifier
+ desc.flags &= ~PxMeshFlag::e16_BIT_INDICES;
+
+ desc.triangles.count = mTriangles.size() / 3;
+ desc.triangles.data = mTriangles.begin();
+ desc.triangles.stride = 3 * sizeof(PxU32);
+
+ desc.quads.count = mQuads.size() / 4;
+ desc.quads.data = mQuads.begin();
+ desc.quads.stride = 4 * sizeof(PxU32);
+
+ PX_ASSERT(desc.isValid());
+
+ return desc;
+}
+#endif //PX_USE_CLOTH_API
+
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtClothSimpleTetherCooker.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothSimpleTetherCooker.cpp
new file mode 100644
index 00000000..b89dd507
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtClothSimpleTetherCooker.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.
+// 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/PxVec4.h"
+#include "foundation/PxMemory.h"
+#include "foundation/PxStrideIterator.h"
+#include "extensions/PxClothTetherCooker.h"
+#include "PsArray.h"
+// from shared foundation
+#include <PsFoundation.h>
+
+using namespace physx;
+
+struct physx::PxClothSimpleTetherCookerImpl
+{
+ PxClothSimpleTetherCookerImpl(const PxClothMeshDesc& desc);
+
+ void getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const;
+
+public:
+ // output
+ shdfnd::Array<PxU32> mTetherAnchors;
+ shdfnd::Array<PxReal> mTetherLengths;
+
+protected:
+ void createTetherData(const PxClothMeshDesc &desc);
+};
+
+PxClothSimpleTetherCooker::PxClothSimpleTetherCooker(const PxClothMeshDesc& desc)
+: mImpl(new PxClothSimpleTetherCookerImpl(desc))
+{
+}
+
+PxClothSimpleTetherCooker::~PxClothSimpleTetherCooker()
+{
+ delete mImpl;
+}
+
+void PxClothSimpleTetherCooker::getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const
+{
+ mImpl->getTetherData(userTetherAnchors, userTetherLengths);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+PxClothSimpleTetherCookerImpl::PxClothSimpleTetherCookerImpl(const PxClothMeshDesc &desc)
+{
+ createTetherData(desc);
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void PxClothSimpleTetherCookerImpl::createTetherData(const PxClothMeshDesc &desc)
+{
+ PxU32 numParticles = desc.points.count;
+
+ if (!desc.invMasses.data)
+ return;
+
+ // assemble points
+ shdfnd::Array<PxVec4> particles;
+ particles.reserve(numParticles);
+ PxStrideIterator<const PxVec3> pIt(reinterpret_cast<const PxVec3*>(desc.points.data), desc.points.stride);
+ PxStrideIterator<const PxReal> wIt(reinterpret_cast<const PxReal*>(desc.invMasses.data), desc.invMasses.stride);
+ for(PxU32 i=0; i<numParticles; ++i)
+ particles.pushBack(PxVec4(*pIt++, wIt.ptr() ? *wIt++ : 1.0f));
+
+ // compute tether data
+ shdfnd::Array<PxU32> attachedIndices;
+ for(PxU32 i=0; i < numParticles; ++i)
+ if(particles[i].w == 0.0f)
+ attachedIndices.pushBack(i);
+
+ PxU32 n = attachedIndices.empty() ? 0 : numParticles;
+ for(PxU32 i=0; i < n; ++i)
+ {
+ mTetherAnchors.reserve(numParticles);
+ mTetherLengths.reserve(numParticles);
+
+ PxVec3 position = reinterpret_cast<const PxVec3&>(particles[i]);
+ float minSqrDist = FLT_MAX;
+ PxU32 minIndex = numParticles;
+ const PxU32 *aIt, *aEnd = attachedIndices.end();
+ for(aIt = attachedIndices.begin(); aIt != aEnd; ++aIt)
+ {
+ float sqrDist = (reinterpret_cast<const PxVec3&>(
+ particles[*aIt]) - position).magnitudeSquared();
+ if(minSqrDist > sqrDist)
+ {
+ minSqrDist = sqrDist;
+ minIndex = *aIt;
+ }
+ }
+
+ mTetherAnchors.pushBack(minIndex);
+ mTetherLengths.pushBack(PxSqrt(minSqrDist));
+ }
+
+ PX_ASSERT(mTetherAnchors.size() == mTetherLengths.size());
+
+}
+
+///////////////////////////////////////////////////////////////////////////////
+void
+PxClothSimpleTetherCookerImpl::getTetherData(PxU32* userTetherAnchors, PxReal* userTetherLengths) const
+{
+ PxMemCopy(userTetherAnchors, mTetherAnchors.begin(), mTetherAnchors.size() * sizeof(PxU32));
+ PxMemCopy(userTetherLengths, mTetherLengths.begin(), mTetherLengths.size() * sizeof(PxReal));
+}
+
+
+#endif //PX_USE_CLOTH_API
+
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtCollection.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtCollection.cpp
new file mode 100644
index 00000000..0a768d8e
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtCollection.cpp
@@ -0,0 +1,252 @@
+// 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 "PxBase.h"
+#include "PsArray.h"
+#include "PxShape.h"
+#include "PxConvexMesh.h"
+#include "PxTriangleMesh.h"
+#include "PxHeightField.h"
+#include "PxMaterial.h"
+#include "PxJoint.h"
+#include "PxConstraintExt.h"
+#include "PxArticulation.h"
+#include "PxAggregate.h"
+#include "PxPhysics.h"
+#include "PxScene.h"
+#include "PxPruningStructure.h"
+#include "PxCollectionExt.h"
+
+
+using namespace physx;
+
+void PxCollectionExt::releaseObjects(PxCollection& collection, bool releaseExclusiveShapes)
+{
+ shdfnd::Array<PxBase*> releasableObjects;
+
+ for (PxU32 i = 0; i < collection.getNbObjects(); ++i)
+ {
+ PxBase* s = &collection.getObject(i);
+ // pruning structure must be released before its actors
+ if(s->is<PxPruningStructure>())
+ {
+ if(!releasableObjects.empty())
+ {
+ PxBase* first = releasableObjects[0];
+ releasableObjects.pushBack(first);
+ releasableObjects[0] = s;
+ }
+ }
+ else
+ {
+ if (s->isReleasable() && (releaseExclusiveShapes || !s->is<PxShape>() || !s->is<PxShape>()->isExclusive()))
+ releasableObjects.pushBack(s);
+ }
+ }
+
+ for (PxU32 i = 0; i < releasableObjects.size(); ++i)
+ releasableObjects[i]->release();
+
+ while (collection.getNbObjects() > 0)
+ collection.remove(collection.getObject(0));
+}
+
+
+void PxCollectionExt::remove(PxCollection& collection, PxType concreteType, PxCollection* to)
+{
+ shdfnd::Array<PxBase*> removeObjects;
+
+ for (PxU32 i = 0; i < collection.getNbObjects(); i++)
+ {
+ PxBase& object = collection.getObject(i);
+ if(concreteType == object.getConcreteType())
+ {
+ if(to)
+ to->add(object);
+
+ removeObjects.pushBack(&object);
+ }
+ }
+
+ for (PxU32 i = 0; i < removeObjects.size(); ++i)
+ collection.remove(*removeObjects[i]);
+}
+
+PxCollection* PxCollectionExt::createCollection(PxPhysics& physics)
+{
+ PxCollection* collection = PxCreateCollection();
+ if (!collection)
+ return NULL;
+
+ // Collect convexes
+ {
+ shdfnd::Array<PxConvexMesh*> objects(physics.getNbConvexMeshes());
+ const PxU32 nb = physics.getConvexMeshes(objects.begin(), objects.size());
+ PX_ASSERT(nb == objects.size());
+ PX_UNUSED(nb);
+
+ for(PxU32 i=0;i<objects.size();i++)
+ collection->add(*objects[i]);
+ }
+
+ // Collect triangle meshes
+ {
+ shdfnd::Array<PxTriangleMesh*> objects(physics.getNbTriangleMeshes());
+ const PxU32 nb = physics.getTriangleMeshes(objects.begin(), objects.size());
+
+ PX_ASSERT(nb == objects.size());
+ PX_UNUSED(nb);
+
+ for(PxU32 i=0;i<objects.size();i++)
+ collection->add(*objects[i]);
+ }
+
+ // Collect heightfields
+ {
+ shdfnd::Array<PxHeightField*> objects(physics.getNbHeightFields());
+ const PxU32 nb = physics.getHeightFields(objects.begin(), objects.size());
+
+ PX_ASSERT(nb == objects.size());
+ PX_UNUSED(nb);
+
+ for(PxU32 i=0;i<objects.size();i++)
+ collection->add(*objects[i]);
+ }
+
+ // Collect materials
+ {
+ shdfnd::Array<PxMaterial*> objects(physics.getNbMaterials());
+ const PxU32 nb = physics.getMaterials(objects.begin(), objects.size());
+
+ PX_ASSERT(nb == objects.size());
+ PX_UNUSED(nb);
+
+ for(PxU32 i=0;i<objects.size();i++)
+ collection->add(*objects[i]);
+ }
+
+#if PX_USE_CLOTH_API
+ // Collect cloth fabrics
+ {
+ shdfnd::Array<PxClothFabric*> objects(physics.getNbClothFabrics());
+ const PxU32 nb = physics.getClothFabrics(objects.begin(), objects.size());
+
+ PX_ASSERT(nb == objects.size());
+ PX_UNUSED(nb);
+
+ for(PxU32 i=0;i<objects.size();i++)
+ collection->add(*objects[i]);
+ }
+#endif
+
+ // Collect shapes
+ {
+ shdfnd::Array<PxShape*> objects(physics.getNbShapes());
+ const PxU32 nb = physics.getShapes(objects.begin(), objects.size());
+
+ PX_ASSERT(nb == objects.size());
+ PX_UNUSED(nb);
+
+ for(PxU32 i=0;i<objects.size();i++)
+ collection->add(*objects[i]);
+ }
+ return collection;
+}
+
+PxCollection* PxCollectionExt::createCollection(PxScene& scene)
+{
+ PxCollection* collection = PxCreateCollection();
+ if (!collection)
+ return NULL;
+
+ // Collect actors
+ {
+ PxActorTypeFlags selectionFlags = PxActorTypeFlag::eRIGID_STATIC | PxActorTypeFlag::eRIGID_DYNAMIC;
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ selectionFlags |= PxActorTypeFlag::ePARTICLE_SYSTEM | PxActorTypeFlag::ePARTICLE_FLUID;
+#endif
+#if PX_USE_CLOTH_API
+ selectionFlags |= PxActorTypeFlag::eCLOTH;
+#endif
+
+ shdfnd::Array<PxActor*> objects(scene.getNbActors(selectionFlags));
+ const PxU32 nb = scene.getActors(selectionFlags, objects.begin(), objects.size());
+
+ PX_ASSERT(nb==objects.size());
+ PX_UNUSED(nb);
+
+ for(PxU32 i=0;i<objects.size();i++)
+ collection->add(*objects[i]);
+ }
+
+
+ // Collect constraints
+ {
+ shdfnd::Array<PxConstraint*> objects(scene.getNbConstraints());
+ const PxU32 nb = scene.getConstraints(objects.begin(), objects.size());
+
+ PX_ASSERT(nb==objects.size());
+ PX_UNUSED(nb);
+
+ for(PxU32 i=0;i<objects.size();i++)
+ {
+ PxU32 typeId;
+ PxJoint* joint = reinterpret_cast<PxJoint*>(objects[i]->getExternalReference(typeId));
+ if(typeId == PxConstraintExtIDs::eJOINT)
+ collection->add(*joint);
+ }
+ }
+
+ // Collect articulations
+ {
+ shdfnd::Array<PxArticulation*> objects(scene.getNbArticulations());
+ const PxU32 nb = scene.getArticulations(objects.begin(), objects.size());
+
+ PX_ASSERT(nb==objects.size());
+ PX_UNUSED(nb);
+
+ for(PxU32 i=0;i<objects.size();i++)
+ collection->add(*objects[i]);
+ }
+
+ // Collect aggregates
+ {
+ shdfnd::Array<PxAggregate*> objects(scene.getNbAggregates());
+ const PxU32 nb = scene.getAggregates(objects.begin(), objects.size());
+
+ PX_ASSERT(nb==objects.size());
+ PX_UNUSED(nb);
+
+ for(PxU32 i=0;i<objects.size();i++)
+ collection->add(*objects[i]);
+ }
+
+ return collection;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtConstraintHelper.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtConstraintHelper.h
new file mode 100644
index 00000000..b742434d
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtConstraintHelper.h
@@ -0,0 +1,378 @@
+// 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_CONSTRAINT_HELPER_H
+#define NP_CONSTRAINT_HELPER_H
+
+#include "foundation/PxAssert.h"
+#include "foundation/PxTransform.h"
+#include "foundation/PxMat33.h"
+#include "PxJointLimit.h"
+#include "ExtJoint.h"
+
+namespace physx
+{
+namespace Ext
+{
+ namespace joint
+ {
+ PX_INLINE void computeDerived(const JointData& data,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w,
+ PxTransform& cA2w,
+ PxTransform& cB2w,
+ PxTransform& cB2cA)
+ {
+ PX_ASSERT(bA2w.isValid() && bB2w.isValid());
+
+ cA2w = bA2w.transform(data.c2b[0]);
+ cB2w = bB2w.transform(data.c2b[1]);
+
+ if(cA2w.q.dot(cB2w.q)<0) // minimum error quat
+ cB2w.q = -cB2w.q;
+
+ cB2cA = cA2w.transformInv(cB2w);
+
+ PX_ASSERT(cA2w.isValid() && cB2w.isValid() && cB2cA.isValid());
+ }
+
+ PX_INLINE PxVec3 truncateLinear(const PxVec3& in, PxReal tolerance, bool& truncated)
+ {
+ PxReal m = in.magnitudeSquared();
+ truncated = m>tolerance * tolerance;
+ return truncated ? in * PxRecipSqrt(m) * tolerance : in;
+ }
+
+ PX_INLINE PxQuat truncateAngular(const PxQuat& in, PxReal sinHalfTol, PxReal cosHalfTol, bool& truncated)
+ {
+ truncated = false;
+
+ if(sinHalfTol > 0.9999f) // fixes numerical tolerance issue of projecting because quat is not exactly normalized
+ return in;
+
+ PxQuat q = in.w>=0 ? in : -in;
+
+ const PxVec3& im = q.getImaginaryPart();
+ PxReal m = im.magnitudeSquared();
+ truncated = m>sinHalfTol*sinHalfTol;
+ if(!truncated)
+ return in;
+
+ PxVec3 outV = im * sinHalfTol * PxRecipSqrt(m);
+ return PxQuat(outV.x, outV.y, outV.z, cosHalfTol);
+ }
+
+ PX_FORCE_INLINE void projectTransforms(PxTransform& bA2w, PxTransform& bB2w,
+ const PxTransform& cA2w, const PxTransform& cB2w,
+ const PxTransform& cB2cA, const JointData& data, bool projectToA)
+ {
+ PX_ASSERT(cB2cA.isValid());
+
+ // normalization here is unfortunate: long chains of projected constraints can result in
+ // accumulation of error in the quaternion which eventually leaves the quaternion
+ // magnitude outside the validation range. The approach here is slightly overconservative
+ // in that we could just normalize the quaternions which are out of range, but since we
+ // regard projection as an occasional edge case it shouldn't be perf-sensitive, and
+ // this way we maintain the invariant (also maintained by the dynamics integrator) that
+ // body quats are properly normalized up to FP error.
+
+ if (projectToA)
+ {
+ bB2w = cA2w.transform(cB2cA.transform(data.c2b[1].getInverse()));
+ bB2w.q.normalize();
+ }
+ else
+ {
+ bA2w = cB2w.transform(cB2cA.transformInv(data.c2b[0].getInverse()));
+ bA2w.q.normalize();
+ }
+
+
+ PX_ASSERT(bA2w.isValid());
+ PX_ASSERT(bB2w.isValid());
+ }
+
+
+
+ PX_INLINE void computeJacobianAxes(PxVec3 row[3], const PxQuat& qa, const PxQuat& qb)
+ {
+ // Compute jacobian matrix for (qa* qb) [[* means conjugate in this expr]]
+ // d/dt (qa* qb) = 1/2 L(qa*) R(qb) (omega_b - omega_a)
+ // result is L(qa*) R(qb), where L(q) and R(q) are left/right q multiply matrix
+
+ PxReal wa = qa.w, wb = qb.w;
+ const PxVec3 va(qa.x,qa.y,qa.z), vb(qb.x,qb.y,qb.z);
+
+ const PxVec3 c = vb*wa + va*wb;
+ const PxReal d0 = wa*wb;
+ const PxReal d1 = va.dot(vb);
+ const PxReal d = d0 - d1;
+
+ row[0] = (va * vb.x + vb * va.x + PxVec3(d, c.z, -c.y)) * 0.5f;
+ row[1] = (va * vb.y + vb * va.y + PxVec3(-c.z, d, c.x)) * 0.5f;
+ row[2] = (va * vb.z + vb * va.z + PxVec3(c.y, -c.x, d)) * 0.5f;
+
+ if ((d0 + d1) != 0.0f) // check if relative rotation is 180 degrees which can lead to singular matrix
+ return;
+ else
+ {
+ row[0].x += PX_EPS_F32;
+ row[1].y += PX_EPS_F32;
+ row[2].z += PX_EPS_F32;
+ }
+ }
+
+ class ConstraintHelper
+ {
+ Px1DConstraint* mConstraints;
+ Px1DConstraint* mCurrent;
+ PxVec3 mRa, mRb;
+
+ public:
+ ConstraintHelper(Px1DConstraint* c, const PxVec3& ra, const PxVec3& rb)
+ : mConstraints(c), mCurrent(c), mRa(ra), mRb(rb) {}
+
+
+ // hard linear & angular
+ PX_FORCE_INLINE void linearHard(const PxVec3& axis, PxReal posErr)
+ {
+ Px1DConstraint *c = linear(axis, posErr, PxConstraintSolveHint::eEQUALITY);
+ c->flags |= Px1DConstraintFlag::eOUTPUT_FORCE;
+ }
+
+ PX_FORCE_INLINE void angularHard(const PxVec3& axis, PxReal posErr)
+ {
+ Px1DConstraint *c = angular(axis, posErr, PxConstraintSolveHint::eEQUALITY);
+ c->flags |= Px1DConstraintFlag::eOUTPUT_FORCE;
+ }
+
+ // limited linear & angular
+ PX_FORCE_INLINE void linearLimit(const PxVec3& axis, PxReal ordinate, PxReal limitValue, const PxJointLimitParameters& limit)
+ {
+ PxReal pad = limit.isSoft() ? 0 : limit.contactDistance;
+
+ if(ordinate + pad > limitValue)
+ addLimit(linear(axis,limitValue - ordinate, PxConstraintSolveHint::eNONE),limit);
+ }
+
+ PX_FORCE_INLINE void angularLimit(const PxVec3& axis, PxReal ordinate, PxReal limitValue, PxReal pad, const PxJointLimitParameters& limit)
+ {
+ if(limit.isSoft())
+ pad = 0;
+
+ if(ordinate + pad > limitValue)
+ addLimit(angular(axis,limitValue - ordinate, PxConstraintSolveHint::eNONE),limit);
+ }
+
+
+ PX_FORCE_INLINE void angularLimit(const PxVec3& axis, PxReal error, const PxJointLimitParameters& limit)
+ {
+ addLimit(angular(axis,error, PxConstraintSolveHint::eNONE),limit);
+ }
+
+ PX_FORCE_INLINE void halfAnglePair(PxReal halfAngle, PxReal lower, PxReal upper, PxReal pad, const PxVec3& axis, const PxJointLimitParameters& limit)
+ {
+ PX_ASSERT(lower<upper);
+ if(limit.isSoft())
+ pad = 0;
+
+ if(halfAngle < lower+pad)
+ angularLimit(-axis, -(lower - halfAngle)*2,limit);
+ if(halfAngle > upper-pad)
+ angularLimit(axis, (upper - halfAngle)*2, limit);
+ }
+
+ PX_FORCE_INLINE void quarterAnglePair(PxReal quarterAngle, PxReal lower, PxReal upper, PxReal pad, const PxVec3& axis, const PxJointLimitParameters& limit)
+ {
+ if(limit.isSoft())
+ pad = 0;
+
+ PX_ASSERT(lower<upper);
+ if(quarterAngle < lower+pad)
+ angularLimit(-axis, -(lower - quarterAngle)*4,limit);
+ if(quarterAngle > upper-pad)
+ angularLimit(axis, (upper - quarterAngle)*4, limit);
+ }
+
+ // driven linear & angular
+
+ PX_FORCE_INLINE void linear(const PxVec3& axis, PxReal velTarget, PxReal error, const PxD6JointDrive& drive)
+ {
+ addDrive(linear(axis,error,PxConstraintSolveHint::eNONE),velTarget,drive);
+ }
+
+ PX_FORCE_INLINE void angular(const PxVec3& axis, PxReal velTarget, PxReal error, const PxD6JointDrive& drive, PxConstraintSolveHint::Enum hint = PxConstraintSolveHint::eNONE)
+ {
+ addDrive(angular(axis,error,hint),velTarget,drive);
+ }
+
+
+ PX_FORCE_INLINE PxU32 getCount() { return PxU32(mCurrent - mConstraints); }
+
+ void prepareLockedAxes(const PxQuat& qA, const PxQuat& qB, const PxVec3& cB2cAp, PxU32 lin, PxU32 ang)
+ {
+ Px1DConstraint* current = mCurrent;
+ if(ang)
+ {
+ PxQuat qB2qA = qA.getConjugate() * qB;
+
+ PxVec3 row[3];
+ computeJacobianAxes(row, qA, qB);
+ PxVec3 imp = qB2qA.getImaginaryPart();
+ if(ang&1) angular(row[0], -imp.x, PxConstraintSolveHint::eEQUALITY, current++);
+ if(ang&2) angular(row[1], -imp.y, PxConstraintSolveHint::eEQUALITY, current++);
+ if(ang&4) angular(row[2], -imp.z, PxConstraintSolveHint::eEQUALITY, current++);
+ }
+
+ if(lin)
+ {
+ PxMat33 axes(qA);
+ if(lin&1) linear(axes[0], -cB2cAp[0], PxConstraintSolveHint::eEQUALITY, current++);
+ if(lin&2) linear(axes[1], -cB2cAp[1], PxConstraintSolveHint::eEQUALITY, current++);
+ if(lin&4) linear(axes[2], -cB2cAp[2], PxConstraintSolveHint::eEQUALITY, current++);
+ }
+
+ for(Px1DConstraint* front = mCurrent; front < current; front++)
+ front->flags = Px1DConstraintFlag::eOUTPUT_FORCE;
+
+ mCurrent = current;
+ }
+
+ Px1DConstraint *getConstraintRow()
+ {
+ return mCurrent++;
+ }
+
+ private:
+ PX_FORCE_INLINE Px1DConstraint* linear(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint)
+ {
+ Px1DConstraint* c = mCurrent++;
+
+ c->solveHint = PxU16(hint);
+ c->linear0 = axis; c->angular0 = mRa.cross(axis);
+ c->linear1 = axis; c->angular1 = mRb.cross(axis);
+ PX_ASSERT(c->linear0.isFinite());
+ PX_ASSERT(c->linear1.isFinite());
+ PX_ASSERT(c->angular0.isFinite());
+ PX_ASSERT(c->angular1.isFinite());
+
+ c->geometricError = posErr;
+
+ return c;
+ }
+
+ PX_FORCE_INLINE Px1DConstraint* angular(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint)
+ {
+ Px1DConstraint* c = mCurrent++;
+
+ c->solveHint = PxU16(hint);
+ c->linear0 = PxVec3(0); c->angular0 = axis;
+ c->linear1 = PxVec3(0); c->angular1 = axis;
+
+ c->geometricError = posErr;
+ return c;
+ }
+
+ PX_FORCE_INLINE Px1DConstraint* linear(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint, Px1DConstraint* c)
+ {
+ c->solveHint = PxU16(hint);
+ c->linear0 = axis; c->angular0 = mRa.cross(axis);
+ c->linear1 = axis; c->angular1 = mRb.cross(axis);
+ PX_ASSERT(c->linear0.isFinite());
+ PX_ASSERT(c->linear1.isFinite());
+ PX_ASSERT(c->angular0.isFinite());
+ PX_ASSERT(c->angular1.isFinite());
+
+ c->geometricError = posErr;
+
+
+ return c;
+ }
+
+ PX_FORCE_INLINE Px1DConstraint* angular(const PxVec3& axis, PxReal posErr, PxConstraintSolveHint::Enum hint, Px1DConstraint* c)
+ {
+ c->solveHint = PxU16(hint);
+ c->linear0 = PxVec3(0.f); c->angular0 = axis;
+ c->linear1 = PxVec3(0.f); c->angular1 = axis;
+
+ c->geometricError = posErr;
+
+ return c;
+ }
+
+ void addLimit(Px1DConstraint* c, const PxJointLimitParameters& limit)
+ {
+ PxU16 flags = PxU16(c->flags | Px1DConstraintFlag::eOUTPUT_FORCE);
+
+ if(limit.isSoft())
+ {
+ flags |= Px1DConstraintFlag::eSPRING;
+ c->mods.spring.stiffness = limit.stiffness;
+ c->mods.spring.damping = limit.damping;
+ }
+ else
+ {
+ c->solveHint = PxConstraintSolveHint::eINEQUALITY;
+ c->mods.bounce.restitution = limit.restitution;
+ c->mods.bounce.velocityThreshold = limit.bounceThreshold;
+ if(c->geometricError>0)
+ flags |= Px1DConstraintFlag::eKEEPBIAS;
+ if(limit.restitution>0)
+ flags |= Px1DConstraintFlag::eRESTITUTION;
+ }
+
+ c->flags = flags;
+ c->minImpulse = 0;
+ }
+
+ void addDrive(Px1DConstraint* c, PxReal velTarget, const PxD6JointDrive& drive)
+ {
+ c->velocityTarget = velTarget;
+
+ PxU16 flags = PxU16(c->flags | Px1DConstraintFlag::eSPRING | Px1DConstraintFlag::eHAS_DRIVE_LIMIT);
+ if(drive.flags & PxD6JointDriveFlag::eACCELERATION)
+ flags |= Px1DConstraintFlag::eACCELERATION_SPRING;
+ c->flags = flags;
+ c->mods.spring.stiffness = drive.stiffness;
+ c->mods.spring.damping = drive.damping;
+
+ c->minImpulse = -drive.forceLimit;
+ c->maxImpulse = drive.forceLimit;
+
+ PX_ASSERT(c->linear0.isFinite());
+ PX_ASSERT(c->angular0.isFinite());
+ }
+ };
+ }
+} // namespace
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtConvexMeshExt.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtConvexMeshExt.cpp
new file mode 100644
index 00000000..ef0aab39
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtConvexMeshExt.cpp
@@ -0,0 +1,91 @@
+// 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 "PxConvexMeshExt.h"
+#include "PxConvexMeshGeometry.h"
+#include "PxConvexMesh.h"
+#include "foundation/PxTransform.h"
+
+using namespace physx;
+
+static const PxReal gEpsilon = .01f;
+
+PxU32 physx::PxFindFaceIndex(const PxConvexMeshGeometry& convexGeom, const PxTransform& pose,
+ const PxVec3& impactPos, const PxVec3& unitDir)
+{
+ PX_ASSERT(unitDir.isFinite());
+ PX_ASSERT(unitDir.isNormalized());
+ PX_ASSERT(impactPos.isFinite());
+ PX_ASSERT(pose.isFinite());
+
+ const PxVec3 impact = impactPos - unitDir * gEpsilon;
+
+ const PxVec3 localPoint = pose.transformInv(impact);
+ const PxVec3 localDir = pose.rotateInv(unitDir);
+
+ // Create shape to vertex scale transformation matrix
+ const PxMeshScale& meshScale = convexGeom.scale;
+ const PxMat33 rot(meshScale.rotation);
+ PxMat33 shape2VertexSkew = rot.getTranspose();
+ const PxMat33 diagonal = PxMat33::createDiagonal(PxVec3(1.0f / meshScale.scale.x, 1.0f / meshScale.scale.y, 1.0f / meshScale.scale.z));
+ shape2VertexSkew = shape2VertexSkew * diagonal;
+ shape2VertexSkew = shape2VertexSkew * rot;
+
+ const PxU32 nbPolys = convexGeom.convexMesh->getNbPolygons();
+ PxU32 minIndex = 0;
+ PxReal minD = PX_MAX_REAL;
+ for (PxU32 j = 0; j < nbPolys; j++)
+ {
+ PxHullPolygon hullPolygon;
+ convexGeom.convexMesh->getPolygonData(j, hullPolygon);
+
+ // transform hull plane into shape space
+ PxPlane plane;
+ const PxVec3 tmp = shape2VertexSkew.transformTranspose(PxVec3(hullPolygon.mPlane[0],hullPolygon.mPlane[1],hullPolygon.mPlane[2]));
+ const PxReal denom = 1.0f / tmp.magnitude();
+ plane.n = tmp * denom;
+ plane.d = hullPolygon.mPlane[3] * denom;
+
+ PxReal d = plane.distance(localPoint);
+ if (d < 0.0f)
+ continue;
+
+ const PxReal tweak = plane.n.dot(localDir) * gEpsilon;
+ d += tweak;
+
+ if (d < minD)
+ {
+ minIndex = j;
+ minD = d;
+ }
+ }
+ return minIndex;
+}
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.cpp
new file mode 100644
index 00000000..fb977c36
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.cpp
@@ -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.
+
+
+#include "task/PxTask.h"
+#include "ExtCpuWorkerThread.h"
+#include "ExtDefaultCpuDispatcher.h"
+#include "ExtTaskQueueHelper.h"
+#include "PsFPU.h"
+
+using namespace physx;
+
+Ext::CpuWorkerThread::CpuWorkerThread()
+: mQueueEntryPool(EXT_TASK_QUEUE_ENTRY_POOL_SIZE),
+ mThreadId(0)
+{
+}
+
+
+Ext::CpuWorkerThread::~CpuWorkerThread()
+{
+}
+
+
+void Ext::CpuWorkerThread::initialize(DefaultCpuDispatcher* ownerDispatcher)
+{
+ mOwner = ownerDispatcher;
+}
+
+
+bool Ext::CpuWorkerThread::tryAcceptJobToLocalQueue(PxBaseTask& task, Ps::Thread::Id taskSubmitionThread)
+{
+ if(taskSubmitionThread == mThreadId)
+ {
+ SharedQueueEntry* entry = mQueueEntryPool.getEntry(&task);
+ if (entry)
+ {
+ mLocalJobList.push(*entry);
+ return true;
+ }
+ else
+ return false;
+ }
+
+ return false;
+}
+
+
+PxBaseTask* Ext::CpuWorkerThread::giveUpJob()
+{
+ return TaskQueueHelper::fetchTask(mLocalJobList, mQueueEntryPool);
+}
+
+
+void Ext::CpuWorkerThread::execute()
+{
+ mThreadId = getId();
+
+ while (!quitIsSignalled())
+ {
+ mOwner->resetWakeSignal();
+
+ PxBaseTask* task = TaskQueueHelper::fetchTask(mLocalJobList, mQueueEntryPool);
+
+ if(!task)
+ task = mOwner->fetchNextTask();
+
+ if (task)
+ {
+ mOwner->runTask(*task);
+ task->release();
+ }
+ else
+ {
+ mOwner->waitForWork();
+ }
+ }
+
+ quit();
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.h
new file mode 100644
index 00000000..e1f1c82d
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtCpuWorkerThread.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 PX_PHYSICS_EXTENSIONS_NP_CPU_WORKER_THREAD_H
+#define PX_PHYSICS_EXTENSIONS_NP_CPU_WORKER_THREAD_H
+
+#include "CmPhysXCommon.h"
+#include "PsThread.h"
+#include "ExtDefaultCpuDispatcher.h"
+#include "ExtSharedQueueEntryPool.h"
+
+
+namespace physx
+{
+namespace Ext
+{
+class DefaultCpuDispatcher;
+
+
+#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 // Because of the SList member I assume
+
+ class CpuWorkerThread : public Ps::Thread
+ {
+ public:
+ CpuWorkerThread();
+ ~CpuWorkerThread();
+
+ void initialize(DefaultCpuDispatcher* ownerDispatcher);
+ void execute();
+ bool tryAcceptJobToLocalQueue(PxBaseTask& task, Ps::Thread::Id taskSubmitionThread);
+ PxBaseTask* giveUpJob();
+ Ps::Thread::Id getWorkerThreadId() const { return mThreadId; }
+
+ protected:
+ SharedQueueEntryPool<> mQueueEntryPool;
+ DefaultCpuDispatcher* mOwner;
+ Ps::SList mLocalJobList;
+ Ps::Thread::Id mThreadId;
+ };
+
+#if PX_VC
+#pragma warning(pop)
+#endif
+
+} // namespace Ext
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.cpp
new file mode 100644
index 00000000..5fdad2e7
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.cpp
@@ -0,0 +1,564 @@
+// 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 "ExtD6Joint.h"
+#include "ExtConstraintHelper.h"
+#include "CmRenderOutput.h"
+#include "CmConeLimitHelper.h"
+#include "PxTolerancesScale.h"
+#include "CmUtils.h"
+#include "PxConstraint.h"
+
+#include "common/PxSerialFramework.h"
+
+using namespace physx;
+using namespace Ext;
+
+PxD6Joint* physx::PxD6JointCreate(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+{
+ PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxD6JointCreate: local frame 0 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxD6JointCreate: local frame 1 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxD6JointCreate: actors must be different");
+ PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxD6JointCreate: at least one actor must be dynamic");
+
+ D6Joint *j;
+ PX_NEW_SERIALIZED(j,D6Joint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1);
+ if(j->attach(physics, actor0, actor1))
+ return j;
+
+ PX_DELETE(j);
+ return NULL;
+}
+
+
+
+D6Joint::D6Joint(const PxTolerancesScale& scale,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+: D6JointT(PxJointConcreteType::eD6, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+, mRecomputeMotion(true)
+, mRecomputeLimits(true)
+{
+ D6JointData* data = reinterpret_cast<D6JointData*>(PX_ALLOC(sizeof(D6JointData), "D6JointData"));
+ Cm::markSerializedMem(data, sizeof(D6JointData));
+ mData = data;
+
+ initCommonData(*data,actor0, localFrame0, actor1, localFrame1);
+ for(PxU32 i=0;i<6;i++)
+ data->motion[i] = PxD6Motion::eLOCKED;
+
+ data->twistLimit = PxJointAngularLimitPair(-PxPi/2, PxPi/2);
+ data->swingLimit = PxJointLimitCone(PxPi/2, PxPi/2);
+ data->linearLimit = PxJointLinearLimit(scale, PX_MAX_F32);
+ data->linearMinDist = 1e-6f*scale.length;
+
+ for(PxU32 i=0;i<PxD6Drive::eCOUNT;i++)
+ data->drive[i] = PxD6JointDrive();
+
+ data->drivePosition = PxTransform(PxIdentity);
+ data->driveLinearVelocity = PxVec3(0);
+ data->driveAngularVelocity = PxVec3(0);
+
+ data->projectionLinearTolerance = 1e10;
+ data->projectionAngularTolerance = PxPi;
+}
+
+PxD6Motion::Enum D6Joint::getMotion(PxD6Axis::Enum index) const
+{
+ return data().motion[index];
+}
+
+void D6Joint::setMotion(PxD6Axis::Enum index, PxD6Motion::Enum t)
+{
+ data().motion[index] = t;
+ mRecomputeMotion = true;
+ markDirty();
+}
+
+PxReal D6Joint::getTwist() const
+{
+ PxQuat q = getRelativeTransform().q, swing, twist;
+ Ps::separateSwingTwist(q, swing, twist);
+ if (twist.x < 0)
+ twist = -twist;
+ PxReal angle = twist.getAngle(); // angle is in range [0, 2pi]
+ return angle < PxPi ? angle : angle - PxTwoPi;
+}
+
+PxReal D6Joint::getSwingYAngle() const
+{
+ PxQuat q = getRelativeTransform().q, swing, twist;
+ Ps::separateSwingTwist(q, swing, twist);
+ if (swing.w < 0) // choose the shortest rotation
+ swing = -swing;
+
+ PxReal angle = 4 * PxAtan2(swing.y, 1 + swing.w); // tan (t/2) = sin(t)/(1+cos t), so this is the quarter angle
+ PX_ASSERT(angle>-PxPi && angle<=PxPi); // since |y| < w+1, the atan magnitude is < PI/4
+ return angle;
+}
+
+PxReal D6Joint::getSwingZAngle() const
+{
+ PxQuat q = getRelativeTransform().q, swing, twist;
+ Ps::separateSwingTwist(q, swing, twist);
+ if (swing.w < 0) // choose the shortest rotation
+ swing = -swing;
+
+ PxReal angle = 4 * PxAtan2(swing.z, 1 + swing.w); // tan (t/2) = sin(t)/(1+cos t), so this is the quarter angle
+ PX_ASSERT(angle>-PxPi && angle <= PxPi); // since |y| < w+1, the atan magnitude is < PI/4
+ return angle;
+}
+
+
+PxD6JointDrive D6Joint::getDrive(PxD6Drive::Enum index) const
+{
+ return data().drive[index];
+}
+
+void D6Joint::setDrive(PxD6Drive::Enum index, const PxD6JointDrive& d)
+{
+ PX_CHECK_AND_RETURN(d.isValid(), "PxD6Joint::setDrive: drive is invalid");
+
+ data().drive[index] = d;
+ mRecomputeMotion = true;
+ markDirty();
+}
+
+PxJointLinearLimit D6Joint::getLinearLimit() const
+{
+
+ return data().linearLimit;
+}
+
+void D6Joint::setLinearLimit(const PxJointLinearLimit& l)
+{
+ PX_CHECK_AND_RETURN(l.isValid(), "PxD6Joint::setLinearLimit: limit invalid");
+ data().linearLimit = l;
+ mRecomputeLimits = true;
+ markDirty();
+}
+
+PxJointAngularLimitPair D6Joint::getTwistLimit() const
+{
+ return data().twistLimit;
+}
+
+void D6Joint::setTwistLimit(const PxJointAngularLimitPair& l)
+{
+ PX_CHECK_AND_RETURN(l.isValid(), "PxD6Joint::setTwistLimit: limit invalid");
+ PX_CHECK_AND_RETURN(l.lower>-PxTwoPi && l.upper<PxTwoPi , "PxD6Joint::twist limit must be strictly -2*PI and 2*PI");
+ PX_CHECK_AND_RETURN(l.upper - l.lower < PxTwoPi, "PxD6Joint::twist limit range must be strictly less than 2*PI");
+
+ data().twistLimit = l;
+ mRecomputeLimits = true;
+ markDirty();
+}
+
+PxJointLimitCone D6Joint::getSwingLimit() const
+{
+ return data().swingLimit;
+}
+
+void D6Joint::setSwingLimit(const PxJointLimitCone& l)
+{
+ PX_CHECK_AND_RETURN(l.isValid(), "PxD6Joint::setSwingLimit: limit invalid");
+
+ data().swingLimit = l;
+ mRecomputeLimits = true;
+ markDirty();
+}
+
+PxTransform D6Joint::getDrivePosition() const
+{
+ return data().drivePosition;
+}
+
+void D6Joint::setDrivePosition(const PxTransform& pose)
+{
+ PX_CHECK_AND_RETURN(pose.isSane(), "PxD6Joint::setDrivePosition: pose invalid");
+ data().drivePosition = pose.getNormalized();
+ markDirty();
+}
+
+void D6Joint::getDriveVelocity(PxVec3& linear, PxVec3& angular) const
+{
+ linear = data().driveLinearVelocity;
+ angular = data().driveAngularVelocity;
+}
+
+void D6Joint::setDriveVelocity(const PxVec3& linear,
+ const PxVec3& angular)
+{
+ PX_CHECK_AND_RETURN(linear.isFinite() && angular.isFinite(), "PxD6Joint::setDriveVelocity: velocity invalid");
+ data().driveLinearVelocity = linear;
+ data().driveAngularVelocity = angular;
+ markDirty();
+}
+
+void D6Joint::setProjectionAngularTolerance(PxReal tolerance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0 && tolerance <= PxPi, "PxD6Joint::setProjectionAngularTolerance: tolerance invalid");
+ data().projectionAngularTolerance = tolerance;
+ markDirty();
+}
+
+PxReal D6Joint::getProjectionAngularTolerance() const
+{
+ return data().projectionAngularTolerance;
+}
+
+void D6Joint::setProjectionLinearTolerance(PxReal tolerance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0, "PxD6Joint::setProjectionLinearTolerance: invalid parameter");
+ data().projectionLinearTolerance = tolerance;
+ markDirty();
+}
+
+PxReal D6Joint::getProjectionLinearTolerance() const
+{
+ return data().projectionLinearTolerance;
+}
+
+
+
+void* D6Joint::prepareData()
+{
+ D6JointData& d = data();
+
+ if(mRecomputeLimits)
+ {
+ d.thSwingY = PxTan(d.swingLimit.yAngle/2);
+ d.thSwingZ = PxTan(d.swingLimit.zAngle/2);
+ d.thSwingPad = PxTan(d.swingLimit.contactDistance/2);
+
+ d.tqSwingY = PxTan(d.swingLimit.yAngle/4);
+ d.tqSwingZ = PxTan(d.swingLimit.zAngle/4);
+ d.tqSwingPad = PxTan(d.swingLimit.contactDistance/4);
+
+ d.tqTwistLow = PxTan(d.twistLimit.lower/4);
+ d.tqTwistHigh = PxTan(d.twistLimit.upper/4);
+ d.tqTwistPad = PxTan(d.twistLimit.contactDistance/4);
+ mRecomputeLimits = false;
+ }
+
+ if(mRecomputeMotion)
+ {
+ d.driving = 0;
+ d.limited = 0;
+ d.locked = 0;
+
+ for(PxU32 i=0;i<PxD6Axis::eCOUNT;i++)
+ {
+ if(d.motion[i] == PxD6Motion::eLIMITED)
+ d.limited |= 1<<i;
+ else if(d.motion[i] == PxD6Motion::eLOCKED)
+ d.locked |= 1<<i;
+ }
+
+ // a linear direction isn't driven if it's locked
+ if(active(PxD6Drive::eX) && d.motion[PxD6Axis::eX]!=PxD6Motion::eLOCKED) d.driving |= 1<< PxD6Drive::eX;
+ if(active(PxD6Drive::eY) && d.motion[PxD6Axis::eY]!=PxD6Motion::eLOCKED) d.driving |= 1<< PxD6Drive::eY;
+ if(active(PxD6Drive::eZ) && d.motion[PxD6Axis::eZ]!=PxD6Motion::eLOCKED) d.driving |= 1<< PxD6Drive::eZ;
+
+ // SLERP drive requires all angular dofs unlocked, and inhibits swing/twist
+
+ bool swing1Locked = d.motion[PxD6Axis::eSWING1] == PxD6Motion::eLOCKED;
+ bool swing2Locked = d.motion[PxD6Axis::eSWING2] == PxD6Motion::eLOCKED;
+ bool twistLocked = d.motion[PxD6Axis::eTWIST] == PxD6Motion::eLOCKED;
+
+ if(active(PxD6Drive::eSLERP) && !swing1Locked && !swing2Locked && !twistLocked)
+ d.driving |= 1<<PxD6Drive::eSLERP;
+ else
+ {
+ if(active(PxD6Drive::eTWIST) && !twistLocked)
+ d.driving |= 1<<PxD6Drive::eTWIST;
+ if(active(PxD6Drive::eSWING) && (!swing1Locked || !swing2Locked))
+ d.driving |= 1<< PxD6Drive::eSWING;
+ }
+
+ mRecomputeMotion = false;
+ }
+
+ this->D6JointT::prepareData();
+
+ return mData;
+}
+
+// Notes:
+/*
+
+This used to be in the linear drive model:
+
+ if(motion[PxD6Axis::eX+i] == PxD6Motion::eLIMITED)
+ {
+ if(data.driveLinearVelocity[i] < 0.0f && cB2cA.p[i] < -mLimits[PxD6Limit::eLINEAR].mValue ||
+ data.driveLinearVelocity[i] > 0.0f && cB2cA.p[i] > mLimits[PxD6Limit::eLINEAR].mValue)
+ continue;
+ }
+
+it doesn't seem like a good idea though, because it turns off drive altogether, despite the fact that positional
+drive might pull us back in towards the limit. Might be better to make the drive unilateral so it can only pull
+us in from the limit
+
+This used to be in angular locked:
+
+ // Angular locked
+ //TODO fix this properly.
+ if(PxAbs(cB2cA.q.x) < 0.0001f) cB2cA.q.x = 0;
+ if(PxAbs(cB2cA.q.y) < 0.0001f) cB2cA.q.y = 0;
+ if(PxAbs(cB2cA.q.z) < 0.0001f) cB2cA.q.z = 0;
+ if(PxAbs(cB2cA.q.w) < 0.0001f) cB2cA.q.w = 0;
+
+
+*/
+
+namespace
+{
+PxReal tanHalfFromSin(PxReal sin)
+{
+ return Ps::tanHalf(sin, 1 - sin*sin);
+}
+
+PxQuat truncate(const PxQuat& qIn, PxReal minCosHalfTol, bool& truncated)
+{
+ PxQuat q = qIn.w >= 0 ? qIn : -qIn;
+ truncated = q.w < minCosHalfTol;
+ if (!truncated)
+ return q;
+ PxVec3 v = q.getImaginaryPart().getNormalized() * PxSqrt(1 - minCosHalfTol * minCosHalfTol);
+ return PxQuat(v.x, v.y, v.z, minCosHalfTol);
+}
+
+// we decompose the quaternion as q1 * q2, where q1 is a rotation orthogonal to the unit axis, and q2 a rotation around it.
+// (so for example if 'axis' is the twist axis, this is separateSwingTwist).
+
+PxQuat project(const PxQuat& q, const PxVec3& axis, PxReal cosHalfTol, bool& truncated)
+{
+ PxReal a = q.getImaginaryPart().dot(axis);
+ PxQuat q2 = PxAbs(a) >= 1e-6f ? PxQuat(a*axis.x, a*axis.y, a*axis.z, q.w).getNormalized() : PxQuat(PxIdentity);
+ PxQuat q1 = q * q2.getConjugate();
+
+ PX_ASSERT(PxAbs(q1.getImaginaryPart().dot(q2.getImaginaryPart())) < 1e-6f);
+
+ return truncate(q1, cosHalfTol, truncated) * q2;
+}
+}
+
+namespace physx
+{
+// Here's how the angular part works:
+// * if no DOFs are locked, there's nothing to do.
+// * if all DOFs are locked, we just truncate the rotation
+// * if two DOFs are locked
+// * we decompose the rotation into swing * twist, where twist is a rotation around the free DOF and swing is a rotation around an axis orthogonal to the free DOF
+// * then we truncate swing
+// The case of one locked DOF is currently unimplemented, but one option would be:
+// * if one DOF is locked (the tricky case), we define the 'free' axis as follows (as the velocity solver prep function does)
+// TWIST: cB[0]
+// SWING1: cB[0].cross(cA[2])
+// SWING2: cB[0].cross(cA[1])
+// then, as above, we decompose into swing * free, and truncate the free rotation
+
+//export this in the physx namespace so we can unit test it
+PxQuat angularProject(PxU32 lockedDofs, const PxQuat& q, PxReal cosHalfTol, bool& truncated)
+{
+ PX_ASSERT(lockedDofs <= 7);
+ truncated = false;
+
+ switch (lockedDofs)
+ {
+ case 0: return q;
+ case 1: return q; // currently unimplemented
+ case 2: return q; // currently unimplemented
+ case 3: return project(q, PxVec3(0.0f, 0.0f, 1.0f), cosHalfTol, truncated);
+ case 4: return q; // currently unimplemented
+ case 5: return project(q, PxVec3(0.0f, 1.0f, 0.0f), cosHalfTol, truncated);
+ case 6: return project(q, PxVec3(1.0f, 0.0f, 0.0f), cosHalfTol, truncated);
+ case 7: return truncate(q, cosHalfTol, truncated);
+ default: return PxQuat(PxIdentity);
+ }
+}
+}
+
+namespace
+{
+void D6JointProject(const void* constantBlock,
+ PxTransform& bodyAToWorld,
+ PxTransform& bodyBToWorld,
+ bool projectToA)
+{
+ using namespace joint;
+ const D6JointData &data = *reinterpret_cast<const D6JointData*>(constantBlock);
+
+ PxTransform cA2w, cB2w, cB2cA, projected;
+ computeDerived(data, bodyAToWorld, bodyBToWorld, cA2w, cB2w, cB2cA);
+
+ PxVec3 v(data.locked & 1 ? cB2cA.p.x : 0,
+ data.locked & 2 ? cB2cA.p.y : 0,
+ data.locked & 4 ? cB2cA.p.z : 0);
+
+ bool linearTrunc, angularTrunc = false;
+ projected.p = truncateLinear(v, data.projectionLinearTolerance, linearTrunc) + (cB2cA.p - v);
+
+ projected.q = angularProject(data.locked >> 3, cB2cA.q, PxCos(data.projectionAngularTolerance / 2), angularTrunc);
+
+ if (linearTrunc || angularTrunc)
+ projectTransforms(bodyAToWorld, bodyBToWorld, cA2w, cB2w, projected, data, projectToA);
+}
+
+
+void D6JointVisualize(PxConstraintVisualizer &viz,
+ const void* constantBlock,
+ const PxTransform& body0Transform,
+ const PxTransform& body1Transform,
+ PxU32 /*flags*/)
+{
+ using namespace joint;
+
+ const PxU32 SWING1_FLAG = 1<<PxD6Axis::eSWING1,
+ SWING2_FLAG = 1<<PxD6Axis::eSWING2,
+ TWIST_FLAG = 1<<PxD6Axis::eTWIST;
+
+ const PxU32 ANGULAR_MASK = SWING1_FLAG | SWING2_FLAG | TWIST_FLAG;
+ const PxU32 LINEAR_MASK = 1<<PxD6Axis::eX | 1<<PxD6Axis::eY | 1<<PxD6Axis::eZ;
+
+ PX_UNUSED(ANGULAR_MASK);
+ PX_UNUSED(LINEAR_MASK);
+
+ const D6JointData & data = *reinterpret_cast<const D6JointData*>(constantBlock);
+
+ PxTransform cA2w = body0Transform * data.c2b[0];
+ PxTransform cB2w = body1Transform * data.c2b[1];
+
+ viz.visualizeJointFrames(cA2w, 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);
+ PxVec3 bX = cB2w_m[0], aY = cA2w_m[1], aZ = cA2w_m[2];
+
+ if(data.limited&TWIST_FLAG)
+ {
+ PxReal tqPhi = Ps::tanHalf(twist.x, twist.w); // always support (-pi, +pi)
+ viz.visualizeAngularLimit(cA2w, data.twistLimit.lower, data.twistLimit.upper,
+ PxAbs(tqPhi) > data.tqTwistHigh + data.tqSwingPad);
+ }
+
+ bool swing1Limited = (data.limited & SWING1_FLAG)!=0, swing2Limited = (data.limited & SWING2_FLAG)!=0;
+
+ if(swing1Limited && swing2Limited)
+ {
+ PxVec3 tanQSwing = PxVec3(0, Ps::tanHalf(swing.z,swing.w), -Ps::tanHalf(swing.y,swing.w));
+ Cm::ConeLimitHelper coneHelper(data.tqSwingZ, data.tqSwingY, data.tqSwingPad);
+ viz.visualizeLimitCone(cA2w, data.tqSwingZ, data.tqSwingY,
+ !coneHelper.contains(tanQSwing));
+ }
+ else if(swing1Limited ^ swing2Limited)
+ {
+ PxTransform yToX = PxTransform(PxVec3(0), PxQuat(-PxPi/2, PxVec3(0,0,1.f)));
+ PxTransform zToX = PxTransform(PxVec3(0), PxQuat(PxPi/2, PxVec3(0,1.f,0)));
+
+ if(swing1Limited)
+ {
+ if(data.locked & SWING2_FLAG)
+ viz.visualizeAngularLimit(cA2w * yToX, -data.swingLimit.yAngle, data.swingLimit.yAngle,
+ PxAbs(Ps::tanHalf(swing.y, swing.w)) > data.tqSwingY - data.tqSwingPad);
+ else
+ viz.visualizeDoubleCone(cA2w * zToX, data.swingLimit.yAngle,
+ PxAbs(tanHalfFromSin(aZ.dot(bX)))> data.thSwingY - data.thSwingPad);
+ }
+ else
+ {
+ if(data.locked & SWING1_FLAG)
+ viz.visualizeAngularLimit(cA2w * zToX, -data.swingLimit.zAngle, data.swingLimit.zAngle,
+ PxAbs(Ps::tanHalf(swing.z, swing.w)) > data.tqSwingZ - data.tqSwingPad);
+ else
+ viz.visualizeDoubleCone(cA2w * yToX, data.swingLimit.zAngle,
+ PxAbs(tanHalfFromSin(aY.dot(bX)))> data.thSwingZ - data.thSwingPad);
+ }
+ }
+}
+}
+
+bool D6Joint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1)
+{
+ mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(D6JointData));
+ return mPxConstraint!=NULL;
+}
+
+void D6Joint::exportExtraData(PxSerializationContext& stream)
+{
+ if(mData)
+ {
+ stream.alignData(PX_SERIAL_ALIGN);
+ stream.writeData(mData, sizeof(D6JointData));
+ }
+ stream.writeName(mName);
+}
+
+void D6Joint::importExtraData(PxDeserializationContext& context)
+{
+ if(mData)
+ mData = context.readExtraData<D6JointData, PX_SERIAL_ALIGN>();
+
+ context.readName(mName);
+}
+
+void D6Joint::resolveReferences(PxDeserializationContext& context)
+{
+ setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders));
+}
+
+D6Joint* D6Joint::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ D6Joint* obj = new (address) D6Joint(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(D6Joint);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+
+// global function to share the joint shaders with API capture
+const PxConstraintShaderTable* Ext::GetD6JointShaderTable()
+{
+ return &D6Joint::getConstraintShaderTable();
+}
+
+//~PX_SERIALIZATION
+PxConstraintShaderTable Ext::D6Joint::sShaders = { Ext::D6JointSolverPrep, D6JointProject, D6JointVisualize, PxConstraintFlag::eGPU_COMPATIBLE };
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.h
new file mode 100644
index 00000000..b789c688
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6Joint.h
@@ -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.
+
+
+#ifndef NP_D6JOINTCONSTRAINT_H
+#define NP_D6JOINTCONSTRAINT_H
+
+#include "ExtJoint.h"
+#include "PxD6Joint.h"
+
+namespace physx
+{
+struct PxD6JointGeneratedValues;
+namespace Ext
+{
+ struct D6JointData : public JointData
+ {
+ //= 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.
+ //==================================================================================================
+
+ PxD6Motion::Enum motion[6];
+ PxJointLinearLimit linearLimit;
+ PxJointAngularLimitPair twistLimit;
+ PxJointLimitCone swingLimit;
+
+ PxD6JointDrive drive[PxD6Drive::eCOUNT];
+
+ PxTransform drivePosition;
+ PxVec3 driveLinearVelocity;
+ PxVec3 driveAngularVelocity;
+
+ // derived quantities
+
+ PxU32 locked; // bitmap of locked DOFs
+ PxU32 limited; // bitmap of limited DOFs
+ PxU32 driving; // bitmap of active drives (implies driven DOFs not locked)
+
+ // tan-half and tan-quarter angles
+
+ PxReal thSwingY;
+ PxReal thSwingZ;
+ PxReal thSwingPad;
+
+ PxReal tqSwingY;
+ PxReal tqSwingZ;
+ PxReal tqSwingPad;
+
+ PxReal tqTwistLow;
+ PxReal tqTwistHigh;
+ PxReal tqTwistPad;
+
+ PxReal linearMinDist; // linear limit minimum distance to get a good direction
+
+ // projection quantities
+ PxReal projectionLinearTolerance;
+ PxReal projectionAngularTolerance;
+
+ // forestall compiler complaints about not being able to generate a constructor
+ private:
+ D6JointData(const PxJointLinearLimit& linear, const PxJointAngularLimitPair& twist, const PxJointLimitCone& swing):
+ linearLimit(linear), twistLimit(twist), swingLimit(swing) {}
+ };
+
+ typedef Joint<PxD6Joint, PxD6JointGeneratedValues> D6JointT;
+
+ class D6Joint : public Joint<PxD6Joint, PxD6JointGeneratedValues>
+ {
+ public:
+// PX_SERIALIZATION
+ D6Joint(PxBaseFlags baseFlags) : D6JointT(baseFlags) {}
+ virtual void exportExtraData(PxSerializationContext& context);
+ void importExtraData(PxDeserializationContext& context);
+ void resolveReferences(PxDeserializationContext& context);
+ static D6Joint* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ virtual ~D6Joint()
+ {
+ if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY)
+ PX_FREE(mData);
+ }
+
+ D6Joint(const PxTolerancesScale& scale,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1);
+
+
+ PxReal getTwist() const;
+ PxReal getSwingYAngle() const;
+ PxReal getSwingZAngle() const;
+
+
+ PxD6Motion::Enum getMotion(PxD6Axis::Enum index) const;
+ void setMotion(PxD6Axis::Enum index, PxD6Motion::Enum t);
+
+ PxD6JointDrive getDrive(PxD6Drive::Enum index) const;
+ void setDrive(PxD6Drive::Enum index, const PxD6JointDrive& d);
+
+ PxJointLinearLimit getLinearLimit() const;
+ void setLinearLimit(const PxJointLinearLimit& l);
+
+ PxJointAngularLimitPair getTwistLimit() const;
+ void setTwistLimit(const PxJointAngularLimitPair& l);
+
+ PxJointLimitCone getSwingLimit() const;
+ void setSwingLimit(const PxJointLimitCone& l);
+
+ PxTransform getDrivePosition() const;
+ void setDrivePosition(const PxTransform& pose);
+
+ void getDriveVelocity(PxVec3& linear,
+ PxVec3& angular) const;
+
+ void setDriveVelocity(const PxVec3& linear,
+ const PxVec3& angular);
+
+ void setProjectionAngularTolerance(PxReal tolerance);
+ PxReal getProjectionAngularTolerance() const;
+
+ void setProjectionLinearTolerance(PxReal tolerance);
+ PxReal getProjectionLinearTolerance() const;
+
+ void visualize(PxRenderBuffer& out,
+ const void* constantBlock,
+ const PxTransform& body0Transform,
+ const PxTransform& body1Transform,
+ PxReal frameScale,
+ PxReal limitScale,
+ PxU32 flags) const;
+
+ bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1);
+
+ static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; }
+
+ virtual PxConstraintSolverPrep getPrep() const { return sShaders.solverPrep; }
+
+ private:
+
+ static PxConstraintShaderTable sShaders;
+
+ D6JointData& data() const
+ {
+ return *static_cast<D6JointData*>(mData);
+ }
+
+ bool active(const PxD6Drive::Enum index) const
+ {
+ PxD6JointDrive& d = data().drive[index];
+ return d.stiffness!=0 || d.damping != 0;
+ }
+
+ void* prepareData();
+
+ bool mRecomputeMotion;
+ bool mRecomputeLimits;
+ bool mPadding[2]; // PT: padding from prev bools
+ };
+
+} // namespace Ext
+
+namespace Ext
+{
+ extern "C" PxU32 D6JointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 maxConstraints,
+ PxConstraintInvMassScale& invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w);
+
+ // global function to share the joint shaders with API capture
+ extern "C" const PxConstraintShaderTable* GetD6JointShaderTable();
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtD6JointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6JointSolverPrep.cpp
new file mode 100644
index 00000000..498bb0e4
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtD6JointSolverPrep.cpp
@@ -0,0 +1,232 @@
+// 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 "ExtD6Joint.h"
+#include "ExtConstraintHelper.h"
+#include "CmConeLimitHelper.h"
+
+namespace physx
+{
+namespace Ext
+{
+ PxU32 D6JointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 maxConstraints,
+ PxConstraintInvMassScale& invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w)
+ {
+ PX_UNUSED(maxConstraints);
+
+ using namespace joint;
+
+ PX_UNUSED(maxConstraints);
+ const D6JointData& data =
+ *reinterpret_cast<const D6JointData*>(constantBlock);
+
+ invMassScale = data.invMassScale;
+
+ const PxU32 SWING1_FLAG = 1<<PxD6Axis::eSWING1,
+ SWING2_FLAG = 1<<PxD6Axis::eSWING2,
+ TWIST_FLAG = 1<<PxD6Axis::eTWIST;
+
+ const PxU32 ANGULAR_MASK = SWING1_FLAG | SWING2_FLAG | TWIST_FLAG;
+ const PxU32 LINEAR_MASK = 1<<PxD6Axis::eX | 1<<PxD6Axis::eY | 1<<PxD6Axis::eZ;
+
+ const PxD6JointDrive* drives = data.drive;
+ PxU32 locked = data.locked, limited = data.limited, driving = data.driving;
+
+ PxTransform cA2w = bA2w.transform(data.c2b[0]);
+ PxTransform cB2w = bB2w.transform(data.c2b[1]);
+
+ body0WorldOffset = cB2w.p-bA2w.p;
+ ConstraintHelper g(constraints, cB2w.p-bA2w.p, cB2w.p-bB2w.p);
+
+ if(cA2w.q.dot(cB2w.q)<0) // minimum dist quat (equiv to flipping cB2bB.q, which we don't use anywhere)
+ cB2w.q = -cB2w.q;
+
+ PxTransform cB2cA = cA2w.transformInv(cB2w);
+
+ PX_ASSERT(data.c2b[0].isValid());
+ PX_ASSERT(data.c2b[1].isValid());
+ PX_ASSERT(cA2w.isValid());
+ PX_ASSERT(cB2w.isValid());
+ PX_ASSERT(cB2cA.isValid());
+
+ PxMat33 cA2w_m(cA2w.q), cB2w_m(cB2w.q);
+
+ // handy for swing computation
+ PxVec3 bX = cB2w_m[0], aY = cA2w_m[1], aZ = cA2w_m[2];
+
+ if(driving & ((1<<PxD6Drive::eX)|(1<<PxD6Drive::eY)|(1<<PxD6Drive::eZ)))
+ {
+ // TODO: make drive unilateral if we are outside the limit
+ PxVec3 posErr = data.drivePosition.p - cB2cA.p;
+ for(PxU32 i = 0; i < 3; i++)
+ {
+ // -driveVelocity because velTarget is child (body1) - parent (body0) and Jacobian is 1 for body0 and -1 for parent
+ if(driving & (1<<(PxD6Drive::eX+i)))
+ g.linear(cA2w_m[i], -data.driveLinearVelocity[i], posErr[i], drives[PxD6Drive::eX+i]);
+ }
+ }
+
+ if(driving & ((1<<PxD6Drive::eSLERP)|(1<<PxD6Drive::eSWING)|(1<<PxD6Drive::eTWIST)))
+ {
+ PxQuat d2cA_q = cB2cA.q.dot(data.drivePosition.q)>0 ? data.drivePosition.q : -data.drivePosition.q;
+
+ const PxVec3& v = data.driveAngularVelocity;
+ PxQuat delta = d2cA_q.getConjugate() * cB2cA.q;
+
+ if(driving & (1<<PxD6Drive::eSLERP))
+ {
+ PxVec3 velTarget = -cA2w.rotate(data.driveAngularVelocity);
+
+ PxVec3 axis[3] = { PxVec3(1.f,0,0), PxVec3(0,1.f,0), PxVec3(0,0,1.f) };
+
+ if(drives[PxD6Drive::eSLERP].stiffness!=0)
+ computeJacobianAxes(axis, cA2w.q * d2cA_q, cB2w.q); // converges faster if there is only velocity drive
+
+ for(PxU32 i = 0; i < 3; i++)
+ g.angular(axis[i], axis[i].dot(velTarget), -delta.getImaginaryPart()[i], drives[PxD6Drive::eSLERP], PxConstraintSolveHint::eSLERP_SPRING);
+ }
+ else
+ {
+ if(driving & (1<<PxD6Drive::eTWIST))
+ g.angular(bX, v.x, -2.0f * delta.x, drives[PxD6Drive::eTWIST]);
+
+ if(driving & (1<<PxD6Drive::eSWING))
+ {
+ PxVec3 err = delta.rotate(PxVec3(1.f,0,0));
+
+ if(!(locked & SWING1_FLAG))
+ g.angular(cB2w_m[1], v.y, err.z, drives[PxD6Drive::eSWING]);
+
+ if(!(locked & SWING2_FLAG))
+ g.angular(cB2w_m[2], v.z, -err.y, drives[PxD6Drive::eSWING]);
+ }
+ }
+ }
+
+ if (limited & ANGULAR_MASK)
+ {
+ PxQuat swing, twist;
+ Ps::separateSwingTwist(cB2cA.q,swing,twist);
+
+ // swing limits: if just one is limited: if the other is free, we support
+ // (-pi/2, +pi/2) limit, using tan of the half-angle as the error measure parameter.
+ // If the other is locked, we support (-pi, +pi) limits using the tan of the quarter-angle
+ // Notation: th == Ps::tanHalf, tq = tanQuarter
+
+ if(limited & SWING1_FLAG && limited & SWING2_FLAG)
+ {
+ Cm::ConeLimitHelper coneHelper(data.tqSwingZ, data.tqSwingY, data.tqSwingPad);
+
+ PxVec3 axis;
+ PxReal error;
+ if(coneHelper.getLimit(swing, axis, error))
+ g.angularLimit(cA2w.rotate(axis),error,data.swingLimit);
+ }
+ else
+ {
+ const PxJointLimitCone &limit = data.swingLimit;
+
+ PxReal tqPad = data.tqSwingPad, thPad = data.thSwingPad;
+
+ if(limited & SWING1_FLAG)
+ {
+ if(locked & SWING2_FLAG)
+ {
+ g.quarterAnglePair(Ps::tanHalf(swing.y, swing.w), -data.tqSwingY, data.tqSwingY, tqPad, aY, limit);
+ }
+ else
+ {
+ PxReal dot=-aZ.dot(bX);
+ g.halfAnglePair(Ps::tanHalf(dot, 1-dot*dot), -data.thSwingY, data.thSwingY, thPad, aZ.cross(bX), limit);
+ }
+ }
+ if(limited & SWING2_FLAG)
+ {
+ if(locked & SWING1_FLAG)
+ {
+ g.quarterAnglePair(Ps::tanHalf(swing.z, swing.w), -data.tqSwingZ, data.tqSwingZ, tqPad, aZ, limit);
+ }
+ else
+ {
+ PxReal dot=aY.dot(bX);
+ g.halfAnglePair(Ps::tanHalf(dot, 1-dot*dot), -data.thSwingZ, data.thSwingZ, thPad, -aY.cross(bX), limit);
+ }
+ }
+ }
+
+ if(limited & TWIST_FLAG)
+ {
+ g.quarterAnglePair(Ps::tanHalf(twist.x, twist.w), data.tqTwistLow, data.tqTwistHigh, data.tqTwistPad,
+ cB2w_m[0], data.twistLimit);
+ }
+ }
+
+ if(limited & LINEAR_MASK)
+ {
+ PxVec3 limitDir = PxVec3(0);
+
+ for(PxU32 i = 0; i < 3; i++)
+ {
+ if(limited & (1<<(PxD6Axis::eX+i)))
+ limitDir += cA2w_m[i] * cB2cA.p[i];
+ }
+
+ PxReal distance = limitDir.magnitude();
+ if(distance > data.linearMinDist)
+ g.linearLimit(limitDir * (1.0f/distance), distance, data.linearLimit.value, data.linearLimit);
+ }
+
+ // we handle specially the case of just one swing dof locked
+
+ PxU32 angularLocked = locked & ANGULAR_MASK;
+
+ if(angularLocked == SWING1_FLAG)
+ {
+ g.angularHard(bX.cross(aZ), -bX.dot(aZ));
+ locked &= ~SWING1_FLAG;
+ }
+ else if(angularLocked == SWING2_FLAG)
+ {
+ locked &= ~SWING2_FLAG;
+ g.angularHard(bX.cross(aY), -bX.dot(aY));
+ }
+
+ g.prepareLockedAxes(cA2w.q, cB2w.q, cB2cA.p,locked&7, locked>>3);
+
+ return g.getCount();
+ }
+}//namespace
+
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.cpp
new file mode 100644
index 00000000..aef580b3
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.cpp
@@ -0,0 +1,236 @@
+// 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 "task/PxTask.h"
+#include "ExtDefaultCpuDispatcher.h"
+#include "ExtCpuWorkerThread.h"
+#include "ExtTaskQueueHelper.h"
+#include "PsString.h"
+
+using namespace physx;
+
+namespace physx
+{
+ PxDefaultCpuDispatcher* PxDefaultCpuDispatcherCreate(PxU32 numThreads, PxU32* affinityMasks);
+}
+
+PxDefaultCpuDispatcher* physx::PxDefaultCpuDispatcherCreate(PxU32 numThreads, PxU32* affinityMasks)
+{
+ return PX_NEW(Ext::DefaultCpuDispatcher)(numThreads, affinityMasks);
+}
+
+#if !PX_PS4 && !PX_XBOXONE
+void Ext::DefaultCpuDispatcher::getAffinityMasks(PxU32* affinityMasks, PxU32 threadCount)
+{
+ for(PxU32 i=0; i < threadCount; i++)
+ {
+ affinityMasks[i] = 0;
+ }
+}
+#endif
+
+Ext::DefaultCpuDispatcher::DefaultCpuDispatcher(PxU32 numThreads, PxU32* affinityMasks)
+ : mQueueEntryPool(EXT_TASK_QUEUE_ENTRY_POOL_SIZE, "QueueEntryPool"), mNumThreads(numThreads), mShuttingDown(false)
+#if PX_PROFILE
+ ,mRunProfiled(true)
+#else
+ ,mRunProfiled(false)
+#endif
+{
+ PxU32* defaultAffinityMasks = NULL;
+
+ if(!affinityMasks)
+ {
+ defaultAffinityMasks = reinterpret_cast<PxU32*>(PX_ALLOC(numThreads * sizeof(PxU32), "ThreadAffinityMasks"));
+ getAffinityMasks(defaultAffinityMasks, numThreads);
+ affinityMasks = defaultAffinityMasks;
+ }
+
+ // initialize threads first, then start
+
+ mWorkerThreads = reinterpret_cast<CpuWorkerThread*>(PX_ALLOC(numThreads * sizeof(CpuWorkerThread), "CpuWorkerThread"));
+ const PxU32 nameLength = 32;
+ mThreadNames = reinterpret_cast<PxU8*>(PX_ALLOC(nameLength * numThreads, "CpuWorkerThreadName"));
+
+ if (mWorkerThreads)
+ {
+ for(PxU32 i = 0; i < numThreads; ++i)
+ {
+ PX_PLACEMENT_NEW(mWorkerThreads+i, CpuWorkerThread)();
+ mWorkerThreads[i].initialize(this);
+ }
+
+ for(PxU32 i = 0; i < numThreads; ++i)
+ {
+ mWorkerThreads[i].setAffinityMask(affinityMasks[i]);
+ mWorkerThreads[i].start(Ps::Thread::getDefaultStackSize());
+
+ if (mThreadNames)
+ {
+ char* threadName = reinterpret_cast<char*>(mThreadNames + (i*nameLength));
+ Ps::snprintf(threadName, nameLength, "PxWorker%02d", i);
+ mWorkerThreads[i].setName(threadName);
+ }
+ }
+
+ if (defaultAffinityMasks)
+ PX_FREE(defaultAffinityMasks);
+ }
+ else
+ {
+ mNumThreads = 0;
+ }
+}
+
+
+Ext::DefaultCpuDispatcher::~DefaultCpuDispatcher()
+{
+ for(PxU32 i = 0; i < mNumThreads; ++i)
+ mWorkerThreads[i].signalQuit();
+
+ mShuttingDown = true;
+ mWorkReady.set();
+ for(PxU32 i = 0; i < mNumThreads; ++i)
+ mWorkerThreads[i].waitForQuit();
+
+ for(PxU32 i = 0; i < mNumThreads; ++i)
+ mWorkerThreads[i].~CpuWorkerThread();
+
+ PX_FREE(mWorkerThreads);
+
+ if (mThreadNames)
+ PX_FREE(mThreadNames);
+}
+
+
+void Ext::DefaultCpuDispatcher::submitTask(PxBaseTask& task)
+{
+ Ps::Thread::Id currentThread = Ps::Thread::getId();
+ if(!mNumThreads)
+ {
+ // no worker threads, run directly
+ if(mRunProfiled)
+ task.runProfiled(PxU32(currentThread));
+ else
+ task.run();
+ task.release();
+ return;
+ }
+
+ // TODO: Could use TLS to make this more efficient
+ for(PxU32 i = 0; i < mNumThreads; ++i)
+ {
+ if(mWorkerThreads[i].tryAcceptJobToLocalQueue(task, currentThread))
+ return mWorkReady.set();
+ }
+
+ SharedQueueEntry* entry = mQueueEntryPool.getEntry(&task);
+ if (entry)
+ {
+ mJobList.push(*entry);
+ mWorkReady.set();
+ }
+}
+
+PxBaseTask* Ext::DefaultCpuDispatcher::fetchNextTask()
+{
+ PxBaseTask* task = getJob();
+
+ if(!task)
+ task = stealJob();
+
+ return task;
+}
+
+void Ext::DefaultCpuDispatcher::runTask(PxBaseTask& task)
+{
+ if(mRunProfiled)
+ {
+ const PxU32 threadId = PxU32(Ps::Thread::getId());
+ task.runProfiled(threadId);
+ }
+ else
+ task.run();
+}
+
+PxU32 Ext::DefaultCpuDispatcher::getWorkerCount() const
+{
+ return mNumThreads;
+}
+
+void Ext::DefaultCpuDispatcher::release()
+{
+ PX_DELETE(this);
+}
+
+
+PxBaseTask* Ext::DefaultCpuDispatcher::getJob(void)
+{
+ return TaskQueueHelper::fetchTask(mJobList, mQueueEntryPool);
+}
+
+
+PxBaseTask* Ext::DefaultCpuDispatcher::stealJob()
+{
+ PxBaseTask* ret = NULL;
+
+ for(PxU32 i = 0; i < mNumThreads; ++i)
+ {
+ ret = mWorkerThreads[i].giveUpJob();
+
+ if(ret != NULL)
+ break;
+ }
+
+ return ret;
+}
+
+
+void Ext::DefaultCpuDispatcher::resetWakeSignal()
+{
+ mWorkReady.reset();
+
+ // The code below is necessary to avoid deadlocks on shut down.
+ // A thread usually loops as follows:
+ // while quit is not signaled
+ // 1) reset wake signal
+ // 2) fetch work
+ // 3) if work -> process
+ // 4) else -> wait for wake signal
+ //
+ // If a thread reaches 1) after the thread pool signaled wake up,
+ // the wake up sync gets reset and all other threads which have not
+ // passed 4) already will wait forever.
+ // The code below makes sure that on shutdown, the wake up signal gets
+ // sent again after it was reset
+ //
+ if (mShuttingDown)
+ mWorkReady.set();
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.h
new file mode 100644
index 00000000..ca9595c5
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultCpuDispatcher.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_EXTENSIONS_NP_DEFAULT_CPU_DISPATCHER_H
+#define PX_PHYSICS_EXTENSIONS_NP_DEFAULT_CPU_DISPATCHER_H
+
+#include "CmPhysXCommon.h"
+#include "PsUserAllocated.h"
+#include "PsSync.h"
+#include "PsSList.h"
+#include "PxDefaultCpuDispatcher.h"
+#include "ExtSharedQueueEntryPool.h"
+
+namespace physx
+{
+
+namespace Ext
+{
+ class CpuWorkerThread;
+
+#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 // Because of the SList member I assume
+
+ class DefaultCpuDispatcher : public PxDefaultCpuDispatcher, public Ps::UserAllocated
+ {
+ friend class TaskQueueHelper;
+
+ private:
+ DefaultCpuDispatcher() : mQueueEntryPool(0) {}
+ ~DefaultCpuDispatcher();
+
+ public:
+ DefaultCpuDispatcher(PxU32 numThreads, PxU32* affinityMasks);
+
+ //---------------------------------------------------------------------------------
+ // physx::CpuDispatcher implementation
+ //---------------------------------------------------------------------------------
+ virtual void submitTask(PxBaseTask& task);
+ virtual PxU32 getWorkerCount() const;
+
+ //---------------------------------------------------------------------------------
+ // PxDefaultCpuDispatcher implementation
+ //---------------------------------------------------------------------------------
+ virtual void release();
+
+ virtual void setRunProfiled(bool runProfiled) { mRunProfiled = runProfiled; }
+
+ virtual bool getRunProfiled() const { return mRunProfiled; }
+
+ //---------------------------------------------------------------------------------
+ // DefaultCpuDispatcher
+ //---------------------------------------------------------------------------------
+ PxBaseTask* getJob();
+ PxBaseTask* stealJob();
+ PxBaseTask* fetchNextTask();
+ void runTask(PxBaseTask& task);
+
+ void waitForWork() { mWorkReady.wait(); }
+ void resetWakeSignal();
+
+ static void getAffinityMasks(PxU32* affinityMasks, PxU32 threadCount);
+
+
+ protected:
+ CpuWorkerThread* mWorkerThreads;
+ SharedQueueEntryPool<> mQueueEntryPool;
+ Ps::SList mJobList;
+ Ps::Sync mWorkReady;
+ PxU8* mThreadNames;
+ PxU32 mNumThreads;
+ bool mShuttingDown;
+ bool mRunProfiled;
+ };
+
+#if PX_VC
+#pragma warning(pop)
+#endif
+
+} // namespace Ext
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultErrorCallback.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultErrorCallback.cpp
new file mode 100644
index 00000000..68ca7747
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultErrorCallback.cpp
@@ -0,0 +1,104 @@
+// 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/PxAssert.h"
+#include "PxDefaultErrorCallback.h"
+#include "PsString.h"
+#include "PsThread.h"
+#include <stdio.h>
+
+using namespace physx;
+
+
+PxDefaultErrorCallback::PxDefaultErrorCallback()
+{
+}
+
+PxDefaultErrorCallback::~PxDefaultErrorCallback()
+{
+}
+
+void PxDefaultErrorCallback::reportError(PxErrorCode::Enum e, const char* message, const char* file, int line)
+{
+ const char* errorCode = NULL;
+
+ switch (e)
+ {
+ case PxErrorCode::eNO_ERROR:
+ errorCode = "no error";
+ break;
+ case PxErrorCode::eINVALID_PARAMETER:
+ errorCode = "invalid parameter";
+ break;
+ case PxErrorCode::eINVALID_OPERATION:
+ errorCode = "invalid operation";
+ break;
+ case PxErrorCode::eOUT_OF_MEMORY:
+ errorCode = "out of memory";
+ break;
+ case PxErrorCode::eDEBUG_INFO:
+ errorCode = "info";
+ break;
+ case PxErrorCode::eDEBUG_WARNING:
+ errorCode = "warning";
+ break;
+ case PxErrorCode::ePERF_WARNING:
+ errorCode = "performance warning";
+ break;
+ case PxErrorCode::eABORT:
+ errorCode = "abort";
+ break;
+ case PxErrorCode::eINTERNAL_ERROR:
+ errorCode = "internal error";
+ break;
+ case PxErrorCode::eMASK_ALL:
+ errorCode = "unknown error";
+ break;
+ }
+
+ PX_ASSERT(errorCode);
+ if(errorCode)
+ {
+ char buffer[1024];
+ sprintf(buffer, "%s (%d) : %s : %s\n", file, line, errorCode, message);
+
+ physx::shdfnd::printString(buffer);
+
+ // in debug builds halt execution for abort codes
+ PX_ASSERT(e != PxErrorCode::eABORT);
+
+ // in release builds we also want to halt execution
+ // and make sure that the error message is flushed
+ while (e == PxErrorCode::eABORT)
+ {
+ physx::shdfnd::printString(buffer);
+ physx::shdfnd::Thread::sleep(1000);
+ }
+ }
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultSimulationFilterShader.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultSimulationFilterShader.cpp
new file mode 100644
index 00000000..317b9696
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultSimulationFilterShader.cpp
@@ -0,0 +1,386 @@
+// 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 "PxDefaultSimulationFilterShader.h"
+#include "PsIntrinsics.h"
+#include "particles/PxParticleBase.h"
+#include "cloth/PxCloth.h"
+#include "PxRigidActor.h"
+#include "PxShape.h"
+#include "PsAllocator.h"
+#include "CmPhysXCommon.h"
+#include "PsInlineArray.h"
+#include "PsFoundation.h"
+
+using namespace physx;
+
+namespace
+{
+ #define GROUP_SIZE 32
+
+ struct PxCollisionBitMap
+ {
+ PX_INLINE PxCollisionBitMap() : enable(true) {}
+
+ bool operator()() const { return enable; }
+ bool& operator= (const bool &v) { enable = v; return enable; }
+
+ private:
+ bool enable;
+ };
+
+ PxCollisionBitMap gCollisionTable[GROUP_SIZE][GROUP_SIZE];
+
+ PxFilterOp::Enum gFilterOps[3] = { PxFilterOp::PX_FILTEROP_AND, PxFilterOp::PX_FILTEROP_AND, PxFilterOp::PX_FILTEROP_AND };
+
+ PxGroupsMask gFilterConstants[2];
+
+ bool gFilterBool = false;
+
+ static void gAND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
+ {
+ results.bits0 = PxU16(mask0.bits0 & mask1.bits0);
+ results.bits1 = PxU16(mask0.bits1 & mask1.bits1);
+ results.bits2 = PxU16(mask0.bits2 & mask1.bits2);
+ results.bits3 = PxU16(mask0.bits3 & mask1.bits3);
+ }
+ static void gOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
+ {
+ results.bits0 = PxU16(mask0.bits0 | mask1.bits0);
+ results.bits1 = PxU16(mask0.bits1 | mask1.bits1);
+ results.bits2 = PxU16(mask0.bits2 | mask1.bits2);
+ results.bits3 = PxU16(mask0.bits3 | mask1.bits3);
+ }
+ static void gXOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
+ {
+ results.bits0 = PxU16(mask0.bits0 ^ mask1.bits0);
+ results.bits1 = PxU16(mask0.bits1 ^ mask1.bits1);
+ results.bits2 = PxU16(mask0.bits2 ^ mask1.bits2);
+ results.bits3 = PxU16(mask0.bits3 ^ mask1.bits3);
+ }
+ static void gNAND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
+ {
+ results.bits0 = PxU16(~(mask0.bits0 & mask1.bits0));
+ results.bits1 = PxU16(~(mask0.bits1 & mask1.bits1));
+ results.bits2 = PxU16(~(mask0.bits2 & mask1.bits2));
+ results.bits3 = PxU16(~(mask0.bits3 & mask1.bits3));
+ }
+ static void gNOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
+ {
+ results.bits0 = PxU16(~(mask0.bits0 | mask1.bits0));
+ results.bits1 = PxU16(~(mask0.bits1 | mask1.bits1));
+ results.bits2 = PxU16(~(mask0.bits2 | mask1.bits2));
+ results.bits3 = PxU16(~(mask0.bits3 | mask1.bits3));
+ }
+ static void gNXOR(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
+ {
+ results.bits0 = PxU16(~(mask0.bits0 ^ mask1.bits0));
+ results.bits1 = PxU16(~(mask0.bits1 ^ mask1.bits1));
+ results.bits2 = PxU16(~(mask0.bits2 ^ mask1.bits2));
+ results.bits3 = PxU16(~(mask0.bits3 ^ mask1.bits3));
+ }
+
+ static void gSWAP_AND(PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1)
+ {
+ results.bits0 = PxU16(mask0.bits0 & mask1.bits2);
+ results.bits1 = PxU16(mask0.bits1 & mask1.bits3);
+ results.bits2 = PxU16(mask0.bits2 & mask1.bits0);
+ results.bits3 = PxU16(mask0.bits3 & mask1.bits1);
+ }
+
+ typedef void (*FilterFunction) (PxGroupsMask& results, const PxGroupsMask& mask0, const PxGroupsMask& mask1);
+
+ FilterFunction const gTable[] = { gAND, gOR, gXOR, gNAND, gNOR, gNXOR, gSWAP_AND };
+
+ static PxFilterData convert(const PxGroupsMask& mask)
+ {
+ PxFilterData fd;
+
+ fd.word2 = PxU32(mask.bits0 | (mask.bits1 << 16));
+ fd.word3 = PxU32(mask.bits2 | (mask.bits3 << 16));
+
+ return fd;
+ }
+
+ static PxGroupsMask convert(const PxFilterData& fd)
+ {
+ PxGroupsMask mask;
+
+ mask.bits0 = PxU16((fd.word2 & 0xffff));
+ mask.bits1 = PxU16((fd.word2 >> 16));
+ mask.bits2 = PxU16((fd.word3 & 0xffff));
+ mask.bits3 = PxU16((fd.word3 >> 16));
+
+ return mask;
+ }
+
+ static bool getFilterData(const PxActor& actor, PxFilterData& fd)
+ {
+ PxActorType::Enum aType = actor.getType();
+ switch (aType)
+ {
+ case PxActorType::eRIGID_DYNAMIC:
+ case PxActorType::eRIGID_STATIC:
+ case PxActorType::eARTICULATION_LINK:
+ {
+ const PxRigidActor& rActor = static_cast<const PxRigidActor&>(actor);
+ PX_CHECK_AND_RETURN_VAL(rActor.getNbShapes() >= 1,"There must be a shape in actor", false);
+
+ PxShape* shape = NULL;
+ rActor.getShapes(&shape, 1);
+
+ fd = shape->getSimulationFilterData();
+ }
+ break;
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ case PxActorType::ePARTICLE_FLUID:
+ case PxActorType::ePARTICLE_SYSTEM:
+ {
+ const PxParticleBase& pActor = static_cast<const PxParticleBase&>(actor);
+ fd = pActor.getSimulationFilterData();
+ }
+ break;
+#endif
+
+#if PX_USE_CLOTH_API
+ case PxActorType::eCLOTH:
+ {
+ const PxCloth& cActor = static_cast<const PxCloth&>(actor);
+ fd = cActor.getSimulationFilterData();
+ }
+ break;
+#endif
+ case PxActorType::eACTOR_COUNT:
+ case PxActorType::eACTOR_FORCE_DWORD:
+ break;
+ }
+
+ return true;
+ }
+
+ PX_FORCE_INLINE static void adjustFilterData(bool groupsMask, const PxFilterData& src, PxFilterData& dst)
+ {
+ if (groupsMask)
+ {
+ dst.word2 = src.word2;
+ dst.word3 = src.word3;
+ }
+ else
+ dst.word0 = src.word0;
+ }
+
+ template<bool TGroupsMask>
+ static void setFilterData(PxActor& actor, const PxFilterData& fd)
+ {
+ PxActorType::Enum aType = actor.getType();
+ switch (aType)
+ {
+ case PxActorType::eRIGID_DYNAMIC:
+ case PxActorType::eRIGID_STATIC:
+ case PxActorType::eARTICULATION_LINK:
+ {
+ const PxRigidActor& rActor = static_cast<const PxRigidActor&>(actor);
+
+ PxShape* shape;
+ for(PxU32 i=0; i < rActor.getNbShapes(); i++)
+ {
+ rActor.getShapes(&shape, 1, i);
+
+ // retrieve current group mask
+ PxFilterData resultFd = shape->getSimulationFilterData();
+
+ adjustFilterData(TGroupsMask, fd, resultFd);
+
+ // set new filter data
+ shape->setSimulationFilterData(resultFd);
+ }
+ }
+ break;
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ case PxActorType::ePARTICLE_FLUID:
+ case PxActorType::ePARTICLE_SYSTEM:
+ {
+ PxParticleBase& pActor = static_cast<PxParticleBase&>(actor);
+
+ PxFilterData resultFd = pActor.getSimulationFilterData();
+
+ adjustFilterData(TGroupsMask, fd, resultFd);
+
+ pActor.setSimulationFilterData(resultFd);
+ }
+ break;
+#endif
+
+#if PX_USE_CLOTH_API
+ case PxActorType::eCLOTH:
+ {
+ PxCloth& cActor = static_cast<PxCloth&>(actor);
+
+ PxFilterData resultFd = cActor.getSimulationFilterData();
+
+ adjustFilterData(TGroupsMask, fd, resultFd);
+
+ cActor.setSimulationFilterData(resultFd);
+ }
+ break;
+#endif
+
+ case PxActorType::eACTOR_COUNT:
+ case PxActorType::eACTOR_FORCE_DWORD:
+ break;
+ }
+ }
+}
+
+PxFilterFlags physx::PxDefaultSimulationFilterShader(
+ PxFilterObjectAttributes attributes0,
+ PxFilterData filterData0,
+ PxFilterObjectAttributes attributes1,
+ PxFilterData filterData1,
+ PxPairFlags& pairFlags,
+ const void* constantBlock,
+ PxU32 constantBlockSize)
+{
+ PX_UNUSED(constantBlock);
+ PX_UNUSED(constantBlockSize);
+
+ // let triggers through
+ if(PxFilterObjectIsTrigger(attributes0) || PxFilterObjectIsTrigger(attributes1))
+ {
+ pairFlags = PxPairFlag::eTRIGGER_DEFAULT;
+ return PxFilterFlags();
+ }
+
+ // Collision Group
+ if (!gCollisionTable[filterData0.word0][filterData1.word0]())
+ {
+ return PxFilterFlag::eSUPPRESS;
+ }
+
+ // Filter function
+ PxGroupsMask g0 = convert(filterData0);
+ PxGroupsMask g1 = convert(filterData1);
+
+ PxGroupsMask g0k0; gTable[gFilterOps[0]](g0k0, g0, gFilterConstants[0]);
+ PxGroupsMask g1k1; gTable[gFilterOps[1]](g1k1, g1, gFilterConstants[1]);
+ PxGroupsMask final; gTable[gFilterOps[2]](final, g0k0, g1k1);
+
+ bool r = final.bits0 || final.bits1 || final.bits2 || final.bits3;
+ if (r != gFilterBool)
+ {
+ return PxFilterFlag::eSUPPRESS;
+ }
+
+ pairFlags = PxPairFlag::eCONTACT_DEFAULT;
+
+ return PxFilterFlags();
+}
+
+bool physx::PxGetGroupCollisionFlag(const PxU16 group1, const PxU16 group2)
+{
+ PX_CHECK_AND_RETURN_NULL(group1 < 32 && group2 < 32, "Group must be less than 32");
+
+ return gCollisionTable[group1][group2]();
+}
+
+void physx::PxSetGroupCollisionFlag(const PxU16 group1, const PxU16 group2, const bool enable)
+{
+ PX_CHECK_AND_RETURN(group1 < 32 && group2 < 32, "Group must be less than 32");
+
+ gCollisionTable[group1][group2] = enable;
+ gCollisionTable[group2][group1] = enable;
+}
+
+PxU16 physx::PxGetGroup(const PxActor& actor)
+{
+ PxFilterData fd;
+ getFilterData(actor, fd);
+ return PxU16(fd.word0);
+}
+
+void physx::PxSetGroup(PxActor& actor, const PxU16 collisionGroup)
+{
+ PX_CHECK_AND_RETURN(collisionGroup < 32,"Collision group must be less than 32");
+ PxFilterData fd(collisionGroup, 0, 0, 0);
+ setFilterData<false>(actor, fd);
+}
+
+void physx::PxGetFilterOps(PxFilterOp::Enum& op0, PxFilterOp::Enum& op1, PxFilterOp::Enum& op2)
+{
+ op0 = gFilterOps[0];
+ op1 = gFilterOps[1];
+ op2 = gFilterOps[2];
+}
+
+void physx::PxSetFilterOps(const PxFilterOp::Enum& op0, const PxFilterOp::Enum& op1, const PxFilterOp::Enum& op2)
+{
+ gFilterOps[0] = op0;
+ gFilterOps[1] = op1;
+ gFilterOps[2] = op2;
+}
+
+bool physx::PxGetFilterBool()
+{
+ return gFilterBool;
+}
+
+void physx::PxSetFilterBool(const bool enable)
+{
+ gFilterBool = enable;
+}
+
+void physx::PxGetFilterConstants(PxGroupsMask& c0, PxGroupsMask& c1)
+{
+ c0 = gFilterConstants[0];
+ c1 = gFilterConstants[1];
+}
+
+void physx::PxSetFilterConstants(const PxGroupsMask& c0, const PxGroupsMask& c1)
+{
+ gFilterConstants[0] = c0;
+ gFilterConstants[1] = c1;
+}
+
+PxGroupsMask physx::PxGetGroupsMask(const PxActor& actor)
+{
+ PxFilterData fd;
+ if (getFilterData(actor, fd))
+ return convert(fd);
+ else
+ return PxGroupsMask();
+}
+
+void physx::PxSetGroupsMask(PxActor& actor, const PxGroupsMask& mask)
+{
+ PxFilterData fd = convert(mask);
+ setFilterData<true>(actor, fd);
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultStreams.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultStreams.cpp
new file mode 100644
index 00000000..49b55f56
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDefaultStreams.cpp
@@ -0,0 +1,193 @@
+// 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/PxPreprocessor.h"
+#include "foundation/PxAssert.h"
+#include "foundation/PxAllocatorCallback.h"
+
+#include <errno.h>
+#include "PsFoundation.h"
+#include "PxDefaultStreams.h"
+#include "SnFile.h"
+#include "CmPhysXCommon.h"
+#include "PsUtilities.h"
+#include "PsBitUtils.h"
+
+using namespace physx;
+
+PxDefaultMemoryOutputStream::PxDefaultMemoryOutputStream(PxAllocatorCallback &allocator)
+: mAllocator (allocator)
+, mData (NULL)
+, mSize (0)
+, mCapacity (0)
+{
+}
+
+PxDefaultMemoryOutputStream::~PxDefaultMemoryOutputStream()
+{
+ if(mData)
+ mAllocator.deallocate(mData);
+}
+
+PxU32 PxDefaultMemoryOutputStream::write(const void* src, PxU32 size)
+{
+ PxU32 expectedSize = mSize + size;
+ if(expectedSize > mCapacity)
+ {
+ mCapacity = PxMax(Ps::nextPowerOfTwo(expectedSize), 4096u);
+
+ PxU8* newData = reinterpret_cast<PxU8*>(mAllocator.allocate(mCapacity,"PxDefaultMemoryOutputStream",__FILE__,__LINE__));
+ PX_ASSERT(newData!=NULL);
+
+ memcpy(newData, mData, mSize);
+ if(mData)
+ mAllocator.deallocate(mData);
+
+ mData = newData;
+ }
+ memcpy(mData+mSize, src, size);
+ mSize += size;
+ return size;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxDefaultMemoryInputData::PxDefaultMemoryInputData(PxU8* data, PxU32 length) :
+ mSize (length),
+ mData (data),
+ mPos (0)
+{
+}
+
+PxU32 PxDefaultMemoryInputData::read(void* dest, PxU32 count)
+{
+ PxU32 length = PxMin<PxU32>(count, mSize-mPos);
+ memcpy(dest, mData+mPos, length);
+ mPos += length;
+ return length;
+}
+
+PxU32 PxDefaultMemoryInputData::getLength() const
+{
+ return mSize;
+}
+
+void PxDefaultMemoryInputData::seek(PxU32 offset)
+{
+ mPos = PxMin<PxU32>(mSize, offset);
+}
+
+PxU32 PxDefaultMemoryInputData::tell() const
+{
+ return mPos;
+}
+
+PxDefaultFileOutputStream::PxDefaultFileOutputStream(const char* filename)
+{
+ mFile = NULL;
+ sn::fopen_s(&mFile, filename, "wb");
+ // PT: when this fails, check that:
+ // - the path is correct
+ // - the file does not already exist. If it does, check that it is not write protected.
+ if(NULL == mFile)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "Unable to open file %s, errno 0x%x\n",filename,errno);
+ }
+ PX_ASSERT(mFile);
+}
+
+PxDefaultFileOutputStream::~PxDefaultFileOutputStream()
+{
+ if(mFile)
+ fclose(mFile);
+}
+
+PxU32 PxDefaultFileOutputStream::write(const void* src, PxU32 count)
+{
+ return mFile ? PxU32(fwrite(src, 1, count, mFile)) : 0;
+}
+
+bool PxDefaultFileOutputStream::isValid()
+{
+ return mFile != NULL;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+PxDefaultFileInputData::PxDefaultFileInputData(const char* filename)
+{
+ mFile = NULL;
+ sn::fopen_s(&mFile, filename, "rb");
+
+ if(mFile)
+ {
+ fseek(mFile, 0, SEEK_END);
+ mLength = PxU32(ftell(mFile));
+ fseek(mFile, 0, SEEK_SET);
+ }
+ else
+ {
+ mLength = 0;
+ }
+}
+
+PxDefaultFileInputData::~PxDefaultFileInputData()
+{
+ if(mFile)
+ fclose(mFile);
+}
+
+PxU32 PxDefaultFileInputData::read(void* dest, PxU32 count)
+{
+ PX_ASSERT(mFile);
+ const size_t size = fread(dest, 1, count, mFile);
+ // there should be no assert here since by spec of PxInputStream we can read fewer bytes than expected
+ return PxU32(size);
+}
+
+PxU32 PxDefaultFileInputData::getLength() const
+{
+ return mLength;
+}
+
+void PxDefaultFileInputData::seek(PxU32 pos)
+{
+ fseek(mFile, long(pos), SEEK_SET);
+}
+
+PxU32 PxDefaultFileInputData::tell() const
+{
+ return PxU32(ftell(mFile));
+}
+
+bool PxDefaultFileInputData::isValid() const
+{
+ return mFile != NULL;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.cpp
new file mode 100644
index 00000000..6e6e69bd
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.cpp
@@ -0,0 +1,215 @@
+// 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 "ExtDistanceJoint.h"
+#include "common/PxSerialFramework.h"
+
+using namespace physx;
+using namespace Ext;
+
+namespace physx
+{
+ PxDistanceJoint* PxDistanceJointCreate(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1);
+}
+
+PxDistanceJoint* physx::PxDistanceJointCreate(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+{
+ PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxDistanceJointCreate: local frame 0 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxDistanceJointCreate: local frame 1 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxDistanceJointCreate: actors must be different");
+ PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxD6JointCreate: at least one actor must be dynamic");
+
+ DistanceJoint* j;
+ PX_NEW_SERIALIZED(j,DistanceJoint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1);
+ if(j->attach(physics, actor0, actor1))
+ return j;
+
+ PX_DELETE(j);
+ return NULL;
+}
+
+PxReal DistanceJoint::getDistance() const
+{
+ return getRelativeTransform().p.magnitudeSquared();
+}
+
+void DistanceJoint::setMinDistance(PxReal distance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(distance), "PxDistanceJoint::setMinDistance: invalid parameter");
+ data().minDistance = distance;
+ markDirty();
+}
+
+PxReal DistanceJoint::getMinDistance() const
+{
+ return data().minDistance;
+}
+
+void DistanceJoint::setMaxDistance(PxReal distance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(distance), "PxDistanceJoint::setMaxDistance: invalid parameter");
+ data().maxDistance = distance;
+ markDirty();
+}
+
+PxReal DistanceJoint::getMaxDistance() const
+{
+ return data().maxDistance;
+}
+
+void DistanceJoint::setTolerance(PxReal tolerance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(tolerance), "PxDistanceJoint::setTolerance: invalid parameter");
+ data().tolerance = tolerance;
+ markDirty();
+}
+
+PxReal DistanceJoint::getTolerance() const
+{
+ return data().tolerance;
+}
+
+void DistanceJoint::setStiffness(PxReal stiffness)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(stiffness), "PxDistanceJoint::setStiffness: invalid parameter");
+ data().stiffness = stiffness;
+ markDirty();
+}
+
+PxReal DistanceJoint::getStiffness() const
+{
+ return data().stiffness;
+}
+
+void DistanceJoint::setDamping(PxReal damping)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(damping), "PxDistanceJoint::setDamping: invalid parameter");
+ data().damping = damping;
+ markDirty();
+}
+
+PxReal DistanceJoint::getDamping() const
+{
+ return data().damping;
+}
+
+PxDistanceJointFlags DistanceJoint::getDistanceJointFlags(void) const
+{
+ return data().jointFlags;
+}
+
+void DistanceJoint::setDistanceJointFlags(PxDistanceJointFlags flags)
+{
+ data().jointFlags = flags;
+ markDirty();
+}
+
+void DistanceJoint::setDistanceJointFlag(PxDistanceJointFlag::Enum flag, bool value)
+{
+ if(value)
+ data().jointFlags |= flag;
+ else
+ data().jointFlags &= ~flag;
+ markDirty();
+}
+
+
+
+namespace
+{
+void DistanceJointVisualize(PxConstraintVisualizer& /*viz*/,
+ const void* /*constantBlock*/,
+ const PxTransform& /*body0Transform*/,
+ const PxTransform& /*body1Transform*/,
+ PxU32 /*flags*/)
+{
+}
+
+void DistanceJointProject(const void* /*constantBlock*/,
+ PxTransform& /*bodyAToWorld*/,
+ PxTransform& /*bodyBToWorld*/,
+ bool /*projectToA*/)
+{
+ // TODO
+}
+
+
+}
+
+bool Ext::DistanceJoint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1)
+{
+ mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(DistanceJointData));
+ return mPxConstraint!=NULL;
+}
+
+void DistanceJoint::exportExtraData(PxSerializationContext& stream)
+{
+ if(mData)
+ {
+ stream.alignData(PX_SERIAL_ALIGN);
+ stream.writeData(mData, sizeof(DistanceJointData));
+ }
+ stream.writeName(mName);
+}
+
+void DistanceJoint::importExtraData(PxDeserializationContext& context)
+{
+ if(mData)
+ mData = context.readExtraData<DistanceJointData, PX_SERIAL_ALIGN>();
+
+ context.readName(mName);
+}
+
+void DistanceJoint::resolveReferences(PxDeserializationContext& context)
+{
+ setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders));
+}
+
+DistanceJoint* DistanceJoint::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ DistanceJoint* obj = new (address) DistanceJoint(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(DistanceJoint);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+
+// global function to share the joint shaders with API capture
+const PxConstraintShaderTable* Ext::GetDistanceJointShaderTable()
+{
+ return &DistanceJoint::getConstraintShaderTable();
+}
+
+//~PX_SERIALIZATION
+PxConstraintShaderTable Ext::DistanceJoint::sShaders = { Ext::DistanceJointSolverPrep, DistanceJointProject, DistanceJointVisualize, PxConstraintFlag::Enum(0) };
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.h
new file mode 100644
index 00000000..593b2ee2
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJoint.h
@@ -0,0 +1,162 @@
+// 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_DISTANCEJOINTCONSTRAINT_H
+#define NP_DISTANCEJOINTCONSTRAINT_H
+
+#include "PsUserAllocated.h"
+#include "ExtJoint.h"
+#include "PxDistanceJoint.h"
+#include "PxTolerancesScale.h"
+#include "CmUtils.h"
+
+namespace physx
+{
+struct PxDistanceJointGeneratedValues;
+namespace Ext
+{
+
+ struct DistanceJointData : public JointData
+ {
+ //= 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.
+ //==================================================================================================
+
+ PxReal minDistance;
+ PxReal maxDistance;
+ PxReal tolerance;
+ PxReal stiffness;
+ PxReal damping;
+
+ PxDistanceJointFlags jointFlags;
+ };
+
+ typedef Joint<PxDistanceJoint, PxDistanceJointGeneratedValues> DistanceJointT;
+ class DistanceJoint : public DistanceJointT
+ {
+ //= 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
+ DistanceJoint(PxBaseFlags baseFlags) : DistanceJointT(baseFlags) {}
+ virtual void exportExtraData(PxSerializationContext& context);
+ void importExtraData(PxDeserializationContext& context);
+ void resolveReferences(PxDeserializationContext& context);
+ static DistanceJoint* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+ //~PX_SERIALIZATION
+ virtual ~DistanceJoint()
+ {
+ if (getBaseFlags()&PxBaseFlag::eOWNS_MEMORY)
+ PX_FREE(mData);
+ }
+
+ DistanceJoint(const PxTolerancesScale& scale,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ : DistanceJointT(PxJointConcreteType::eDISTANCE, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+ {
+ DistanceJointData* data = reinterpret_cast<DistanceJointData*>(PX_ALLOC(sizeof(DistanceJointData), "DistanceJointData"));
+ Cm::markSerializedMem(data, sizeof(DistanceJointData));
+ mData = data;
+
+ initCommonData(*data, actor0, localFrame0, actor1, localFrame1);
+
+ data->stiffness = 0;
+ data->damping = 0;
+ data->minDistance = 0;
+ data->maxDistance = 0;
+ data->tolerance = 0.025f * scale.length;
+ data->jointFlags = PxDistanceJointFlag::eMAX_DISTANCE_ENABLED;
+ }
+
+ PxReal getDistance() const;
+
+ void setMinDistance(PxReal distance);
+ PxReal getMinDistance() const;
+
+ void setMaxDistance(PxReal distance);
+ PxReal getMaxDistance() const;
+
+ void setTolerance(PxReal tolerance);
+ PxReal getTolerance() const;
+
+ void setStiffness(PxReal spring);
+ PxReal getStiffness() const;
+
+ void setDamping(PxReal damping);
+ PxReal getDamping() const;
+
+ PxDistanceJointFlags getDistanceJointFlags(void) const;
+ void setDistanceJointFlags(PxDistanceJointFlags flags);
+ void setDistanceJointFlag(PxDistanceJointFlag::Enum flag, bool value);
+
+ bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1);
+
+ static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; }
+
+ virtual PxConstraintSolverPrep getPrep()const {return sShaders.solverPrep;}
+
+ private:
+
+ static PxConstraintShaderTable sShaders;
+
+ PX_FORCE_INLINE DistanceJointData& data() const
+ {
+ return *static_cast<DistanceJointData*>(mData);
+ }
+ };
+
+} // namespace Ext
+
+namespace Ext
+{
+ extern "C" PxU32 DistanceJointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 maxConstraints,
+ PxConstraintInvMassScale& invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w);
+
+ // global function to share the joint shaders with API capture
+ extern "C" const PxConstraintShaderTable* GetDistanceJointShaderTable();
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJointSolverPrep.cpp
new file mode 100644
index 00000000..c0b8797d
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtDistanceJointSolverPrep.cpp
@@ -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.
+
+
+#include "foundation/PxSimpleTypes.h"
+#include "ExtDistanceJoint.h"
+
+namespace physx
+{
+namespace Ext
+{
+ PxU32 DistanceJointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 maxConstraints,
+ PxConstraintInvMassScale &invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w)
+ {
+ PX_UNUSED(maxConstraints);
+
+ const DistanceJointData& data = *reinterpret_cast<const DistanceJointData*>(constantBlock);
+ invMassScale = data.invMassScale;
+
+ PxTransform cA2w = bA2w.transform(data.c2b[0]);
+ PxTransform cB2w = bB2w.transform(data.c2b[1]);
+
+ body0WorldOffset = cB2w.p - bA2w.p;
+
+ PxVec3 direction = cA2w.p - cB2w.p;
+ PxReal distance = direction.normalize();
+
+ bool enforceMax = (data.jointFlags & PxDistanceJointFlag::eMAX_DISTANCE_ENABLED);
+ bool enforceMin = (data.jointFlags & PxDistanceJointFlag::eMIN_DISTANCE_ENABLED);
+
+ if((!enforceMax || distance<=data.maxDistance) && (!enforceMin || distance>=data.minDistance))
+ return 0;
+
+#define EPS_REAL 1.192092896e-07F
+
+ if (distance < EPS_REAL)
+ direction = PxVec3(1.f,0,0);
+
+ Px1DConstraint *c = constraints;
+
+ // constraint is breakable, so we need to output forces
+
+ c->flags = Px1DConstraintFlag::eOUTPUT_FORCE;
+
+ c->linear0 = direction; c->angular0 = (cA2w.p - bA2w.p).cross(c->linear0);
+ c->linear1 = direction; c->angular1 = (cB2w.p - bB2w.p).cross(c->linear1);
+
+ if (data.jointFlags & PxDistanceJointFlag::eSPRING_ENABLED)
+ {
+ c->flags |= Px1DConstraintFlag::eSPRING;
+ c->mods.spring.stiffness= data.stiffness;
+ c->mods.spring.damping = data.damping;
+ }
+
+ //add tolerance so we don't have contact-style jitter problem.
+
+ if (data.minDistance == data.maxDistance && enforceMin && enforceMax)
+ {
+ PxReal error = distance - data.maxDistance;
+ c->geometricError = error > data.tolerance ? error - data.tolerance :
+ error < -data.tolerance ? error + data.tolerance : 0;
+ }
+ else if (enforceMax && distance > data.maxDistance)
+ {
+ c->geometricError = distance - data.maxDistance - data.tolerance;
+ c->maxImpulse = 0;
+ }
+ else if (enforceMin && distance < data.minDistance)
+ {
+ c->geometricError = distance - data.minDistance + data.tolerance;
+ c->minImpulse = 0;
+ }
+
+ return 1;
+ }
+}//namespace
+
+}
+
+//~PX_SERIALIZATION
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtExtensions.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtExtensions.cpp
new file mode 100644
index 00000000..4b1e95ac
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtExtensions.cpp
@@ -0,0 +1,212 @@
+// 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 "PxExtensionsAPI.h"
+#include "PsFoundation.h"
+#include "PxMetaData.h"
+#include "ExtDistanceJoint.h"
+#include "ExtD6Joint.h"
+#include "ExtFixedJoint.h"
+#include "ExtPrismaticJoint.h"
+#include "ExtRevoluteJoint.h"
+#include "ExtSphericalJoint.h"
+#include "PxRepXSerializer.h"
+#include "SnRepXCoreSerializer.h"
+#include "SnRepXSerializerImpl.h"
+#include "PxExtensionMetaDataObjects.h"
+#include "PxJointRepXSerializer.h"
+#include "PxSerializer.h"
+#include "ExtSerialization.h"
+
+#if PX_SUPPORT_PVD
+#include "ExtPvd.h"
+#include "PxPvdDataStream.h"
+#include "PxPvdClient.h"
+#include "PsPvd.h"
+#endif
+
+using namespace physx;
+using namespace physx::pvdsdk;
+
+#if PX_SUPPORT_PVD
+struct JointConnectionHandler : public PvdClient
+{
+ JointConnectionHandler() : mPvd(NULL),mConnected(false){}
+
+ PvdDataStream* getDataStream()
+ {
+ return NULL;
+ }
+ PvdUserRenderer* getUserRender()
+ {
+ return NULL;
+ }
+
+ void onPvdConnected()
+ {
+ PvdDataStream* stream = PvdDataStream::create(mPvd);
+ if(stream)
+ {
+ mConnected = true;
+ Ext::Pvd::sendClassDescriptions(*stream);
+ stream->release();
+ }
+ }
+
+ bool isConnected() const
+ {
+ return mConnected;
+ }
+
+ void onPvdDisconnected()
+ {
+ mConnected = false;
+ }
+
+ void flush()
+ {
+ }
+
+ PsPvd* mPvd;
+ bool mConnected;
+};
+
+static JointConnectionHandler gPvdHandler;
+#endif
+
+bool PxInitExtensions(PxPhysics& physics, PxPvd* pvd)
+{
+ PX_ASSERT(static_cast<Ps::Foundation*>(&physics.getFoundation()) == &Ps::Foundation::getInstance());
+ PX_UNUSED(physics);
+ PX_UNUSED(pvd);
+ Ps::Foundation::incRefCount();
+
+#if PX_SUPPORT_PVD
+ if(pvd)
+ {
+ gPvdHandler.mPvd = static_cast<PsPvd*>(pvd);
+ gPvdHandler.mPvd->addClient(&gPvdHandler);
+ }
+#endif
+
+ return true;
+}
+
+void PxCloseExtensions(void)
+{
+ Ps::Foundation::decRefCount();
+
+#if PX_SUPPORT_PVD
+ if(gPvdHandler.mConnected)
+ {
+ PX_ASSERT(gPvdHandler.mPvd);
+ gPvdHandler.mPvd->removeClient(&gPvdHandler);
+ gPvdHandler.mPvd = NULL;
+ }
+#endif
+}
+
+void Ext::RegisterExtensionsSerializers(PxSerializationRegistry& sr)
+{
+ //for repx serialization
+ sr.registerRepXSerializer(PxConcreteType::eMATERIAL, PX_NEW_REPX_SERIALIZER( PxMaterialRepXSerializer ));
+ sr.registerRepXSerializer(PxConcreteType::eSHAPE, PX_NEW_REPX_SERIALIZER( PxShapeRepXSerializer ));
+// sr.registerRepXSerializer(PxConcreteType::eTRIANGLE_MESH, PX_NEW_REPX_SERIALIZER( PxTriangleMeshRepXSerializer ));
+ sr.registerRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH33, PX_NEW_REPX_SERIALIZER( PxBVH33TriangleMeshRepXSerializer ));
+ sr.registerRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH34, PX_NEW_REPX_SERIALIZER( PxBVH34TriangleMeshRepXSerializer ));
+ sr.registerRepXSerializer(PxConcreteType::eHEIGHTFIELD, PX_NEW_REPX_SERIALIZER( PxHeightFieldRepXSerializer ));
+ sr.registerRepXSerializer(PxConcreteType::eCONVEX_MESH, PX_NEW_REPX_SERIALIZER( PxConvexMeshRepXSerializer ));
+ sr.registerRepXSerializer(PxConcreteType::eRIGID_STATIC, PX_NEW_REPX_SERIALIZER( PxRigidStaticRepXSerializer ));
+ sr.registerRepXSerializer(PxConcreteType::eRIGID_DYNAMIC, PX_NEW_REPX_SERIALIZER( PxRigidDynamicRepXSerializer ));
+ sr.registerRepXSerializer(PxConcreteType::eARTICULATION, PX_NEW_REPX_SERIALIZER( PxArticulationRepXSerializer ));
+ sr.registerRepXSerializer(PxConcreteType::eAGGREGATE, PX_NEW_REPX_SERIALIZER( PxAggregateRepXSerializer ));
+
+#if PX_USE_CLOTH_API
+ sr.registerRepXSerializer(PxConcreteType::eCLOTH_FABRIC, PX_NEW_REPX_SERIALIZER( PxClothFabricRepXSerializer ));
+ sr.registerRepXSerializer(PxConcreteType::eCLOTH, PX_NEW_REPX_SERIALIZER( PxClothRepXSerializer ));
+#endif
+#if PX_USE_PARTICLE_SYSTEM_API
+ sr.registerRepXSerializer(PxConcreteType::ePARTICLE_SYSTEM, PX_NEW_REPX_SERIALIZER( PxParticleRepXSerializer<PxParticleSystem> ));
+ sr.registerRepXSerializer(PxConcreteType::ePARTICLE_FLUID, PX_NEW_REPX_SERIALIZER( PxParticleRepXSerializer<PxParticleFluid> ));
+#endif
+
+ sr.registerRepXSerializer(PxJointConcreteType::eFIXED, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxFixedJoint> ));
+ sr.registerRepXSerializer(PxJointConcreteType::eDISTANCE, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxDistanceJoint> ));
+ sr.registerRepXSerializer(PxJointConcreteType::eD6, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxD6Joint> ));
+ sr.registerRepXSerializer(PxJointConcreteType::ePRISMATIC, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxPrismaticJoint> ));
+ sr.registerRepXSerializer(PxJointConcreteType::eREVOLUTE, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxRevoluteJoint> ));
+ sr.registerRepXSerializer(PxJointConcreteType::eSPHERICAL, PX_NEW_REPX_SERIALIZER( PxJointRepXSerializer<PxSphericalJoint> ));
+
+ //for binary serialization
+ sr.registerSerializer(PxJointConcreteType::eFIXED, PX_NEW_SERIALIZER_ADAPTER( FixedJoint ));
+ sr.registerSerializer(PxJointConcreteType::eDISTANCE, PX_NEW_SERIALIZER_ADAPTER( DistanceJoint ));
+ sr.registerSerializer(PxJointConcreteType::eD6, PX_NEW_SERIALIZER_ADAPTER( D6Joint) );
+ sr.registerSerializer(PxJointConcreteType::ePRISMATIC, PX_NEW_SERIALIZER_ADAPTER( PrismaticJoint ));
+ sr.registerSerializer(PxJointConcreteType::eREVOLUTE, PX_NEW_SERIALIZER_ADAPTER( RevoluteJoint ));
+ sr.registerSerializer(PxJointConcreteType::eSPHERICAL, PX_NEW_SERIALIZER_ADAPTER( SphericalJoint ));
+}
+
+void Ext::UnregisterExtensionsSerializers(PxSerializationRegistry& sr)
+{
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eFIXED));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eDISTANCE));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eD6 ));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::ePRISMATIC));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eREVOLUTE));
+ PX_DELETE_SERIALIZER_ADAPTER(sr.unregisterSerializer(PxJointConcreteType::eSPHERICAL));
+
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eMATERIAL));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eSHAPE));
+// PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eTRIANGLE_MESH));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH33));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eTRIANGLE_MESH_BVH34));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eHEIGHTFIELD));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eCONVEX_MESH));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eRIGID_STATIC));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eRIGID_DYNAMIC));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eARTICULATION));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eAGGREGATE));
+
+#if PX_USE_CLOTH_API
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eCLOTH_FABRIC));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::eCLOTH));
+#endif
+#if PX_USE_PARTICLE_SYSTEM_API
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::ePARTICLE_SYSTEM));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxConcreteType::ePARTICLE_FLUID));
+#endif
+
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eFIXED));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eDISTANCE));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eD6));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::ePRISMATIC));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eREVOLUTE));
+ PX_DELETE_REPX_SERIALIZER(sr.unregisterRepXSerializer(PxJointConcreteType::eSPHERICAL));
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.cpp
new file mode 100644
index 00000000..55dfd4a4
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.cpp
@@ -0,0 +1,173 @@
+// 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 "ExtFixedJoint.h"
+#include "ExtConstraintHelper.h"
+#include "CmVisualization.h"
+
+#include "common/PxSerialFramework.h"
+
+using namespace physx;
+using namespace Ext;
+
+namespace physx
+{
+ PxFixedJoint* PxFixedJointCreate(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1);
+}
+
+PxFixedJoint* physx::PxFixedJointCreate(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+{
+ PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxFixedJointCreate: local frame 0 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxFixedJointCreate: local frame 1 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxFixedJointCreate: at least one actor must be dynamic");
+ PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxFixedJointCreate: actors must be different");
+
+ FixedJoint* j;
+ PX_NEW_SERIALIZED(j,FixedJoint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1);
+
+ if(j->attach(physics, actor0, actor1))
+ return j;
+
+ PX_DELETE(j);
+ return NULL;
+}
+
+PxReal FixedJoint::getProjectionLinearTolerance() const
+{
+ return data().projectionLinearTolerance;
+}
+
+void FixedJoint::setProjectionLinearTolerance(PxReal tolerance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0, "PxFixedJoint::setProjectionLinearTolerance: invalid parameter");
+ data().projectionLinearTolerance = tolerance;
+ markDirty();
+}
+
+PxReal FixedJoint::getProjectionAngularTolerance() const
+{
+ return data().projectionAngularTolerance;
+}
+
+void FixedJoint::setProjectionAngularTolerance(PxReal tolerance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0 && tolerance <= PxPi, "PxFixedJoint::setProjectionAngularTolerance: invalid parameter");
+ data().projectionAngularTolerance = tolerance; markDirty();
+}
+
+
+namespace
+{
+void FixedJointVisualize(PxConstraintVisualizer& viz,
+ const void* constantBlock,
+ const PxTransform& body0Transform,
+ const PxTransform& body1Transform,
+ PxU32 /*flags*/)
+{
+ const FixedJointData& data = *reinterpret_cast<const FixedJointData*>(constantBlock);
+
+ const PxTransform& t0 = body0Transform * data.c2b[0];
+ const PxTransform& t1 = body1Transform * data.c2b[1];
+
+ viz.visualizeJointFrames(t0, t1);
+}
+
+
+
+void FixedJointProject(const void* constantBlock,
+ PxTransform& bodyAToWorld,
+ PxTransform& bodyBToWorld,
+ bool projectToA)
+{
+
+ using namespace joint;
+ const FixedJointData &data = *reinterpret_cast<const FixedJointData*>(constantBlock);
+
+ PxTransform cA2w, cB2w, cB2cA, projected;
+ computeDerived(data, bodyAToWorld, bodyBToWorld, cA2w, cB2w, cB2cA);
+
+ bool linearTrunc, angularTrunc;
+ projected.p = truncateLinear(cB2cA.p, data.projectionLinearTolerance, linearTrunc);
+ projected.q = truncateAngular(cB2cA.q, PxSin(data.projectionAngularTolerance/2), PxCos(data.projectionAngularTolerance/2), angularTrunc);
+
+ if(linearTrunc || angularTrunc)
+ projectTransforms(bodyAToWorld, bodyBToWorld, cA2w, cB2w, projected, data, projectToA);
+}
+}
+
+bool Ext::FixedJoint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1)
+{
+ mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(FixedJointData));
+ return mPxConstraint!=NULL;
+}
+
+void FixedJoint::exportExtraData(PxSerializationContext& stream) const
+{
+ if(mData)
+ {
+ stream.alignData(PX_SERIAL_ALIGN);
+ stream.writeData(mData, sizeof(FixedJointData));
+ }
+ stream.writeName(mName);
+}
+
+void FixedJoint::importExtraData(PxDeserializationContext& context)
+{
+ if(mData)
+ mData = context.readExtraData<FixedJointData, PX_SERIAL_ALIGN>();
+ context.readName(mName);
+}
+
+void FixedJoint::resolveReferences(PxDeserializationContext& context)
+{
+ setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders));
+}
+
+FixedJoint* FixedJoint::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ FixedJoint* obj = new (address) FixedJoint(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(FixedJoint);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+
+// global function to share the joint shaders with API capture
+const PxConstraintShaderTable* Ext::GetFixedJointShaderTable()
+{
+ return &FixedJoint::getConstraintShaderTable();
+}
+
+//~PX_SERIALIZATION
+PxConstraintShaderTable Ext::FixedJoint::sShaders = { Ext::FixedJointSolverPrep, FixedJointProject, FixedJointVisualize, PxConstraintFlag::Enum(0) };
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.h
new file mode 100644
index 00000000..887cb24b
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJoint.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 NP_FIXEDJOINTCONSTRAINT_H
+#define NP_FIXEDJOINTCONSTRAINT_H
+
+#include "ExtJoint.h"
+#include "PxFixedJoint.h"
+#include "CmUtils.h"
+
+namespace physx
+{
+struct PxFixedJointGeneratedValues;
+namespace Ext
+{
+
+ struct FixedJointData : public JointData
+ {
+ //= 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.
+ //==================================================================================================
+
+ PxReal projectionLinearTolerance;
+ PxReal projectionAngularTolerance;
+ };
+
+ typedef Joint<PxFixedJoint, PxFixedJointGeneratedValues> FixedJointT;
+
+ class FixedJoint : public FixedJointT
+ {
+ //= 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
+ FixedJoint(PxBaseFlags baseFlags) : FixedJointT(baseFlags) {}
+ virtual void exportExtraData(PxSerializationContext& context) const;
+ void importExtraData(PxDeserializationContext& context);
+ void resolveReferences(PxDeserializationContext& context);
+ static FixedJoint* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ virtual ~FixedJoint()
+ {
+ if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY)
+ PX_FREE(mData);
+ }
+
+ PxReal getProjectionLinearTolerance() const;
+ void setProjectionLinearTolerance(PxReal tolerance);
+
+ PxReal getProjectionAngularTolerance() const;
+ void setProjectionAngularTolerance(PxReal tolerance);
+
+ FixedJoint(const PxTolerancesScale& /*scale*/,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ : FixedJointT(PxJointConcreteType::eFIXED, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+ {
+ FixedJointData* data = reinterpret_cast<FixedJointData*>(PX_ALLOC(sizeof(FixedJointData), "FixedJointData"));
+ Cm::markSerializedMem(data, sizeof(FixedJointData));
+ mData = data;
+ data->projectionLinearTolerance = 1e10f;
+ data->projectionAngularTolerance = PxPi;
+
+ initCommonData(*data, actor0, localFrame0, actor1, localFrame1);
+ }
+
+ bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1);
+
+ static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; }
+
+ virtual PxConstraintSolverPrep getPrep() const { return sShaders.solverPrep; }
+
+ private:
+
+ static PxConstraintShaderTable sShaders;
+
+ PX_FORCE_INLINE FixedJointData& data() const
+ {
+ return *static_cast<FixedJointData*>(mData);
+ }
+ };
+} // namespace Ext
+
+namespace Ext
+{
+ extern "C" PxU32 FixedJointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 maxConstraints,
+ PxConstraintInvMassScale& invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w);
+
+ // global function to share the joint shaders with API capture
+ extern "C" const PxConstraintShaderTable* GetFixedJointShaderTable();
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJointSolverPrep.cpp
new file mode 100644
index 00000000..811d2a11
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtFixedJointSolverPrep.cpp
@@ -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.
+
+
+#include "ExtFixedJoint.h"
+#include "ExtConstraintHelper.h"
+
+namespace physx
+{
+namespace Ext
+{
+
+ PxU32 FixedJointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 maxConstraints,
+ PxConstraintInvMassScale &invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w)
+ {
+ PX_UNUSED(maxConstraints);
+
+ const FixedJointData& data = *reinterpret_cast<const FixedJointData*>(constantBlock);
+ invMassScale = data.invMassScale;
+
+ PxTransform cA2w = bA2w.transform(data.c2b[0]);
+ PxTransform cB2w = bB2w.transform(data.c2b[1]);
+
+ PxVec3 bOriginInA = cA2w.transformInv(cB2w.p);
+
+ body0WorldOffset = cB2w.p-bA2w.p;
+ joint::ConstraintHelper ch(constraints,cB2w.p-bA2w.p, cB2w.p-bB2w.p);
+ ch.prepareLockedAxes(cA2w.q, cB2w.q, bOriginInA, 7, 7);
+
+ return ch.getCount();
+ }
+
+
+}//namespace
+
+}
+
+//~PX_SERIALIZATION
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtInertiaTensor.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtInertiaTensor.h
new file mode 100644
index 00000000..510e46b7
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtInertiaTensor.h
@@ -0,0 +1,404 @@
+// 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_EXTENSIONS_INERTIATENSOR_H
+#define PX_PHYSICS_EXTENSIONS_INERTIATENSOR_H
+
+#include "foundation/PxMat33.h"
+#include "foundation/PxMathUtils.h"
+#include "CmPhysXCommon.h"
+#include "PsMathUtils.h"
+
+namespace physx
+{
+namespace Ext
+{
+ class InertiaTensorComputer
+ {
+ public:
+ InertiaTensorComputer(bool initTozero = true);
+ InertiaTensorComputer(const PxMat33& inertia, const PxVec3& com, PxReal mass);
+ ~InertiaTensorComputer();
+
+ PX_INLINE void zero(); //sets to zero mass
+ PX_INLINE void setDiagonal(PxReal mass, const PxVec3& diagonal); //sets as a diagonal tensor
+ PX_INLINE void rotate(const PxMat33& rot); //rotates the mass
+ void translate(const PxVec3& t); //translates the mass
+ PX_INLINE void transform(const PxTransform& transform); //transforms the mass
+ PX_INLINE void scaleDensity(PxReal densityScale); //scales by a density factor
+ PX_INLINE void add(const InertiaTensorComputer& it); //adds a mass
+ PX_INLINE void center(); //recenters inertia around center of mass
+
+ void setBox(const PxVec3& halfWidths); //sets as an axis aligned box
+ PX_INLINE void setBox(const PxVec3& halfWidths, const PxTransform* pose); //sets as an oriented box
+
+ void setSphere(PxReal radius);
+ PX_INLINE void setSphere(PxReal radius, const PxTransform* pose);
+
+ void setCylinder(int dir, PxReal r, PxReal l);
+ PX_INLINE void setCylinder(int dir, PxReal r, PxReal l, const PxTransform* pose);
+
+ void setCapsule(int dir, PxReal r, PxReal l);
+ PX_INLINE void setCapsule(int dir, PxReal r, PxReal l, const PxTransform* pose);
+ void addCapsule(PxReal density, int dir, PxReal r, PxReal l, const PxTransform* pose = 0);
+
+ void setEllipsoid(PxReal rx, PxReal ry, PxReal rz);
+ PX_INLINE void setEllipsoid(PxReal rx, PxReal ry, PxReal rz, const PxTransform* pose);
+
+ PX_INLINE PxVec3 getCenterOfMass() const { return mG; }
+ PX_INLINE PxReal getMass() const { return mMass; }
+ PX_INLINE PxMat33 getInertia() const { return mI; }
+
+ private:
+ PxMat33 mI;
+ PxVec3 mG;
+ PxReal mMass;
+ };
+
+
+ //--------------------------------------------------------------
+ //
+ // Helper routines
+ //
+ //--------------------------------------------------------------
+
+ // Special version allowing 2D quads
+ PX_INLINE PxReal volume(const PxVec3& extents)
+ {
+ PxReal v = 1.0f;
+ if(extents.x != 0.0f) v*=extents.x;
+ if(extents.y != 0.0f) v*=extents.y;
+ if(extents.z != 0.0f) v*=extents.z;
+ return v;
+ }
+
+ // Sphere
+ PX_INLINE PxReal computeSphereRatio(PxReal radius) { return (4.0f/3.0f) * PxPi * radius * radius * radius; }
+ PxReal computeSphereMass(PxReal radius, PxReal density) { return density * computeSphereRatio(radius); }
+ PxReal computeSphereDensity(PxReal radius, PxReal mass) { return mass / computeSphereRatio(radius); }
+
+ // Box
+ PX_INLINE PxReal computeBoxRatio(const PxVec3& extents) { return volume(extents); }
+ PxReal computeBoxMass(const PxVec3& extents, PxReal density) { return density * computeBoxRatio(extents); }
+ PxReal computeBoxDensity(const PxVec3& extents, PxReal mass) { return mass / computeBoxRatio(extents); }
+
+ // Ellipsoid
+ PX_INLINE PxReal computeEllipsoidRatio(const PxVec3& extents) { return (4.0f/3.0f) * PxPi * volume(extents); }
+ PxReal computeEllipsoidMass(const PxVec3& extents, PxReal density) { return density * computeEllipsoidRatio(extents); }
+ PxReal computeEllipsoidDensity(const PxVec3& extents, PxReal mass) { return mass / computeEllipsoidRatio(extents); }
+
+ // Cylinder
+ PX_INLINE PxReal computeCylinderRatio(PxReal r, PxReal l) { return PxPi * r * r * (2.0f*l); }
+ PxReal computeCylinderMass(PxReal r, PxReal l, PxReal density) { return density * computeCylinderRatio(r, l); }
+ PxReal computeCylinderDensity(PxReal r, PxReal l, PxReal mass) { return mass / computeCylinderRatio(r, l); }
+
+ // Capsule
+ PX_INLINE PxReal computeCapsuleRatio(PxReal r, PxReal l) { return computeSphereRatio(r) + computeCylinderRatio(r, l);}
+ PxReal computeCapsuleMass(PxReal r, PxReal l, PxReal density) { return density * computeCapsuleRatio(r, l); }
+ PxReal computeCapsuleDensity(PxReal r, PxReal l, PxReal mass) { return mass / computeCapsuleRatio(r, l); }
+
+ // Cone
+ PX_INLINE PxReal computeConeRatio(PxReal r, PxReal l) { return PxPi * r * r * PxAbs(l)/3.0f; }
+ PxReal computeConeMass(PxReal r, PxReal l, PxReal density) { return density * computeConeRatio(r, l); }
+ PxReal computeConeDensity(PxReal r, PxReal l, PxReal mass) { return mass / computeConeRatio(r, l); }
+
+ void computeBoxInertiaTensor(PxVec3& inertia, PxReal mass, PxReal xlength, PxReal ylength, PxReal zlength);
+ void computeSphereInertiaTensor(PxVec3& inertia, PxReal mass, PxReal radius, bool hollow);
+ bool jacobiTransform(PxI32 n, PxF64 a[], PxF64 w[]);
+ bool diagonalizeInertiaTensor(const PxMat33& denseInertia, PxVec3& diagonalInertia, PxMat33& rotation);
+
+} // namespace Ext
+
+void Ext::computeBoxInertiaTensor(PxVec3& inertia, PxReal mass, PxReal xlength, PxReal ylength, PxReal zlength)
+{
+ //to model a hollow block, one would have to multiply coeff by up to two.
+ const PxReal coeff = mass/12;
+ inertia.x = coeff * (ylength*ylength + zlength*zlength);
+ inertia.y = coeff * (xlength*xlength + zlength*zlength);
+ inertia.z = coeff * (xlength*xlength + ylength*ylength);
+
+ PX_ASSERT(inertia.x != 0.0f);
+ PX_ASSERT(inertia.y != 0.0f);
+ PX_ASSERT(inertia.z != 0.0f);
+ PX_ASSERT(inertia.isFinite());
+}
+
+
+void Ext::computeSphereInertiaTensor(PxVec3& inertia, PxReal mass, PxReal radius, bool hollow)
+{
+ inertia.x = mass * radius * radius;
+ if (hollow)
+ inertia.x *= PxReal(2 / 3.0);
+ else
+ inertia.x *= PxReal(2 / 5.0);
+
+ inertia.z = inertia.y = inertia.x;
+ PX_ASSERT(inertia.isFinite());
+}
+
+//--------------------------------------------------------------
+//
+// InertiaTensorComputer implementation
+//
+//--------------------------------------------------------------
+
+Ext::InertiaTensorComputer::InertiaTensorComputer(bool initTozero)
+{
+ if (initTozero)
+ zero();
+}
+
+
+Ext::InertiaTensorComputer::InertiaTensorComputer(const PxMat33& inertia, const PxVec3& com, PxReal mass) :
+ mI(inertia),
+ mG(com),
+ mMass(mass)
+{
+}
+
+
+Ext::InertiaTensorComputer::~InertiaTensorComputer()
+{
+ //nothing
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::zero()
+{
+ mMass = 0.0f;
+ mI = PxMat33(PxZero);
+ mG = PxVec3(0);
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::setDiagonal(PxReal mass, const PxVec3& diag)
+{
+ mMass = mass;
+ mI = PxMat33::createDiagonal(diag);
+ mG = PxVec3(0);
+ PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite());
+ PX_ASSERT(PxIsFinite(mMass));
+}
+
+
+void Ext::InertiaTensorComputer::setBox(const PxVec3& halfWidths)
+{
+ // Setup inertia tensor for a cube with unit density
+ const PxReal mass = 8.0f * computeBoxRatio(halfWidths);
+ const PxReal s =(1.0f/3.0f) * mass;
+
+ const PxReal x = halfWidths.x*halfWidths.x;
+ const PxReal y = halfWidths.y*halfWidths.y;
+ const PxReal z = halfWidths.z*halfWidths.z;
+
+ setDiagonal(mass, PxVec3(y+z, z+x, x+y) * s);
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::rotate(const PxMat33& rot)
+{
+ //well known inertia tensor rotation expression is: RIR' -- this could be optimized due to symmetry, see code to do that in Body::updateGlobalInverseInertia
+ mI = rot * mI * rot.getTranspose();
+ PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite());
+ //com also needs to be rotated
+ mG = rot * mG;
+ PX_ASSERT(mG.isFinite());
+}
+
+
+void Ext::InertiaTensorComputer::translate(const PxVec3& t)
+{
+ if (!t.isZero()) //its common for this to be zero
+ {
+ PxMat33 t1, t2;
+
+ t1.column0 = PxVec3(0, mG.z, -mG.y);
+ t1.column1 = PxVec3(-mG.z, 0, mG.x);
+ t1.column2 = PxVec3(mG.y, -mG.x, 0);
+
+ PxVec3 sum = mG + t;
+ if (sum.isZero())
+ {
+ mI += (t1 * t1)*mMass;
+ }
+ else
+ {
+ t2.column0 = PxVec3(0, sum.z, -sum.y);
+ t2.column1 = PxVec3(-sum.z, 0, sum.x);
+ t2.column2 = PxVec3(sum.y, -sum.x, 0);
+ mI += (t1 * t1 - t2 * t2)*mMass;
+ }
+
+ //move center of mass
+ mG += t;
+
+ PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite());
+ PX_ASSERT(mG.isFinite());
+ }
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::transform(const PxTransform& transform)
+{
+ rotate(PxMat33(transform.q));
+ translate(transform.p);
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::setBox(const PxVec3& halfWidths, const PxTransform* pose)
+{
+ setBox(halfWidths);
+ if (pose)
+ transform(*pose);
+
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::scaleDensity(PxReal densityScale)
+{
+ mI *= densityScale;
+ mMass *= densityScale;
+ PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite());
+ PX_ASSERT(PxIsFinite(mMass));
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::add(const InertiaTensorComputer& it)
+{
+ const PxReal TotalMass = mMass + it.mMass;
+ mG = (mG * mMass + it.mG * it.mMass) / TotalMass;
+
+ mMass = TotalMass;
+ mI += it.mI;
+ PX_ASSERT(mI.column0.isFinite() && mI.column1.isFinite() && mI.column2.isFinite());
+ PX_ASSERT(mG.isFinite());
+ PX_ASSERT(PxIsFinite(mMass));
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::center()
+{
+ PxVec3 center = -mG;
+ translate(center);
+}
+
+
+void Ext::InertiaTensorComputer::setSphere(PxReal radius)
+{
+ // Compute mass of the sphere
+ const PxReal m = computeSphereRatio(radius);
+ // Compute moment of inertia
+ const PxReal s = m * radius * radius * (2.0f/5.0f);
+ setDiagonal(m,PxVec3(s,s,s));
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::setSphere(PxReal radius, const PxTransform* pose)
+{
+ setSphere(radius);
+ if (pose)
+ transform(*pose);
+}
+
+
+void Ext::InertiaTensorComputer::setCylinder(int dir, PxReal r, PxReal l)
+{
+ // Compute mass of cylinder
+ const PxReal m = computeCylinderRatio(r, l);
+
+ const PxReal i1 = r*r*m/2.0f;
+ const PxReal i2 = (3.0f*r*r+4.0f*l*l)*m/12.0f;
+
+ switch(dir)
+ {
+ case 0: setDiagonal(m,PxVec3(i1,i2,i2)); break;
+ case 1: setDiagonal(m,PxVec3(i2,i1,i2)); break;
+ default: setDiagonal(m,PxVec3(i2,i2,i1)); break;
+ }
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::setCylinder(int dir, PxReal r, PxReal l, const PxTransform* pose)
+{
+ setCylinder(dir, r, l);
+ if (pose)
+ transform(*pose);
+}
+
+
+void Ext::InertiaTensorComputer::setCapsule(int dir, PxReal r, PxReal l)
+{
+ // Compute mass of capsule
+ const PxReal m = computeCapsuleRatio(r, l);
+
+ const PxReal t = PxPi * r * r;
+ const PxReal i1 = t * ((r*r*r * 8.0f/15.0f) + (l*r*r));
+ const PxReal i2 = t * ((r*r*r * 8.0f/15.0f) + (l*r*r * 3.0f/2.0f) + (l*l*r * 4.0f/3.0f) + (l*l*l * 2.0f/3.0f));
+
+ switch(dir)
+ {
+ case 0: setDiagonal(m,PxVec3(i1,i2,i2)); break;
+ case 1: setDiagonal(m,PxVec3(i2,i1,i2)); break;
+ default: setDiagonal(m,PxVec3(i2,i2,i1)); break;
+ }
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::setCapsule(int dir, PxReal r, PxReal l, const PxTransform* pose)
+{
+ setCapsule(dir, r, l);
+ if (pose)
+ transform(*pose);
+}
+
+
+void Ext::InertiaTensorComputer::setEllipsoid(PxReal rx, PxReal ry, PxReal rz)
+{
+ // Compute mass of ellipsoid
+ const PxReal m = computeEllipsoidRatio(PxVec3(rx, ry, rz));
+
+ // Compute moment of inertia
+ const PxReal s = m * (2.0f/5.0f);
+
+ // Setup inertia tensor for an ellipsoid centered at the origin
+ setDiagonal(m,PxVec3(ry*rz,rz*rx,rx*ry)*s);
+}
+
+
+PX_INLINE void Ext::InertiaTensorComputer::setEllipsoid(PxReal rx, PxReal ry, PxReal rz, const PxTransform* pose)
+{
+ setEllipsoid(rx,ry,rz);
+ if (pose)
+ transform(*pose);
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.cpp
new file mode 100644
index 00000000..48b699ab
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.cpp
@@ -0,0 +1,134 @@
+// 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 NOMINMAX
+#define NOMINMAX
+#endif
+
+#include "foundation/PxMat33.h"
+#include "PxConstraint.h"
+#include "PxJoint.h"
+#include "ExtJoint.h"
+
+using namespace physx;
+using namespace Ext;
+
+PxConstraint* physx::resolveConstraintPtr(PxDeserializationContext& v,
+ PxConstraint* old,
+ PxConstraintConnector* connector,
+ PxConstraintShaderTable &shaders)
+{
+ v.translatePxBase(old);
+ PxConstraint* new_nx = static_cast<PxConstraint*>(old);
+ new_nx->setConstraintFunctions(*connector, shaders);
+ return new_nx;
+}
+//~PX_SERIALIZATION
+
+
+static void normalToTangents(const PxVec3& n, PxVec3& t1, PxVec3& t2)
+{
+ const PxReal m_sqrt1_2 = PxReal(0.7071067811865475244008443621048490);
+ if(fabsf(n.z) > m_sqrt1_2)
+ {
+ const PxReal a = n.y*n.y + n.z*n.z;
+ const PxReal k = PxReal(1.0)/PxSqrt(a);
+ t1 = PxVec3(0,-n.z*k,n.y*k);
+ t2 = PxVec3(a*k,-n.x*t1.z,n.x*t1.y);
+ }
+ else
+ {
+ const PxReal a = n.x*n.x + n.y*n.y;
+ const PxReal k = PxReal(1.0)/PxSqrt(a);
+ t1 = PxVec3(-n.y*k,n.x*k,0);
+ t2 = PxVec3(-n.z*t1.y,n.z*t1.x,a*k);
+ }
+ t1.normalize();
+ t2.normalize();
+}
+
+void PxSetJointGlobalFrame(PxJoint& joint, const PxVec3* wsAnchor, const PxVec3* axisIn)
+{
+ PxRigidActor* actors[2];
+ joint.getActors(actors[0], actors[1]);
+
+ PxTransform localPose[2];
+ for(PxU32 i=0; i<2; i++)
+ localPose[i] = PxTransform(PxIdentity);
+
+ // 1) global anchor
+ if(wsAnchor)
+ {
+ //transform anchorPoint to local space
+ for(PxU32 i=0; i<2; i++)
+ localPose[i].p = actors[i] ? actors[i]->getGlobalPose().transformInv(*wsAnchor) : *wsAnchor;
+ }
+
+ // 2) global axis
+ if(axisIn)
+ {
+ PxVec3 localAxis[2], localNormal[2];
+
+ //find 2 orthogonal vectors.
+ //gotta do this in world space, if we choose them
+ //separately in local space they won't match up in worldspace.
+ PxVec3 axisw = *axisIn;
+ axisw.normalize();
+
+ PxVec3 normalw, binormalw;
+ ::normalToTangents(axisw, binormalw, normalw);
+ //because axis is supposed to be the Z axis of a frame with the other two being X and Y, we need to negate
+ //Y to make the frame right handed. Note that the above call makes a right handed frame if we pass X --> Y,Z, so
+ //it need not be changed.
+
+ for(PxU32 i=0; i<2; i++)
+ {
+ if(actors[i])
+ {
+ const PxTransform& m = actors[i]->getGlobalPose();
+ PxMat33 mM(m.q);
+ localAxis[i] = mM.transformTranspose(axisw);
+ localNormal[i] = mM.transformTranspose(normalw);
+ }
+ else
+ {
+ localAxis[i] = axisw;
+ localNormal[i] = normalw;
+ }
+
+ PxMat33 rot(localAxis[i], localNormal[i], localAxis[i].cross(localNormal[i]));
+
+ localPose[i].q = PxQuat(rot);
+ localPose[i].q.normalize();
+ }
+ }
+
+ for(PxU32 i=0; i<2; i++)
+ joint.setLocalPose(static_cast<PxJointActorIndex::Enum>( i ), localPose[i]);
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.h
new file mode 100644
index 00000000..d5ef06ea
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtJoint.h
@@ -0,0 +1,500 @@
+// 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_JOINTCONSTRAINT_H
+#define NP_JOINTCONSTRAINT_H
+
+#include "PsAllocator.h"
+#include "PsUtilities.h"
+#include "PxConstraint.h"
+#include "PxConstraintExt.h"
+#include "PxJoint.h"
+#include "PxD6Joint.h"
+#include "PxRigidDynamic.h"
+#include "PxRigidStatic.h"
+#include "ExtPvd.h"
+#include "PxMetaData.h"
+#include "CmRenderOutput.h"
+#include "PxPhysics.h"
+#include "PsFoundation.h"
+
+#if PX_SUPPORT_PVD
+#include "PxScene.h"
+#include "PxPvdClient.h"
+#include "PxPvdSceneClient.h"
+#endif
+
+// PX_SERIALIZATION
+
+namespace physx
+{
+
+PxConstraint* resolveConstraintPtr(PxDeserializationContext& v,
+ PxConstraint* old,
+ PxConstraintConnector* connector,
+ PxConstraintShaderTable& shaders);
+
+// ~PX_SERIALIZATION
+
+namespace Ext
+{
+ struct JointData
+ {
+ //= 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.
+ //==================================================================================================
+ PxConstraintInvMassScale invMassScale;
+ PxTransform c2b[2];
+ protected:
+ ~JointData(){}
+ };
+
+ template <class Base, class ValueStruct>
+ class Joint : public Base,
+ public PxConstraintConnector,
+ public Ps::UserAllocated
+ {
+
+ public:
+// PX_SERIALIZATION
+ Joint(PxBaseFlags baseFlags) : Base(baseFlags) {}
+ virtual void requires(PxProcessPxBaseCallback& c)
+ {
+ c.process(*mPxConstraint);
+
+ {
+ PxRigidActor* a0 = NULL;
+ PxRigidActor* a1 = NULL;
+ mPxConstraint->getActors(a0,a1);
+
+ if (a0)
+ {
+ c.process(*a0);
+ }
+ if (a1)
+ {
+ c.process(*a1);
+ }
+ }
+ }
+//~PX_SERIALIZATION
+
+#if PX_SUPPORT_PVD
+
+ virtual bool updatePvdProperties(physx::pvdsdk::PvdDataStream& pvdConnection, const PxConstraint* c, PxPvdUpdateType::Enum updateType) const
+ {
+ if(updateType == PxPvdUpdateType::UPDATE_SIM_PROPERTIES)
+ {
+ Ext::Pvd::simUpdate<Base>(pvdConnection, *this);
+ return true;
+ }
+ else if(updateType == PxPvdUpdateType::UPDATE_ALL_PROPERTIES)
+ {
+ Ext::Pvd::updatePvdProperties<Base, ValueStruct>(pvdConnection, *this);
+ return true;
+ }
+ else if(updateType == PxPvdUpdateType::CREATE_INSTANCE)
+ {
+ Ext::Pvd::createPvdInstance<Base>(pvdConnection, *c, *this);
+ return true;
+ }
+ else if(updateType == PxPvdUpdateType::RELEASE_INSTANCE)
+ {
+ Ext::Pvd::releasePvdInstance(pvdConnection, *c, *this);
+ return true;
+ }
+ return false;
+ }
+#else
+ virtual bool updatePvdProperties(physx::pvdsdk::PvdDataStream&, const PxConstraint*, PxPvdUpdateType::Enum) const
+ {
+ return false;
+ }
+#endif
+
+
+
+ void getActors(PxRigidActor*& actor0, PxRigidActor*& actor1) const
+ {
+ if ( mPxConstraint ) mPxConstraint->getActors(actor0,actor1);
+ else
+ {
+ actor0 = NULL;
+ actor1 = NULL;
+ }
+ }
+
+ void setActors(PxRigidActor* actor0, PxRigidActor* actor1)
+ {
+ //TODO SDK-DEV
+ //You can get the debugger stream from the NpScene
+ //Ext::Pvd::setActors( stream, this, mPxConstraint, actor0, actor1 );
+ PX_CHECK_AND_RETURN(actor0 != actor1, "PxJoint::setActors: actors must be different");
+ PX_CHECK_AND_RETURN((actor0 && !actor0->is<PxRigidStatic>()) || (actor1 && !actor1->is<PxRigidStatic>()), "PxJoint::setActors: at least one actor must be non-static");
+
+#if PX_SUPPORT_PVD
+ PxScene* scene = getScene();
+ if(scene)
+ {
+ //if pvd not connect data stream is NULL
+ physx::pvdsdk::PvdDataStream* conn = scene->getScenePvdClient()->getClientInternal()->getDataStream();
+ if( conn != NULL )
+ Ext::Pvd::setActors(
+ *conn,
+ *this,
+ *mPxConstraint,
+ actor0,
+ actor1
+ );
+ }
+#endif
+
+ mPxConstraint->setActors(actor0, actor1);
+ mData->c2b[0] = getCom(actor0).transformInv(mLocalPose[0]);
+ mData->c2b[1] = getCom(actor1).transformInv(mLocalPose[1]);
+ mPxConstraint->markDirty();
+ }
+
+ // this is the local pose relative to the actor, and we store internally the local
+ // pose relative to the body
+
+ PxTransform getLocalPose(PxJointActorIndex::Enum actor) const
+ {
+ return mLocalPose[actor];
+ }
+
+ void setLocalPose(PxJointActorIndex::Enum actor, const PxTransform& pose)
+ {
+ PX_CHECK_AND_RETURN(pose.isSane(), "PxJoint::setLocalPose: transform is invalid");
+ PxTransform p = pose.getNormalized();
+ mLocalPose[actor] = p;
+ mData->c2b[actor] = getCom(actor).transformInv(p);
+ mPxConstraint->markDirty();
+ }
+
+ PxTransform getBodyPose(const PxRigidActor* actor) const
+ {
+ if(!actor)
+ return PxTransform(PxIdentity);
+ else if(actor->is<PxRigidStatic>())
+ return actor->getGlobalPose();
+ else
+ return actor->getGlobalPose() * static_cast<const PxRigidBody*>(actor)->getCMassLocalPose();
+ }
+
+
+ void getActorVelocity(const PxRigidActor* actor, PxVec3& linear, PxVec3& angular) const
+ {
+ if(!actor || actor->is<PxRigidStatic>())
+ {
+ linear = angular = PxVec3(0);
+ return;
+ }
+
+ linear = static_cast<const PxRigidBody*>(actor)->getLinearVelocity();
+ angular = static_cast<const PxRigidBody*>(actor)->getAngularVelocity();
+ }
+
+
+ PxTransform getRelativeTransform() const
+ {
+ PxRigidActor* actor0, * actor1;
+ mPxConstraint->getActors(actor0, actor1);
+ PxTransform t0 = getBodyPose(actor0) * mLocalPose[0],
+ t1 = getBodyPose(actor1) * mLocalPose[1];
+ return t0.transformInv(t1);
+ }
+
+ PxVec3 getRelativeLinearVelocity() const
+ {
+ PxRigidActor* actor0, * actor1;
+ PxVec3 l0, a0, l1, a1;
+ mPxConstraint->getActors(actor0, actor1);
+
+ PxTransform t0 = getCom(actor0), t1 = getCom(actor1);
+ getActorVelocity(actor0, l0, a0);
+ getActorVelocity(actor1, l1, a1);
+
+ PxVec3 p0 = t0.q.rotate(mLocalPose[0].p),
+ p1 = t1.q.rotate(mLocalPose[1].p);
+ return t0.transformInv(l1 - a1.cross(p1) - l0 + a0.cross(p0));
+ }
+
+ PxVec3 getRelativeAngularVelocity() const
+ {
+ PxRigidActor* actor0, * actor1;
+ PxVec3 l0, a0, l1, a1;
+ mPxConstraint->getActors(actor0, actor1);
+
+ PxTransform t0 = getCom(actor0);
+ getActorVelocity(actor0, l0, a0);
+ getActorVelocity(actor1, l1, a1);
+
+ return t0.transformInv(a1 - a0);
+ }
+
+
+ void getBreakForce(PxReal& force, PxReal& torque) const
+ {
+ mPxConstraint->getBreakForce(force,torque);
+ }
+
+ void setBreakForce(PxReal force, PxReal torque)
+ {
+ PX_CHECK_AND_RETURN(PxIsFinite(force) && PxIsFinite(torque), "NpJoint::setBreakForce: invalid float");
+ mPxConstraint->setBreakForce(force,torque);
+ }
+
+
+ PxConstraintFlags getConstraintFlags() const
+ {
+ return mPxConstraint->getFlags();
+ }
+
+ void setConstraintFlags(PxConstraintFlags flags)
+ {
+ mPxConstraint->setFlags(flags);
+ }
+
+ void setConstraintFlag(PxConstraintFlag::Enum flag, bool value)
+ {
+ mPxConstraint->setFlag(flag, value);
+ }
+
+ void setInvMassScale0(PxReal invMassScale)
+ {
+ PX_CHECK_AND_RETURN(PxIsFinite(invMassScale) && invMassScale>=0, "PxJoint::setInvMassScale0: scale must be non-negative");
+ mData->invMassScale.linear0 = invMassScale;
+ mPxConstraint->markDirty();
+ }
+
+ PxReal getInvMassScale0() const
+ {
+ return mData->invMassScale.linear0;
+ }
+
+ void setInvInertiaScale0(PxReal invInertiaScale)
+ {
+ PX_CHECK_AND_RETURN(PxIsFinite(invInertiaScale) && invInertiaScale>=0, "PxJoint::setInvInertiaScale0: scale must be non-negative");
+ mData->invMassScale.angular0 = invInertiaScale;
+ mPxConstraint->markDirty();
+ }
+
+ PxReal getInvInertiaScale0() const
+ {
+ return mData->invMassScale.angular0;
+ }
+
+ void setInvMassScale1(PxReal invMassScale)
+ {
+ PX_CHECK_AND_RETURN(PxIsFinite(invMassScale) && invMassScale>=0, "PxJoint::setInvMassScale1: scale must be non-negative");
+ mData->invMassScale.linear1 = invMassScale;
+ mPxConstraint->markDirty();
+ }
+
+ PxReal getInvMassScale1() const
+ {
+ return mData->invMassScale.linear1;
+ }
+
+ void setInvInertiaScale1(PxReal invInertiaScale)
+ {
+ PX_CHECK_AND_RETURN(PxIsFinite(invInertiaScale) && invInertiaScale>=0, "PxJoint::setInvInertiaScale: scale must be non-negative");
+ mData->invMassScale.angular1 = invInertiaScale;
+ mPxConstraint->markDirty();
+ }
+
+ PxReal getInvInertiaScale1() const
+ {
+ return mData->invMassScale.angular1;
+ }
+
+ const char* getName() const
+ {
+ return mName;
+ }
+
+ void setName(const char* name)
+ {
+ mName = name;
+ }
+
+ void onComShift(PxU32 actor)
+ {
+ mData->c2b[actor] = getCom(actor).transformInv(mLocalPose[actor]);
+ markDirty();
+ }
+
+ void onOriginShift(const PxVec3& shift)
+ {
+ PxRigidActor* a[2];
+ mPxConstraint->getActors(a[0], a[1]);
+
+ if (!a[0])
+ {
+ mLocalPose[0].p -= shift;
+ mData->c2b[0].p -= shift;
+ markDirty();
+ }
+ else if (!a[1])
+ {
+ mLocalPose[1].p -= shift;
+ mData->c2b[1].p -= shift;
+ markDirty();
+ }
+ }
+
+ void* prepareData()
+ {
+ return mData;
+ }
+
+ PxJoint* getPxJoint()
+ {
+ return this;
+ }
+
+ void* getExternalReference(PxU32& typeID)
+ {
+ typeID = PxConstraintExtIDs::eJOINT;
+ return static_cast<PxJoint*>( this );
+ }
+
+ PxConstraintConnector* getConnector()
+ {
+ return this;
+ }
+
+ PX_INLINE void setPxConstraint(PxConstraint* pxConstraint)
+ {
+ mPxConstraint = pxConstraint;
+ }
+
+ PX_INLINE PxConstraint* getPxConstraint()
+ {
+ return mPxConstraint;
+ }
+
+ PX_INLINE const PxConstraint* getPxConstraint() const
+ {
+ return mPxConstraint;
+ }
+
+ void release()
+ {
+ mPxConstraint->release();
+ }
+
+ PxBase* getSerializable()
+ {
+ return this;
+ }
+
+ void onConstraintRelease()
+ {
+ PX_FREE_AND_RESET(mData);
+ delete this;
+ }
+
+ PxScene* getScene() const
+ {
+ return mPxConstraint ? mPxConstraint->getScene() : NULL;
+ }
+
+ private:
+ PxConstraint* getConstraint() const { return mPxConstraint; }
+
+ protected:
+
+ PxTransform getCom(PxU32 index) const
+ {
+ PxRigidActor* a[2];
+ mPxConstraint->getActors(a[0],a[1]);
+ return getCom(a[index]);
+ }
+
+ PxTransform getCom(PxRigidActor* actor) const
+ {
+ if (!actor)
+ return PxTransform(PxIdentity);
+ else if (actor->getType() == PxActorType::eRIGID_DYNAMIC || actor->getType() == PxActorType::eARTICULATION_LINK)
+ return static_cast<PxRigidBody*>(actor)->getCMassLocalPose();
+ else
+ {
+ PX_ASSERT(actor->getType() == PxActorType::eRIGID_STATIC);
+ return static_cast<PxRigidStatic*>(actor)->getGlobalPose().getInverse();
+ }
+ }
+
+ void initCommonData(JointData& data,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ {
+ mLocalPose[0] = localFrame0.getNormalized();
+ mLocalPose[1] = localFrame1.getNormalized();
+ data.c2b[0] = getCom(actor0).transformInv(localFrame0);
+ data.c2b[1] = getCom(actor1).transformInv(localFrame1);
+ data.invMassScale.linear0 = 1.0f;
+ data.invMassScale.angular0 = 1.0f;
+ data.invMassScale.linear1 = 1.0f;
+ data.invMassScale.angular1 = 1.0f;
+ }
+
+
+ Joint(PxType concreteType, PxBaseFlags baseFlags)
+ : Base(concreteType, baseFlags)
+ , mName(NULL)
+ , mPxConstraint(0)
+ {
+ Base::userData = NULL;
+ }
+
+
+ void markDirty()
+ {
+ mPxConstraint->markDirty();
+ }
+
+ virtual const void* getConstantBlock() const { return mData; }
+
+ const char* mName;
+ PxTransform mLocalPose[2];
+ PxConstraint* mPxConstraint;
+ JointData* mData;
+ };
+
+} // namespace Ext
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtJointMetaDataExtensions.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtJointMetaDataExtensions.h
new file mode 100644
index 00000000..f3d730fc
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtJointMetaDataExtensions.h
@@ -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.
+
+#ifndef EXT_JOINT_META_DATA_EXTENSIONS_H
+#define EXT_JOINT_META_DATA_EXTENSIONS_H
+#include "PvdMetaDataExtensions.h"
+
+namespace physx
+{
+
+namespace pvdsdk
+{
+
+
+struct PxExtensionPvdOnlyProperties
+{
+ enum Enum
+ {
+ FirstProp = PxExtensionsPropertyInfoName::LastPxPropertyInfoName,
+ DEFINE_ENUM_RANGE( PxJoint_Actors, 2 ),
+ DEFINE_ENUM_RANGE( PxJoint_BreakForce, 2 ),
+ DEFINE_ENUM_RANGE( PxD6Joint_DriveVelocity, 2 ),
+ DEFINE_ENUM_RANGE( PxD6Joint_Motion, PxD6Axis::eCOUNT ),
+ DEFINE_ENUM_RANGE( PxD6Joint_Drive, PxD6Drive::eCOUNT * ( PxExtensionsPropertyInfoName::PxD6JointDrive_PropertiesStop - PxExtensionsPropertyInfoName::PxD6JointDrive_PropertiesStart ) ),
+ DEFINE_ENUM_RANGE( PxD6Joint_LinearLimit, 100 ),
+ DEFINE_ENUM_RANGE( PxD6Joint_SwingLimit, 100 ),
+ DEFINE_ENUM_RANGE( PxD6Joint_TwistLimit, 100 ),
+ DEFINE_ENUM_RANGE( PxPrismaticJoint_Limit, 100 ),
+ DEFINE_ENUM_RANGE( PxRevoluteJoint_Limit, 100 ),
+ DEFINE_ENUM_RANGE( PxSphericalJoint_LimitCone, 100 ),
+ DEFINE_ENUM_RANGE( PxJoint_LocalPose, 2 )
+ };
+};
+
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtMetaData.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtMetaData.cpp
new file mode 100644
index 00000000..4b1ff97a
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtMetaData.cpp
@@ -0,0 +1,447 @@
+// 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 "PxJoint.h"
+#include "ExtJoint.h"
+#include "ExtD6Joint.h"
+#include "ExtFixedJoint.h"
+#include "ExtSphericalJoint.h"
+#include "ExtDistanceJoint.h"
+#include "ExtSphericalJoint.h"
+#include "ExtRevoluteJoint.h"
+#include "ExtPrismaticJoint.h"
+#include "serialization/SnSerializationRegistry.h"
+#include "serialization/Binary/SnSerializationContext.h"
+
+using namespace physx;
+using namespace Cm;
+using namespace Ext;
+
+///////////////////////////////////////////////////////////////////////////////
+
+
+
+
+static void getBinaryMetaData_JointData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, JointData)
+
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, JointData, PxTransform, c2b, 0)
+#ifdef EXPLICIT_PADDING_METADATA
+ PX_DEF_BIN_METADATA_ITEM(stream, JointData, PxU32, paddingFromFlags, PxMetaDataFlag::ePADDING)
+#endif
+ PX_DEF_BIN_METADATA_ITEM(stream, JointData, PxConstraintInvMassScale, invMassScale, 0)
+}
+
+static void getBinaryMetaData_PxD6JointDrive(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxD6JointDriveFlags, PxU32)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, PxD6JointDrive)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxD6JointDrive, PxReal, stiffness, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxD6JointDrive, PxReal, damping, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxD6JointDrive, PxReal, forceLimit, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxD6JointDrive, PxD6JointDriveFlags, flags, 0)
+}
+
+static void getBinaryMetaData_PxJointLimitParameters(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxJointLimitParameters)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitParameters, PxReal, restitution, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitParameters, PxReal, bounceThreshold, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitParameters, PxReal, stiffness, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitParameters, PxReal, damping, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitParameters, PxReal, contactDistance, 0)
+}
+
+static void getBinaryMetaData_PxJointLinearLimit(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxJointLinearLimit)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, PxJointLinearLimit, PxJointLimitParameters)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointLinearLimit, PxReal, value, 0)
+}
+
+static void getBinaryMetaData_PxJointLinearLimitPair(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxJointLinearLimitPair)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, PxJointLinearLimitPair, PxJointLimitParameters)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointLinearLimitPair, PxReal, upper, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointLinearLimitPair, PxReal, lower, 0)
+}
+
+static void getBinaryMetaData_PxJointAngularLimitPair(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxJointAngularLimitPair)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, PxJointAngularLimitPair, PxJointLimitParameters)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointAngularLimitPair, PxReal, upper, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointAngularLimitPair, PxReal, lower, 0)
+}
+
+
+static void getBinaryMetaData_PxJointLimitCone(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, PxJointLimitCone)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, PxJointLimitCone, PxJointLimitParameters)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitCone, PxReal, yAngle, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJointLimitCone, PxReal, zAngle, 0)
+}
+
+void PxJoint::getBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_VCLASS(stream, PxJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, PxJoint, PxBase)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, PxJoint, void, userData, PxMetaDataFlag::ePTR)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void getBinaryMetaData_RevoluteJointData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxRevoluteJointFlags, PxU16)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, RevoluteJointData)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, RevoluteJointData, JointData)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, driveVelocity, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, driveForceLimit, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, driveGearRatio, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxJointAngularLimitPair,limit, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, tqHigh, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, tqLow, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, tqPad, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, projectionLinearTolerance, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxReal, projectionAngularTolerance, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxRevoluteJointFlags, jointFlags, 0)
+#ifdef EXPLICIT_PADDING_METADATA
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJointData, PxU16, paddingFromFlags, PxMetaDataFlag::ePADDING)
+#endif
+}
+
+void RevoluteJoint::getBinaryMetaData(PxOutputStream& stream)
+{
+ getBinaryMetaData_RevoluteJointData(stream);
+
+ PX_DEF_BIN_METADATA_VCLASS(stream, RevoluteJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, RevoluteJoint, PxJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, RevoluteJoint, PxConstraintConnector)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJoint, char, mName, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, RevoluteJoint, PxTransform, mLocalPose, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJoint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, RevoluteJoint, JointData, mData, PxMetaDataFlag::ePTR)
+
+ //------ Extra-data ------
+
+ PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, RevoluteJoint, RevoluteJointData, mData, PX_SERIAL_ALIGN)
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, RevoluteJoint, mName, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void getBinaryMetaData_SphericalJointData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxSphericalJointFlags, PxU16)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, SphericalJointData)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, SphericalJointData, JointData)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxJointLimitCone, limit, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxReal, tanQYLimit, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxReal, tanQZLimit, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxReal, tanQPad, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxReal, projectionLinearTolerance, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxSphericalJointFlags, jointFlags, 0)
+#ifdef EXPLICIT_PADDING_METADATA
+ PX_DEF_BIN_METADATA_ITEM(stream, SphericalJointData, PxU16, paddingFromFlags, PxMetaDataFlag::ePADDING)
+#endif
+}
+
+void SphericalJoint::getBinaryMetaData(PxOutputStream& stream)
+{
+ getBinaryMetaData_SphericalJointData(stream);
+
+ PX_DEF_BIN_METADATA_VCLASS(stream, SphericalJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, SphericalJoint, PxJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, SphericalJoint, PxConstraintConnector)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, SphericalJoint, char, mName, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, SphericalJoint, PxTransform, mLocalPose, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, SphericalJoint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, SphericalJoint, JointData, mData, PxMetaDataFlag::ePTR)
+
+ //------ Extra-data ------
+
+ PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, SphericalJoint, SphericalJointData, mData, PX_SERIAL_ALIGN)
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, SphericalJoint, mName, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void getBinaryMetaData_DistanceJointData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxDistanceJointFlags, PxU16)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, DistanceJointData)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, DistanceJointData, JointData)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxReal, minDistance, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxReal, maxDistance, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxReal, tolerance, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxReal, stiffness, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxReal, damping, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxDistanceJointFlags, jointFlags, 0)
+#ifdef EXPLICIT_PADDING_METADATA
+ PX_DEF_BIN_METADATA_ITEM(stream, DistanceJointData, PxU16, paddingFromFlags, PxMetaDataFlag::ePADDING)
+#endif
+}
+
+void DistanceJoint::getBinaryMetaData(PxOutputStream& stream)
+{
+ getBinaryMetaData_DistanceJointData(stream);
+
+ PX_DEF_BIN_METADATA_VCLASS(stream, DistanceJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, DistanceJoint, PxJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, DistanceJoint, PxConstraintConnector)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, DistanceJoint, char, mName, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, DistanceJoint, PxTransform, mLocalPose, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, DistanceJoint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, DistanceJoint, JointData, mData, PxMetaDataFlag::ePTR)
+
+ //------ Extra-data ------
+
+ PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, DistanceJoint, DistanceJointData, mData, PX_SERIAL_ALIGN)
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, DistanceJoint, mName, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void getBinaryMetaData_D6JointData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxD6Motion::Enum, PxU32)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, D6JointData)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, D6JointData, JointData)
+
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, D6JointData, PxD6Motion::Enum, motion, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxJointLinearLimit, linearLimit, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxJointLimitCone, swingLimit, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxJointAngularLimitPair, twistLimit, 0)
+
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, D6JointData, PxD6JointDrive, drive, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxTransform, drivePosition, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxVec3, driveLinearVelocity, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxVec3, driveAngularVelocity, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxU32, locked, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxU32, limited, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxU32, driving, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, thSwingY, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, thSwingZ, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, thSwingPad, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqSwingY, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqSwingZ, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqSwingPad, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqTwistLow, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqTwistHigh, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, tqTwistPad, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, linearMinDist, 0)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, projectionLinearTolerance, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6JointData, PxReal, projectionAngularTolerance, 0)
+}
+
+void D6Joint::getBinaryMetaData(PxOutputStream& stream)
+{
+ getBinaryMetaData_D6JointData(stream);
+
+ PX_DEF_BIN_METADATA_VCLASS(stream, D6Joint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, D6Joint, PxJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, D6Joint, PxConstraintConnector)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, D6Joint, char, mName, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, D6Joint, PxTransform, mLocalPose, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6Joint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6Joint, JointData, mData, PxMetaDataFlag::ePTR)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, D6Joint, bool, mRecomputeMotion, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, D6Joint, bool, mRecomputeLimits, 0)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, D6Joint, bool, mPadding, PxMetaDataFlag::ePADDING)
+
+ //------ Extra-data ------
+
+ PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, D6Joint, D6JointData, mData, PX_SERIAL_ALIGN)
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, D6Joint, mName, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void getBinaryMetaData_PrismaticJointData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxPrismaticJointFlags, PxU16)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, PrismaticJointData)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, PrismaticJointData, JointData)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJointData, PxJointLinearLimitPair, limit, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJointData, PxReal, projectionLinearTolerance, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJointData, PxReal, projectionAngularTolerance, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJointData, PxPrismaticJointFlags, jointFlags, 0)
+#ifdef EXPLICIT_PADDING_METADATA
+ PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJointData, PxU16, paddingFromFlags, PxMetaDataFlag::ePADDING)
+#endif
+}
+
+void PrismaticJoint::getBinaryMetaData(PxOutputStream& stream)
+{
+ getBinaryMetaData_PrismaticJointData(stream);
+
+ PX_DEF_BIN_METADATA_VCLASS(stream, PrismaticJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, PrismaticJoint, PxJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, PrismaticJoint, PxConstraintConnector)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJoint, char, mName, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, PrismaticJoint, PxTransform, mLocalPose, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJoint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, PrismaticJoint, JointData, mData, PxMetaDataFlag::ePTR)
+
+ //------ Extra-data ------
+
+ PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, PrismaticJoint, PrismaticJointData, mData, PX_SERIAL_ALIGN)
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, PrismaticJoint, mName, 0)
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+static void getBinaryMetaData_FixedJointData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_CLASS(stream, FixedJointData)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, FixedJointData, JointData)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, FixedJointData, PxReal, projectionLinearTolerance, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, FixedJointData, PxReal, projectionAngularTolerance, 0)
+}
+
+void FixedJoint::getBinaryMetaData(PxOutputStream& stream)
+{
+ getBinaryMetaData_FixedJointData(stream);
+
+ PX_DEF_BIN_METADATA_VCLASS(stream, FixedJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, FixedJoint, PxJoint)
+ PX_DEF_BIN_METADATA_BASE_CLASS(stream, FixedJoint, PxConstraintConnector)
+
+ PX_DEF_BIN_METADATA_ITEM(stream, FixedJoint, char, mName, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEMS_AUTO(stream, FixedJoint, PxTransform, mLocalPose, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, FixedJoint, PxConstraint, mPxConstraint, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, FixedJoint, JointData, mData, PxMetaDataFlag::ePTR)
+
+ //------ Extra-data ------
+
+ PX_DEF_BIN_METADATA_EXTRA_ITEM(stream, FixedJoint, FixedJointData, mData, PX_SERIAL_ALIGN)
+ PX_DEF_BIN_METADATA_EXTRA_NAME(stream, FixedJoint, mName, 0)
+}
+
+
+void getBinaryMetaData_SerializationContext(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, PxSerialObjectId, PxU64)
+ PX_DEF_BIN_METADATA_TYPEDEF(stream, SerialObjectIndex, PxU32)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, Sn::ManifestEntry)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::ManifestEntry, PxU32, offset, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::ManifestEntry, PxType, type, 0)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, Sn::ImportReference)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::ImportReference, PxSerialObjectId, id, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::ImportReference, PxType, type, 0)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, Sn::ExportReference)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::ExportReference, PxSerialObjectId, id, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::ExportReference, SerialObjectIndex, objIndex, 0)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, Sn::InternalReferencePtr)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferencePtr, void, reference, PxMetaDataFlag::ePTR)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferencePtr, PxU32, kind, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferencePtr, SerialObjectIndex, objIndex, 0)
+
+ PX_DEF_BIN_METADATA_CLASS(stream, Sn::InternalReferenceIdx)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferenceIdx, PxU32, reference, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferenceIdx, PxU32, kind, 0)
+ PX_DEF_BIN_METADATA_ITEM(stream, Sn::InternalReferenceIdx, SerialObjectIndex, objIndex, 0)
+}
+
+namespace physx
+{
+namespace Ext
+{
+void GetExtensionsBinaryMetaData(PxOutputStream& stream)
+{
+ PX_DEF_BIN_METADATA_VCLASS(stream,PxConstraintConnector)
+
+ getBinaryMetaData_JointData(stream);
+ getBinaryMetaData_PxD6JointDrive(stream);
+ getBinaryMetaData_PxJointLimitParameters(stream);
+ getBinaryMetaData_PxJointLimitCone(stream);
+ getBinaryMetaData_PxJointLinearLimit(stream);
+ getBinaryMetaData_PxJointLinearLimitPair(stream);
+ getBinaryMetaData_PxJointAngularLimitPair(stream);
+
+ PxJoint::getBinaryMetaData(stream);
+ RevoluteJoint::getBinaryMetaData(stream);
+ SphericalJoint::getBinaryMetaData(stream);
+ DistanceJoint::getBinaryMetaData(stream);
+ D6Joint::getBinaryMetaData(stream);
+ PrismaticJoint::getBinaryMetaData(stream);
+ FixedJoint::getBinaryMetaData(stream);
+
+ getBinaryMetaData_SerializationContext(stream);
+}
+
+}
+}
+
+///////////////////////////////////////////////////////////////////////////////
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtParticleExt.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtParticleExt.cpp
new file mode 100644
index 00000000..8f6ee803
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtParticleExt.cpp
@@ -0,0 +1,356 @@
+// 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/PxMemory.h"
+#include "foundation/PxBounds3.h"
+
+#include "PxParticleExt.h"
+#include "PsUserAllocated.h"
+#include "CmPhysXCommon.h"
+#include "PsArray.h"
+#include "PsHash.h"
+#include "PsBitUtils.h"
+#include "PsMathUtils.h"
+#include "PsIntrinsics.h"
+#include "PsFoundation.h"
+
+using namespace physx;
+
+//----------------------------------------------------------------------------//
+
+static const PxU32 sInvalidIndex = 0xffffffff;
+
+//----------------------------------------------------------------------------//
+
+struct CellCoords
+{
+ //! Set grid cell coordinates based on a point in space and a scaling factor
+ PX_INLINE void set(const PxVec3& realVec, PxReal scale)
+ {
+ x = static_cast<PxI16>(Ps::floor(realVec.x * scale));
+ y = static_cast<PxI16>(Ps::floor(realVec.y * scale));
+ z = static_cast<PxI16>(Ps::floor(realVec.z * scale));
+ }
+
+ PX_INLINE bool operator==(const CellCoords& v) const
+ {
+ return ((x == v.x) && (y == v.y) && (z == v.z));
+ }
+
+ PxI16 x;
+ PxI16 y;
+ PxI16 z;
+};
+
+//----------------------------------------------------------------------------//
+
+struct Cell
+{
+ CellCoords coords;
+ PxBounds3 aabb;
+ PxU32 start;
+ PxU32 size;
+};
+
+//----------------------------------------------------------------------------//
+
+PxU32 PX_INLINE hashFunction(const CellCoords& coords)
+{
+ PxU32 mix = PxU32(coords.x) + 101 * PxU32(coords.y) + 7919 * PxU32(coords.z);
+ PxU32 hash = Ps::hash(mix);
+ return hash;
+}
+
+//----------------------------------------------------------------------------//
+
+PxU32 PX_INLINE getEntry(const CellCoords& coords, const PxU32 hashSize, const Cell* cells)
+{
+ PxU32 hash = hashFunction(coords);
+ PxU32 index = hash & (hashSize - 1);
+ for (;;)
+ {
+ const Cell& cell = cells[index];
+ if (cell.size == sInvalidIndex || cell.coords == coords)
+ break;
+ index = (index + 1) & (hashSize - 1);
+ }
+ return index;
+}
+
+//----------------------------------------------------------------------------//
+
+PxU32 PxParticleExt::buildBoundsHash(PxU32* sortedParticleIndices,
+ ParticleBounds* particleBounds,
+ const PxStrideIterator<const PxVec3>& positionBuffer,
+ const PxU32 validParticleRange,
+ const PxU32* validParticleBitmap,
+ const PxU32 hashSize,
+ const PxU32 maxBounds,
+ const PxReal gridSpacing)
+{
+ // test if hash size is a multiple of 2
+ PX_ASSERT((((hashSize - 1) ^ hashSize) + 1) == (2 * hashSize));
+ PX_ASSERT(maxBounds <= hashSize);
+
+ PxReal cellSizeInv = 1.0f / gridSpacing;
+
+ Ps::Array<PxU32> particleToCellMap PX_DEBUG_EXP("buildBoundsHashCellMap");
+ particleToCellMap.resize(validParticleRange);
+
+ // initialize cells
+ Ps::Array<Cell> cells PX_DEBUG_EXP("buildBoundsCells");
+ cells.resize(hashSize);
+ PxMemSet(cells.begin(), sInvalidIndex, sizeof(Cell) * hashSize);
+
+ // count number of particles per cell
+ PxU32 entryCounter = 0;
+
+ if (validParticleRange > 0)
+ {
+ for (PxU32 w = 0; w <= (validParticleRange-1) >> 5; w++)
+ for (PxU32 b = validParticleBitmap[w]; b; b &= b-1)
+ {
+ PxU32 index = (w<<5|Ps::lowestSetBit(b));
+ const PxVec3& position = positionBuffer[index];
+
+ PxU32& cellIndex = particleToCellMap[index];
+ cellIndex = sInvalidIndex; // initialize to invalid in case we reach maxBounds
+ if (entryCounter < maxBounds)
+ {
+ CellCoords particleCoords;
+ particleCoords.set(position, cellSizeInv);
+ cellIndex = getEntry(particleCoords, hashSize, cells.begin());
+ PX_ASSERT(cellIndex != sInvalidIndex);
+
+ Cell& cell = cells[cellIndex];
+ if (cell.size == sInvalidIndex)
+ {
+ // this is the first particle in this cell
+ cell.coords = particleCoords;
+ cell.aabb = PxBounds3(position, position);
+ cell.size = 1;
+ ++entryCounter;
+ }
+ else
+ {
+ // the cell is already occupied
+ cell.aabb.include(position);
+ ++cell.size;
+ }
+ }
+ }
+ }
+
+
+ // accumulate start indices from cell size histogram and write to the user's particleBounds buffer
+ PxU32 numBounds = 0;
+ for (PxU32 i = 0, counter = 0; i < cells.size(); i++)
+ {
+ Cell& cell = cells[i];
+ if (cell.size != sInvalidIndex)
+ {
+ cell.start = counter;
+ counter += cell.size;
+
+ PxParticleExt::ParticleBounds& cellBounds = particleBounds[numBounds++];
+ PX_ASSERT(cell.aabb.isValid());
+ cellBounds.bounds = cell.aabb;
+ cellBounds.firstParticle = cell.start;
+ cellBounds.numParticles = cell.size;
+
+ cell.size = 0;
+ }
+ }
+
+ // sort output particle indices by cell
+ if (validParticleRange > 0)
+ {
+ for (PxU32 w = 0; w <= (validParticleRange-1) >> 5; w++)
+ for (PxU32 b = validParticleBitmap[w]; b; b &= b-1)
+ {
+ PxU32 index = (w<<5|Ps::lowestSetBit(b));
+ PxU32 cellIndex = particleToCellMap[index];
+ if (cellIndex != sInvalidIndex)
+ {
+ Cell& cell = cells[cellIndex];
+ PX_ASSERT(cell.start != sInvalidIndex && cell.size != sInvalidIndex);
+ sortedParticleIndices[cell.start + cell.size] = index;
+ ++cell.size;
+ }
+ }
+ }
+
+ return numBounds;
+}
+
+//----------------------------------------------------------------------------//
+
+class InternalIndexPool : public PxParticleExt::IndexPool, public Ps::UserAllocated
+{
+public:
+ InternalIndexPool(PxU32 maxParticles);
+ InternalIndexPool(PxU32 maxParticles, PxU32 validParticleRange, const PxU32* validParticleBitmap);
+ virtual ~InternalIndexPool() {}
+
+ virtual PxU32 allocateIndices(PxU32 num, const PxStrideIterator<PxU32>& indexBuffer);
+ virtual void freeIndices(PxU32 num, const PxStrideIterator<const PxU32>& indexBuffer);
+ virtual void freeIndices();
+ virtual void release();
+
+private:
+ PxU32 mIndexCount;
+ Ps::Array<PxU32> mFreeList;
+};
+
+InternalIndexPool::InternalIndexPool(PxU32 maxParticles) : mIndexCount(0), mFreeList(PX_DEBUG_EXP("InternalIndexPool:mFreeList"))
+{
+ mFreeList.reserve(maxParticles);
+}
+
+InternalIndexPool::InternalIndexPool(PxU32 maxParticles, PxU32 validParticleRange, const PxU32* validParticleBitmap) : mIndexCount(0), mFreeList()
+{
+ mFreeList.reserve(maxParticles);
+ PX_ASSERT(validParticleRange <= maxParticles);
+
+ mIndexCount = validParticleRange;
+
+ if (validParticleRange > 0)
+ {
+ //find all the free indices in the valid range (for words fitting into validParticleRangle)
+ for (PxU32 w = 0; w < (validParticleRange-1) >> 5; w++)
+ {
+ for (PxU32 b = ~validParticleBitmap[w]; b; b &= b-1)
+ {
+ PxU32 invalidIndex = (w<<5|Ps::lowestSetBit(b));
+ PX_ASSERT(invalidIndex < validParticleRange);
+ mFreeList.pushBack(invalidIndex);
+ }
+ }
+
+ //for the last word, we need to make sure the index is in the valid range
+ {
+ PxU32 w = (validParticleRange-1) >> 5;
+ for (PxU32 b = ~validParticleBitmap[w]; b; b &= b-1)
+ {
+ PxU32 invalidIndex = (w<<5|Ps::lowestSetBit(b));
+ if (invalidIndex >= validParticleRange)
+ break;
+
+ mFreeList.pushBack(invalidIndex);
+ }
+ }
+ }
+}
+
+PxU32 InternalIndexPool::allocateIndices(PxU32 num, const PxStrideIterator<PxU32>& indexBuffer)
+{
+ PxU32 numAllocated = mIndexCount - mFreeList.size();
+ PxU32 numFree = mFreeList.capacity() - numAllocated;
+ PxU32 numAccepted = PxMin(num, numFree);
+
+ if (numAccepted < num)
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxParticleExt::IndexPool::allocateIndices: Not all requested indices allocated; maximum reached.");
+
+ PxU32 numAdded = 0;
+
+ PxU32 numToAddFromFreeList = PxMin(numAccepted, mFreeList.size());
+ PxU32 numToAddFromFullBlock = numAccepted - numToAddFromFreeList;
+
+ //add from free list
+ while (numToAddFromFreeList > 0)
+ {
+ indexBuffer[numAdded++] = mFreeList.popBack();
+ numToAddFromFreeList--;
+ }
+
+ //add from full block
+ while (numToAddFromFullBlock > 0)
+ {
+ indexBuffer[numAdded++] = mIndexCount++;
+ numToAddFromFullBlock--;
+ }
+
+ PX_ASSERT(numAdded == numAccepted);
+ return numAccepted;
+}
+
+void InternalIndexPool::freeIndices(PxU32 num, const PxStrideIterator<const PxU32>& indexBuffer)
+{
+ PxU32 numAllocated = mIndexCount - mFreeList.size();
+ if (num > numAllocated)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxParticleExt::IndexPool::freeIndices: Provided number of indices exceeds number of actually allocated indices. Call faild.");
+ return;
+ }
+
+#ifdef PX_CHECK
+ for (PxU32 i = 0; i < num; ++i)
+ {
+ if (indexBuffer[i] < mIndexCount)
+ continue;
+
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxParticleExt::IndexPool::freeIndices: Provided indices which where not actually allocated before. Call failed.");
+ return;
+ }
+#endif
+
+ for (PxU32 i = 0; i < num; ++i)
+ mFreeList.pushBack(indexBuffer[i]);
+}
+
+void InternalIndexPool::freeIndices()
+{
+ mIndexCount = 0;
+ mFreeList.clear();
+}
+
+void InternalIndexPool::release()
+{
+ PX_DELETE(this);
+}
+
+//----------------------------------------------------------------------------//
+
+PxParticleExt::IndexPool* PxParticleExt::createIndexPool(PxU32 maxParticles)
+{
+ return PX_NEW(InternalIndexPool)(maxParticles);
+}
+
+//----------------------------------------------------------------------------//
+
+PxParticleExt::IndexPool* PxParticleExt::createIndexPool(PxU32 maxParticles, PxU32 validParticleRange, const PxU32* validParticleBitmap)
+{
+ return PX_NEW(InternalIndexPool)(maxParticles, validParticleRange, validParticleBitmap);
+}
+
+//----------------------------------------------------------------------------//
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPlatform.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtPlatform.h
new file mode 100644
index 00000000..237ff1e3
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPlatform.h
@@ -0,0 +1,39 @@
+// 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 PLATFORM_H
+#define PLATFORM_H
+
+#include <assert.h>
+#include "foundation/Px.h"
+#include "PsThread.h"
+#include "CmPhysXCommon.h"
+
+#endif \ No newline at end of file
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.cpp
new file mode 100644
index 00000000..418fecf3
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.cpp
@@ -0,0 +1,219 @@
+// 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 "ExtPrismaticJoint.h"
+#include "ExtConstraintHelper.h"
+#include "CmRenderOutput.h"
+#include "CmVisualization.h"
+
+#include "common/PxSerialFramework.h"
+
+using namespace physx;
+using namespace Ext;
+
+PxPrismaticJoint* physx::PxPrismaticJointCreate(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+{
+ PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxPrismaticJointCreate: local frame 0 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxPrismaticJointCreate: local frame 1 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxPrismaticJointCreate: at least one actor must be dynamic");
+ PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxPrismaticJointCreate: actors must be different");
+
+ PrismaticJoint* j;
+ PX_NEW_SERIALIZED(j,PrismaticJoint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1);
+
+ if(j->attach(physics, actor0, actor1))
+ return j;
+
+ PX_DELETE(j);
+ return NULL;
+}
+
+void PrismaticJoint::setProjectionAngularTolerance(PxReal tolerance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0 && tolerance <= PxPi, "PxPrismaticJoint::setProjectionAngularTolerance: invalid parameter");
+ data().projectionAngularTolerance = tolerance;
+ markDirty();
+}
+
+PxReal PrismaticJoint::getProjectionAngularTolerance() const
+{
+ return data().projectionAngularTolerance;
+}
+
+void PrismaticJoint::setProjectionLinearTolerance(PxReal tolerance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0, "PxPrismaticJoint::setProjectionLinearTolerance: invalid parameter");
+ data().projectionLinearTolerance = tolerance;
+ markDirty();
+}
+
+PxReal PrismaticJoint::getProjectionLinearTolerance() const
+{
+ return data().projectionLinearTolerance;
+}
+
+PxPrismaticJointFlags PrismaticJoint::getPrismaticJointFlags(void) const
+{
+ return data().jointFlags;
+}
+
+void PrismaticJoint::setPrismaticJointFlags(PxPrismaticJointFlags flags)
+{
+ data().jointFlags = flags; markDirty();
+}
+
+void PrismaticJoint::setPrismaticJointFlag(PxPrismaticJointFlag::Enum flag, bool value)
+{
+ if(value)
+ data().jointFlags |= flag;
+ else
+ data().jointFlags &= ~flag;
+ markDirty();
+}
+
+
+PxJointLinearLimitPair PrismaticJoint::getLimit() const
+{
+ return data().limit;
+}
+
+void PrismaticJoint::setLimit(const PxJointLinearLimitPair& limit)
+{
+ PX_CHECK_AND_RETURN(limit.isValid(), "PxPrismaticJoint::setLimit: invalid parameter");
+ data().limit = limit;
+ markDirty();
+}
+
+
+
+namespace
+{
+
+
+void PrismaticJointVisualize(PxConstraintVisualizer& viz,
+ const void* constantBlock,
+ const PxTransform& body0Transform,
+ const PxTransform& body1Transform,
+ PxU32 /*flags*/)
+{
+ const PrismaticJointData& data = *reinterpret_cast<const PrismaticJointData*>(constantBlock);
+
+ const PxTransform& t0 = body0Transform * data.c2b[0];
+ const PxTransform& t1 = body1Transform * data.c2b[1];
+
+ viz.visualizeJointFrames(t0, t1);
+
+ PxVec3 axis = t0.rotate(PxVec3(1.f,0,0));
+ PxReal ordinate = axis.dot(t0.transformInv(t1.p)-t0.p);
+
+ if(data.jointFlags & PxPrismaticJointFlag::eLIMIT_ENABLED)
+ {
+ viz.visualizeLinearLimit(t0, t1, data.limit.lower, ordinate < data.limit.lower + data.limit.contactDistance);
+ viz.visualizeLinearLimit(t0, t1, data.limit.upper, ordinate > data.limit.upper - data.limit.contactDistance);
+ }
+
+}
+
+
+
+void PrismaticJointProject(const void* constantBlock,
+ PxTransform& bodyAToWorld,
+ PxTransform& bodyBToWorld,
+ bool projectToA)
+{
+ using namespace joint;
+
+ const PrismaticJointData& data = *reinterpret_cast<const PrismaticJointData*>(constantBlock);
+
+ PxTransform cA2w, cB2w, cB2cA, projected;
+ computeDerived(data, bodyAToWorld, bodyBToWorld, cA2w, cB2w, cB2cA);
+
+ PxVec3 v(0,cB2cA.p.y,cB2cA.p.z);
+ bool linearTrunc, angularTrunc;
+ projected.p = truncateLinear(v, data.projectionLinearTolerance, linearTrunc);
+ projected.q = truncateAngular(cB2cA.q, PxSin(data.projectionAngularTolerance/2), PxCos(data.projectionAngularTolerance/2), angularTrunc);
+
+ if(linearTrunc || angularTrunc)
+ {
+ projected.p.x = cB2cA.p.x;
+ projectTransforms(bodyAToWorld, bodyBToWorld, cA2w, cB2w, projected, data, projectToA);
+ }
+}
+}
+
+bool Ext::PrismaticJoint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1)
+{
+ mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(PrismaticJointData));
+ return mPxConstraint!=NULL;
+}
+
+void PrismaticJoint::exportExtraData(PxSerializationContext& stream)
+{
+ if(mData)
+ {
+ stream.alignData(PX_SERIAL_ALIGN);
+ stream.writeData(mData, sizeof(PrismaticJointData));
+ }
+ stream.writeName(mName);
+}
+
+void PrismaticJoint::importExtraData(PxDeserializationContext& context)
+{
+ if(mData)
+ mData = context.readExtraData<PrismaticJointData, PX_SERIAL_ALIGN>();
+ context.readName(mName);
+}
+
+void PrismaticJoint::resolveReferences(PxDeserializationContext& context)
+{
+ setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders));
+}
+
+PrismaticJoint* PrismaticJoint::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ PrismaticJoint* obj = new (address) PrismaticJoint(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(PrismaticJoint);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+
+// global function to share the joint shaders with API capture
+const PxConstraintShaderTable* Ext::GetPrismaticJointShaderTable()
+{
+ return &PrismaticJoint::getConstraintShaderTable();
+}
+
+//~PX_SERIALIZATION
+PxConstraintShaderTable Ext::PrismaticJoint::sShaders = { Ext::PrismaticJointSolverPrep, PrismaticJointProject, PrismaticJointVisualize, PxConstraintFlag::Enum(0) };
+
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.h
new file mode 100644
index 00000000..79ce5f93
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJoint.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 NP_PRISMATICJOINTCONSTRAINT_H
+#define NP_PRISMATICJOINTCONSTRAINT_H
+
+#include "ExtJoint.h"
+#include "PxPrismaticJoint.h"
+#include "PxTolerancesScale.h"
+#include "CmUtils.h"
+
+namespace physx
+{
+struct PxPrismaticJointGeneratedValues;
+namespace Ext
+{
+ struct PrismaticJointData : public JointData
+ {
+ //= 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.
+ //==================================================================================================
+
+ PxJointLinearLimitPair limit;
+ PxReal projectionLinearTolerance;
+ PxReal projectionAngularTolerance;
+
+ PxPrismaticJointFlags jointFlags;
+ // forestall compiler complaints about not being able to generate a constructor
+ private:
+ PrismaticJointData(const PxJointLinearLimitPair &pair):
+ limit(pair) {}
+ };
+
+ typedef Joint<PxPrismaticJoint, PxPrismaticJointGeneratedValues> PrismaticJointT;
+
+ class PrismaticJoint : public PrismaticJointT
+ {
+ //= 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
+ PrismaticJoint(PxBaseFlags baseFlags) : PrismaticJointT(baseFlags) {}
+ virtual void exportExtraData(PxSerializationContext& context);
+ void importExtraData(PxDeserializationContext& context);
+ void resolveReferences(PxDeserializationContext& context);
+ static PrismaticJoint* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ virtual ~PrismaticJoint()
+ {
+ if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY)
+ PX_FREE(mData);
+ }
+
+ PrismaticJoint(const PxTolerancesScale& scale,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ : PrismaticJointT(PxJointConcreteType::ePRISMATIC, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+ {
+ PrismaticJointData* data = reinterpret_cast<PrismaticJointData*>(PX_ALLOC(sizeof(PrismaticJointData), "PrismaticJointData"));
+ Cm::markSerializedMem(data, sizeof(PrismaticJointData));
+ mData = data;
+
+ data->limit = PxJointLinearLimitPair(scale, -PX_MAX_F32/3, PX_MAX_F32/3);
+ data->projectionLinearTolerance = 1e10f;
+ data->projectionAngularTolerance = PxPi;
+ data->jointFlags = PxPrismaticJointFlags();
+
+ initCommonData(*data, actor0, localFrame0, actor1, localFrame1);
+ }
+
+ PxReal getPosition() const { return getRelativeTransform().p.x; }
+ PxReal getVelocity() const { return getRelativeLinearVelocity().x; }
+
+
+ void setProjectionAngularTolerance(PxReal tolerance);
+ PxReal getProjectionAngularTolerance() const;
+
+ void setProjectionLinearTolerance(PxReal tolerance);
+ PxReal getProjectionLinearTolerance() const;
+
+ PxJointLinearLimitPair getLimit() const;
+ void setLimit(const PxJointLinearLimitPair& limit);
+
+ PxPrismaticJointFlags getPrismaticJointFlags(void) const;
+ void setPrismaticJointFlags(PxPrismaticJointFlags flags);
+ void setPrismaticJointFlag(PxPrismaticJointFlag::Enum flag, bool value);
+
+ bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1);
+
+ static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; }
+
+ virtual PxConstraintSolverPrep getPrep() const { return sShaders.solverPrep; }
+
+ private:
+ PX_FORCE_INLINE PrismaticJointData& data() const
+ {
+ return *static_cast<PrismaticJointData*>(mData);
+ }
+
+ static PxConstraintShaderTable sShaders;
+ };
+} // namespace Ext
+
+namespace Ext
+{
+ extern "C" PxU32 PrismaticJointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 maxConstraints,
+ PxConstraintInvMassScale& invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w);
+
+ // global function to share the joint shaders with API capture
+ extern "C" const PxConstraintShaderTable* GetPrismaticJointShaderTable();
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJointSolverPrep.cpp
new file mode 100644
index 00000000..64249545
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPrismaticJointSolverPrep.cpp
@@ -0,0 +1,81 @@
+// 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 "ExtPrismaticJoint.h"
+#include "ExtConstraintHelper.h"
+#include "CmRenderOutput.h"
+
+namespace physx
+{
+namespace Ext
+{
+ PxU32 PrismaticJointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 maxConstraints,
+ PxConstraintInvMassScale &invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w)
+ {
+ PX_UNUSED(maxConstraints);
+
+ const PrismaticJointData& data = *reinterpret_cast<const PrismaticJointData*>(constantBlock);
+ invMassScale = data.invMassScale;
+
+ PxTransform cA2w = bA2w.transform(data.c2b[0]);
+ PxTransform cB2w = bB2w.transform(data.c2b[1]);
+
+ bool limitEnabled = data.jointFlags & PxPrismaticJointFlag::eLIMIT_ENABLED;
+ const PxJointLinearLimitPair &limit = data.limit;
+ bool limitIsLocked = limitEnabled && limit.lower >= limit.upper;
+
+ PxVec3 bOriginInA = cA2w.transformInv(cB2w.p);
+
+ body0WorldOffset = cB2w.p-bA2w.p;
+ joint::ConstraintHelper ch(constraints,cB2w.p-bA2w.p, cB2w.p-bB2w.p);
+ ch.prepareLockedAxes(cA2w.q, cB2w.q, bOriginInA, limitIsLocked ? 7ul : 6ul, 7ul);
+
+ if(limitEnabled && !limitIsLocked)
+ {
+ PxVec3 axis = cA2w.rotate(PxVec3(1.f,0,0));
+ PxReal ordinate = bOriginInA.x;
+
+ ch.linearLimit(axis, ordinate, limit.upper, limit);
+ ch.linearLimit(-axis, -ordinate, -limit.lower, limit);
+ }
+
+ return ch.getCount();
+ }
+}//namespace
+
+}
+
+//~PX_SERIALIZATION
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.cpp
new file mode 100644
index 00000000..c6589a68
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.cpp
@@ -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.
+
+// suppress LNK4221
+#include "foundation/PxPreprocessor.h"
+PX_DUMMY_SYMBOL
+
+#if PX_SUPPORT_PVD
+#include "ExtPvd.h"
+#include "PxExtensionMetaDataObjects.h"
+
+#include "ExtD6Joint.h"
+#include "ExtFixedJoint.h"
+#include "ExtSphericalJoint.h"
+#include "ExtDistanceJoint.h"
+#include "ExtSphericalJoint.h"
+#include "ExtRevoluteJoint.h"
+#include "ExtPrismaticJoint.h"
+#include "ExtJointMetaDataExtensions.h"
+#include "PvdMetaDataPropertyVisitor.h"
+#include "PvdMetaDataDefineProperties.h"
+
+namespace physx
+{
+namespace Ext
+{
+ using namespace physx::Vd;
+
+ template<typename TObjType, typename TOperator>
+ inline void visitPvdInstanceProperties( TOperator inOperator )
+ {
+ PxClassInfoTraits<TObjType>().Info.visitInstanceProperties( makePvdPropertyFilter( inOperator ), 0 );
+ }
+
+ template<typename TObjType, typename TOperator>
+ inline void visitPvdProperties( TOperator inOperator )
+ {
+ PvdPropertyFilter<TOperator> theFilter( makePvdPropertyFilter( inOperator ) );
+ PxU32 thePropCount = PxClassInfoTraits<TObjType>().Info.visitBaseProperties( theFilter );
+ PxClassInfoTraits<TObjType>().Info.visitInstanceProperties( theFilter, thePropCount );
+ }
+
+ Pvd::PvdNameSpace::PvdNameSpace(physx::pvdsdk::PvdDataStream& conn, const char* /*name*/)
+ : mConnection(conn)
+ {
+ }
+
+ Pvd::PvdNameSpace::~PvdNameSpace()
+ {
+ }
+
+ void Pvd::releasePvdInstance(physx::pvdsdk::PvdDataStream& pvdConnection, const PxConstraint& c, const PxJoint& joint)
+ {
+ if(!pvdConnection.isConnected())
+ return;
+ //remove from scene and from any attached actors.
+ PxRigidActor* actor0, *actor1;
+ c.getActors( actor0, actor1 );
+ PxScene* scene = c.getScene();
+ if(scene) pvdConnection.removeObjectRef( scene, "Joints", &joint );
+ if ( actor0 && actor0->getScene() ) pvdConnection.removeObjectRef( actor0, "Joints", &joint );
+ if ( actor1 && actor1->getScene()) pvdConnection.removeObjectRef( actor1, "Joints", &joint );
+ pvdConnection.destroyInstance(&joint);
+ }
+
+ template<typename TObjType>
+ void registerProperties( PvdDataStream& inStream )
+ {
+ inStream.createClass<TObjType>();
+ PvdPropertyDefinitionHelper& theHelper( inStream.getPropertyDefinitionHelper() );
+ PvdClassInfoDefine theDefinitionObj( theHelper, getPvdNamespacedNameForType<TObjType>() );
+ visitPvdInstanceProperties<TObjType>( theDefinitionObj );
+ }
+
+ template<typename TObjType, typename TValueStructType>
+ void registerPropertiesAndValueStruct( PvdDataStream& inStream )
+ {
+ inStream.createClass<TObjType>();
+ inStream.deriveClass<PxJoint,TObjType>();
+ PvdPropertyDefinitionHelper& theHelper( inStream.getPropertyDefinitionHelper() );
+ {
+ PvdClassInfoDefine theDefinitionObj( theHelper, getPvdNamespacedNameForType<TObjType>() );
+ visitPvdInstanceProperties<TObjType>( theDefinitionObj );
+ }
+ {
+ PvdClassInfoValueStructDefine theDefinitionObj( theHelper );
+ visitPvdProperties<TObjType>( theDefinitionObj );
+ theHelper.addPropertyMessage<TObjType,TValueStructType>();
+ }
+ }
+
+ void Pvd::sendClassDescriptions(physx::pvdsdk::PvdDataStream& inStream)
+ {
+ if (inStream.isClassExist<PxJoint>())
+ return;
+
+ { //PxJoint
+ registerProperties<PxJoint>( inStream );
+ inStream.createProperty<PxJoint,ObjectRef>( "Parent", "parents" );
+ registerPropertiesAndValueStruct<PxDistanceJoint,PxDistanceJointGeneratedValues>( inStream);
+ registerPropertiesAndValueStruct<PxFixedJoint,PxFixedJointGeneratedValues>( inStream);
+ registerPropertiesAndValueStruct<PxPrismaticJoint,PxPrismaticJointGeneratedValues>( inStream);
+ registerPropertiesAndValueStruct<PxSphericalJoint,PxSphericalJointGeneratedValues>( inStream);
+ registerPropertiesAndValueStruct<PxRevoluteJoint,PxRevoluteJointGeneratedValues>( inStream);
+ registerPropertiesAndValueStruct<PxD6Joint,PxD6JointGeneratedValues>( inStream);
+ }
+ }
+
+ void Pvd::setActors( physx::pvdsdk::PvdDataStream& inStream, const PxJoint& inJoint, const PxConstraint& c, const PxActor* newActor0, const PxActor* newActor1 )
+ {
+ PxRigidActor* actor0, *actor1;
+ c.getActors( actor0, actor1 );
+ if ( actor0 )
+ inStream.removeObjectRef( actor0, "Joints", &inJoint );
+ if ( actor1 )
+ inStream.removeObjectRef( actor1, "Joints", &inJoint );
+
+ if ( newActor0 && newActor0->getScene())
+ inStream.pushBackObjectRef( newActor0, "Joints", &inJoint );
+ if ( newActor1 && newActor1->getScene())
+ inStream.pushBackObjectRef( newActor1, "Joints", &inJoint );
+
+ inStream.setPropertyValue( &inJoint, "Actors.actor0", reinterpret_cast<const void*>(newActor0) );
+ inStream.setPropertyValue( &inJoint, "Actors.actor1", reinterpret_cast<const void*>(newActor1) );
+ const void* parent = newActor0 ? newActor0 : newActor1;
+ inStream.setPropertyValue( &inJoint, "Parent", parent );
+
+ if((newActor0 && !newActor0->getScene()) || (newActor1 && !newActor1->getScene()))
+ {
+ inStream.removeObjectRef( c.getScene(), "Joints", &inJoint );
+ }
+
+ }
+}
+
+}
+
+#endif // PX_SUPPORT_PVD
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.h
new file mode 100644
index 00000000..2f3e3cf0
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPvd.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 EXT_PVD_H
+#define EXT_PVD_H
+
+#if PX_SUPPORT_PVD
+
+#include "CmPhysXCommon.h"
+#include "PsUserAllocated.h"
+#include "PxJoint.h"
+#include "PxPvdDataStream.h"
+#include "PxExtensionMetaDataObjects.h"
+#include "PvdTypeNames.h"
+#include "PxPvdObjectModelBaseTypes.h"
+
+namespace physx
+{
+
+class PxJoint;
+class PxD6Joint;
+class PxDistanceJoint;
+class PxFixedJoint;
+class PxPrismaticJoint;
+class PxRevoluteJoint;
+class PxSphericalJoint;
+}
+
+#define JOINT_GROUP 3
+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(PxJoint)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxJointGeneratedValues)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxFixedJoint)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxFixedJointGeneratedValues)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxDistanceJoint)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxDistanceJointGeneratedValues)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxPrismaticJoint)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxPrismaticJointGeneratedValues)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRevoluteJoint)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxRevoluteJointGeneratedValues)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSphericalJoint)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxSphericalJointGeneratedValues)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxD6Joint)
+ DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP(PxD6JointGeneratedValues)
+#undef DEFINE_NATIVE_PVD_PHYSX3_TYPE_MAP
+} //pvdsdk
+} // physx
+
+namespace physx
+{
+namespace Ext
+{
+ using namespace physx::pvdsdk;
+
+ class Pvd: public physx::shdfnd::UserAllocated
+ {
+ Pvd& operator=(const Pvd&);
+ public:
+ class PvdNameSpace
+ {
+
+ public:
+ PvdNameSpace(PvdDataStream& conn, const char* name);
+ ~PvdNameSpace();
+ private:
+ PvdNameSpace& operator=(const PvdNameSpace&);
+ PvdDataStream& mConnection;
+ };
+
+ static void setActors( PvdDataStream& PvdDataStream,
+ const PxJoint& inJoint, const PxConstraint& c, const PxActor* newActor0, const PxActor* newActor1 );
+
+ template<typename TObjType>
+ static void createInstance( PvdDataStream& inStream, const PxConstraint& c, const TObjType& inSource )
+ {
+ inStream.createInstance( &inSource );
+ inStream.pushBackObjectRef( c.getScene(), "Joints", &inSource );
+
+ class ConstraintUpdateCmd : public PvdDataStream::PvdCommand
+ {
+ ConstraintUpdateCmd &operator=(const ConstraintUpdateCmd&) { PX_ASSERT(0); return *this; } //PX_NOCOPY doesn't work for local classes
+ public:
+
+ const PxConstraint& mConstraint;
+ const PxJoint& mJoint;
+
+ PxRigidActor* actor0, *actor1;
+ ConstraintUpdateCmd(const PxConstraint& constraint, const PxJoint& joint):PvdDataStream::PvdCommand(), mConstraint(constraint), mJoint(joint)
+ {
+ mConstraint.getActors( actor0, actor1 );
+ }
+
+ //Assigned is needed for copying
+ ConstraintUpdateCmd(const ConstraintUpdateCmd& cmd)
+ :PvdDataStream::PvdCommand(), mConstraint(cmd.mConstraint), mJoint(cmd.mJoint)
+ {
+ }
+
+ virtual bool canRun(PvdInstanceDataStream &inStream_ )
+ {
+ PX_ASSERT(inStream_.isInstanceValid(&mJoint));
+ //When run this command, the constraint maybe buffer removed
+ return ((actor0 == NULL) || inStream_.isInstanceValid(actor0))
+ && ((actor1 == NULL) || inStream_.isInstanceValid(actor1));
+ }
+ virtual void run( PvdInstanceDataStream &inStream_ )
+ {
+ //When run this command, the constraint maybe buffer removed
+ if(!inStream_.isInstanceValid(&mJoint))
+ return;
+
+ PxRigidActor* actor0_, *actor1_;
+ mConstraint.getActors( actor0_, actor1_ );
+
+ if ( actor0_ && (inStream_.isInstanceValid(actor0_)) )
+ inStream_.pushBackObjectRef( actor0_, "Joints", &mJoint );
+ if ( actor1_ && (inStream_.isInstanceValid(actor1_)) )
+ inStream_.pushBackObjectRef( actor1_, "Joints", &mJoint );
+ const void* parent = actor0_ ? actor0_ : actor1_;
+ inStream_.setPropertyValue( &mJoint, "Parent", parent );
+ }
+ };
+
+ ConstraintUpdateCmd* cmd = PX_PLACEMENT_NEW(inStream.allocateMemForCmd(sizeof(ConstraintUpdateCmd)),
+ ConstraintUpdateCmd)(c, inSource);
+
+ if(cmd->canRun( inStream ))
+ cmd->run( inStream );
+ else
+ inStream.pushPvdCommand( *cmd );
+ }
+
+ template<typename jointtype, typename structValue>
+ static void updatePvdProperties(PvdDataStream& pvdConnection, const jointtype& joint)
+ {
+ structValue theValueStruct( &joint );
+ pvdConnection.setPropertyMessage( &joint, theValueStruct );
+ }
+
+ template<typename jointtype>
+ static void simUpdate(PvdDataStream& /*pvdConnection*/, const jointtype& /*joint*/) {}
+
+ template<typename jointtype>
+ static void createPvdInstance(PvdDataStream& pvdConnection, const PxConstraint& c, const jointtype& joint)
+ {
+ createInstance<jointtype>( pvdConnection, c, joint );
+ }
+
+ static void releasePvdInstance(PvdDataStream& pvdConnection, const PxConstraint& c, const PxJoint& joint);
+ static void sendClassDescriptions(PvdDataStream& pvdConnection);
+ };
+} // ext
+
+} // physx
+
+#endif // PX_SUPPORT_PVD
+#endif // EXT_PVD_H
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtPxStringTable.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtPxStringTable.cpp
new file mode 100644
index 00000000..ac302013
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtPxStringTable.cpp
@@ -0,0 +1,99 @@
+// 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/PxAllocatorCallback.h"
+#include "PxStringTableExt.h"
+#include "PxProfileAllocatorWrapper.h" //tools for using a custom allocator
+#include "PsString.h"
+#include "PsUserAllocated.h"
+#include "CmPhysXCommon.h"
+
+namespace physx
+{
+ using namespace physx::profile;
+
+ class PxStringTableImpl : public PxStringTable, public Ps::UserAllocated
+ {
+ typedef PxProfileHashMap<const char*, PxU32> THashMapType;
+ PxProfileAllocatorWrapper mWrapper;
+ THashMapType mHashMap;
+ public:
+
+ PxStringTableImpl( PxAllocatorCallback& inAllocator )
+ : mWrapper ( inAllocator )
+ , mHashMap ( mWrapper )
+ {
+ }
+
+ virtual ~PxStringTableImpl()
+ {
+ for ( THashMapType::Iterator iter = mHashMap.getIterator();
+ iter.done() == false;
+ ++iter )
+ PX_PROFILE_DELETE( mWrapper, const_cast<char*>( iter->first ) );
+ mHashMap.clear();
+ }
+
+
+ virtual const char* allocateStr( const char* inSrc )
+ {
+ if ( inSrc == NULL )
+ inSrc = "";
+ const THashMapType::Entry* existing( mHashMap.find( inSrc ) );
+ if ( existing == NULL )
+ {
+ size_t len( strlen( inSrc ) );
+ len += 1;
+ char* newMem = reinterpret_cast<char*>(mWrapper.getAllocator().allocate( len, "PxStringTableImpl: const char*", __FILE__, __LINE__ ));
+ physx::shdfnd::strlcpy( newMem, len, inSrc );
+ mHashMap.insert( newMem, 1 );
+ return newMem;
+ }
+ else
+ {
+ ++const_cast<THashMapType::Entry*>(existing)->second;
+ return existing->first;
+ }
+ }
+
+ /**
+ * Release the string table and all the strings associated with it.
+ */
+ virtual void release()
+ {
+ PX_PROFILE_DELETE( mWrapper.getAllocator(), this );
+ }
+ };
+
+ PxStringTable& PxStringTableExt::createStringTable( PxAllocatorCallback& inAllocator )
+ {
+ return *PX_PROFILE_NEW( inAllocator, PxStringTableImpl )( inAllocator );
+ }
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtRaycastCCD.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtRaycastCCD.cpp
new file mode 100644
index 00000000..6122e82a
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtRaycastCCD.cpp
@@ -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.
+
+#include "PxRaycastCCD.h"
+
+using namespace physx;
+
+#include "geometry/PxBoxGeometry.h"
+#include "geometry/PxSphereGeometry.h"
+#include "geometry/PxCapsuleGeometry.h"
+#include "geometry/PxConvexMeshGeometry.h"
+#include "geometry/PxConvexMesh.h"
+#include "PxScene.h"
+#include "PxRigidDynamic.h"
+#include "extensions/PxShapeExt.h"
+#include "PsArray.h"
+
+namespace physx
+{
+class RaycastCCDManagerInternal
+{
+ PX_NOCOPY(RaycastCCDManagerInternal)
+ public:
+ RaycastCCDManagerInternal(PxScene* scene) : mScene(scene) {}
+ ~RaycastCCDManagerInternal(){}
+
+ bool registerRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape);
+
+ void doRaycastCCD(bool doDynamicDynamicCCD);
+
+ struct CCDObject
+ {
+ PX_FORCE_INLINE CCDObject(PxRigidDynamic* actor, PxShape* shape, const PxVec3& witness) : mActor(actor), mShape(shape), mWitness(witness) {}
+ PxRigidDynamic* mActor;
+ PxShape* mShape;
+ PxVec3 mWitness;
+ };
+
+ private:
+ PxScene* mScene;
+ physx::shdfnd::Array<CCDObject> mObjects;
+};
+}
+
+static PxVec3 getShapeCenter(PxShape* shape, const PxTransform& pose)
+{
+ PxVec3 offset(0.0f);
+ if(shape->getGeometryType()==PxGeometryType::eCONVEXMESH)
+ {
+ PxConvexMeshGeometry geometry;
+ bool status = shape->getConvexMeshGeometry(geometry);
+ PX_UNUSED(status);
+ PX_ASSERT(status);
+
+ PxReal mass;
+ PxMat33 localInertia;
+ PxVec3 localCenterOfMass;
+ geometry.convexMesh->getMassInformation(mass, localInertia, localCenterOfMass);
+
+ offset += localCenterOfMass;
+ }
+ return pose.transform(offset);
+}
+
+static PX_FORCE_INLINE PxVec3 getShapeCenter(PxRigidActor* actor, PxShape* shape)
+{
+ const PxTransform pose = PxShapeExt::getGlobalPose(*shape, *actor);
+ return getShapeCenter(shape, pose);
+}
+
+static PxReal computeInternalRadius(PxRigidActor* actor, PxShape* shape, const PxVec3& dir)
+{
+ const PxBounds3 bounds = PxShapeExt::getWorldBounds(*shape, *actor);
+ const PxReal diagonal = (bounds.maximum - bounds.minimum).magnitude();
+ const PxReal offsetFromOrigin = diagonal * 2.0f;
+
+ PxTransform pose = PxShapeExt::getGlobalPose(*shape, *actor);
+
+ PxReal internalRadius = 0.0f;
+ const PxReal length = offsetFromOrigin*2.0f;
+
+ switch(shape->getGeometryType())
+ {
+ case PxGeometryType::eSPHERE:
+ {
+ PxSphereGeometry geometry;
+ bool status = shape->getSphereGeometry(geometry);
+ PX_UNUSED(status);
+ PX_ASSERT(status);
+
+ internalRadius = geometry.radius;
+ }
+ break;
+
+ case PxGeometryType::eBOX:
+ case PxGeometryType::eCAPSULE:
+ {
+ pose.p = PxVec3(0.0f);
+ const PxVec3 virtualOrigin = pose.p + dir * offsetFromOrigin;
+
+ PxRaycastHit hit;
+ PxU32 nbHits = PxGeometryQuery::raycast(virtualOrigin, -dir, shape->getGeometry().any(), pose, length, PxHitFlag::eDISTANCE, 1, &hit);
+ PX_UNUSED(nbHits);
+ PX_ASSERT(nbHits);
+
+ internalRadius = offsetFromOrigin - hit.distance;
+ }
+ break;
+
+ case PxGeometryType::eCONVEXMESH:
+ {
+ PxVec3 shapeCenter = getShapeCenter(shape, pose);
+ shapeCenter -= pose.p;
+ pose.p = PxVec3(0.0f);
+
+ const PxVec3 virtualOrigin = shapeCenter + dir * offsetFromOrigin;
+ PxRaycastHit hit;
+ PxU32 nbHits = PxGeometryQuery::raycast(virtualOrigin, -dir, shape->getGeometry().any(), pose, length, PxHitFlag::eDISTANCE, 1, &hit);
+ PX_UNUSED(nbHits);
+ PX_ASSERT(nbHits);
+
+ internalRadius = offsetFromOrigin - hit.distance;
+ }
+ break;
+
+ case PxGeometryType::ePLANE:
+ case PxGeometryType::eHEIGHTFIELD:
+ case PxGeometryType::eTRIANGLEMESH:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ break;
+ }
+ return internalRadius;
+}
+
+class CCDRaycastFilterCallback : public PxQueryFilterCallback
+{
+public:
+ CCDRaycastFilterCallback(PxRigidActor* actor, PxShape* shape) : mActor(actor), mShape(shape){}
+
+ PxRigidActor* mActor;
+ PxShape* mShape;
+
+ virtual PxQueryHitType::Enum preFilter(const PxFilterData&, const PxShape* shape, const PxRigidActor* actor, PxHitFlags&)
+ {
+ if(mActor==actor && mShape==shape)
+ return PxQueryHitType::eNONE;
+ return PxQueryHitType::eBLOCK;
+ }
+
+ virtual PxQueryHitType::Enum postFilter(const PxFilterData&, const PxQueryHit&)
+ {
+ return PxQueryHitType::eNONE;
+ }
+};
+
+static bool CCDRaycast(PxScene* scene, PxRigidActor* actor, PxShape* shape, const PxVec3& origin, const PxVec3& unitDir, const PxReal distance, PxRaycastHit& hit, bool dyna_dyna)
+{
+ const PxQueryFlags qf(dyna_dyna ? PxQueryFlags(PxQueryFlag::eSTATIC|PxQueryFlag::eDYNAMIC|PxQueryFlag::ePREFILTER) : PxQueryFlags(PxQueryFlag::eSTATIC));
+ const PxQueryFilterData filterData(PxFilterData(), qf);
+
+ CCDRaycastFilterCallback CB(actor, shape);
+
+ PxRaycastBuffer buf1;
+ scene->raycast(origin, unitDir, distance, buf1, PxHitFlag::eDISTANCE, filterData, &CB);
+ hit = buf1.block;
+ return buf1.hasBlock;
+}
+
+static PxRigidDynamic* canDoCCD(PxRigidActor& actor, PxShape* /*shape*/)
+{
+ if(actor.getConcreteType()!=PxConcreteType::eRIGID_DYNAMIC)
+ return NULL; // PT: no need to do it for statics
+ PxRigidDynamic* dyna = static_cast<PxRigidDynamic*>(&actor);
+
+ const PxU32 nbShapes = dyna->getNbShapes();
+ if(nbShapes!=1)
+ return NULL; // PT: only works with simple actors for now
+
+ if(dyna->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC)
+ return NULL; // PT: no need to do it for kinematics
+
+ return dyna;
+}
+
+static bool doRaycastCCD(PxScene* scene, const RaycastCCDManagerInternal::CCDObject& object, PxTransform& newPose, PxVec3& newShapeCenter, bool dyna_dyna)
+{
+ PxRigidDynamic* dyna = canDoCCD(*object.mActor, object.mShape);
+ if(!dyna)
+ return true;
+
+ bool updateCCDWitness = true;
+
+ const PxVec3 offset = newPose.p - newShapeCenter;
+ const PxVec3& origin = object.mWitness;
+ const PxVec3& dest = newShapeCenter;
+
+ PxVec3 dir = dest - origin;
+ const PxReal length = dir.magnitude();
+ if(length!=0.0f)
+ {
+ dir /= length;
+
+ const PxReal internalRadius = computeInternalRadius(object.mActor, object.mShape, dir);
+
+ PxRaycastHit hit;
+ if(internalRadius!=0.0f && CCDRaycast(scene, object.mActor, object.mShape, origin, dir, length, hit, dyna_dyna))
+ {
+ updateCCDWitness = false;
+
+ const PxReal radiusLimit = internalRadius * 0.75f;
+ if(hit.distance>radiusLimit)
+ {
+ newShapeCenter = origin + dir * (hit.distance - radiusLimit);
+ }
+ else
+ {
+ if(hit.actor->getConcreteType()==PxConcreteType::eRIGID_DYNAMIC)
+ return true;
+
+ newShapeCenter = origin;
+ }
+
+ newPose.p = offset + newShapeCenter;
+ const PxTransform shapeLocalPose = object.mShape->getLocalPose();
+ const PxTransform inverseShapeLocalPose = shapeLocalPose.getInverse();
+ const PxTransform newGlobalPose = newPose * inverseShapeLocalPose;
+ dyna->setGlobalPose(newGlobalPose);
+ }
+ }
+ return updateCCDWitness;
+}
+
+bool RaycastCCDManagerInternal::registerRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape)
+{
+ if(!actor || !shape)
+ return false;
+
+ mObjects.pushBack(CCDObject(actor, shape, getShapeCenter(actor, shape)));
+ return true;
+}
+
+void RaycastCCDManagerInternal::doRaycastCCD(bool doDynamicDynamicCCD)
+{
+ const PxU32 nbObjects = mObjects.size();
+ for(PxU32 i=0;i<nbObjects;i++)
+ {
+ CCDObject& object = mObjects[i];
+
+ if(object.mActor->isSleeping())
+ continue;
+
+ PxTransform newPose = PxShapeExt::getGlobalPose(*object.mShape, *object.mActor);
+ PxVec3 newShapeCenter = getShapeCenter(object.mShape, newPose);
+
+ if(::doRaycastCCD(mScene, object, newPose, newShapeCenter, doDynamicDynamicCCD))
+ object.mWitness = newShapeCenter;
+ }
+}
+
+RaycastCCDManager::RaycastCCDManager(PxScene* scene)
+{
+ mImpl = new RaycastCCDManagerInternal(scene);
+}
+
+RaycastCCDManager::~RaycastCCDManager()
+{
+ delete mImpl;
+}
+
+bool RaycastCCDManager::registerRaycastCCDObject(PxRigidDynamic* actor, PxShape* shape)
+{
+ return mImpl->registerRaycastCCDObject(actor, shape);
+}
+
+void RaycastCCDManager::doRaycastCCD(bool doDynamicDynamicCCD)
+{
+ mImpl->doRaycastCCD(doDynamicDynamicCCD);
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.cpp
new file mode 100644
index 00000000..2fb85184
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.cpp
@@ -0,0 +1,287 @@
+// 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 "ExtRevoluteJoint.h"
+#include "PsUtilities.h"
+#include "ExtConstraintHelper.h"
+#include "CmRenderOutput.h"
+#include "PsMathUtils.h"
+#include "CmVisualization.h"
+#include "CmUtils.h"
+
+#include "common/PxSerialFramework.h"
+
+using namespace physx;
+using namespace Ext;
+
+namespace physx
+{
+ PxRevoluteJoint* PxRevoluteJointCreate(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1);
+}
+
+PxRevoluteJoint* physx::PxRevoluteJointCreate(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+{
+ PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxRevoluteJointCreate: local frame 0 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxRevoluteJointCreate: local frame 1 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxRevoluteJointCreate: actors must be different");
+ PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxRevoluteJointCreate: at least one actor must be dynamic");
+
+ RevoluteJoint* j;
+ PX_NEW_SERIALIZED(j,RevoluteJoint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1);
+ if(j->attach(physics, actor0, actor1))
+ return j;
+
+ PX_DELETE(j);
+ return NULL;
+}
+
+
+PxReal RevoluteJoint::getAngle() const
+{
+ PxQuat q = getRelativeTransform().q, swing, twist;
+ Ps::separateSwingTwist(q, swing, twist);
+ PxReal angle = twist.getAngle();
+ if(q.x<0)
+ angle = 2*PxPi - angle;
+ if(angle>PxPi)
+ angle-=2*PxPi;
+ return angle;
+
+}
+
+PxReal RevoluteJoint::getVelocity() const
+{
+ return getRelativeAngularVelocity().x;
+}
+
+
+
+PxJointAngularLimitPair RevoluteJoint::getLimit() const
+{
+ return data().limit;
+}
+
+void RevoluteJoint::setLimit(const PxJointAngularLimitPair& limit)
+{
+ PX_CHECK_AND_RETURN(limit.isValid(), "PxRevoluteJoint::setTwistLimit: limit invalid");
+ PX_CHECK_AND_RETURN(limit.lower>-PxPi && limit.upper<PxPi , "PxRevoluteJoint::twist limit must be strictly -*PI and PI");
+ PX_CHECK_AND_RETURN(limit.upper - limit.lower < PxTwoPi, "PxRevoluteJoint::twist limit range must be strictly less than 2*PI");
+ data().limit = limit;
+ markDirty();
+}
+
+PxReal RevoluteJoint::getDriveVelocity() const
+{
+ return data().driveVelocity;
+}
+
+void RevoluteJoint::setDriveVelocity(PxReal velocity)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(velocity), "PxRevoluteJoint::setDriveVelocity: invalid parameter");
+ data().driveVelocity = velocity;
+ markDirty();
+}
+
+PxReal RevoluteJoint::getDriveForceLimit() const
+{
+ return data().driveForceLimit;
+}
+
+void RevoluteJoint::setDriveForceLimit(PxReal forceLimit)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(forceLimit), "PxRevoluteJoint::setDriveForceLimit: invalid parameter");
+ data().driveForceLimit = forceLimit;
+ markDirty();
+}
+
+PxReal RevoluteJoint::getDriveGearRatio() const
+{
+ return data().driveGearRatio;
+}
+
+void RevoluteJoint::setDriveGearRatio(PxReal gearRatio)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(gearRatio) && gearRatio>0, "PxRevoluteJoint::setDriveGearRatio: invalid parameter");
+ data().driveGearRatio = gearRatio;
+ markDirty();
+}
+
+void RevoluteJoint::setProjectionAngularTolerance(PxReal tolerance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance>=0 && tolerance<=PxPi, "PxRevoluteJoint::setProjectionAngularTolerance: invalid parameter");
+ data().projectionAngularTolerance = tolerance;
+ markDirty();
+}
+
+PxReal RevoluteJoint::getProjectionAngularTolerance() const
+{
+ return data().projectionAngularTolerance;
+}
+
+void RevoluteJoint::setProjectionLinearTolerance(PxReal tolerance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0, "PxRevoluteJoint::setProjectionLinearTolerance: invalid parameter");
+ data().projectionLinearTolerance = tolerance;
+ markDirty();
+}
+
+PxReal RevoluteJoint::getProjectionLinearTolerance() const
+{
+ return data().projectionLinearTolerance;
+}
+
+PxRevoluteJointFlags RevoluteJoint::getRevoluteJointFlags(void) const
+{
+ return data().jointFlags;
+}
+
+void RevoluteJoint::setRevoluteJointFlags(PxRevoluteJointFlags flags)
+{
+ data().jointFlags = flags;
+}
+
+void RevoluteJoint::setRevoluteJointFlag(PxRevoluteJointFlag::Enum flag, bool value)
+{
+ if(value)
+ data().jointFlags |= flag;
+ else
+ data().jointFlags &= ~flag;
+ markDirty();
+}
+
+
+
+
+void* Ext::RevoluteJoint::prepareData()
+{
+ data().tqHigh = PxTan(data().limit.upper/4);
+ data().tqLow = PxTan(data().limit.lower/4);
+ data().tqPad = PxTan(data().limit.contactDistance/4);
+
+ return RevoluteJointT::prepareData();
+}
+
+
+namespace
+{
+
+void RevoluteJointProject(const void* constantBlock,
+ PxTransform& bodyAToWorld,
+ PxTransform& bodyBToWorld,
+ bool projectToA)
+{
+ using namespace joint;
+
+ const RevoluteJointData& data = *reinterpret_cast<const RevoluteJointData*>(constantBlock);
+
+ PxTransform cA2w, cB2w, cB2cA, projected;
+ computeDerived(data, bodyAToWorld, bodyBToWorld, cA2w, cB2w, cB2cA);
+
+ bool linearTrunc, angularTrunc;
+ projected.p = truncateLinear(cB2cA.p, data.projectionLinearTolerance, linearTrunc);
+
+ PxQuat swing, twist, projSwing;
+ Ps::separateSwingTwist(cB2cA.q,swing,twist);
+ projSwing = truncateAngular(swing, PxSin(data.projectionAngularTolerance/2), PxCos(data.projectionAngularTolerance/2), angularTrunc);
+
+ if(linearTrunc || angularTrunc)
+ {
+ projected.q = projSwing * twist;
+ projectTransforms(bodyAToWorld, bodyBToWorld, cA2w, cB2w, projected, data, projectToA);
+ }
+}
+
+void RevoluteJointVisualize(PxConstraintVisualizer& viz,
+ const void* constantBlock,
+ const PxTransform& body0Transform,
+ const PxTransform& body1Transform,
+ PxU32 /*flags*/)
+{
+ const RevoluteJointData& data = *reinterpret_cast<const RevoluteJointData*>(constantBlock);
+
+ const PxTransform& t0 = body0Transform * data.c2b[0];
+ const PxTransform& t1 = body1Transform * data.c2b[1];
+
+ viz.visualizeJointFrames(t0, t1);
+
+ if(data.jointFlags & PxRevoluteJointFlag::eLIMIT_ENABLED)
+ viz.visualizeAngularLimit(t0, data.limit.lower, data.limit.upper, false);
+}
+}
+
+bool Ext::RevoluteJoint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1)
+{
+ mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(RevoluteJointData));
+ return mPxConstraint!=NULL;
+}
+
+void RevoluteJoint::exportExtraData(PxSerializationContext& stream)
+{
+ if(mData)
+ {
+ stream.alignData(PX_SERIAL_ALIGN);
+ stream.writeData(mData, sizeof(RevoluteJointData));
+ }
+ stream.writeName(mName);
+}
+
+void RevoluteJoint::importExtraData(PxDeserializationContext& context)
+{
+ if(mData)
+ mData = context.readExtraData<RevoluteJointData, PX_SERIAL_ALIGN>();
+ context.readName(mName);
+}
+
+void RevoluteJoint::resolveReferences(PxDeserializationContext& context)
+{
+ setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders));
+}
+
+RevoluteJoint* RevoluteJoint::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ RevoluteJoint* obj = new (address) RevoluteJoint(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(RevoluteJoint);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+
+// global function to share the joint shaders with API capture
+const PxConstraintShaderTable* Ext::GetRevoluteJointShaderTable()
+{
+ return &RevoluteJoint::getConstraintShaderTable();
+}
+
+//~PX_SERIALIZATION
+PxConstraintShaderTable Ext::RevoluteJoint::sShaders = { Ext::RevoluteJointSolverPrep, RevoluteJointProject, RevoluteJointVisualize, PxConstraintFlag::Enum(0) };
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.h
new file mode 100644
index 00000000..caf65b3a
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJoint.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 NP_REVOLUTEJOINTCONSTRAINT_H
+#define NP_REVOLUTEJOINTCONSTRAINT_H
+
+#include "ExtJoint.h"
+#include "PxRevoluteJoint.h"
+#include "PsIntrinsics.h"
+#include "CmUtils.h"
+
+namespace physx
+{
+
+class PxConstraintSolverPrepKernel;
+class PxConstraintProjectionKernel;
+struct PxRevoluteJointGeneratedValues;
+
+namespace Ext
+{
+ struct RevoluteJointData : public JointData
+ {
+ //= 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.
+ //==================================================================================================
+
+ PxReal driveVelocity;
+ PxReal driveForceLimit;
+ PxReal driveGearRatio;
+
+ PxJointAngularLimitPair limit;
+
+ PxReal tqHigh;
+ PxReal tqLow;
+ PxReal tqPad;
+
+ PxReal projectionLinearTolerance;
+ PxReal projectionAngularTolerance;
+
+ PxRevoluteJointFlags jointFlags;
+ // forestall compiler complaints about not being able to generate a constructor
+ private:
+ RevoluteJointData(const PxJointAngularLimitPair &pair):
+ limit(pair) {}
+ };
+
+ typedef Joint<PxRevoluteJoint, PxRevoluteJointGeneratedValues> RevoluteJointT;
+
+ class RevoluteJoint : public RevoluteJointT
+ {
+ //= 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
+ RevoluteJoint(PxBaseFlags baseFlags) : RevoluteJointT(baseFlags) {}
+ void resolveReferences(PxDeserializationContext& context);
+ virtual void exportExtraData(PxSerializationContext& context);
+ void importExtraData(PxDeserializationContext& context);
+ static RevoluteJoint* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ virtual ~RevoluteJoint()
+ {
+ if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY)
+ PX_FREE(mData);
+ }
+
+ RevoluteJoint(const PxTolerancesScale& /*scale*/,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ : RevoluteJointT(PxJointConcreteType::eREVOLUTE, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+ {
+ RevoluteJointData* data = reinterpret_cast<RevoluteJointData*>(PX_ALLOC(sizeof(RevoluteJointData), "RevoluteJointData"));
+ Cm::markSerializedMem(data, sizeof(RevoluteJointData));
+ mData = data;
+
+ initCommonData(*data, actor0, localFrame0, actor1, localFrame1);
+
+ data->projectionLinearTolerance = 1e10f;
+ data->projectionAngularTolerance = PxPi;
+ data->driveForceLimit = PX_MAX_F32;
+ data->driveVelocity = 0;
+ data->driveGearRatio = 1.0f;
+ data->limit = PxJointAngularLimitPair(-PxPi/2, PxPi/2);
+ data->jointFlags = PxRevoluteJointFlags();
+ }
+
+ PxReal getAngle() const;
+ PxReal getVelocity() const;
+
+ PxJointAngularLimitPair getLimit() const;
+ void setLimit(const PxJointAngularLimitPair& limit);
+
+ PxReal getDriveVelocity() const;
+ void setDriveVelocity(PxReal velocity);
+
+ PxReal getDriveForceLimit() const;
+ void setDriveForceLimit(PxReal forceLimit);
+
+ PxReal getDriveGearRatio() const;
+ void setDriveGearRatio(PxReal gearRatio);
+
+ void setProjectionAngularTolerance(PxReal tolerance);
+ PxReal getProjectionAngularTolerance() const;
+
+ void setProjectionLinearTolerance(PxReal distance);
+ PxReal getProjectionLinearTolerance() const;
+
+ PxRevoluteJointFlags getRevoluteJointFlags(void) const;
+ void setRevoluteJointFlags(PxRevoluteJointFlags flags);
+ void setRevoluteJointFlag(PxRevoluteJointFlag::Enum flag, bool value);
+
+ void* prepareData();
+
+ bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1);
+
+ static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; }
+
+ virtual PxConstraintSolverPrep getPrep() const { return sShaders.solverPrep; }
+
+ private:
+
+ static PxConstraintShaderTable sShaders;
+
+ PX_FORCE_INLINE RevoluteJointData& data() const
+ {
+ return *static_cast<RevoluteJointData*>(mData);
+ }
+
+ };
+
+} // namespace Ext
+
+namespace Ext
+{
+ extern "C" PxU32 RevoluteJointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 maxConstraints,
+ PxConstraintInvMassScale& invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w);
+
+ // global function to share the joint shaders with API capture
+ extern "C" const PxConstraintShaderTable* GetRevoluteJointShaderTable();
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJointSolverPrep.cpp
new file mode 100644
index 00000000..f6e524c5
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtRevoluteJointSolverPrep.cpp
@@ -0,0 +1,117 @@
+// 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 "ExtRevoluteJoint.h"
+#include "PsUtilities.h"
+#include "ExtConstraintHelper.h"
+#include "CmRenderOutput.h"
+#include "PsMathUtils.h"
+
+namespace physx
+{
+namespace Ext
+{
+ PxU32 RevoluteJointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 /*maxConstraints*/,
+ PxConstraintInvMassScale &invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w)
+ {
+ const RevoluteJointData& data = *reinterpret_cast<const RevoluteJointData*>(constantBlock);
+ invMassScale = data.invMassScale;
+
+ const PxJointAngularLimitPair& limit = data.limit;
+
+ bool limitEnabled = data.jointFlags & PxRevoluteJointFlag::eLIMIT_ENABLED;
+ bool limitIsLocked = limitEnabled && limit.lower >= limit.upper;
+
+ PxTransform cA2w = bA2w * data.c2b[0];
+ PxTransform cB2w = bB2w * data.c2b[1];
+
+ if(cB2w.q.dot(cA2w.q)<0.f)
+ cB2w.q = -cB2w.q;
+
+ body0WorldOffset = cB2w.p-bA2w.p;
+ Ext::joint::ConstraintHelper ch(constraints, cB2w.p - bA2w.p, cB2w.p - bB2w.p);
+
+ ch.prepareLockedAxes(cA2w.q, cB2w.q, cA2w.transformInv(cB2w.p), 7, PxU32(limitIsLocked ? 7 : 6));
+
+ if(limitIsLocked)
+ return ch.getCount();
+
+ PxVec3 axis = cA2w.rotate(PxVec3(1.f,0,0));
+
+ if(data.jointFlags & PxRevoluteJointFlag::eDRIVE_ENABLED)
+ {
+ Px1DConstraint *c = ch.getConstraintRow();
+
+ c->solveHint = PxConstraintSolveHint::eNONE;
+
+ c->linear0 = PxVec3(0);
+ c->angular0 = -axis;
+ c->linear1 = PxVec3(0);
+ c->angular1 = -axis * data.driveGearRatio;
+
+ c->velocityTarget = data.driveVelocity;
+
+ c->minImpulse = -data.driveForceLimit;
+ c->maxImpulse = data.driveForceLimit;
+ if(data.jointFlags & PxRevoluteJointFlag::eDRIVE_FREESPIN)
+ {
+ if(data.driveVelocity > 0)
+ c->minImpulse = 0;
+ if(data.driveVelocity < 0)
+ c->maxImpulse = 0;
+ }
+ c->flags |= Px1DConstraintFlag::eHAS_DRIVE_LIMIT;
+ }
+
+
+ if(limitEnabled)
+ {
+ PxQuat cB2cAq = cA2w.q.getConjugate() * cB2w.q;
+ PxQuat twist(cB2cAq.x,0,0,cB2cAq.w);
+
+ PxReal magnitude = twist.normalize();
+ PxReal tqPhi = physx::intrinsics::fsel(magnitude - 1e-6f, twist.x / (1.0f + twist.w), 0.f);
+
+ ch.quarterAnglePair(tqPhi, data.tqLow, data.tqHigh, data.tqPad, axis, limit);
+ }
+
+ return ch.getCount();
+ }
+}//namespace
+
+}
+
+//~PX_SERIALIZATION
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtRigidBodyExt.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtRigidBodyExt.cpp
new file mode 100644
index 00000000..a6dc4262
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtRigidBodyExt.cpp
@@ -0,0 +1,648 @@
+// 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 "PxRigidBodyExt.h"
+#include "PxShapeExt.h"
+#include "PxMassProperties.h"
+
+#include "ExtInertiaTensor.h"
+#include "PsAllocator.h"
+#include "PsFoundation.h"
+
+#include "PxShape.h"
+#include "PxScene.h"
+
+#include "PxBoxGeometry.h"
+#include "PxSphereGeometry.h"
+#include "PxCapsuleGeometry.h"
+#include "PxPlaneGeometry.h"
+#include "PxConvexMeshGeometry.h"
+#include "PxTriangleMeshGeometry.h"
+#include "PxHeightFieldGeometry.h"
+#include "PxGeometryHelpers.h"
+
+#include "PxConvexMesh.h"
+
+#include "PxBatchQuery.h"
+
+#include "PxRigidDynamic.h"
+#include "PxRigidStatic.h"
+#include "CmUtils.h"
+
+using namespace physx;
+using namespace Cm;
+
+static bool computeMassAndDiagInertia(Ext::InertiaTensorComputer& inertiaComp,
+ PxVec3& diagTensor, PxQuat& orient, PxReal& massOut, PxVec3& coM, bool lockCOM, const PxRigidBody& body, const char* errorStr)
+{
+ // The inertia tensor and center of mass is relative to the actor at this point. Transform to the
+ // body frame directly if CoM is specified, else use computed center of mass
+ if (lockCOM)
+ {
+ inertiaComp.translate(-coM); // base the tensor on user's desired center of mass.
+ }
+ else
+ {
+ //get center of mass - has to be done BEFORE centering.
+ coM = inertiaComp.getCenterOfMass();
+
+ //the computed result now needs to be centered around the computed center of mass:
+ inertiaComp.center();
+ }
+ // The inertia matrix is now based on the body's center of mass desc.massLocalPose.p
+
+ massOut = inertiaComp.getMass();
+ diagTensor = PxDiagonalize(inertiaComp.getInertia(), orient);
+
+ if ((diagTensor.x > 0.0f) && (diagTensor.y > 0.0f) && (diagTensor.z > 0.0f))
+ return true;
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "%s: inertia tensor has negative components (ill-conditioned input expected). Approximation for inertia tensor will be used instead.", errorStr);
+
+ // keep center of mass but use the AABB as a crude approximation for the inertia tensor
+ PxBounds3 bounds = body.getWorldBounds();
+ PxTransform pose = body.getGlobalPose();
+ bounds = PxBounds3::transformFast(pose.getInverse(), bounds);
+ Ext::InertiaTensorComputer it(false);
+ it.setBox(bounds.getExtents());
+ it.scaleDensity(massOut / it.getMass());
+ PxMat33 inertia = it.getInertia();
+ diagTensor = PxVec3(inertia.column0.x, inertia.column1.y, inertia.column2.z);
+ orient = PxQuat(PxIdentity);
+
+ return true;
+ }
+}
+
+static bool computeMassAndInertia(bool multipleMassOrDensity, PxRigidBody& body, const PxReal* densities, const PxReal* masses, PxU32 densityOrMassCount, bool includeNonSimShapes, Ext::InertiaTensorComputer& computer)
+{
+ PX_ASSERT(!densities || !masses);
+ PX_ASSERT((densities || masses) && (densityOrMassCount > 0));
+
+ Ext::InertiaTensorComputer inertiaComp(true);
+
+ Ps::InlineArray<PxShape*, 16> shapes("PxShape*"); shapes.resize(body.getNbShapes());
+
+ body.getShapes(shapes.begin(), shapes.size());
+
+ PxU32 validShapeIndex = 0;
+ PxReal currentMassOrDensity;
+ const PxReal* massOrDensityArray;
+ if (densities)
+ {
+ massOrDensityArray = densities;
+ currentMassOrDensity = densities[0];
+ }
+ else
+ {
+ massOrDensityArray = masses;
+ currentMassOrDensity = masses[0];
+ }
+ if (!PxIsFinite(currentMassOrDensity))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "computeMassAndInertia: Provided mass or density has no valid value");
+ return false;
+ }
+
+ for(PxU32 i=0; i < shapes.size(); i++)
+ {
+ if ((!(shapes[i]->getFlags() & PxShapeFlag::eSIMULATION_SHAPE)) && (!includeNonSimShapes))
+ continue;
+
+ if (multipleMassOrDensity)
+ {
+ if (validShapeIndex < densityOrMassCount)
+ {
+ currentMassOrDensity = massOrDensityArray[validShapeIndex];
+
+ if (!PxIsFinite(currentMassOrDensity))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "computeMassAndInertia: Provided mass or density has no valid value");
+ return false;
+ }
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "computeMassAndInertia: Not enough mass/density values provided for all (simulation) shapes");
+ return false;
+ }
+ }
+
+ Ext::InertiaTensorComputer it(false);
+
+ switch(shapes[i]->getGeometryType())
+ {
+ case PxGeometryType::eSPHERE :
+ {
+ PxSphereGeometry g;
+ bool ok = shapes[i]->getSphereGeometry(g);
+ PX_ASSERT(ok);
+ PX_UNUSED(ok);
+ PxTransform temp(shapes[i]->getLocalPose());
+
+ it.setSphere(g.radius, &temp);
+ }
+ break;
+
+ case PxGeometryType::eBOX :
+ {
+ PxBoxGeometry g;
+ bool ok = shapes[i]->getBoxGeometry(g);
+ PX_ASSERT(ok);
+ PX_UNUSED(ok);
+ PxTransform temp(shapes[i]->getLocalPose());
+
+ it.setBox(g.halfExtents, &temp);
+ }
+ break;
+
+ case PxGeometryType::eCAPSULE :
+ {
+ PxCapsuleGeometry g;
+ bool ok = shapes[i]->getCapsuleGeometry(g);
+ PX_ASSERT(ok);
+ PX_UNUSED(ok);
+ PxTransform temp(shapes[i]->getLocalPose());
+
+ it.setCapsule(0, g.radius, g.halfHeight, &temp);
+ }
+ break;
+
+ case PxGeometryType::eCONVEXMESH :
+ {
+ PxConvexMeshGeometry g;
+ bool ok = shapes[i]->getConvexMeshGeometry(g);
+ PX_ASSERT(ok);
+ PX_UNUSED(ok);
+ PxConvexMesh& convMesh = *g.convexMesh;
+
+ PxReal convMass;
+ PxMat33 convInertia;
+ PxVec3 convCoM;
+ convMesh.getMassInformation(convMass, reinterpret_cast<PxMat33&>(convInertia), convCoM);
+
+ if (!g.scale.isIdentity())
+ {
+ //scale the mass properties
+ convMass *= (g.scale.scale.x * g.scale.scale.y * g.scale.scale.z);
+ convCoM = g.scale.rotation.rotateInv(g.scale.scale.multiply(g.scale.rotation.rotate(convCoM)));
+ convInertia = PxMassProperties::scaleInertia(convInertia, g.scale.rotation, g.scale.scale);
+ }
+
+ it = Ext::InertiaTensorComputer(convInertia, convCoM, convMass);
+ it.transform(shapes[i]->getLocalPose());
+ }
+ break;
+ case PxGeometryType::eHEIGHTFIELD:
+ case PxGeometryType::ePLANE:
+ case PxGeometryType::eTRIANGLEMESH:
+ case PxGeometryType::eINVALID:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ {
+
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "computeMassAndInertia: Dynamic actor with illegal collision shapes");
+ return false;
+ }
+ }
+
+ if (densities)
+ it.scaleDensity(currentMassOrDensity);
+ else if (multipleMassOrDensity) // mass per shape -> need to scale density per shape
+ it.scaleDensity(currentMassOrDensity / it.getMass());
+
+ inertiaComp.add(it);
+
+ validShapeIndex++;
+ }
+
+ if (validShapeIndex && masses && (!multipleMassOrDensity)) // at least one simulation shape and single mass for all shapes -> scale density at the end
+ {
+ inertiaComp.scaleDensity(currentMassOrDensity / inertiaComp.getMass());
+ }
+
+ computer = inertiaComp;
+ return true;
+}
+
+static bool updateMassAndInertia(bool multipleMassOrDensity, PxRigidBody& body, const PxReal* densities, PxU32 densityCount, const PxVec3* massLocalPose, bool includeNonSimShapes)
+{
+ bool success;
+
+ // default values in case there were no shapes
+ PxReal massOut = 1.0f;
+ PxVec3 diagTensor(1.f,1.f,1.f);
+ PxQuat orient = PxQuat(PxIdentity);
+ bool lockCom = massLocalPose != NULL;
+ PxVec3 com = lockCom ? *massLocalPose : PxVec3(0);
+ const char* errorStr = "PxRigidBodyExt::updateMassAndInertia";
+
+ if (densities && densityCount)
+ {
+ Ext::InertiaTensorComputer inertiaComp(true);
+ if(computeMassAndInertia(multipleMassOrDensity, body, densities, NULL, densityCount, includeNonSimShapes, inertiaComp))
+ {
+ if(inertiaComp.getMass()!=0 && computeMassAndDiagInertia(inertiaComp, diagTensor, orient, massOut, com, lockCom, body, errorStr))
+ success = true;
+ else
+ success = false; // body with no shapes provided or computeMassAndDiagInertia() failed
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "%s: Mass and inertia computation failed, setting mass to 1 and inertia to (1,1,1)", errorStr);
+
+ success = false;
+ }
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "%s: No density specified, setting mass to 1 and inertia to (1,1,1)", errorStr);
+
+ success = false;
+ }
+
+ PX_ASSERT(orient.isFinite());
+ PX_ASSERT(diagTensor.isFinite());
+ PX_ASSERT(PxIsFinite(massOut));
+
+ body.setMass(massOut);
+ body.setMassSpaceInertiaTensor(diagTensor);
+ body.setCMassLocalPose(PxTransform(com, orient));
+
+ return success;
+}
+
+bool PxRigidBodyExt::updateMassAndInertia(PxRigidBody& body, const PxReal* densities, PxU32 densityCount, const PxVec3* massLocalPose, bool includeNonSimShapes)
+{
+ return ::updateMassAndInertia(true, body, densities, densityCount, massLocalPose, includeNonSimShapes);
+}
+
+bool PxRigidBodyExt::updateMassAndInertia(PxRigidBody& body, PxReal density, const PxVec3* massLocalPose, bool includeNonSimShapes)
+{
+ return ::updateMassAndInertia(false, body, &density, 1, massLocalPose, includeNonSimShapes);
+}
+
+static bool setMassAndUpdateInertia(bool multipleMassOrDensity, PxRigidBody& body, const PxReal* masses, PxU32 massCount, const PxVec3* massLocalPose, bool includeNonSimShapes)
+{
+ bool success;
+
+ // default values in case there were no shapes
+ PxReal massOut = 1.0f;
+ PxVec3 diagTensor(1.0f,1.0f,1.0f);
+ PxQuat orient = PxQuat(PxIdentity);
+ bool lockCom = massLocalPose != NULL;
+ PxVec3 com = lockCom ? *massLocalPose : PxVec3(0);
+ const char* errorStr = "PxRigidBodyExt::setMassAndUpdateInertia";
+
+ if(masses && massCount)
+ {
+ Ext::InertiaTensorComputer inertiaComp(true);
+ if(computeMassAndInertia(multipleMassOrDensity, body, NULL, masses, massCount, includeNonSimShapes, inertiaComp))
+ {
+ success = true;
+
+ if (inertiaComp.getMass()!=0 && !computeMassAndDiagInertia(inertiaComp, diagTensor, orient, massOut, com, lockCom, body, errorStr))
+ success = false; // computeMassAndDiagInertia() failed (mass zero?)
+
+ if (massCount == 1)
+ massOut = masses[0]; // to cover special case where body has no simulation shape
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "%s: Mass and inertia computation failed, setting mass to 1 and inertia to (1,1,1)", errorStr);
+
+ success = false;
+ }
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "%s: No mass specified, setting mass to 1 and inertia to (1,1,1)", errorStr);
+ success = false;
+ }
+
+ PX_ASSERT(orient.isFinite());
+ PX_ASSERT(diagTensor.isFinite());
+
+ body.setMass(massOut);
+ body.setMassSpaceInertiaTensor(diagTensor);
+ body.setCMassLocalPose(PxTransform(com, orient));
+
+ return success;
+}
+
+bool PxRigidBodyExt::setMassAndUpdateInertia(PxRigidBody& body, const PxReal* masses, PxU32 massCount, const PxVec3* massLocalPose, bool includeNonSimShapes)
+{
+ return ::setMassAndUpdateInertia(true, body, masses, massCount, massLocalPose, includeNonSimShapes);
+}
+
+bool PxRigidBodyExt::setMassAndUpdateInertia(PxRigidBody& body, PxReal mass, const PxVec3* massLocalPose, bool includeNonSimShapes)
+{
+ return ::setMassAndUpdateInertia(false, body, &mass, 1, massLocalPose, includeNonSimShapes);
+}
+
+PxMassProperties PxRigidBodyExt::computeMassPropertiesFromShapes(const PxShape* const* shapes, PxU32 shapeCount)
+{
+ Ps::InlineArray<PxMassProperties, 16> massProps;
+ massProps.reserve(shapeCount);
+ Ps::InlineArray<PxTransform, 16> localTransforms;
+ localTransforms.reserve(shapeCount);
+
+ for(PxU32 shapeIdx=0; shapeIdx < shapeCount; shapeIdx++)
+ {
+ const PxShape* shape = shapes[shapeIdx];
+ PxMassProperties mp(shape->getGeometry().any());
+ massProps.pushBack(mp);
+ localTransforms.pushBack(shape->getLocalPose());
+ }
+
+ return PxMassProperties::sum(massProps.begin(), localTransforms.begin(), shapeCount);
+}
+
+PX_INLINE void addForceAtPosInternal(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup)
+{
+ if(mode == PxForceMode::eACCELERATION || mode == PxForceMode::eVELOCITY_CHANGE)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxRigidBodyExt::addForce methods do not support eACCELERATION or eVELOCITY_CHANGE modes");
+ return;
+ }
+
+ const PxTransform globalPose = body.getGlobalPose();
+ const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);
+
+ const PxVec3 torque = (pos - centerOfMass).cross(force);
+ body.addForce(force, mode, wakeup);
+ body.addTorque(torque, mode, wakeup);
+}
+
+void PxRigidBodyExt::addForceAtPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup)
+{
+ addForceAtPosInternal(body, force, pos, mode, wakeup);
+}
+
+void PxRigidBodyExt::addForceAtLocalPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup)
+{
+ //transform pos to world space
+ const PxVec3 globalForcePos = body.getGlobalPose().transform(pos);
+
+ addForceAtPosInternal(body, force, globalForcePos, mode, wakeup);
+}
+
+void PxRigidBodyExt::addLocalForceAtPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup)
+{
+ const PxVec3 globalForce = body.getGlobalPose().rotate(force);
+
+ addForceAtPosInternal(body, globalForce, pos, mode, wakeup);
+}
+
+void PxRigidBodyExt::addLocalForceAtLocalPos(PxRigidBody& body, const PxVec3& force, const PxVec3& pos, PxForceMode::Enum mode, bool wakeup)
+{
+ const PxTransform globalPose = body.getGlobalPose();
+ const PxVec3 globalForcePos = globalPose.transform(pos);
+ const PxVec3 globalForce = globalPose.rotate(force);
+
+ addForceAtPosInternal(body, globalForce, globalForcePos, mode, wakeup);
+}
+
+PX_INLINE PxVec3 getVelocityAtPosInternal(const PxRigidBody& body, const PxVec3& point)
+{
+ PxVec3 velocity = body.getLinearVelocity();
+ velocity += body.getAngularVelocity().cross(point);
+
+ return velocity;
+}
+
+PxVec3 PxRigidBodyExt::getVelocityAtPos(const PxRigidBody& body, const PxVec3& point)
+{
+ const PxTransform globalPose = body.getGlobalPose();
+ const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);
+ const PxVec3 rpoint = point - centerOfMass;
+
+ return getVelocityAtPosInternal(body, rpoint);
+}
+
+PxVec3 PxRigidBodyExt::getLocalVelocityAtLocalPos(const PxRigidBody& body, const PxVec3& point)
+{
+ const PxTransform globalPose = body.getGlobalPose();
+ const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);
+ const PxVec3 rpoint = globalPose.transform(point) - centerOfMass;
+
+ return getVelocityAtPosInternal(body, rpoint);
+}
+
+PxVec3 PxRigidBodyExt::getVelocityAtOffset(const PxRigidBody& body, const PxVec3& point)
+{
+ const PxTransform globalPose = body.getGlobalPose();
+ const PxVec3 centerOfMass = globalPose.rotate(body.getCMassLocalPose().p);
+ const PxVec3 rpoint = point - centerOfMass;
+
+ return getVelocityAtPosInternal(body, rpoint);
+}
+
+void PxRigidBodyExt::computeVelocityDeltaFromImpulse(const PxRigidBody& body, const PxTransform& globalPose, const PxVec3& point, const PxVec3& impulse, const PxReal invMassScale,
+ const PxReal invInertiaScale, PxVec3& linearVelocityChange, PxVec3& angularVelocityChange)
+{
+ const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);
+ const PxReal invMass = body.getInvMass() * invMassScale;
+ const PxVec3 invInertiaMS = body.getMassSpaceInvInertiaTensor() * invInertiaScale;
+
+ PxMat33 invInertia;
+ transformInertiaTensor(invInertiaMS, PxMat33(globalPose.q), invInertia);
+ linearVelocityChange = impulse * invMass;
+ const PxVec3 rXI = (point - centerOfMass).cross(impulse);
+ angularVelocityChange = invInertia * rXI;
+}
+
+void PxRigidBodyExt::computeLinearAngularImpulse(const PxRigidBody& body, const PxTransform& globalPose, const PxVec3& point, const PxVec3& impulse, const PxReal invMassScale,
+ const PxReal invInertiaScale, PxVec3& linearImpulse, PxVec3& angularImpulse)
+{
+ const PxVec3 centerOfMass = globalPose.transform(body.getCMassLocalPose().p);
+ linearImpulse = impulse * invMassScale;
+ angularImpulse = (point - centerOfMass).cross(impulse) * invInertiaScale;
+}
+
+
+
+//=================================================================================
+// Single closest hit compound sweep
+bool PxRigidBodyExt::linearSweepSingle(
+ PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance,
+ PxHitFlags outputFlags, PxSweepHit& closestHit, PxU32& shapeIndex,
+ const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ const PxQueryCache* cache, const PxReal inflation)
+{
+ shapeIndex = 0xFFFFffff;
+ PxReal closestDist = distance;
+ PxU32 nbShapes = body.getNbShapes();
+ for(PxU32 i=0; i < nbShapes; i++)
+ {
+ PxShape* shape = NULL;
+ body.getShapes(&shape, 1, i);
+ PX_ASSERT(shape != NULL);
+ PxTransform pose = PxShapeExt::getGlobalPose(*shape, body);
+ PxQueryFilterData fd;
+ fd.flags = filterData.flags;
+ PxU32 or4 = (filterData.data.word0 | filterData.data.word1 | filterData.data.word2 | filterData.data.word3);
+ fd.data = or4 ? filterData.data : shape->getQueryFilterData();
+ PxGeometryHolder anyGeom = shape->getGeometry();
+
+ PxSweepBuffer subHit; // touching hits are not allowed to be returned from the filters
+ scene.sweep(anyGeom.any(), pose, unitDir, distance, subHit, outputFlags, fd, filterCall, cache, inflation);
+ if (subHit.hasBlock && subHit.block.distance < closestDist)
+ {
+ closestDist = subHit.block.distance;
+ closestHit = subHit.block;
+ shapeIndex = i;
+ }
+ }
+
+ return (shapeIndex != 0xFFFFffff);
+}
+
+//=================================================================================
+// Multiple hits compound sweep
+// AP: we might be able to improve the return results API but no time for it in 3.3
+PxU32 PxRigidBodyExt::linearSweepMultiple(
+ PxRigidBody& body, PxScene& scene, const PxVec3& unitDir, const PxReal distance, PxHitFlags outputFlags,
+ PxSweepHit* hitBuffer, PxU32* hitShapeIndices, PxU32 hitBufferSize, PxSweepHit& block, PxI32& blockingHitShapeIndex,
+ bool& overflow, const PxQueryFilterData& filterData, PxQueryFilterCallback* filterCall,
+ const PxQueryCache* cache, const PxReal inflation)
+{
+ overflow = false;
+ blockingHitShapeIndex = -1;
+
+ for (PxU32 i = 0; i < hitBufferSize; i++)
+ hitShapeIndices[i] = 0xFFFFffff;
+
+ PxI32 sumNbResults = 0;
+
+ PxU32 nbShapes = body.getNbShapes();
+ PxF32 shrunkMaxDistance = distance;
+ for(PxU32 i=0; i < nbShapes; i++)
+ {
+ PxShape* shape = NULL;
+ body.getShapes(&shape, 1, i);
+ PX_ASSERT(shape != NULL);
+ PxTransform pose = PxShapeExt::getGlobalPose(*shape, body);
+ PxQueryFilterData fd;
+ fd.flags = filterData.flags;
+ PxU32 or4 = (filterData.data.word0 | filterData.data.word1 | filterData.data.word2 | filterData.data.word3);
+ fd.data = or4 ? filterData.data : shape->getQueryFilterData();
+ PxGeometryHolder anyGeom = shape->getGeometry();
+
+ PxU32 bufSizeLeft = hitBufferSize-sumNbResults;
+ PxSweepHit extraHit;
+ PxSweepBuffer buffer(bufSizeLeft == 0 ? &extraHit : hitBuffer+sumNbResults, bufSizeLeft == 0 ? 1 : hitBufferSize-sumNbResults);
+ scene.sweep(anyGeom.any(), pose, unitDir, shrunkMaxDistance, buffer, outputFlags, fd, filterCall, cache, inflation);
+
+ // Check and abort on overflow. Assume overflow if result count is bufSize.
+ PxU32 nbNewResults = buffer.getNbTouches();
+ overflow |= (nbNewResults >= bufSizeLeft);
+ if (bufSizeLeft == 0) // this is for when we used the extraHit buffer
+ nbNewResults = 0;
+
+ // set hitShapeIndices for each new non-blocking hit
+ for (PxU32 j = 0; j < nbNewResults; j++)
+ if (sumNbResults + PxU32(j) < hitBufferSize)
+ hitShapeIndices[sumNbResults+j] = i;
+
+ if (buffer.hasBlock) // there's a blocking hit in the most recent sweepMultiple results
+ {
+ // overwrite the return result blocking hit with the new blocking hit if under
+ if (blockingHitShapeIndex == -1 || buffer.block.distance < block.distance)
+ {
+ blockingHitShapeIndex = PxI32(i);
+ block = buffer.block;
+ }
+
+ // Remove all the old touching hits below the new maxDist
+ // sumNbResults is not updated yet at this point
+ // and represents the count accumulated so far excluding the very last query
+ PxI32 nbNewResultsSigned = PxI32(nbNewResults); // need a signed version, see nbNewResultsSigned-- below
+ for (PxI32 j = sumNbResults-1; j >= 0; j--) // iterate over "old" hits (up to shapeIndex-1)
+ if (buffer.block.distance < hitBuffer[j].distance)
+ {
+ // overwrite with last "new" hit
+ PxI32 sourceIndex = PxI32(sumNbResults)+nbNewResultsSigned-1; PX_ASSERT(sourceIndex >= j);
+ hitBuffer[j] = hitBuffer[sourceIndex];
+ hitShapeIndices[j] = hitShapeIndices[sourceIndex];
+ nbNewResultsSigned--; // can get negative, that means we are shifting the last results array
+ }
+
+ sumNbResults += nbNewResultsSigned;
+ } else // if there was no new blocking hit we don't need to do anything special, simply append all results to touch array
+ sumNbResults += nbNewResults;
+
+ PX_ASSERT(sumNbResults >= 0 && sumNbResults <= PxI32(hitBufferSize));
+ }
+
+ return PxU32(sumNbResults);
+}
+
+void PxRigidBodyExt::computeVelocityDeltaFromImpulse(const PxRigidBody& body, const PxVec3& impulsiveForce, const PxVec3& impulsiveTorque, PxVec3& deltaLinearVelocity, PxVec3& deltaAngularVelocity)
+{
+ {
+ const PxF32 recipMass = body.getInvMass();
+ deltaLinearVelocity = impulsiveForce*recipMass;
+ }
+
+ {
+ const PxTransform globalPose = body.getGlobalPose();
+ const PxTransform cmLocalPose = body.getCMassLocalPose();
+ const PxTransform body2World = globalPose*cmLocalPose;
+ PxMat33 M(body2World.q);
+
+ const PxVec3 recipInertiaBodySpace = body.getMassSpaceInvInertiaTensor();
+
+ PxMat33 recipInertiaWorldSpace;
+ const float axx = recipInertiaBodySpace.x*M(0,0), axy = recipInertiaBodySpace.x*M(1,0), axz = recipInertiaBodySpace.x*M(2,0);
+ const float byx = recipInertiaBodySpace.y*M(0,1), byy = recipInertiaBodySpace.y*M(1,1), byz = recipInertiaBodySpace.y*M(2,1);
+ const float czx = recipInertiaBodySpace.z*M(0,2), czy = recipInertiaBodySpace.z*M(1,2), czz = recipInertiaBodySpace.z*M(2,2);
+ recipInertiaWorldSpace(0,0) = axx*M(0,0) + byx*M(0,1) + czx*M(0,2);
+ recipInertiaWorldSpace(1,1) = axy*M(1,0) + byy*M(1,1) + czy*M(1,2);
+ recipInertiaWorldSpace(2,2) = axz*M(2,0) + byz*M(2,1) + czz*M(2,2);
+ recipInertiaWorldSpace(0,1) = recipInertiaWorldSpace(1,0) = axx*M(1,0) + byx*M(1,1) + czx*M(1,2);
+ recipInertiaWorldSpace(0,2) = recipInertiaWorldSpace(2,0) = axx*M(2,0) + byx*M(2,1) + czx*M(2,2);
+ recipInertiaWorldSpace(1,2) = recipInertiaWorldSpace(2,1) = axy*M(2,0) + byy*M(2,1) + czy*M(2,2);
+
+ deltaAngularVelocity = recipInertiaWorldSpace*(impulsiveTorque);
+ }
+}
+
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSceneQueryExt.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtSceneQueryExt.cpp
new file mode 100644
index 00000000..a02c2ed0
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSceneQueryExt.cpp
@@ -0,0 +1,197 @@
+// 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 "PxSceneQueryExt.h"
+
+using namespace physx;
+
+bool PxSceneQueryExt::raycastAny( const PxScene& scene,
+ const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
+ PxSceneQueryHit& hit, const PxSceneQueryFilterData& filterData,
+ PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache,
+ PxClientID queryClient)
+{
+ PxSceneQueryFilterData fdAny = filterData;
+ fdAny.flags |= PxQueryFlag::eANY_HIT;
+ fdAny.clientId = queryClient;
+ PxRaycastBuffer buf;
+ scene.raycast(origin, unitDir, distance, buf, PxHitFlags(), fdAny, filterCall, cache);
+ hit = buf.block;
+ return buf.hasBlock;
+}
+
+bool PxSceneQueryExt::raycastSingle(const PxScene& scene,
+ const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
+ PxSceneQueryFlags outputFlags, PxRaycastHit& hit,
+ const PxSceneQueryFilterData& filterData,
+ PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache,
+ PxClientID queryClient)
+{
+ PxRaycastBuffer buf;
+ PxQueryFilterData fd1 = filterData; fd1.clientId = queryClient;
+ scene.raycast(origin, unitDir, distance, buf, outputFlags, fd1, filterCall, cache);
+ hit = buf.block;
+ return buf.hasBlock;
+}
+
+PxI32 PxSceneQueryExt::raycastMultiple( const PxScene& scene,
+ const PxVec3& origin, const PxVec3& unitDir, const PxReal distance,
+ PxSceneQueryFlags outputFlags,
+ PxRaycastHit* hitBuffer, PxU32 hitBufferSize, bool& blockingHit,
+ const PxSceneQueryFilterData& filterData,
+ PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache,
+ PxClientID queryClient)
+{
+ PxRaycastBuffer buf(hitBuffer, hitBufferSize);
+ PxQueryFilterData fd1 = filterData; fd1.clientId = queryClient;
+ scene.raycast(origin, unitDir, distance, buf, outputFlags, fd1, filterCall, cache);
+ blockingHit = buf.hasBlock;
+ if(blockingHit)
+ {
+ if(buf.nbTouches < hitBufferSize)
+ {
+ hitBuffer[buf.nbTouches] = buf.block;
+ return PxI32(buf.nbTouches+1);
+ }
+ else // overflow, drop the last touch
+ {
+ hitBuffer[hitBufferSize-1] = buf.block;
+ return -1;
+ }
+ } else
+ // no block
+ return PxI32(buf.nbTouches);
+}
+
+bool PxSceneQueryExt::sweepAny( const PxScene& scene,
+ const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
+ PxSceneQueryFlags queryFlags,
+ PxSceneQueryHit& hit,
+ const PxSceneQueryFilterData& filterData,
+ PxSceneQueryFilterCallback* filterCall,
+ const PxSceneQueryCache* cache,
+ PxClientID queryClient,
+ PxReal inflation)
+{
+ PxSceneQueryFilterData fdAny = filterData;
+ fdAny.flags |= PxQueryFlag::eANY_HIT;
+ fdAny.clientId = queryClient;
+ PxSweepBuffer buf;
+ scene.sweep(geometry, pose, unitDir, distance, buf, queryFlags, fdAny, filterCall, cache, inflation);
+ hit = buf.block;
+ return buf.hasBlock;
+}
+
+bool PxSceneQueryExt::sweepSingle( const PxScene& scene,
+ const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
+ PxSceneQueryFlags outputFlags,
+ PxSweepHit& hit,
+ const PxSceneQueryFilterData& filterData,
+ PxSceneQueryFilterCallback* filterCall,
+ const PxSceneQueryCache* cache,
+ PxClientID queryClient, PxReal inflation)
+{
+ PxSweepBuffer buf;
+ PxQueryFilterData fd1 = filterData; fd1.clientId = queryClient;
+ scene.sweep(geometry, pose, unitDir, distance, buf, outputFlags, fd1, filterCall, cache, inflation);
+ hit = buf.block;
+ return buf.hasBlock;
+}
+
+PxI32 PxSceneQueryExt::sweepMultiple( const PxScene& scene,
+ const PxGeometry& geometry, const PxTransform& pose, const PxVec3& unitDir, const PxReal distance,
+ PxSceneQueryFlags outputFlags, PxSweepHit* hitBuffer, PxU32 hitBufferSize, bool& blockingHit,
+ const PxSceneQueryFilterData& filterData,
+ PxSceneQueryFilterCallback* filterCall, const PxSceneQueryCache* cache,
+ PxClientID queryClient, PxReal inflation)
+{
+ PxQueryFilterData fd1 = filterData; fd1.clientId = queryClient;
+ PxSweepBuffer buf(hitBuffer, hitBufferSize);
+ scene.sweep(geometry, pose, unitDir, distance, buf, outputFlags, fd1, filterCall, cache, inflation);
+ blockingHit = buf.hasBlock;
+ if(blockingHit)
+ {
+ if(buf.nbTouches < hitBufferSize)
+ {
+ hitBuffer[buf.nbTouches] = buf.block;
+ return PxI32(buf.nbTouches+1);
+ }
+ else // overflow, drop the last touch
+ {
+ hitBuffer[hitBufferSize-1] = buf.block;
+ return -1;
+ }
+ } else
+ // no block
+ return PxI32(buf.nbTouches);
+}
+
+PxI32 PxSceneQueryExt::overlapMultiple( const PxScene& scene,
+ const PxGeometry& geometry, const PxTransform& pose,
+ PxOverlapHit* hitBuffer, PxU32 hitBufferSize,
+ const PxSceneQueryFilterData& filterData,
+ PxSceneQueryFilterCallback* filterCall,
+ PxClientID queryClient)
+{
+ PxQueryFilterData fd1 = filterData; fd1.clientId = queryClient;
+ fd1.flags |= PxQueryFlag::eNO_BLOCK;
+ PxOverlapBuffer buf(hitBuffer, hitBufferSize);
+ scene.overlap(geometry, pose, buf, fd1, filterCall);
+ if(buf.hasBlock)
+ {
+ if(buf.nbTouches < hitBufferSize)
+ {
+ hitBuffer[buf.nbTouches] = buf.block;
+ return PxI32(buf.nbTouches+1);
+ }
+ else // overflow, drop the last touch
+ {
+ hitBuffer[hitBufferSize-1] = buf.block;
+ return -1;
+ }
+ } else
+ // no block
+ return PxI32(buf.nbTouches);
+}
+
+bool PxSceneQueryExt::overlapAny( const PxScene& scene,
+ const PxGeometry& geometry, const PxTransform& pose,
+ PxOverlapHit& hit,
+ const PxSceneQueryFilterData& filterData,
+ PxSceneQueryFilterCallback* filterCall,
+ PxClientID queryClient)
+{
+ PxSceneQueryFilterData fdAny = filterData;
+ fdAny.flags |= (PxQueryFlag::eANY_HIT | PxQueryFlag::eNO_BLOCK);
+ fdAny.clientId = queryClient;
+ PxOverlapBuffer buf;
+ scene.overlap(geometry, pose, buf, fdAny, filterCall);
+ hit = buf.block;
+ return buf.hasBlock;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSerialization.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtSerialization.h
new file mode 100644
index 00000000..390b0ad3
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSerialization.h
@@ -0,0 +1,44 @@
+// 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 EXT_SERIALIZATION_H
+#define EXT_SERIALIZATION_H
+
+namespace physx
+{
+namespace Ext
+{
+ void RegisterExtensionsSerializers(PxSerializationRegistry& sr);
+ void UnregisterExtensionsSerializers(PxSerializationRegistry& sr);
+ void GetExtensionsBinaryMetaData(PxOutputStream& stream);
+}
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSharedQueueEntryPool.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtSharedQueueEntryPool.h
new file mode 100644
index 00000000..9b01718d
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSharedQueueEntryPool.h
@@ -0,0 +1,156 @@
+// 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_EXTENSIONS_NP_SHARED_QUEUE_ENTRY_POOL_H
+#define PX_PHYSICS_EXTENSIONS_NP_SHARED_QUEUE_ENTRY_POOL_H
+
+#include "CmPhysXCommon.h"
+#include "PsAllocator.h"
+#include "PsArray.h"
+#include "PsSList.h"
+
+namespace physx
+{
+namespace Ext
+{
+ class SharedQueueEntry : public Ps::SListEntry
+ {
+ public:
+ SharedQueueEntry(void* objectRef) : mObjectRef(objectRef), mPooledEntry(false) {}
+ SharedQueueEntry() : mObjectRef(NULL), mPooledEntry(true) {}
+
+ public:
+ void* mObjectRef;
+ bool mPooledEntry; // True if the entry was preallocated in a pool
+ };
+
+#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 // Because of the SList member I assume*/
+
+ template<class Alloc = typename Ps::AllocatorTraits<SharedQueueEntry>::Type >
+ class SharedQueueEntryPool : private Alloc
+ {
+ public:
+ SharedQueueEntryPool(PxU32 poolSize, const Alloc& alloc = Alloc(PX_DEBUG_EXP("SharedQueueEntryPool")));
+ ~SharedQueueEntryPool();
+
+ SharedQueueEntry* getEntry(void* objectRef);
+ void putEntry(SharedQueueEntry& entry);
+
+ private:
+ SharedQueueEntry* mTaskEntryPool;
+ Ps::SList mTaskEntryPtrPool;
+ };
+
+#if PX_VC
+#pragma warning(pop)
+#endif
+
+} // namespace Ext
+
+
+template <class Alloc>
+Ext::SharedQueueEntryPool<Alloc>::SharedQueueEntryPool(PxU32 poolSize, const Alloc& alloc)
+ : Alloc(alloc)
+{
+ Ps::AlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc("SharedQueueEntryPool");
+
+ mTaskEntryPool = poolSize ? reinterpret_cast<SharedQueueEntry*>(alignedAlloc.allocate(sizeof(SharedQueueEntry) * poolSize, __FILE__, __LINE__)) : NULL;
+
+ if (mTaskEntryPool)
+ {
+ for(PxU32 i=0; i < poolSize; i++)
+ {
+ PX_ASSERT((size_t(&mTaskEntryPool[i]) & (PX_SLIST_ALIGNMENT-1)) == 0); // The SList entry must be aligned according to PX_SLIST_ALIGNMENT
+
+ PX_PLACEMENT_NEW(&mTaskEntryPool[i], SharedQueueEntry)();
+ PX_ASSERT(mTaskEntryPool[i].mPooledEntry == true);
+ mTaskEntryPtrPool.push(mTaskEntryPool[i]);
+ }
+ }
+}
+
+
+template <class Alloc>
+Ext::SharedQueueEntryPool<Alloc>::~SharedQueueEntryPool()
+{
+ if (mTaskEntryPool)
+ {
+ Ps::AlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc("SharedQueueEntryPool");
+ alignedAlloc.deallocate(mTaskEntryPool);
+ }
+}
+
+
+template <class Alloc>
+Ext::SharedQueueEntry* Ext::SharedQueueEntryPool<Alloc>::getEntry(void* objectRef)
+{
+ SharedQueueEntry* e = static_cast<SharedQueueEntry*>(mTaskEntryPtrPool.pop());
+ if (e)
+ {
+ PX_ASSERT(e->mPooledEntry == true);
+ e->mObjectRef = objectRef;
+ return e;
+ }
+ else
+ {
+ Ps::AlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc;
+ e = reinterpret_cast<SharedQueueEntry*>(alignedAlloc.allocate(sizeof(SharedQueueEntry), __FILE__, __LINE__));
+ if (e)
+ {
+ PX_PLACEMENT_NEW(e, SharedQueueEntry)(objectRef);
+ PX_ASSERT(e->mPooledEntry == false);
+ }
+
+ return e;
+ }
+}
+
+
+template <class Alloc>
+void Ext::SharedQueueEntryPool<Alloc>::putEntry(Ext::SharedQueueEntry& entry)
+{
+ if (entry.mPooledEntry)
+ {
+ entry.mObjectRef = NULL;
+ mTaskEntryPtrPool.push(entry);
+ }
+ else
+ {
+ Ps::AlignedAllocator<PX_SLIST_ALIGNMENT, Alloc> alignedAlloc;
+ alignedAlloc.deallocate(&entry);
+ }
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSimpleFactory.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtSimpleFactory.cpp
new file mode 100644
index 00000000..41a6176f
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSimpleFactory.cpp
@@ -0,0 +1,385 @@
+// 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/PxMathUtils.h"
+#include "foundation/PxQuat.h"
+#include "CmPhysXCommon.h"
+#include "PsFoundation.h"
+#include "PsUtilities.h"
+#include "PsInlineArray.h"
+#include "PxSimpleFactory.h"
+#include "PxRigidStatic.h"
+#include "PxSphereGeometry.h"
+#include "PxBoxGeometry.h"
+#include "PxCapsuleGeometry.h"
+#include "PxConvexMeshGeometry.h"
+#include "PxPlaneGeometry.h"
+#include "PxRigidBodyExt.h"
+#include "PxRigidStatic.h"
+#include "PxScene.h"
+#include "PxShape.h"
+#include "PxRigidDynamic.h"
+#include "CmPhysXCommon.h"
+#include "PxPhysics.h"
+
+using namespace physx;
+using namespace shdfnd;
+
+namespace
+{
+
+bool isDynamicGeometry(PxGeometryType::Enum type)
+{
+ return type == PxGeometryType::eBOX
+ || type == PxGeometryType::eSPHERE
+ || type == PxGeometryType::eCAPSULE
+ || type == PxGeometryType::eCONVEXMESH;
+}
+}
+
+namespace physx
+{
+PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk,
+ const PxTransform& transform,
+ PxShape& shape,
+ PxReal density)
+{
+ PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateDynamic: transform is not valid.");
+
+ PxRigidDynamic* actor = sdk.createRigidDynamic(transform);
+ if(actor)
+ {
+ actor->attachShape(shape);
+ PxRigidBodyExt::updateMassAndInertia(*actor, density);
+ }
+ return actor;
+}
+
+PxRigidDynamic* PxCreateDynamic(PxPhysics& sdk,
+ const PxTransform& transform,
+ const PxGeometry& geometry,
+ PxMaterial& material,
+ PxReal density,
+ const PxTransform& shapeOffset)
+{
+ PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateDynamic: transform is not valid.");
+ PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateDynamic: shapeOffset is not valid.");
+
+ if(!isDynamicGeometry(geometry.getType()) || density <= 0.0f)
+ return NULL;
+
+ PxShape* shape = sdk.createShape(geometry, material, true);
+ if(!shape)
+ return NULL;
+
+ shape->setLocalPose(shapeOffset);
+
+ PxRigidDynamic* body = shape ? PxCreateDynamic(sdk, transform, *shape, density) : NULL;
+ shape->release();
+ return body;
+}
+
+
+
+PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk,
+ const PxTransform& transform,
+ PxShape& shape,
+ PxReal density)
+{
+ PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateKinematic: transform is not valid.");
+
+ bool isDynGeom = isDynamicGeometry(shape.getGeometryType());
+ if(isDynGeom && density <= 0.0f)
+ return NULL;
+
+ PxRigidDynamic* actor = sdk.createRigidDynamic(transform);
+ if(actor)
+ {
+ actor->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+ if(!isDynGeom)
+ shape.setFlag(PxShapeFlag::eSIMULATION_SHAPE, false);
+
+ actor->attachShape(shape);
+
+ if(isDynGeom)
+ PxRigidBodyExt::updateMassAndInertia(*actor, density);
+ else
+ {
+ actor->setMass(1.f);
+ actor->setMassSpaceInertiaTensor(PxVec3(1.f,1.f,1.f));
+ }
+ }
+
+ return actor;
+}
+
+
+PxRigidDynamic* PxCreateKinematic(PxPhysics& sdk,
+ const PxTransform& transform,
+ const PxGeometry& geometry,
+ PxMaterial& material,
+ PxReal density,
+ const PxTransform& shapeOffset)
+{
+ PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateKinematic: transform is not valid.");
+ PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateKinematic: shapeOffset is not valid.");
+
+ bool isDynGeom = isDynamicGeometry(geometry.getType());
+ if(isDynGeom && density <= 0.0f)
+ return NULL;
+
+ PxShape* shape = sdk.createShape(geometry, material, true);
+ if(!shape)
+ return NULL;
+
+ shape->setLocalPose(shapeOffset);
+
+ PxRigidDynamic* body = PxCreateKinematic(sdk, transform, *shape, density);
+ shape->release();
+ return body;
+}
+
+
+
+
+PxRigidStatic* PxCreateStatic(PxPhysics& sdk,
+ const PxTransform& transform,
+ PxShape& shape)
+{
+ PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateStatic: transform is not valid.");
+
+ PxRigidStatic* s = sdk.createRigidStatic(transform);
+ if(s)
+ s->attachShape(shape);
+ return s;
+}
+
+PxRigidStatic* PxCreateStatic(PxPhysics& sdk,
+ const PxTransform& transform,
+ const PxGeometry& geometry,
+ PxMaterial& material,
+ const PxTransform& shapeOffset)
+{
+
+ PX_CHECK_AND_RETURN_NULL(transform.isValid(), "PxCreateStatic: transform is not valid.");
+ PX_CHECK_AND_RETURN_NULL(shapeOffset.isValid(), "PxCreateStatic: shapeOffset is not valid.");
+
+ PxShape* shape = sdk.createShape(geometry, material, true);
+ if(!shape)
+ return NULL;
+
+ shape->setLocalPose(shapeOffset);
+
+ PxRigidStatic* s = PxCreateStatic(sdk, transform, *shape);
+ shape->release();
+ return s;
+}
+
+
+
+
+PxRigidStatic* PxCreatePlane(PxPhysics& sdk,
+ const PxPlane& plane,
+ PxMaterial& material)
+{
+ PX_CHECK_AND_RETURN_NULL(plane.n.isFinite(), "PxCreatePlane: plane normal is not valid.");
+
+ if (!plane.n.isNormalized())
+ return NULL;
+
+ return PxCreateStatic(sdk, PxTransformFromPlaneEquation(plane), PxPlaneGeometry(), material);
+}
+
+
+PxShape* PxCloneShape(PxPhysics &physics, const PxShape& from, bool isExclusive)
+{
+ Ps::InlineArray<PxMaterial*, 64> materials;
+ PxU16 materialCount = from.getNbMaterials();
+ materials.resize(materialCount);
+ from.getMaterials(materials.begin(), materialCount);
+
+ PxShape* to = physics.createShape(from.getGeometry().any(), materials.begin(), materialCount, isExclusive, from.getFlags());
+
+ to->setLocalPose(from.getLocalPose());
+ to->setContactOffset(from.getContactOffset());
+ to->setRestOffset(from.getRestOffset());
+ to->setSimulationFilterData(from.getSimulationFilterData());
+ to->setQueryFilterData(from.getQueryFilterData());
+ return to;
+}
+
+
+namespace
+{
+ void copyStaticProperties(PxPhysics& physics, PxRigidActor& to, const PxRigidActor& from)
+ {
+ Ps::InlineArray<PxShape*, 64> shapes;
+ shapes.resize(from.getNbShapes());
+
+ PxU32 shapeCount = from.getNbShapes();
+ from.getShapes(shapes.begin(), shapeCount);
+
+ for(PxU32 i = 0; i < shapeCount; i++)
+ {
+ PxShape* s = shapes[i];
+ if(!s->isExclusive())
+ to.attachShape(*s);
+ else
+ {
+ PxShape* newShape = physx::PxCloneShape(physics, *s, true);
+ to.attachShape(*newShape);
+ newShape->release();
+ }
+ }
+
+ to.setActorFlags(from.getActorFlags());
+ to.setOwnerClient(from.getOwnerClient());
+ to.setClientBehaviorFlags(from.getClientBehaviorFlags());
+ to.setDominanceGroup(from.getDominanceGroup());
+ }
+}
+
+PxRigidStatic* PxCloneStatic(PxPhysics& physicsSDK,
+ const PxTransform& transform,
+ const PxRigidActor& from)
+{
+ PxRigidStatic* to = physicsSDK.createRigidStatic(transform);
+ if(!to)
+ return NULL;
+
+ copyStaticProperties(physicsSDK, *to, from);
+
+ return to;
+}
+
+PxRigidDynamic* PxCloneDynamic(PxPhysics& physicsSDK,
+ const PxTransform& transform,
+ const PxRigidDynamic& from)
+{
+ PxRigidDynamic* to = physicsSDK.createRigidDynamic(transform);
+ if(!to)
+ return NULL;
+
+ copyStaticProperties(physicsSDK, *to, from);
+
+
+ to->setRigidBodyFlags(from.getRigidBodyFlags());
+
+ to->setMass(from.getMass());
+ to->setMassSpaceInertiaTensor(from.getMassSpaceInertiaTensor());
+ to->setCMassLocalPose(from.getCMassLocalPose());
+
+ to->setLinearVelocity(from.getLinearVelocity());
+ to->setAngularVelocity(from.getAngularVelocity());
+
+ to->setLinearDamping(from.getAngularDamping());
+ to->setAngularDamping(from.getAngularDamping());
+
+ PxU32 posIters, velIters;
+ from.getSolverIterationCounts(posIters, velIters);
+ to->setSolverIterationCounts(posIters, velIters);
+
+ to->setMaxAngularVelocity(from.getMaxAngularVelocity());
+ to->setMaxDepenetrationVelocity(from.getMaxDepenetrationVelocity());
+ to->setSleepThreshold(from.getSleepThreshold());
+ to->setStabilizationThreshold(from.getStabilizationThreshold());
+ to->setMinCCDAdvanceCoefficient(from.getMinCCDAdvanceCoefficient());
+ to->setContactReportThreshold(from.getContactReportThreshold());
+ to->setMaxContactImpulse(from.getMaxContactImpulse());
+
+ return to;
+}
+
+namespace
+{
+ PxTransform scalePosition(const PxTransform& t, PxReal scale)
+ {
+ return PxTransform(t.p*scale, t.q);
+ }
+}
+
+void PxScaleRigidActor(PxRigidActor& actor, PxReal scale, bool scaleMassProps)
+{
+ PX_CHECK_AND_RETURN(scale > 0,
+ "PxScaleRigidActor requires that the scale parameter is greater than zero");
+
+ Ps::InlineArray<PxShape*, 64> shapes;
+ shapes.resize(actor.getNbShapes());
+ actor.getShapes(shapes.begin(), shapes.size());
+
+ for(PxU32 i=0;i<shapes.size();i++)
+ {
+ shapes[i]->setLocalPose(scalePosition(shapes[i]->getLocalPose(), scale));
+ PxGeometryHolder h = shapes[i]->getGeometry();
+
+ switch(h.getType())
+ {
+ case PxGeometryType::eSPHERE:
+ h.sphere().radius *= scale;
+ break;
+ case PxGeometryType::ePLANE:
+ break;
+ case PxGeometryType::eCAPSULE:
+ h.capsule().halfHeight *= scale;
+ h.capsule().radius *= scale;
+ break;
+ case PxGeometryType::eBOX:
+ h.box().halfExtents *= scale;
+ break;
+ case PxGeometryType::eCONVEXMESH:
+ h.convexMesh().scale.scale *= scale;
+ break;
+ case PxGeometryType::eTRIANGLEMESH:
+ h.triangleMesh().scale.scale *= scale;
+ break;
+ case PxGeometryType::eHEIGHTFIELD:
+ h.heightField().heightScale *= scale;
+ h.heightField().rowScale *= scale;
+ h.heightField().columnScale *= scale;
+ break;
+ case PxGeometryType::eINVALID:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ PX_ASSERT(0);
+ }
+ shapes[i]->setGeometry(h.any());
+ }
+
+ if(!scaleMassProps)
+ return;
+
+ PxRigidDynamic* dynamic = (&actor)->is<PxRigidDynamic>();
+ if(!dynamic)
+ return;
+
+ PxReal scale3 = scale*scale*scale;
+ dynamic->setMass(dynamic->getMass()*scale3);
+ dynamic->setMassSpaceInertiaTensor(dynamic->getMassSpaceInertiaTensor()*scale3*scale*scale);
+ dynamic->setCMassLocalPose(scalePosition(dynamic->getCMassLocalPose(), scale));
+}
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSmoothNormals.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtSmoothNormals.cpp
new file mode 100644
index 00000000..35d511cc
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSmoothNormals.cpp
@@ -0,0 +1,145 @@
+// 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/PxMemory.h"
+#include "PxSmoothNormals.h"
+#include "PsMathUtils.h"
+#include "PsUserAllocated.h"
+#include "PsUtilities.h"
+#include "CmPhysXCommon.h"
+
+using namespace physx;
+
+static PxReal computeAngle(const PxVec3* verts, const PxU32* refs, PxU32 vref)
+{
+ PxU32 e0=0,e2=0;
+ if(vref==refs[0])
+ {
+ e0 = 2;
+ e2 = 1;
+ }
+ else if(vref==refs[1])
+ {
+ e0 = 2;
+ e2 = 0;
+ }
+ else if(vref==refs[2])
+ {
+ e0 = 0;
+ e2 = 1;
+ }
+ else
+ {
+ PX_ASSERT(0);
+ }
+ const PxVec3 edge0 = verts[refs[e0]] - verts[vref];
+ const PxVec3 edge1 = verts[refs[e2]] - verts[vref];
+
+ return Ps::angle(edge0, edge1);
+}
+
+bool PxBuildSmoothNormals(PxU32 nbTris, PxU32 nbVerts, const PxVec3* verts, const PxU32* dFaces, const PxU16* wFaces, PxVec3* normals, bool flip)
+{
+ if(!verts || !normals || !nbTris || !nbVerts)
+ return false;
+
+ // Get correct destination buffers
+ // - if available, write directly to user-provided buffers
+ // - else get some ram and keep track of it
+ PxVec3* FNormals = reinterpret_cast<PxVec3*>(PX_ALLOC_TEMP(sizeof(PxVec3)*nbTris, "PxVec3"));
+ if(!FNormals) return false;
+
+ // Compute face normals
+ const PxU32 c = PxU32(flip!=0);
+ for(PxU32 i=0; i<nbTris; i++)
+ {
+ // compute indices outside of array index to workaround
+ // SNC bug which was generating incorrect addresses
+ const PxU32 i0 = i*3+0;
+ const PxU32 i1 = i*3+1+c;
+ const PxU32 i2 = i*3+2-c;
+
+ const PxU32 Ref0 = dFaces ? dFaces[i0] : wFaces ? wFaces[i0] : 0;
+ const PxU32 Ref1 = dFaces ? dFaces[i1] : wFaces ? wFaces[i1] : 1;
+ const PxU32 Ref2 = dFaces ? dFaces[i2] : wFaces ? wFaces[i2] : 2;
+
+ FNormals[i] = (verts[Ref2]-verts[Ref0]).cross(verts[Ref1] - verts[Ref0]);
+ PX_ASSERT(!FNormals[i].isZero());
+ FNormals[i].normalize();
+ }
+
+ // Compute vertex normals
+ PxMemSet(normals, 0, nbVerts*sizeof(PxVec3));
+
+ // TTP 3751
+ PxVec3* TmpNormals = reinterpret_cast<PxVec3*>(PX_ALLOC_TEMP(sizeof(PxVec3)*nbVerts, "PxVec3"));
+ PxMemSet(TmpNormals, 0, nbVerts*sizeof(PxVec3));
+ for(PxU32 i=0;i<nbTris;i++)
+ {
+ PxU32 Ref[3];
+ Ref[0] = dFaces ? dFaces[i*3+0] : wFaces ? wFaces[i*3+0] : 0;
+ Ref[1] = dFaces ? dFaces[i*3+1] : wFaces ? wFaces[i*3+1] : 1;
+ Ref[2] = dFaces ? dFaces[i*3+2] : wFaces ? wFaces[i*3+2] : 2;
+
+ for(PxU32 j=0;j<3;j++)
+ {
+ if(TmpNormals[Ref[j]].isZero())
+ TmpNormals[Ref[j]] = FNormals[i];
+ }
+ }
+ //~TTP 3751
+
+ for(PxU32 i=0;i<nbTris;i++)
+ {
+ PxU32 Ref[3];
+ Ref[0] = dFaces ? dFaces[i*3+0] : wFaces ? wFaces[i*3+0] : 0;
+ Ref[1] = dFaces ? dFaces[i*3+1] : wFaces ? wFaces[i*3+1] : 1;
+ Ref[2] = dFaces ? dFaces[i*3+2] : wFaces ? wFaces[i*3+2] : 2;
+
+ normals[Ref[0]] += FNormals[i] * computeAngle(verts, Ref, Ref[0]);
+ normals[Ref[1]] += FNormals[i] * computeAngle(verts, Ref, Ref[1]);
+ normals[Ref[2]] += FNormals[i] * computeAngle(verts, Ref, Ref[2]);
+ }
+
+ // Normalize vertex normals
+ for(PxU32 i=0;i<nbVerts;i++)
+ {
+ if(normals[i].isZero())
+ normals[i] = TmpNormals[i];
+// PX_ASSERT(!normals[i].isZero());
+ normals[i].normalize();
+ }
+
+ PX_FREE_AND_RESET(TmpNormals); // TTP 3751
+ PX_FREE_AND_RESET(FNormals);
+
+ return true;
+}
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.cpp
new file mode 100644
index 00000000..bb7bc10b
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.cpp
@@ -0,0 +1,228 @@
+// 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 "ExtSphericalJoint.h"
+#include "ExtConstraintHelper.h"
+#include "CmConeLimitHelper.h"
+#include "CmRenderOutput.h"
+#include "CmVisualization.h"
+
+#include "common/PxSerialFramework.h"
+
+using namespace physx;
+using namespace Ext;
+
+namespace physx
+{
+ PxSphericalJoint* PxSphericalJointCreate(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1);
+}
+
+PxSphericalJoint* physx::PxSphericalJointCreate(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+{
+ PX_CHECK_AND_RETURN_NULL(localFrame0.isSane(), "PxSphericalJointCreate: local frame 0 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL(localFrame1.isSane(), "PxSphericalJointCreate: local frame 1 is not a valid transform");
+ PX_CHECK_AND_RETURN_NULL(actor0 != actor1, "PxSphericalJointCreate: actors must be different");
+ PX_CHECK_AND_RETURN_NULL((actor0 && actor0->is<PxRigidBody>()) || (actor1 && actor1->is<PxRigidBody>()), "PxSphericalJointCreate: at least one actor must be dynamic");
+
+ SphericalJoint* j;
+ PX_NEW_SERIALIZED(j,SphericalJoint)(physics.getTolerancesScale(), actor0, localFrame0, actor1, localFrame1);
+
+ if(j->attach(physics, actor0, actor1))
+ return j;
+
+ PX_DELETE(j);
+ return NULL;
+}
+
+void SphericalJoint::setProjectionLinearTolerance(PxReal tolerance)
+{
+ PX_CHECK_AND_RETURN(PxIsFinite(tolerance) && tolerance >=0, "PxSphericalJoint::setProjectionLinearTolerance: invalid parameter");
+ data().projectionLinearTolerance = tolerance;
+ markDirty();
+}
+
+PxReal SphericalJoint::getProjectionLinearTolerance() const
+{
+ return data().projectionLinearTolerance;
+}
+
+void SphericalJoint::setLimitCone(const PxJointLimitCone &limit)
+{
+ PX_CHECK_AND_RETURN(limit.isValid(), "PxSphericalJoint::setLimit: invalid parameter");
+ data().limit = limit;
+ markDirty();
+}
+
+PxJointLimitCone SphericalJoint::getLimitCone() const
+{
+ return data().limit;
+}
+
+
+PxSphericalJointFlags SphericalJoint::getSphericalJointFlags(void) const
+{
+ return data().jointFlags;
+}
+
+void SphericalJoint::setSphericalJointFlags(PxSphericalJointFlags flags)
+{
+ data().jointFlags = flags;
+}
+void SphericalJoint::setSphericalJointFlag(PxSphericalJointFlag::Enum flag, bool value)
+{
+ if(value)
+ data().jointFlags |= flag;
+ else
+ data().jointFlags &= ~flag;
+ markDirty();
+}
+
+
+void* Ext::SphericalJoint::prepareData()
+{
+ SphericalJointData& d = data();
+ if(d.jointFlags & PxSphericalJointFlag::eLIMIT_ENABLED)
+ {
+ d.tanQYLimit = PxTan(d.limit.yAngle/4);
+ d.tanQZLimit = PxTan(d.limit.zAngle/4);
+ d.tanQPad = PxTan(d.limit.contactDistance/4);
+ }
+ return SphericalJointT::prepareData();
+}
+
+namespace
+{
+
+void SphericalJointVisualize(PxConstraintVisualizer& viz,
+ const void* constantBlock,
+ const PxTransform& body0Transform,
+ const PxTransform& body1Transform,
+ PxU32 /*flags*/)
+{
+ using namespace joint;
+ const SphericalJointData& data = *reinterpret_cast<const SphericalJointData*>(constantBlock);
+
+ PxTransform cA2w = body0Transform * data.c2b[0];
+ PxTransform cB2w = body1Transform * data.c2b[1];
+
+ viz.visualizeJointFrames(cA2w, cB2w);
+
+
+ if(data.jointFlags & PxSphericalJointFlag::eLIMIT_ENABLED)
+ {
+ 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);
+
+ PxVec3 tanQSwing = PxVec3(0, Ps::tanHalf(swing.z,swing.w), -Ps::tanHalf(swing.y,swing.w));
+ Cm::ConeLimitHelper coneHelper(data.tanQZLimit, data.tanQYLimit, data.tanQPad);
+ viz.visualizeLimitCone(cA2w, data.tanQZLimit, data.tanQYLimit,
+ !coneHelper.contains(tanQSwing));
+ }
+}
+
+
+
+void SphericalJointProject(const void* constantBlock,
+ PxTransform& bodyAToWorld,
+ PxTransform& bodyBToWorld,
+ bool projectToA)
+{
+ using namespace joint;
+
+ const SphericalJointData& data = *reinterpret_cast<const SphericalJointData*>(constantBlock);
+
+ PxTransform cA2w, cB2w, cB2cA, projected;
+ joint::computeDerived(data, bodyAToWorld, bodyBToWorld, cA2w, cB2w, cB2cA);
+
+ bool linearTrunc;
+ projected.p = truncateLinear(cB2cA.p, data.projectionLinearTolerance, linearTrunc);
+
+ if(linearTrunc)
+ {
+ projected.q = cB2cA.q;
+ projectTransforms(bodyAToWorld, bodyBToWorld, cA2w, cB2w, projected, data, projectToA);
+ }
+}
+}
+
+
+bool Ext::SphericalJoint::attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1)
+{
+ mPxConstraint = physics.createConstraint(actor0, actor1, *this, sShaders, sizeof(SphericalJointData));
+ return mPxConstraint!=NULL;
+}
+
+void SphericalJoint::exportExtraData(PxSerializationContext& stream)
+{
+ if(mData)
+ {
+ stream.alignData(PX_SERIAL_ALIGN);
+ stream.writeData(mData, sizeof(SphericalJointData));
+ }
+ stream.writeName(mName);
+}
+
+void SphericalJoint::importExtraData(PxDeserializationContext& context)
+{
+ if(mData)
+ mData = context.readExtraData<SphericalJointData, PX_SERIAL_ALIGN>();
+ context.readName(mName);
+}
+
+void SphericalJoint::resolveReferences(PxDeserializationContext& context)
+{
+ setPxConstraint(resolveConstraintPtr(context, getPxConstraint(), getConnector(), sShaders));
+}
+
+SphericalJoint* SphericalJoint::createObject(PxU8*& address, PxDeserializationContext& context)
+{
+ SphericalJoint* obj = new (address) SphericalJoint(PxBaseFlag::eIS_RELEASABLE);
+ address += sizeof(SphericalJoint);
+ obj->importExtraData(context);
+ obj->resolveReferences(context);
+ return obj;
+}
+
+// global function to share the joint shaders with API capture
+const PxConstraintShaderTable* Ext::GetSphericalJointShaderTable()
+{
+ return &SphericalJoint::getConstraintShaderTable();
+}
+
+//~PX_SERIALIZATION
+PxConstraintShaderTable Ext::SphericalJoint::sShaders = { Ext::SphericalJointSolverPrep, SphericalJointProject, SphericalJointVisualize, PxConstraintFlag::Enum(0) };
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.h
new file mode 100644
index 00000000..cef79293
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJoint.h
@@ -0,0 +1,151 @@
+// 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_SPHERICALJOINTCONSTRAINT_H
+#define NP_SPHERICALJOINTCONSTRAINT_H
+
+#include "ExtJoint.h"
+#include "PxSphericalJoint.h"
+#include "CmUtils.h"
+
+namespace physx
+{
+struct PxSphericalJointGeneratedValues;
+namespace Ext
+{
+ struct SphericalJointData: public JointData
+ {
+ //= 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.
+ //==================================================================================================
+ PxJointLimitCone limit;
+ PxReal tanQYLimit;
+ PxReal tanQZLimit;
+ PxReal tanQPad;
+
+ PxReal projectionLinearTolerance;
+
+ PxSphericalJointFlags jointFlags;
+ // forestall compiler complaints about not being able to generate a constructor
+ private:
+ SphericalJointData(const PxJointLimitCone &cone):
+ limit(cone) {}
+ };
+
+ typedef Joint<PxSphericalJoint, PxSphericalJointGeneratedValues> SphericalJointT;
+
+ class SphericalJoint : public SphericalJointT
+ {
+ //= 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
+ SphericalJoint(PxBaseFlags baseFlags) : SphericalJointT(baseFlags) {}
+ virtual void exportExtraData(PxSerializationContext& context);
+ void importExtraData(PxDeserializationContext& context);
+ void resolveReferences(PxDeserializationContext& context);
+ static SphericalJoint* createObject(PxU8*& address, PxDeserializationContext& context);
+ static void getBinaryMetaData(PxOutputStream& stream);
+//~PX_SERIALIZATION
+ virtual ~SphericalJoint()
+ {
+ if(getBaseFlags()&PxBaseFlag::eOWNS_MEMORY)
+ PX_FREE(mData);
+ }
+
+ SphericalJoint(const PxTolerancesScale& /*scale*/,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ : SphericalJointT(PxJointConcreteType::eSPHERICAL, PxBaseFlag::eOWNS_MEMORY | PxBaseFlag::eIS_RELEASABLE)
+ {
+ SphericalJointData* data = reinterpret_cast<SphericalJointData*>(PX_ALLOC(sizeof(SphericalJointData), "SphericalJointData"));
+ Cm::markSerializedMem(data, sizeof(SphericalJointData));
+ mData = data;
+
+ initCommonData(*data,actor0, localFrame0, actor1, localFrame1);
+ data->projectionLinearTolerance = 1e10f;
+ data->limit = PxJointLimitCone(PxPi/2, PxPi/2);
+ data->jointFlags = PxSphericalJointFlags();
+ }
+
+ void setProjectionLinearTolerance(PxReal distance);
+ PxReal getProjectionLinearTolerance() const;
+
+ void setLimitCone(const PxJointLimitCone &limit);
+ PxJointLimitCone getLimitCone() const;
+
+ PxSphericalJointFlags getSphericalJointFlags(void) const;
+ void setSphericalJointFlags(PxSphericalJointFlags flags);
+ void setSphericalJointFlag(PxSphericalJointFlag::Enum flag, bool value);
+
+ void* prepareData();
+
+ bool attach(PxPhysics &physics, PxRigidActor* actor0, PxRigidActor* actor1);
+
+ static const PxConstraintShaderTable& getConstraintShaderTable() { return sShaders; }
+
+ virtual PxConstraintSolverPrep getPrep() const { return sShaders.solverPrep; }
+
+ private:
+
+ static PxConstraintShaderTable sShaders;
+
+ PX_FORCE_INLINE SphericalJointData& data() const
+ {
+ return *static_cast<SphericalJointData*>(mData);
+ }
+ };
+
+} // namespace Ext
+
+namespace Ext
+{
+ extern "C" PxU32 SphericalJointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 maxConstraints,
+ PxConstraintInvMassScale& invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w);
+
+ // global function to share the joint shaders with API capture
+ extern "C" const PxConstraintShaderTable* GetSphericalJointShaderTable();
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJointSolverPrep.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJointSolverPrep.cpp
new file mode 100644
index 00000000..937b8a3b
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtSphericalJointSolverPrep.cpp
@@ -0,0 +1,87 @@
+// 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 "ExtSphericalJoint.h"
+#include "ExtConstraintHelper.h"
+#include "CmConeLimitHelper.h"
+#include "CmRenderOutput.h"
+
+namespace physx
+{
+namespace Ext
+{
+ PxU32 SphericalJointSolverPrep(Px1DConstraint* constraints,
+ PxVec3& body0WorldOffset,
+ PxU32 /*maxConstraints*/,
+ PxConstraintInvMassScale &invMassScale,
+ const void* constantBlock,
+ const PxTransform& bA2w,
+ const PxTransform& bB2w)
+ {
+
+ using namespace joint;
+ const SphericalJointData& data = *reinterpret_cast<const SphericalJointData*>(constantBlock);
+ invMassScale = data.invMassScale;
+
+
+ PxTransform cA2w = bA2w * data.c2b[0];
+ PxTransform cB2w = bB2w * data.c2b[1];
+
+ if(cB2w.q.dot(cA2w.q)<0)
+ cB2w.q = -cB2w.q;
+
+ body0WorldOffset = cB2w.p-bA2w.p;
+ joint::ConstraintHelper ch(constraints, cB2w.p - bA2w.p, cB2w.p - bB2w.p);
+
+ if(data.jointFlags & PxSphericalJointFlag::eLIMIT_ENABLED)
+ {
+ PxQuat swing, twist;
+ Ps::separateSwingTwist(cA2w.q.getConjugate() * cB2w.q, swing, twist);
+ PX_ASSERT(PxAbs(swing.x)<1e-6f);
+
+ Cm::ConeLimitHelper coneHelper(data.tanQZLimit, data.tanQYLimit, data.tanQPad);
+
+ PxVec3 axis;
+ PxReal error;
+ if(coneHelper.getLimit(swing, axis, error))
+ ch.angularLimit(cA2w.rotate(axis),error,data.limit);
+
+ }
+
+ ch.prepareLockedAxes(cA2w.q, cB2w.q, cA2w.transformInv(cB2w.p), 7, 0);
+
+ return ch.getCount();
+ }
+}//namespace
+
+}
+
+//~PX_SERIALIZATION
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtTaskQueueHelper.h b/PhysX_3.4/Source/PhysXExtensions/src/ExtTaskQueueHelper.h
new file mode 100644
index 00000000..c5f663f2
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtTaskQueueHelper.h
@@ -0,0 +1,66 @@
+// 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_EXTENSIONS_NP_TASK_QUEUE_HELPER_H
+#define PX_PHYSICS_EXTENSIONS_NP_TASK_QUEUE_HELPER_H
+
+#include "task/PxTask.h"
+#include "CmPhysXCommon.h"
+#include "ExtSharedQueueEntryPool.h"
+
+namespace physx
+{
+
+#define EXT_TASK_QUEUE_ENTRY_POOL_SIZE 128
+
+namespace Ext
+{
+ class TaskQueueHelper
+ {
+ public:
+ static PxBaseTask* fetchTask(Ps::SList& taskQueue, Ext::SharedQueueEntryPool<>& entryPool)
+ {
+ SharedQueueEntry* entry = static_cast<SharedQueueEntry*>(taskQueue.pop());
+ if (entry)
+ {
+ PxBaseTask* task = reinterpret_cast<PxBaseTask*>(entry->mObjectRef);
+ entryPool.putEntry(*entry);
+ return task;
+ }
+ else
+ return NULL;
+ }
+ };
+
+} // namespace Ext
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/ExtTriangleMeshExt.cpp b/PhysX_3.4/Source/PhysXExtensions/src/ExtTriangleMeshExt.cpp
new file mode 100644
index 00000000..92702047
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/ExtTriangleMeshExt.cpp
@@ -0,0 +1,183 @@
+// 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 "PxTriangleMeshExt.h"
+#include "PxMeshQuery.h"
+#include "PxGeometryQuery.h"
+#include "PxTriangleMeshGeometry.h"
+#include "PxHeightFieldGeometry.h"
+#include "PxTriangleMesh.h"
+#include "PsAllocator.h"
+
+using namespace physx;
+
+PxMeshOverlapUtil::PxMeshOverlapUtil() : mResultsMemory(mResults), mNbResults(0), mMaxNbResults(256)
+{
+}
+
+PxMeshOverlapUtil::~PxMeshOverlapUtil()
+{
+ if(mResultsMemory != mResults)
+ PX_FREE(mResultsMemory);
+}
+
+PxU32 PxMeshOverlapUtil::findOverlap(const PxGeometry& geom, const PxTransform& geomPose, const PxTriangleMeshGeometry& meshGeom, const PxTransform& meshPose)
+{
+ bool overflow;
+ PxU32 nbTouchedTris = PxMeshQuery::findOverlapTriangleMesh(geom, geomPose, meshGeom, meshPose, mResultsMemory, mMaxNbResults, 0, overflow);
+
+ if(overflow)
+ {
+ const PxU32 maxNbTris = meshGeom.triangleMesh->getNbTriangles();
+ if(!maxNbTris)
+ {
+ mNbResults = 0;
+ return 0;
+ }
+
+ if(mMaxNbResults<maxNbTris)
+ {
+ if(mResultsMemory != mResults)
+ PX_FREE(mResultsMemory);
+
+ mResultsMemory = reinterpret_cast<PxU32*>(PX_ALLOC(sizeof(PxU32)*maxNbTris, "PxMeshOverlapUtil::findOverlap"));
+ mMaxNbResults = maxNbTris;
+ }
+ nbTouchedTris = PxMeshQuery::findOverlapTriangleMesh(geom, geomPose, meshGeom, meshPose, mResultsMemory, mMaxNbResults, 0, overflow);
+ PX_ASSERT(nbTouchedTris);
+ PX_ASSERT(!overflow);
+ }
+ mNbResults = nbTouchedTris;
+ return nbTouchedTris;
+}
+
+PxU32 PxMeshOverlapUtil::findOverlap(const PxGeometry& geom, const PxTransform& geomPose, const PxHeightFieldGeometry& hfGeom, const PxTransform& hfPose)
+{
+ bool overflow = true;
+ PxU32 nbTouchedTris = 0;
+ do
+ {
+ nbTouchedTris = PxMeshQuery::findOverlapHeightField(geom, geomPose, hfGeom, hfPose, mResultsMemory, mMaxNbResults, 0, overflow);
+ if(overflow)
+ {
+ const PxU32 maxNbTris = mMaxNbResults * 2;
+
+ if(mResultsMemory != mResults)
+ PX_FREE(mResultsMemory);
+
+ mResultsMemory = reinterpret_cast<PxU32*>(PX_ALLOC(sizeof(PxU32)*maxNbTris, "PxMeshOverlapUtil::findOverlap"));
+ mMaxNbResults = maxNbTris;
+ }
+ }while(overflow);
+
+ mNbResults = nbTouchedTris;
+ return nbTouchedTris;
+}
+namespace
+{
+template<typename MeshGeometry>
+bool computeMeshPenetrationT(PxVec3& direction,
+ PxReal& depth,
+ const PxGeometry& geom,
+ const PxTransform& geomPose,
+ const MeshGeometry& meshGeom,
+ const PxTransform& meshPose,
+ PxU32 maxIter,
+ PxU32* nbIterOut)
+{
+ PxU32 nbIter = 0;
+ PxTransform pose = geomPose;
+ for (; nbIter < maxIter; nbIter++)
+ {
+ PxVec3 currentDir;
+ PxF32 currentDepth;
+
+ if (!PxGeometryQuery::computePenetration(currentDir, currentDepth, geom, pose, meshGeom, meshPose))
+ break;
+
+ pose.p += currentDir * currentDepth;
+ }
+
+ if(nbIterOut)
+ *nbIterOut = nbIter;
+
+ PxVec3 diff = pose.p - geomPose.p;
+ depth = diff.magnitude();
+
+ if (depth>0)
+ direction = diff / depth;
+
+ return nbIter!=0;
+}
+}
+
+bool physx::PxComputeTriangleMeshPenetration(PxVec3& direction,
+ PxReal& depth,
+ const PxGeometry& geom,
+ const PxTransform& geomPose,
+ const PxTriangleMeshGeometry& meshGeom,
+ const PxTransform& meshPose,
+ PxU32 maxIter,
+ PxU32* nbIter)
+{
+ return computeMeshPenetrationT(direction, depth, geom, geomPose, meshGeom, meshPose, maxIter, nbIter);
+}
+
+
+PxVec3 physx::PxComputeMeshPenetration(PxU32 maxIter, const PxGeometry& geom, const PxTransform& geomPose, const PxTriangleMeshGeometry& meshGeom, const PxTransform& meshPose, PxU32& nb)
+{
+ PxVec3 direction;
+ PxReal depth;
+ computeMeshPenetrationT(direction, depth, geom, geomPose, meshGeom, meshPose, maxIter, &nb);
+ return direction * depth;
+}
+
+
+bool physx::PxComputeHeightFieldPenetration(PxVec3& direction,
+ PxReal& depth,
+ const PxGeometry& geom,
+ const PxTransform& geomPose,
+ const PxHeightFieldGeometry& hfGeom,
+ const PxTransform& meshPose,
+ PxU32 maxIter,
+ PxU32* nbIter)
+{
+ return computeMeshPenetrationT(direction, depth, geom, geomPose, hfGeom, meshPose, maxIter, nbIter);
+}
+
+
+PxVec3 physx::PxComputeHeightFieldPenetration(PxU32 maxIter, const PxGeometry& geom, const PxTransform& geomPose, const PxHeightFieldGeometry& meshGeom, const PxTransform& meshPose, PxU32& nb)
+{
+ PxVec3 direction;
+ PxReal depth;
+ computeMeshPenetrationT(direction, depth, geom, geomPose, meshGeom, meshPose, maxIter, &nb);
+ return direction * depth;
+}
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp
new file mode 100644
index 00000000..981cfa2a
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinaryDeserialization.cpp
@@ -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.
+
+#include "PsHash.h"
+#include "PsHashMap.h"
+#include "PsFoundation.h"
+#include "CmIO.h"
+#include "SnFile.h"
+#include "PsString.h"
+#include "extensions/PxSerialization.h"
+#include "PxPhysics.h"
+#include "PxPhysicsSerialization.h"
+#include "SnSerializationContext.h"
+#include "PxSerializer.h"
+#include "serialization/SnSerializationRegistry.h"
+#include "serialization/SnSerialUtils.h"
+#include "CmCollection.h"
+#include "SnConvX_Align.h"
+
+using namespace physx;
+using namespace Sn;
+
+namespace
+{
+ PX_INLINE PxU8* alignPtr(PxU8* ptr, PxU32 alignment = PX_SERIAL_ALIGN)
+ {
+ if(!alignment)
+ return ptr;
+
+ const PxU32 padding = getPadding(size_t(ptr), alignment);
+ PX_ASSERT(!getPadding(size_t(ptr + padding), alignment));
+ return ptr + padding;
+ }
+
+ PX_FORCE_INLINE PxU32 read32(PxU8*& address)
+ {
+ const PxU32 value = *reinterpret_cast<PxU32*>(address);
+ address += sizeof(PxU32);
+ return value;
+ }
+
+ bool readHeader(PxU8*& address, PxU32& version)
+ {
+ const PxU32 header = read32(address);
+ PX_UNUSED(header);
+
+ version = read32(address);
+
+ const PxU32 binaryVersion = read32(address);
+ PX_UNUSED(binaryVersion);
+ const PxU32 buildNumber = read32(address);
+ PX_UNUSED(buildNumber);
+ const PxU32 platformTag = read32(address);
+ PX_UNUSED(platformTag);
+ const PxU32 markedPadding = read32(address);
+ PX_UNUSED(markedPadding);
+
+#if PX_CHECKED
+ if (header != PX_MAKE_FOURCC('S','E','B','D'))
+ {
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "Buffer contains data with wrong header indicating invalid binary data.");
+ return false;
+ }
+
+ if (!checkCompatibility(version, binaryVersion))
+ {
+ char buffer[512];
+ getCompatibilityVersionsStr(buffer, 512);
+
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "Buffer contains data version (%x-%d) is incompatible with this PhysX sdk.\n These versions would be compatible: %s",
+ version, binaryVersion, buffer);
+ return false;
+ }
+
+ if (platformTag != getBinaryPlatformTag())
+ {
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "Buffer contains data with platform mismatch:\nExpected: %s \nActual: %s\n",
+ getBinaryPlatformName(getBinaryPlatformTag()),
+ getBinaryPlatformName(platformTag));
+ return false;
+ }
+#endif
+ return true;
+ }
+
+ bool checkImportReferences(const ImportReference* importReferences, PxU32 nbImportReferences, const Cm::Collection* externalRefs)
+ {
+ if (!externalRefs)
+ {
+ if (nbImportReferences > 0)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerialization::createCollectionFromBinary: External references needed but no externalRefs collection specified.");
+ return false;
+ }
+ }
+ else
+ {
+ for (PxU32 i=0; i<nbImportReferences;i++)
+ {
+ PxSerialObjectId id = importReferences[i].id;
+ PxType type = importReferences[i].type;
+
+ PxBase* referencedObject = externalRefs->find(id);
+ if (!referencedObject)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerialization::createCollectionFromBinary: External reference %" PX_PRIu64 " expected in externalRefs collection but not found.", id);
+ return false;
+ }
+ if (referencedObject->getConcreteType() != type)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerialization::createCollectionFromBinary: External reference %d type mismatch. Expected %d but found %d in externalRefs collection.", type, referencedObject->getConcreteType());
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+}
+
+PxCollection* PxSerialization::createCollectionFromBinary(void* memBlock, PxSerializationRegistry& sr, const PxCollection* pxExternalRefs)
+{
+#if PX_CHECKED
+ if(size_t(memBlock) & (PX_SERIAL_FILE_ALIGN-1))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "Buffer must be 128-bytes aligned.");
+ return NULL;
+ }
+#endif
+ PxU8* address = reinterpret_cast<PxU8*>(memBlock);
+ const Cm::Collection* externalRefs = static_cast<const Cm::Collection*>(pxExternalRefs);
+
+ PxU32 version;
+ if (!readHeader(address, version))
+ {
+ return NULL;
+ }
+
+ ManifestEntry* manifestTable;
+ PxU32 nbObjectsInCollection;
+ PxU32 objectDataEndOffset;
+
+ // read number of objects in collection
+ address = alignPtr(address);
+ nbObjectsInCollection = read32(address);
+
+ // read manifest (PxU32 offset, PxConcreteType type)
+ {
+ address = alignPtr(address);
+ PxU32 nbManifestEntries = read32(address);
+ PX_ASSERT(*reinterpret_cast<PxU32*>(address) == 0); //first offset is always 0
+ manifestTable = (nbManifestEntries > 0) ? reinterpret_cast<ManifestEntry*>(address) : NULL;
+ address += nbManifestEntries*sizeof(ManifestEntry);
+ objectDataEndOffset = read32(address);
+ }
+
+ ImportReference* importReferences;
+ PxU32 nbImportReferences;
+ // read import references
+ {
+ address = alignPtr(address);
+ nbImportReferences = read32(address);
+ importReferences = (nbImportReferences > 0) ? reinterpret_cast<ImportReference*>(address) : NULL;
+ address += nbImportReferences*sizeof(ImportReference);
+ }
+
+ if (!checkImportReferences(importReferences, nbImportReferences, externalRefs))
+ {
+ return NULL;
+ }
+
+ ExportReference* exportReferences;
+ PxU32 nbExportReferences;
+ // read export references
+ {
+ address = alignPtr(address);
+ nbExportReferences = read32(address);
+ exportReferences = (nbExportReferences > 0) ? reinterpret_cast<ExportReference*>(address) : NULL;
+ address += nbExportReferences*sizeof(ExportReference);
+ }
+
+ // read internal references arrays
+ PxU32 nbInternalPtrReferences = 0;
+ PxU32 nbInternalIdxReferences = 0;
+ InternalReferencePtr* internalPtrReferences = NULL;
+ InternalReferenceIdx* internalIdxReferences = NULL;
+ {
+ address = alignPtr(address);
+
+ nbInternalPtrReferences = read32(address);
+ internalPtrReferences = (nbInternalPtrReferences > 0) ? reinterpret_cast<InternalReferencePtr*>(address) : NULL;
+ address += nbInternalPtrReferences*sizeof(InternalReferencePtr);
+
+ nbInternalIdxReferences = read32(address);
+ internalIdxReferences = (nbInternalIdxReferences > 0) ? reinterpret_cast<InternalReferenceIdx*>(address) : NULL;
+ address += nbInternalIdxReferences*sizeof(InternalReferenceIdx);
+ }
+
+ // create internal references map
+ PxF32 loadFactor = 0.75f;
+ PxF32 _loadFactor = 1.0f / loadFactor;
+ PxU32 hashSize = PxU32((nbInternalPtrReferences + nbInternalIdxReferences + 1)*_loadFactor);
+ InternalRefMap internalReferencesMap(hashSize, loadFactor);
+ {
+ //create hash (we should load the hashes directly from memory)
+ for (PxU32 i=0;i<nbInternalPtrReferences;i++)
+ {
+ const InternalReferencePtr& ref = internalPtrReferences[i];
+ internalReferencesMap.insertUnique( InternalRefKey(ref.reference, ref.kind), SerialObjectIndex(ref.objIndex));
+ }
+ for (PxU32 i=0;i<nbInternalIdxReferences;i++)
+ {
+ const InternalReferenceIdx& ref = internalIdxReferences[i];
+ internalReferencesMap.insertUnique(InternalRefKey(ref.reference, ref.kind), SerialObjectIndex(ref.objIndex));
+ }
+ }
+
+ SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
+ Cm::Collection* collection = static_cast<Cm::Collection*>(PxCreateCollection());
+ PX_ASSERT(collection);
+ collection->mObjects.reserve(PxU32(nbObjectsInCollection*_loadFactor) + 1);
+ if(nbExportReferences > 0)
+ collection->mIds.reserve(PxU32(nbExportReferences*_loadFactor) + 1);
+
+ PxU8* addressObjectData = alignPtr(address);
+ PxU8* addressExtraData = alignPtr(addressObjectData + objectDataEndOffset);
+
+ DeserializationContext context(manifestTable, importReferences, addressObjectData, internalReferencesMap, externalRefs, addressExtraData, version);
+
+ // iterate over memory containing PxBase objects, create the instances, resolve the addresses, import the external data, add to collection.
+ {
+ PxU32 nbObjects = nbObjectsInCollection;
+
+ while(nbObjects--)
+ {
+ address = alignPtr(address);
+ context.alignExtraData();
+
+ // read PxBase header with type and get corresponding serializer.
+ PxBase* header = reinterpret_cast<PxBase*>(address);
+ const PxType classType = header->getConcreteType();
+ const PxSerializer* serializer = sn.getSerializer(classType);
+ PX_ASSERT(serializer);
+
+ PxBase* instance = serializer->createObject(address, context);
+ if (!instance)
+ {
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "Cannot create class instance for concrete type %d.", classType);
+ collection->release();
+ return NULL;
+ }
+
+ collection->internalAdd(instance);
+ }
+ }
+
+ PX_ASSERT(nbObjectsInCollection == collection->internalGetNbObjects());
+
+ // update new collection with export references
+ {
+ PX_ASSERT(addressObjectData != NULL);
+ for (PxU32 i=0;i<nbExportReferences;i++)
+ {
+ bool isExternal;
+ PxU32 manifestIndex = exportReferences[i].objIndex.getIndex(isExternal);
+ PX_ASSERT(!isExternal);
+ PxBase* obj = reinterpret_cast<PxBase*>(addressObjectData + manifestTable[manifestIndex].offset);
+ collection->mIds.insertUnique(exportReferences[i].id, obj);
+ collection->mObjects[obj] = exportReferences[i].id;
+ }
+ }
+
+ PxAddCollectionToPhysics(*collection);
+ return collection;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinarySerialization.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinarySerialization.cpp
new file mode 100644
index 00000000..f9a8b1b9
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnBinarySerialization.cpp
@@ -0,0 +1,402 @@
+// 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 "PsHash.h"
+#include "PsHashMap.h"
+#include "CmIO.h"
+#include "SnFile.h"
+#include "PsString.h"
+#include "PsIntrinsics.h"
+#include "extensions/PxSerialization.h"
+#include "SnSerializationContext.h"
+#include "PxSerializer.h"
+#include "serialization/SnSerialUtils.h"
+#include "serialization/SnSerializationRegistry.h"
+#include "SnConvX_Align.h"
+#include "PxDefaultStreams.h"
+#include "CmCollection.h"
+#include "PxPhysicsVersion.h"
+#include "PsUtilities.h"
+
+using namespace physx;
+using namespace Cm;
+using namespace Sn;
+
+//------------------------------------------------------------------------------------
+//// Binary Serialized PxCollection, format documentation
+//------------------------------------------------------------------------------------
+//
+//
+//------------------------------------------------------------------------------------
+//// overview:
+//// header information
+//// manifest table
+//// import references
+//// export references
+//// internal references
+//// object data
+//// extra data
+//------------------------------------------------------------------------------------
+//
+//
+//------------------------------------------------------------------------------------
+//// header information:
+//// header tag plus various version and platform information
+//------------------------------------------------------------------------------------
+// header SEBD
+// PX_PHYSICS_VERSION
+// PX_BINARY_SERIAL_VERSION
+// PX_BUILD_NUMBER (or 0 if not defined)
+// platform tag
+// markedPadding (on for PX_CHECKED)
+// nbObjectsInCollection
+//
+//
+//------------------------------------------------------------------------------------
+//// manifest table:
+//// one entry per collected object
+//// offsets relative to object data buffer
+//------------------------------------------------------------------------------------
+// alignment
+// PxU32 size
+// (PxU32 offset, PxType type)*size
+// PxU32 endOffset
+//
+//
+//------------------------------------------------------------------------------------
+//// import references:
+//// one entry per required reference to external collection
+//------------------------------------------------------------------------------------
+// alignment
+// PxU32 size
+// (PxSerialObjectId id, PxType type)*size
+//
+//
+//------------------------------------------------------------------------------------
+//// export references:
+//// one entry per object in the collection with id
+//// object indices point into the manifest table (objects in the same collection)
+//------------------------------------------------------------------------------------
+// alignment
+// PxU32 size
+// (PxSerialObjectId id, SerialObjectIndex objIndex)*size
+//
+//
+//------------------------------------------------------------------------------------
+//// internal references:
+//// one entry per reference, kind pair
+//// object indices point either into the manifest table or into the import references
+//// depending on whether the entry references the same collection or the external one
+//// one section for pointer type references and one for index type references.
+//------------------------------------------------------------------------------------
+// alignment
+// PxU32 sizePtrs;
+// (size_t reference, PxU32 kind, SerialObjectIndex objIndex)*sizePtrs
+// PxU32 sizeIdx;
+// (PxU32 reference, PxU32 kind, SerialObjectIndex objIndex)*sizePtrs
+//
+//
+//------------------------------------------------------------------------------------
+//// object data:
+//// serialized PxBase derived class instances
+//// each object size depends on specific class
+//// offsets are stored in manifest table
+//------------------------------------------------------------------------------------
+// alignment
+// (PxConcreteType type, -----)
+// alignment
+// (PxConcreteType type, --------)
+// alignment
+// (PxConcreteType type, --)
+// .
+// .
+//
+//
+// -----------------------------------------------------------------------------------
+//// extra data:
+//// extra data memory block
+//// serialized and deserialized by PxBase implementations
+////----------------------------------------------------------------------------------
+// extra data
+//
+//------------------------------------------------------------------------------------
+
+namespace
+{
+
+ class LegacySerialStream : public PxSerializationContext
+ {
+ public:
+ LegacySerialStream(OutputStreamWriter& writer,
+ const PxCollection& collection,
+ bool exportNames) : mWriter(writer), mCollection(collection), mExportNames(exportNames) {}
+ void writeData(const void* buffer, PxU32 size) { mWriter.write(buffer, size); }
+ PxU32 getTotalStoredSize() { return mWriter.getStoredSize(); }
+ void alignData(PxU32 alignment)
+ {
+ if(!alignment)
+ return;
+
+ PxI32 bytesToPad = PxI32(getPadding(getTotalStoredSize(), alignment));
+ static const PxI32 BUFSIZE = 64;
+ char buf[BUFSIZE];
+ PxMemSet(buf, 0, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE));
+ while(bytesToPad > 0)
+ {
+ writeData(buf, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE));
+ bytesToPad -= BUFSIZE;
+ }
+ PX_ASSERT(!getPadding(getTotalStoredSize(), alignment));
+ }
+
+ virtual void registerReference(PxBase&, PxU32, size_t)
+ {
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Cannot register references during exportData, exportExtraData.");
+ }
+
+ virtual const PxCollection& getCollection() const
+ {
+ return mCollection;
+ }
+ virtual void writeName(const char* name)
+ {
+ PxU32 len = name && mExportNames ? PxU32(strlen(name)) + 1 : 0;
+ writeData(&len, sizeof(len));
+ if(len) writeData(name, len);
+ }
+
+ private:
+ LegacySerialStream& operator=(const LegacySerialStream&);
+ OutputStreamWriter& mWriter;
+ const PxCollection& mCollection;
+ bool mExportNames;
+ };
+
+ void writeHeader(PxSerializationContext& stream, bool hasDeserializedAssets)
+ {
+ PX_UNUSED(hasDeserializedAssets);
+ struct Header
+ {
+ PxU32 header;
+ PxU32 version;
+ PxU32 binaryVersion;
+ PxU32 buildNumber;
+ PxU32 platformTag;
+ PxU32 markedPadding;
+ PxU32 materialOffset;
+ };
+
+ //serialized binary data.
+ const PxU32 header = PX_MAKE_FOURCC('S','E','B','D');
+ stream.writeData(&header, sizeof(PxU32));
+
+ PxU32 version = PX_PHYSICS_VERSION;
+ stream.writeData(&version, sizeof(PxU32));
+
+ PxU32 binaryVersion = PX_BINARY_SERIAL_VERSION;
+ stream.writeData(&binaryVersion, sizeof(PxU32));
+
+ PxU32 buildNumber = 0;
+#if defined(PX_BUILD_NUMBER)
+ buildNumber = PX_BUILD_NUMBER;
+#endif
+ stream.writeData(&buildNumber, sizeof(PxU32));
+
+ PxU32 platformTag = getBinaryPlatformTag();
+ stream.writeData(&platformTag, sizeof(PxU32));
+
+ PxU32 markedPadding = 0;
+#if PX_CHECKED
+ if(!hasDeserializedAssets)
+ markedPadding = 1;
+#endif
+ stream.writeData(&markedPadding, sizeof(PxU32));
+ }
+}
+
+bool PxSerialization::serializeCollectionToBinary(PxOutputStream& outputStream, PxCollection& pxCollection, PxSerializationRegistry& sr, const PxCollection* pxExternalRefs, bool exportNames)
+{
+ if(!PxSerialization::isSerializable(pxCollection, sr, pxExternalRefs))
+ return false;
+
+ Collection& collection = static_cast<Collection&>(pxCollection);
+ const Collection* externalRefs = static_cast<const Collection*>(pxExternalRefs);
+
+ //temporary memory stream which allows fixing up data up stream
+
+ SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
+
+ // sort collection by "order" value (this will be the order in which they get serialized)
+ sortCollection(collection, sn, false);
+
+ //initialized the context with the sorted collection.
+ SerializationContext context(collection, externalRefs);
+
+ // gather reference information
+ bool hasDeserializedAssets = false;
+ {
+ const PxU32 nb = collection.internalGetNbObjects();
+ for(PxU32 i=0;i<nb;i++)
+ {
+ PxBase* s = collection.internalGetObject(i);
+ PX_ASSERT(s && s->getConcreteType());
+#if PX_CHECKED
+ //can't guarantee marked padding for deserialized instances
+ if(!(s->getBaseFlags() & PxBaseFlag::eOWNS_MEMORY))
+ hasDeserializedAssets = true;
+#endif
+ const PxSerializer* serializer = sn.getSerializer(s->getConcreteType());
+ PX_ASSERT(serializer);
+ serializer->registerReferences(*s, context);
+ }
+ }
+
+ // now start the actual serialization into the output stream
+ OutputStreamWriter writer(outputStream);
+ LegacySerialStream stream(writer, collection, exportNames);
+
+ writeHeader(stream, hasDeserializedAssets);
+
+ // write size of collection
+ stream.alignData(PX_SERIAL_ALIGN);
+ PxU32 nbObjectsInCollection = collection.internalGetNbObjects();
+ stream.writeData(&nbObjectsInCollection, sizeof(PxU32));
+
+ // write the manifest table (PxU32 offset, PxConcreteType type)
+ {
+ Ps::Array<ManifestEntry> manifestTable(collection.internalGetNbObjects());
+ PxU32 headerOffset = 0;
+ for(PxU32 i=0;i<collection.internalGetNbObjects();i++)
+ {
+ PxBase* s = collection.internalGetObject(i);
+ PX_ASSERT(s && s->getConcreteType());
+ PxType concreteType = s->getConcreteType();
+ const PxSerializer* serializer = sn.getSerializer(concreteType);
+ PX_ASSERT(serializer);
+ manifestTable[i] = ManifestEntry(headerOffset, concreteType);
+ PxU32 classSize = PxU32(serializer->getClassSize());
+ headerOffset += getPadding(classSize, PX_SERIAL_ALIGN) + classSize;
+ }
+ stream.alignData(PX_SERIAL_ALIGN);
+ const PxU32 nb = manifestTable.size();
+ stream.writeData(&nb, sizeof(PxU32));
+ stream.writeData(manifestTable.begin(), manifestTable.size()*sizeof(ManifestEntry));
+
+ //store offset for end of object buffer (PxU32 offset)
+ stream.writeData(&headerOffset, sizeof(PxU32));
+ }
+
+ // write import references
+ {
+ const Ps::Array<ImportReference>& importReferences = context.getImportReferences();
+ stream.alignData(PX_SERIAL_ALIGN);
+ const PxU32 nb = importReferences.size();
+ stream.writeData(&nb, sizeof(PxU32));
+ stream.writeData(importReferences.begin(), importReferences.size()*sizeof(ImportReference));
+ }
+
+ // write export references
+ {
+ PxU32 nbIds = collection.getNbIds();
+ Ps::Array<ExportReference> exportReferences(nbIds);
+ //we can't get quickly from id to object index in collection.
+ //if we only need this here, its not worth to build a hash
+ nbIds = 0;
+ for (PxU32 i=0;i<collection.getNbObjects();i++)
+ {
+ PxBase& obj = collection.getObject(i);
+ PxSerialObjectId id = collection.getId(obj);
+ if (id != PX_SERIAL_OBJECT_ID_INVALID)
+ {
+ SerialObjectIndex objIndex(i, false); //i corresponds to manifest entry
+ exportReferences[nbIds++] = ExportReference(id, objIndex);
+ }
+ }
+ stream.alignData(PX_SERIAL_ALIGN);
+ stream.writeData(&nbIds, sizeof(PxU32));
+ stream.writeData(exportReferences.begin(), exportReferences.size()*sizeof(ExportReference));
+ }
+
+ // write internal references
+ {
+ InternalRefMap& internalReferencesPtrMap = context.getInternalReferencesPtrMap();
+ Ps::Array<InternalReferencePtr> internalReferencesPtr(internalReferencesPtrMap.size());
+ PxU32 nbInternalPtrReferences = 0;
+ for(InternalRefMap::Iterator iter = internalReferencesPtrMap.getIterator(); !iter.done(); ++iter)
+ internalReferencesPtr[nbInternalPtrReferences++] = InternalReferencePtr(iter->first.first, iter->first.second, iter->second);
+
+ InternalRefMap& internalReferencesIdxMap = context.getInternalReferencesIdxMap();
+ Ps::Array<InternalReferenceIdx> internalReferencesIdx(internalReferencesIdxMap.size());
+ PxU32 nbInternalIdxReferences = 0;
+ for(InternalRefMap::Iterator iter = internalReferencesIdxMap.getIterator(); !iter.done(); ++iter)
+ internalReferencesIdx[nbInternalIdxReferences++] = InternalReferenceIdx(Ps::to32(iter->first.first), iter->first.second, iter->second);
+
+ stream.alignData(PX_SERIAL_ALIGN);
+
+ stream.writeData(&nbInternalPtrReferences, sizeof(PxU32));
+ stream.writeData(internalReferencesPtr.begin(), internalReferencesPtr.size()*sizeof(InternalReferencePtr));
+
+ stream.writeData(&nbInternalIdxReferences, sizeof(PxU32));
+ stream.writeData(internalReferencesIdx.begin(), internalReferencesIdx.size()*sizeof(InternalReferenceIdx));
+ }
+
+ // write object data
+ {
+ stream.alignData(PX_SERIAL_ALIGN);
+ const PxU32 nb = collection.internalGetNbObjects();
+ for(PxU32 i=0;i<nb;i++)
+ {
+ PxBase* s = collection.internalGetObject(i);
+ PX_ASSERT(s && s->getConcreteType());
+ const PxSerializer* serializer = sn.getSerializer(s->getConcreteType());
+ PX_ASSERT(serializer);
+ stream.alignData(PX_SERIAL_ALIGN);
+ serializer->exportData(*s, stream);
+ }
+ }
+
+ // write extra data
+ {
+ const PxU32 nb = collection.internalGetNbObjects();
+ for(PxU32 i=0;i<nb;i++)
+ {
+ PxBase* s = collection.internalGetObject(i);
+ PX_ASSERT(s && s->getConcreteType());
+
+ const PxSerializer* serializer = sn.getSerializer(s->getConcreteType());
+ PX_ASSERT(serializer);
+
+ stream.alignData(PX_SERIAL_ALIGN);
+ serializer->exportExtraData(*s, stream);
+ }
+ }
+
+ return true;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.cpp
new file mode 100644
index 00000000..ad486c2d
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.cpp
@@ -0,0 +1,156 @@
+// 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.
+
+/*
+- get rid of STL
+
+- NpArticulationLinkArray with more than 4 entries
+- big convexes Xbox => PC
+
+- put a cache in "convertClass" function
+- remove MD one at a time and check what happens in the converter. Make it robust/report errors
+- for xbox, compare against source xbox file if it exists
+- maybe put some info in the header to display "File generated by ConvX 1.xx" on screen (to debug)
+- report inconsistent naming convention in each class!!!!
+- try to automatically discover padding bytes? use "0xcd" pattern?
+* do last param of XXXX_ITEMS macro automatically
+- what if source files are 64bits? can we safely convert a 64bit ptr to 32bit?
+*/
+
+#include "foundation/PxErrorCallback.h"
+#include "foundation/PxAllocatorCallback.h"
+#include "foundation/PxIO.h"
+#include "SnConvX.h"
+#include "serialization/SnSerializationRegistry.h"
+#include <assert.h>
+#include "PsFoundation.h"
+
+using namespace physx;
+
+Sn::ConvX::ConvX() :
+ mMetaData_Src (NULL),
+ mMetaData_Dst (NULL),
+ mOutStream (NULL),
+ mMustFlip (false),
+ mOutputSize (0),
+ mSrcPtrSize (0),
+ mDstPtrSize (0),
+ mNullPtr (false),
+ mNoOutput (false),
+ mMarkedPadding (false),
+ mNbErrors (0),
+ mNbWarnings (0),
+ mReportMode (PxConverterReportMode::eNORMAL),
+ mPerformConversion (true)
+{
+ // memset(mZeros, 0, CONVX_ZERO_BUFFER_SIZE);
+ memset(mZeros, 0x42, CONVX_ZERO_BUFFER_SIZE);
+}
+
+Sn::ConvX::~ConvX()
+{
+ resetNbErrors();
+ resetConvexFlags();
+ releaseMetaData();
+ resetUnions();
+}
+
+void Sn::ConvX::release()
+{
+ delete this;
+}
+
+bool Sn::ConvX::setMetaData(PxInputStream& inputStream, MetaDataType type)
+{
+ resetNbErrors();
+ return (loadMetaData(inputStream, type) != NULL);
+}
+
+bool Sn::ConvX::setMetaData(PxInputStream& srcMetaData, PxInputStream& dstMetaData)
+{
+ releaseMetaData();
+ resetUnions();
+
+ if(!setMetaData(srcMetaData, META_DATA_SRC))
+ return false;
+ if(!setMetaData(dstMetaData, META_DATA_DST))
+ return false;
+
+ return true;
+}
+
+
+bool Sn::ConvX::convert(PxInputStream& srcStream, PxU32 srcSize, PxOutputStream& targetStream)
+{
+ if(!mMetaData_Src || !mMetaData_Dst)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "PxBinaryConverter: metadata not defined. Call PxBinaryConverter::setMetaData first.\n");
+ return false;
+ }
+
+ resetConvexFlags();
+ resetNbErrors();
+
+ bool conversionStatus = false;
+ if(mPerformConversion)
+ {
+ if(srcSize == 0)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxBinaryConverter: source serialized data size is zero.\n");
+ return false;
+ }
+
+ void* memory = PX_ALLOC_TEMP(srcSize+ALIGN_FILE, "ConvX source file");
+ void* memoryA = reinterpret_cast<void*>((size_t(memory) + ALIGN_FILE)&~(ALIGN_FILE-1));
+
+ const PxU32 nbBytesRead = srcStream.read(memoryA, srcSize);
+ if(nbBytesRead != srcSize)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxBinaryConverter: failure on reading source serialized data.\n");
+ PX_FREE(memory);
+ return false;
+ }
+
+ displayMessage(PxErrorCode::eDEBUG_INFO, "\n\nConverting...\n\n");
+
+ {
+ if(!initOutput(targetStream))
+ {
+ PX_FREE(memory);
+ return false;
+ }
+ conversionStatus = convert(memoryA, int(srcSize));
+ closeOutput();
+ }
+
+ PX_FREE(memory);
+ }
+ return conversionStatus;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.h
new file mode 100644
index 00000000..9ce9d86f
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX.h
@@ -0,0 +1,182 @@
+// 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.
+
+#ifndef PX_CONVX_H
+#define PX_CONVX_H
+
+#include "foundation/PxErrors.h"
+#include "PxBinaryConverter.h"
+#include "PxTypeInfo.h"
+#include "CmPhysXCommon.h"
+#include "PsUserAllocated.h"
+#include "PsArray.h"
+#include "SnConvX_Common.h"
+#include "SnConvX_Union.h"
+#include "SnConvX_MetaData.h"
+#include "SnConvX_Align.h"
+
+#define CONVX_ZERO_BUFFER_SIZE 256
+
+namespace physx {
+
+class PxSerializationRegistry;
+
+namespace Sn {
+
+ struct HeightFieldData;
+ class PointerRemap
+ {
+ public:
+ PointerRemap();
+ ~PointerRemap();
+
+ bool checkRefIsNotUsed(PxU32 ref) const;
+ void setObjectRef(PxU64 object64, PxU32 ref);
+ bool getObjectRef(PxU64 object64, PxU32& ref) const;
+
+ struct InternalData
+ {
+ PxU64 object;
+ PxU32 id;
+ };
+
+ Ps::Array<InternalData> mData;
+ };
+
+ class ConvX : public physx::PxBinaryConverter, public shdfnd::UserAllocated
+ {
+ public:
+ ConvX();
+ virtual ~ConvX();
+
+ virtual void release();
+ virtual void setReportMode(PxConverterReportMode::Enum mode) { mReportMode = mode; }
+ PX_FORCE_INLINE bool silentMode() const { return mReportMode==PxConverterReportMode::eNONE; }
+ PX_FORCE_INLINE bool verboseMode() const { return mReportMode==PxConverterReportMode::eVERBOSE; }
+
+ virtual bool setMetaData(PxInputStream& srcMetaData, PxInputStream& dstMetaData);
+ virtual bool convert(PxInputStream& srcStream, PxU32 srcSize, PxOutputStream& targetStream);
+
+ private:
+ ConvX& operator=(const ConvX&);
+ bool setMetaData(PxInputStream& inputStream, MetaDataType type);
+
+ // Meta-data
+ void releaseMetaData();
+ const MetaData* loadMetaData(PxInputStream& inputStream, MetaDataType type);
+ const MetaData* getBinaryMetaData(MetaDataType type);
+ int getNbMetaClasses(MetaDataType type);
+ MetaClass* getMetaClass(unsigned int i, MetaDataType type) const;
+ MetaClass* getMetaClass(const char* name, MetaDataType type) const;
+ MetaClass* getMetaClass(PxConcreteType::Enum concreteType, MetaDataType type);
+ MetaData* mMetaData_Src;
+ MetaData* mMetaData_Dst;
+
+ // Convert
+
+ bool convert(const void* buffer, int fileSize);
+ void resetConvexFlags();
+ void _enumerateFields(const MetaClass* mc, ExtraDataEntry2* entries, int& nb, int baseOffset, MetaDataType type) const;
+ void _enumerateExtraData(const char* address, const MetaClass* mc, ExtraDataEntry* entries, int& nb, int offset, MetaDataType type) const;
+ PxU64 read64(const void*& buffer);
+ int read32(const void*& buffer);
+ short read16(const void*& buffer);
+ bool convertClass(const char* buffer, const MetaClass* mc, int offset);
+ const char* convertExtraData_Array(const char* Address, const char* lastAddress, const char* objectAddress, const ExtraDataEntry& ed);
+ const char* convertExtraData_Ptr(const char* Address, const char* lastAddress, const PxMetaDataEntry& entry, int count, int ptrSize_Src, int ptrSize_Dst);
+ int getConcreteType(const char* buffer);
+ bool convertCollection(const void* buffer, int fileSize, int nbObjects);
+ const void* convertManifestTable(const void* buffer, int& fileSize);
+ const void* convertImportReferences(const void* buffer, int& fileSize);
+ const void* convertExportReferences(const void* buffer, int& fileSize);
+ const void* convertInternalReferences(const void* buffer, int& fileSize);
+ const void* convertReferenceTables(const void* buffer, int& fileSize, int& nbObjectsInCollection);
+ bool checkPaddingBytes(const char* buffer, int byteCount);
+
+ // ---- big convex surgery ----
+ PsArray<bool> mConvexFlags;
+ // Align
+ const char* alignStream(const char* buffer, int alignment=ALIGN_DEFAULT);
+ void alignTarget(int alignment);
+
+ char mZeros[CONVX_ZERO_BUFFER_SIZE];
+ // Unions
+ bool registerUnion(const char* name);
+ bool registerUnionType(const char* unionName, const char* typeName, int typeValue);
+ const char* getTypeName(const char* unionName, int typeValue);
+ void resetUnions();
+ PsArray<Union> mUnions;
+ // Output
+ void setNullPtr(bool);
+ void setNoOutput(bool);
+ bool initOutput(PxOutputStream& targetStream);
+ void closeOutput();
+ int getCurrentOutputSize();
+ void output(short value);
+ void output(int value);
+ void output(PxU64 value);
+ void output(const char* buffer, int nbBytes);
+ void convert8 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry);
+ void convertPad8 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry);
+ void convert16 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry);
+ void convert32 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry);
+ void convert64 (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry);
+ void convertFloat(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry);
+ void convertPtr (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry);
+ PxOutputStream* mOutStream;
+ bool mMustFlip;
+ int mOutputSize;
+ int mSrcPtrSize;
+ int mDstPtrSize;
+ bool mNullPtr;
+ bool mNoOutput;
+ bool mMarkedPadding;
+
+ // Errors
+ void resetNbErrors();
+ int getNbErrors() const;
+ void displayMessage(physx::PxErrorCode::Enum code, const char* format, ...);
+ int mNbErrors;
+ int mNbWarnings;
+
+ // Settings
+ PxConverterReportMode::Enum mReportMode;
+ bool mPerformConversion;
+
+ // Remap pointers
+ void exportIntAsPtr(int value);
+ void exportInt(int value);
+ void exportInt64(PxU64 value);
+ PointerRemap mRemap;
+ PointerRemap* mActiveRemap;
+ PxU32 mPointerRemapCounter;
+
+ friend class MetaData;
+ friend struct MetaClass;
+ };
+} }
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.cpp
new file mode 100644
index 00000000..5c576f5c
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.cpp
@@ -0,0 +1,63 @@
+// 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 "SnConvX.h"
+#include "SnConvX_Align.h"
+#include <assert.h>
+using namespace physx;
+
+void Sn::ConvX::alignTarget(int alignment)
+{
+ const int outputSize = getCurrentOutputSize();
+ const PxU32 outPadding = getPadding(size_t(outputSize), PxU32(alignment));
+ if(outPadding)
+ {
+ assert(outPadding<CONVX_ZERO_BUFFER_SIZE);
+ output(mZeros, int(outPadding));
+ }
+}
+
+const char* Sn::ConvX::alignStream(const char* buffer, int alignment)
+{
+ const PxU32 padding = getPadding(size_t(buffer), PxU32(alignment));
+ assert(!getPadding(size_t(buffer + padding), PxU32(alignment)));
+
+ const int outputSize = getCurrentOutputSize();
+ const PxU32 outPadding = getPadding(size_t(outputSize), PxU32(alignment));
+ if(outPadding==padding)
+ {
+ assert(outPadding<CONVX_ZERO_BUFFER_SIZE);
+ output(mZeros, int(outPadding));
+ }
+ else if(outPadding)
+ {
+ assert(outPadding<CONVX_ZERO_BUFFER_SIZE);
+ output(mZeros, int(outPadding));
+ }
+
+ return buffer + padding;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.h
new file mode 100644
index 00000000..b3ec81c2
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Align.h
@@ -0,0 +1,44 @@
+// 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.
+
+#ifndef PX_CONVX_ALIGN_H
+#define PX_CONVX_ALIGN_H
+
+namespace physx { namespace Sn {
+ #define ALIGN_DEFAULT 16
+ #define ALIGN_FILE 128
+
+ PX_INLINE PxU32 getPadding(size_t value, PxU32 alignment)
+ {
+ const PxU32 mask = alignment-1;
+ const PxU32 overhead = PxU32(value) & mask;
+ return (alignment - overhead) & mask;
+ }
+
+} }
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Common.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Common.h
new file mode 100644
index 00000000..677480e4
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Common.h
@@ -0,0 +1,43 @@
+// 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.
+
+#ifndef PX_CONVX_COMMON_H
+#define PX_CONVX_COMMON_H
+
+#if PX_VC
+#pragma warning(disable:4121) // alignment of a member was sensitive to packing
+#endif
+
+#include "common/PxPhysXCommonConfig.h"
+
+#define DELETESINGLE(x) if(x){ delete x; x = NULL; }
+#define DELETEARRAY(x) if(x){ delete []x; x = NULL; }
+
+#define inline_ PX_FORCE_INLINE
+#define PsArray physx::shdfnd::Array
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Convert.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Convert.cpp
new file mode 100644
index 00000000..a9fe0b9c
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Convert.cpp
@@ -0,0 +1,1434 @@
+// 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 "foundation/PxErrorCallback.h"
+#include "SnConvX.h"
+#include "serialization/SnSerialUtils.h"
+#include "PsAlloca.h"
+#include "CmUtils.h"
+#include "PxDefaultStreams.h"
+#include <assert.h>
+
+using namespace physx;
+using namespace physx::Sn;
+using namespace Cm;
+
+void Sn::ConvX::resetConvexFlags()
+{
+ mConvexFlags.clear();
+}
+
+void Sn::ConvX::_enumerateFields(const MetaClass* mc, ExtraDataEntry2* entries, int& nb, int baseOffset, MetaDataType type) const
+{
+ PxU32 nbFields = mc->mFields.size();
+ int offsetCheck = baseOffset;
+ for(PxU32 j=0;j<nbFields;j++)
+ {
+ const PxMetaDataEntry& entry = mc->mFields[j];
+ if(entry.mFlags & PxMetaDataFlag::eCLASS || entry.mFlags & PxMetaDataFlag::eEXTRA_DATA)
+ continue;
+
+ assert(offsetCheck == baseOffset + entry.mOffset);
+
+ int currentOffset = baseOffset + entry.mOffset;
+
+ //for(int c=0;c<entry.mCount;c++)
+ {
+ if(entry.mFlags & PxMetaDataFlag::eUNION)
+ {
+ entries[nb].entry = entry;
+ entries[nb].offset = currentOffset;
+ entries[nb].cb = 0;
+ nb++;
+ }
+ else if(entry.mFlags & PxMetaDataFlag::ePTR) // This also takes care of the vtable pointer
+ {
+ entries[nb].entry = entry;
+ entries[nb].offset = currentOffset;
+ entries[nb].cb = &Sn::ConvX::convertPtr;
+ nb++;
+ }
+ else
+ {
+ MetaClass* fieldType = getMetaClass(entry.mType, type);
+ assert(fieldType);
+ if(fieldType->mCallback)
+ {
+ entries[nb].entry = entry;
+ entries[nb].offset = currentOffset;
+ entries[nb].cb = fieldType->mCallback;
+ nb++;
+ }
+ else
+ {
+ for(int c=0;c<entry.mCount;c++)
+ {
+ _enumerateFields(fieldType, entries, nb, currentOffset, type);
+ currentOffset += entry.mSize/entry.mCount;
+ }
+ }
+ }
+ }
+ offsetCheck += entry.mSize;
+ }
+}
+
+void Sn::ConvX::_enumerateExtraData(const char* address, const MetaClass* mc, ExtraDataEntry* entries,
+ int& nb, int offset, MetaDataType type) const
+{
+ PxU32 nbFields = mc->mFields.size();
+ for(PxU32 j=0;j<nbFields;j++)
+ {
+ const PxMetaDataEntry& entry = mc->mFields[j];
+ if(entry.mFlags & PxMetaDataFlag::eCLASS /*|| entry.mFlags & PxMetaDataFlag::ePTR*/ || entry.mFlags & PxMetaDataFlag::eTYPEDEF)
+ continue;
+
+ const char* entryType = entry.mType;
+
+ //
+ // Insanely Twisted Shadow GeometryUnion
+ //
+ // Special code is needed as long as there are no meta data tags to describe our unions properly. The way it is done here is
+ // not future-proof at all. There should be a tag to describe where the union type can be found and the number of bytes
+ // this type id needs. Then a mapping needs to get added from each union type id to the proper meta class name.
+ //
+ if (entry.mFlags & PxMetaDataFlag::eUNION)
+ {
+ if (!mc->mClassName || strcmp(mc->mClassName, "Gu::GeometryUnion")!=0)
+ continue;
+ else
+ {
+ // ### hardcoded bit here, will only work when union type is the first int of the struct
+ const int* tmp = reinterpret_cast<const int*>(address + offset);
+ const int unionType = *tmp;
+
+ ConvX* tmpConv = const_cast<ConvX*>(this); // ... don't ask
+ const char* typeName = tmpConv->getTypeName(entry.mType, unionType);
+ assert(typeName);
+
+ bool isTriMesh = (strcmp(typeName, "PxTriangleMeshGeometryLL") == 0);
+ bool isHeightField = (strcmp(typeName, "PxHeightFieldGeometryLL") == 0);
+ if (!isTriMesh && !isHeightField)
+ {
+ continue;
+ }
+ else
+ {
+ entryType = typeName;
+ }
+ }
+ }
+
+ // MetaClass* extraDataType = getMetaClass(entry.mType, type);
+ // if(!extraDataType)
+ // continue;
+
+ if(entry.mFlags & PxMetaDataFlag::eEXTRA_DATA)
+ {
+ entries[nb].entry = entry;
+ entries[nb].offset = offset+entry.mOffset;
+ nb++;
+ }
+ else
+ {
+ if(entry.mFlags & PxMetaDataFlag::ePTR)
+ continue;
+
+ MetaClass* extraDataType = getMetaClass(entryType, type);
+ if(!extraDataType)
+ continue;
+
+ if(!extraDataType->mCallback)
+ _enumerateExtraData(address, extraDataType, entries, nb, offset+entry.mOffset, type);
+ }
+ }
+}
+
+PxU64 Sn::ConvX::read64(const void*& buffer)
+{
+ const PxU64* buf64 = reinterpret_cast<const PxU64*>(buffer);
+ buffer = reinterpret_cast<const void*>(size_t(buffer) + sizeof(PxU64));
+ PxU64 value = *buf64;
+ output(value);
+ return value;
+}
+
+int Sn::ConvX::read32(const void*& buffer)
+{
+ const int* buf32 = reinterpret_cast<const int*>(buffer);
+ buffer = reinterpret_cast<const void*>(size_t(buffer) + sizeof(int));
+ int value = *buf32;
+ output(value);
+ return value;
+}
+
+short Sn::ConvX::read16(const void*& buffer)
+{
+ const short* buf16 = reinterpret_cast<const short*>(buffer);
+ buffer = reinterpret_cast<const void*>(size_t(buffer) + sizeof(short));
+ short value = *buf16;
+ output(value);
+ return value;
+}
+
+#if PX_CHECKED
+extern const char* gVTable;
+static bool compareEntries(const ExtraDataEntry2& e0, const ExtraDataEntry2& e1)
+{
+ if(e0.entry.isVTablePtr() && e1.entry.isVTablePtr())
+ return true;
+
+ if((e0.entry.mFlags & PxMetaDataFlag::eUNION) && (e1.entry.mFlags & PxMetaDataFlag::eUNION))
+ {
+ if(e0.entry.mType && e1.entry.mType)
+ {
+ // We can't compare the ptrs since they index different string tables
+ if(strcmp(e0.entry.mType, e1.entry.mType)==0)
+ return true;
+ }
+ return false;
+ }
+
+ if(e0.entry.mName && e1.entry.mName)
+ {
+ // We can't compare the ptrs since they index different string tables
+ if(strcmp(e0.entry.mName, e1.entry.mName)==0)
+ return true;
+ }
+ return false;
+}
+#endif
+
+// TODO: optimize this
+bool Sn::ConvX::convertClass(const char* buffer, const MetaClass* mc, int offset)
+{
+ // ---- big convex surgery ----
+ bool convexSurgery = false;
+ bool foundNbVerts = false;
+ bool removeBigData = false;
+
+ // force reference
+ (void)foundNbVerts;
+
+ displayMessage(PxErrorCode::eDEBUG_INFO, "%s\n", mc->mClassName);
+ displayMessage(PxErrorCode::eDEBUG_INFO, "+++++++++++++++++++++++++++++++++++++++++++++\n");
+
+ if(strcmp(mc->mClassName, "ConvexMesh")==0)
+ {
+ convexSurgery = true;
+ }
+ // ---- big convex surgery ----
+
+ int nbSrcEntries = 0;
+ PX_ALLOCA(srcEntries, ExtraDataEntry2, 256); // ### painful ctors here
+ int nbDstEntries = 0;
+ PX_ALLOCA(dstEntries, ExtraDataEntry2, 256); // ### painful ctors here
+ // Find corresponding meta-class for target platform
+ const MetaClass* target_mc = getMetaClass(mc->mClassName, META_DATA_DST);
+ assert(target_mc);
+
+ if(mc->mCallback)
+ {
+ srcEntries[0].cb = mc->mCallback;
+ srcEntries[0].offset = offset;
+ srcEntries[0].entry.mType = mc->mClassName;
+ srcEntries[0].entry.mName = mc->mClassName;
+ srcEntries[0].entry.mOffset = offset;
+ srcEntries[0].entry.mSize = mc->mSize;
+ srcEntries[0].entry.mCount = 1;
+ srcEntries[0].entry.mFlags = 0;
+ nbSrcEntries = 1;
+
+ assert(target_mc->mCallback);
+ dstEntries[0].cb = target_mc->mCallback;
+ dstEntries[0].offset = offset;
+ dstEntries[0].entry.mType = target_mc->mClassName;
+ dstEntries[0].entry.mName = target_mc->mClassName;
+ dstEntries[0].entry.mOffset = offset;
+ dstEntries[0].entry.mSize = target_mc->mSize;
+ dstEntries[0].entry.mCount = 1;
+ dstEntries[0].entry.mFlags = 0;
+ nbDstEntries = 1;
+ }
+ else
+ {
+ nbSrcEntries = 0;
+ _enumerateFields(mc, srcEntries, nbSrcEntries, 0, META_DATA_SRC);
+ assert(nbSrcEntries<256);
+
+ nbDstEntries = 0;
+ _enumerateFields(target_mc, dstEntries, nbDstEntries, 0, META_DATA_DST);
+ assert(nbDstEntries<256);
+
+ // nb = mc->mNbEntries;
+ // assert(nb>=0);
+ // memcpy(entries, mc->mEntries, nb*sizeof(ExtraDataEntry2));
+ }
+
+ int srcOffsetCheck = 0;
+ int dstOffsetCheck = 0;
+ int j = 0;
+ // Track cases where the vtable pointer location is different for different platforms.
+ // The variables indicate whether a platform has a vtable pointer entry that has not been converted yet
+ // and they will remember the index of the corrssponding entry. This works because there can only
+ // be one open vtable pointer entry at a time.
+ int srcOpenVTablePtrEntry = -1;
+ int dstOpenVTablePtrEntry = -1;
+
+ //if the src and dst platform place the vtable pointers at different locations some fiddling with the iteration count can be necessary.
+ int addVTablePtrShiftIteration = 0;
+ const int maxNb = nbSrcEntries > nbDstEntries ? nbSrcEntries : nbDstEntries;
+ for(int i=0; i < (maxNb + addVTablePtrShiftIteration); i++)
+ {
+
+ if (i < nbSrcEntries)
+ {
+ displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t%d\t%d\t%s", buffer + srcOffsetCheck,
+ buffer[srcOffsetCheck], srcOffsetCheck, srcEntries[i].entry.mOffset, srcEntries[i].entry.mName);
+ for (int byteCount = 1; byteCount < srcEntries[i].entry.mSize; ++byteCount)
+ displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t%d\t%d\t.", buffer + srcOffsetCheck + byteCount,
+ buffer[srcOffsetCheck + byteCount], srcOffsetCheck + byteCount, srcEntries[i].entry.mOffset + byteCount);
+ }
+
+ bool handlePadding = true;
+ bool skipLoop = false;
+ while(handlePadding)
+ {
+ const int pad0 = i<nbSrcEntries ? srcEntries[i].entry.mFlags & PxMetaDataFlag::ePADDING : 0;
+ const int pad1 = j<nbDstEntries ? dstEntries[j].entry.mFlags & PxMetaDataFlag::ePADDING : 0;
+ if(pad0 || pad1)
+ {
+ if(pad0)
+ {
+#if PX_CHECKED
+ if (mMarkedPadding && (strcmp(srcEntries[i].entry.mType, "paddingByte")==0))
+ if(!checkPaddingBytes(buffer + srcOffsetCheck, srcEntries[i].entry.mSize))
+ {
+ if(i>0)
+ {
+ displayMessage(PxErrorCode::eDEBUG_WARNING,
+ "PxBinaryConverter warning: Bytes after %s::%s don't look like padding bytes. Likely mismatch between binary data and metadata.\n",
+ mc->mClassName, srcEntries[i-1].entry.mName );
+ }
+ else
+ displayMessage(PxErrorCode::eDEBUG_WARNING,
+ "PxBinaryConverter warning: Bytes after %s don't look like padding bytes. Likely mismatch between binary data and metadata.\n",
+ mc->mClassName);
+
+ }
+#endif
+ if(pad1)
+ {
+ // Both have padding
+ // ### check sizes, output bytes
+ if(srcEntries[i].entry.mSize==dstEntries[j].entry.mSize)
+ {
+ // I guess we can just go on with the normal code here
+ handlePadding = false;
+ }
+ else
+ {
+ // Output padding
+ assert(srcEntries[i].cb);
+ assert(srcEntries[i].offset == srcOffsetCheck);
+
+ const int padSize = dstEntries[j].entry.mSize;
+ char* paddingBytes = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*padSize, "paddingByte"));
+ memset(paddingBytes, 0, size_t(padSize));
+ assert(dstEntries[j].cb);
+ (this->*dstEntries[j].cb)(paddingBytes, dstEntries[j].entry, dstEntries[j].entry);
+ assert(dstOffsetCheck==dstEntries[j].offset);
+ dstOffsetCheck += padSize;
+ PX_FREE(paddingBytes);
+
+ // srcEntries[i].cb(buffer+srcOffsetCheck, srcEntries[i].entry, dstEntries[j].entry);
+ // assert(dstOffsetCheck==dstEntries[j].offset);
+ // dstOffsetCheck += dstEntries[j].entry.mSize;
+ srcOffsetCheck += srcEntries[i].entry.mSize;
+
+ // Skip dest padding field
+ j++;
+
+ // continue; // ### BUG, doesn't go back to the "for"
+ skipLoop = true;
+ handlePadding = false;
+ }
+ }
+ else
+ {
+ // Src has padding, dst has not => skip conversion
+ // Don't increase j
+ skipLoop = true;
+ handlePadding = false;
+ srcOffsetCheck += srcEntries[i].entry.mSize;
+ }
+ }
+ else
+ {
+ if(pad1)
+ {
+ // Dst has padding, src has not
+
+ // Output padding
+ const int padSize = dstEntries[j].entry.mSize;
+ char* paddingBytes = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*padSize, "paddingByte"));
+ memset(paddingBytes, 0, size_t(padSize));
+ assert(dstEntries[j].cb);
+ (this->*dstEntries[j].cb)(paddingBytes, dstEntries[j].entry, dstEntries[j].entry);
+ assert(dstOffsetCheck==dstEntries[j].offset);
+ dstOffsetCheck += padSize;
+ PX_FREE(paddingBytes);
+
+ // Skip dest padding field, keep same src field
+ j++;
+ }
+ else
+ {
+ assert(0);
+ }
+ }
+ }
+ else handlePadding = false;
+ }
+
+ if(skipLoop)
+ continue;
+
+ int modSrcOffsetCheck = srcOffsetCheck;
+ const ExtraDataEntry2* srcEntryPtr = &srcEntries[i];
+ const ExtraDataEntry2* dstEntryPtr = &dstEntries[j];
+
+ bool isSrcVTablePtr = (i < nbSrcEntries) ? srcEntryPtr->entry.isVTablePtr() : false;
+ if (isSrcVTablePtr && (dstOpenVTablePtrEntry != -1))
+ {
+ // vtable ptr position mismatch:
+ // this check is necessary to align src and dst index again when the
+ // dst vtable pointer has been written already and the src vtable ptr
+ // element is reached.
+ //
+ // i
+ // src: | a | b | vt-ptr | c | ...
+ // dst: | vt-ptr | a | b | c | ...
+ // j
+ //
+ // it needs special treatment because the following case fails otherwise
+ // i
+ // src: | a | b | vt-ptr | c | vt-ptr | ...
+ // dst: | vt-ptr | a | b | vt-ptr | c | ...
+ // j
+
+ //
+ // This entry has been written already -> advance to next src entry
+ //
+ srcOffsetCheck += srcEntryPtr->entry.mSize;
+ i++;
+ isSrcVTablePtr = (i < nbSrcEntries) ? srcEntryPtr->entry.isVTablePtr() : false;
+ PX_ASSERT(dstOpenVTablePtrEntry < nbDstEntries);
+ PX_ASSERT(dstEntries[dstOpenVTablePtrEntry].entry.isVTablePtr());
+ dstOpenVTablePtrEntry = -1;
+ PX_ASSERT(addVTablePtrShiftIteration == 0);
+ }
+ bool isDstVTablePtr = (j < nbDstEntries) ? dstEntryPtr->entry.isVTablePtr() : false;
+ if (isDstVTablePtr && (srcOpenVTablePtrEntry != -1))
+ {
+ // i
+ // src: | vt-ptr | a | b | c | ...
+ // dst: | a | b | vt-ptr | c | ...
+ // j
+
+ i--; // next iteration the current element should get processed
+ isSrcVTablePtr = true;
+ PX_ASSERT(srcOpenVTablePtrEntry < nbSrcEntries);
+ srcEntryPtr = &srcEntries[srcOpenVTablePtrEntry];
+ PX_ASSERT(srcEntryPtr->entry.isVTablePtr());
+ modSrcOffsetCheck = srcEntryPtr->offset;
+ srcOffsetCheck -= srcEntryPtr->entry.mSize; // to make sure total change is 0 after this iteration
+ srcOpenVTablePtrEntry = -1;
+ PX_ASSERT(addVTablePtrShiftIteration == 1);
+ addVTablePtrShiftIteration = 0;
+ }
+
+ if(i==nbSrcEntries && j==nbDstEntries)
+ {
+ PX_ASSERT((srcOpenVTablePtrEntry == -1) && (dstOpenVTablePtrEntry == -1));
+ break;
+ }
+
+ if (isSrcVTablePtr || isDstVTablePtr)
+ {
+ if (!isSrcVTablePtr)
+ {
+ // i
+ // src: | a | b | vt-ptr | c | ...
+ // dst: | vt-ptr | a | b | c | ...
+ // j
+
+ PX_ASSERT(dstOpenVTablePtrEntry == -1); // the other case should be detected and treated earlier
+ PX_ASSERT(srcOpenVTablePtrEntry == -1);
+ PX_ASSERT(addVTablePtrShiftIteration == 0);
+
+ int k;
+ for(k=i+1; k < nbSrcEntries; k++)
+ {
+ if (srcEntries[k].entry.isVTablePtr())
+ break;
+ }
+ PX_ASSERT(k < nbSrcEntries);
+
+ srcEntryPtr = &srcEntries[k];
+ modSrcOffsetCheck = srcEntryPtr->offset;
+ srcOffsetCheck -= srcEntryPtr->entry.mSize; // to make sure total change is 0 after this iteration
+
+ dstOpenVTablePtrEntry = j;
+ i--; // to make sure the original entry gets processed in the next iteration
+ }
+ else if (!isDstVTablePtr)
+ {
+ // i ---> i
+ // src: | vt-ptr | a | b | c | ...
+ // dst: | a | b | vt-ptr | c | ...
+ // j
+
+ PX_ASSERT(srcOpenVTablePtrEntry == -1); // the other case should be detected and treated earlier
+ PX_ASSERT(dstOpenVTablePtrEntry == -1);
+ PX_ASSERT(addVTablePtrShiftIteration == 0);
+
+ srcOffsetCheck += srcEntryPtr->entry.mSize;
+ modSrcOffsetCheck = srcOffsetCheck;
+ srcOpenVTablePtrEntry = i;
+ i++;
+ srcEntryPtr = &srcEntries[i];
+
+ addVTablePtrShiftIteration = 1; // additional iteration might be needed to process vtable pointer at the end of a class
+
+ PX_ASSERT((i < nbSrcEntries) && ((srcEntryPtr->entry.mFlags & PxMetaDataFlag::ePADDING) == 0));
+ // if the second check fails, this whole section might have to be done before the padding bytes get processed. Not sure
+ // what other consequences that might have though.
+ }
+ }
+#if PX_CHECKED
+ else
+ {
+ if(!compareEntries(*srcEntryPtr, *dstEntryPtr))
+ {
+ displayMessage(PxErrorCode::eINVALID_PARAMETER, "\rConvX::convertClass: %s, src meta data and dst meta data don't match!", mc->mClassName);
+ return false;
+ }
+ }
+#endif
+
+ const ExtraDataEntry2& srcEntry = *srcEntryPtr;
+ const ExtraDataEntry2& dstEntry = *dstEntryPtr;
+
+ if(srcEntry.entry.mFlags & PxMetaDataFlag::eUNION)
+ {
+ // ### hardcoded bit here, will only work when union type is the first int of the struct
+ const int* tmp = reinterpret_cast<const int*>(buffer + modSrcOffsetCheck);
+ const int unionType = *tmp;
+
+ const char* typeName = getTypeName(srcEntry.entry.mType, unionType);
+ assert(typeName);
+
+ MetaClass* unionMC = getMetaClass(typeName, META_DATA_SRC);
+ assert(unionMC);
+
+ convertClass(buffer + modSrcOffsetCheck, unionMC, 0); // ### recurse
+
+ dstOffsetCheck += dstEntry.entry.mSize;
+
+ MetaClass* targetUnionMC = getMetaClass(typeName, META_DATA_DST);
+ assert(targetUnionMC);
+
+ const int delta = dstEntry.entry.mSize - targetUnionMC->mSize;
+ char* deltaBytes = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*delta, "deltaBytes"));
+ memset(deltaBytes, 0, size_t(delta));
+ output(deltaBytes, delta); // Skip unused bytes at the end of the union
+ PX_FREE(deltaBytes);
+ srcOffsetCheck += srcEntry.entry.mSize; // do not use modSrcOffsetCheck here!
+ }
+ else
+ {
+ assert(srcEntry.cb);
+ assert(srcEntry.offset == modSrcOffsetCheck);
+
+ // ---- big convex surgery ----
+ if(convexSurgery)
+ {
+ if(strcmp(srcEntry.entry.mName, "mNbHullVertices")==0)
+ {
+ assert(srcEntry.entry.mSize==1);
+ const int nbVerts = int(*(buffer+modSrcOffsetCheck));
+ assert(!foundNbVerts);
+ foundNbVerts = true;
+
+ const int gaussMapLimit = getBinaryMetaData(META_DATA_DST)->getGaussMapLimit();
+ if(nbVerts > gaussMapLimit)
+ {
+ // We need a gauss map and we have one => keep it
+ }
+ else
+ {
+ // We don't need a gauss map and we have one => remove it
+ removeBigData = true;
+ }
+ }
+ else
+ {
+ if(removeBigData)
+ {
+ const bool isBigConvexData = strcmp(srcEntry.entry.mType, "BigConvexData")==0 ||
+ strcmp(srcEntry.entry.mType, "BigConvexRawData")==0;
+ if(isBigConvexData)
+ {
+ assert(foundNbVerts);
+ setNullPtr(true);
+ }
+ }
+ }
+ }
+ // ---- big convex surgery ----
+
+ (this->*srcEntry.cb)(buffer+modSrcOffsetCheck, srcEntry.entry, dstEntry.entry);
+ assert(dstOffsetCheck==dstEntry.offset);
+ dstOffsetCheck += dstEntry.entry.mSize;
+ srcOffsetCheck += srcEntry.entry.mSize; // do not use modSrcOffsetCheck here!
+
+ // ---- big convex surgery ----
+ if(convexSurgery && removeBigData)
+ setNullPtr(false);
+ // ---- big convex surgery ----
+ }
+
+ j++;
+ }
+
+ displayMessage(PxErrorCode::eDEBUG_INFO, "---------------------------------------------\n");
+
+ while(j<nbDstEntries)
+ {
+ assert(dstEntries[j].entry.mFlags & PxMetaDataFlag::ePADDING);
+ if(dstEntries[j].entry.mFlags & PxMetaDataFlag::ePADDING)
+ {
+ dstOffsetCheck += dstEntries[j].entry.mSize;
+ }
+ j++;
+ }
+
+ assert(j==nbDstEntries);
+ assert(dstOffsetCheck==target_mc->mSize);
+ assert(srcOffsetCheck==mc->mSize);
+
+ // ---- big convex surgery ----
+ if(convexSurgery)
+ mConvexFlags.pushBack(removeBigData);
+ // ---- big convex surgery ----
+
+ return true;
+}
+
+// Handles data defined with PX_DEF_BIN_METADATA_EXTRA_ARRAY
+const char* Sn::ConvX::convertExtraData_Array(const char* Address, const char* lastAddress, const char* objectAddress,
+ const ExtraDataEntry& ed)
+{
+ (void)lastAddress;
+ MetaClass* mc = getMetaClass(ed.entry.mType, META_DATA_SRC);
+ assert(mc);
+
+ // PT: safe to cast to int here since we're reading a count.
+ const int count = int(peek(ed.entry.mSize, objectAddress + ed.offset, ed.entry.mFlags));
+
+ // if(ed.entry.mCount) // Reused as align value
+ if(ed.entry.mAlignment)
+ {
+ Address = alignStream(Address, ed.entry.mAlignment);
+ // Address = alignStream(Address, ed.entry.mCount);
+ assert(Address<=lastAddress);
+ }
+
+ for(int c=0;c<count;c++)
+ {
+ convertClass(Address, mc, 0);
+ Address += mc->mSize;
+ assert(Address<=lastAddress);
+ }
+ return Address;
+}
+
+const char* Sn::ConvX::convertExtraData_Ptr(const char* Address, const char* lastAddress, const PxMetaDataEntry& entry, int count,
+ int ptrSize_Src, int ptrSize_Dst)
+{
+ (void)lastAddress;
+
+ PxMetaDataEntry tmpSrc = entry;
+ tmpSrc.mCount = count;
+ tmpSrc.mSize = count * ptrSize_Src;
+
+ PxMetaDataEntry tmpDst = entry;
+ tmpDst.mCount = count;
+ tmpDst.mSize = count * ptrSize_Dst;
+
+
+ displayMessage(PxErrorCode::eDEBUG_INFO, "extra data ptrs\n");
+ displayMessage(PxErrorCode::eDEBUG_INFO, "+++++++++++++++++++++++++++++++++++++++++++++\n");
+ displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t\t\t%s", Address, Address[0], entry.mName);
+ for (int byteCount = 1; byteCount < ptrSize_Src*count; ++byteCount)
+ displayMessage(PxErrorCode::eDEBUG_INFO, "\t0x%p\t%x\t\t\t.", Address + byteCount, Address[byteCount]);
+
+ convertPtr(Address, tmpSrc, tmpDst);
+ Address += count * ptrSize_Src;
+ assert(Address<=lastAddress);
+ return Address;
+}
+
+static bool decodeControl(PxU64 control, const ExtraDataEntry& ed, PxU64 controlMask = 0)
+{
+ if(ed.entry.mFlags & PxMetaDataFlag::eCONTROL_FLIP)
+ {
+ if(controlMask)
+ {
+ return (control & controlMask) ? false : true;
+ }
+ else
+ {
+ return control==0;
+ }
+ }
+ else
+ {
+ if(controlMask)
+ {
+ return (control & controlMask) ? true : false;
+ }
+ else
+ {
+ return control!=0;
+ }
+ }
+
+}
+
+// ### currently hardcoded, should change
+int Sn::ConvX::getConcreteType(const char* buffer)
+{
+ MetaClass* mc = getMetaClass("PxBase", META_DATA_SRC);
+ assert(mc);
+ PxMetaDataEntry entry;
+ if(mc->getFieldByType("PxType", entry))
+ {
+ // PT: safe to cast to int here since we're reading our own PxType
+ return int(peek(entry.mSize, buffer + entry.mOffset));
+ }
+ assert(0);
+ return 0xffffffff;
+}
+
+struct Item : public shdfnd::UserAllocated
+{
+ MetaClass* mc;
+ const char* address;
+};
+
+bool Sn::ConvX::convertCollection(const void* buffer, int fileSize, int nbObjects)
+{
+ const char* lastAddress = reinterpret_cast<const char*>(buffer) + fileSize;
+ const char* Address = alignStream(reinterpret_cast<const char*>(buffer));
+
+ const int ptrSize_Src = mSrcPtrSize;
+ const int ptrSize_Dst = mDstPtrSize;
+ Item* objects = PX_NEW(Item)[PxU32(nbObjects)];
+
+ for(PxU32 i=0;i<PxU32(nbObjects);i++)
+ {
+ const float percents = float(i)/float(nbObjects);
+
+ displayMessage(PxErrorCode::eDEBUG_INFO, "Object conversion: %d%%", int(percents*100.0f));
+
+ Address = alignStream(Address);
+ assert(Address<=lastAddress);
+
+ PxConcreteType::Enum classType = PxConcreteType::Enum(getConcreteType(Address));
+ MetaClass* metaClass = getMetaClass(classType, META_DATA_SRC);
+ if(!metaClass)
+ {
+ PX_DELETE_ARRAY(objects);
+ return false;
+ }
+
+ objects[i].mc = metaClass;
+ objects[i].address = Address;
+
+ if(!convertClass(Address, metaClass, 0))
+ {
+ PX_DELETE_ARRAY(objects);
+ return false;
+ }
+
+ Address += metaClass->mSize;
+ assert(Address<=lastAddress);
+ }
+
+ // Fields / extra data
+ if(1)
+ {
+ // ---- big convex surgery ----
+ unsigned int nbConvexes = 0;
+ // ---- big convex surgery ----
+ //const char* StartAddress2 = Address;
+ //int startDstSize2 = getCurrentOutputSize();
+ for(int i=0;i<nbObjects;i++)
+ {
+ //const char* StartAddress = Address;
+ //int startDstSize = getCurrentOutputSize();
+
+ const float percents = float(i)/float(nbObjects);
+
+ displayMessage(PxErrorCode::eDEBUG_INFO, "Extra data conversion: %d%%", int(percents*100.0f));
+
+ MetaClass* mc0 = objects[i].mc;
+ const char* objectAddress = objects[i].address;
+
+ // printf("%d: %s\n", i, mc->mClassName);
+ // if(strcmp(mc->mClassName, "TriangleMesh")==0)
+ // if(strcmp(mc->mClassName, "NpRigidDynamic")==0)
+ if(strcmp(mc0->mClassName, "HybridModel")==0)
+ {
+ int stop=1;
+ (void)(stop);
+ }
+
+ // ### we actually need to collect all extra data for this class, including data from embedded members.
+
+ PX_ALLOCA(entries, ExtraDataEntry, 256);
+ int nbEntries = 0;
+ _enumerateExtraData(objectAddress, mc0, entries, nbEntries, 0, META_DATA_SRC);
+ assert(nbEntries<256);
+
+ Address = alignStream(Address);
+ assert(Address<=lastAddress);
+
+ for(int j=0;j<nbEntries;j++)
+ {
+ const ExtraDataEntry& ed = entries[j];
+ assert(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_DATA);
+
+ if(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEM)
+ {
+ // ---- big convex surgery ----
+ if(1)
+ {
+ const bool isBigConvexData = strcmp(ed.entry.mType, "BigConvexData")==0;
+ if(isBigConvexData)
+ {
+ assert(nbConvexes<mConvexFlags.size());
+ if(mConvexFlags[nbConvexes++])
+ setNoOutput(true);
+ }
+ }
+ // ---- big convex surgery ----
+
+ MetaClass* extraDataType = getMetaClass(ed.entry.mType, META_DATA_SRC);
+ assert(extraDataType);
+
+ //sschirm: we used to have ed.entry.mOffset here, but that made cloth deserialization fail.
+ const char* controlAddress = objectAddress + ed.offset;
+ const PxU64 controlValue = peek(ed.entry.mOffsetSize, controlAddress);
+
+ if(controlValue)
+ {
+ if(ed.entry.mAlignment)
+ {
+ Address = alignStream(Address, ed.entry.mAlignment);
+ assert(Address<=lastAddress);
+ }
+
+ const char* classAddress = Address;
+ convertClass(Address, extraDataType, 0);
+ Address += extraDataType->mSize;
+ assert(Address<=lastAddress);
+
+ // Enumerate extra data for this optional class, and convert it too.
+ // This assumes the extra data for the optional class is always appended to the class itself,
+ // which is something we'll need to enforce in the SDK. So far this is only to handle optional
+ // inline arrays.
+
+ // ### this should probably be recursive eventually
+ PX_ALLOCA(entries2, ExtraDataEntry, 256);
+ int nbEntries2 = 0;
+ _enumerateExtraData(objectAddress, extraDataType, entries2, nbEntries2, 0, META_DATA_SRC);
+ assert(nbEntries2<256);
+ for(int k=0;k<nbEntries2;k++)
+ {
+ const ExtraDataEntry& ed2 = entries2[k];
+ assert(ed2.entry.mFlags & PxMetaDataFlag::eEXTRA_DATA);
+ if(ed2.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEMS)
+ {
+ const int controlOffset = ed2.entry.mOffset;
+ const int controlSize = ed2.entry.mSize;
+ const int countOffset = ed2.entry.mCount;
+ const int countSize = ed2.entry.mOffsetSize;
+
+ const PxU64 controlValue2 = peek(controlSize, classAddress + controlOffset);
+
+ PxU64 controlMask = 0;
+ if(ed2.entry.mFlags & PxMetaDataFlag::eCONTROL_MASK)
+ {
+ controlMask = PxU64(ed2.entry.mFlags & (PxMetaDataFlag::eCONTROL_MASK_RANGE << 16));
+ controlMask = controlMask >> 16;
+ }
+
+ if(decodeControl(controlValue2, ed2, controlMask))
+ {
+ // PT: safe to cast to int here since we're reading a count
+ int count = int(peek(countSize, classAddress + countOffset, ed2.entry.mFlags));
+
+ if(ed2.entry.mAlignment)
+ {
+ assert(0); // Never tested
+ Address = alignStream(Address, ed2.entry.mAlignment);
+ assert(Address<=lastAddress);
+ }
+
+ if(ed2.entry.mFlags & PxMetaDataFlag::ePTR)
+ {
+ assert(0); // Never tested
+ }
+ else
+ {
+ MetaClass* mc = getMetaClass(ed2.entry.mType, META_DATA_SRC);
+ assert(mc);
+
+ while(count--)
+ {
+ convertClass(Address, mc, 0);
+ Address += mc->mSize;
+ assert(Address<=lastAddress);
+ }
+ }
+
+ }
+ }
+ else
+ {
+ if( (ed2.entry.mFlags & PxMetaDataFlag::eALIGNMENT) && ed2.entry.mAlignment)
+ {
+ Address = alignStream(Address, ed2.entry.mAlignment);
+ assert(Address<=lastAddress);
+ }
+ else
+ {
+ // We assume it's an normal array, e.g. the ones from "big convexes"
+ assert(!(ed2.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEM));
+
+ Address = convertExtraData_Array(Address, lastAddress, classAddress, ed2);
+ }
+ }
+ }
+
+ }
+ else
+ {
+ int stop = 0;
+ (void)(stop);
+ }
+
+ // ---- big convex surgery ----
+ setNoOutput(false);
+ // ---- big convex surgery ----
+ }
+ else if(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_ITEMS)
+ {
+ // PX_DEF_BIN_METADATA_EXTRA_ITEMS
+ int reloc = ed.offset - ed.entry.mOffset; // ### because the enum code only fixed the "controlOffset"!
+ const int controlOffset = ed.entry.mOffset;
+ const int controlSize = ed.entry.mSize;
+ const int countOffset = ed.entry.mCount;
+ const int countSize = ed.entry.mOffsetSize;
+
+ // const int controlValue2 = peek(controlSize, objectAddress + controlOffset);
+ const PxU64 controlValue2 = peek(controlSize, objectAddress + controlOffset + reloc);
+
+ PxU64 controlMask = 0;
+ if(ed.entry.mFlags & PxMetaDataFlag::eCONTROL_MASK)
+ {
+ controlMask = PxU64(ed.entry.mFlags & (PxMetaDataFlag::eCONTROL_MASK_RANGE << 16));
+ controlMask = controlMask >> 16;
+ }
+
+ if(decodeControl(controlValue2, ed, controlMask))
+ {
+ // PT: safe to cast to int here since we're reading a count
+ // int count = peek(countSize, objectAddress + countOffset); // ###
+ int count = int(peek(countSize, objectAddress + countOffset + reloc, ed.entry.mFlags)); // ###
+
+ if(ed.entry.mAlignment)
+ {
+ Address = alignStream(Address, ed.entry.mAlignment);
+ assert(Address<=lastAddress);
+ }
+
+ if(ed.entry.mFlags & PxMetaDataFlag::ePTR)
+ {
+ Address = convertExtraData_Ptr(Address, lastAddress, ed.entry, count, ptrSize_Src, ptrSize_Dst);
+ }
+ else
+ {
+ MetaClass* mc = getMetaClass(ed.entry.mType, META_DATA_SRC);
+ assert(mc);
+
+ while(count--)
+ {
+ convertClass(Address, mc, 0);
+ Address += mc->mSize;
+ assert(Address<=lastAddress);
+ }
+ }
+ }
+
+ }
+ else if(ed.entry.mFlags & PxMetaDataFlag::eALIGNMENT)
+ {
+ if(ed.entry.mAlignment)
+ {
+ displayMessage(PxErrorCode::eDEBUG_INFO, " align to %d bytes\n", ed.entry.mAlignment);
+ displayMessage(PxErrorCode::eDEBUG_INFO, "---------------------------------------------\n");
+
+ Address = alignStream(Address, ed.entry.mAlignment);
+ assert(Address<=lastAddress);
+ }
+ }
+ else if(ed.entry.mFlags & PxMetaDataFlag::eEXTRA_NAME)
+ {
+ if(ed.entry.mAlignment)
+ {
+ Address = alignStream(Address, ed.entry.mAlignment);
+ assert(Address<=lastAddress);
+ }
+
+ //get string count
+ MetaClass* mc = getMetaClass("PxU32", META_DATA_SRC);
+ assert(mc);
+ //safe to cast to int here since we're reading a count.
+ const int count = int(peek(mc->mSize, Address, 0));
+
+ displayMessage(PxErrorCode::eDEBUG_INFO, " convert %d bytes string\n", count);
+
+ convertClass(Address, mc, 0);
+ Address += mc->mSize;
+
+ mc = getMetaClass(ed.entry.mType, META_DATA_SRC);
+ assert(mc);
+
+ for(int c=0;c<count;c++)
+ {
+ convertClass(Address, mc, 0);
+ Address += mc->mSize;
+ assert(Address<=lastAddress);
+ }
+ }
+ else
+ {
+ Address = convertExtraData_Array(Address, lastAddress, objectAddress, ed);
+ }
+ }
+ }
+ PX_DELETE_ARRAY(objects);
+ assert(nbConvexes==mConvexFlags.size());
+ }
+
+ assert(Address==lastAddress);
+
+ return true;
+}
+
+bool Sn::ConvX::convert(const void* buffer, int fileSize)
+{
+ // Test initial alignment
+ if(size_t(buffer) & (ALIGN_DEFAULT-1))
+ {
+ assert(0);
+ return false;
+ }
+
+ const int header = read32(buffer); fileSize -= 4; (void)header;
+
+ if (header != PX_MAKE_FOURCC('S','E','B','D'))
+ {
+ displayMessage(physx::PxErrorCode::eINVALID_PARAMETER,
+ "PxBinaryConverter: Buffer contains data with bad header indicating invalid serialized data.");
+ return false;
+ }
+
+ const int version = read32(buffer); fileSize -= 4; (void)version;
+
+ const int binaryVersion = read32(buffer); fileSize -= 4;
+
+ if (!checkCompatibility(PxU32(version), PxU32(binaryVersion)))
+ {
+ char buf[512];
+ getCompatibilityVersionsStr(buf, 512);
+
+ displayMessage(physx::PxErrorCode::eINVALID_PARAMETER,
+ "PxBinaryConverter: Buffer contains data version (%x-%d) is incompatible with this PhysX sdk.\n These versions would be compatible: %s",
+ version, binaryVersion, buf);
+ return false;
+ }
+ const int buildNumber = read32(buffer); fileSize -= 4; (void)buildNumber;
+
+ //read src platform tag and write dst platform tag according dst meta data
+ const int srcPlatformTag = *reinterpret_cast<const int*>(buffer);
+ buffer = reinterpret_cast<const void*>(size_t(buffer) + 4);
+ fileSize -= 4;
+ const int dstPlatformTag = mMetaData_Dst->getPlatformTag();
+ output(dstPlatformTag);
+
+ if (srcPlatformTag != mMetaData_Src->getPlatformTag())
+ {
+ displayMessage(physx::PxErrorCode::eINVALID_PARAMETER,
+ "PxBinaryConverter: Mismatch of platform tags of binary data and metadata:\n Binary Data: %s\n MetaData: %s\n",
+ getBinaryPlatformName(PxU32(srcPlatformTag)),
+ getBinaryPlatformName(PxU32(mMetaData_Src->getPlatformTag())));
+ return false;
+ }
+
+ //read whether input data has marked padding, and set it for the output data (since 0xcd is written into pads on conversion)
+ const int srcMarkedPadding = *reinterpret_cast<const int*>(buffer);
+ buffer = reinterpret_cast<const void*>(size_t(buffer) + 4);
+ fileSize -= 4;
+ mMarkedPadding = srcMarkedPadding != 0;
+ const int dstMarkedPadding = 1;
+ output(dstMarkedPadding);
+
+ int nbObjectsInCollection;
+
+ buffer = convertReferenceTables(buffer, fileSize, nbObjectsInCollection);
+ if(!buffer)
+ return false;
+
+ bool ret = convertCollection(buffer, fileSize, nbObjectsInCollection);
+ mMarkedPadding = false;
+ return ret;
+}
+
+// PT: code below added to support 64bit-to-32bit conversions
+void Sn::ConvX::exportIntAsPtr(int value)
+{
+ const int ptrSize_Src = mSrcPtrSize;
+ const int ptrSize_Dst = mDstPtrSize;
+
+ PxMetaDataEntry entry;
+
+ const char* address = NULL;
+ const PxU32 value32 = PxU32(value);
+ const PxU64 value64 = PxU64(value)&0xffffffff;
+
+ if(ptrSize_Src==4)
+ {
+ address = reinterpret_cast<const char*>(&value32);
+ }
+ else if(ptrSize_Src==8)
+ {
+ address = reinterpret_cast<const char*>(&value64);
+ }
+ else assert(0);
+
+ convertExtraData_Ptr(address, address + ptrSize_Src, entry, 1, ptrSize_Src, ptrSize_Dst);
+}
+
+void Sn::ConvX::exportInt(int value)
+{
+ output(value);
+}
+
+void Sn::ConvX::exportInt64(PxU64 value)
+{
+ output(value);
+}
+
+PointerRemap::PointerRemap()
+{
+}
+
+PointerRemap::~PointerRemap()
+{
+}
+
+bool PointerRemap::checkRefIsNotUsed(PxU32 ref) const
+{
+ const PxU32 size = mData.size();
+ for(PxU32 i=0;i<size;i++)
+ {
+ if(mData[i].id==ref)
+ return false;
+ }
+ return true;
+}
+
+void PointerRemap::setObjectRef(PxU64 object64, PxU32 ref)
+{
+ const PxU32 size = mData.size();
+ for(PxU32 i=0;i<size;i++)
+ {
+ if(mData[i].object==object64)
+ {
+ mData[i].id = ref;
+ return;
+ }
+ }
+ InternalData data;
+ data.object = object64;
+ data.id = ref;
+ mData.pushBack(data);
+}
+
+bool PointerRemap::getObjectRef(PxU64 object64, PxU32& ref) const
+{
+ const PxU32 size = mData.size();
+ for(PxU32 i=0;i<size;i++)
+ {
+ if(mData[i].object==object64)
+ {
+ ref = mData[i].id;
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+Converting the PxBase object offsets in the manifest table is fairly complicated now.
+It would be good to have an easy callback mechanism for custom things like this.
+*/
+const void* Sn::ConvX::convertManifestTable(const void* buffer, int& fileSize)
+{
+ PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT);
+ buffer = alignStream(reinterpret_cast<const char*>(buffer));
+ fileSize -= padding;
+ int nb = read32(buffer);
+ fileSize -= 4;
+
+ MetaClass* mc_src = getMetaClass("Sn::ManifestEntry", META_DATA_SRC);
+ assert(mc_src);
+
+ MetaClass* mc_dst = getMetaClass("Sn::ManifestEntry", META_DATA_DST);
+ assert(mc_dst);
+
+ bool mdOk;
+ PxMetaDataEntry srcTypeField;
+ mdOk = mc_src->getFieldByName("type", srcTypeField);
+ PX_UNUSED(mdOk);
+ PX_ASSERT(mdOk);
+
+ PxMetaDataEntry dstOffsetField;
+ mdOk = mc_dst->getFieldByName("offset", dstOffsetField);
+ PX_ASSERT(mdOk);
+
+ const char* address = reinterpret_cast<const char*>(buffer);
+ PxU32 headerOffset = 0;
+ for(int i=0;i<nb;i++)
+ {
+ PxConcreteType::Enum classType = PxConcreteType::Enum(peek(srcTypeField.mSize, address + srcTypeField.mOffset));
+
+ //convert ManifestEntry but output to tmpStream
+ PxDefaultMemoryOutputStream tmpStream;
+ {
+ //backup output state
+ PxOutputStream* outStream = mOutStream;
+ PxU32 outputSize = PxU32(mOutputSize);
+
+ mOutStream = &tmpStream;
+ mOutputSize = 0;
+
+ convertClass(address, mc_src, 0);
+ PX_ASSERT(tmpStream.getSize() == PxU32(mc_dst->mSize));
+
+ //restore output state
+ mOutStream = outStream;
+ mOutputSize = int(outputSize);
+ }
+
+ //output patched offset
+ PX_ASSERT(dstOffsetField.mOffset == 0); //assuming offset is the first data
+ output(int(headerOffset));
+
+ //output rest of ManifestEntry
+ PxU32 restSize = PxU32(mc_dst->mSize - dstOffsetField.mSize);
+ mOutStream->write(tmpStream.getData() + dstOffsetField.mSize, restSize);
+ mOutputSize += restSize;
+
+ //increment source stream
+ address += mc_src->mSize;
+ fileSize -= mc_src->mSize;
+ assert(fileSize>=0);
+
+ //update headerOffset using the type and dst meta data of the type
+ MetaClass* mc_classType_dst = getMetaClass(classType, META_DATA_DST);
+ if(!mc_classType_dst)
+ return NULL;
+ headerOffset += getPadding(size_t(mc_classType_dst->mSize), PX_SERIAL_ALIGN) + mc_classType_dst->mSize;
+ }
+
+ output(int(headerOffset)); //endoffset
+ buffer = address + 4;
+ fileSize -= 4;
+ return buffer;
+}
+
+const void* Sn::ConvX::convertImportReferences(const void* buffer, int& fileSize)
+{
+ PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT);
+ buffer = alignStream(reinterpret_cast<const char*>(buffer));
+ fileSize -= padding;
+ int nb = read32(buffer);
+ fileSize -= 4;
+
+ if(!nb)
+ return buffer;
+
+ MetaClass* mc = getMetaClass("Sn::ImportReference", META_DATA_SRC);
+ assert(mc);
+
+ const char* address = reinterpret_cast<const char*>(buffer);
+ for(int i=0;i<nb;i++)
+ {
+ convertClass(address, mc, 0);
+ address += mc->mSize;
+ fileSize -= mc->mSize;
+ assert(fileSize>=0);
+ }
+ return address;
+}
+
+const void* Sn::ConvX::convertExportReferences(const void* buffer, int& fileSize)
+{
+ PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT);
+ buffer = alignStream(reinterpret_cast<const char*>(buffer));
+ fileSize -= padding;
+ int nb = read32(buffer);
+ fileSize -= 4;
+
+ if(!nb)
+ return buffer;
+
+ MetaClass* mc = getMetaClass("Sn::ExportReference", META_DATA_SRC);
+ assert(mc);
+
+ const char* address = reinterpret_cast<const char*>(buffer);
+ for(int i=0;i<nb;i++)
+ {
+ convertClass(address, mc, 0);
+ address += mc->mSize;
+ fileSize -= mc->mSize;
+ assert(fileSize>=0);
+ }
+ return address;
+}
+
+const void* Sn::ConvX::convertInternalReferences(const void* buffer, int& fileSize)
+{
+ PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT);
+ buffer = alignStream(reinterpret_cast<const char*>(buffer));
+ fileSize -= padding;
+
+ //pointer references
+ int nbPtrReferences = read32(buffer);
+ fileSize -= 4;
+ if(nbPtrReferences)
+ {
+ const char* address = reinterpret_cast<const char*>(buffer);
+ MetaClass* mc = getMetaClass("Sn::InternalReferencePtr", META_DATA_SRC);
+ assert(mc);
+ for(int i=0;i<nbPtrReferences;i++)
+ {
+ convertClass(address, mc, 0);
+ address += mc->mSize;
+ fileSize -= mc->mSize;
+ assert(fileSize>=0);
+ }
+ buffer = address;
+ }
+
+ //index references
+ int nbIdxReferences = read32(buffer);
+ fileSize -= 4;
+ if (nbIdxReferences)
+ {
+ const char* address = reinterpret_cast<const char*>(buffer);
+ MetaClass* mc = getMetaClass("Sn::InternalReferenceIdx", META_DATA_SRC);
+ assert(mc);
+ for(int i=0;i<nbIdxReferences;i++)
+ {
+ convertClass(address, mc, 0);
+ address += mc->mSize;
+ fileSize -= mc->mSize;
+ assert(fileSize>=0);
+ }
+ buffer = address;
+ }
+ return buffer;
+}
+
+
+const void* Sn::ConvX::convertReferenceTables(const void* buffer, int& fileSize, int& nbObjectsInCollection)
+{
+ // PT: the map should not be used while creating it, so use one indirection
+ mActiveRemap = NULL;
+ mRemap.mData.clear();
+ mPointerRemapCounter = 0;
+
+ PxU32 padding = getPadding(size_t(buffer), ALIGN_DEFAULT);
+ buffer = alignStream(reinterpret_cast<const char*>(buffer));
+ fileSize -= padding;
+
+ nbObjectsInCollection = read32(buffer);
+ if (nbObjectsInCollection == 0)
+ displayMessage(PxErrorCode::eDEBUG_INFO, "\n\nConverting empty collection!\n\n");
+ fileSize -= 4;
+
+ buffer = convertManifestTable(buffer, fileSize);
+
+ if(!buffer)
+ return NULL;
+
+ buffer = convertImportReferences(buffer, fileSize);
+ buffer = convertExportReferences(buffer, fileSize);
+ buffer = convertInternalReferences(buffer, fileSize);
+
+ // PT: the map can now be used
+ mActiveRemap = &mRemap;
+
+ return buffer;
+}
+
+bool Sn::ConvX::checkPaddingBytes(const char* buffer, int byteCount)
+{
+ const unsigned char* src = reinterpret_cast<const unsigned char*>(buffer);
+
+ int i = 0;
+ while ((i < byteCount) && (src[i] == 0xcd))
+ i++;
+ return (i == byteCount);
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Error.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Error.cpp
new file mode 100644
index 00000000..9debc679
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Error.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.
+
+#include "foundation/PxErrorCallback.h"
+#include "SnConvX.h"
+#include <stdarg.h>
+#include "PsString.h"
+#include "PsFoundation.h"
+
+#define MAX_DISPLAYED_ISSUES 10
+
+using namespace physx;
+
+void Sn::ConvX::resetNbErrors()
+{
+ mNbErrors = 0;
+ mNbWarnings = 0;
+}
+
+int Sn::ConvX::getNbErrors() const
+{
+ return mNbErrors;
+}
+
+void Sn::ConvX::displayMessage(PxErrorCode::Enum code, const char* format, ...)
+{
+ if(silentMode())
+ return;
+
+ int sum = mNbWarnings + mNbErrors;
+ if(sum >= MAX_DISPLAYED_ISSUES)
+ return;
+
+ bool display = false;
+
+ if(code==PxErrorCode::eINTERNAL_ERROR || code==PxErrorCode::eINVALID_OPERATION || code==PxErrorCode::eINVALID_PARAMETER)
+ {
+ mNbErrors++;
+ display = true;
+ }
+ else if(code == PxErrorCode::eDEBUG_WARNING)
+ {
+ mNbWarnings++;
+ display = true;
+ }
+
+ if(display || ((sum == 0) && verboseMode()) )
+ {
+ va_list va;
+ va_start(va, format);
+ Ps::getFoundation().errorImpl(code, __FILE__, __LINE__, format, va);
+ va_end(va);
+ }
+
+ if(display)
+ {
+ if( sum == 0)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_INFO, __FILE__, __LINE__, "Hit warnings or errors: skipping further verbose output.\n");
+ }
+ else if(sum == MAX_DISPLAYED_ISSUES-1)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_INFO, __FILE__, __LINE__, "Exceeding 10 warnings or errors: skipping further output.\n");
+ }
+ }
+
+ return;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.cpp
new file mode 100644
index 00000000..4d2eda22
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.cpp
@@ -0,0 +1,840 @@
+// 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 "foundation/PxIO.h"
+#include "SnConvX.h"
+#include "common/PxSerialFramework.h"
+#include "serialization/SnSerialUtils.h"
+#include <assert.h>
+
+using namespace physx;
+using namespace physx::Sn;
+
+//#define REMOVE_EXPLICIT_PADDING
+
+static const char gVTablePtr[] = "v-table ptr";
+static const char gAutoPadding[] = "auto-generated padding";
+static const char gByte[] = "paddingByte";
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool PxMetaDataEntry::isVTablePtr() const
+{
+ return mType==gVTablePtr;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+bool MetaClass::getFieldByType(const char* type, PxMetaDataEntry& entry) const
+{
+ assert(type);
+ PxU32 nbFields = mFields.size();
+ for(PxU32 i=0;i<nbFields;i++)
+ {
+ if(strcmp(mFields[i].mType, type)==0)
+ {
+ entry = mFields[i];
+ return true;
+ }
+ }
+ return false;
+}
+
+bool MetaClass::getFieldByName(const char* name, PxMetaDataEntry& entry) const
+{
+ assert(name);
+ PxU32 nbFields = mFields.size();
+ for(PxU32 i=0;i<nbFields;i++)
+ {
+ if(strcmp(mFields[i].mName, name)==0)
+ {
+ entry = mFields[i];
+ return true;
+ }
+ }
+ return false;
+}
+
+void MetaClass::checkAndCompleteClass(const MetaData& owner, int& startOffset, int& nbBytes)
+{
+ if(startOffset!=-1)
+ {
+ owner.mConvX.displayMessage(PxErrorCode::eDEBUG_INFO,
+ "\n Adding %d padding bytes at offset %d in class %s.\n", nbBytes, startOffset, mClassName);
+
+ // Leap of faith: add padding bytes there
+ PxMetaDataEntry padding;
+ padding.mType = gByte;
+ padding.mName = gAutoPadding;
+ padding.mOffset = startOffset;
+ padding.mSize = nbBytes;
+ padding.mCount = nbBytes;
+ padding.mFlags = PxMetaDataFlag::ePADDING;
+ mFields.pushBack(padding);
+
+ startOffset = -1;
+ }
+}
+
+bool MetaClass::check(const MetaData& owner)
+{
+ owner.mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Checking class: %s\n", mClassName);
+
+ if(mCallback)
+ return true; // Skip atomic types
+ if(mMaster)
+ return true; // Skip typedefs
+
+ bool* map = reinterpret_cast<bool*>(PX_ALLOC(sizeof(bool)*mSize, "bool"));
+ memset(map, 0, size_t(mSize));
+
+ const PxU32 nbFields = mFields.size();
+ for(PxU32 i=0;i<nbFields;i++)
+ {
+ const PxMetaDataEntry& field = mFields[i];
+ if(field.mFlags & PxMetaDataFlag::eEXTRA_DATA)
+ continue;
+// if((field.mFlags & PxMetaDataFlag::eUNION) && !field.mSize)
+// continue; // Union type
+ assert(field.mSize);
+ const int byteStart = field.mOffset;
+ const int byteEnd = field.mOffset + field.mSize;
+ assert(byteStart>=0 && byteStart<mSize);
+ assert(byteEnd>=0 && byteEnd<=mSize);
+
+ int startOffset = -1;
+ int nbBytes = 0;
+ for(int j=byteStart;j<byteEnd;j++)
+ {
+ if(map[j])
+ {
+ if(startOffset==-1)
+ {
+ startOffset = int(i);
+ nbBytes = 0;
+ }
+ nbBytes++;
+// displayErrorMessage(" %s: found overlapping bytes!\n", mClassName);
+ }
+ else
+ {
+ if(startOffset!=-1)
+ {
+ owner.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR,
+ "PxBinaryConverter: %s: %d overlapping bytes at offset %d!\n", mClassName, nbBytes, startOffset);
+ startOffset = -1;
+ PX_ALWAYS_ASSERT_MESSAGE("Overlapping bytes!");
+ }
+ }
+ map[j] = true;
+ }
+ if(startOffset!=-1)
+ {
+ owner.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR,
+ "PxBinaryConverter: %s: %d overlapping bytes at offset %d!\n", mClassName, nbBytes, startOffset);
+ startOffset = -1;
+ PX_ALWAYS_ASSERT_MESSAGE("Overlapping bytes!");
+ }
+ }
+
+ {
+ int startOffset = -1;
+ int nbBytes = 0;
+ for(int i=0;i<mSize;i++)
+ {
+ if(!map[i])
+ {
+ if(startOffset==-1)
+ {
+ startOffset = i;
+ nbBytes = 0;
+ }
+ nbBytes++;
+ }
+ else
+ {
+ checkAndCompleteClass(owner, startOffset, nbBytes);
+ }
+ }
+ checkAndCompleteClass(owner, startOffset, nbBytes);
+ }
+ PX_FREE(map);
+
+
+ //
+ for(PxU32 i=0;i<nbFields;i++)
+ {
+ const PxMetaDataEntry& current = mFields[i];
+ if(current.mFlags & PxMetaDataFlag::ePTR)
+ continue;
+
+ MetaClass* fieldMetaClass = owner.mConvX.getMetaClass(current.mType, owner.getType());
+ if(!fieldMetaClass)
+ {
+ owner.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR,
+ "PxBinaryConverter: Missing meta-data for: %s\n", current.mType);
+ return false;
+ }
+ else
+ {
+ if(current.mFlags & PxMetaDataFlag::eEXTRA_DATA)
+ {
+ owner.mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Extra data: %s\n", current.mType);
+ }
+ else
+ {
+ assert(fieldMetaClass->mSize*current.mCount==current.mSize);
+ }
+ }
+ }
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+MetaData::MetaData(ConvX& convx) :
+ mConvX (convx),
+ mType (META_DATA_NONE),
+ mNbEntries (0),
+ mEntries (NULL),
+ mStringTable (NULL),
+ mVersion (0),
+ mBuildNumber (0),
+ mSizeOfPtr (0),
+ mPlatformTag (0),
+ mGaussMapLimit (0),
+ mFlip (false)
+{
+}
+
+MetaData::~MetaData()
+{
+ PxU32 nbMetaClasses = mMetaClasses.size();
+ for(PxU32 i=0;i<nbMetaClasses;i++)
+ {
+ MetaClass* current = mMetaClasses[i];
+ PX_DELETE(current);
+ }
+
+ PX_FREE(mStringTable);
+ PX_DELETE_ARRAY(mEntries);
+}
+
+MetaClass* MetaData::getMetaClass(const char* name) const
+{
+ PxU32 nbMetaClasses = mMetaClasses.size();
+ for(PxU32 i=0;i<nbMetaClasses;i++)
+ {
+ MetaClass* current = mMetaClasses[i];
+ if(strcmp(current->mClassName, name)==0)
+ {
+ while(current->mMaster)
+ current = current->mMaster;
+ return current;
+ }
+ }
+ return NULL;
+}
+
+MetaClass* MetaData::getMetaClass(PxConcreteType::Enum concreteType) const
+{
+ for(PxU32 i=0; i< mConcreteTypeTable.size(); i++)
+ {
+ if(mConcreteTypeTable[i].first == concreteType)
+ {
+ const char* className = offsetToText(reinterpret_cast<const char*>(size_t(mConcreteTypeTable[i].second)));
+ return getMetaClass(className);
+ }
+ }
+ return NULL;
+}
+
+MetaClass* MetaData::addNewClass(const char* name, int size, MetaClass* master, ConvertCallback callback)
+{
+ // PT: if you reach this assert, you used PX_DEF_BIN_METADATA_TYPEDEF twice on the same type
+ assert(!getMetaClass(name));
+ MetaClass* mc = PX_NEW(MetaClass);
+ mc->mCallback = callback;
+ mc->mMaster = master;
+ mc->mClassName = name;
+ mc->mSize = size;
+ mc->mDepth = 0;
+ mc->mProcessed = false;
+// mc->mNbEntries = -1;
+
+ mMetaClasses.pushBack(mc);
+
+ return mc;
+}
+
+bool MetaData::load(PxInputStream& inputStream, MetaDataType type)
+{
+ assert(type!=META_DATA_NONE);
+
+ mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Loading %s meta-data...\n", type==META_DATA_SRC ? "source" : "target");
+
+ mType = type;
+
+ mFlip = false;
+ {
+ int header;
+ inputStream.read(&header, 4);
+ if(header==PX_MAKE_FOURCC('M','E','T','A'))
+ {
+ mFlip = false;
+ }
+ else if(header==PX_MAKE_FOURCC('A','T','E','M'))
+ {
+ mFlip = true;
+ }
+ else
+ {
+ mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER, "PxBinaryConverter: invalid meta-data file!\n");
+ return false;
+ }
+
+ if (type == META_DATA_SRC && mFlip)
+ {
+ mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER,
+ "PxBinaryConverter: source meta data needs to match endianness with current system!");
+ return false;
+ }
+
+ inputStream.read(&mVersion, 4);
+ inputStream.read(&mBinaryVersion, 4);
+ if(mFlip)
+ {
+ flip(mVersion);
+ flip(mBinaryVersion);
+ }
+
+ if (!checkCompatibility(PxU32(mVersion), PxU32(mBinaryVersion)))
+ {
+ char buffer[512];
+ getCompatibilityVersionsStr(buffer, 512);
+
+ mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER,
+ "PxBinaryConverter: data version (%x-%d) is incompatible with this PhysX sdk.\n These versions would be compatible: %s",
+ mVersion, mBinaryVersion, buffer);
+
+ return false;
+ }
+ inputStream.read(&mBuildNumber, 4);
+ if(mFlip)
+ flip(mBuildNumber);
+
+
+ inputStream.read(&mSizeOfPtr, 4);
+ if(mFlip)
+ flip(mSizeOfPtr);
+
+ inputStream.read(&mPlatformTag, 4);
+ if(mFlip)
+ flip(mPlatformTag);
+
+ if (!Sn::isBinaryPlatformTagValid(PxU32(mPlatformTag)))
+ {
+ mConvX.displayMessage(PxErrorCode::eINVALID_PARAMETER, "PxBinaryConverter: Unknown meta data platform tag");
+ return false;
+ }
+
+ inputStream.read(&mGaussMapLimit, 4);
+ if(mFlip)
+ flip(mGaussMapLimit);
+
+ inputStream.read(&mNbEntries, 4);
+ if(mFlip)
+ flip(mNbEntries);
+
+ mEntries = PX_NEW(PxMetaDataEntry)[PxU32(mNbEntries)];
+ if(mSizeOfPtr==8)
+ {
+ for(int i=0;i<mNbEntries;i++)
+ {
+ MetaDataEntry64 tmp;
+ inputStream.read(&tmp, sizeof(MetaDataEntry64));
+ if (mFlip) // important to flip them first, else the cast below might destroy information
+ {
+ flip(tmp.mType);
+ flip(tmp.mName);
+ }
+ // We can safely cast to 32bits here since we transformed the pointers to offsets in the string table on export
+ mEntries[i].mType = reinterpret_cast<const char*>(size_t(tmp.mType));
+ mEntries[i].mName = reinterpret_cast<const char*>(size_t(tmp.mName));
+ mEntries[i].mOffset = tmp.mOffset;
+ mEntries[i].mSize = tmp.mSize;
+ mEntries[i].mCount = tmp.mCount;
+ mEntries[i].mOffsetSize = tmp.mOffsetSize;
+ mEntries[i].mFlags = tmp.mFlags;
+ mEntries[i].mAlignment = tmp.mAlignment;
+ }
+ }
+ else
+ {
+ assert(mSizeOfPtr==4);
+// inputStream.read(mEntries, mNbEntries*sizeof(PxMetaDataEntry));
+ for(int i=0;i<mNbEntries;i++)
+ {
+ MetaDataEntry32 tmp;
+ inputStream.read(&tmp, sizeof(MetaDataEntry32));
+ if (mFlip)
+ {
+ flip(tmp.mType);
+ flip(tmp.mName);
+ }
+ mEntries[i].mType = reinterpret_cast<const char*>(size_t(tmp.mType));
+ mEntries[i].mName = reinterpret_cast<const char*>(size_t(tmp.mName));
+ mEntries[i].mOffset = tmp.mOffset;
+ mEntries[i].mSize = tmp.mSize;
+ mEntries[i].mCount = tmp.mCount;
+ mEntries[i].mOffsetSize = tmp.mOffsetSize;
+ mEntries[i].mFlags = tmp.mFlags;
+ mEntries[i].mAlignment = tmp.mAlignment;
+ }
+ }
+
+ if(mFlip)
+ {
+ for(int i=0;i<mNbEntries;i++)
+ {
+ // mEntries[i].mType and mEntries[i].mName have been flipped already because they need special treatment
+ // on 64bit to 32bit platform conversions
+ flip(mEntries[i].mOffset);
+ flip(mEntries[i].mSize);
+ flip(mEntries[i].mCount);
+ flip(mEntries[i].mOffsetSize);
+ flip(mEntries[i].mFlags);
+ flip(mEntries[i].mAlignment);
+ }
+ }
+
+ int nbConcreteType;
+ inputStream.read(&nbConcreteType, 4);
+ if(mFlip)
+ flip(nbConcreteType);
+
+ for(int i=0; i<nbConcreteType; i++)
+ {
+ PxU16 concreteType;
+ PxU32 nameOffset;
+ inputStream.read(&concreteType, 2);
+ inputStream.read(&nameOffset, 4);
+ if(mFlip)
+ {
+ flip(concreteType);
+ flip(nameOffset);
+ }
+
+ mConcreteTypeTable.pushBack( Ps::Pair<PxConcreteType::Enum, PxU32>(PxConcreteType::Enum(concreteType), nameOffset) );
+ }
+
+ int tableSize;
+ inputStream.read(&tableSize, 4);
+ if(mFlip)
+ flip(tableSize);
+
+ mStringTable = reinterpret_cast<char*>(PX_ALLOC(sizeof(char)*tableSize, "MetaData StringTable"));
+ inputStream.read(mStringTable, PxU32(tableSize));
+ }
+
+ // Register atomic types
+ {
+ addNewClass("bool", 1, NULL, &ConvX::convert8);
+ addNewClass("char", 1, NULL, &ConvX::convert8);
+ addNewClass("short", 2, NULL, &ConvX::convert16);
+ addNewClass("int", 4, NULL, &ConvX::convert32);
+ addNewClass("PxU64", 8, NULL, &ConvX::convert64);
+ addNewClass("float", 4, NULL, &ConvX::convertFloat);
+
+ addNewClass("paddingByte", 1, NULL, &ConvX::convertPad8);
+ }
+
+ {
+ MetaClass* currentClass = NULL;
+ for(int i=0;i<mNbEntries;i++)
+ {
+ mEntries[i].mType = offsetToText(mEntries[i].mType);
+ mEntries[i].mName = offsetToText(mEntries[i].mName);
+
+ if(mEntries[i].mFlags & PxMetaDataFlag::eTYPEDEF)
+ {
+ mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Found typedef: %s => %s\n", mEntries[i].mName, mEntries[i].mType);
+ MetaClass* mc = getMetaClass(mEntries[i].mName);
+ if(mc)
+ addNewClass(mEntries[i].mType, mc->mSize, mc, mc->mCallback);
+ else
+ mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR,
+ "PxBinaryConverter: Invalid typedef - Missing metadata for: %s, please check the source metadata.\n"
+ , mEntries[i].mName);
+ }
+ else if(mEntries[i].mFlags & PxMetaDataFlag::eCLASS)
+ {
+ if(!mEntries[i].mName)
+ {
+ mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, "Found class: %s\n", mEntries[i].mType);
+ currentClass = addNewClass(mEntries[i].mType, mEntries[i].mSize);
+
+ if(mEntries[i].mFlags & PxMetaDataFlag::eVIRTUAL)
+ {
+ PxMetaDataEntry vtable;
+ vtable.mType = gVTablePtr;
+ vtable.mName = gVTablePtr;
+ vtable.mOffset = 0;
+ vtable.mSize = mSizeOfPtr;
+ vtable.mCount = 1;
+ vtable.mFlags = PxMetaDataFlag::ePTR;
+ currentClass->mFields.pushBack(vtable);
+ }
+ }
+ else
+ {
+ assert(currentClass);
+ mConvX.displayMessage(PxErrorCode::eDEBUG_INFO, " - inherits from: %s\n", mEntries[i].mName);
+ currentClass->mBaseClasses.pushBack(mEntries[i]);
+ }
+ }
+ else
+ {
+ const int isUnion = mEntries[i].mFlags & PxMetaDataFlag::eUNION;
+
+ if(isUnion && !mEntries[i].mSize)
+ {
+ mConvX.registerUnionType(mEntries[i].mType, mEntries[i].mName, mEntries[i].mOffset);
+ }
+ else
+ {
+ if(isUnion)
+ {
+ mConvX.registerUnion(mEntries[i].mType);
+ }
+
+ const int isPadding = mEntries[i].mFlags & PxMetaDataFlag::ePADDING;
+
+ assert(currentClass);
+#ifdef REMOVE_EXPLICIT_PADDING
+ if(!isPadding)
+#endif
+ currentClass->mFields.pushBack(mEntries[i]);
+
+ if(isPadding)
+ mConvX.displayMessage(PxErrorCode::eDEBUG_INFO,
+ " - contains padding: %s - %s\n", mEntries[i].mType, mEntries[i].mName);
+ else if(mEntries[i].mFlags & PxMetaDataFlag::eEXTRA_DATA)
+ mConvX.displayMessage(PxErrorCode::eDEBUG_INFO,
+ " - contains extra data: %s%s\n", mEntries[i].mType, mEntries[i].mFlags & PxMetaDataFlag::ePTR ? "*" : "");
+ else
+ mConvX.displayMessage(PxErrorCode::eDEBUG_INFO,
+ " - contains field: %s%s\n", mEntries[i].mType, mEntries[i].mFlags & PxMetaDataFlag::ePTR ? "*" : "");
+
+ }
+ }
+ }
+ }
+
+ // Sort classes by depth
+ struct Local
+ {
+ static bool _computeDepth(const MetaData& md, MetaClass* current, int currentDepth, int& maxDepth)
+ {
+ if(currentDepth>maxDepth)
+ maxDepth = currentDepth;
+
+ PxU32 nbBases = current->mBaseClasses.size();
+ for(PxU32 i=0;i<nbBases;i++)
+ {
+ const PxMetaDataEntry& baseClassEntry = current->mBaseClasses[i];
+ MetaClass* baseClass = md.getMetaClass(baseClassEntry.mName);
+ if(!baseClass)
+ {
+ md.mConvX.displayMessage(PxErrorCode::eINTERNAL_ERROR,
+ "PxBinaryConverter: Can't find class %s metadata, please check the source metadata.\n", baseClassEntry.mName);
+ return false;
+ }
+ if (!_computeDepth(md, baseClass, currentDepth+1, maxDepth))
+ return false;
+ }
+ return true;
+ }
+
+ static int compareClasses(const void* c0, const void* c1)
+ {
+ MetaClass** mc0 = reinterpret_cast<MetaClass**>(const_cast<void*>(c0));
+ MetaClass** mc1 = reinterpret_cast<MetaClass**>(const_cast<void*>(c1));
+// return (*mc0)->mSize - (*mc1)->mSize;
+ return (*mc0)->mDepth - (*mc1)->mDepth;
+ }
+
+ static int compareEntries(const void* c0, const void* c1)
+ {
+ PxMetaDataEntry* mc0 = reinterpret_cast<PxMetaDataEntry*>(const_cast<void*>(c0));
+ PxMetaDataEntry* mc1 = reinterpret_cast<PxMetaDataEntry*>(const_cast<void*>(c1));
+ //mOffset is used to access control information for extra data, and not for offsets of the data itself.
+ assert(!(mc0->mFlags & PxMetaDataFlag::eEXTRA_DATA));
+ assert(!(mc1->mFlags & PxMetaDataFlag::eEXTRA_DATA));
+ return mc0->mOffset - mc1->mOffset;
+ }
+ };
+ {
+ // Compute depths
+ const PxU32 nbMetaClasses = mMetaClasses.size();
+ for(PxU32 i=0;i<nbMetaClasses;i++)
+ {
+ MetaClass* current = mMetaClasses[i];
+ int maxDepth = 0;
+ if(!Local::_computeDepth(*this, current, 0, maxDepth))
+ return false;
+ current->mDepth = maxDepth;
+ }
+
+ // Sort by depth
+ MetaClass** metaClasses = &mMetaClasses[0];
+ qsort(metaClasses, size_t(nbMetaClasses), sizeof(MetaClass*), Local::compareClasses);
+ }
+
+ // Replicate fields from base classes
+ {
+ PxU32 nbMetaClasses = mMetaClasses.size();
+ for(PxU32 k=0;k<nbMetaClasses;k++)
+ {
+ MetaClass* current = mMetaClasses[k];
+ PxU32 nbBases = current->mBaseClasses.size();
+
+ // merge entries of base classes and current class in the right order
+ // this is needed for extra data ordering, which is not covered by the mOffset sort
+ // in the next stage below
+ PsArray<PxMetaDataEntry> mergedEntries;
+
+ for(PxU32 i=0;i<nbBases;i++)
+ {
+ const PxMetaDataEntry& baseClassEntry = current->mBaseClasses[i];
+ MetaClass* baseClass = getMetaClass(baseClassEntry.mName);
+ assert(baseClass);
+ assert(baseClass->mBaseClasses.size()==0 || baseClass->mProcessed);
+
+ PxU32 nbBaseFields = baseClass->mFields.size();
+ for(PxU32 j=0;j<nbBaseFields;j++)
+ {
+ PxMetaDataEntry f = baseClass->mFields[j];
+ // Don't merge primary v-tables to avoid redundant v-table entries.
+ // It means the base v-table won't be inherited & needs to be explicitly defined in the metadata. Seems reasonable.
+ // Could be done better though.
+
+ if(f.mType==gVTablePtr && !f.mOffset && !baseClassEntry.mOffset)
+ continue;
+
+ f.mOffset += baseClassEntry.mOffset;
+ mergedEntries.pushBack(f);
+ }
+ current->mProcessed = true;
+ }
+
+ //append current fields to base class fields
+ for (PxU32 i = 0; i < current->mFields.size(); i++)
+ {
+ mergedEntries.pushBack(current->mFields[i]);
+ }
+ current->mFields.clear();
+ current->mFields.assign(mergedEntries.begin(), mergedEntries.end());
+ }
+ }
+
+ // Check classes
+ {
+ PxU32 nbMetaClasses = mMetaClasses.size();
+ for(PxU32 i=0;i<nbMetaClasses;i++)
+ {
+ MetaClass* current = mMetaClasses[i];
+ if(!current->check(*this))
+ return false;
+ }
+ }
+
+ // Sort meta-data by offset
+ {
+ PxU32 nbMetaClasses = mMetaClasses.size();
+ for(PxU32 i=0;i<nbMetaClasses;i++)
+ {
+ MetaClass* current = mMetaClasses[i];
+ PxU32 nbFields = current->mFields.size();
+ if(nbFields<2)
+ continue;
+ PxMetaDataEntry* entries = &current->mFields[0];
+
+ PxMetaDataEntry* newEntries = PX_NEW(PxMetaDataEntry)[nbFields];
+ PxU32 nb = 0;
+ for(PxU32 j=0;j<nbFields;j++)
+ if(!(entries[j].mFlags & PxMetaDataFlag::eEXTRA_DATA))
+ newEntries[nb++] = entries[j];
+ PxU32 nbToSort = nb;
+ for(PxU32 j=0;j<nbFields;j++)
+ if(entries[j].mFlags & PxMetaDataFlag::eEXTRA_DATA)
+ newEntries[nb++] = entries[j];
+ assert(nb==nbFields);
+ memcpy(entries, newEntries, nb*sizeof(PxMetaDataEntry));
+ PX_DELETE_ARRAY(newEntries);
+ qsort(entries, size_t(nbToSort), sizeof(PxMetaDataEntry), Local::compareEntries);
+ }
+ }
+ return true;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+void ConvX::releaseMetaData()
+{
+ DELETESINGLE(mMetaData_Dst);
+ DELETESINGLE(mMetaData_Src);
+}
+
+const MetaData* ConvX::loadMetaData(PxInputStream& inputStream, MetaDataType type)
+{
+ if (type != META_DATA_SRC && type != META_DATA_DST)
+ {
+ displayMessage(PxErrorCode::eINTERNAL_ERROR,
+ "PxBinaryConverter: Wrong meta data type, please check the source metadata.\n");
+ return NULL;
+ }
+
+ PX_ASSERT(type == META_DATA_SRC || type == META_DATA_DST);
+
+ MetaData*& metaDataPtr = (type == META_DATA_SRC) ? mMetaData_Src : mMetaData_Dst;
+ metaDataPtr = PX_NEW(MetaData)(*this);
+ if(!(metaDataPtr)->load(inputStream, type))
+ DELETESINGLE(metaDataPtr);
+ return metaDataPtr;
+}
+
+const MetaData* ConvX::getBinaryMetaData(MetaDataType type)
+{
+ if(type==META_DATA_SRC)
+ return mMetaData_Src;
+ if(type==META_DATA_DST)
+ return mMetaData_Dst;
+ PX_ASSERT(0);
+ return NULL;
+}
+
+int ConvX::getNbMetaClasses(MetaDataType type)
+{
+ if(type==META_DATA_SRC)
+ return mMetaData_Src->getNbMetaClasses();
+ if(type==META_DATA_DST)
+ return mMetaData_Dst->getNbMetaClasses();
+ PX_ASSERT(0);
+ return 0;
+}
+
+MetaClass* ConvX::getMetaClass(unsigned int i, MetaDataType type) const
+{
+ if(type==META_DATA_SRC)
+ return mMetaData_Src->getMetaClass(i);
+ if(type==META_DATA_DST)
+ return mMetaData_Dst->getMetaClass(i);
+ PX_ASSERT(0);
+ return NULL;
+}
+
+MetaClass* ConvX::getMetaClass(const char* name, MetaDataType type) const
+{
+ if(type==META_DATA_SRC)
+ return mMetaData_Src->getMetaClass(name);
+ if(type==META_DATA_DST)
+ return mMetaData_Dst->getMetaClass(name);
+ PX_ASSERT(0);
+ return NULL;
+}
+
+MetaClass* ConvX::getMetaClass(PxConcreteType::Enum concreteType, MetaDataType type)
+{
+ MetaClass* metaClass = NULL;
+ if(type==META_DATA_SRC)
+ metaClass = mMetaData_Src->getMetaClass(concreteType);
+ if(type==META_DATA_DST)
+ metaClass = mMetaData_Dst->getMetaClass(concreteType);
+
+ if(!metaClass)
+ {
+ displayMessage(PxErrorCode::eINTERNAL_ERROR,
+ "PxBinaryConverter: Missing concreteType %d metadata! serialized a class without dumping metadata. Please check the metadata.",
+ concreteType);
+ return NULL;
+ }
+
+ return metaClass;
+}
+
+///////////////////////////////////////////////////////////////////////////////
+
+// Peek & poke, yes sir.
+PxU64 physx::Sn::peek(int size, const char* buffer, int flags)
+{
+ const int maskMSB = flags & PxMetaDataFlag::eCOUNT_MASK_MSB;
+ const int skipIfOne = flags & PxMetaDataFlag::eCOUNT_SKIP_IF_ONE;
+ switch(size)
+ {
+ case 1:
+ {
+ unsigned char value = *(reinterpret_cast<const unsigned char*>(buffer));
+ if(maskMSB)
+ value &= 0x7f;
+ if(skipIfOne && value==1)
+ return 0;
+ return PxU64(value);
+ }
+ case 2:
+ {
+ unsigned short value = *(reinterpret_cast<const unsigned short*>(buffer));
+ if(maskMSB)
+ value &= 0x7fff;
+ if(skipIfOne && value==1)
+ return 0;
+ return PxU64(value);
+ }
+ case 4:
+ {
+ unsigned int value = *(reinterpret_cast<const unsigned int*>(buffer));
+ if(maskMSB)
+ value &= 0x7fffffff;
+ if(skipIfOne && value==1)
+ return 0;
+ return PxU64(value);
+ }
+ case 8:
+ {
+ PxU64 value = *(reinterpret_cast<const PxU64*>(buffer));
+ if(maskMSB)
+ value &= (PxU64(-1))>>1;
+ if(skipIfOne && value==1)
+ return 0;
+ return value;
+ }
+ };
+ PX_ASSERT(0);
+ return PxU64(-1);
+}
+
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.h
new file mode 100644
index 00000000..29597b62
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_MetaData.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.
+
+#ifndef PX_CONVX_METADATA_H
+#define PX_CONVX_METADATA_H
+
+#include "SnConvX_Output.h"
+#include "PxMetaDataFlags.h"
+
+namespace physx { namespace Sn {
+
+#if PX_VC
+#pragma warning (push)
+#pragma warning (disable : 4371) //layout of class may have changed from a previous version of the compiler due to better packing of member
+#endif
+
+
+ // PT: beware, must match corresponding structure in PxMetaData.h
+ struct PxMetaDataEntry : public shdfnd::UserAllocated
+ {
+ PxMetaDataEntry()
+ {
+ memset(this, 0, sizeof(*this));
+ }
+ bool isVTablePtr() const;
+
+ const char* mType; //!< Field type (bool, byte, quaternion, etc)
+ const char* mName; //!< Field name (appears exactly as in the source file)
+ int mOffset; //!< Offset from the start of the class (ie from "this", field is located at "this"+Offset)
+ int mSize; //!< sizeof(Type)
+ int mCount; //!< Number of items of type Type (0 for dynamic sizes)
+ int mOffsetSize; //!< Offset of dynamic size param, for dynamic arrays
+ int mFlags; //!< Field parameters
+ int mAlignment; //!< Explicit alignment added for DE1340
+ };
+
+ struct MetaDataEntry32
+ {
+ PxI32 mType; //!< Field type (bool, byte, quaternion, etc)
+ PxI32 mName; //!< Field name (appears exactly as in the source file)
+ int mOffset; //!< Offset from the start of the class (ie from "this", field is located at "this"+Offset)
+ int mSize; //!< sizeof(Type)
+ int mCount; //!< Number of items of type Type (0 for dynamic sizes)
+ int mOffsetSize; //!< Offset of dynamic size param, for dynamic arrays
+ int mFlags; //!< Field parameters
+ int mAlignment; //!< Explicit alignment added for DE1340
+ };
+
+ struct MetaDataEntry64
+ {
+ PxI64 mType; //!< Field type (bool, byte, quaternion, etc)
+ PxI64 mName; //!< Field name (appears exactly as in the source file)
+ int mOffset; //!< Offset from the start of the class (ie from "this", field is located at "this"+Offset)
+ int mSize; //!< sizeof(Type)
+ int mCount; //!< Number of items of type Type (0 for dynamic sizes)
+ int mOffsetSize; //!< Offset of dynamic size param, for dynamic arrays
+ int mFlags; //!< Field parameters
+ int mAlignment; //!< Explicit alignment added for DE1340
+ };
+
+ struct ExtraDataEntry
+ {
+ PxMetaDataEntry entry;
+ int offset;
+ };
+
+ struct ExtraDataEntry2 : ExtraDataEntry
+ {
+ ConvertCallback cb;
+ };
+
+ class MetaData;
+
+ struct MetaClass : public shdfnd::UserAllocated
+ {
+ bool getFieldByType(const char* type, PxMetaDataEntry& entry) const;
+ bool getFieldByName(const char* name, PxMetaDataEntry& entry) const;
+ bool check(const MetaData& owner);
+
+ ConvertCallback mCallback;
+ MetaClass* mMaster;
+ const char* mClassName;
+ int mSize;
+ int mDepth;
+ PsArray<PxMetaDataEntry> mBaseClasses;
+ PsArray<PxMetaDataEntry> mFields;
+ bool mProcessed;
+
+// int mNbEntries;
+// ExtraDataEntry2 mEntries[256];
+
+ private:
+ void checkAndCompleteClass(const MetaData& owner, int& startOffset, int& nbBytes);
+ };
+
+ enum MetaDataType
+ {
+ META_DATA_NONE,
+ META_DATA_SRC,
+ META_DATA_DST
+ };
+
+ class ConvX;
+ class MetaData : public shdfnd::UserAllocated
+ {
+ public:
+ MetaData(Sn::ConvX&);
+ ~MetaData();
+
+ bool load(PxInputStream& inputStream, MetaDataType type);
+
+ inline_ MetaDataType getType() const { return mType; }
+ inline_ int getVersion() const { return mVersion; }
+ inline_ int getBuildNumber() const { return mBuildNumber; }
+ inline_ int getPtrSize() const { return mSizeOfPtr; }
+ inline_ int getPlatformTag() const { return mPlatformTag; }
+ inline_ int getGaussMapLimit() const { return mGaussMapLimit; }
+ inline_ int getNbMetaClasses() const { return int(mMetaClasses.size()); }
+ inline_ MetaClass* getMetaClass(unsigned int i) const { return mMetaClasses[i]; }
+ inline_ bool getFlip() const { return mFlip; }
+
+ MetaClass* getMetaClass(const char* name) const;
+ MetaClass* getMetaClass(PxConcreteType::Enum concreteType) const;
+ MetaClass* addNewClass(const char* name, int size, MetaClass* master=NULL, ConvertCallback callback=NULL);
+ private:
+ MetaData& operator=(const MetaData&);
+ Sn::ConvX& mConvX;
+ MetaDataType mType;
+ int mNbEntries;
+ PxMetaDataEntry* mEntries;
+ char* mStringTable;
+ PsArray<MetaClass*> mMetaClasses;
+ int mVersion;
+ int mBinaryVersion;
+ int mBuildNumber;
+ int mSizeOfPtr;
+ int mPlatformTag;
+ int mGaussMapLimit;
+ bool mFlip;
+
+ PsArray< Ps::Pair<PxConcreteType::Enum, PxU32> > mConcreteTypeTable;
+
+ inline_ const char* offsetToText(const char* text) const
+ {
+ const size_t offset = size_t(text);
+ const PxU32 offset32 = PxU32(offset);
+// if(offset==-1)
+ if(offset32==0xffffffff)
+ return NULL;
+ return mStringTable + offset32;
+ }
+ friend struct MetaClass;
+ };
+
+ PxU64 peek(int size, const char* buffer, int flags=0);
+
+#if PX_VC
+#pragma warning (pop)
+#endif
+} }
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.cpp
new file mode 100644
index 00000000..9eaa601c
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.cpp
@@ -0,0 +1,451 @@
+// 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 "foundation/PxIO.h"
+#include "foundation/PxErrorCallback.h"
+#include "SnConvX.h"
+
+#if PX_VC
+#pragma warning(disable:4389) // signed/unsigned mismatch
+#endif
+
+using namespace physx;
+
+void Sn::ConvX::setNullPtr(bool flag)
+{
+ mNullPtr = flag;
+}
+
+void Sn::ConvX::setNoOutput(bool flag)
+{
+ mNoOutput = flag;
+}
+
+bool Sn::ConvX::initOutput(PxOutputStream& targetStream)
+{
+ mOutStream = &targetStream;
+
+ mOutputSize = 0;
+ mNullPtr = false;
+ mNoOutput = false;
+
+ const MetaData* srcMetaData = getBinaryMetaData(META_DATA_SRC);
+ PX_ASSERT(srcMetaData);
+ const MetaData* dstMetaData = getBinaryMetaData(META_DATA_DST);
+ PX_ASSERT(dstMetaData);
+
+ mSrcPtrSize = srcMetaData->getPtrSize();
+ mDstPtrSize = dstMetaData->getPtrSize();
+
+ PX_ASSERT(!srcMetaData->getFlip());
+ mMustFlip = dstMetaData->getFlip();
+ return true;
+}
+
+void Sn::ConvX::closeOutput()
+{
+ mOutStream = NULL;
+}
+
+int Sn::ConvX::getCurrentOutputSize()
+{
+ return mOutputSize;
+}
+
+void Sn::ConvX::output(short value)
+{
+ if(mNoOutput)
+ return;
+
+ if(mMustFlip)
+ flip(value);
+
+ PX_ASSERT(mOutStream);
+ const size_t size = mOutStream->write(&value, 2);
+ PX_ASSERT(size==2);
+ mOutputSize += int(size);
+}
+
+void Sn::ConvX::output(int value)
+{
+ if(mNoOutput)
+ return;
+
+ if(mMustFlip)
+ flip(value);
+
+ PX_ASSERT(mOutStream);
+ const size_t size = mOutStream->write(&value, 4);
+ PX_ASSERT(size==4);
+ mOutputSize += int(size);
+}
+
+//ntohll is a macro on apple yosemite
+static PxU64 ntohll_internal(const PxU64 value)
+{
+ union
+ {
+ PxU64 ull;
+ PxU8 c[8];
+ } x;
+
+ x.ull = value;
+
+ PxU8 c = 0;
+ c = x.c[0]; x.c[0] = x.c[7]; x.c[7] = c;
+ c = x.c[1]; x.c[1] = x.c[6]; x.c[6] = c;
+ c = x.c[2]; x.c[2] = x.c[5]; x.c[5] = c;
+ c = x.c[3]; x.c[3] = x.c[4]; x.c[4] = c;
+
+ return x.ull;
+}
+
+void Sn::ConvX::output(PxU64 value)
+{
+ if(mNoOutput)
+ return;
+
+ if(mMustFlip)
+// flip(value);
+ value = ntohll_internal(value);
+
+ PX_ASSERT(mOutStream);
+ const size_t size = mOutStream->write(&value, 8);
+ PX_ASSERT(size==8);
+ mOutputSize += int(size);
+}
+
+void Sn::ConvX::output(const char* buffer, int nbBytes)
+{
+ if(mNoOutput)
+ return;
+
+ if(!nbBytes)
+ return;
+
+ PX_ASSERT(mOutStream);
+ const PxU32 size = mOutStream->write(buffer, PxU32(nbBytes));
+ PX_ASSERT(size== PxU32(nbBytes));
+ mOutputSize += int(size);
+}
+
+void Sn::ConvX::convert8(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
+{
+ (void)dstEntry;
+ if(mNoOutput)
+ return;
+
+ PX_ASSERT(entry.mSize==1*entry.mCount);
+ PX_ASSERT(mOutStream);
+ PX_ASSERT(entry.mSize==dstEntry.mSize);
+
+ const PxU32 size = mOutStream->write(src, PxU32(entry.mSize));
+ PX_ASSERT(size== PxU32(entry.mSize));
+ mOutputSize += int(size);
+}
+
+// This is called to convert auto-generated "padding bytes" (or so we think).
+// We use a special converter to check the input bytes and issue warnings when it doesn't look like padding
+void Sn::ConvX::convertPad8(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
+{
+ (void)dstEntry;
+ (void)src;
+ if(mNoOutput)
+ return;
+
+ PX_ASSERT(entry.mSize);
+ PX_ASSERT(entry.mSize==1*entry.mCount);
+ PX_ASSERT(mOutStream);
+ PX_ASSERT(entry.mSize==dstEntry.mSize);
+
+ // PT: we don't output the source data on purpose, to catch missing meta-data
+ // sschirm: changed that to 0xcd, so we can mark the output as "having marked pads"
+ const unsigned char b = 0xcd;
+ for(int i=0;i<entry.mSize;i++)
+ {
+ const size_t size = mOutStream->write(&b, 1);
+ (void)size;
+ }
+ mOutputSize += entry.mSize;
+}
+
+void Sn::ConvX::convert16(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
+{
+ (void)dstEntry;
+ if(mNoOutput)
+ return;
+
+ PX_ASSERT(entry.mSize==int(sizeof(short)*entry.mCount));
+ PX_ASSERT(mOutStream);
+ PX_ASSERT(entry.mSize==dstEntry.mSize);
+
+ const short* data = reinterpret_cast<const short*>(src);
+ for(int i=0;i<entry.mCount;i++)
+ {
+ short value = *data++;
+ if(mMustFlip)
+ flip(value);
+
+ const size_t size = mOutStream->write(&value, sizeof(short));
+ PX_ASSERT(size==sizeof(short));
+ mOutputSize += int(size);
+ }
+}
+
+void Sn::ConvX::convert32(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
+{
+ (void)dstEntry;
+ if(mNoOutput)
+ return;
+
+ PX_ASSERT(entry.mSize==int(sizeof(int)*entry.mCount));
+ PX_ASSERT(mOutStream);
+ PX_ASSERT(entry.mSize==dstEntry.mSize);
+
+ const int* data = reinterpret_cast<const int*>(src);
+ for(int i=0;i<entry.mCount;i++)
+ {
+ int value = *data++;
+ if(mMustFlip)
+ flip(value);
+
+ const size_t size = mOutStream->write(&value, sizeof(int));
+ PX_ASSERT(size==sizeof(int));
+ mOutputSize += int(size);
+ }
+}
+
+void Sn::ConvX::convert64(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
+{
+ (void)dstEntry;
+ if(mNoOutput)
+ return;
+
+ PX_ASSERT(entry.mSize==int(sizeof(PxU64)*entry.mCount));
+ PX_ASSERT(mOutStream);
+ PX_ASSERT(entry.mSize==dstEntry.mSize);
+
+ const PxU64* data = reinterpret_cast<const PxU64*>(src);
+ for(int i=0;i<entry.mCount;i++)
+ {
+ PxU64 value = *data++;
+ if(mMustFlip)
+ value = ntohll_internal(value);
+
+ const size_t size = mOutStream->write(&value, sizeof(PxU64));
+ PX_ASSERT(size==sizeof(PxU64));
+ mOutputSize += int(size);
+ }
+}
+
+void Sn::ConvX::convertFloat(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
+{
+ (void)dstEntry;
+ if(mNoOutput)
+ return;
+
+ PX_ASSERT(entry.mSize==int(sizeof(float)*entry.mCount));
+ PX_ASSERT(mOutStream);
+ PX_ASSERT(entry.mSize==dstEntry.mSize);
+
+ const float* data = reinterpret_cast<const float*>(src);
+ for(int i=0;i<entry.mCount;i++)
+ {
+ float value = *data++;
+ if(mMustFlip)
+ flip(value);
+
+ const size_t size = mOutStream->write(&value, sizeof(float));
+ PX_ASSERT(size==sizeof(float));
+ mOutputSize += int(size);
+ }
+}
+
+void Sn::ConvX::convertPtr(const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry)
+{
+ (void)dstEntry;
+ if(mNoOutput)
+ return;
+
+ PX_ASSERT(entry.mSize==mSrcPtrSize*entry.mCount);
+ PX_ASSERT(mOutStream);
+
+ char buffer[16];
+ for(int i=0;i<entry.mCount;i++)
+ {
+ PxU64 testValue=0;
+ // Src pointer can be 4 or 8 bytes so we can't use "void*" here
+ if(mSrcPtrSize==4)
+ {
+ PX_ASSERT(sizeof(PxU32)==4);
+ const PxU32* data = reinterpret_cast<const PxU32*>(src);
+ PxU32 value = *data++;
+ src = reinterpret_cast<const char*>(data);
+
+ if(mActiveRemap)
+ {
+ PxU32 ref;
+ if(mActiveRemap->getObjectRef(value, ref))
+ {
+ value = ref;
+ }
+ else if(value)
+ {
+ // value = 0;
+ //We use the pointer of mName for its length
+ // PT: on serialization mName is transformed to an index by the name manager, so we should not modify its value.
+ if(!entry.mName || strcmp(entry.mName, "mName"))
+ value=0x12345678;
+ }
+ }
+ else
+ {
+ //we should only get here during convertReferenceTables to build up the pointer map
+ PxU32 ref;
+ if (mRemap.getObjectRef(value, ref))
+ {
+ value = ref;
+ }
+ else if(value)
+ {
+ const PxU32 remappedRef = 0x80000000 | (mPointerRemapCounter++ +1);
+ mRemap.setObjectRef(value, remappedRef);
+ value = remappedRef;
+ }
+ }
+
+ if(mMustFlip)
+ flip(value);
+
+ if(mNullPtr)
+ value = 0;
+
+ *reinterpret_cast<PxU32*>(buffer) = value;
+ }
+ else
+ {
+ PX_ASSERT(mSrcPtrSize==8);
+ PX_ASSERT(sizeof(PxU64)==8);
+ const PxU64* data = reinterpret_cast<const PxU64*>(src);
+ PxU64 value = *data++;
+ src = reinterpret_cast<const char*>(data);
+
+ if(mActiveRemap)
+ {
+ PxU32 ref;
+ if(mActiveRemap->getObjectRef(value, ref))
+ {
+ value = ref;
+ }
+ else if(value)
+ {
+ // value = 0;
+ //We use the pointer of mName for its length
+ // PT: on serialization mName is transformed to an index by the name manager, so we should not modify its value.
+ if(!entry.mName || strcmp(entry.mName, "mName"))
+ value=0x12345678;
+ }
+ }
+ else
+ {
+ //we should only get here during convertReferenceTables to build up the pointer map
+ PxU32 ref;
+ if (mRemap.getObjectRef(value, ref))
+ {
+ value = ref;
+ }
+ else if(value)
+ {
+ const PxU32 remappedRef = 0x80000000 | (mPointerRemapCounter++ +1);
+ mRemap.setObjectRef(value, remappedRef);
+ value = remappedRef;
+ }
+ }
+
+// PX_ASSERT(!mMustFlip);
+// if(mMustFlip)
+// flip(value);
+
+ if(mNullPtr)
+ value = 0;
+
+ testValue = value;
+
+ *reinterpret_cast<PxU64*>(buffer) = value;
+ }
+
+ if(mSrcPtrSize==mDstPtrSize)
+ {
+ const size_t size = mOutStream->write(buffer, PxU32(mSrcPtrSize));
+ PX_ASSERT(size==PxU32(mSrcPtrSize));
+ mOutputSize += int(size);
+ }
+ else
+ {
+ if(mDstPtrSize>mSrcPtrSize)
+ {
+ // 32bit to 64bit
+ PX_ASSERT(mDstPtrSize==8);
+ PX_ASSERT(mSrcPtrSize==4);
+
+ // We need to output the lower 32bits first for PC. Might be different on a 64bit console....
+
+ // Output src ptr for the lower 32bits
+ const size_t size = mOutStream->write(buffer, PxU32(mSrcPtrSize));
+ PX_ASSERT(size==PxU32(mSrcPtrSize));
+ mOutputSize += int(size);
+
+ // Output zeros for the higher 32bits
+ const int zero = 0;
+ const size_t size0 = mOutStream->write(&zero, 4);
+ PX_ASSERT(size0==4);
+ mOutputSize += int(size0);
+ }
+ else
+ {
+ // 64bit to 32bit
+ PX_ASSERT(mSrcPtrSize==8);
+ PX_ASSERT(mDstPtrSize==4);
+
+ // Not sure how we can safely convert 64bit ptrs to 32bit... just drop the high 32 bits?!?
+
+ PxU32 ptr32 = *reinterpret_cast<PxU32*>(buffer);
+ (void)ptr32;
+ PxU32 ptr32b = PxU32(testValue);
+ (void)ptr32b;
+
+ if(mMustFlip)
+ flip(ptr32b);
+
+ // Output src ptr for the lower 32bits
+ const size_t size = mOutStream->write(&ptr32b, 4);
+ PX_ASSERT(size==4);
+ mOutputSize += int(size);
+ }
+ }
+ }
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.h
new file mode 100644
index 00000000..6eaf7b99
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Output.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.
+
+#ifndef PX_CONVX_OUTPUT_H
+#define PX_CONVX_OUTPUT_H
+
+#include "foundation/PxSimpleTypes.h"
+
+namespace physx { namespace Sn {
+
+ struct PxMetaDataEntry;
+ class ConvX;
+
+ typedef void (Sn::ConvX::*ConvertCallback) (const char* src, const PxMetaDataEntry& entry, const PxMetaDataEntry& dstEntry);
+
+ inline_ void flip(PxI16& v)
+ {
+ PxI8* b = reinterpret_cast<PxI8*>(&v);
+ PxI8 temp = b[0];
+ b[0] = b[1];
+ b[1] = temp;
+ }
+
+ inline_ void flip(PxU16& v)
+ {
+ flip(reinterpret_cast<PxI16&>(v));
+ }
+
+ inline_ void flip32(PxI8* b)
+ {
+ PxI8 temp = b[0];
+ b[0] = b[3];
+ b[3] = temp;
+ temp = b[1];
+ b[1] = b[2];
+ b[2] = temp;
+ }
+
+ inline_ void flip(PxI32& v)
+ {
+ PxI8* b = reinterpret_cast<PxI8*>(&v);
+ flip32(b);
+ }
+
+ inline_ void flip(PxU32& v)
+ {
+ PxI8* b = reinterpret_cast<PxI8*>(&v);
+ flip32(b);
+ }
+
+ inline_ void flip(PxI64& v)
+ {
+ PxI8* b = reinterpret_cast<PxI8*>(&v);
+
+ PxI8 temp = b[0];
+ b[0] = b[7];
+ b[7] = temp;
+ temp = b[1];
+ b[1] = b[6];
+ b[6] = temp;
+ temp = b[2];
+ b[2] = b[5];
+ b[5] = temp;
+ temp = b[3];
+ b[3] = b[4];
+ b[4] = temp;
+ }
+
+ inline_ void flip(PxF32& v)
+ {
+ PxI8* b = reinterpret_cast<PxI8*>(&v);
+ flip32(b);
+ }
+
+ inline_ void flip(void*& v)
+ {
+ PxI8* b = reinterpret_cast<PxI8*>(&v);
+ flip32(b);
+ }
+
+ inline_ void flip(const PxI8*& v)
+ {
+ PxI8* b = const_cast<PxI8*>(v);
+ flip32(b);
+ }
+} }
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.cpp
new file mode 100644
index 00000000..ddff8df1
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.cpp
@@ -0,0 +1,90 @@
+// 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 "SnConvX.h"
+#include <assert.h>
+
+using namespace physx;
+
+void Sn::ConvX::resetUnions()
+{
+ mUnions.clear();
+}
+
+bool Sn::ConvX::registerUnion(const char* name)
+{
+ displayMessage(PxErrorCode::eDEBUG_INFO, "Registering union: %s\n", name);
+
+ Sn::Union u;
+ u.mName = name;
+
+ mUnions.pushBack(u);
+ return true;
+}
+
+bool Sn::ConvX::registerUnionType(const char* unionName, const char* typeName, int typeValue)
+{
+ const PxU32 nb = mUnions.size();
+ for(PxU32 i=0;i<nb;i++)
+ {
+ if(strcmp(mUnions[i].mName, unionName)==0)
+ {
+ UnionType t;
+ t.mTypeName = typeName;
+ t.mTypeValue = typeValue;
+ mUnions[i].mTypes.pushBack(t);
+ displayMessage(PxErrorCode::eDEBUG_INFO, "Registering union type: %s | %s | %d\n", unionName, typeName, typeValue);
+ return true;
+ }
+ }
+
+ displayMessage(PxErrorCode::eINTERNAL_ERROR, "PxBinaryConverter: union not found: %s, please check the source metadata.\n", unionName);
+ return false;
+}
+
+const char* Sn::ConvX::getTypeName(const char* unionName, int typeValue)
+{
+ const PxU32 nb = mUnions.size();
+ for(PxU32 i=0;i<nb;i++)
+ {
+ if(strcmp(mUnions[i].mName, unionName)==0)
+ {
+ const PxU32 nbTypes = mUnions[i].mTypes.size();
+ for(PxU32 j=0;j<nbTypes;j++)
+ {
+ const UnionType& t = mUnions[i].mTypes[j];
+ if(t.mTypeValue==typeValue)
+ return t.mTypeName;
+ }
+ break;
+ }
+ }
+ displayMessage(PxErrorCode::eINTERNAL_ERROR,
+ "PxBinaryConverter: union type not found: %s, type %d, please check the source metadata.\n", unionName, typeValue);
+ assert(0);
+ return NULL;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.h
new file mode 100644
index 00000000..6c94a12c
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnConvX_Union.h
@@ -0,0 +1,45 @@
+// 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.
+
+#ifndef PX_UNION_H
+#define PX_UNION_H
+
+namespace physx { namespace Sn {
+ struct UnionType
+ {
+ const char* mTypeName;
+ int mTypeValue;
+ };
+
+ struct Union
+ {
+ const char* mName;
+ PsArray<UnionType> mTypes;
+ };
+} }
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.cpp
new file mode 100644
index 00000000..ef46d552
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.cpp
@@ -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.
+
+#include "PxBase.h"
+#include "SnSerializationContext.h"
+#include "PsFoundation.h"
+
+using namespace physx;
+using namespace Sn;
+
+PxBase* DeserializationContext::resolveReference(PxU32 kind, size_t reference) const
+{
+ const InternalRefMap::Entry* entry0 = mInternalReferencesMap.find(InternalRefKey(reference, kind));
+ PX_ASSERT(entry0);
+ SerialObjectIndex objIndex = entry0->second;
+ bool isExternal;
+ PxU32 index = objIndex.getIndex(isExternal);
+ PxBase* base = NULL;
+ if (isExternal)
+ {
+ const ImportReference& entry = mImportReferences[index];
+ base = mExternalRefs->find(entry.id);
+ }
+ else
+ {
+ const ManifestEntry& entry = mManifestTable[index];
+ base = reinterpret_cast<PxBase*>(mObjectDataAddress + entry.offset);
+ }
+ PX_ASSERT(base);
+ return base;
+}
+
+void SerializationContext::registerReference(PxBase& serializable, PxU32 kind, size_t reference)
+{
+#if PX_CHECKED
+ if ((kind & PX_SERIAL_REF_KIND_PTR_TYPE_BIT) == 0 && reference > 0xffffffff)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__, "PxSerializationContext::registerReference: only 32 bit indices supported.");
+ return;
+ }
+#endif
+
+ bool isExternal = mExternalRefs && mExternalRefs->contains(serializable);
+ PxU32 index;
+ if (isExternal)
+ {
+ PxSerialObjectId id = mExternalRefs->getId(serializable);
+ PX_ASSERT(id != PX_SERIAL_OBJECT_ID_INVALID);
+ if (const Ps::HashMap<PxSerialObjectId, PxU32>::Entry* entry = mImportReferencesMap.find(id))
+ {
+ index = entry->second;
+ }
+ else
+ {
+ index = mImportReferences.size();
+ mImportReferencesMap.insert(id, index);
+ mImportReferences.pushBack(ImportReference(id, serializable.getConcreteType()));
+ }
+ }
+ else
+ {
+ PX_ASSERT(mCollection.contains(serializable));
+ index = mObjToCollectionIndexMap[&serializable];
+ }
+
+ InternalRefMap& targetMap = (kind & PX_SERIAL_REF_KIND_PTR_TYPE_BIT) ? mInternalReferencesPtrMap : mInternalReferencesIdxMap;
+ targetMap[InternalRefKey(reference, kind)] = SerialObjectIndex(index, isExternal);
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.h
new file mode 100644
index 00000000..6bfa05e1
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Binary/SnSerializationContext.h
@@ -0,0 +1,303 @@
+// 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_SN_SERIALIZATION_CONTEXT
+#define PX_PHYSICS_SN_SERIALIZATION_CONTEXT
+
+#include "foundation/PxAssert.h"
+#include "foundation/PxMemory.h"
+#include "CmPhysXCommon.h"
+#include "PsHash.h"
+#include "PsUserAllocated.h"
+#include "PxSerialFramework.h"
+#include "CmCollection.h"
+#include "CmUtils.h"
+#include "PxDefaultStreams.h"
+#include "PsFoundation.h"
+#include "SnConvX_Align.h"
+
+namespace physx
+{
+ namespace Sn
+ {
+
+ struct ManifestEntry
+ {
+ //= 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_FORCE_INLINE ManifestEntry(PxU32 _offset, PxType _type)
+ {
+ Cm::markSerializedMem(this, sizeof(ManifestEntry));
+ offset = _offset;
+ type = _type;
+ }
+ PX_FORCE_INLINE ManifestEntry() { Cm::markSerializedMem(this, sizeof(ManifestEntry)); }
+ PX_FORCE_INLINE void operator =(const ManifestEntry& m)
+ {
+ PxMemCopy(this, &m, sizeof(ManifestEntry));
+ }
+
+ PxU32 offset;
+ PxType type;
+ };
+
+ struct ImportReference
+ {
+ //= 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_FORCE_INLINE ImportReference(PxSerialObjectId _id, PxType _type)
+ {
+ Cm::markSerializedMem(this, sizeof(ImportReference));
+ id = _id;
+ type = _type;
+ }
+ PX_FORCE_INLINE ImportReference() { Cm::markSerializedMem(this, sizeof(ImportReference)); }
+ PX_FORCE_INLINE void operator =(const ImportReference& m)
+ {
+ PxMemCopy(this, &m, sizeof(ImportReference));
+ }
+ PxSerialObjectId id;
+ PxType type;
+ };
+
+#define SERIAL_OBJECT_INDEX_TYPE_BIT (1u<<31)
+ struct SerialObjectIndex
+ {
+ //= 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_FORCE_INLINE SerialObjectIndex(PxU32 index, bool external) { setIndex(index, external); }
+ PX_FORCE_INLINE SerialObjectIndex(const SerialObjectIndex& objIndex) : mObjIndex(objIndex.mObjIndex) {}
+ PX_FORCE_INLINE SerialObjectIndex() : mObjIndex(PX_INVALID_U32) {}
+
+ PX_FORCE_INLINE void setIndex(PxU32 index, bool external)
+ {
+ PX_ASSERT((index & SERIAL_OBJECT_INDEX_TYPE_BIT) == 0);
+ mObjIndex = index | (external ? SERIAL_OBJECT_INDEX_TYPE_BIT : 0);
+ }
+
+ PX_FORCE_INLINE PxU32 getIndex(bool& isExternal)
+ {
+ PX_ASSERT(mObjIndex != PX_INVALID_U32);
+ isExternal = (mObjIndex & SERIAL_OBJECT_INDEX_TYPE_BIT) > 0;
+ return mObjIndex & ~SERIAL_OBJECT_INDEX_TYPE_BIT;
+ }
+
+ private:
+ PxU32 mObjIndex;
+ };
+
+ struct ExportReference
+ {
+ //= 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_FORCE_INLINE ExportReference(PxSerialObjectId _id, SerialObjectIndex _objIndex)
+ {
+ Cm::markSerializedMem(this, sizeof(ExportReference));
+ id = _id;
+ objIndex = _objIndex;
+ }
+ PX_FORCE_INLINE ExportReference() { Cm::markSerializedMem(this, sizeof(ExportReference)); }
+ PX_FORCE_INLINE void operator =(const ExportReference& m)
+ {
+ PxMemCopy(this, &m, sizeof(ExportReference));
+ }
+ PxSerialObjectId id;
+ SerialObjectIndex objIndex;
+ };
+
+ template<class ReferenceType>
+ struct InternalReference
+ {
+ //= 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_FORCE_INLINE InternalReference(ReferenceType _reference, PxU32 _kind, SerialObjectIndex _objIndex)
+ {
+ Cm::markSerializedMem(this, sizeof(InternalReference));
+ reference = _reference;
+ kind = _kind;
+ objIndex = _objIndex;
+ }
+ PX_FORCE_INLINE InternalReference() { Cm::markSerializedMem(this, sizeof(InternalReference)); }
+ PX_FORCE_INLINE void operator =(const InternalReference& m)
+ {
+ PxMemCopy(this, &m, sizeof(InternalReference));
+ }
+ ReferenceType reference;
+ PxU32 kind;
+ SerialObjectIndex objIndex;
+ };
+
+ typedef InternalReference<size_t> InternalReferencePtr;
+ typedef InternalReference<PxU32> InternalReferenceIdx;
+
+ typedef shdfnd::Pair<size_t, PxU32> InternalRefKey;
+ typedef Cm::CollectionHashMap<InternalRefKey, SerialObjectIndex> InternalRefMap;
+
+ class DeserializationContext : public PxDeserializationContext, public Ps::UserAllocated
+ {
+ PX_NOCOPY(DeserializationContext)
+
+ public:
+ DeserializationContext(const ManifestEntry* manifestTable,
+ const ImportReference* importReferences,
+ PxU8* objectDataAddress,
+ const InternalRefMap& internalReferencesMap,
+ const Cm::Collection* externalRefs,
+ PxU8* extraData,
+ PxU32 physxVersion)
+ : mManifestTable(manifestTable)
+ , mImportReferences(importReferences)
+ , mObjectDataAddress(objectDataAddress)
+ , mInternalReferencesMap(internalReferencesMap)
+ , mExternalRefs(externalRefs)
+ , mPhysXVersion(physxVersion)
+ {
+ mExtraDataAddress = extraData;
+ }
+
+ virtual PxBase* resolveReference(PxU32 kind, size_t reference) const;
+
+ PxU32 getPhysXVersion() const { return mPhysXVersion; }
+ private:
+ //various pointers to deserialized data
+ const ManifestEntry* mManifestTable;
+ const ImportReference* mImportReferences;
+ PxU8* mObjectDataAddress;
+
+ //internal references map for resolving references.
+ const InternalRefMap& mInternalReferencesMap;
+
+ //external collection for resolving import references.
+ const Cm::Collection* mExternalRefs;
+ const PxU32 mPhysXVersion;
+ };
+
+ class SerializationContext : public PxSerializationContext, public Ps::UserAllocated
+ {
+ PX_NOCOPY(SerializationContext)
+ public:
+ SerializationContext(const Cm::Collection& collection, const Cm::Collection* externalRefs)
+ : mCollection(collection)
+ , mExternalRefs(externalRefs)
+ {
+ // fill object to collection index map (same ordering as manifest)
+ for (PxU32 i=0;i<mCollection.internalGetNbObjects();i++)
+ {
+ mObjToCollectionIndexMap[mCollection.internalGetObject(i)] = i;
+ }
+ }
+
+ virtual void writeData(const void* buffer, PxU32 size) { mMemStream.write(buffer, size); }
+ virtual PxU32 getTotalStoredSize() { return mMemStream.getSize(); }
+ virtual void alignData(PxU32 alignment = PX_SERIAL_ALIGN)
+ {
+ if(!alignment)
+ return;
+
+ PxI32 bytesToPad = PxI32(getPadding(mMemStream.getSize(), alignment));
+ static const PxI32 BUFSIZE = 64;
+ char buf[BUFSIZE];
+ PxMemSet(buf, 0, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE));
+ while(bytesToPad > 0)
+ {
+ mMemStream.write(buf, bytesToPad < BUFSIZE ? PxU32(bytesToPad) : PxU32(BUFSIZE));
+ bytesToPad -= BUFSIZE;
+ }
+ PX_ASSERT(!getPadding(getTotalStoredSize(), alignment));
+ }
+
+ virtual void writeName(const char*)
+ {
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_OPERATION, __FILE__, __LINE__,
+ "Cannot export names during exportData.");
+ }
+
+ const PxCollection& getCollection() const { return mCollection; }
+
+ virtual void registerReference(PxBase& serializable, PxU32 kind, size_t reference);
+
+ const Ps::Array<ImportReference>& getImportReferences() { return mImportReferences; }
+ InternalRefMap& getInternalReferencesPtrMap() { return mInternalReferencesPtrMap; }
+ InternalRefMap& getInternalReferencesIdxMap() { return mInternalReferencesIdxMap; }
+
+ PxU32 getSize() const { return mMemStream.getSize(); }
+ PxU8* getData() const { return mMemStream.getData(); }
+
+
+
+ private:
+ //import reference map for unique registration of import references and corresponding buffer.
+ Ps::HashMap<PxSerialObjectId, PxU32> mImportReferencesMap;
+ Ps::Array<ImportReference> mImportReferences;
+
+ //maps for unique registration of internal references
+ InternalRefMap mInternalReferencesPtrMap;
+ InternalRefMap mInternalReferencesIdxMap;
+
+ //map for quick lookup of manifest index.
+ Ps::HashMap<const PxBase*, PxU32> mObjToCollectionIndexMap;
+
+ //collection and externalRefs collection for assigning references.
+ const Cm::Collection& mCollection;
+ const Cm::Collection* mExternalRefs;
+
+ PxDefaultMemoryOutputStream mMemStream;
+
+ };
+
+ } // namespace Sn
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/File/SnFile.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/File/SnFile.h
new file mode 100644
index 00000000..0c5a817e
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/File/SnFile.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 SN_FILE_H
+#define SN_FILE_H
+
+// fopen_s - returns 0 on success, non-zero on failure
+
+#if PX_MICROSOFT_FAMILY
+
+#include <stdio.h>
+
+namespace physx
+{
+namespace sn
+{
+PX_INLINE PxI32 fopen_s(FILE** file, const char* name, const char* mode)
+{
+ static const PxU32 MAX_LEN = 300;
+ char buf[MAX_LEN+1];
+
+ PxU32 i;
+ for(i = 0; i<MAX_LEN && name[i]; i++)
+ buf[i] = name[i] == '/' ? '\\' : name[i];
+ buf[i] = 0;
+
+ return i == MAX_LEN ? -1 : ::fopen_s(file, buf, mode);
+};
+
+} // namespace sn
+} // namespace physx
+
+#elif PX_UNIX_FAMILY || PX_PS4
+
+#include <stdio.h>
+
+namespace physx
+{
+namespace sn
+{
+PX_INLINE PxI32 fopen_s(FILE** file, const char* name, const char* mode)
+{
+ FILE* fp = ::fopen(name, mode);
+ if(fp)
+ {
+ *file = fp;
+ return PxI32(0);
+ }
+ return -1;
+}
+} // namespace sn
+} // namespace physx
+#else
+#error "Platform not supported!"
+#endif
+
+#endif //SN_FILE_H
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.cpp
new file mode 100644
index 00000000..1a147058
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.cpp
@@ -0,0 +1,151 @@
+// 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 "SnSerialUtils.h"
+#include "PsString.h"
+#include "PxSerialization.h"
+#include "PxPhysicsVersion.h"
+#include "PsBasicTemplates.h"
+
+using namespace physx;
+
+namespace
+{
+
+#define SN_NUM_BINARY_PLATFORMS 11
+const PxU32 sBinaryPlatformTags[SN_NUM_BINARY_PLATFORMS] =
+{
+ PX_MAKE_FOURCC('W','_','3','2'),
+ PX_MAKE_FOURCC('W','_','6','4'),
+ PX_MAKE_FOURCC('L','_','3','2'),
+ PX_MAKE_FOURCC('L','_','6','4'),
+ PX_MAKE_FOURCC('M','_','3','2'),
+ PX_MAKE_FOURCC('M','_','6','4'),
+ PX_MAKE_FOURCC('M','O','C','A'),
+ PX_MAKE_FOURCC('A','N','D','R'),
+ PX_MAKE_FOURCC('A','I','O','S'),
+ PX_MAKE_FOURCC('A','A','6','4'),
+ PX_MAKE_FOURCC('X','O','N','E')
+};
+
+const char* sBinaryPlatformNames[SN_NUM_BINARY_PLATFORMS] =
+{
+ "win32",
+ "win64",
+ "linux32",
+ "linux64",
+ "macOSX32",
+ "macOSX64",
+ "ps4",
+ "android",
+ "ios",
+ "ios64",
+ "xboxone"
+};
+
+#define SN_NUM_BINARY_COMPATIBLE_VERSIONS 1
+
+//
+// Important: if you adjust the following structure, please adjust the comment for PX_BINARY_SERIAL_VERSION as well
+//
+const Ps::Pair<PxU32, PxU32> sBinaryCompatibleVersions[SN_NUM_BINARY_COMPATIBLE_VERSIONS] =
+{
+ Ps::Pair<PxU32, PxU32>(PX_PHYSICS_VERSION, PX_BINARY_SERIAL_VERSION)
+};
+
+}
+
+namespace physx { namespace Sn {
+
+PxU32 getBinaryPlatformTag()
+{
+#if PX_WINDOWS && PX_X86
+ return sBinaryPlatformTags[0];
+#elif PX_WINDOWS && PX_X64
+ return sBinaryPlatformTags[1];
+#elif PX_LINUX && (PX_X86 || PX_ARM)
+ return sBinaryPlatformTags[2];
+#elif PX_LINUX && (PX_X64 || PX_A64)
+ return sBinaryPlatformTags[3];
+#elif PX_OSX && PX_X86
+ return sBinaryPlatformTags[4];
+#elif PX_OSX && PX_X64
+ return sBinaryPlatformTags[5];
+#elif PX_PS4
+ return sBinaryPlatformTags[6];
+#elif PX_ANDROID
+ return sBinaryPlatformTags[7];
+#elif PX_IOS && PX_ARM
+ return sBinaryPlatformTags[8];
+#elif PX_IOS && PX_A64
+ return sBinaryPlatformTags[9];
+#elif PX_XBOXONE
+ return sBinaryPlatformTags[10];
+#else
+ #error Unknown binary platform
+#endif
+}
+
+bool isBinaryPlatformTagValid(physx::PxU32 platformTag)
+{
+ PxU32 platformIndex = 0;
+ while (platformIndex < SN_NUM_BINARY_PLATFORMS && platformTag != sBinaryPlatformTags[platformIndex]) platformIndex++;
+ return platformIndex < SN_NUM_BINARY_PLATFORMS;
+}
+
+const char* getBinaryPlatformName(physx::PxU32 platformTag)
+{
+ PxU32 platformIndex = 0;
+ while (platformIndex < SN_NUM_BINARY_PLATFORMS && platformTag != sBinaryPlatformTags[platformIndex]) platformIndex++;
+ return (platformIndex == SN_NUM_BINARY_PLATFORMS) ? "unknown" : sBinaryPlatformNames[platformIndex];
+}
+
+bool checkCompatibility(const PxU32 version, const PxU32 binaryVersion)
+{
+ for(PxU32 i =0; i<SN_NUM_BINARY_COMPATIBLE_VERSIONS; i++)
+ {
+ if(version == sBinaryCompatibleVersions[i].first && binaryVersion == sBinaryCompatibleVersions[i].second)
+ return true;
+ }
+ return false;
+}
+
+void getCompatibilityVersionsStr(char* buffer, PxU32 lenght)
+{
+ size_t len = 0;
+ for(PxU32 i =0; i<SN_NUM_BINARY_COMPATIBLE_VERSIONS; i++)
+ {
+ physx::shdfnd::snprintf(buffer + len, lenght - len, "%x-%d\n", sBinaryCompatibleVersions[i].first, sBinaryCompatibleVersions[i].second);
+ len = strlen(buffer);
+ }
+}
+
+} // Sn
+} // physx
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.h
new file mode 100644
index 00000000..31aa3944
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialUtils.h
@@ -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.
+
+
+#ifndef PX_PHYSICS_SN_SERIAL_UTILS
+#define PX_PHYSICS_SN_SERIAL_UTILS
+
+#include "CmPhysXCommon.h"
+
+namespace physx
+{
+
+namespace Sn
+{
+ PxU32 getBinaryPlatformTag();
+ bool isBinaryPlatformTagValid(PxU32 platformTag);
+ const char* getBinaryPlatformName(PxU32 platformTag);
+ bool checkCompatibility(const PxU32 version, const PxU32 binaryVersion);
+ void getCompatibilityVersionsStr(char* buffer, PxU32 lenght);
+}
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialization.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialization.cpp
new file mode 100644
index 00000000..15edeb46
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerialization.cpp
@@ -0,0 +1,433 @@
+// 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 "PxPhysicsAPI.h"
+#include "PxConstraintExt.h"
+#include "PxPhysicsVersion.h"
+#include "PsFoundation.h"
+#include "PxMetaData.h"
+#include "SnConvX.h"
+#include "SnSerializationRegistry.h"
+#include "SnSerialUtils.h"
+#include "ExtSerialization.h"
+#include "PxSerializer.h"
+#include "CmCollection.h"
+
+using namespace physx;
+using namespace Sn;
+
+namespace
+{
+ struct RequiresCallback : public PxProcessPxBaseCallback
+ {
+ RequiresCallback(physx::PxCollection& c) : collection(c) {}
+ void process(PxBase& base)
+ {
+ if(!collection.contains(base))
+ collection.add(base);
+ }
+
+ PxCollection& collection;
+ PX_NOCOPY(RequiresCallback)
+ };
+
+ struct CompleteCallback : public PxProcessPxBaseCallback
+ {
+ CompleteCallback(physx::PxCollection& r, physx::PxCollection& c, const physx::PxCollection* e) :
+ requires(r), complete(c), external(e) {}
+ void process(PxBase& base)
+ {
+ if(complete.contains(base) || (external && external->contains(base)))
+ return;
+ if(!requires.contains(base))
+ requires.add(base);
+ }
+
+ PxCollection& requires;
+ PxCollection& complete;
+ const PxCollection* external;
+ PX_NOCOPY(CompleteCallback)
+ };
+
+ void getRequiresCollection(PxCollection& requires, PxCollection& collection, PxCollection& complete, const PxCollection* external, PxSerializationRegistry& sr, bool followJoints)
+ {
+ CompleteCallback callback(requires, complete, external);
+ for (PxU32 i = 0; i < collection.getNbObjects(); ++i)
+ {
+ PxBase& s = collection.getObject(i);
+ const PxSerializer* serializer = sr.getSerializer(s.getConcreteType());
+ PX_ASSERT(serializer);
+ serializer->requires(s, callback);
+
+ if(followJoints)
+ {
+ PxRigidActor* actor = s.is<PxRigidActor>();
+ if(actor)
+ {
+ Ps::Array<PxConstraint*> objects(actor->getNbConstraints());
+ actor->getConstraints(objects.begin(), objects.size());
+
+ for(PxU32 j=0;j<objects.size();j++)
+ {
+ PxU32 typeId;
+ PxJoint* joint = reinterpret_cast<PxJoint*>(objects[j]->getExternalReference(typeId));
+ if(typeId == PxConstraintExtIDs::eJOINT)
+ {
+ const PxSerializer* sj = sr.getSerializer(joint->getConcreteType());
+ PX_ASSERT(sj);
+ sj->requires(*joint, callback);
+ if(!requires.contains(*joint))
+ requires.add(*joint);
+ }
+ }
+ }
+ }
+ }
+ }
+}
+
+bool PxSerialization::isSerializable(PxCollection& collection, PxSerializationRegistry& sr, const PxCollection* externalReferences)
+{
+ PxCollection* subordinateCollection = PxCreateCollection();
+ PX_ASSERT(subordinateCollection);
+
+ for(PxU32 i = 0; i < collection.getNbObjects(); ++i)
+ {
+ PxBase& s = collection.getObject(i);
+ const PxSerializer* serializer = sr.getSerializer(s.getConcreteType());
+ PX_ASSERT(serializer);
+ if(serializer->isSubordinate())
+ subordinateCollection->add(s);
+
+ if(externalReferences)
+ {
+ PxSerialObjectId id = collection.getId(s);
+ if(id != PX_SERIAL_OBJECT_ID_INVALID)
+ {
+ PxBase* object = externalReferences->find(id);
+ if(object && (object != &s))
+ {
+ subordinateCollection->release();
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxSerialization::isSerializable: Reference id %" PX_PRIu64 " used both in current collection and in externalReferences. "
+ "Please use unique identifiers.", id);
+ return false;
+ }
+ }
+ }
+ }
+
+ PxCollection* requiresCollection = PxCreateCollection();
+ PX_ASSERT(requiresCollection);
+
+ RequiresCallback requiresCallback0(*requiresCollection);
+
+ for (PxU32 i = 0; i < collection.getNbObjects(); ++i)
+ {
+ PxBase& s = collection.getObject(i);
+ const PxSerializer* serializer = sr.getSerializer(s.getConcreteType());
+ PX_ASSERT(serializer);
+ serializer->requires(s, requiresCallback0);
+
+ Cm::Collection* cmRequiresCollection = static_cast<Cm::Collection*>(requiresCollection);
+
+ for(PxU32 j = 0; j < cmRequiresCollection->getNbObjects(); ++j)
+ {
+ PxBase& s0 = cmRequiresCollection->getObject(j);
+
+ if(subordinateCollection->contains(s0))
+ {
+ subordinateCollection->remove(s0);
+ continue;
+ }
+
+ bool requiredIsInCollection = collection.contains(s0);
+ if(!requiredIsInCollection)
+ {
+ if(externalReferences)
+ {
+ if(!externalReferences->contains(s0))
+ {
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxSerialization::isSerializable: Object of type %s references a missing object of type %s. "
+ "The missing object needs to be added to either the current collection or the externalReferences collection.",
+ s.getConcreteTypeName(), s0.getConcreteTypeName());
+ }
+ else if(externalReferences->getId(s0) == PX_SERIAL_OBJECT_ID_INVALID)
+ {
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxSerialization::isSerializable: Object of type %s in externalReferences collection requires an id.",
+ s0.getConcreteTypeName());
+ }
+ else
+ continue;
+ }
+ else
+ {
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxSerialization::isSerializable: Object of type %s references a missing serial object of type %s. "
+ "Please completed the collection or specify an externalReferences collection containing the object.",
+ s.getConcreteTypeName(), s0.getConcreteTypeName());
+ }
+ subordinateCollection->release();
+ requiresCollection->release();
+ return false;
+ }
+ }
+ cmRequiresCollection->mObjects.clear();
+ }
+ requiresCollection->release();
+
+ PxU32 numOrphans = subordinateCollection->getNbObjects();
+
+ for(PxU32 j = 0; j < numOrphans; ++j)
+ {
+ PxBase& subordinate = subordinateCollection->getObject(j);
+
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxSerialization::isSerializable: An object of type %s is subordinate but not required "
+ "by other objects in the collection (orphan). Please remove the object from the collection or add its owner.",
+ subordinate.getConcreteTypeName());
+ }
+
+ subordinateCollection->release();
+
+ if(numOrphans>0)
+ return false;
+
+ if(externalReferences)
+ {
+ PxCollection* oppositeRequiresCollection = PxCreateCollection();
+ PX_ASSERT(oppositeRequiresCollection);
+
+ RequiresCallback requiresCallback(*oppositeRequiresCollection);
+
+ for (PxU32 i = 0; i < externalReferences->getNbObjects(); ++i)
+ {
+ PxBase& s = externalReferences->getObject(i);
+ const PxSerializer* serializer = sr.getSerializer(s.getConcreteType());
+ PX_ASSERT(serializer);
+ serializer->requires(s, requiresCallback);
+
+ Cm::Collection* cmCollection = static_cast<Cm::Collection*>(oppositeRequiresCollection);
+
+ for(PxU32 j = 0; j < cmCollection->getNbObjects(); ++j)
+ {
+ PxBase& s0 = cmCollection->getObject(j);
+
+ if(collection.contains(s0))
+ {
+ oppositeRequiresCollection->release();
+ Ps::getFoundation().error(physx::PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxSerialization::isSerializable: Object of type %s in externalReferences references an object "
+ "of type %s in collection (circular dependency).",
+ s.getConcreteTypeName(), s0.getConcreteTypeName());
+ return false;
+ }
+ }
+ cmCollection->mObjects.clear();
+ }
+ oppositeRequiresCollection->release();
+ }
+
+ return true;
+}
+
+void PxSerialization::complete(PxCollection& collection, PxSerializationRegistry& sr, const PxCollection* exceptFor, bool followJoints)
+{
+ PxCollection* curCollection = PxCreateCollection();
+ PX_ASSERT(curCollection);
+ curCollection->add(collection);
+
+ PxCollection* requiresCollection = PxCreateCollection();
+ PX_ASSERT(requiresCollection);
+
+ do
+ {
+ getRequiresCollection(*requiresCollection, *curCollection, collection, exceptFor, sr, followJoints);
+
+ collection.add(*requiresCollection);
+ PxCollection* swap = curCollection;
+ curCollection = requiresCollection;
+ requiresCollection = swap;
+ (static_cast<Cm::Collection*>(requiresCollection))->mObjects.clear();
+
+ }while(curCollection->getNbObjects() > 0);
+
+ requiresCollection->release();
+ curCollection->release();
+
+}
+
+void PxSerialization::createSerialObjectIds(PxCollection& collection, const PxSerialObjectId base)
+{
+ PxSerialObjectId localBase = base;
+ PxU32 nbObjects = collection.getNbObjects();
+
+ for (PxU32 i = 0; i < nbObjects; ++i)
+ {
+ while(collection.find(localBase))
+ {
+ localBase++;
+ }
+
+ PxBase& s = collection.getObject(i);
+ if(PX_SERIAL_OBJECT_ID_INVALID == collection.getId(s))
+ {
+ collection.addId(s, localBase);
+ localBase++;
+ }
+ }
+}
+
+namespace physx { namespace Sn
+{
+ static PxU32 addToStringTable(physx::shdfnd::Array<char>& stringTable, const char* str)
+ {
+ if(!str)
+ return 0xffffffff;
+
+ PxI32 length = PxI32(stringTable.size());
+ const char* table = stringTable.begin();
+ const char* start = table;
+ while(length)
+ {
+ if(strcmp(table, str)==0)
+ return PxU32(table - start);
+
+ const char* saved = table;
+ while(*table++);
+ length -= PxU32(table - saved);
+ PX_ASSERT(length>=0);
+ }
+
+ const PxU32 offset = stringTable.size();
+
+ while(*str)
+ stringTable.pushBack(*str++);
+ stringTable.pushBack(0);
+ return offset;
+ }
+} }
+
+void PxSerialization::dumpBinaryMetaData(PxOutputStream& outputStream, PxSerializationRegistry& sr)
+{
+ class MetaDataStream : public PxOutputStream
+ {
+ public:
+ bool addNewType(const char* typeName)
+ {
+ for(PxU32 i=0;i<types.size();i++)
+ {
+ if(strcmp(types[i], typeName)==0)
+ return false;
+ }
+ types.pushBack(typeName);
+ return true;
+ }
+ virtual PxU32 write(const void* src, PxU32 count)
+ {
+ PX_ASSERT(count==sizeof(PxMetaDataEntry));
+ const PxMetaDataEntry* entry = reinterpret_cast<const PxMetaDataEntry*>(src);
+ if(( entry->flags & PxMetaDataFlag::eTYPEDEF) || ((entry->flags & PxMetaDataFlag::eCLASS) && (!entry->name)) )
+ newType = addNewType(entry->type);
+ if(newType)
+ metaData.pushBack(*entry);
+ return count;
+ }
+ shdfnd::Array<PxMetaDataEntry> metaData;
+ shdfnd::Array<const char*> types;
+ bool newType;
+ }s;
+
+ SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
+ sn.getBinaryMetaData(s);
+
+ shdfnd::Array<char> stringTable;
+
+ PxU32 nb = s.metaData.size();
+ PxMetaDataEntry* entries = s.metaData.begin();
+ for(PxU32 i=0;i<nb;i++)
+ {
+ entries[i].type = reinterpret_cast<const char*>(size_t(addToStringTable(stringTable, entries[i].type)));
+ entries[i].name = reinterpret_cast<const char*>(size_t(addToStringTable(stringTable, entries[i].name)));
+ }
+
+ PxU32 platformTag = getBinaryPlatformTag();
+
+#if PX_X64
+ const PxU32 gaussMapLimit = PxGetGaussMapVertexLimitForPlatform(PxPlatform::ePC);
+#endif
+#if PX_X86 || defined(__CYGWIN__)
+ const PxU32 gaussMapLimit = PxGetGaussMapVertexLimitForPlatform(PxPlatform::ePC);
+#endif
+#if PX_ARM_FAMILY
+ const PxU32 gaussMapLimit = PxGetGaussMapVertexLimitForPlatform(PxPlatform::eARM);
+#endif
+
+ const PxU32 header = PX_MAKE_FOURCC('M','E','T','A');
+ const PxU32 version = PX_PHYSICS_VERSION;
+ const PxU32 binaryVersion = PX_BINARY_SERIAL_VERSION;
+ const PxU32 ptrSize = sizeof(void*);
+ PxU32 buildNumber = 0;
+#if defined(PX_BUILD_NUMBER)
+ buildNumber = PX_BUILD_NUMBER;
+#endif
+ outputStream.write(&header, 4);
+ outputStream.write(&version, 4);
+ outputStream.write(&binaryVersion, 4);
+ outputStream.write(&buildNumber, 4);
+ outputStream.write(&ptrSize, 4);
+ outputStream.write(&platformTag, 4);
+ outputStream.write(&gaussMapLimit, 4);
+
+ outputStream.write(&nb, 4);
+ outputStream.write(entries, nb*sizeof(PxMetaDataEntry));
+
+ //concreteTypes to name
+ PxU32 num = sn.getNbSerializers();
+ outputStream.write(&num, 4);
+ for(PxU32 i=0; i<num; i++)
+ {
+ PxU16 type = sn.getSerializerType(i);
+ PxU32 nameOffset = addToStringTable(stringTable, sn.getSerializerName(i));
+ outputStream.write(&type, 2);
+ outputStream.write(&nameOffset, 4);
+ }
+
+ PxU32 length = stringTable.size();
+ const char* table = stringTable.begin();
+ outputStream.write(&length, 4);
+ outputStream.write(table, length);
+}
+
+PxBinaryConverter* PxSerialization::createBinaryConverter()
+{
+ return PX_NEW(ConvX)();
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.cpp
new file mode 100644
index 00000000..091f7e08
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.cpp
@@ -0,0 +1,287 @@
+// 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 "SnSerializationRegistry.h"
+#include "PxPhysics.h"
+#include "PxPhysicsSerialization.h"
+#include "ExtSerialization.h"
+#include "PxSerializer.h"
+#include "CmCollection.h"
+#include "PxArticulationLink.h"
+#include "PsFoundation.h"
+#include "PsString.h"
+
+using namespace physx;
+
+namespace
+{
+ class CollectionSorter : public PxProcessPxBaseCallback
+ {
+ typedef Ps::Pair<PxBase*, PxSerialObjectId> Object;
+
+ class Element
+ {
+ public:
+ Object object;
+ Ps::Array<PxU32> children;
+ bool isFinished;
+
+ Element(PxBase* obj = NULL) : object(obj, PX_SERIAL_OBJECT_ID_INVALID), isFinished(false) {}
+ };
+
+ public:
+ CollectionSorter(Cm::Collection& collection, Sn::SerializationRegistry& sr, bool isRepx) : mCollection(collection), mSr(sr), mIsRepx(isRepx) {}
+ virtual ~CollectionSorter(){}
+
+ void process(PxBase& base)
+ {
+ addChild(&base);
+ //ArticulationLink is not a repx serializer, so should require Articulation here
+ if( mIsRepx && PxConcreteType::eARTICULATION_LINK == base.getConcreteType() )
+ {
+ PxArticulationLink* link = static_cast<PxArticulationLink*>(&base);
+ PxBase* a = reinterpret_cast<PxBase*>(&link->getArticulation());
+ if(mCurElement->object.first != a ) //don't require itself
+ addChild(a);
+ }
+ }
+
+ void sort()
+ {
+ Element element;
+ PxU32 i;
+
+ PxU32 nbObject = mCollection.internalGetNbObjects();
+ const Cm::Collection::ObjectToIdMap::Entry* objectdatas = mCollection.internalGetObjects();
+ for( i = 0; i < nbObject; ++i )
+ {
+ element.object.first = objectdatas[i].first;
+ element.object.second = objectdatas[i].second;
+ mObjToIdMap.insert(objectdatas[i].first, mElements.size());
+ mElements.pushBack(element);
+ }
+
+ for( i = 0; i < nbObject; ++i )
+ {
+ mCurElement = &mElements[i];
+ const PxSerializer* serializer = mSr.getSerializer(mCurElement->object.first->getConcreteType());
+ PX_ASSERT(serializer);
+ serializer->requires(*mCurElement->object.first, *this);
+ }
+
+ for( i = 0; i < nbObject; ++i )
+ {
+ if( mElements[i].isFinished )
+ continue;
+
+ AddElement(mElements[i]);
+ }
+
+ mCollection.mObjects.clear();
+ for(Ps::Array<Object>::Iterator o = mSorted.begin(); o != mSorted.end(); ++o )
+ {
+ mCollection.internalAdd(o->first, o->second);
+ }
+ }
+
+ void AddElement(Element& e)
+ {
+ if( !e.isFinished )
+ {
+ for( Ps::Array<PxU32>::Iterator child = e.children.begin(); child != e.children.end(); ++child )
+ {
+ AddElement(mElements[*child]);
+ }
+ mSorted.pushBack(e.object);
+ e.isFinished = true;
+ }
+ }
+
+ private:
+ PX_INLINE void addChild(PxBase* base)
+ {
+ PX_ASSERT(mCurElement);
+ const Ps::HashMap<PxBase*, PxU32>::Entry* entry = mObjToIdMap.find(base);
+ if(entry)
+ mCurElement->children.pushBack(entry->second);
+ }
+
+ CollectionSorter& operator=(const CollectionSorter&);
+ Ps::HashMap<PxBase*, PxU32> mObjToIdMap;
+ Ps::Array<Element> mElements;
+ Cm::Collection& mCollection;
+ Sn::SerializationRegistry& mSr;
+ Ps::Array<Object> mSorted;
+ Element* mCurElement;
+ bool mIsRepx;
+ };
+}
+
+namespace physx { namespace Sn {
+
+SerializationRegistry::SerializationRegistry(PxPhysics& physics)
+ : mPhysics(physics)
+{
+ PxRegisterPhysicsSerializers(*this);
+ Ext::RegisterExtensionsSerializers(*this);
+
+ registerBinaryMetaDataCallback(PxGetPhysicsBinaryMetaData);
+ registerBinaryMetaDataCallback(Ext::GetExtensionsBinaryMetaData);
+}
+
+SerializationRegistry::~SerializationRegistry()
+{
+ PxUnregisterPhysicsSerializers(*this);
+ Ext::UnregisterExtensionsSerializers(*this);
+
+ if(mSerializers.size() > 0)
+ {
+ shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxSerializationRegistry::release(): some registered PxSerializer instances were not unregistered");
+ }
+
+ if(mRepXSerializers.size() > 0)
+ {
+ shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxSerializationRegistry::release(): some registered PxRepXSerializer instances were not unregistered");
+ }
+}
+
+void SerializationRegistry::registerSerializer(PxType type, PxSerializer& serializer)
+{
+ if(mSerializers.find(type))
+ {
+ shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxSerializationRegistry::registerSerializer: Type %d has already been registered", type);
+ }
+
+ mSerializers.insert(type, &serializer);
+}
+
+PxSerializer* SerializationRegistry::unregisterSerializer(PxType type)
+{
+ const SerializerMap::Entry* e = mSerializers.find(type);
+ PxSerializer* s = e ? e->second : NULL;
+
+ if(!mSerializers.erase(type))
+ {
+ shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxSerializationRegistry::unregisterSerializer: failed to find PxSerializer instance for type %d", type);
+ }
+ return s;
+}
+
+const PxSerializer* SerializationRegistry::getSerializer(PxType type) const
+{
+ const SerializerMap::Entry* e = mSerializers.find(type);
+#if PX_CHECKED
+ if (!e)
+ {
+ shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxSerializationRegistry::getSerializer: failed to find PxSerializer instance for type %d", type);
+ }
+#endif
+ return e ? e->second : NULL;
+}
+
+PxType SerializationRegistry::getSerializerType(PxU32 index) const
+{
+ PX_ASSERT(index < mSerializers.size());
+ return mSerializers.getEntries()[index].first;
+}
+
+const char* SerializationRegistry::getSerializerName(PxU32 index) const
+{
+ PX_ASSERT(index < mSerializers.size());
+ return mSerializers.getEntries()[index].second->getConcreteTypeName();
+}
+
+void SerializationRegistry::registerBinaryMetaDataCallback(PxBinaryMetaDataCallback callback)
+{
+ mMetaDataCallbacks.pushBack(callback);
+}
+
+void SerializationRegistry::getBinaryMetaData(PxOutputStream& stream) const
+{
+ for(PxU32 i = 0; i < mMetaDataCallbacks.size(); i++)
+ {
+ mMetaDataCallbacks[i](stream);
+ }
+}
+
+void SerializationRegistry::registerRepXSerializer(PxType type, PxRepXSerializer& serializer)
+{
+ if(mRepXSerializers.find(type))
+ {
+ shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxSerializationRegistry::registerRepXSerializer: Type %d has already been registered", type);
+ }
+
+ mRepXSerializers.insert(type, &serializer);
+}
+
+PxRepXSerializer* SerializationRegistry::getRepXSerializer(const char* typeName) const
+{
+ SerializationRegistry* sr = const_cast<SerializationRegistry*>(this);
+ for( RepXSerializerMap::Iterator iter = sr->mRepXSerializers.getIterator(); !iter.done(); ++iter)
+ {
+ if ( physx::shdfnd::stricmp( iter->second->getTypeName(), typeName ) == 0 )
+ return iter->second;
+ }
+ return NULL;
+}
+
+PxRepXSerializer* SerializationRegistry::unregisterRepXSerializer(PxType type)
+{
+ const RepXSerializerMap::Entry* e = mRepXSerializers.find(type);
+ PxRepXSerializer* s = e ? e->second : NULL;
+
+ if(!mRepXSerializers.erase(type))
+ {
+ shdfnd::getFoundation().error(physx::PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "PxSerializationRegistry::unregisterRepXSerializer: failed to find PxRepXSerializer instance for type %d", type);
+ }
+ return s;
+}
+
+void sortCollection(Cm::Collection& collection, SerializationRegistry& sr, bool isRepx)
+{
+ CollectionSorter sorter(collection, sr, isRepx);
+ sorter.sort();
+}
+
+} // Sn
+
+PxSerializationRegistry* PxSerialization::createSerializationRegistry(PxPhysics& physics)
+{
+ return PX_NEW(Sn::SerializationRegistry)(physics);
+}
+
+} // physx
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.h
new file mode 100644
index 00000000..6aa21c24
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/SnSerializationRegistry.h
@@ -0,0 +1,91 @@
+// 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_SN_SERIALIZATION_REGISTRY
+#define PX_PHYSICS_SN_SERIALIZATION_REGISTRY
+
+#include "PxSerialization.h"
+#include "PxRepXSerializer.h"
+#include "CmPhysXCommon.h"
+#include "PsUserAllocated.h"
+#include "PsArray.h"
+#include "PsHashMap.h"
+
+namespace physx
+{
+
+namespace Cm { class Collection; }
+
+namespace Sn {
+
+ class SerializationRegistry : public PxSerializationRegistry, public Ps::UserAllocated
+ {
+ public:
+ SerializationRegistry(PxPhysics& physics);
+ virtual ~SerializationRegistry();
+
+ virtual void release(){ PX_DELETE(this); }
+
+ PxPhysics& getPhysics() const { return mPhysics; }
+
+ //binary
+ void registerSerializer(PxType type, PxSerializer& serializer);
+ PxSerializer* unregisterSerializer(PxType type);
+ void registerBinaryMetaDataCallback(PxBinaryMetaDataCallback callback);
+ void getBinaryMetaData(PxOutputStream& stream) const;
+ const PxSerializer* getSerializer(PxType type) const;
+ const char* getSerializerName(PxU32 index) const;
+ PxType getSerializerType(PxU32 index) const;
+ PxU32 getNbSerializers() const { return mSerializers.size(); }
+ //repx
+ void registerRepXSerializer(PxType type, PxRepXSerializer& serializer);
+ PxRepXSerializer* getRepXSerializer(const char* typeName) const;
+ PxRepXSerializer* unregisterRepXSerializer(PxType type);
+
+ protected:
+ SerializationRegistry &operator=(const SerializationRegistry &);
+ private:
+ typedef Ps::CoalescedHashMap<PxType, PxSerializer*> SerializerMap;
+ typedef Ps::HashMap<PxType, PxRepXSerializer*> RepXSerializerMap;
+
+ PxPhysics& mPhysics;
+ SerializerMap mSerializers;
+ RepXSerializerMap mRepXSerializers;
+ Ps::Array<PxBinaryMetaDataCallback> mMetaDataCallbacks;
+ };
+
+ void sortCollection(Cm::Collection& collection, SerializationRegistry& sr, bool isRepx);
+} // Sn
+
+} // physx
+
+
+
+#endif
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnJointRepXSerializer.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnJointRepXSerializer.cpp
new file mode 100644
index 00000000..94d60453
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnJointRepXSerializer.cpp
@@ -0,0 +1,137 @@
+// 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 "PxMetaDataObjects.h"
+#include "PxExtensionMetaDataObjects.h"
+#include "ExtJointMetaDataExtensions.h"
+#include "SnRepXSerializerImpl.h"
+#include "PxJointRepXSerializer.h"
+
+namespace physx {
+
+ template<typename TJointType>
+ inline TJointType* createJoint( PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1 )
+ {
+ PX_UNUSED(physics);
+ PX_UNUSED(actor0);
+ PX_UNUSED(actor1);
+ PX_UNUSED(localFrame0);
+ PX_UNUSED(localFrame1);
+ return NULL;
+ }
+
+ template<>
+ inline PxD6Joint* createJoint<PxD6Joint>(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ {
+ return PxD6JointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
+ }
+
+ template<>
+ inline PxDistanceJoint* createJoint<PxDistanceJoint>(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ {
+ return PxDistanceJointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
+ }
+
+ template<>
+ inline PxFixedJoint* createJoint<PxFixedJoint>(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ {
+ return PxFixedJointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
+ }
+
+ template<>
+ inline PxPrismaticJoint* createJoint<PxPrismaticJoint>(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ {
+ return PxPrismaticJointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
+ }
+
+ template<>
+ inline PxRevoluteJoint* createJoint<PxRevoluteJoint>(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ {
+ return PxRevoluteJointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
+ }
+
+ template<>
+ inline PxSphericalJoint* createJoint<PxSphericalJoint>(PxPhysics& physics,
+ PxRigidActor* actor0, const PxTransform& localFrame0,
+ PxRigidActor* actor1, const PxTransform& localFrame1)
+ {
+ return PxSphericalJointCreate( physics, actor0, localFrame0, actor1, localFrame1 );
+ }
+
+ template<typename TJointType>
+ PxRepXObject PxJointRepXSerializer<TJointType>::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
+ {
+ PxRigidActor* actor0 = NULL;
+ PxRigidActor* actor1 = NULL;
+ PxTransform localPose0 = PxTransform(PxIdentity);
+ PxTransform localPose1 = PxTransform(PxIdentity);
+ bool ok = true;
+ if ( inReader.gotoChild( "Actors" ) )
+ {
+ ok = readReference<PxRigidActor>( inReader, *inCollection, "actor0", actor0 );
+ ok &= readReference<PxRigidActor>( inReader, *inCollection, "actor1", actor1 );
+ inReader.leaveChild();
+ }
+ TJointType* theJoint = !ok ? NULL : createJoint<TJointType>( inArgs.physics, actor0, localPose0, actor1, localPose1 );
+
+ if ( theJoint )
+ {
+ PxConstraint* constraint = theJoint->getConstraint();
+ PX_ASSERT( constraint );
+ inCollection->add( *constraint );
+ this->fileToObjectImpl( theJoint, inReader, inAllocator, inArgs, inCollection );
+ }
+ return PxCreateRepXObject(theJoint);
+ }
+
+ template<typename TJointType>
+ void PxJointRepXSerializer<TJointType>::objectToFileImpl( const TJointType* inObj, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& )
+ {
+ writeAllProperties( inObj, inWriter, inTempBuffer, *inCollection );
+ }
+
+ // explicit instantiations
+ template struct PxJointRepXSerializer<PxFixedJoint>;
+ template struct PxJointRepXSerializer<PxDistanceJoint>;
+ template struct PxJointRepXSerializer<PxD6Joint>;
+ template struct PxJointRepXSerializer<PxPrismaticJoint>;
+ template struct PxJointRepXSerializer<PxRevoluteJoint>;
+ template struct PxJointRepXSerializer<PxSphericalJoint>;
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnPxStreamOperators.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnPxStreamOperators.h
new file mode 100644
index 00000000..efca5662
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnPxStreamOperators.h
@@ -0,0 +1,134 @@
+// 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_PXSTREAMOPERATORS_H
+#define PX_PXSTREAMOPERATORS_H
+
+#include "foundation/PxVec3.h"
+#include "foundation/PxTransform.h"
+#include "foundation/PxBounds3.h"
+#include "PxFiltering.h"
+
+#include "PsString.h"
+
+namespace physx
+{
+ static inline PxU32 strLenght( const char* inStr )
+ {
+ return inStr ? PxU32(strlen(inStr)) : 0;
+ }
+}
+
+namespace physx // ADL requires we put the operators in the same namespace as the underlying type of PxOutputStream
+{
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, const char* inString )
+ {
+ if ( inString && *inString )
+ {
+ ioStream.write( inString, PxU32(strlen(inString)) );
+ }
+ return ioStream;
+ }
+
+ template<typename TDataType>
+ inline PxOutputStream& toStream( PxOutputStream& ioStream, const char* inFormat, const TDataType inData )
+ {
+ char buffer[128] = { 0 };
+ Ps::snprintf( buffer, 128, inFormat, inData );
+ ioStream << buffer;
+ return ioStream;
+ }
+
+ struct endl_obj {};
+ //static endl_obj endl;
+
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, bool inData ) { ioStream << (inData ? "true" : "false"); return ioStream; }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxI32 inData ) { return toStream( ioStream, "%d", inData ); }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU16 inData ) { return toStream( ioStream, "%u", PxU32(inData) ); }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU8 inData ) { return toStream( ioStream, "%u", PxU32(inData) ); }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, char inData ) { return toStream( ioStream, "%c", inData ); }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU32 inData ) { return toStream( ioStream, "%u", inData ); }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxU64 inData ) { return toStream( ioStream, "%" PX_PRIu64, inData ); }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, const void* inData ) { return ioStream << PX_PROFILE_POINTER_TO_U64( inData ); }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxF32 inData ) { return toStream( ioStream, "%g", PxF64(inData) ); }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, PxF64 inData ) { return toStream( ioStream, "%g", inData ); }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, endl_obj) { return ioStream << "\n"; }
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxVec3& inData )
+ {
+ ioStream << inData[0];
+ ioStream << " ";
+ ioStream << inData[1];
+ ioStream << " ";
+ ioStream << inData[2];
+ return ioStream;
+ }
+
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxQuat& inData )
+ {
+ ioStream << inData.x;
+ ioStream << " ";
+ ioStream << inData.y;
+ ioStream << " ";
+ ioStream << inData.z;
+ ioStream << " ";
+ ioStream << inData.w;
+ return ioStream;
+ }
+
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxTransform& inData )
+ {
+ ioStream << inData.q;
+ ioStream << " ";
+ ioStream << inData.p;
+ return ioStream;
+ }
+
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxBounds3& inData )
+ {
+ ioStream << inData.minimum;
+ ioStream << " ";
+ ioStream << inData.maximum;
+ return ioStream;
+ }
+
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, const PxFilterData& inData )
+ {
+ ioStream << inData.word0 << " " << inData.word1 << " " << inData.word2 << " " << inData.word3;
+ return ioStream;
+ }
+
+ inline PxOutputStream& operator << ( PxOutputStream& ioStream, struct PxMetaDataPlane& inData )
+ {
+ ioStream << inData.normal;
+ ioStream << " ";
+ ioStream << inData.distance;
+ return ioStream;
+ }
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX1_0Defaults.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX1_0Defaults.h
new file mode 100644
index 00000000..31ad950e
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX1_0Defaults.h
@@ -0,0 +1,245 @@
+// 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.
+
+ DEFINE_REPX_DEFAULT_PROPERTY("PxBoxGeometry.HalfExtents", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphereGeometry.Radius", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Scale", "1 1 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Rotation", "0 0 0 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.ConvexMesh", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Scale", "1 1 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Rotation", "0 0 0 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.MeshFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.TriangleMesh", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightField", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightScale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.RowScale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.ColumnScale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightFieldFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Length", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Mass", "1000" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Speed", "10" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFriction", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFriction", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFrictionV", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFrictionV", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DirOfAnisotropy", "1 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.FrictionCombineMode", "eAVERAGE" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.RestitutionCombineMode", "eAVERAGE" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.LocalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.SimulationFilterData", "0 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.QueryFilterData", "0 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.ContactOffset", "0.02" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.RestOffset", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Flags", "eSIMULATION_SHAPE|eSCENE_QUERY_SHAPE|eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.CMassLocalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Mass", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MassSpaceInertiaTensor", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearDamping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularDamping", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MaxAngularVelocity", "7" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SleepEnergyThreshold", "0.005" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minPositionIters", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minVelocityIters", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ContactReportThreshold", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.RigidDynamicFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ParentPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ChildPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetOrientation", "0 0 0 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.InternalCompliance", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ExternalCompliance", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.yLimit", "0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.zLimit", "0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitEnabled", "false" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.lower", "-0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.upper", "0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitEnabled", "false" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.CMassLocalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Mass", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.MassSpaceInertiaTensor", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.LinearVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.AngularVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.MaxProjectionIterations", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SeparationTolerance", "0.1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.InternalDriveIterations", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.ExternalDriveIterations", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minPositionIters", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minVelocityIters", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eX", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eY", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eZ", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eTWIST", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING1", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING2", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Value", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Upper", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Lower", "-1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.YAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ZAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DrivePosition", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.linear", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.angular", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MinDistance", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MaxDistance", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Tolerance", "0.025" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.DistanceJointFlags", "eMAX_DISTANCE_ENABLED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Upper", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Lower", "-1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveVelocity", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveGearRatio", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.RevoluteJointFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.ContactDistance", "0.01" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Upper", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Lower", "-3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.PrismaticJointFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.UserData", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.YAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ZAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.SphericalJointFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("THEEND", "false" )
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_1Defaults.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_1Defaults.h
new file mode 100644
index 00000000..a3e52a73
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_1Defaults.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.
+
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Length", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Mass", "1000" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Speed", "10" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxBoxGeometry.HalfExtents", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphereGeometry.Radius", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Scale", "1 1 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Rotation", "0 0 0 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.ConvexMesh", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Scale", "1 1 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Rotation", "0 0 0 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.MeshFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.TriangleMesh", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightField", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightScale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.RowScale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.ColumnScale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightFieldFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFriction", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFriction", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFrictionV", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFrictionV", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DirOfAnisotropy", "1 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.FrictionCombineMode", "eAVERAGE" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.RestitutionCombineMode", "eAVERAGE" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.LocalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.SimulationFilterData", "0 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.QueryFilterData", "0 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.ContactOffset", "0.02" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.RestOffset", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Flags", "eSIMULATION_SHAPE|eSCENE_QUERY_SHAPE|eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.CMassLocalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Mass", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MassSpaceInertiaTensor", "1 1 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearDamping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularDamping", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MaxAngularVelocity", "7" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SleepThreshold", "0.005" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minPositionIters", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minVelocityIters", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ContactReportThreshold", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.RigidDynamicFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ParentPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ChildPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetOrientation", "0 0 0 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.InternalCompliance", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ExternalCompliance", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.yLimit", "0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.zLimit", "0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialSpring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialDamping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitEnabled", "false" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.lower", "-0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.upper", "0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitEnabled", "false" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.CMassLocalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Mass", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.MassSpaceInertiaTensor", "1 1 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.LinearVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.AngularVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.MaxProjectionIterations", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SeparationTolerance", "0.1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.InternalDriveIterations", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.ExternalDriveIterations", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minPositionIters", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minVelocityIters", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SleepThreshold", "0.005" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eX", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eY", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eZ", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eTWIST", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING1", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING2", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Value", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Upper", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Lower", "-1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.YAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ZAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DrivePosition", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.linear", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.angular", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MinDistance", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MaxDistance", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Tolerance", "0.025" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.DistanceJointFlags", "eMAX_DISTANCE_ENABLED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Upper", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Lower", "-1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveVelocity", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveGearRatio", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.RevoluteJointFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.ContactDistance", "0.01" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Upper", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Lower", "-3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.PrismaticJointFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.YAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ZAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.SphericalJointFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.scale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.bias", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ExternalAcceleration", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DampingCoefficient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SolverFrequency", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SleepLinearVelocity", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("THEEND", "false" )
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_2Defaults.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_2Defaults.h
new file mode 100644
index 00000000..f3959504
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepX3_2Defaults.h
@@ -0,0 +1,313 @@
+// 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.
+
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Length", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Mass", "1000" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTolerancesScale.Speed", "10" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxBoxGeometry.HalfExtents", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphereGeometry.Radius", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Scale", "1 1 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.Scale.Rotation", "0 0 0 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxConvexMeshGeometry.ConvexMesh", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Scale", "1 1 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.Scale.Rotation", "0 0 0 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.MeshFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxTriangleMeshGeometry.TriangleMesh", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightField", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightScale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.RowScale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.ColumnScale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxHeightFieldGeometry.HeightFieldFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.DynamicFriction", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.StaticFriction", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.FrictionCombineMode", "eAVERAGE" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxMaterial.RestitutionCombineMode", "eAVERAGE" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.LocalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.SimulationFilterData", "0 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.QueryFilterData", "0 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.ContactOffset", "0.02" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.RestOffset", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Flags", "eSIMULATION_SHAPE|eSCENE_QUERY_SHAPE|eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxShape.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidStatic.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.CMassLocalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.Mass", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MassSpaceInertiaTensor", "1 1 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.LinearDamping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.AngularDamping", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.MaxAngularVelocity", "7" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SleepThreshold", "0.005" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minPositionIters", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.SolverIterationCounts.minVelocityIters", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.ContactReportThreshold", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRigidDynamic.RigidDynamicFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ParentPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ChildPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetOrientation", "0 0 0 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TargetVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.InternalCompliance", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.ExternalCompliance", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.yLimit", "0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimit.zLimit", "0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialSpring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TangentialDamping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.SwingLimitEnabled", "false" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.lower", "-0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimit.upper", "0.78539816339" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitEnabled", "false" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationJoint.TwistLimitContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.CMassLocalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.Mass", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.MassSpaceInertiaTensor", "1 1 1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.LinearVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulationLink.AngularVelocity", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.MaxProjectionIterations", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SeparationTolerance", "0.1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.InternalDriveIterations", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.ExternalDriveIterations", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minPositionIters", "4" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SolverIterationCounts.minVelocityIters", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.SleepThreshold", "0.005" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxArticulation.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eX", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eY", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eZ", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eTWIST", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING1", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Motion.eSWING2", "eLOCKED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.LinearLimit.Value", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Upper", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.TwistLimit.Lower", "-1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.YAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.SwingLimit.ZAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eX.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eY.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eZ.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSWING.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eTWIST.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.ForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.Drive.eSLERP.Flags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DrivePosition", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.linear", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.DriveVelocity.angular", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxD6Joint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxFixedJoint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MinDistance", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.MaxDistance", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Tolerance", "0.025" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxDistanceJoint.DistanceJointFlags", "eMAX_DISTANCE_ENABLED" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Upper", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.Limit.Lower", "-1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveVelocity", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveForceLimit", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.DriveGearRatio", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.RevoluteJointFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxRevoluteJoint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.ContactDistance", "0.01" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Upper", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.Limit.Lower", "-3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.PrismaticJointFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxPrismaticJoint.ProjectionAngularTolerance", "3.14159" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor0", "8887040" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Actors.actor1", "8887456" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR0", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LocalPose.eACTOR1", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.force", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.BreakForce.torque", "3.40282e+038" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ConstraintFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Restitution", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Spring", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ContactDistance", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.YAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.LimitCone.ZAngle", "1.5708" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.SphericalJointFlags", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxSphericalJoint.ProjectionLinearTolerance", "1e+010" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.Name", "" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ClientBehaviorBits", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.scale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.MotionConstraintScaleBias.bias", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.GlobalPose", "0 0 0 1 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.ExternalAcceleration", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DampingCoefficient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SolverFrequency", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.SleepLinearVelocity", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.InertiaScale", "1" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.FrictionCoefficient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.DragCoefficient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxCloth.CollisionMassScale", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ExternalAcceleration", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ParticleMass", "0.001" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.Restitution", "0.5" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.DynamicFriction", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.StaticFriction", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.SimulationFilterData", "0 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.MaxMotionDistance", "0.06" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.RestOffset", "0.004" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ContactOffset", "0.008" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.GridSize", "0.96" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ProjectionPlane", "0 0 1 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ParticleReadDataFlags", "ePOSITION_BUFFER|eFLAGS_BUFFER" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleSystem.ParticleBaseFlags", "eCOLLISION_WITH_DYNAMIC_ACTORS|eENABLED|ePER_PARTICLE_REST_OFFSET|ePER_PARTICLE_COLLISION_CACHE_HINT")
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ActorFlags", "eVISUALIZATION" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.DominanceGroup", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.OwnerClient", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Damping", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ExternalAcceleration", "0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ParticleMass", "0.001" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Restitution", "0.5" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.DynamicFriction", "0.05" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.StaticFriction", "0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.SimulationFilterData", "0 0 0 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.MaxMotionDistance", "0.06" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.RestOffset", "0.004" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ContactOffset", "0.008" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.GridSize", "0.64" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ProjectionPlane", "0 0 1 0" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Stiffness", "20" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.Viscosity", "6" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.RestParticleDistance", "0.02" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ParticleReadDataFlags", "ePOSITION_BUFFER|eFLAGS_BUFFER" )
+ DEFINE_REPX_DEFAULT_PROPERTY("PxParticleFluid.ParticleBaseFlags", "eCOLLISION_WITH_DYNAMIC_ACTORS|eENABLED|ePER_PARTICLE_REST_OFFSET|ePER_PARTICLE_COLLISION_CACHE_HINT")
+ DEFINE_REPX_DEFAULT_PROPERTY("PxAggregate.SelfCollision", "false" )
+ DEFINE_REPX_DEFAULT_PROPERTY("THEEND", "false" )
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCollection.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCollection.h
new file mode 100644
index 00000000..b479754d
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCollection.h
@@ -0,0 +1,173 @@
+// 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_REPXCOLLECTION_H
+#define PX_REPXCOLLECTION_H
+
+#include "common/PxTolerancesScale.h"
+#include "PxRepXSerializer.h"
+
+namespace physx { namespace Sn {
+
+ struct XmlNode;
+
+ struct RepXCollectionItem
+ {
+ PxRepXObject liveObject;
+ XmlNode* descriptor;
+ RepXCollectionItem( PxRepXObject inItem = PxRepXObject(), XmlNode* inDescriptor = NULL )
+ : liveObject( inItem )
+ , descriptor( inDescriptor )
+ {
+ }
+ };
+
+ struct RepXDefaultEntry
+ {
+ const char* name;
+ const char* value;
+ RepXDefaultEntry( const char* pn, const char* val ) : name( pn ), value( val ){}
+ };
+
+ /**
+ * The result of adding an object to the collection.
+ */
+ struct RepXAddToCollectionResult
+ {
+ enum Enum
+ {
+ Success,
+ SerializerNotFound,
+ InvalidParameters, //Null data passed in.
+ AlreadyInCollection
+ };
+
+ PxSerialObjectId collectionId;
+ Enum result;
+
+ RepXAddToCollectionResult( Enum inResult = Success, const PxSerialObjectId inId = 0 )
+ : collectionId( inId )
+ , result( inResult )
+ {
+ }
+ bool isValid() { return result == Success && collectionId != 0; }
+ };
+ /**
+ * A RepX collection contains a set of static data objects that can be transformed
+ * into live objects. It uses RepX serializer to do two transformations:
+ * live object <-> collection object (descriptor)
+ * collection object <-> file system.
+ *
+ * A live object is considered to be something live in the physics
+ * world such as a material or a rigidstatic.
+ *
+ * A collection object is a piece of data from which a live object
+ * of identical characteristics can be created.
+ *
+ * Clients need to pass PxCollection so that objects can resolve
+ * references. In addition, objects must be added in an order such that
+ * references can be resolved in the first place. So objects must be added
+ * to the collection *after* objects they are dependent upon.
+ *
+ * When deserializing from a file, the collection will allocate char*'s that will
+ * not be freed when the collection itself is freed. The user must be responsible
+ * for these character allocations.
+ */
+ class RepXCollection
+ {
+ protected:
+ virtual ~RepXCollection(){}
+
+ public:
+ virtual void destroy() = 0;
+
+ /**
+ * Set the scale on this collection. The scale is saved with the collection.
+ *
+ * If the scale wasn't set, it will be invalid.
+ */
+ virtual void setTolerancesScale( const PxTolerancesScale& inScale ) = 0;
+
+ /**
+ * Get the scale that was set at collection creation time or at load time.
+ * If this is a loaded file and the source data does not contain a scale
+ * this value will be invalid (PxTolerancesScale::isValid()).
+ */
+ virtual PxTolerancesScale getTolerancesScale() const = 0;
+
+ /**
+ * Set the up vector on this collection. The up vector is saved with the collection.
+ *
+ * If the up vector wasn't set, it will be (0,0,0).
+ */
+ virtual void setUpVector( const PxVec3& inUpVector ) = 0;
+
+ /**
+ * If the up vector wasn't set, it will be (0,0,0). Else this will be the up vector
+ * optionally set when the collection was created.
+ */
+ virtual PxVec3 getUpVector() const = 0;
+
+ virtual const char* getVersion() = 0;
+ static const char* getLatestVersion();
+
+ //Necessary accessor functions for translation/upgrading.
+ virtual const RepXCollectionItem* begin() const = 0;
+ virtual const RepXCollectionItem* end() const = 0;
+
+
+ //Performs a deep copy of the repx node.
+ virtual XmlNode* copyRepXNode( const XmlNode* srcNode ) = 0;
+
+ virtual void addCollectionItem( RepXCollectionItem inItem ) = 0;
+
+ //Create a new repx node with this name. Its value is unset.
+ virtual XmlNode& createRepXNode( const char* name ) = 0;
+
+ virtual RepXCollection& createCollection( const char* inVersionStr ) = 0;
+ //Release this when finished.
+ virtual XmlReaderWriter& createNodeEditor() = 0;
+
+ virtual PxAllocatorCallback& getAllocator() = 0;
+
+ virtual bool instantiateCollection( PxRepXInstantiationArgs& inArgs, PxCollection& inPxCollection ) = 0;
+
+
+ virtual RepXAddToCollectionResult addRepXObjectToCollection( const PxRepXObject& inObject, PxCollection* inCollection, PxRepXInstantiationArgs& inArgs ) = 0;
+
+ /**
+ * Save this collection out to a file stream. Uses the RepX serialize to perform
+ * collection object->file conversions.
+ *
+ * /param[in] inStream Write-only stream to save collection out to.
+ */
+ virtual void save( PxOutputStream& inStream ) = 0;
+ };
+} }
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.cpp
new file mode 100644
index 00000000..104e521c
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.cpp
@@ -0,0 +1,1158 @@
+// 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 "PxPhysicsAPI.h"
+#include "PxMetaDataObjects.h"
+#include "CmIO.h"
+#include "SnPxStreamOperators.h"
+#include "PsUtilities.h"
+#include "SnXmlImpl.h"
+#include "SnXmlSerializer.h"
+#include "SnXmlDeserializer.h"
+#include "SnRepXCoreSerializer.h"
+
+using namespace physx::Sn;
+namespace physx {
+ typedef PxProfileHashMap< const PxSerialObjectId, const PxArticulationLink* > TArticulationLinkLinkMap;
+ typedef PxReadOnlyPropertyInfo<PxPropertyInfoName::PxArticulationLink_InboundJoint, PxArticulationLink, PxArticulationJoint *> TIncomingJointPropType;
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxMaterial
+ //*************************************************************
+ PxMaterial* PxMaterialRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs )
+ {
+ return inArgs.physics.createMaterial(0, 0, 0);
+ }
+
+ PxRepXObject PxShapeRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
+ {
+ PxProfileAllocatorWrapper wrapper( inAllocator.getAllocator() );
+ TReaderNameStack names( wrapper );
+ PxProfileArray<PxU32> contexts( wrapper );
+ bool hadError = false;
+ RepXVisitorReader<PxShape> theVisitor( names, contexts, inArgs, inReader, NULL, inAllocator, *inCollection, hadError );
+
+ Ps::Array<PxMaterial*> materials;
+ PxGeometry* geometry = NULL;
+ parseShape( theVisitor, geometry, materials );
+ if(hadError)
+ return PxRepXObject();
+ PxShape *theShape = inArgs.physics.createShape( *geometry, materials.begin(), Ps::to16(materials.size()) );
+
+ switch(geometry->getType())
+ {
+ case PxGeometryType::eSPHERE :
+ static_cast<PxSphereGeometry*>(geometry)->~PxSphereGeometry();
+ break;
+ case PxGeometryType::ePLANE :
+ static_cast<PxPlaneGeometry*>(geometry)->~PxPlaneGeometry();
+ break;
+ case PxGeometryType::eCAPSULE :
+ static_cast<PxCapsuleGeometry*>(geometry)->~PxCapsuleGeometry();
+ break;
+ case PxGeometryType::eBOX :
+ static_cast<PxBoxGeometry*>(geometry)->~PxBoxGeometry();
+ break;
+ case PxGeometryType::eCONVEXMESH :
+ static_cast<PxConvexMeshGeometry*>(geometry)->~PxConvexMeshGeometry();
+ break;
+ case PxGeometryType::eTRIANGLEMESH :
+ static_cast<PxTriangleMeshGeometry*>(geometry)->~PxTriangleMeshGeometry();
+ break;
+ case PxGeometryType::eHEIGHTFIELD :
+ static_cast<PxHeightFieldGeometry*>(geometry)->~PxHeightFieldGeometry();
+ break;
+
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ PX_ASSERT(0);
+ }
+ inAllocator.getAllocator().deallocate(geometry);
+
+ bool ret = readAllProperties( inArgs, inReader, theShape, inAllocator, *inCollection );
+
+ return ret ? PxCreateRepXObject(theShape) : PxRepXObject();
+ }
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxTriangleMesh
+ //*************************************************************
+
+ template<typename TTriIndexElem>
+ inline void writeTriangle( MemoryBuffer& inTempBuffer, const Triangle<TTriIndexElem>& inTriangle )
+ {
+ inTempBuffer << inTriangle.mIdx0
+ << " " << inTriangle.mIdx1
+ << " " << inTriangle.mIdx2;
+ }
+
+ PxU32 materialAccess( const PxTriangleMesh* inMesh, PxU32 inIndex ) { return inMesh->getTriangleMaterialIndex( inIndex ); }
+ template<typename TDataType>
+ void writeDatatype( MemoryBuffer& inTempBuffer, const TDataType& inType ) { inTempBuffer << inType; }
+
+ void PxBVH33TriangleMeshRepXSerializer::objectToFileImpl( const PxBVH33TriangleMesh* mesh, PxCollection* /*inCollection*/, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs )
+ {
+ bool hasMatIndex = mesh->getTriangleMaterialIndex(0) != 0xffff;
+ PxU32 numVertices = mesh->getNbVertices();
+ const PxVec3* vertices = mesh->getVertices();
+ writeBuffer( inWriter, inTempBuffer, 2, vertices, numVertices, "Points", writePxVec3 );
+ bool isU16 = mesh->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES ? true : false;
+ PxU32 triCount = mesh->getNbTriangles();
+ const void* indices = mesh->getTriangles();
+ if ( isU16 )
+ writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU16>* >( indices ), triCount, "Triangles", writeTriangle<PxU16> );
+ else
+ writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU32>* >( indices ), triCount, "Triangles", writeTriangle<PxU32> );
+ if ( hasMatIndex )
+ writeBuffer( inWriter, inTempBuffer, 6, mesh, materialAccess, triCount, "materialIndices", writeDatatype<PxU32> );
+
+ //Cooked stream
+ PxTriangleMeshDesc meshDesc;
+ meshDesc.points.count = numVertices;
+ meshDesc.points.data = vertices;
+ meshDesc.points.stride = sizeof(PxVec3);
+ meshDesc.triangles.count = triCount;
+ meshDesc.triangles.data = indices;
+ meshDesc.triangles.stride = isU16?3*sizeof(PxU16):3*sizeof(PxU32);
+
+ if(isU16)
+ {
+ meshDesc.triangles.stride = sizeof(PxU16)*3;
+ meshDesc.flags |= PxMeshFlag::e16_BIT_INDICES;
+ }
+ else
+ {
+ meshDesc.triangles.stride = sizeof(PxU32)*3;
+ }
+
+ if(hasMatIndex)
+ {
+ PxMaterialTableIndex* materialIndices = new PxMaterialTableIndex[triCount];
+ for(PxU32 i = 0; i < triCount; i++)
+ materialIndices[i] = mesh->getTriangleMaterialIndex(i);
+
+ meshDesc.materialIndices.data = materialIndices;
+ meshDesc.materialIndices.stride = sizeof(PxMaterialTableIndex);
+
+ }
+
+ if(inArgs.cooker != NULL)
+ {
+ TMemoryPoolManager theManager(mAllocator);
+ MemoryBuffer theTempBuf( &theManager );
+ theTempBuf.clear();
+ inArgs.cooker->cookTriangleMesh( meshDesc, theTempBuf );
+
+ writeBuffer( inWriter, inTempBuffer, 16, theTempBuf.mBuffer, theTempBuf.mWriteOffset, "CookedData", writeDatatype<PxU8> );
+ }
+
+ delete []meshDesc.materialIndices.data;
+ }
+
+ PxRepXObject PxBVH33TriangleMeshRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/ )
+ {
+ //We can't do a simple inverse; we *have* to cook data to get a mesh.
+ PxTriangleMeshDesc theDesc;
+ readStridedBufferProperty<PxVec3>( inReader, "points", theDesc.points, inAllocator);
+ readStridedBufferProperty<Triangle<PxU32> >( inReader, "triangles", theDesc.triangles, inAllocator);
+ PxU32 triCount;
+ readStridedBufferProperty<PxMaterialTableIndex>( inReader, "materialIndices", theDesc.materialIndices, triCount, inAllocator);
+ PxStridedData cookedData;
+ cookedData.stride = sizeof(PxU8);
+ PxU32 dataSize;
+ readStridedBufferProperty<PxU8>( inReader, "CookedData", cookedData, dataSize, inAllocator);
+
+ TMemoryPoolManager theManager(inAllocator.getAllocator());
+ MemoryBuffer theTempBuf( &theManager );
+
+// PxTriangleMesh* theMesh = NULL;
+ PxBVH33TriangleMesh* theMesh = NULL;
+
+ if(dataSize != 0)
+ {
+ theTempBuf.write(cookedData.data, dataSize*sizeof(PxU8));
+// theMesh = inArgs.physics.createTriangleMesh( theTempBuf );
+ theMesh = static_cast<PxBVH33TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf ));
+ }
+
+ if(theMesh == NULL)
+ {
+ PX_ASSERT(inArgs.cooker);
+ theTempBuf.clear();
+
+ {
+ PxCookingParams params = inArgs.cooker->getParams();
+ params.midphaseDesc = PxMeshMidPhase::eBVH33;
+ inArgs.cooker->setParams(params);
+ }
+
+ inArgs.cooker->cookTriangleMesh( theDesc, theTempBuf );
+// theMesh = inArgs.physics.createTriangleMesh( theTempBuf );
+ theMesh = static_cast<PxBVH33TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf ));
+ }
+
+ return PxCreateRepXObject( theMesh );
+ }
+
+ void PxBVH34TriangleMeshRepXSerializer::objectToFileImpl( const PxBVH34TriangleMesh* mesh, PxCollection* /*inCollection*/, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs )
+ {
+ bool hasMatIndex = mesh->getTriangleMaterialIndex(0) != 0xffff;
+ PxU32 numVertices = mesh->getNbVertices();
+ const PxVec3* vertices = mesh->getVertices();
+ writeBuffer( inWriter, inTempBuffer, 2, vertices, numVertices, "Points", writePxVec3 );
+ bool isU16 = mesh->getTriangleMeshFlags() & PxTriangleMeshFlag::e16_BIT_INDICES ? true : false;
+ PxU32 triCount = mesh->getNbTriangles();
+ const void* indices = mesh->getTriangles();
+ if ( isU16 )
+ writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU16>* >( indices ), triCount, "Triangles", writeTriangle<PxU16> );
+ else
+ writeBuffer( inWriter, inTempBuffer, 2, reinterpret_cast<const Triangle<PxU32>* >( indices ), triCount, "Triangles", writeTriangle<PxU32> );
+ if ( hasMatIndex )
+ writeBuffer( inWriter, inTempBuffer, 6, mesh, materialAccess, triCount, "materialIndices", writeDatatype<PxU32> );
+
+ //Cooked stream
+ PxTriangleMeshDesc meshDesc;
+ meshDesc.points.count = numVertices;
+ meshDesc.points.data = vertices;
+ meshDesc.points.stride = sizeof(PxVec3);
+ meshDesc.triangles.count = triCount;
+ meshDesc.triangles.data = indices;
+ meshDesc.triangles.stride = isU16?3*sizeof(PxU16):3*sizeof(PxU32);
+
+ if(isU16)
+ {
+ meshDesc.triangles.stride = sizeof(PxU16)*3;
+ meshDesc.flags |= PxMeshFlag::e16_BIT_INDICES;
+ }
+ else
+ {
+ meshDesc.triangles.stride = sizeof(PxU32)*3;
+ }
+
+ if(hasMatIndex)
+ {
+ PxMaterialTableIndex* materialIndices = new PxMaterialTableIndex[triCount];
+ for(PxU32 i = 0; i < triCount; i++)
+ materialIndices[i] = mesh->getTriangleMaterialIndex(i);
+
+ meshDesc.materialIndices.data = materialIndices;
+ meshDesc.materialIndices.stride = sizeof(PxMaterialTableIndex);
+
+ }
+
+ if(inArgs.cooker != NULL)
+ {
+ TMemoryPoolManager theManager(mAllocator);
+ MemoryBuffer theTempBuf( &theManager );
+ theTempBuf.clear();
+ inArgs.cooker->cookTriangleMesh( meshDesc, theTempBuf );
+
+ writeBuffer( inWriter, inTempBuffer, 16, theTempBuf.mBuffer, theTempBuf.mWriteOffset, "CookedData", writeDatatype<PxU8> );
+ }
+
+ delete []meshDesc.materialIndices.data;
+ }
+
+ PxRepXObject PxBVH34TriangleMeshRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/ )
+ {
+ //We can't do a simple inverse; we *have* to cook data to get a mesh.
+ PxTriangleMeshDesc theDesc;
+ readStridedBufferProperty<PxVec3>( inReader, "points", theDesc.points, inAllocator);
+ readStridedBufferProperty<Triangle<PxU32> >( inReader, "triangles", theDesc.triangles, inAllocator);
+ PxU32 triCount;
+ readStridedBufferProperty<PxMaterialTableIndex>( inReader, "materialIndices", theDesc.materialIndices, triCount, inAllocator);
+ PxStridedData cookedData;
+ cookedData.stride = sizeof(PxU8);
+ PxU32 dataSize;
+ readStridedBufferProperty<PxU8>( inReader, "CookedData", cookedData, dataSize, inAllocator);
+
+ TMemoryPoolManager theManager(inAllocator.getAllocator());
+ MemoryBuffer theTempBuf( &theManager );
+
+// PxTriangleMesh* theMesh = NULL;
+ PxBVH34TriangleMesh* theMesh = NULL;
+
+ if(dataSize != 0)
+ {
+ theTempBuf.write(cookedData.data, dataSize*sizeof(PxU8));
+// theMesh = inArgs.physics.createTriangleMesh( theTempBuf );
+ theMesh = static_cast<PxBVH34TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf ));
+ }
+
+ if(theMesh == NULL)
+ {
+ PX_ASSERT(inArgs.cooker);
+ theTempBuf.clear();
+
+ {
+ PxCookingParams params = inArgs.cooker->getParams();
+ params.midphaseDesc = PxMeshMidPhase::eBVH34;
+ inArgs.cooker->setParams(params);
+ }
+
+ inArgs.cooker->cookTriangleMesh( theDesc, theTempBuf );
+// theMesh = inArgs.physics.createTriangleMesh( theTempBuf );
+ theMesh = static_cast<PxBVH34TriangleMesh*>(inArgs.physics.createTriangleMesh( theTempBuf ));
+ }
+
+ return PxCreateRepXObject(theMesh);
+ }
+
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxHeightField
+ //*************************************************************
+ void PxHeightFieldRepXSerializer::objectToFileImpl( const PxHeightField* inHeightField, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
+ {
+ PxHeightFieldDesc theDesc;
+
+ theDesc.nbRows = inHeightField->getNbRows();
+ theDesc.nbColumns = inHeightField->getNbColumns();
+ theDesc.format = inHeightField->getFormat();
+ theDesc.samples.stride = inHeightField->getSampleStride();
+ theDesc.samples.data = NULL;
+ theDesc.thickness = inHeightField->getThickness();
+ theDesc.convexEdgeThreshold = inHeightField->getConvexEdgeThreshold();
+ theDesc.flags = inHeightField->getFlags();
+
+ PxU32 theCellCount = inHeightField->getNbRows() * inHeightField->getNbColumns();
+ PxU32 theSampleStride = sizeof( PxHeightFieldSample );
+ PxU32 theSampleBufSize = theCellCount * theSampleStride;
+ PxHeightFieldSample* theSamples = reinterpret_cast< PxHeightFieldSample*> ( inTempBuffer.mManager->allocate( theSampleBufSize ) );
+ inHeightField->saveCells( theSamples, theSampleBufSize );
+ theDesc.samples.data = theSamples;
+ writeAllProperties( &theDesc, inWriter, inTempBuffer, *inCollection );
+ writeStridedBufferProperty<PxHeightFieldSample>( inWriter, inTempBuffer, "samples", theDesc.samples, theDesc.nbRows * theDesc.nbColumns, 6, writeHeightFieldSample);
+ inTempBuffer.mManager->deallocate( reinterpret_cast<PxU8*>(theSamples) );
+ }
+
+ PxRepXObject PxHeightFieldRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
+ {
+ PX_ASSERT(inArgs.cooker);
+ PxHeightFieldDesc theDesc;
+ readAllProperties( inArgs, inReader, &theDesc, inAllocator, *inCollection );
+ //Now read the data...
+ PxU32 count = 0; //ignored becaues numRows and numColumns tells the story
+ readStridedBufferProperty<PxHeightFieldSample>( inReader, "samples", theDesc.samples, count, inAllocator);
+ PxHeightField* retval = inArgs.cooker->createHeightField( theDesc, inArgs.physics.getPhysicsInsertionCallback() );
+ return PxCreateRepXObject(retval);
+ }
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxConvexMesh
+ //*************************************************************
+ void PxConvexMeshRepXSerializer::objectToFileImpl( const PxConvexMesh* mesh, PxCollection* /*inCollection*/, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs )
+ {
+ writeBuffer( inWriter, inTempBuffer, 2, mesh->getVertices(), mesh->getNbVertices(), "points", writePxVec3 );
+
+ if(inArgs.cooker != NULL)
+ {
+ //Cache cooked Data
+ PxConvexMeshDesc theDesc;
+ theDesc.points.data = mesh->getVertices();
+ theDesc.points.stride = sizeof(PxVec3);
+ theDesc.points.count = mesh->getNbVertices();
+
+ theDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
+ TMemoryPoolManager theManager(mAllocator);
+ MemoryBuffer theTempBuf( &theManager );
+ inArgs.cooker->cookConvexMesh( theDesc, theTempBuf );
+
+ writeBuffer( inWriter, inTempBuffer, 16, theTempBuf.mBuffer, theTempBuf.mWriteOffset, "CookedData", writeDatatype<PxU8> );
+ }
+
+ }
+
+ //Conversion from scene object to descriptor.
+ PxRepXObject PxConvexMeshRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/)
+ {
+ PxConvexMeshDesc theDesc;
+ readStridedBufferProperty<PxVec3>( inReader, "points", theDesc.points, inAllocator);
+ theDesc.flags = PxConvexFlag::eCOMPUTE_CONVEX;
+
+ PxStridedData cookedData;
+ cookedData.stride = sizeof(PxU8);
+ PxU32 dataSize;
+ readStridedBufferProperty<PxU8>( inReader, "CookedData", cookedData, dataSize, inAllocator);
+
+ TMemoryPoolManager theManager(inAllocator.getAllocator());
+ MemoryBuffer theTempBuf( &theManager );
+
+ PxConvexMesh* theMesh = NULL;
+
+ if(dataSize != 0)
+ {
+ theTempBuf.write(cookedData.data, dataSize*sizeof(PxU8));
+ theMesh = inArgs.physics.createConvexMesh( theTempBuf );
+ }
+
+ if(theMesh == NULL)
+ {
+ PX_ASSERT(inArgs.cooker);
+ theTempBuf.clear();
+
+ inArgs.cooker->cookConvexMesh( theDesc, theTempBuf );
+ theMesh = inArgs.physics.createConvexMesh( theTempBuf );
+ }
+
+ return PxCreateRepXObject(theMesh);
+ }
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxRigidStatic
+ //*************************************************************
+ PxRigidStatic* PxRigidStaticRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs )
+ {
+ return inArgs.physics.createRigidStatic( PxTransform(PxIdentity) );
+ }
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxRigidDynamic
+ //*************************************************************
+ PxRigidDynamic* PxRigidDynamicRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs )
+ {
+ return inArgs.physics.createRigidDynamic( PxTransform(PxIdentity) );
+ }
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxArticulation
+ //*************************************************************
+ void PxArticulationRepXSerializer::objectToFileImpl( const PxArticulation* inObj, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
+ {
+ TNameStack nameStack( inTempBuffer.mManager->mWrapper );
+ Sn::TArticulationLinkLinkMap linkMap( inTempBuffer.mManager->mWrapper );
+ RepXVisitorWriter<PxArticulation> writer( nameStack, inWriter, inObj, inTempBuffer, *inCollection, &linkMap );
+ RepXPropertyFilter<RepXVisitorWriter<PxArticulation> > theOp( writer );
+ visitAllProperties<PxArticulation>( theOp );
+ }
+ PxArticulation* PxArticulationRepXSerializer::allocateObject( PxRepXInstantiationArgs& inArgs ) { return inArgs.physics.createArticulation(); }
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxAggregate
+ //*************************************************************
+ void PxAggregateRepXSerializer::objectToFileImpl( const PxAggregate* data, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
+ {
+ PxArticulationLink *link = NULL;
+ inWriter.addAndGotoChild( "Actors" );
+ for(PxU32 i = 0; i < data->getNbActors(); ++i)
+ {
+ PxActor* actor;
+
+ if(data->getActors(&actor, 1, i))
+ {
+ link = actor->is<PxArticulationLink>();
+ }
+
+ if(link && !link->getInboundJoint() )
+ {
+ writeProperty( inWriter, *inCollection, inTempBuffer, "PxArticulationRef", &link->getArticulation());
+ }
+ else if( !link )
+ {
+ PxSerialObjectId theId = 0;
+
+ theId = inCollection->getId( *actor );
+ if( theId == 0 )
+ theId = PX_PROFILE_POINTER_TO_U64( actor );
+
+ writeProperty( inWriter, *inCollection, inTempBuffer, "PxActorRef", theId );
+ }
+ }
+
+ inWriter.leaveChild( );
+
+ writeProperty( inWriter, *inCollection, inTempBuffer, "NumActors", data->getNbActors() );
+ writeProperty( inWriter, *inCollection, inTempBuffer, "MaxNbActors", data->getMaxNbActors() );
+ writeProperty( inWriter, *inCollection, inTempBuffer, "SelfCollision", data->getSelfCollision() );
+
+ writeAllProperties( data, inWriter, inTempBuffer, *inCollection );
+ }
+
+ PxRepXObject PxAggregateRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
+ {
+ PxU32 numActors;
+ readProperty( inReader, "NumActors", numActors );
+ PxU32 maxNbActors;
+ readProperty( inReader, "MaxNbActors", maxNbActors );
+
+ bool selfCollision;
+ bool ret = readProperty( inReader, "SelfCollision", selfCollision );
+
+ PxAggregate* theAggregate = inArgs.physics.createAggregate(maxNbActors, selfCollision);
+ ret &= readAllProperties( inArgs, inReader, theAggregate, inAllocator, *inCollection );
+
+ inReader.pushCurrentContext();
+ if ( inReader.gotoChild( "Actors" ) )
+ {
+ inReader.pushCurrentContext();
+ for( bool matSuccess = inReader.gotoFirstChild(); matSuccess;
+ matSuccess = inReader.gotoNextSibling() )
+ {
+ const char* actorType = inReader.getCurrentItemName();
+ if ( 0 == physx::shdfnd::stricmp( actorType, "PxActorRef" ) )
+ {
+ PxActor *actor = NULL;
+ ret &= readReference<PxActor>( inReader, *inCollection, actor );
+
+ if(actor)
+ {
+ PxScene *currScene = actor->getScene();
+ if(currScene)
+ {
+ currScene->removeActor(*actor);
+ }
+ theAggregate->addActor(*actor);
+ }
+ }
+ else if ( 0 == physx::shdfnd::stricmp( actorType, "PxArticulationRef" ) )
+ {
+ PxArticulation* articulation = NULL;
+ ret &= readReference<PxArticulation>( inReader, *inCollection, articulation );
+ if(articulation)
+ {
+ PxScene *currScene = articulation->getScene();
+ if(currScene)
+ {
+ currScene->removeArticulation(*articulation);
+ }
+ theAggregate->addArticulation(*articulation);
+ }
+ }
+ }
+ inReader.popCurrentContext();
+ inReader.leaveChild();
+ }
+ inReader.popCurrentContext();
+
+ return ret ? PxCreateRepXObject(theAggregate) : PxRepXObject();
+ }
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxClothFabric
+ //*************************************************************
+#if PX_USE_CLOTH_API
+
+ void writeFabricPhase( PxOutputStream& stream, const PxClothFabricPhase& phase )
+ {
+ const PxU32ToName* conv = PxEnumTraits<PxClothFabricPhaseType::Enum>().NameConversion;
+ for ( ; conv->mName != NULL; ++conv )
+ if ( conv->mValue == PxU32(phase.phaseType) )
+ stream << conv->mName;
+ stream << " " << phase.setIndex;
+ }
+
+ namespace Sn {
+ template<> struct StrToImpl<PxClothFabricPhase>
+ {
+ void strto( PxClothFabricPhase& datatype, const char*& ioData )
+ {
+ char buffer[512];
+ eatwhite( ioData );
+ nullTerminateWhite(ioData, buffer, 512 );
+
+ const PxU32ToName* conv = PxEnumTraits<PxClothFabricPhaseType::Enum>().NameConversion;
+ for ( ; conv->mName != NULL; ++conv )
+ if ( 0 == physx::shdfnd::stricmp( buffer, conv->mName ) )
+ datatype = static_cast<PxClothFabricPhaseType::Enum>( conv->mValue );
+
+ StrToImpl<PxU32>().strto( datatype.setIndex, ioData );
+ }
+ };
+ }
+
+ void PxClothFabricRepXSerializer::objectToFileImpl( const PxClothFabric* data, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
+ {
+
+ PxProfileAllocatorWrapper& wrapper( inTempBuffer.mManager->getWrapper() );
+ PxU32 numParticles = data->getNbParticles();
+ PxU32 numPhases = data->getNbPhases();
+ PxU32 numRestvalues = data->getNbRestvalues();
+ PxU32 numSets = data->getNbSets();
+ PxU32 numIndices = data->getNbParticleIndices();
+ PxU32 numTethers = data->getNbTethers();
+
+ PxProfileArray<PxU8> dataBuffer( wrapper );
+ PxU32 numInts = PxMax(PxMax(numIndices, numRestvalues), numTethers);
+ dataBuffer.resize( PxU32(PxMax( PxMax( numInts * sizeof(PxU32), numTethers * sizeof(PxReal) ),
+ numPhases * sizeof(PxClothFabricPhase)) ) );
+
+ PxClothFabricPhase* phasePtr( reinterpret_cast<PxClothFabricPhase*>( dataBuffer.begin() ) );
+ PxU32* indexPtr( reinterpret_cast<PxU32*>( dataBuffer.begin() ) );
+
+ writeProperty( inWriter, *inCollection, inTempBuffer, "NbParticles", numParticles );
+
+ data->getPhases( phasePtr, numPhases );
+ writeBuffer( inWriter, inTempBuffer, 18, phasePtr, PtrAccess<PxClothFabricPhase>, numPhases, "Phases", writeFabricPhase );
+
+ PX_COMPILE_TIME_ASSERT( sizeof( PxReal ) == sizeof( PxU32 ) );
+ PxReal* realPtr = reinterpret_cast< PxReal* >( indexPtr );
+ data->getRestvalues( realPtr, numRestvalues );
+ writeBuffer( inWriter, inTempBuffer, 18, realPtr, PtrAccess<PxReal>, numRestvalues, "Restvalues", BasicDatatypeWrite<PxReal> );
+
+ data->getSets( indexPtr, numSets );
+ writeBuffer( inWriter, inTempBuffer, 18, indexPtr, PtrAccess<PxU32>, numSets, "Sets", BasicDatatypeWrite<PxU32> );
+
+ data->getParticleIndices( indexPtr, numIndices );
+ writeBuffer( inWriter, inTempBuffer, 18, indexPtr, PtrAccess<PxU32>, numIndices, "ParticleIndices", BasicDatatypeWrite<PxU32> );
+
+ data->getTetherAnchors( indexPtr, numTethers );
+ writeBuffer( inWriter, inTempBuffer, 18, indexPtr, PtrAccess<PxU32>, numTethers, "TetherAnchors", BasicDatatypeWrite<PxU32> );
+
+ data->getTetherLengths( realPtr, numTethers );
+ writeBuffer( inWriter, inTempBuffer, 18, realPtr, PtrAccess<PxReal>, numTethers, "TetherLengths", BasicDatatypeWrite<PxReal> );
+ }
+
+ //Conversion from scene object to descriptor.
+ PxRepXObject PxClothFabricRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* /*inCollection*/)
+ {
+ PxU32 strideIgnored = 0;
+
+ PxClothFabricDesc desc;
+
+ readProperty( inReader, "NbParticles", desc.nbParticles );
+
+ readStridedBufferProperty<PxClothFabricPhase>( inReader, "Phases", const_cast<PxClothFabricPhase*&>(desc.phases), strideIgnored, desc.nbPhases, inAllocator );
+
+ PxU32 numRestvalues = 0;
+ readStridedBufferProperty<PxF32>( inReader, "Restvalues", const_cast<PxF32*&>(desc.restvalues), strideIgnored, numRestvalues, inAllocator );
+
+ readStridedBufferProperty<PxU32>( inReader, "Sets", const_cast<PxU32*&>(desc.sets), strideIgnored, desc.nbSets, inAllocator );
+
+ PxU32 numIndices = 0;
+ readStridedBufferProperty<PxU32>( inReader, "ParticleIndices", const_cast<PxU32*&>(desc.indices), strideIgnored, numIndices, inAllocator );
+
+ readStridedBufferProperty<PxU32>( inReader, "TetherAnchors", const_cast<PxU32*&>(desc.tetherAnchors), strideIgnored, desc.nbTethers, inAllocator );
+ readStridedBufferProperty<PxF32>( inReader, "TetherLengths", const_cast<PxF32*&>(desc.tetherLengths), strideIgnored, desc.nbTethers, inAllocator );
+
+ PxClothFabric* newFabric = inArgs.physics.createClothFabric( desc );
+
+ PX_ASSERT( newFabric );
+ return PxCreateRepXObject(newFabric);
+ }
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxCloth
+ //*************************************************************
+ void clothParticleWriter( PxOutputStream& stream, const PxClothParticle& particle )
+ {
+ stream << particle.pos << " " << particle.invWeight;
+ }
+
+ namespace Sn {
+ template<> struct StrToImpl<PxClothParticle>
+ {
+ void strto( PxClothParticle& datatype, const char*& ioData )
+ {
+ StrToImpl<PxF32>().strto( datatype.pos[0], ioData );
+ StrToImpl<PxF32>().strto( datatype.pos[1], ioData );
+ StrToImpl<PxF32>().strto( datatype.pos[2], ioData );
+ StrToImpl<PxF32>().strto( datatype.invWeight, ioData );
+ }
+ };
+
+ template<> struct StrToImpl<PxClothCollisionSphere>
+ {
+ void strto( PxClothCollisionSphere& datatype, const char*& ioData )
+ {
+ StrToImpl<PxF32>().strto( datatype.pos[0], ioData );
+ StrToImpl<PxF32>().strto( datatype.pos[1], ioData );
+ StrToImpl<PxF32>().strto( datatype.pos[2], ioData );
+ StrToImpl<PxF32>().strto( datatype.radius, ioData );
+ }
+ };
+
+ template<> struct StrToImpl<PxClothCollisionPlane>
+ {
+ void strto( PxClothCollisionPlane& datatype, const char*& ioData )
+ {
+ StrToImpl<PxF32>().strto( datatype.normal[0], ioData );
+ StrToImpl<PxF32>().strto( datatype.normal[1], ioData );
+ StrToImpl<PxF32>().strto( datatype.normal[2], ioData );
+ StrToImpl<PxF32>().strto( datatype.distance, ioData );
+ }
+ };
+
+ template<> struct StrToImpl<PxClothCollisionTriangle>
+ {
+ void strto( PxClothCollisionTriangle& datatype, const char*& ioData )
+ {
+ StrToImpl<PxVec3>().strto( datatype.vertex0, ioData );
+ StrToImpl<PxVec3>().strto( datatype.vertex1, ioData );
+ StrToImpl<PxVec3>().strto( datatype.vertex2, ioData );
+ }
+ };
+
+ template<> struct StrToImpl<PxVec4>
+ {
+ void strto( PxVec4& datatype, const char*& ioData )
+ {
+ StrToImpl<PxF32>().strto( datatype.x, ioData );
+ StrToImpl<PxF32>().strto( datatype.y, ioData );
+ StrToImpl<PxF32>().strto( datatype.z, ioData );
+ StrToImpl<PxF32>().strto( datatype.w, ioData );
+ }
+ };
+
+ template<> struct StrToImpl<PxClothParticleMotionConstraint>
+ {
+ void strto( PxClothParticleMotionConstraint& datatype, const char*& ioData )
+ {
+ StrToImpl<PxVec3>().strto( datatype.pos, ioData );
+ StrToImpl<PxF32>().strto( datatype.radius, ioData );
+ }
+ };
+
+ template<> struct StrToImpl<PxClothParticleSeparationConstraint>
+ {
+ void strto( PxClothParticleSeparationConstraint& datatype, const char*& ioData )
+ {
+ StrToImpl<PxVec3>().strto( datatype.pos, ioData );
+ StrToImpl<PxF32>().strto( datatype.radius, ioData );
+ }
+ };
+
+ }
+
+ void clothSphereWriter( PxOutputStream& stream, const PxClothCollisionSphere& sphere )
+ {
+ stream << sphere.pos << " " << sphere.radius;
+ }
+
+ void clothPlaneWriter( PxOutputStream& stream, const PxClothCollisionPlane& plane )
+ {
+ stream << plane.normal << " " << plane.distance;
+ }
+
+ void clothTriangleWriter( PxOutputStream& stream, const PxClothCollisionTriangle& triangle )
+ {
+ stream << triangle.vertex0 << " " << triangle.vertex1 << " " << triangle.vertex2;
+ }
+
+ void PxClothRepXSerializer::objectToFileImpl( const PxCloth* data, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
+ {
+ PxClothParticleData* readData( data->lockParticleData() );
+ writeBuffer( inWriter, inTempBuffer, 4, readData->particles, PtrAccess<PxClothParticle>, data->getNbParticles(), "Particles", clothParticleWriter );
+ readData->unlock();
+
+ writeReference( inWriter, *inCollection, "Fabric", data->getFabric() );
+
+ PxProfileArray<PxU8> dataBuffer( inTempBuffer.mManager->getWrapper() );
+
+ // collision data
+ const PxCloth& cloth = *data;
+ 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);
+
+ dataBuffer.resize( sphereBytes + pairBytes + planesBytes + convexBytes + triangleBytes);
+ PxClothCollisionSphere* spheresBuffer = reinterpret_cast<PxClothCollisionSphere*>( dataBuffer.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);
+
+ data->getCollisionData( spheresBuffer, indexBuffer, planeBuffer, convexBuffer, trianglesBuffer );
+ writeBuffer( inWriter, inTempBuffer, 4, spheresBuffer, PtrAccess<PxClothCollisionSphere>, numSpheres, "CollisionSpheres", clothSphereWriter );
+ writeBuffer( inWriter, inTempBuffer, 18, indexBuffer, PtrAccess<PxU32>, numIndices, "CollisionSpherePairs", BasicDatatypeWrite<PxU32> );
+ writeBuffer( inWriter, inTempBuffer, 4, planeBuffer, PtrAccess<PxClothCollisionPlane>, numPlanes, "CollisionPlanes", clothPlaneWriter );
+ writeBuffer( inWriter, inTempBuffer, 18, convexBuffer, PtrAccess<PxU32>, numConvexes, "CollisionConvexMasks", BasicDatatypeWrite<PxU32> );
+ writeBuffer( inWriter, inTempBuffer, 4, trianglesBuffer, PtrAccess<PxClothCollisionTriangle>, numTriangles, "CollisionTriangles", clothTriangleWriter );
+
+ // particle accelerations
+ PxU32 numParticleAccelerations = cloth.getNbParticleAccelerations();
+ PxU32 sizeParticleAccelerations = sizeof(PxVec4)*numParticleAccelerations;
+ if (dataBuffer.size() < sizeParticleAccelerations)
+ dataBuffer.resize(sizeof(PxClothParticle)*numParticleAccelerations);
+
+ PxVec4* particleAccelerations = reinterpret_cast<PxVec4*>(dataBuffer.begin());
+ cloth.getParticleAccelerations(particleAccelerations);
+ writeBuffer (inWriter, inTempBuffer, 4, reinterpret_cast<PxClothParticle*>(particleAccelerations), PtrAccess<PxClothParticle>, numParticleAccelerations, "ParticleAccelerations", clothParticleWriter );
+
+ //self collision indices
+ PxU32* particleCollisionIndices = reinterpret_cast<PxU32*>(dataBuffer.begin());
+ PxU32 numSelfCollisionIndices = cloth.getNbSelfCollisionIndices();
+ PxU32 sizeSelfCollisionIndices = sizeof(PxU32)*numSelfCollisionIndices;
+ if (dataBuffer.size() < sizeSelfCollisionIndices)
+ dataBuffer.resize(sizeSelfCollisionIndices);
+ data->getSelfCollisionIndices( particleCollisionIndices );
+ writeBuffer( inWriter, inTempBuffer, 18, particleCollisionIndices, PtrAccess<PxU32>, numSelfCollisionIndices, "SelfCollisionIndices", BasicDatatypeWrite<PxU32> );
+
+ // motion constraints
+ PxClothParticleMotionConstraint* motionConstraints = reinterpret_cast<PxClothParticleMotionConstraint*>(dataBuffer.begin());
+ PxU32 numMotionConstraints = cloth.getNbMotionConstraints();
+ PxU32 sizeMotionConstraints = sizeof(PxVec4)*numMotionConstraints;
+ if (dataBuffer.size() < sizeMotionConstraints)
+ dataBuffer.resize(sizeof(PxClothParticle)*numMotionConstraints);
+ data->getMotionConstraints( motionConstraints );
+ writeBuffer (inWriter, inTempBuffer, 4, reinterpret_cast<PxClothParticle*>(motionConstraints), PtrAccess<PxClothParticle>, numMotionConstraints, "MotionConstraints", clothParticleWriter );
+
+ // separation positions
+ PxU32 numSeparationConstraints= cloth.getNbSeparationConstraints();
+ PxU32 restSeparationConstraints = sizeof(PxVec4)*numSeparationConstraints;
+ if (dataBuffer.size() < restSeparationConstraints)
+ dataBuffer.resize(sizeof(PxClothParticle)*numSeparationConstraints);
+ PxClothParticleSeparationConstraint* separationConstraints = reinterpret_cast<PxClothParticleSeparationConstraint*>(dataBuffer.begin());
+ cloth.getSeparationConstraints(separationConstraints);
+ writeBuffer (inWriter, inTempBuffer, 4, reinterpret_cast<PxClothParticle*>(separationConstraints), PtrAccess<PxClothParticle>, numSeparationConstraints, "SeparationConstraints", clothParticleWriter );
+
+ // rest positions
+ PxU32 numRestPositions = cloth.getNbRestPositions();
+ PxU32 restPositionSize = sizeof(PxVec4)*numRestPositions;
+ if (dataBuffer.size() < restPositionSize)
+ dataBuffer.resize(sizeof(PxClothParticle)*numRestPositions);
+
+ PxVec4* restPositions = reinterpret_cast<PxVec4*>(dataBuffer.begin());
+ cloth.getRestPositions(restPositions);
+ writeBuffer (inWriter, inTempBuffer, 4, reinterpret_cast<PxClothParticle*>(restPositions), PtrAccess<PxClothParticle>, numRestPositions, "RestPositions", clothParticleWriter );
+
+ // virtual particles
+ PxU32 numVirtualParticles = data->getNbVirtualParticles();
+ PxU32 numWeightTableEntries = data->getNbVirtualParticleWeights();
+
+ PxU32 totalNeeded = static_cast<PxU32>( PxMax( numWeightTableEntries * sizeof( PxVec3 ), numVirtualParticles * 4 * sizeof( PxU32 ) ) );
+ if ( dataBuffer.size() < totalNeeded )
+ dataBuffer.resize( totalNeeded );
+
+ PxVec3* weightTableEntries = reinterpret_cast<PxVec3*>( dataBuffer.begin() );
+ data->getVirtualParticleWeights( weightTableEntries );
+ writeBuffer( inWriter, inTempBuffer, 6, weightTableEntries, PtrAccess<PxVec3>, numWeightTableEntries, "VirtualParticleWeights", BasicDatatypeWrite<PxVec3> );
+ PxU32* virtualParticles = reinterpret_cast<PxU32*>( dataBuffer.begin() );
+ data->getVirtualParticles( virtualParticles );
+ writeBuffer( inWriter, inTempBuffer, 18, virtualParticles, PtrAccess<PxU32>, numVirtualParticles * 4, "VirtualParticles", BasicDatatypeWrite<PxU32> );
+
+ // Now write the rest of the object data that the meta data generator got.
+ writeAllProperties( data, inWriter, inTempBuffer, *inCollection );
+ }
+
+ PxRepXObject PxClothRepXSerializer::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
+ {
+ PxU32 strideIgnored;
+ PxU32 numParticles;
+ PxClothParticle* particles = NULL;
+
+ PxU32 numSpheres;
+ PxClothCollisionSphere* spheres = NULL;
+ PxU32 numCapsules;
+ PxU32* capsules = NULL;
+ PxU32 numPlanes;
+ PxClothCollisionPlane* planes = NULL;
+ PxU32 numConvexMasks;
+ PxU32* convexMasks = NULL;
+ PxU32 numTriangles;
+ PxClothCollisionTriangle* triangles = NULL;
+
+ PxVec4* particleAccelerations = NULL;
+ PxU32 numParticleAccelerations = 0;
+ PxU32* selfCollisionIndices = NULL;
+ PxU32 numSelfCollisionIndices = 0;
+ PxClothParticleMotionConstraint* particleMotionConstraint = NULL;
+ PxU32 numParticleMotionConstraint = 0;
+ PxClothParticleSeparationConstraint* separationConstraints = NULL;
+ PxU32 numSeparationConstraints = 0;
+
+ PxVec4* restPositions = NULL;
+ PxU32 numRestPositions;
+ PxU32 numVirtualParticleWeights;
+ PxU32 numParticleIndices = 0;
+ PxVec3* virtualParticleWeights = NULL;
+ PxU32* virtualParticles = NULL;
+ PxClothFlags flags;
+ PxClothFabric* fabric = NULL;
+
+ readReference<PxClothFabric>( inReader, *inCollection, "Fabric", fabric );
+
+ if ( fabric == NULL )
+ return PxRepXObject();
+
+ readStridedBufferProperty<PxClothParticle>( inReader, "Particles", particles, strideIgnored, numParticles, inAllocator );
+
+ readStridedBufferProperty<PxClothCollisionSphere>( inReader, "CollisionSpheres", spheres, strideIgnored, numSpheres, inAllocator );
+ readStridedBufferProperty<PxU32>( inReader, "CollisionSpherePairs", capsules, strideIgnored, numCapsules, inAllocator );
+ readStridedBufferProperty<PxClothCollisionPlane>( inReader, "CollisionPlanes", planes, strideIgnored, numPlanes, inAllocator );
+ readStridedBufferProperty<PxU32>( inReader, "CollisionConvexMasks", convexMasks, strideIgnored, numConvexMasks, inAllocator );
+ readStridedBufferProperty<PxClothCollisionTriangle>( inReader, "CollisionTriangles", triangles, strideIgnored, numTriangles, inAllocator );
+
+ readFlagsProperty( inReader, inAllocator, "ClothFlags", PxEnumTraits<PxClothFlag::Enum>().NameConversion, flags );
+
+ readStridedBufferProperty<PxVec4>( inReader, "ParticleAccelerations", particleAccelerations, strideIgnored, numParticleAccelerations, inAllocator );
+ readStridedBufferProperty<PxU32>( inReader, "SelfCollisionIndices", selfCollisionIndices, strideIgnored, numSelfCollisionIndices, inAllocator );
+ readStridedBufferProperty<PxClothParticleMotionConstraint>( inReader, "MotionConstraints", particleMotionConstraint, strideIgnored, numParticleMotionConstraint, inAllocator );
+ readStridedBufferProperty<PxClothParticleSeparationConstraint>( inReader, "SeparationConstraints", separationConstraints, strideIgnored, numSeparationConstraints, inAllocator );
+ readStridedBufferProperty<PxVec4>( inReader, "RestPositions", restPositions, strideIgnored, numRestPositions, inAllocator );
+
+ readStridedBufferProperty<PxVec3>( inReader, "VirtualParticleWeights", virtualParticleWeights, strideIgnored, numVirtualParticleWeights, inAllocator );
+ readStridedBufferProperty<PxU32>( inReader, "VirtualParticles", virtualParticles, strideIgnored, numParticleIndices, inAllocator );
+
+ PxTransform initialPose( PxIdentity );
+ PxCloth* cloth = inArgs.physics.createCloth( initialPose, *fabric, reinterpret_cast<PxClothParticle*>( particles ), flags );
+ bool ret = readAllProperties( inArgs, inReader, cloth, inAllocator, *inCollection );
+
+ if( numSelfCollisionIndices )
+ {
+ cloth->setSelfCollisionIndices( selfCollisionIndices, numSelfCollisionIndices );
+ }
+ if( numParticleMotionConstraint )
+ {
+ cloth->setMotionConstraints( particleMotionConstraint );
+ }
+ if( numSeparationConstraints )
+ {
+ cloth->setSeparationConstraints( separationConstraints );
+ }
+ if( numParticleAccelerations )
+ {
+ cloth->setParticleAccelerations(particleAccelerations);
+ }
+
+ cloth->setCollisionSpheres(spheres, numSpheres);
+ while(numCapsules > 0)
+ {
+ PxU32 first = *capsules++, second = *capsules++;
+ cloth->addCollisionCapsule(first, second);
+ numCapsules -= 2;
+ }
+
+ cloth->setCollisionPlanes(planes, numPlanes);
+ while(numConvexMasks-- > 0)
+ {
+ cloth->addCollisionConvex(*convexMasks++);
+ }
+
+ cloth->setCollisionTriangles(triangles, numTriangles);
+
+ if (numRestPositions)
+ cloth->setRestPositions(restPositions);
+
+ PxU32 numVirtualParticles = numParticleIndices /4;
+ if ( numVirtualParticles && numVirtualParticleWeights )
+ {
+ cloth->setVirtualParticles( numVirtualParticles, reinterpret_cast<PxU32*>( virtualParticles ),
+ numVirtualParticleWeights, reinterpret_cast<PxVec3*>( virtualParticleWeights ) );
+ }
+
+ return ret ? PxCreateRepXObject(cloth) : PxRepXObject();
+ }
+#endif // PX_USE_CLOTH_API
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ template<typename TParticleType>
+ inline TParticleType* createParticles( PxPhysics& physics, PxU32 maxParticles, bool perParticleRestOffset )
+ {
+ PX_UNUSED(physics);
+ PX_UNUSED(maxParticles);
+ PX_UNUSED(perParticleRestOffset);
+ return NULL;
+ }
+
+ template<>
+ inline PxParticleSystem* createParticles<PxParticleSystem>(PxPhysics& physics, PxU32 maxParticles, bool perParticleRestOffset)
+ {
+ return physics.createParticleSystem( maxParticles, perParticleRestOffset );
+ }
+
+ template<>
+ inline PxParticleFluid* createParticles<PxParticleFluid>(PxPhysics& physics, PxU32 maxParticles, bool perParticleRestOffset)
+ {
+ return physics.createParticleFluid( maxParticles, perParticleRestOffset );
+ }
+
+ //*************************************************************
+ // Actual RepXSerializer implementations for PxParticleSystem & PxParticleFluid
+ //*************************************************************
+ template<typename TParticleType>
+ void PxParticleRepXSerializer<TParticleType>::objectToFileImpl( const TParticleType* data, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
+ {
+ PxParticleReadData* readData( const_cast<TParticleType*>( data )->lockParticleReadData() );
+ writeProperty( inWriter, *inCollection, inTempBuffer, "NbParticles", readData->nbValidParticles );
+ writeProperty( inWriter, *inCollection, inTempBuffer, "ValidParticleRange", readData->validParticleRange );
+ PxParticleReadDataFlags readFlags(data->getParticleReadDataFlags());
+
+ if(readData->validParticleRange > 0)
+ {
+ writeBuffer( inWriter, inTempBuffer, 8 , readData->validParticleBitmap, PtrAccess<PxU32>, ((readData->validParticleRange-1) >> 5) + 1 ,"ValidParticleBitmap", BasicDatatypeWrite<PxU32> );
+
+ writeStridedBufferProperty<PxVec3>( inWriter, inTempBuffer, "Positions", readData->positionBuffer, readData->nbValidParticles, 6, writePxVec3);
+
+ if(readFlags & PxParticleReadDataFlag::eVELOCITY_BUFFER)
+ {
+ writeStridedBufferProperty<PxVec3>( inWriter, inTempBuffer, "Velocities", readData->velocityBuffer, readData->nbValidParticles, 6, writePxVec3);
+ }
+ if(readFlags & PxParticleReadDataFlag::eREST_OFFSET_BUFFER)
+ {
+ writeStridedBufferProperty<PxF32>( inWriter, inTempBuffer, "RestOffsets", readData->restOffsetBuffer, readData->nbValidParticles, 6, BasicDatatypeWrite<PxF32>);
+ }
+ if(readFlags & PxParticleReadDataFlag::eFLAGS_BUFFER)
+ {
+ writeStridedFlagsProperty<PxParticleFlags>( inWriter, inTempBuffer, "Flags", readData->flagsBuffer, readData->nbValidParticles, 6, PxEnumTraits<PxParticleFlag::Enum>().NameConversion);
+ }
+ }
+ readData->unlock();
+
+ writeProperty( inWriter, *inCollection, inTempBuffer, "MaxParticles", data->getMaxParticles() );
+
+ PxParticleBaseFlags baseFlags(data->getParticleBaseFlags());
+ writeFlagsProperty( inWriter, inTempBuffer, "ParticleBaseFlags", baseFlags, PxEnumTraits<PxParticleBaseFlag::Enum>().NameConversion );
+
+ writeFlagsProperty( inWriter, inTempBuffer, "ParticleReadDataFlags", readFlags, PxEnumTraits<PxParticleReadDataFlag::Enum>().NameConversion );
+
+ PxVec3 normal;
+ PxReal distance;
+ data->getProjectionPlane(normal, distance);
+ PxMetaDataPlane plane(normal, distance);
+ writeProperty( inWriter, *inCollection, inTempBuffer, "ProjectionPlane", plane);
+
+ writeAllProperties( data, inWriter, inTempBuffer, *inCollection );
+ }
+
+ template<typename TParticleType>
+ PxRepXObject PxParticleRepXSerializer<TParticleType>::fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
+ {
+ PxU32 strideIgnored = 0;
+ PxU32 numParticles = 0;
+ readProperty( inReader, "NbParticles", numParticles );
+
+ PxU32 validParticleRange = 0;
+ readProperty( inReader, "ValidParticleRange", validParticleRange );
+
+ PxU32 numWrite;
+ PxU32* tempValidParticleBitmap = NULL;
+ readStridedBufferProperty<PxU32>( inReader, "ValidParticleBitmap", tempValidParticleBitmap, strideIgnored, numWrite, inAllocator );
+ PxU32 *validParticleBitmap = reinterpret_cast<PxU32*>( tempValidParticleBitmap );
+
+ PxVec3* tempPosBuf = NULL;
+ readStridedBufferProperty<PxVec3>( inReader, "Positions", tempPosBuf, strideIgnored, numWrite, inAllocator );
+ PxStrideIterator<const PxVec3> posBuffer(reinterpret_cast<const PxVec3*> (tempPosBuf));
+
+ PxVec3* tempVelBuf = NULL;
+ readStridedBufferProperty<PxVec3>( inReader, "Velocities", tempVelBuf, strideIgnored, numWrite, inAllocator );
+ PxStrideIterator<const PxVec3> velBuffer(reinterpret_cast<const PxVec3*> (tempVelBuf));
+
+ PxF32* tempRestBuf = NULL;
+ readStridedBufferProperty<PxF32>( inReader, "RestOffsets", tempRestBuf, strideIgnored, numWrite, inAllocator );
+ PxStrideIterator<const PxF32> restBuffer(reinterpret_cast<const PxF32*> (tempRestBuf));
+
+ PxU32* tempFlagBuf = NULL;
+ readStridedFlagsProperty<PxU32>( inReader, "Flags", tempFlagBuf, strideIgnored, numWrite, inAllocator , PxEnumTraits<PxParticleFlag::Enum>().NameConversion);
+ PxStrideIterator<const PxU32> flagBuffer(reinterpret_cast<const PxU32*> (tempFlagBuf));
+
+ Ps::Array<PxU32> validIndexBuf;
+ Ps::Array<PxVec3> validPosBuf, validVelBuf;
+ Ps::Array<PxF32> validRestBuf;
+ Ps::Array<PxU32> validFlagBuf;
+
+ bool perParticleRestOffset = !!tempRestBuf;
+ bool bVelBuff = !!tempVelBuf;
+ bool bFlagBuff = !!tempFlagBuf;
+
+ if (validParticleRange > 0)
+ {
+ for (PxU32 w = 0; w <= (validParticleRange-1) >> 5; w++)
+ {
+ for (PxU32 b = validParticleBitmap[w]; b; b &= b-1)
+ {
+ PxU32 index = (w<<5|physx::shdfnd::lowestSetBit(b));
+ validIndexBuf.pushBack(index);
+ validPosBuf.pushBack(posBuffer[index]);
+ if(bVelBuff)
+ validVelBuf.pushBack(velBuffer[index]);
+ if(perParticleRestOffset)
+ validRestBuf.pushBack(restBuffer[index]);
+ if(bFlagBuff)
+ validFlagBuf.pushBack(flagBuffer[index]);
+ }
+ }
+
+ PX_ASSERT(validIndexBuf.size() == numParticles);
+
+ PxU32 maxParticleNum;
+ bool ret = readProperty( inReader, "MaxParticles", maxParticleNum );
+ TParticleType* theParticle( createParticles<TParticleType>( inArgs.physics, maxParticleNum, perParticleRestOffset ) );
+ PX_ASSERT( theParticle );
+ ret &= readAllProperties( inArgs, inReader, theParticle, inAllocator, *inCollection );
+
+ PxParticleBaseFlags baseFlags;
+ ret &= readFlagsProperty( inReader, inAllocator, "ParticleBaseFlags", PxEnumTraits<PxParticleBaseFlag::Enum>().NameConversion, baseFlags );
+
+ PxU32 flagData = 1;
+ for(PxU32 i = 0; i < 16; i++)
+ {
+ flagData = PxU32(1 << i);
+ if( !(flagData & PxParticleBaseFlag::ePER_PARTICLE_REST_OFFSET) && (!!(PxU32(baseFlags) & flagData)) )
+ {
+ theParticle->setParticleBaseFlag(PxParticleBaseFlag::Enum(flagData), true);
+ }
+ }
+
+ PxParticleReadDataFlags readFlags;
+ ret &= readFlagsProperty( inReader, inAllocator, "ParticleReadDataFlags", PxEnumTraits<PxParticleReadDataFlag::Enum>().NameConversion, readFlags );
+ for(PxU32 i = 0; i < 16; i++)
+ {
+ flagData = PxU32(1 << i);
+ if( !!(PxU32(readFlags) & flagData) )
+ {
+ theParticle->setParticleReadDataFlag(PxParticleReadDataFlag::Enum(flagData), true);
+ }
+ }
+
+ PxParticleCreationData creationData;
+ creationData.numParticles = numParticles;
+ creationData.indexBuffer = PxStrideIterator<const PxU32>(validIndexBuf.begin());
+ creationData.positionBuffer = PxStrideIterator<const PxVec3>(validPosBuf.begin());
+ if(bVelBuff)
+ creationData.velocityBuffer = PxStrideIterator<const PxVec3>(validVelBuf.begin());
+ if(perParticleRestOffset)
+ creationData.restOffsetBuffer = PxStrideIterator<const PxF32>(validRestBuf.begin());
+ if(bFlagBuff)
+ creationData.flagBuffer = PxStrideIterator<const PxU32>(validFlagBuf.begin());
+
+ theParticle->createParticles(creationData);
+
+ return ret ? PxCreateRepXObject(theParticle) : PxRepXObject();
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxSerialization::createCollectionFromXml: PxParticleRepXSerializer: "
+ "Xml field \"ValidParticleRange\" is zero!");
+ return PxRepXObject();
+ }
+ }
+ // explicit instantiations
+ template struct PxParticleRepXSerializer<PxParticleSystem>;
+ template struct PxParticleRepXSerializer<PxParticleFluid>;
+#endif // #if PX_USE_PARTICLE_SYSTEM_API
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.h
new file mode 100644
index 00000000..edd61210
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXCoreSerializer.h
@@ -0,0 +1,156 @@
+// 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 SN_REPX_CORE_SERIALIZER_H
+#define SN_REPX_CORE_SERIALIZER_H
+/** \addtogroup RepXSerializers
+ @{
+*/
+#include "foundation/PxSimpleTypes.h"
+#include "SnRepXSerializerImpl.h"
+
+#if !PX_DOXYGEN
+namespace physx
+{
+#endif
+
+ template<typename TLiveType>
+ struct RepXSerializerImpl;
+
+ class XmlReader;
+ class XmlMemoryAllocator;
+ class XmlWriter;
+ class MemoryBuffer;
+
+ struct PxMaterialRepXSerializer : RepXSerializerImpl<PxMaterial>
+ {
+ PxMaterialRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxMaterial>( inCallback ) {}
+ virtual PxMaterial* allocateObject( PxRepXInstantiationArgs& );
+ };
+
+ struct PxShapeRepXSerializer : public RepXSerializerImpl<PxShape>
+ {
+ PxShapeRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxShape>( inCallback ) {}
+ virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
+ virtual PxShape* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
+ };
+
+ struct PxBVH33TriangleMeshRepXSerializer : public RepXSerializerImpl<PxBVH33TriangleMesh>
+ {
+ PxBVH33TriangleMeshRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxBVH33TriangleMesh>( inCallback ) {}
+ virtual void objectToFileImpl( const PxBVH33TriangleMesh*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
+ virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
+ virtual PxBVH33TriangleMesh* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
+ };
+ struct PxBVH34TriangleMeshRepXSerializer : public RepXSerializerImpl<PxBVH34TriangleMesh>
+ {
+ PxBVH34TriangleMeshRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxBVH34TriangleMesh>( inCallback ) {}
+ virtual void objectToFileImpl( const PxBVH34TriangleMesh*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
+ virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
+ virtual PxBVH34TriangleMesh* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
+ };
+
+ struct PxHeightFieldRepXSerializer : public RepXSerializerImpl<PxHeightField>
+ {
+ PxHeightFieldRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxHeightField>( inCallback ) {}
+ virtual void objectToFileImpl( const PxHeightField*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
+ virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
+ virtual PxHeightField* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
+ };
+
+ struct PxConvexMeshRepXSerializer : public RepXSerializerImpl<PxConvexMesh>
+ {
+ PxConvexMeshRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxConvexMesh>( inCallback ) {}
+ virtual void objectToFileImpl( const PxConvexMesh*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
+ virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
+ virtual PxConvexMesh* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
+ };
+
+ struct PxRigidStaticRepXSerializer : public RepXSerializerImpl<PxRigidStatic>
+ {
+ PxRigidStaticRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxRigidStatic>( inCallback ) {}
+ virtual PxRigidStatic* allocateObject( PxRepXInstantiationArgs& );
+ };
+
+ struct PxRigidDynamicRepXSerializer : public RepXSerializerImpl<PxRigidDynamic>
+ {
+ PxRigidDynamicRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxRigidDynamic>( inCallback ) {}
+ virtual PxRigidDynamic* allocateObject( PxRepXInstantiationArgs& );
+ };
+
+ struct PxArticulationRepXSerializer : public RepXSerializerImpl<PxArticulation>
+ {
+ PxArticulationRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxArticulation>( inCallback ) {}
+ virtual void objectToFileImpl( const PxArticulation*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
+ virtual PxArticulation* allocateObject( PxRepXInstantiationArgs& );
+ };
+
+ struct PxAggregateRepXSerializer : public RepXSerializerImpl<PxAggregate>
+ {
+ PxAggregateRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxAggregate>( inCallback ) {}
+ virtual void objectToFileImpl( const PxAggregate*, PxCollection*, XmlWriter& , MemoryBuffer&, PxRepXInstantiationArgs& );
+ virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
+ virtual PxAggregate* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
+ };
+
+#if PX_USE_CLOTH_API
+ struct PxClothFabricRepXSerializer : public RepXSerializerImpl<PxClothFabric>
+ {
+ PxClothFabricRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxClothFabric>( inCallback ) {}
+ virtual void objectToFileImpl( const PxClothFabric*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
+ virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
+ virtual PxClothFabric* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
+ };
+
+ struct PxClothRepXSerializer : public RepXSerializerImpl<PxCloth>
+ {
+ PxClothRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<PxCloth>( inCallback ) {}
+ virtual void objectToFileImpl( const PxCloth*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
+ virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
+ virtual PxCloth* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
+ };
+#endif
+
+#if PX_USE_PARTICLE_SYSTEM_API
+ template<typename TParticleType>
+ struct PxParticleRepXSerializer : RepXSerializerImpl<TParticleType>
+ {
+ PxParticleRepXSerializer( PxAllocatorCallback& inCallback ) : RepXSerializerImpl<TParticleType>( inCallback ) {}
+ virtual void objectToFileImpl( const TParticleType*, PxCollection*, XmlWriter&, MemoryBuffer&, PxRepXInstantiationArgs& );
+ virtual PxRepXObject fileToObject( XmlReader&, XmlMemoryAllocator&, PxRepXInstantiationArgs&, PxCollection* );
+ virtual TParticleType* allocateObject( PxRepXInstantiationArgs& ) { return NULL; }
+ };
+#endif
+
+#if !PX_DOXYGEN
+} // namespace physx
+#endif
+
+#endif
+/** @} */
+
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXSerializerImpl.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXSerializerImpl.h
new file mode 100644
index 00000000..08fe861a
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXSerializerImpl.h
@@ -0,0 +1,90 @@
+// 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_REPX_SERIALIZER_IMPL_H
+#define PX_REPX_SERIALIZER_IMPL_H
+
+#include "PsUserAllocated.h"
+#include "SnXmlVisitorWriter.h"
+#include "SnXmlVisitorReader.h"
+
+namespace physx {
+ using namespace Sn;
+
+ /**
+ * The repx serializer impl takes the raw, untyped repx extension interface
+ * and implements the simpler functions plus does the reinterpret-casts required
+ * for any object to implement the serializer safely.
+ */
+ template<typename TLiveType>
+ struct RepXSerializerImpl : public PxRepXSerializer, shdfnd::UserAllocated
+ {
+ protected:
+ RepXSerializerImpl( const RepXSerializerImpl& inOther );
+ RepXSerializerImpl& operator=( const RepXSerializerImpl& inOther );
+
+ public:
+ PxAllocatorCallback& mAllocator;
+
+ RepXSerializerImpl( PxAllocatorCallback& inAllocator )
+ : mAllocator( inAllocator )
+ {
+ }
+
+ virtual const char* getTypeName() { return PxTypeInfo<TLiveType>::name(); }
+
+ virtual void objectToFile( const PxRepXObject& inLiveObject, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& inArgs )
+ {
+ const TLiveType* theObj = reinterpret_cast<const TLiveType*>( inLiveObject.serializable );
+ objectToFileImpl( theObj, inCollection, inWriter, inTempBuffer, inArgs );
+ }
+
+ virtual PxRepXObject fileToObject( XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
+ {
+ TLiveType* theObj( allocateObject( inArgs ) );
+ if ( theObj )
+ if(fileToObjectImpl( theObj, inReader, inAllocator, inArgs, inCollection ))
+ return PxCreateRepXObject(theObj);
+ return PxRepXObject();
+ }
+
+ virtual void objectToFileImpl( const TLiveType* inObj, PxCollection* inCollection, XmlWriter& inWriter, MemoryBuffer& inTempBuffer, PxRepXInstantiationArgs& /*inArgs*/)
+ {
+ writeAllProperties( inObj, inWriter, inTempBuffer, *inCollection );
+ }
+
+ virtual bool fileToObjectImpl( TLiveType* inObj, XmlReader& inReader, XmlMemoryAllocator& inAllocator, PxRepXInstantiationArgs& inArgs, PxCollection* inCollection )
+ {
+ return readAllProperties( inArgs, inReader, inObj, inAllocator, *inCollection );
+ }
+
+ virtual TLiveType* allocateObject( PxRepXInstantiationArgs& inArgs ) = 0;
+ };
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.cpp
new file mode 100644
index 00000000..5eb2f40e
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.cpp
@@ -0,0 +1,444 @@
+// 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 "CmPhysXCommon.h"
+#include "SnXmlImpl.h"
+#include "SnXmlReader.h"
+#include "SnXmlMemoryAllocator.h"
+#include "PsFoundation.h"
+#include "SnRepXCollection.h"
+#include "SnRepXUpgrader.h"
+
+using namespace physx::profile;
+
+namespace physx { namespace Sn {
+
+ #define DEFINE_REPX_DEFAULT_PROPERTY( name, val ) RepXDefaultEntry( name, val ),
+
+ static RepXDefaultEntry gRepX1_0Defaults[] = {
+ #include "SnRepX1_0Defaults.h"
+ };
+ static PxU32 gNumRepX1_0Default = sizeof( gRepX1_0Defaults ) / sizeof ( *gRepX1_0Defaults );
+
+ static RepXDefaultEntry gRepX3_1Defaults[] = {
+ #include "SnRepX3_1Defaults.h"
+ };
+ static PxU32 gNumRepX3_1Defaults = sizeof( gRepX3_1Defaults ) / sizeof ( *gRepX3_1Defaults );
+
+ static RepXDefaultEntry gRepX3_2Defaults[] = {
+ #include "SnRepX3_2Defaults.h"
+ };
+ static PxU32 gNumRepX3_2Defaults = sizeof( gRepX3_2Defaults ) / sizeof ( *gRepX3_2Defaults );
+
+ inline const char* nextPeriod( const char* str )
+ {
+ for( ++str; str && *str && *str != '.'; ++str ); //empty loop intentional
+ return str;
+ }
+
+ inline bool safeStrEq(const char* lhs, const char* rhs)
+ {
+ if (lhs == rhs)
+ return true;
+ //If they aren't equal, and one of them is null,
+ //then they can't be equal.
+ //This is assuming that the null char* is not equal to
+ //the empty "" char*.
+ if (!lhs || !rhs)
+ return false;
+
+ return ::strcmp(lhs, rhs) == 0;
+ }
+
+ typedef PxProfileHashMap<const char*, PxU32> TNameOffsetMap;
+
+ void setMissingPropertiesToDefault( XmlNode* topNode, XmlReaderWriter& editor, const RepXDefaultEntry* defaults, PxU32 numDefaults, TNameOffsetMap& map )
+ {
+ for ( XmlNode* child = topNode->mFirstChild; child != NULL; child = child->mNextSibling )
+ setMissingPropertiesToDefault( child, editor, defaults, numDefaults, map );
+
+ const TNameOffsetMap::Entry* entry( map.find( topNode->mName ) );
+ if ( entry )
+ {
+ XmlReaderWriter& theReader( editor );
+ theReader.setNode( *topNode );
+ char nameBuffer[512] = {0};
+ size_t nameLen = strlen( topNode->mName );
+ //For each default property entry for this node type.
+ for ( const RepXDefaultEntry* item = defaults + entry->second; strncmp( item->name, topNode->mName, nameLen ) == 0; ++item )
+ {
+ bool childAdded = false;
+ const char* nameStart = item->name + nameLen;
+ ++nameStart;
+ theReader.pushCurrentContext();
+ const char* str = nameStart;
+ while( *str )
+ {
+ const char *period = nextPeriod( str );
+ size_t len = size_t(PxMin( period - str, ptrdiff_t(1023) )); //can't be too careful these days.
+ memcpy( nameBuffer, str, len );
+ nameBuffer[len] = 0;
+ if ( theReader.gotoChild( nameBuffer ) == false )
+ {
+ childAdded = true;
+ theReader.addOrGotoChild( nameBuffer );
+ }
+ if (*period )
+ str = period + 1;
+ else
+ str = period;
+ }
+ if ( childAdded )
+ theReader.setCurrentItemValue( item->value );
+ theReader.popCurrentContext();
+ }
+ }
+ }
+
+
+ static void setMissingPropertiesToDefault( RepXCollection& collection, XmlReaderWriter& editor, const RepXDefaultEntry* defaults, PxU32 numDefaults )
+ {
+ PxProfileAllocatorWrapper wrapper( collection.getAllocator() );
+ //Release all strings at once, instead of piece by piece
+ XmlMemoryAllocatorImpl alloc( collection.getAllocator() );
+ //build a hashtable of the initial default value strings.
+ TNameOffsetMap nameOffsets( wrapper );
+ for ( PxU32 idx = 0; idx < numDefaults; ++idx )
+ {
+ const RepXDefaultEntry& item( defaults[idx] );
+ size_t nameLen = 0;
+ const char* periodPtr = nextPeriod (item.name);
+ for ( ; periodPtr && *periodPtr; ++periodPtr ) if( *periodPtr == '.' ) break;
+ if ( periodPtr == NULL || *periodPtr != '.' ) continue;
+ nameLen = size_t(periodPtr - item.name);
+ char* newMem = reinterpret_cast<char*>(alloc.allocate( PxU32(nameLen + 1) ));
+ memcpy( newMem, item.name, nameLen );
+ newMem[nameLen] = 0;
+
+ if ( nameOffsets.find( newMem ) )
+ alloc.deallocate( reinterpret_cast<PxU8*>(newMem) );
+ else
+ nameOffsets.insert( newMem, idx );
+ }
+ //Run through each collection item, and recursively find it and its children
+ //If an object's name is in the hash map, check and add any properties that don't exist.
+ //else return.
+ for ( const RepXCollectionItem* item = collection.begin(), *end = collection.end(); item != end; ++ item )
+ {
+ RepXCollectionItem theItem( *item );
+ setMissingPropertiesToDefault( theItem.descriptor, editor, defaults, numDefaults, nameOffsets );
+ }
+ }
+
+ struct RecursiveTraversal
+ {
+ RecursiveTraversal(XmlReaderWriter& editor): mEditor(editor) {}
+ void traverse()
+ {
+ mEditor.pushCurrentContext();
+ updateNode();
+ for(bool exists = mEditor.gotoFirstChild(); exists; exists = mEditor.gotoNextSibling())
+ traverse();
+ mEditor.popCurrentContext();
+ }
+ virtual void updateNode() = 0;
+ virtual ~RecursiveTraversal() {}
+ XmlReaderWriter& mEditor;
+ protected:
+ RecursiveTraversal& operator=(const RecursiveTraversal&){return *this;}
+ };
+
+
+ RepXCollection& RepXUpgrader::upgrade10CollectionTo3_1Collection(RepXCollection& src)
+ {
+ XmlReaderWriter& editor( src.createNodeEditor() );
+ setMissingPropertiesToDefault(src, editor, gRepX1_0Defaults, gNumRepX1_0Default );
+
+
+ RepXCollection* dest = &src.createCollection("3.1.1");
+
+ for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item )
+ {
+ //either src or dest could do the copy operation, it doesn't matter who does it.
+ RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) );
+ editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) );
+ //Some old files have this name in their system.
+ editor.renameProperty( "MassSpaceInertia", "MassSpaceInertiaTensor" );
+ editor.renameProperty( "SleepEnergyThreshold", "SleepThreshold" );
+
+ if ( strstr( newItem.liveObject.typeName, "Joint" ) || strstr( newItem.liveObject.typeName, "joint" ) )
+ {
+ //Joints changed format a bit. old joints looked like:
+ /*
+ <Actor0 >1627536</Actor0>
+ <Actor1 >1628368</Actor1>
+ <LocalPose0 >0 0 0 1 0.5 0.5 0.5</LocalPose0>
+ <LocalPose1 >0 0 0 1 0.3 0.3 0.3</LocalPose1>*/
+ //New joints look like:
+ /*
+ <Actors >
+ <actor0 >58320336</actor0>
+ <actor1 >56353568</actor1>
+ </Actors>
+ <LocalPose >
+ <eACTOR0 >0 0 0 1 0.5 0.5 0.5</eACTOR0>
+ <eACTOR1 >0 0 0 1 0.3 0.3 0.3</eACTOR1>
+ </LocalPose>
+ */
+ const char* actor0, *actor1, *lp0, *lp1;
+ editor.readAndRemoveProperty( "Actor0", actor0 );
+ editor.readAndRemoveProperty( "Actor1", actor1 );
+ editor.readAndRemoveProperty( "LocalPose0", lp0 );
+ editor.readAndRemoveProperty( "LocalPose1", lp1 );
+
+ editor.addOrGotoChild( "Actors" );
+ editor.writePropertyIfNotEmpty( "actor0", actor0 );
+ editor.writePropertyIfNotEmpty( "actor1", actor1 );
+ editor.leaveChild();
+
+ editor.addOrGotoChild( "LocalPose" );
+ editor.writePropertyIfNotEmpty( "eACTOR0", lp0 );
+ editor.writePropertyIfNotEmpty( "eACTOR1", lp1 );
+ editor.leaveChild();
+ }
+
+
+
+ //now desc owns the new node. Collections share a single allocation pool, however,
+ //which will get destroyed when all the collections referencing it are destroyed themselves.
+ //Data on nodes is shared between nodes, but the node structure itself is allocated.
+ dest->addCollectionItem( newItem );
+ }
+ editor.release();
+ src.destroy();
+ return *dest;
+ }
+
+ RepXCollection& RepXUpgrader::upgrade3_1CollectionTo3_2Collection(RepXCollection& src)
+ {
+ XmlReaderWriter& editor( src.createNodeEditor() );
+ setMissingPropertiesToDefault(src, editor, gRepX3_1Defaults, gNumRepX3_1Defaults );
+
+ RepXCollection* dest = &src.createCollection("3.2.0");
+
+ for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item )
+ {
+ //either src or dest could do the copy operation, it doesn't matter who does it.
+ RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) );
+ editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) );
+
+ if ( strstr( newItem.liveObject.typeName, "PxMaterial" ) )
+ {
+ editor.removeChild( "DynamicFrictionV" );
+ editor.removeChild( "StaticFrictionV" );
+ editor.removeChild( "dirOfAnisotropy" );
+ }
+ //now desc owns the new node. Collections share a single allocation pool, however,
+ //which will get destroyed when all the collections referencing it are destroyed themselves.
+ //Data on nodes is shared between nodes, but the node structure itself is allocated.
+ dest->addCollectionItem( newItem );
+ }
+ editor.release();
+ src.destroy();
+ return *dest;
+ }
+
+ RepXCollection& RepXUpgrader::upgrade3_2CollectionTo3_3Collection(RepXCollection& src)
+ {
+ XmlReaderWriter& editor( src.createNodeEditor() );
+ setMissingPropertiesToDefault(src, editor, gRepX3_2Defaults, gNumRepX3_2Defaults );
+
+ RepXCollection* dest = &src.createCollection("3.3.0");
+
+
+
+ struct RenameSpringToStiffness : public RecursiveTraversal
+ {
+ RenameSpringToStiffness(XmlReaderWriter& editor_): RecursiveTraversal(editor_) {}
+
+ void updateNode()
+ {
+ mEditor.renameProperty("Spring", "Stiffness");
+ mEditor.renameProperty("TangentialSpring", "TangentialStiffness");
+ }
+ };
+
+
+ struct UpdateArticulationSwingLimit : public RecursiveTraversal
+ {
+ UpdateArticulationSwingLimit(XmlReaderWriter& editor_): RecursiveTraversal(editor_) {}
+
+ void updateNode()
+ {
+ if(!Ps::stricmp(mEditor.getCurrentItemName(), "yLimit") && !Ps::stricmp(mEditor.getCurrentItemValue(), "0"))
+ mEditor.setCurrentItemValue("0.785398");
+
+ if(!Ps::stricmp(mEditor.getCurrentItemName(), "zLimit") && !Ps::stricmp(mEditor.getCurrentItemValue(), "0"))
+ mEditor.setCurrentItemValue("0.785398");
+
+ if(!Ps::stricmp(mEditor.getCurrentItemName(), "TwistLimit"))
+ {
+ mEditor.gotoFirstChild();
+ PxReal lower = PxReal(strtod(mEditor.getCurrentItemValue(), NULL));
+ mEditor.gotoNextSibling();
+ PxReal upper = PxReal(strtod(mEditor.getCurrentItemValue(), NULL));
+ mEditor.leaveChild();
+ if(lower>=upper)
+ {
+ mEditor.writePropertyIfNotEmpty("lower", "-0.785398");
+ mEditor.writePropertyIfNotEmpty("upper", "0.785398");
+ }
+ }
+ }
+ };
+
+
+ for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item )
+ {
+ //either src or dest could do the copy operation, it doesn't matter who does it.
+ RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) );
+
+
+ if ( strstr( newItem.liveObject.typeName, "PxCloth" ) || strstr( newItem.liveObject.typeName, "PxClothFabric" ) )
+ {
+ physx::shdfnd::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__, "Didn't suppot PxCloth upgrate from 3.2 to 3.3! ");
+ continue;
+ }
+
+ if ( strstr( newItem.liveObject.typeName, "PxParticleSystem" ) || strstr( newItem.liveObject.typeName, "PxParticleFluid" ) )
+ {
+ editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) );
+ editor.renameProperty( "PositionBuffer", "Positions" );
+ editor.renameProperty( "VelocityBuffer", "Velocities" );
+ editor.renameProperty( "RestOffsetBuffer", "RestOffsets" );
+ }
+
+ if(strstr(newItem.liveObject.typeName, "PxPrismaticJoint" )
+ || strstr(newItem.liveObject.typeName, "PxRevoluteJoint")
+ || strstr(newItem.liveObject.typeName, "PxSphericalJoint")
+ || strstr(newItem.liveObject.typeName, "PxD6Joint")
+ || strstr(newItem.liveObject.typeName, "PxArticulation"))
+ {
+ editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) );
+ RenameSpringToStiffness(editor).traverse();
+ }
+
+ if(strstr(newItem.liveObject.typeName, "PxArticulation"))
+ {
+ editor.setNode( *const_cast<XmlNode*>( newItem.descriptor ) );
+ UpdateArticulationSwingLimit(editor).traverse();
+ }
+
+
+
+ //now dest owns the new node. Collections share a single allocation pool, however,
+ //which will get destroyed when all the collections referencing it are destroyed themselves.
+ //Data on nodes is shared between nodes, but the node structure itself is allocated.
+
+ dest->addCollectionItem( newItem );
+
+ }
+ editor.release();
+ src.destroy();
+
+ return *dest;
+ }
+
+ RepXCollection& RepXUpgrader::upgrade3_3CollectionTo3_4Collection(RepXCollection& src)
+ {
+ RepXCollection* dest = &src.createCollection("3.4.0");
+
+ for ( const RepXCollectionItem* item = src.begin(), *end = src.end(); item != end; ++ item )
+ {
+ if(strstr(item->liveObject.typeName, "PxTriangleMesh"))
+ {
+ PxRepXObject newMeshRepXObj("PxBVH33TriangleMesh", item->liveObject.serializable, item->liveObject.id);
+ XmlNode* newMeshNode = src.copyRepXNode( item->descriptor );
+ newMeshNode->mName = "PxBVH33TriangleMesh";
+ RepXCollectionItem newMeshItem(newMeshRepXObj, newMeshNode);
+ dest->addCollectionItem( newMeshItem );
+ continue;
+ }
+
+ RepXCollectionItem newItem( item->liveObject, src.copyRepXNode( item->descriptor ) );
+ dest->addCollectionItem( newItem );
+ }
+ src.destroy();
+ return *dest;
+ }
+
+ RepXCollection& RepXUpgrader::upgradeCollection(RepXCollection& src)
+ {
+ const char* srcVersion = src.getVersion();
+ if( safeStrEq( srcVersion, RepXCollection::getLatestVersion() ))
+ return src;
+
+ static const char* oldVersions[] = {"1.0",
+ "3.1",
+ "3.1.1",
+ "3.2.0",
+ "3.3.0",
+ "3.3.1",
+ "3.3.2"
+ };//should be increase order
+
+ PxU32 grade = UINT16_MAX;
+ const PxU32 count = sizeof(oldVersions)/sizeof(oldVersions[0]);
+ for (PxU32 i=0; i<count; i++)
+ {
+ if( safeStrEq( srcVersion, oldVersions[i] ))
+ {
+ grade = i;
+ break;
+ }
+ }
+
+ typedef RepXCollection& (*UPGRADE_FUNCTION)(RepXCollection& src);
+
+ UPGRADE_FUNCTION procs[count] =
+ {
+ upgrade10CollectionTo3_1Collection,
+ NULL,
+ upgrade3_1CollectionTo3_2Collection,
+ upgrade3_2CollectionTo3_3Collection,
+ NULL,
+ NULL,
+ upgrade3_3CollectionTo3_4Collection,
+ };
+
+ RepXCollection* dest = &src;
+ for( PxU32 j = grade; j < count; j++ )
+ {
+ if( procs[j] )
+ dest = &(procs[j])(*dest);
+ }
+
+ return *dest;
+ }
+} }
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.h
new file mode 100644
index 00000000..9baf270c
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnRepXUpgrader.h
@@ -0,0 +1,53 @@
+// 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_REPX_UPGRADER_H
+#define PX_REPX_UPGRADER_H
+
+#include "foundation/PxSimpleTypes.h"
+
+namespace physx { namespace Sn {
+ class RepXCollection;
+
+ class RepXUpgrader
+ {
+ public:
+ //If a new collection is created, the source collection is destroyed.
+ //Thus you only need to release the new collection.
+ //This holds for all of the upgrade functions.
+ //So be aware, that the argument to these functions may not be valid
+ //after they are called, but the return value always will be valid.
+ static RepXCollection& upgradeCollection( RepXCollection& src );
+ static RepXCollection& upgrade10CollectionTo3_1Collection( RepXCollection& src );
+ static RepXCollection& upgrade3_1CollectionTo3_2Collection( RepXCollection& src );
+ static RepXCollection& upgrade3_2CollectionTo3_3Collection( RepXCollection& src );
+ static RepXCollection& upgrade3_3CollectionTo3_4Collection( RepXCollection& src );
+ };
+} }
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnSimpleXmlWriter.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnSimpleXmlWriter.h
new file mode 100644
index 00000000..6f63fefc
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnSimpleXmlWriter.h
@@ -0,0 +1,257 @@
+// 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_SIMPLEXMLWRITER_H
+#define PX_SIMPLEXMLWRITER_H
+
+#include "PsArray.h"
+#include "SnXmlMemoryPoolStreams.h"
+#include "CmPhysXCommon.h"
+
+namespace physx { namespace Sn {
+ class SimpleXmlWriter
+ {
+ public:
+
+ struct STagWatcher
+ {
+ typedef SimpleXmlWriter TXmlWriterType;
+ TXmlWriterType& mWriter;
+ STagWatcher( const STagWatcher& inOther );
+ STagWatcher& operator-( const STagWatcher& inOther );
+ STagWatcher( TXmlWriterType& inWriter, const char* inTagName )
+ : mWriter( inWriter )
+ {
+ mWriter.beginTag( inTagName );
+ }
+ ~STagWatcher() { mWriter.endTag(); }
+ protected:
+ STagWatcher& operator=(const STagWatcher&);
+ };
+
+ virtual ~SimpleXmlWriter(){}
+ virtual void beginTag( const char* inTagname ) = 0;
+ virtual void endTag() = 0;
+ virtual void addAttribute( const char* inName, const char* inValue ) = 0;
+ virtual void writeContentTag( const char* inTag, const char* inContent ) = 0;
+ virtual void addContent( const char* inContent ) = 0;
+ virtual PxU32 tabCount() = 0;
+ private:
+ SimpleXmlWriter& operator=(const SimpleXmlWriter&);
+ };
+
+ template<typename TStreamType>
+ class SimpleXmlWriterImpl : public SimpleXmlWriter
+ {
+ PxProfileAllocatorWrapper mWrapper;
+ TStreamType& mStream;
+ SimpleXmlWriterImpl( const SimpleXmlWriterImpl& inOther );
+ SimpleXmlWriterImpl& operator=( const SimpleXmlWriterImpl& inOther );
+ PxProfileArray<const char*> mTags;
+ bool mTagOpen;
+ PxU32 mInitialTagDepth;
+ public:
+
+ SimpleXmlWriterImpl( TStreamType& inStream, PxAllocatorCallback& inAllocator, PxU32 inInitialTagDepth = 0 )
+ : mWrapper( inAllocator )
+ , mStream( inStream )
+ , mTags( mWrapper )
+ , mTagOpen( false )
+ , mInitialTagDepth( inInitialTagDepth )
+ {
+ }
+ virtual ~SimpleXmlWriterImpl()
+ {
+ while( mTags.size() )
+ endTag();
+ }
+ PxU32 tabCount() { return mTags.size() + mInitialTagDepth; }
+
+ void writeTabs( PxU32 inSize )
+ {
+ inSize += mInitialTagDepth;
+ for ( PxU32 idx =0; idx < inSize; ++idx )
+ mStream << "\t";
+ }
+ void beginTag( const char* inTagname )
+ {
+ closeTag();
+ writeTabs(mTags.size());
+ mTags.pushBack( inTagname );
+ mStream << "<" << inTagname;
+ mTagOpen = true;
+ }
+ void addAttribute( const char* inName, const char* inValue )
+ {
+ PX_ASSERT( mTagOpen );
+ mStream << " " << inName << "=" << "\"" << inValue << "\"";
+ }
+ void closeTag(bool useNewline = true)
+ {
+ if ( mTagOpen )
+ {
+ mStream << " " << ">";
+ if (useNewline )
+ mStream << "\n";
+ }
+ mTagOpen = false;
+ }
+ void doEndOpenTag()
+ {
+ mStream << "</" << mTags.back() << ">" << "\n";
+ }
+ void endTag()
+ {
+ PX_ASSERT( mTags.size() );
+ if ( mTagOpen )
+ mStream << " " << "/>" << "\n";
+ else
+ {
+ writeTabs(mTags.size()-1);
+ doEndOpenTag();
+ }
+ mTagOpen = false;
+ mTags.popBack();
+ }
+
+ static bool IsNormalizableWhitespace(char c) { return c == 0x9 || c == 0xA || c == 0xD; }
+ static bool IsValidXmlCharacter(char c) { return IsNormalizableWhitespace(c) || c >= 0x20; }
+
+ void addContent( const char* inContent )
+ {
+ closeTag(false);
+ //escape xml
+ for( ; *inContent; inContent++ )
+ {
+ switch (*inContent)
+ {
+ case '<':
+ mStream << "&lt;";
+ break;
+ case '>':
+ mStream << "&gt;";
+ break;
+ case '&':
+ mStream << "&amp;";
+ break;
+ case '\'':
+ mStream << "&apos;";
+ break;
+ case '"':
+ mStream << "&quot;";
+ break;
+ default:
+ if (IsValidXmlCharacter(*inContent)) {
+ if (IsNormalizableWhitespace(*inContent))
+ {
+ char s[32];
+ Ps::snprintf(s, 32, "&#x%02X;", unsigned(*inContent));
+ mStream << s;
+ }
+ else
+ mStream << *inContent;
+ }
+ break;
+ }
+ }
+ }
+
+ void writeContentTag( const char* inTag, const char* inContent )
+ {
+ beginTag( inTag );
+ addContent( inContent );
+ doEndOpenTag();
+ mTags.popBack();
+ }
+ void insertXml( const char* inXml )
+ {
+ closeTag();
+ mStream << inXml;
+ }
+ };
+
+ struct BeginTag
+ {
+ const char* mTagName;
+ BeginTag( const char* inTagName )
+ : mTagName( inTagName ) { }
+ };
+
+ struct EndTag
+ {
+ EndTag() {}
+ };
+
+ struct Att
+ {
+ const char* mAttName;
+ const char* mAttValue;
+ Att( const char* inAttName, const char* inAttValue )
+ : mAttName( inAttName )
+ , mAttValue( inAttValue ) { }
+ };
+
+ struct Content
+ {
+ const char* mContent;
+ Content( const char* inContent )
+ : mContent( inContent ) { }
+ };
+
+
+ struct ContentTag
+ {
+ const char* mTagName;
+ const char* mContent;
+ ContentTag( const char* inTagName, const char* inContent )
+ : mTagName( inTagName )
+ , mContent( inContent ) { }
+ };
+
+ inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const BeginTag& inTag ) { inWriter.beginTag( inTag.mTagName ); return inWriter; }
+ inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const EndTag& inTag ) { PX_UNUSED(inTag); inWriter.endTag(); return inWriter; }
+ inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const Att& inTag ) { inWriter.addAttribute(inTag.mAttName, inTag.mAttValue); return inWriter; }
+ inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const Content& inTag ) { inWriter.addContent(inTag.mContent); return inWriter; }
+ inline SimpleXmlWriter& operator<<( SimpleXmlWriter& inWriter, const ContentTag& inTag ) { inWriter.writeContentTag(inTag.mTagName, inTag.mContent); return inWriter; }
+
+ inline void writeProperty( SimpleXmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName )
+ {
+ PxU8 data = 0;
+ tempBuffer.write( &data, sizeof(PxU8) );
+ inWriter.writeContentTag( inPropName, reinterpret_cast<const char*>( tempBuffer.mBuffer ) );
+ tempBuffer.clear();
+ }
+
+ template<typename TDataType>
+ inline void writeProperty( SimpleXmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName, TDataType inValue )
+ {
+ tempBuffer << inValue;
+ writeProperty( inWriter, tempBuffer, inPropName );
+ }
+} }
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlDeserializer.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlDeserializer.h
new file mode 100644
index 00000000..fdb29359
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlDeserializer.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_XML_DESERIALIZER_H
+#define PX_XML_DESERIALIZER_H
+
+#include "SnXmlVisitorReader.h"
+
+namespace physx { namespace Sn {
+
+ //Definitions needed internally in the Serializer headers.
+ template<typename TTriIndexElem>
+ struct Triangle
+ {
+ TTriIndexElem mIdx0;
+ TTriIndexElem mIdx1;
+ TTriIndexElem mIdx2;
+ Triangle( TTriIndexElem inIdx0 = 0, TTriIndexElem inIdx1 = 0, TTriIndexElem inIdx2 = 0)
+ : mIdx0( inIdx0 )
+ , mIdx1( inIdx1 )
+ , mIdx2( inIdx2 )
+ {
+ }
+ };
+
+ struct XmlMemoryAllocateMemoryPoolAllocator
+ {
+ XmlMemoryAllocator* mAllocator;
+ XmlMemoryAllocateMemoryPoolAllocator( XmlMemoryAllocator* inAlloc ) : mAllocator( inAlloc ) {}
+
+ PxU8* allocate( PxU32 inSize ) { return mAllocator->allocate( inSize ); }
+ void deallocate( PxU8* inMem ) { mAllocator->deallocate( inMem ); }
+ };
+
+ inline void strtoLong( Triangle<PxU32>& ioDatatype,const char*& ioData )
+ {
+ strto( ioDatatype.mIdx0, ioData );
+ strto( ioDatatype.mIdx1, ioData );
+ strto( ioDatatype.mIdx2, ioData );
+ }
+
+ inline void strtoLong( PxHeightFieldSample& ioDatatype,const char*& ioData )
+ {
+ PxU32 tempData;
+ strto( tempData, ioData );
+ if ( isBigEndian() )
+ {
+ PxU32& theItem(tempData);
+ PxU32 theDest = 0;
+ PxU8* theReadPtr( reinterpret_cast< PxU8* >( &theItem ) );
+ PxU8* theWritePtr( reinterpret_cast< PxU8* >( &theDest ) );
+ //A height field sample is a 16 bit number
+ //followed by two bytes.
+
+ //We write this out as a 32 bit integer, LE.
+ //Thus, on a big endian, we need to move the bytes
+ //around a bit.
+ //LE - 1 2 3 4
+ //BE - 4 3 2 1 - after convert from xml number
+ //Correct BE - 2 1 3 4, just like LE but with the 16 number swapped
+ theWritePtr[0] = theReadPtr[2];
+ theWritePtr[1] = theReadPtr[3];
+ theWritePtr[2] = theReadPtr[1];
+ theWritePtr[3] = theReadPtr[0];
+ theItem = theDest;
+ }
+ ioDatatype = *reinterpret_cast<PxHeightFieldSample*>( &tempData );
+ }
+
+ template<typename TDataType>
+ inline void readStridedFlagsProperty( XmlReader& ioReader, const char* inPropName, TDataType*& outData, PxU32& outStride, PxU32& outCount, XmlMemoryAllocator& inAllocator,
+ const PxU32ToName* inConversions)
+ {
+ const char* theSrcData;
+ outStride = sizeof( TDataType );
+ outData = NULL;
+ outCount = 0;
+ if ( ioReader.read( inPropName, theSrcData ) )
+ {
+ XmlMemoryAllocateMemoryPoolAllocator tempAllocator( &inAllocator );
+ MemoryBufferBase<XmlMemoryAllocateMemoryPoolAllocator> tempBuffer( &tempAllocator );
+
+ if ( theSrcData )
+ {
+ static PxU32 theCount = 0;
+ ++theCount;
+ char* theStartData = const_cast< char*>( copyStr( &tempAllocator, theSrcData ) );
+ char* aData = strtok(theStartData, " \n");
+ while( aData )
+ {
+ TDataType tempValue;
+ stringToFlagsType( aData, inAllocator, tempValue, inConversions );
+ aData = strtok(NULL," \n");
+ tempBuffer.write( &tempValue, sizeof(TDataType) );
+ }
+ outData = reinterpret_cast< TDataType* >( tempBuffer.mBuffer );
+ outCount = tempBuffer.mWriteOffset / sizeof( TDataType );
+ tempAllocator.deallocate( reinterpret_cast<PxU8*>(theStartData) );
+ }
+ tempBuffer.releaseBuffer();
+ }
+ }
+
+ template<typename TDataType>
+ inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, TDataType*& outData, PxU32& outStride, PxU32& outCount, XmlMemoryAllocator& inAllocator)
+ {
+ const char* theSrcData;
+ outStride = sizeof( TDataType );
+ outData = NULL;
+ outCount = 0;
+ if ( ioReader.read( inPropName, theSrcData ) )
+ {
+ XmlMemoryAllocateMemoryPoolAllocator tempAllocator( &inAllocator );
+ MemoryBufferBase<XmlMemoryAllocateMemoryPoolAllocator> tempBuffer( &tempAllocator );
+
+ if ( theSrcData )
+ {
+ static PxU32 theCount = 0;
+ ++theCount;
+ char* theStartData = const_cast< char*>( copyStr( &tempAllocator, theSrcData ) );
+ const char* theData = theStartData;
+ PxU32 theLen = strLenght( theData );
+ const char* theEndData = theData + theLen;
+ while( theData < theEndData )
+ {
+ //These buffers are whitespace delimited.
+ TDataType theType;
+ strtoLong( theType, theData );
+ tempBuffer.write( &theType, sizeof(theType) );
+ }
+ outData = reinterpret_cast< TDataType* >( tempBuffer.mBuffer );
+ outCount = tempBuffer.mWriteOffset / sizeof( TDataType );
+ tempAllocator.deallocate( reinterpret_cast<PxU8*>(theStartData) );
+ }
+ tempBuffer.releaseBuffer();
+ }
+ }
+
+ template<typename TDataType>
+ inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, PxStridedData& ioData, PxU32& outCount, XmlMemoryAllocator& inAllocator)
+ {
+ TDataType* tempData = NULL;
+ readStridedBufferProperty<TDataType>( ioReader, inPropName, tempData, ioData.stride, outCount, inAllocator );
+ ioData.data = tempData;
+ }
+
+ template<typename TDataType>
+ inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, PxTypedStridedData<TDataType>& ioData, PxU32& outCount, XmlMemoryAllocator& inAllocator)
+ {
+ TDataType* tempData = NULL;
+ readStridedBufferProperty<TDataType>( ioReader, inPropName, tempData, ioData.stride, outCount, inAllocator );
+ ioData.data = reinterpret_cast<PxMaterialTableIndex*>( tempData );
+ }
+
+ template<typename TDataType>
+ inline void readStridedBufferProperty( XmlReader& ioReader, const char* inPropName, PxBoundedData& ioData, XmlMemoryAllocator& inAllocator)
+ {
+ return readStridedBufferProperty<TDataType>( ioReader, inPropName, ioData, ioData.count, inAllocator );
+ }
+
+} }
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlImpl.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlImpl.h
new file mode 100644
index 00000000..1718cc86
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlImpl.h
@@ -0,0 +1,242 @@
+// 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_XML_IMPL_H
+#define PX_XML_IMPL_H
+
+#include "SnXmlMemoryPool.h"
+#include "PsString.h"
+
+namespace physx { namespace Sn {
+
+typedef CMemoryPoolManager TMemoryPoolManager;
+
+namespace snXmlImpl {
+
+ inline PxU32 strLen( const char* inStr )
+ {
+ PxU32 len = 0;
+ if ( inStr )
+ {
+ while ( *inStr )
+ {
+ ++len;
+ ++inStr;
+ }
+ }
+ return len;
+ }
+}
+ inline const char* copyStr( PxAllocatorCallback& inAllocator, const char* inStr )
+ {
+ if ( inStr && *inStr )
+ {
+ PxU32 theLen = snXmlImpl::strLen( inStr );
+ //The memory will never be released by repx. If you want it released, you need to pass in a custom allocator
+ //that tracks all allocations and releases unreleased allocations yourself.
+ char* dest = reinterpret_cast<char* >( inAllocator.allocate( theLen + 1, "Repx::const char*", __FILE__, __LINE__ ) );
+ memcpy( dest, inStr, theLen );
+ dest[theLen] = 0;
+ return dest;
+ }
+ return "";
+ }
+
+ template<typename TManagerType>
+ inline const char* copyStr( TManagerType* inMgr, const char* inStr )
+ {
+ if ( inStr && *inStr )
+ {
+ PxU32 theLen = snXmlImpl::strLen( inStr );
+ char* dest = reinterpret_cast<char* >( inMgr->allocate( theLen + 1 ) );
+ memcpy( dest, inStr, theLen );
+ dest[theLen] = 0;
+ return dest;
+ }
+ return "";
+ }
+
+ inline void releaseStr( TMemoryPoolManager* inMgr, const char* inStr, PxU32 )
+ {
+ if ( inStr && *inStr )
+ {
+ inMgr->deallocate( reinterpret_cast< PxU8* >( const_cast<char*>( inStr ) ) );
+ }
+ }
+
+ inline void releaseStr( TMemoryPoolManager* inMgr, const char* inStr )
+ {
+ if ( inStr && *inStr )
+ {
+ PxU32 theLen = snXmlImpl::strLen( inStr );
+ releaseStr( inMgr, inStr, theLen );
+ }
+ }
+
+ struct XmlNode
+ {
+ const char* mName; //Never released until all collections are released
+ const char* mData; //Never released until all collections are released
+
+ XmlNode* mNextSibling;
+ XmlNode* mPreviousSibling;
+ XmlNode* mFirstChild;
+ XmlNode* mParent;
+ XmlNode( const XmlNode& );
+ XmlNode& operator=( const XmlNode& );
+
+ PX_INLINE void initPtrs()
+ {
+ mNextSibling = NULL;
+ mPreviousSibling = NULL;
+ mFirstChild = NULL;
+ mParent = NULL;
+ }
+
+ PX_INLINE XmlNode( const char* inName = "", const char* inData = "" )
+ : mName( inName )
+ , mData( inData )
+ { initPtrs(); }
+
+ void addChild( XmlNode* inItem )
+ {
+ inItem->mParent = this;
+ if ( mFirstChild == NULL )
+ mFirstChild = inItem;
+ else
+ {
+ XmlNode* theNode = mFirstChild;
+ //Follow the chain till the end.
+ while( theNode->mNextSibling != NULL )
+ theNode = theNode->mNextSibling;
+ theNode->mNextSibling = inItem;
+ inItem->mPreviousSibling = theNode;
+ }
+ }
+
+ PX_INLINE XmlNode* findChildByName( const char* inName )
+ {
+ for ( XmlNode* theNode = mFirstChild; theNode; theNode = theNode->mNextSibling )
+ {
+ XmlNode* theRepXNode = theNode;
+ if ( physx::shdfnd::stricmp( theRepXNode->mName, inName ) == 0 )
+ return theNode;
+ }
+ return NULL;
+ }
+
+ PX_INLINE void orphan()
+ {
+ if ( mParent )
+ {
+ if ( mParent->mFirstChild == this )
+ mParent->mFirstChild = mNextSibling;
+ }
+ if ( mPreviousSibling )
+ mPreviousSibling->mNextSibling = mNextSibling;
+ if ( mNextSibling )
+ mNextSibling->mPreviousSibling = mPreviousSibling;
+ if ( mFirstChild )
+ mFirstChild->mParent = NULL;
+ initPtrs();
+ }
+ };
+
+ inline XmlNode* allocateRepXNode( TMemoryPoolManager* inManager, const char* inName, const char* inData )
+ {
+ XmlNode* retval = inManager->allocate<XmlNode>();
+ retval->mName = copyStr( inManager, inName );
+ retval->mData = copyStr( inManager, inData );
+ return retval;
+ }
+
+ inline void release( TMemoryPoolManager* inManager, XmlNode* inNode )
+ {
+ //We *don't* release the strings associated with the node
+ //because they could be shared. Instead, we just let them 'leak'
+ //in some sense, at least until the memory manager itself is deleted.
+ //DO NOT UNCOMMENT THE LINES BELOW!!
+ //releaseStr( inManager, inNode->mName );
+ //releaseStr( inManager, inNode->mData );
+ inManager->deallocate( inNode );
+ }
+
+ static PX_INLINE void releaseNodeAndChildren( TMemoryPoolManager* inManager, XmlNode* inNode )
+ {
+ if ( inNode->mFirstChild )
+ {
+ XmlNode* childNode( inNode->mFirstChild );
+ while( childNode )
+ {
+ XmlNode* _node( childNode );
+ childNode = _node->mNextSibling;
+ releaseNodeAndChildren( inManager, _node );
+ }
+ }
+ inNode->orphan();
+ release( inManager, inNode );
+ }
+
+ static XmlNode* copyRepXNodeAndSiblings( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent );
+
+ static XmlNode* copyRepXNode( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent = NULL )
+ {
+ XmlNode* newNode( allocateRepXNode( inManager, NULL, NULL ) );
+ newNode->mName = inNode->mName; //Some light structural sharing
+ newNode->mData = inNode->mData; //Some light structural sharing
+ newNode->mParent = inParent;
+ if ( inNode->mFirstChild )
+ newNode->mFirstChild = copyRepXNodeAndSiblings( inManager, inNode->mFirstChild, newNode );
+ return newNode;
+ }
+
+ static XmlNode* copyRepXNodeAndSiblings( TMemoryPoolManager* inManager, const XmlNode* inNode, XmlNode* inParent )
+ {
+ XmlNode* sibling = inNode->mNextSibling;
+ if ( sibling ) sibling = copyRepXNodeAndSiblings( inManager, sibling, inParent );
+ XmlNode* newNode = copyRepXNode( inManager, inNode, inParent );
+ newNode->mNextSibling = sibling;
+ if ( sibling ) sibling->mPreviousSibling = newNode;
+ return newNode;
+ }
+
+ inline bool isBigEndian() { int i = 1; return *(reinterpret_cast<char*>(&i))==0; }
+
+
+ struct NameStackEntry
+ {
+ const char* mName;
+ bool mOpen;
+ NameStackEntry( const char* nm ) : mName( nm ), mOpen( false ) {}
+ };
+
+ typedef PxProfileArray<NameStackEntry> TNameStack;
+} }
+
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryAllocator.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryAllocator.h
new file mode 100644
index 00000000..8172a312
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryAllocator.h
@@ -0,0 +1,129 @@
+// 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_XML_MEMORY_ALLOCATOR_H
+#define PX_XML_MEMORY_ALLOCATOR_H
+
+#include "foundation/PxSimpleTypes.h"
+
+namespace physx {
+
+ class XmlMemoryAllocator
+ {
+ protected:
+ virtual ~XmlMemoryAllocator(){}
+ public:
+ virtual PxU8* allocate(PxU32 inSize) = 0;
+ virtual void deallocate( PxU8* inMem ) = 0;
+ virtual PxAllocatorCallback& getAllocator() = 0;
+ template<typename TObjectType>
+ TObjectType* allocate()
+ {
+ TObjectType* retval = reinterpret_cast< TObjectType* >( allocate( sizeof( TObjectType ) ) );
+ new (retval) TObjectType();
+ return retval;
+ }
+
+ template<typename TObjectType, typename TArgType>
+ TObjectType* allocate(const TArgType &arg)
+ {
+ TObjectType* retval = reinterpret_cast< TObjectType* >( allocate( sizeof( TObjectType ) ) );
+ new (retval) TObjectType(arg);
+ return retval;
+ }
+
+ template<typename TObjectType>
+ void deallocate( TObjectType* inObject )
+ {
+ deallocate( reinterpret_cast<PxU8*>( inObject ) );
+ }
+ template<typename TObjectType>
+ inline TObjectType* batchAllocate(PxU32 inCount )
+ {
+ TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) );
+ for ( PxU32 idx = 0; idx < inCount; ++idx )
+ {
+ new (retval + idx) TObjectType();
+ }
+ return retval;
+ }
+
+ template<typename TObjectType, typename TArgType>
+ inline TObjectType* batchAllocate(PxU32 inCount, const TArgType &arg)
+ {
+ TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) );
+ for ( PxU32 idx = 0; idx < inCount; ++idx )
+ {
+ new (retval + idx) TObjectType(arg);
+ }
+ return retval;
+ }
+
+
+ //Duplicate function definition for gcc.
+ template<typename TObjectType>
+ inline TObjectType* batchAllocate(TObjectType*, PxU32 inCount )
+ {
+ TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) );
+ for ( PxU32 idx = 0; idx < inCount; ++idx )
+ {
+ new (retval + idx) TObjectType();
+ }
+ return retval;
+ }
+ };
+
+ struct XmlMemoryAllocatorImpl : public XmlMemoryAllocator
+ {
+ Sn::TMemoryPoolManager mManager;
+
+ XmlMemoryAllocatorImpl( PxAllocatorCallback& inAllocator )
+ : mManager( inAllocator )
+ {
+ }
+ XmlMemoryAllocatorImpl &operator=(const XmlMemoryAllocatorImpl &);
+ virtual PxAllocatorCallback& getAllocator()
+ {
+ return mManager.getWrapper().getAllocator();
+ }
+
+ virtual PxU8* allocate(PxU32 inSize )
+ {
+ if ( !inSize )
+ return NULL;
+
+ return mManager.allocate( inSize );
+ }
+ virtual void deallocate( PxU8* inMem )
+ {
+ if ( inMem )
+ mManager.deallocate( inMem );
+ }
+ };
+}
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPool.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPool.h
new file mode 100644
index 00000000..2c1177e3
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPool.h
@@ -0,0 +1,373 @@
+// 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_XML_MEMORYPOOL_H
+#define PX_XML_MEMORYPOOL_H
+
+#include "foundation/PxAssert.h"
+#include "PsArray.h"
+#include "PxProfileAllocatorWrapper.h"
+
+namespace physx {
+
+ using namespace physx::profile;
+
+ /**
+ * Linked list used to store next node ptr.
+ */
+ struct SMemPoolNode
+ {
+ SMemPoolNode* mNextNode;
+ };
+
+ /**
+ * Template arguments are powers of two.
+ * A very fast memory pool that is not memory efficient. It contains a vector of pointers
+ * to blocks of memory along with a linked list of free sections. All sections are
+ * of the same size so allocating memory is very fast, there isn't a linear search
+ * through blocks of indeterminate size. It also means there is memory wasted
+ * when objects aren't sized to powers of two.
+ */
+ template<PxU8 TItemSize
+ , PxU8 TItemCount >
+ class CMemoryPool
+ {
+ typedef PxProfileArray<PxU8*> TPxU8PtrList;
+
+ PxProfileAllocatorWrapper& mWrapper;
+ TPxU8PtrList mAllMemory;
+ SMemPoolNode* mFirstFreeNode;
+ public:
+ CMemoryPool(PxProfileAllocatorWrapper& inWrapper)
+ : mWrapper( inWrapper )
+ , mAllMemory( inWrapper )
+ , mFirstFreeNode( NULL )
+ {}
+ ~CMemoryPool()
+ {
+ TPxU8PtrList::ConstIterator theEnd = mAllMemory.end();
+ for ( TPxU8PtrList::ConstIterator theIter = mAllMemory.begin();
+ theIter != theEnd;
+ ++theIter )
+ {
+ PxU8* thePtr = *theIter;
+ mWrapper.getAllocator().deallocate( thePtr );
+ }
+ mAllMemory.clear();
+ mFirstFreeNode = NULL;
+ }
+ //Using deallocated memory to hold the pointers to the next amount of memory.
+ PxU8* allocate()
+ {
+ if ( mFirstFreeNode )
+ {
+ PxU8* retval = reinterpret_cast<PxU8*>(mFirstFreeNode);
+ mFirstFreeNode = mFirstFreeNode->mNextNode;
+ return retval;
+ }
+ PxU32 itemSize = GetItemSize();
+ PxU32 itemCount = 1 << TItemCount;
+ //No free nodes, make some more.
+ PxU8* retval = reinterpret_cast<PxU8*>(mWrapper.getAllocator().allocate( itemCount * itemSize, "RepX fixed-size memory pool", __FILE__, __LINE__ ));
+ PxU8* dataPtr = retval + itemSize;
+ //Free extra chunks
+ for( PxU32 idx = 1; idx < itemCount; ++idx, dataPtr += itemSize )
+ deallocate( dataPtr );
+ mAllMemory.pushBack(retval);
+ return retval;
+ }
+ void deallocate( PxU8* inData )
+ {
+ SMemPoolNode* nodePtr = reinterpret_cast<SMemPoolNode*>(inData);
+ nodePtr->mNextNode = mFirstFreeNode;
+ mFirstFreeNode = nodePtr;
+ }
+ //We have to have at least a pointer's worth of memory
+ inline PxU32 GetItemSize() { return sizeof(SMemPoolNode) << TItemSize; }
+ };
+
+ typedef PxU32 TMemAllocSizeType;
+
+ struct SVariableMemPoolNode : SMemPoolNode
+ {
+ TMemAllocSizeType mSize;
+ SVariableMemPoolNode* NextNode() { return static_cast< SVariableMemPoolNode* >( mNextNode ); }
+ };
+
+ /**
+ * Manages variable sized allocations.
+ * Keeps track of freed allocations in a insertion sorted
+ * list. Allocating new memory traverses the list linearly.
+ * This object will split nodes if the node is more than
+ * twice as large as the request memory allocation.
+ */
+ class CVariableMemoryPool
+ {
+ typedef PxProfileHashMap<TMemAllocSizeType, SVariableMemPoolNode*> TFreeNodeMap;
+ typedef PxProfileArray<PxU8*> TPxU8PtrList;
+ PxProfileAllocatorWrapper& mWrapper;
+ TPxU8PtrList mAllMemory;
+ TFreeNodeMap mFreeNodeMap;
+ PxU32 mMinAllocationSize;
+
+ CVariableMemoryPool &operator=(const CVariableMemoryPool &);
+
+ public:
+ CVariableMemoryPool(PxProfileAllocatorWrapper& inWrapper, PxU32 inMinAllocationSize = 0x20 )
+ : mWrapper( inWrapper )
+ , mAllMemory( inWrapper )
+ , mFreeNodeMap( inWrapper)
+ , mMinAllocationSize( inMinAllocationSize )
+ {}
+
+ ~CVariableMemoryPool()
+ {
+ TPxU8PtrList::ConstIterator theEnd = mAllMemory.end();
+ for ( TPxU8PtrList::ConstIterator theIter = mAllMemory.begin();
+ theIter != theEnd;
+ ++theIter )
+ {
+ PxU8* thePtr = *theIter;
+ mWrapper.getAllocator().deallocate( thePtr );
+ }
+ mAllMemory.clear();
+ mFreeNodeMap.clear();
+ }
+ PxU8* MarkMem( PxU8* inMem, TMemAllocSizeType inSize )
+ {
+ PX_ASSERT( inSize >= sizeof( SVariableMemPoolNode ) );
+ SVariableMemPoolNode* theMem = reinterpret_cast<SVariableMemPoolNode*>( inMem );
+ theMem->mSize = inSize;
+ return reinterpret_cast< PxU8* >( theMem + 1 );
+ }
+ //Using deallocated memory to hold the pointers to the next amount of memory.
+ PxU8* allocate( PxU32 size )
+ {
+ //Ensure we can place the size of the memory at the start
+ //of the memory block.
+ //Kai: to reduce the size of hash map, the requested size is aligned to 128 bytes
+ PxU32 theRequestedSize = (size + sizeof(SVariableMemPoolNode) + 127) & ~127;
+
+ TFreeNodeMap::Entry* entry = const_cast<TFreeNodeMap::Entry*>( mFreeNodeMap.find( theRequestedSize ) );
+ if ( NULL != entry )
+ {
+ SVariableMemPoolNode* theNode = entry->second;
+ PX_ASSERT( NULL != theNode );
+ PX_ASSERT( theNode->mSize == theRequestedSize );
+ entry->second = theNode->NextNode();
+ if (entry->second == NULL)
+ mFreeNodeMap.erase( theRequestedSize );
+
+ return reinterpret_cast< PxU8* >( theNode + 1 );
+ }
+
+ if ( theRequestedSize < mMinAllocationSize )
+ theRequestedSize = mMinAllocationSize;
+
+ //No large enough free nodes, make some more.
+ PxU8* retval = reinterpret_cast<PxU8*>(mWrapper.getAllocator().allocate( size_t(theRequestedSize), "RepX variable sized memory pool", __FILE__, __LINE__ ));
+ //If we allocated it, we free it.
+ mAllMemory.pushBack( retval );
+ return MarkMem( retval, theRequestedSize );
+ }
+
+ //The size is stored at the beginning of the memory block.
+ void deallocate( PxU8* inData )
+ {
+ SVariableMemPoolNode* theData = reinterpret_cast< SVariableMemPoolNode* >( inData ) - 1;
+ TMemAllocSizeType theSize = theData->mSize;
+ AddFreeMem( reinterpret_cast< PxU8* >( theData ), theSize );
+ }
+
+ void CheckFreeListInvariant( SVariableMemPoolNode* inNode )
+ {
+ if ( inNode && inNode->mNextNode )
+ {
+ PX_ASSERT( inNode->mSize <= inNode->NextNode()->mSize );
+ }
+ }
+
+ void AddFreeMem( PxU8* inMemory, TMemAllocSizeType inSize )
+ {
+ PX_ASSERT( inSize >= sizeof( SVariableMemPoolNode ) );
+ SVariableMemPoolNode* theNewNode = reinterpret_cast< SVariableMemPoolNode* >( inMemory );
+ theNewNode->mNextNode = NULL;
+ theNewNode->mSize = inSize;
+ TFreeNodeMap::Entry* entry = const_cast<TFreeNodeMap::Entry*>( mFreeNodeMap.find( inSize ) );
+ if (NULL != entry)
+ {
+ theNewNode->mNextNode = entry->second;
+ entry->second = theNewNode;
+ }
+ else
+ {
+ mFreeNodeMap.insert( inSize, theNewNode );
+ }
+ }
+ };
+
+ /**
+ * The manager keeps a list of memory pools for different sizes of allocations.
+ * Anything too large simply gets allocated using the new operator.
+ * This doesn't mark the memory with the size of the allocated memory thus
+ * allowing much more efficient allocation of small items. For large enough
+ * allocations, it does mark the size.
+ *
+ * When using as a general memory manager, you need to wrap this class with
+ * something that actually does mark the returned allocation with the size
+ * of the allocation.
+ */
+ class CMemoryPoolManager
+ {
+ CMemoryPoolManager &operator=(const CMemoryPoolManager &);
+
+ public:
+ PxProfileAllocatorWrapper mWrapper;
+
+ //CMemoryPool<0,8> m0ItemPool;
+ //CMemoryPool<1,8> m1ItemPool;
+ //CMemoryPool<2,8> m2ItemPool;
+ //CMemoryPool<3,8> m3ItemPool;
+ //CMemoryPool<4,8> m4ItemPool;
+ //CMemoryPool<5,8> m5ItemPool;
+ //CMemoryPool<6,8> m6ItemPool;
+ //CMemoryPool<7,8> m7ItemPool;
+ //CMemoryPool<8,8> m8ItemPool;
+ CVariableMemoryPool mVariablePool;
+ CMemoryPoolManager( PxAllocatorCallback& inAllocator )
+ : mWrapper( inAllocator )
+ //, m0ItemPool( mWrapper )
+ //, m1ItemPool( mWrapper )
+ //, m2ItemPool( mWrapper )
+ //, m3ItemPool( mWrapper )
+ //, m4ItemPool( mWrapper )
+ //, m5ItemPool( mWrapper )
+ //, m6ItemPool( mWrapper )
+ //, m7ItemPool( mWrapper )
+ //, m8ItemPool( mWrapper )
+ , mVariablePool( mWrapper )
+ {
+ }
+ PxProfileAllocatorWrapper& getWrapper() { return mWrapper; }
+ inline PxU8* allocate( PxU32 inSize )
+ {
+ /*
+ if ( inSize <= m0ItemPool.GetItemSize() )
+ return m0ItemPool.allocate();
+ if ( inSize <= m1ItemPool.GetItemSize() )
+ return m1ItemPool.allocate();
+ if ( inSize <= m2ItemPool.GetItemSize() )
+ return m2ItemPool.allocate();
+ if ( inSize <= m3ItemPool.GetItemSize() )
+ return m3ItemPool.allocate();
+ if ( inSize <= m4ItemPool.GetItemSize() )
+ return m4ItemPool.allocate();
+ if ( inSize <= m5ItemPool.GetItemSize() )
+ return m5ItemPool.allocate();
+ if ( inSize <= m6ItemPool.GetItemSize() )
+ return m6ItemPool.allocate();
+ if ( inSize <= m7ItemPool.GetItemSize() )
+ return m7ItemPool.allocate();
+ if ( inSize <= m8ItemPool.GetItemSize() )
+ return m8ItemPool.allocate();
+ */
+ return mVariablePool.allocate( inSize );
+ }
+ inline void deallocate( PxU8* inMemory )
+ {
+ if ( inMemory == NULL )
+ return;
+ /*
+ if ( inSize <= m0ItemPool.GetItemSize() )
+ m0ItemPool.deallocate(inMemory);
+ else if ( inSize <= m1ItemPool.GetItemSize() )
+ m1ItemPool.deallocate(inMemory);
+ else if ( inSize <= m2ItemPool.GetItemSize() )
+ m2ItemPool.deallocate(inMemory);
+ else if ( inSize <= m3ItemPool.GetItemSize() )
+ m3ItemPool.deallocate(inMemory);
+ else if ( inSize <= m4ItemPool.GetItemSize() )
+ m4ItemPool.deallocate(inMemory);
+ else if ( inSize <= m5ItemPool.GetItemSize() )
+ m5ItemPool.deallocate(inMemory);
+ else if ( inSize <= m6ItemPool.GetItemSize() )
+ m6ItemPool.deallocate(inMemory);
+ else if ( inSize <= m7ItemPool.GetItemSize() )
+ m7ItemPool.deallocate(inMemory);
+ else if ( inSize <= m8ItemPool.GetItemSize() )
+ m8ItemPool.deallocate(inMemory);
+ else
+ */
+ mVariablePool.deallocate(inMemory);
+ }
+ /**
+ * allocate an object. Calls constructor on the new memory.
+ */
+ template<typename TObjectType>
+ inline TObjectType* allocate()
+ {
+ TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) ) );
+ new (retval)TObjectType();
+ return retval;
+ }
+
+ /**
+ * deallocate an object calling the destructor on the object.
+ * This *must* be the concrete type, it cannot be a generic type.
+ */
+ template<typename TObjectType>
+ inline void deallocate( TObjectType* inObject )
+ {
+ inObject->~TObjectType();
+ deallocate( reinterpret_cast<PxU8*>(inObject) );
+ }
+
+ /**
+ * allocate an object. Calls constructor on the new memory.
+ */
+ template<typename TObjectType>
+ inline TObjectType* BatchAllocate(PxU32 inCount )
+ {
+ TObjectType* retval = reinterpret_cast<TObjectType*>( allocate( sizeof(TObjectType) * inCount ) );
+ return retval;
+ }
+
+ /**
+ * deallocate an object calling the destructor on the object.
+ * This *must* be the concrete type, it cannot be a generic type.
+ */
+ template<typename TObjectType>
+ inline void BatchDeallocate( TObjectType* inObject, PxU32 inCount )
+ {
+ PX_UNUSED(inCount);
+ deallocate( reinterpret_cast<PxU8*>(inObject) );
+ }
+ };
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPoolStreams.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPoolStreams.h
new file mode 100644
index 00000000..375d1e2d
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlMemoryPoolStreams.h
@@ -0,0 +1,173 @@
+// 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_XML_MEMORY_POOL_STREAMS_H
+#define PX_XML_MEMORY_POOL_STREAMS_H
+
+#include "foundation/PxTransform.h"
+#include "foundation/PxIO.h"
+#include "SnXmlMemoryPool.h"
+#include "CmPhysXCommon.h"
+
+namespace physx {
+
+ template<typename TDataType>
+ struct XmlDefaultValue
+ {
+ bool force_compile_error;
+ };
+
+
+#define XML_DEFINE_DEFAULT_VALUE(type, defVal ) \
+ template<> \
+ struct XmlDefaultValue<type> \
+ { \
+ type getDefaultValue() { return type(defVal); } \
+ };
+
+ XML_DEFINE_DEFAULT_VALUE(PxU8, 0)
+ XML_DEFINE_DEFAULT_VALUE(PxI8, 0)
+ XML_DEFINE_DEFAULT_VALUE(PxU16, 0)
+ XML_DEFINE_DEFAULT_VALUE(PxI16, 0)
+ XML_DEFINE_DEFAULT_VALUE(PxU32, 0)
+ XML_DEFINE_DEFAULT_VALUE(PxI32, 0)
+ XML_DEFINE_DEFAULT_VALUE(PxU64, 0)
+ XML_DEFINE_DEFAULT_VALUE(PxI64, 0)
+ XML_DEFINE_DEFAULT_VALUE(PxF32, 0)
+ XML_DEFINE_DEFAULT_VALUE(PxF64, 0)
+
+#undef XML_DEFINE_DEFAULT_VALUE
+
+ template<>
+ struct XmlDefaultValue<PxVec3>
+ {
+ PxVec3 getDefaultValue() { return PxVec3( 0,0,0 ); }
+ };
+
+ template<>
+ struct XmlDefaultValue<PxTransform>
+ {
+ PxTransform getDefaultValue() { return PxTransform(PxIdentity); }
+ };
+
+ template<>
+ struct XmlDefaultValue<PxQuat>
+ {
+ PxQuat getDefaultValue() { return PxQuat(PxIdentity); }
+ };
+
+/**
+ * Mapping of PxOutputStream to a memory pool manager.
+ * Allows write-then-read semantics of a set of
+ * data. Can safely write up to 4GB of data; then you
+ * will silently fail...
+ */
+
+template<typename TAllocatorType>
+struct MemoryBufferBase : public PxOutputStream, public PxInputStream
+{
+ TAllocatorType* mManager;
+ mutable PxU32 mWriteOffset;
+ mutable PxU32 mReadOffset;
+ PxU8* mBuffer;
+ PxU32 mCapacity;
+
+
+ MemoryBufferBase( TAllocatorType* inManager )
+ : mManager( inManager )
+ , mWriteOffset( 0 )
+ , mReadOffset( 0 )
+ , mBuffer( NULL )
+ , mCapacity( 0 )
+ {
+ }
+ virtual ~MemoryBufferBase()
+ {
+ mManager->deallocate( mBuffer );
+ }
+ PxU8* releaseBuffer()
+ {
+ clear();
+ mCapacity = 0;
+ PxU8* retval(mBuffer);
+ mBuffer = NULL;
+ return retval;
+ }
+ void clear()
+ {
+ mWriteOffset = mReadOffset = 0;
+ }
+
+ virtual PxU32 read(void* dest, PxU32 count)
+ {
+ bool fits = ( mReadOffset + count ) <= mWriteOffset;
+ PX_ASSERT( fits );
+ if ( fits )
+ {
+ memcpy( dest, mBuffer + mReadOffset, count );
+ mReadOffset += count;
+ return count;
+ }
+ return 0;
+ }
+
+ inline void checkCapacity( PxU32 inNewCapacity )
+ {
+ if ( mCapacity < inNewCapacity )
+ {
+ PxU32 newCapacity = 32;
+ while( newCapacity < inNewCapacity )
+ newCapacity = newCapacity << 1;
+
+ PxU8* newData( mManager->allocate( newCapacity ) );
+ if ( mWriteOffset )
+ memcpy( newData, mBuffer, mWriteOffset );
+ mManager->deallocate( mBuffer );
+ mBuffer = newData;
+ mCapacity = newCapacity;
+ }
+ }
+
+ virtual PxU32 write(const void* src, PxU32 count)
+ {
+ checkCapacity( mWriteOffset + count );
+ memcpy( mBuffer + mWriteOffset, src, count );
+ mWriteOffset += count;
+ return count;
+ }
+};
+
+class MemoryBuffer : public MemoryBufferBase<CMemoryPoolManager >
+{
+public:
+ MemoryBuffer( CMemoryPoolManager* inManager ) : MemoryBufferBase<CMemoryPoolManager >( inManager ) {}
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlReader.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlReader.h
new file mode 100644
index 00000000..88053d96
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlReader.h
@@ -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.
+#ifndef PX_XML_READER_H
+#define PX_XML_READER_H
+
+#include "foundation/PxSimpleTypes.h"
+#include "extensions/PxRepXSimpleType.h"
+
+namespace physx {
+ namespace Sn { struct XmlNode; }
+
+ /**
+ * Reader used to read data out of the repx format.
+ */
+ class XmlReader
+ {
+ protected:
+ virtual ~XmlReader(){}
+ public:
+ /** Read a key-value pair out of the database */
+ virtual bool read( const char* inName, const char*& outData ) = 0;
+ /** Read an object id out of the database */
+ virtual bool read( const char* inName, PxSerialObjectId& outId ) = 0;
+ /** Goto a child element by name. That child becomes this reader's context */
+ virtual bool gotoChild( const char* inName ) = 0;
+ /** Goto the first child regardless of name */
+ virtual bool gotoFirstChild() = 0;
+ /** Goto the next sibling regardless of name */
+ virtual bool gotoNextSibling() = 0;
+ /** Count all children of the current object */
+ virtual PxU32 countChildren() = 0;
+ /** Get the name of the current item */
+ virtual const char* getCurrentItemName() = 0;
+ /** Get the value of the current item */
+ virtual const char* getCurrentItemValue() = 0;
+ /** Leave the current child */
+ virtual bool leaveChild() = 0;
+ /** Get reader for the parental object */
+ virtual XmlReader* getParentReader() = 0;
+
+ /**
+ * Ensures we don't leave the reader in an odd state
+ * due to not leaving a given child
+ */
+ virtual void pushCurrentContext() = 0;
+ /** Pop the current context back to where it during push*/
+ virtual void popCurrentContext() = 0;
+ };
+
+ //Used when upgrading a repx collection
+ class XmlReaderWriter : public XmlReader
+ {
+ public:
+ //Clears the stack of nodes (push/pop current node reset)
+ //and sets the current node to inNode.
+ virtual void setNode( Sn::XmlNode& node ) = 0;
+ //If the child exists, add it.
+ //the either way goto that child.
+ virtual void addOrGotoChild( const char* name ) = 0;
+ //Value is copied into the collection, inValue has no further references
+ //to it.
+ virtual void setCurrentItemValue( const char* value ) = 0;
+ //Removes the child but does not release the char* name or char* data ptrs.
+ //Those pointers are never released and are shared among collections.
+ //Thus copying nodes is cheap and safe.
+ virtual bool removeChild( const char* name ) = 0;
+ virtual void release() = 0;
+
+ bool renameProperty( const char* oldName, const char* newName )
+ {
+ if ( gotoChild( oldName ) )
+ {
+ const char* value = getCurrentItemValue();
+ leaveChild();
+ removeChild( oldName );
+ addOrGotoChild( newName );
+ setCurrentItemValue( value );
+ leaveChild();
+ return true;
+ }
+ return false;
+ }
+ bool readAndRemoveProperty( const char* name, const char*& outValue )
+ {
+ bool retval = read( name, outValue );
+ if ( retval ) removeChild( name );
+ return retval;
+ }
+
+ bool writePropertyIfNotEmpty( const char* name, const char* value )
+ {
+ if ( value && *value )
+ {
+ addOrGotoChild( name );
+ setCurrentItemValue( value );
+ leaveChild();
+ return true;
+ }
+ return false;
+ }
+ };
+
+}
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerialization.cpp b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerialization.cpp
new file mode 100644
index 00000000..af86eafd
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerialization.cpp
@@ -0,0 +1,834 @@
+// 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 "SnXmlImpl.h"
+#include "PsHash.h"
+#include "PsHashMap.h"
+#include "SnSimpleXmlWriter.h"
+#include "PsSort.h"
+#include "PsFastXml.h"
+#include "PsString.h"
+#include "SnXmlMemoryPool.h"
+#include "PxExtensionMetaDataObjects.h"
+#include "SnXmlVisitorWriter.h"
+#include "SnXmlVisitorReader.h"
+#include "SnXmlMemoryAllocator.h"
+#include "SnXmlStringToType.h"
+#include "PsString.h"
+#include "SnRepXCollection.h"
+#include "SnRepXUpgrader.h"
+#include "../SnSerializationRegistry.h"
+#include "PsFoundation.h"
+#include "CmCollection.h"
+
+using namespace physx;
+using namespace Sn;
+
+using namespace physx::profile; //for the foundation wrapper system.
+
+namespace physx { namespace Sn {
+
+ class XmlNodeWriter : public SimpleXmlWriter
+ {
+ XmlMemoryAllocatorImpl& mParseAllocator;
+ XmlNode* mCurrentNode;
+ XmlNode* mTopNode;
+ PxU32 mTabCount;
+
+ public:
+ XmlNodeWriter( XmlMemoryAllocatorImpl& inAllocator, PxU32 inTabCount = 0 )
+ : mParseAllocator( inAllocator )
+ , mCurrentNode( NULL )
+ , mTopNode( NULL )
+ , mTabCount( inTabCount )
+ {}
+ XmlNodeWriter& operator=(const XmlNodeWriter&);
+ virtual ~XmlNodeWriter(){}
+ void onNewNode( XmlNode* newNode )
+ {
+ if ( mCurrentNode != NULL )
+ mCurrentNode->addChild( newNode );
+ if ( mTopNode == NULL )
+ mTopNode = newNode;
+ mCurrentNode = newNode;
+ ++mTabCount;
+ }
+
+ XmlNode* getTopNode() const { return mTopNode; }
+
+ virtual void beginTag( const char* inTagname )
+ {
+ onNewNode( allocateRepXNode( &mParseAllocator.mManager, inTagname, NULL ) );
+ }
+ virtual void endTag()
+ {
+ if ( mCurrentNode )
+ mCurrentNode = mCurrentNode->mParent;
+ if ( mTabCount )
+ --mTabCount;
+ }
+ virtual void addAttribute( const char*, const char* )
+ {
+ PX_ASSERT( false );
+ }
+ virtual void writeContentTag( const char* inTag, const char* inContent )
+ {
+ onNewNode( allocateRepXNode( &mParseAllocator.mManager, inTag, inContent ) );
+ endTag();
+ }
+ virtual void addContent( const char* inContent )
+ {
+ if ( mCurrentNode->mData )
+ releaseStr( &mParseAllocator.mManager, mCurrentNode->mData );
+ mCurrentNode->mData = copyStr( &mParseAllocator.mManager, inContent );
+ }
+ virtual PxU32 tabCount() { return mTabCount; }
+ };
+
+ struct XmlWriterImpl : public XmlWriter
+ {
+ PxU32 mTagDepth;
+ SimpleXmlWriter* mWriter;
+ MemoryBuffer* mMemBuffer;
+
+ XmlWriterImpl( SimpleXmlWriter* inWriter, MemoryBuffer* inMemBuffer )
+ : mTagDepth( 0 )
+ , mWriter( inWriter )
+ , mMemBuffer( inMemBuffer )
+ {
+ }
+ ~XmlWriterImpl()
+ {
+ while( mTagDepth )
+ {
+ --mTagDepth;
+ mWriter->endTag();
+ }
+ }
+ virtual void write( const char* inName, const char* inData )
+ {
+ mWriter->writeContentTag( inName, inData );
+ }
+ virtual void write( const char* inName, const PxRepXObject& inLiveObject )
+ {
+ (*mMemBuffer) << inLiveObject.id;
+ writeProperty( *mWriter, *mMemBuffer, inName );
+ }
+ virtual void addAndGotoChild( const char* inName )
+ {
+ mWriter->beginTag( inName );
+ mTagDepth++;
+ }
+ virtual void leaveChild()
+ {
+ if ( mTagDepth )
+ {
+ mWriter->endTag();
+ --mTagDepth;
+ }
+ }
+ };
+
+ struct XmlParseArgs
+ {
+ XmlMemoryAllocatorImpl* mAllocator;
+ PxProfileArray<RepXCollectionItem>* mCollection;
+
+ XmlParseArgs( XmlMemoryAllocatorImpl* inAllocator
+ , PxProfileArray<RepXCollectionItem>* inCollection)
+ : mAllocator( inAllocator )
+ , mCollection( inCollection )
+ {
+ }
+ };
+
+ struct XmlNodeReader : public XmlReaderWriter
+ {
+ PxProfileAllocatorWrapper mWrapper;
+ CMemoryPoolManager& mManager;
+ XmlNode* mCurrentNode;
+ XmlNode* mTopNode;
+ PxProfileArray<XmlNode*> mContext;
+ XmlNodeReader( XmlNode* inCurrentNode, PxAllocatorCallback& inAllocator, CMemoryPoolManager& nodePoolManager )
+ : mWrapper( inAllocator )
+ , mManager( nodePoolManager )
+ , mCurrentNode( inCurrentNode )
+ , mTopNode( inCurrentNode )
+ , mContext( mWrapper )
+ {
+ }
+
+ //Does this node exist as data in the format.
+ virtual bool read( const char* inName, const char*& outData )
+ {
+ XmlNode* theChild( mCurrentNode->findChildByName( inName ) );
+ if ( theChild )
+ {
+ outData = theChild->mData;
+ return outData && *outData;
+ }
+ return false;
+ }
+
+ virtual bool read( const char* inName, PxSerialObjectId& outId )
+ {
+ XmlNode* theChild( mCurrentNode->findChildByName( inName ) );
+ if ( theChild )
+ {
+ const char* theValue( theChild->mData );
+ strto( outId, theValue );
+ return true;
+ }
+ return false;
+ }
+
+ virtual bool gotoChild( const char* inName )
+ {
+ XmlNode* theChild( mCurrentNode->findChildByName( inName ) );
+ if ( theChild )
+ {
+ mCurrentNode =theChild;
+ return true;
+ }
+ return false;
+ }
+ virtual bool gotoFirstChild()
+ {
+ if ( mCurrentNode->mFirstChild )
+ {
+ mCurrentNode = mCurrentNode->mFirstChild;
+ return true;
+ }
+ return false;
+ }
+ virtual bool gotoNextSibling()
+ {
+ if ( mCurrentNode->mNextSibling )
+ {
+ mCurrentNode = mCurrentNode->mNextSibling;
+ return true;
+ }
+ return false;
+ }
+ virtual PxU32 countChildren()
+ {
+ PxU32 retval= 0;
+ for ( XmlNode* theChild = mCurrentNode->mFirstChild; theChild != NULL; theChild = theChild->mNextSibling )
+ ++retval;
+ return retval;
+ }
+ virtual const char* getCurrentItemName()
+ {
+ return mCurrentNode->mName;
+ }
+ virtual const char* getCurrentItemValue()
+ {
+ return mCurrentNode->mData;
+ }
+
+ virtual bool leaveChild()
+ {
+ if ( mCurrentNode != mTopNode && mCurrentNode->mParent )
+ {
+ mCurrentNode = mCurrentNode->mParent;
+ return true;
+ }
+ return false;
+ }
+
+ virtual void pushCurrentContext()
+ {
+ mContext.pushBack( mCurrentNode );
+ }
+ virtual void popCurrentContext()
+ {
+ if ( mContext.size() )
+ {
+ mCurrentNode = mContext.back();
+ mContext.popBack();
+ }
+ }
+
+ virtual void setNode( XmlNode& inNode )
+ {
+ mContext.clear();
+ mCurrentNode = &inNode;
+ mTopNode = mCurrentNode;
+ }
+
+ virtual XmlReader* getParentReader()
+ {
+ XmlReader* retval = PX_PLACEMENT_NEW((mWrapper.getAllocator().allocate(sizeof(XmlNodeReader), "createNodeEditor", __FILE__, __LINE__ )), XmlNodeReader)
+ ( mTopNode, mWrapper.getAllocator(), mManager );
+ return retval;
+ }
+
+ virtual void addOrGotoChild( const char* inName )
+ {
+ if ( gotoChild( inName )== false )
+ {
+ XmlNode* newNode = allocateRepXNode( &mManager, inName, NULL );
+ mCurrentNode->addChild( newNode );
+ mCurrentNode = newNode;
+ }
+ }
+ virtual void setCurrentItemValue( const char* inValue )
+ {
+ mCurrentNode->mData = copyStr( &mManager, inValue );
+ }
+ virtual bool removeChild( const char* name )
+ {
+ XmlNode* theChild( mCurrentNode->findChildByName( name ) );
+ if ( theChild )
+ {
+ releaseNodeAndChildren( &mManager, theChild );
+ return true;
+ }
+ return false;
+ }
+ virtual void release() { this->~XmlNodeReader(); mWrapper.getAllocator().deallocate(this); }
+
+ private:
+ XmlNodeReader& operator=(const XmlNodeReader&);
+ };
+
+ PX_INLINE void freeNodeAndChildren( XmlNode* tempNode, TMemoryPoolManager& inManager )
+ {
+ for( XmlNode* theNode = tempNode->mFirstChild; theNode != NULL; theNode = theNode->mNextSibling )
+ freeNodeAndChildren( theNode, inManager );
+ tempNode->orphan();
+ release( &inManager, tempNode );
+ }
+
+ class XmlParser : public Ps::FastXml::Callback
+ {
+ XmlParseArgs mParseArgs;
+ //For parse time only allocations
+ XmlMemoryAllocatorImpl& mParseAllocator;
+ XmlNode* mCurrentNode;
+ XmlNode* mTopNode;
+
+ public:
+ XmlParser( XmlParseArgs inArgs, XmlMemoryAllocatorImpl& inParseAllocator )
+ : mParseArgs( inArgs )
+ , mParseAllocator( inParseAllocator )
+ , mCurrentNode( NULL )
+ , mTopNode( NULL )
+ {
+ }
+
+ virtual ~XmlParser(){}
+
+ virtual bool processComment(const char* /*comment*/) { return true; }
+ // 'element' is the name of the element that is being closed.
+ // depth is the recursion depth of this element.
+ // Return true to continue processing the XML file.
+ // Return false to stop processing the XML file; leaves the read pointer of the stream right after this close tag.
+ // The bool 'isError' indicates whether processing was stopped due to an error, or intentionally canceled early.
+ virtual bool processClose(const char* /*element*/,physx::PxU32 /*depth*/,bool& /*isError*/)
+ {
+ mCurrentNode = mCurrentNode->mParent;
+ return true;
+ }
+
+ // return true to continue processing the XML document, false to skip.
+ virtual bool processElement(
+ const char *elementName, // name of the element
+ const char *elementData, // element data, null if none
+ const Ps::FastXml::AttributePairs& attr, // attributes
+ PxI32 /*lineno*/)
+ {
+ XmlNode* newNode = allocateRepXNode( &mParseAllocator.mManager, elementName, elementData );
+ if ( mCurrentNode )
+ mCurrentNode->addChild( newNode );
+ mCurrentNode = newNode;
+ //Add the elements as children.
+ for( PxI32 item = 0; item < attr.getNbAttr(); item ++ )
+ {
+ XmlNode* node = allocateRepXNode( &mParseAllocator.mManager, attr.getKey(PxU32(item)), attr.getValue(PxU32(item)) );
+ mCurrentNode->addChild( node );
+ }
+ if ( mTopNode == NULL ) mTopNode = newNode;
+ return true;
+ }
+
+ XmlNode* getTopNode() { return mTopNode; }
+
+ virtual void * allocate(PxU32 size)
+ {
+ if ( size )
+ return mParseAllocator.allocate(size);
+ return NULL;
+ }
+ virtual void deallocate(void *mem)
+ {
+ if ( mem )
+ mParseAllocator.deallocate(reinterpret_cast<PxU8*>(mem));
+ }
+
+ private:
+ XmlParser& operator=(const XmlParser&);
+ };
+
+ struct RepXCollectionSharedData
+ {
+ PxProfileAllocatorWrapper mWrapper;
+ XmlMemoryAllocatorImpl mAllocator;
+ PxU32 mRefCount;
+
+ RepXCollectionSharedData( PxAllocatorCallback& inAllocator )
+ : mWrapper( inAllocator )
+ , mAllocator( inAllocator )
+ , mRefCount( 0 )
+ {
+ }
+ ~RepXCollectionSharedData() {}
+
+ void addRef() { ++mRefCount;}
+ void release()
+ {
+ if ( mRefCount ) --mRefCount;
+ if ( !mRefCount ) { this->~RepXCollectionSharedData(); mWrapper.getAllocator().deallocate(this);}
+ }
+ };
+
+ struct SharedDataPtr
+ {
+ RepXCollectionSharedData* mData;
+ SharedDataPtr( RepXCollectionSharedData* inData )
+ : mData( inData )
+ {
+ mData->addRef();
+ }
+ SharedDataPtr( const SharedDataPtr& inOther )
+ : mData( inOther.mData )
+ {
+ mData->addRef();
+ }
+ SharedDataPtr& operator=( const SharedDataPtr& inOther );
+ ~SharedDataPtr()
+ {
+ mData->release();
+ mData = NULL;
+ }
+ RepXCollectionSharedData* operator->() { return mData; }
+ const RepXCollectionSharedData* operator->() const { return mData; }
+ };
+
+ class RepXCollectionImpl : public RepXCollection, public Ps::UserAllocated
+ {
+ SharedDataPtr mSharedData;
+
+ XmlMemoryAllocatorImpl& mAllocator;
+ PxSerializationRegistry& mSerializationRegistry;
+ PxProfileArray<RepXCollectionItem> mCollection;
+ TMemoryPoolManager mSerializationManager;
+ MemoryBuffer mPropertyBuffer;
+ PxTolerancesScale mScale;
+ PxVec3 mUpVector;
+ const char* mVersionStr;
+ PxCollection* mPxCollection;
+
+ public:
+ RepXCollectionImpl( PxSerializationRegistry& inRegistry, PxAllocatorCallback& inAllocator, PxCollection& inPxCollection )
+ : mSharedData( &PX_NEW_REPX_SERIALIZER( RepXCollectionSharedData ))
+ , mAllocator( mSharedData->mAllocator )
+ , mSerializationRegistry( inRegistry )
+ , mCollection( mSharedData->mWrapper )
+ , mSerializationManager( inAllocator )
+ , mPropertyBuffer( &mSerializationManager )
+ , mUpVector( 0,0,0 )
+ , mVersionStr( getLatestVersion() )
+ , mPxCollection( &inPxCollection )
+ {
+ memset( &mScale, 0, sizeof( PxTolerancesScale ) );
+ PX_ASSERT( mScale.isValid() == false );
+ }
+
+ RepXCollectionImpl( PxSerializationRegistry& inRegistry, const RepXCollectionImpl& inSrc, const char* inNewVersion )
+ : mSharedData( inSrc.mSharedData )
+ , mAllocator( mSharedData->mAllocator )
+ , mSerializationRegistry( inRegistry )
+ , mCollection( mSharedData->mWrapper )
+ , mSerializationManager( mSharedData->mWrapper.getAllocator() )
+ , mPropertyBuffer( &mSerializationManager )
+ , mScale( inSrc.mScale )
+ , mUpVector( inSrc.mUpVector )
+ , mVersionStr( inNewVersion )
+ , mPxCollection( NULL )
+ {
+ }
+
+ virtual ~RepXCollectionImpl()
+ {
+ PxU32 numItems = mCollection.size();
+ for ( PxU32 idx = 0; idx < numItems; ++idx )
+ {
+ XmlNode* theNode = mCollection[idx].descriptor;
+ releaseNodeAndChildren( &mAllocator.mManager, theNode );
+ }
+ }
+ RepXCollectionImpl& operator=(const RepXCollectionImpl&);
+
+ virtual void destroy()
+ {
+ PxProfileAllocatorWrapper tempWrapper( mSharedData->mWrapper.getAllocator() );
+ this->~RepXCollectionImpl();
+ tempWrapper.getAllocator().deallocate(this);
+ }
+
+ virtual void setTolerancesScale(const PxTolerancesScale& inScale) { mScale = inScale; }
+ virtual PxTolerancesScale getTolerancesScale() const { return mScale; }
+ virtual void setUpVector( const PxVec3& inUpVector ) { mUpVector = inUpVector; }
+ virtual PxVec3 getUpVector() const { return mUpVector; }
+
+
+ PX_INLINE RepXCollectionItem findItemBySceneItem( const PxRepXObject& inObject ) const
+ {
+ //See if the object is in the collection
+ for ( PxU32 idx =0; idx < mCollection.size(); ++idx )
+ if ( mCollection[idx].liveObject.serializable == inObject.serializable )
+ return mCollection[idx];
+ return RepXCollectionItem();
+ }
+
+ virtual RepXAddToCollectionResult addRepXObjectToCollection( const PxRepXObject& inObject, PxCollection* inCollection, PxRepXInstantiationArgs& inArgs )
+ {
+ PX_ASSERT( inObject.serializable );
+ PX_ASSERT( inObject.id );
+ if ( inObject.serializable == NULL || inObject.id == 0 )
+ return RepXAddToCollectionResult( RepXAddToCollectionResult::InvalidParameters );
+
+ PxRepXSerializer* theSerializer = mSerializationRegistry.getRepXSerializer( inObject.typeName );
+ if ( theSerializer == NULL )
+ return RepXAddToCollectionResult( RepXAddToCollectionResult::SerializerNotFound );
+
+ RepXCollectionItem existing = findItemBySceneItem( inObject );
+ if ( existing.liveObject.serializable )
+ return RepXAddToCollectionResult( RepXAddToCollectionResult::AlreadyInCollection, existing.liveObject.id );
+
+ XmlNodeWriter theXmlWriter( mAllocator, 1 );
+ XmlWriterImpl theRepXWriter( &theXmlWriter, &mPropertyBuffer );
+ {
+ SimpleXmlWriter::STagWatcher theWatcher( theXmlWriter, inObject.typeName );
+ writeProperty( theXmlWriter, mPropertyBuffer, "Id", inObject.id );
+ theSerializer->objectToFile( inObject, inCollection, theRepXWriter, mPropertyBuffer,inArgs );
+ }
+ mCollection.pushBack( RepXCollectionItem( inObject, theXmlWriter.getTopNode() ) );
+ return RepXAddToCollectionResult( RepXAddToCollectionResult::Success, inObject.id );
+ }
+
+ virtual bool instantiateCollection( PxRepXInstantiationArgs& inArgs, PxCollection& inCollection )
+ {
+ for ( PxU32 idx =0; idx < mCollection.size(); ++idx )
+ {
+ RepXCollectionItem theItem( mCollection[idx] );
+ PxRepXSerializer* theSerializer = mSerializationRegistry.getRepXSerializer( theItem.liveObject.typeName );
+ if (theSerializer )
+ {
+ XmlNodeReader theReader( theItem.descriptor, mAllocator.getAllocator(), mAllocator.mManager );
+ XmlMemoryAllocatorImpl instantiationAllocator( mAllocator.getAllocator() );
+ PxRepXObject theLiveObject = theSerializer->fileToObject( theReader, instantiationAllocator, inArgs, &inCollection );
+ if (theLiveObject.isValid())
+ {
+ const PxBase* s = reinterpret_cast<const PxBase*>( theLiveObject.serializable ) ;
+ inCollection.add( *const_cast<PxBase*>(s), PxSerialObjectId( theItem.liveObject.id ));
+ }
+ else
+ return false;
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "PxSerialization::createCollectionFromXml: "
+ "PxRepXSerializer missing for type %s", theItem.liveObject.typeName);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ void saveXmlNode( XmlNode* inNode, SimpleXmlWriter& inWriter )
+ {
+ XmlNode* theNode( inNode );
+ if ( theNode->mData && *theNode->mData && theNode->mFirstChild == NULL )
+ inWriter.writeContentTag( theNode->mName, theNode->mData );
+ else
+ {
+ inWriter.beginTag( theNode->mName );
+ if ( theNode->mData && *theNode->mData )
+ inWriter.addContent( theNode->mData );
+ for ( XmlNode* theChild = theNode->mFirstChild;
+ theChild != NULL;
+ theChild = theChild->mNextSibling )
+ saveXmlNode( theChild, inWriter );
+ inWriter.endTag();
+ }
+ }
+
+ virtual void save( PxOutputStream& inStream )
+ {
+ SimpleXmlWriterImpl<PxOutputStream> theWriter( inStream, mAllocator.getAllocator() );
+ theWriter.beginTag( "PhysX30Collection" );
+ theWriter.addAttribute( "version", mVersionStr );
+ {
+ XmlWriterImpl theRepXWriter( &theWriter, &mPropertyBuffer );
+ writeProperty( theWriter, mPropertyBuffer, "UpVector", mUpVector );
+ theRepXWriter.addAndGotoChild( "Scale" );
+ writeAllProperties( &mScale, theRepXWriter, mPropertyBuffer, *mPxCollection);
+ theRepXWriter.leaveChild();
+ }
+ for ( PxU32 idx =0; idx < mCollection.size(); ++idx )
+ {
+ RepXCollectionItem theItem( mCollection[idx] );
+ XmlNode* theNode( theItem.descriptor );
+ saveXmlNode( theNode, theWriter );
+ }
+ }
+
+ void load( PxInputData& inFileBuf, SerializationRegistry& s )
+ {
+ inFileBuf.seek(0);
+ XmlParser theParser( XmlParseArgs( &mAllocator, &mCollection ), mAllocator );
+ Ps::FastXml* theFastXml = Ps::createFastXml( &theParser );
+ theFastXml->processXml( inFileBuf );
+ XmlNode* theTopNode = theParser.getTopNode();
+ if ( theTopNode != NULL )
+ {
+ {
+
+ XmlMemoryAllocatorImpl instantiationAllocator( mAllocator.getAllocator() );
+ XmlNodeReader theReader( theTopNode, mAllocator.getAllocator(), mAllocator.mManager );
+ readProperty( theReader, "UpVector", mUpVector );
+ if ( theReader.gotoChild( "Scale" ) )
+ {
+ readAllProperties( PxRepXInstantiationArgs( s.getPhysics() ), theReader, &mScale, instantiationAllocator, *mPxCollection);
+ theReader.leaveChild();
+ }
+ const char* verStr = NULL;
+ if ( theReader.read( "version", verStr ) )
+ mVersionStr = verStr;
+ }
+ for ( XmlNode* theChild = theTopNode->mFirstChild;
+ theChild != NULL;
+ theChild = theChild->mNextSibling )
+ {
+ if ( physx::shdfnd::stricmp( theChild->mName, "scale" ) == 0
+ || physx::shdfnd::stricmp( theChild->mName, "version" ) == 0
+ || physx::shdfnd::stricmp( theChild->mName, "upvector" ) == 0 )
+ continue;
+ XmlNodeReader theReader( theChild, mAllocator.getAllocator(), mAllocator.mManager );
+ PxRepXObject theObject;
+ theObject.typeName = theChild->mName;
+ theObject.serializable = NULL;
+ PxSerialObjectId theId = 0;
+ theReader.read( "Id", theId );
+ theObject.id = theId;
+ mCollection.pushBack( RepXCollectionItem( theObject, theChild ) );
+ }
+ }
+ else
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "Cannot parse any object from the input buffer, please check the input repx data.");
+ }
+ theFastXml->release();
+ }
+
+ virtual const char* getVersion() { return mVersionStr; }
+
+ virtual const RepXCollectionItem* begin() const
+ {
+ return mCollection.begin();
+ }
+ virtual const RepXCollectionItem* end() const
+ {
+ return mCollection.end();
+ }
+
+ virtual RepXCollection& createCollection( const char* inVersionStr )
+ {
+ PxAllocatorCallback& allocator = mSharedData->mWrapper.getAllocator();
+ RepXCollectionImpl* retval = PX_PLACEMENT_NEW((allocator.allocate(sizeof(RepXCollectionImpl), "createCollection", __FILE__, __LINE__ )), RepXCollectionImpl) ( mSerializationRegistry, *this, inVersionStr );
+
+ return *retval;
+ }
+
+ //Performs a deep copy of the repx node.
+ virtual XmlNode* copyRepXNode( const XmlNode* srcNode )
+ {
+ return physx::Sn::copyRepXNode( &mAllocator.mManager, srcNode );
+ }
+
+ virtual void addCollectionItem( RepXCollectionItem inItem )
+ {
+ mCollection.pushBack( inItem );
+ }
+
+ virtual PxAllocatorCallback& getAllocator() { return mSharedData->mAllocator.getAllocator(); }
+ //Create a new repx node with this name. Its value is unset.
+ virtual XmlNode& createRepXNode( const char* name )
+ {
+ XmlNode* newNode = allocateRepXNode( &mSharedData->mAllocator.mManager, name, NULL );
+ return *newNode;
+ }
+
+ //Release this when finished.
+ virtual XmlReaderWriter& createNodeEditor()
+ {
+ PxAllocatorCallback& allocator = mSharedData->mWrapper.getAllocator();
+ XmlReaderWriter* retval = PX_PLACEMENT_NEW((allocator.allocate(sizeof(XmlNodeReader), "createNodeEditor", __FILE__, __LINE__ )), XmlNodeReader) ( NULL, allocator, mAllocator.mManager );
+ return *retval;
+ }
+ };
+
+ const char* RepXCollection::getLatestVersion()
+ {
+#define TOSTR_(x) #x
+#define CONCAT_(a, b, c) TOSTR_(a.##b.##c)
+#define MAKE_VERSION_STR(a,b,c) CONCAT_(a, b, c)
+
+ return MAKE_VERSION_STR(PX_PHYSICS_VERSION_MAJOR,PX_PHYSICS_VERSION_MINOR,PX_PHYSICS_VERSION_BUGFIX);
+
+ }
+
+ static RepXCollection* create(SerializationRegistry& s, PxAllocatorCallback& inAllocator, PxCollection& inCollection )
+ {
+ return PX_PLACEMENT_NEW((inAllocator.allocate(sizeof(RepXCollectionImpl), "RepXCollection::create", __FILE__, __LINE__ )), RepXCollectionImpl) ( s, inAllocator, inCollection );
+ }
+
+ static RepXCollection* create(SerializationRegistry& s, PxInputData &data, PxAllocatorCallback& inAllocator, PxCollection& inCollection )
+ {
+ RepXCollectionImpl* theCollection = static_cast<RepXCollectionImpl*>( create(s, inAllocator, inCollection ) );
+ theCollection->load( data, s );
+ return theCollection;
+ }
+}
+
+ bool PxSerialization::serializeCollectionToXml( PxOutputStream& outputStream, PxCollection& collection, PxSerializationRegistry& sr, PxCooking* cooking, const PxCollection* externalRefs, PxXmlMiscParameter* inArgs )
+ {
+ if( !PxSerialization::isSerializable(collection, sr, const_cast<PxCollection*>(externalRefs)) )
+ return false;
+
+ bool bRet = true;
+
+ SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
+ PxRepXInstantiationArgs args( sn.getPhysics(), cooking );
+
+ PxCollection* tmpCollection = PxCreateCollection();
+ PX_ASSERT(tmpCollection);
+
+ tmpCollection->add( collection );
+ if(externalRefs)
+ {
+ tmpCollection->add(*const_cast<PxCollection*>(externalRefs));
+ }
+
+ PxAllocatorCallback& allocator = PxGetFoundation().getAllocatorCallback();
+ Sn::RepXCollection* theRepXCollection = Sn::create(sn, allocator, *tmpCollection );
+
+ if(inArgs != NULL)
+ {
+ theRepXCollection->setTolerancesScale(inArgs->scale);
+ theRepXCollection->setUpVector(inArgs->upVector);
+ }
+
+ PxU32 nbObjects = collection.getNbObjects();
+ if( nbObjects )
+ {
+ sortCollection( static_cast<Cm::Collection&>(collection), sn, true);
+
+ for( PxU32 i = 0; i < nbObjects; i++ )
+ {
+ PxBase& s = collection.getObject(i);
+ if( PxConcreteType::eSHAPE == s.getConcreteType() )
+ {
+ PxShape& shape = static_cast<PxShape&>(s);
+ if( shape.isExclusive() )
+ continue;
+ }
+
+ PxSerialObjectId id = collection.getId(s);
+ if(id == PX_SERIAL_OBJECT_ID_INVALID)
+ id = static_cast<PxSerialObjectId>( reinterpret_cast<size_t>( &s ));
+
+ PxRepXObject ro = PxCreateRepXObject( &s, id );
+ if ( ro.serializable == NULL || ro.id == 0 )
+ {
+ bRet = false;
+ break;
+ }
+
+ theRepXCollection->addRepXObjectToCollection( ro, tmpCollection, args );
+ }
+ }
+ tmpCollection->release();
+
+ theRepXCollection->save(outputStream);
+ theRepXCollection->destroy();
+
+
+ return bRet;
+ }
+
+ PxCollection* PxSerialization::createCollectionFromXml(PxInputData& inputData, PxCooking& cooking, PxSerializationRegistry& sr, const PxCollection* externalRefs, PxStringTable* stringTable, PxXmlMiscParameter* outArgs)
+ {
+ SerializationRegistry& sn = static_cast<SerializationRegistry&>(sr);
+ PxCollection* collection = PxCreateCollection();
+ PX_ASSERT(collection);
+
+ if( externalRefs )
+ collection->add(*const_cast<PxCollection*>(externalRefs));
+
+ PxAllocatorCallback& allocator = PxGetFoundation().getAllocatorCallback();
+ Sn::RepXCollection* theRepXCollection = Sn::create(sn, inputData, allocator, *collection);
+ theRepXCollection = &Sn::RepXUpgrader::upgradeCollection( *theRepXCollection );
+
+ PxRepXInstantiationArgs args( sn.getPhysics(), &cooking, stringTable );
+ if( !theRepXCollection->instantiateCollection(args, *collection) )
+ {
+ collection->release();
+ theRepXCollection->destroy();
+ return NULL;
+ }
+
+ if( externalRefs )
+ collection->remove(*const_cast<PxCollection*>(externalRefs));
+
+ if(outArgs != NULL)
+ {
+ outArgs->upVector = theRepXCollection->getUpVector();
+ outArgs->scale = theRepXCollection->getTolerancesScale();
+ }
+
+ theRepXCollection->destroy();
+
+ return collection;
+ }
+}
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerializer.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerializer.h
new file mode 100644
index 00000000..9effab4f
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSerializer.h
@@ -0,0 +1,117 @@
+// 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_XML_SERIALIZER_H
+#define PX_XML_SERIALIZER_H
+
+#include "PxExtensionMetaDataObjects.h"
+#include "SnXmlVisitorWriter.h"
+
+namespace physx {
+
+namespace Sn {
+
+ void writeHeightFieldSample( PxOutputStream& inStream, const PxHeightFieldSample& inSample )
+ {
+ PxU32 retval = 0;
+ PxU8* writePtr( reinterpret_cast< PxU8*>( &retval ) );
+ const PxU8* inPtr( reinterpret_cast<const PxU8*>( &inSample ) );
+ if ( isBigEndian() )
+ {
+ //Height field samples are a
+ //16 bit integer followed by two bytes.
+ //right now, data is 2 1 3 4
+ //We need a 32 bit integer that
+ //when read in by a LE system is 4 3 2 1.
+ //Thus, we need a BE integer that looks like:
+ //4 3 2 1
+
+ writePtr[0] = inPtr[3];
+ writePtr[1] = inPtr[2];
+ writePtr[2] = inPtr[0];
+ writePtr[3] = inPtr[1];
+ }
+ else
+ {
+ writePtr[0] = inPtr[0];
+ writePtr[1] = inPtr[1];
+ writePtr[2] = inPtr[2];
+ writePtr[3] = inPtr[3];
+ }
+ inStream << retval;
+ }
+
+
+
+ template<typename TDataType, typename TWriteOperator>
+ inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const void* inData, PxU32 inStride, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inOperator )
+ {
+ PX_ASSERT( inStride == 0 || inStride == sizeof( TDataType ) );
+ PX_UNUSED( inStride );
+ writeBuffer( writer, tempBuffer
+ , inItemsPerLine, reinterpret_cast<const TDataType*>( inData )
+ , inCount, inPropName, inOperator );
+ }
+
+ template<typename TDataType, typename TWriteOperator>
+ inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const PxStridedData& inData, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inOperator )
+ {
+ writeStridedBufferProperty<TDataType>( writer, tempBuffer, inPropName, inData.data, inData.stride, inCount, inItemsPerLine, inOperator );
+ }
+
+ template<typename TDataType, typename TWriteOperator>
+ inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const PxTypedStridedData<TDataType>& inData, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inOperator )
+ {
+ writeStridedBufferProperty<TDataType>( writer, tempBuffer, inPropName, inData.data, inData.stride, inCount, inItemsPerLine, inOperator );
+ }
+
+ template<typename TDataType, typename TWriteOperator>
+ inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, const PxBoundedData& inData, PxU32 inItemsPerLine, TWriteOperator inWriteOperator )
+ {
+ writeStridedBufferProperty<TDataType>( writer, tempBuffer, inPropName, inData, inData.count, inItemsPerLine, inWriteOperator );
+ }
+
+ template<typename TDataType, typename TWriteOperator>
+ inline void writeStridedBufferProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, PxStrideIterator<const TDataType>& inData, PxU32 inCount, PxU32 inItemsPerLine, TWriteOperator inWriteOperator )
+ {
+ writeStrideBuffer<TDataType>(writer, tempBuffer
+ , inItemsPerLine, inData, PtrAccess<TDataType>
+ , inCount, inPropName, inData.stride(), inWriteOperator );
+ }
+
+ template<typename TDataType>
+ inline void writeStridedFlagsProperty( XmlWriter& writer, MemoryBuffer& tempBuffer, const char* inPropName, PxStrideIterator<const TDataType>& inData, PxU32 inCount, PxU32 inItemsPerLine, const PxU32ToName* inTable )
+ {
+ writeStrideFlags<TDataType>(writer, tempBuffer
+ , inItemsPerLine, inData, PtrAccess<TDataType>
+ , inCount, inPropName, inTable );
+ }
+
+}
+}
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSimpleXmlWriter.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSimpleXmlWriter.h
new file mode 100644
index 00000000..7ee771b8
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlSimpleXmlWriter.h
@@ -0,0 +1,215 @@
+// 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_SIMPLEXMLWRITER_H
+#define PX_SIMPLEXMLWRITER_H
+
+#include "PsArray.h"
+#include "SnXmlMemoryPoolStreams.h"
+#include "CmPhysXCommon.h"
+
+namespace physx { namespace Sn {
+ class XmlWriter
+ {
+ public:
+
+ struct STagWatcher
+ {
+ typedef XmlWriter TXmlWriterType;
+ TXmlWriterType& mWriter;
+ STagWatcher( const STagWatcher& inOther );
+ STagWatcher& operator-( const STagWatcher& inOther );
+ STagWatcher( TXmlWriterType& inWriter, const char* inTagName )
+ : mWriter( inWriter )
+ {
+ mWriter.beginTag( inTagName );
+ }
+ ~STagWatcher() { mWriter.endTag(); }
+ };
+
+ virtual ~XmlWriter(){}
+ virtual void beginTag( const char* inTagname ) = 0;
+ virtual void endTag() = 0;
+ virtual void addAttribute( const char* inName, const char* inValue ) = 0;
+ virtual void writeContentTag( const char* inTag, const char* inContent ) = 0;
+ virtual void addContent( const char* inContent ) = 0;
+ virtual PxU32 tabCount() = 0;
+ };
+
+ template<typename TStreamType>
+ class XmlWriterImpl : public XmlWriter
+ {
+ PxProfileAllocatorWrapper mWrapper;
+ TStreamType& mStream;
+ XmlWriterImpl( const XmlWriterImpl& inOther );
+ XmlWriterImpl& operator=( const XmlWriterImpl& inOther );
+ PxProfileArray<const char*> mTags;
+ bool mTagOpen;
+ PxU32 mInitialTagDepth;
+ public:
+
+ XmlWriterImpl( TStreamType& inStream, PxAllocatorCallback& inAllocator, PxU32 inInitialTagDepth = 0 )
+ : mWrapper( inAllocator )
+ , mStream( inStream )
+ , mTags( mWrapper )
+ , mTagOpen( false )
+ , mInitialTagDepth( inInitialTagDepth )
+ {
+ }
+ virtual ~XmlWriterImpl()
+ {
+ while( mTags.size() )
+ endTag();
+ }
+ PxU32 tabCount() { return mTags.size() + mInitialTagDepth; }
+
+ void writeTabs( PxU32 inSize )
+ {
+ inSize += mInitialTagDepth;
+ for ( PxU32 idx =0; idx < inSize; ++idx )
+ mStream << "\t";
+ }
+ void beginTag( const char* inTagname )
+ {
+ closeTag();
+ writeTabs(mTags.size());
+ mTags.pushBack( inTagname );
+ mStream << "<" << inTagname;
+ mTagOpen = true;
+ }
+ void addAttribute( const char* inName, const char* inValue )
+ {
+ PX_ASSERT( mTagOpen );
+ mStream << " " << inName << "=" << "\"" << inValue << "\"";
+ }
+ void closeTag(bool useNewline = true)
+ {
+ if ( mTagOpen )
+ {
+ mStream << " " << ">";
+ if (useNewline )
+ mStream << "\n";
+ }
+ mTagOpen = false;
+ }
+ void doEndOpenTag()
+ {
+ mStream << "</" << mTags.back() << ">" << "\n";
+ }
+ void endTag()
+ {
+ PX_ASSERT( mTags.size() );
+ if ( mTagOpen )
+ mStream << " " << "/>" << "\n";
+ else
+ {
+ writeTabs(mTags.size()-1);
+ doEndOpenTag();
+ }
+ mTagOpen = false;
+ mTags.popBack();
+ }
+ void addContent( const char* inContent )
+ {
+ closeTag(false);
+ mStream << inContent;
+ }
+ void writeContentTag( const char* inTag, const char* inContent )
+ {
+ beginTag( inTag );
+ addContent( inContent );
+ doEndOpenTag();
+ mTags.popBack();
+ }
+ void insertXml( const char* inXml )
+ {
+ closeTag();
+ mStream << inXml;
+ }
+ };
+
+ struct BeginTag
+ {
+ const char* mTagName;
+ BeginTag( const char* inTagName )
+ : mTagName( inTagName ) { }
+ };
+
+ struct EndTag
+ {
+ EndTag() {}
+ };
+
+ struct Att
+ {
+ const char* mAttName;
+ const char* mAttValue;
+ Att( const char* inAttName, const char* inAttValue )
+ : mAttName( inAttName )
+ , mAttValue( inAttValue ) { }
+ };
+
+ struct Content
+ {
+ const char* mContent;
+ Content( const char* inContent )
+ : mContent( inContent ) { }
+ };
+
+
+ struct ContentTag
+ {
+ const char* mTagName;
+ const char* mContent;
+ ContentTag( const char* inTagName, const char* inContent )
+ : mTagName( inTagName )
+ , mContent( inContent ) { }
+ };
+
+ inline XmlWriter& operator<<( XmlWriter& inWriter, const BeginTag& inTag ) { inWriter.beginTag( inTag.mTagName ); return inWriter; }
+ inline XmlWriter& operator<<( XmlWriter& inWriter, const EndTag& inTag ) { inWriter.endTag(); return inWriter; }
+ inline XmlWriter& operator<<( XmlWriter& inWriter, const Att& inTag ) { inWriter.addAttribute(inTag.mAttName, inTag.mAttValue); return inWriter; }
+ inline XmlWriter& operator<<( XmlWriter& inWriter, const Content& inTag ) { inWriter.addContent(inTag.mContent); return inWriter; }
+ inline XmlWriter& operator<<( XmlWriter& inWriter, const ContentTag& inTag ) { inWriter.writeContentTag(inTag.mTagName, inTag.mContent); return inWriter; }
+
+ inline void writeProperty( XmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName )
+ {
+ PxU8 data = 0;
+ tempBuffer.write( &data, sizeof(PxU8) );
+ inWriter.writeContentTag( inPropName, reinterpret_cast<const char*>( tempBuffer.mBuffer ) );
+ tempBuffer.clear();
+ }
+
+ template<typename TDataType>
+ inline void writeProperty( XmlWriter& inWriter, MemoryBuffer& tempBuffer, const char* inPropName, TDataType inValue )
+ {
+ tempBuffer << inValue;
+ writeProperty( inWriter, tempBuffer, inPropName );
+ }
+} }
+#endif \ No newline at end of file
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlStringToType.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlStringToType.h
new file mode 100644
index 00000000..0361a2bf
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlStringToType.h
@@ -0,0 +1,275 @@
+// 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_XML_STRINGTOTYPE_H
+#define PX_XML_STRINGTOTYPE_H
+
+#include <stdio.h>
+#include <ctype.h>
+#include "PsString.h"
+#include "PxCoreUtilityTypes.h"
+#include "PxFiltering.h"
+
+//Remapping function name for gcc-based systems.
+#ifndef _MSC_VER
+#define _strtoui64 strtoull
+#endif
+
+
+namespace physx { namespace Sn {
+
+ template<typename TDataType>
+ struct StrToImpl
+ {
+ bool compile_error;
+ };
+
+ template<> struct StrToImpl<PxU64> {
+ //Id's (void ptrs) are written to file as unsigned
+ //64 bit integers, so this method gets called more
+ //often than one might think.
+ PX_INLINE void strto( PxU64& ioDatatype,const char*& ioData )
+ {
+ ioDatatype = _strtoui64( ioData, const_cast<char **>(&ioData), 10 );
+ }
+ };
+
+ PX_INLINE PxF32 strToFloat(const char *str,const char **nextScan)
+ {
+ PxF32 ret;
+ while ( *str && isspace(static_cast<unsigned char>(*str))) str++; // skip leading whitespace
+ char temp[256] = "";
+ char *dest = temp;
+ char *end = &temp[255];
+ const char *begin = str;
+ while ( *str && !isspace(static_cast<unsigned char>(*str)) && dest < end ) // copy the number up to the first whitespace or eos
+ {
+ *dest++ = *str++;
+ }
+ *dest = 0;
+ ret = PxF32(strtod(temp,&end));
+ if ( nextScan )
+ {
+ *nextScan = begin+(end-temp);
+ }
+ return ret;
+ }
+
+
+ template<> struct StrToImpl<PxU32> {
+ PX_INLINE void strto( PxU32& ioDatatype,const char*& ioData )
+ {
+ ioDatatype = static_cast<PxU32>( strtoul( ioData,const_cast<char **>(&ioData), 10 ) );
+ }
+ };
+
+ template<> struct StrToImpl<PxI32> {
+ PX_INLINE void strto( PxI32& ioDatatype,const char*& ioData )
+ {
+ ioDatatype = static_cast<PxI32>( strtoul( ioData,const_cast<char **>(&ioData), 10 ) );
+ }
+ };
+
+
+ template<> struct StrToImpl<PxU16> {
+ PX_INLINE void strto( PxU16& ioDatatype,const char*& ioData )
+ {
+ ioDatatype = static_cast<PxU16>( strtoul( ioData,const_cast<char **>(&ioData), 10 ) );
+ }
+ };
+
+ PX_INLINE void eatwhite(const char*& ioData )
+ {
+ if ( ioData )
+ {
+ while( isspace( static_cast<unsigned char>(*ioData) ) )
+ ++ioData;
+ }
+ }
+
+ // copy the source data to the dest buffer until the first whitespace is encountered.
+ // Do not overflow the buffer based on the bufferLen provided.
+ // Advance the input 'ioData' pointer so that it sits just at the next whitespace
+ PX_INLINE void nullTerminateWhite(const char*& ioData,char *buffer,PxU32 bufferLen)
+ {
+ if ( ioData )
+ {
+ char *eof = buffer+(bufferLen-1);
+ char *dest = buffer;
+ while( *ioData && !isspace(static_cast<unsigned char>(*ioData)) && dest < eof )
+ {
+ *dest++ = *ioData++;
+ }
+ *dest = 0;
+ }
+ }
+
+ inline void nonNullTerminateWhite(const char*& ioData )
+ {
+ if ( ioData )
+ {
+ while( *ioData && !isspace( static_cast<unsigned char>(*ioData) ) )
+ ++ioData;
+ }
+ }
+
+ template<> struct StrToImpl<PxF32> {
+ inline void strto( PxF32& ioDatatype,const char*& ioData )
+ {
+ ioDatatype = strToFloat(ioData,&ioData);
+ }
+
+ };
+
+
+ template<> struct StrToImpl<void*> {
+ inline void strto( void*& ioDatatype,const char*& ioData )
+ {
+ PxU64 theData;
+ StrToImpl<PxU64>().strto( theData, ioData );
+ ioDatatype = reinterpret_cast<void*>( static_cast<size_t>( theData ) );
+ }
+ };
+
+
+ template<> struct StrToImpl<physx::PxVec3> {
+ inline void strto( physx::PxVec3& ioDatatype,const char*& ioData )
+ {
+ StrToImpl<PxF32>().strto( ioDatatype[0], ioData );
+ StrToImpl<PxF32>().strto( ioDatatype[1], ioData );
+ StrToImpl<PxF32>().strto( ioDatatype[2], ioData );
+ }
+ };
+
+ template<> struct StrToImpl<PxU8*> {
+ inline void strto( PxU8*& /*ioDatatype*/,const char*& /*ioData*/)
+ {
+ }
+ };
+
+ template<> struct StrToImpl<bool> {
+ inline void strto( bool& ioType,const char*& inValue )
+ {
+ ioType = physx::shdfnd::stricmp( inValue, "true" ) == 0 ? true : false;
+ }
+ };
+
+ template<> struct StrToImpl<PxU8> {
+ PX_INLINE void strto( PxU8& ioType,const char* & inValue)
+ {
+ ioType = static_cast<PxU8>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) );
+ }
+ };
+
+ template<> struct StrToImpl<PxFilterData> {
+ PX_INLINE void strto( PxFilterData& ioType,const char*& inValue)
+ {
+ ioType.word0 = static_cast<PxU32>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) );
+ ioType.word1 = static_cast<PxU32>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) );
+ ioType.word2 = static_cast<PxU32>( strtoul( inValue,const_cast<char **>(&inValue), 10 ) );
+ ioType.word3 = static_cast<PxU32>( strtoul( inValue, NULL, 10 ) );
+ }
+ };
+
+
+ template<> struct StrToImpl<PxQuat> {
+ PX_INLINE void strto( PxQuat& ioType,const char*& inValue )
+ {
+ ioType.x = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.y = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.z = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.w = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ }
+ };
+
+ template<> struct StrToImpl<PxTransform> {
+ PX_INLINE void strto( PxTransform& ioType,const char*& inValue)
+ {
+ ioType.q.x = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.q.y = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.q.z = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.q.w = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+
+ ioType.p[0] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.p[1] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.p[2] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ }
+ };
+
+ template<> struct StrToImpl<PxBounds3> {
+ PX_INLINE void strto( PxBounds3& ioType,const char*& inValue)
+ {
+ ioType.minimum[0] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.minimum[1] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.minimum[2] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+
+ ioType.maximum[0] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.maximum[1] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.maximum[2] = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ }
+ };
+
+ template<> struct StrToImpl<PxMetaDataPlane> {
+ PX_INLINE void strto( PxMetaDataPlane& ioType,const char*& inValue)
+ {
+ ioType.normal.x = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.normal.y = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.normal.z = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ ioType.distance = static_cast<PxReal>( strToFloat( inValue, &inValue ) );
+ }
+ };
+
+
+ template<> struct StrToImpl<PxRigidDynamic*> {
+ PX_INLINE void strto( PxRigidDynamic*& /*ioDatatype*/,const char*& /*ioData*/)
+ {
+ }
+ };
+
+ template<typename TDataType>
+ inline void strto( TDataType& ioType,const char*& ioData )
+ {
+ if ( ioData && *ioData ) StrToImpl<TDataType>().strto( ioType, ioData );
+ }
+
+ template<typename TDataType>
+ inline void strtoLong( TDataType& ioType,const char*& ioData )
+ {
+ if ( ioData && *ioData ) StrToImpl<TDataType>().strto( ioType, ioData );
+ }
+
+ template<typename TDataType>
+ inline void stringToType( const char* inValue, TDataType& ioType )
+ {
+ const char* theValue( inValue );
+ return strto( ioType, theValue );
+ }
+
+} }
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorReader.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorReader.h
new file mode 100644
index 00000000..e003edf0
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorReader.h
@@ -0,0 +1,889 @@
+// 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_XML_VISITOR_READER_H
+#define PX_XML_VISITOR_READER_H
+
+#include "PsArray.h"
+#include "PsUtilities.h"
+#include "RepXMetaDataPropertyVisitor.h"
+#include "SnPxStreamOperators.h"
+#include "SnXmlMemoryPoolStreams.h"
+#include "SnXmlReader.h"
+#include "SnXmlImpl.h"
+#include "SnXmlMemoryAllocator.h"
+#include "SnXmlStringToType.h"
+
+namespace physx { namespace Sn {
+
+
+ inline PxU32 findEnumByName( const char* inName, const PxU32ToName* inTable )
+ {
+ for ( PxU32 idx = 0; inTable[idx].mName != NULL; ++idx )
+ {
+ if ( physx::shdfnd::stricmp( inTable[idx].mName, inName ) == 0 )
+ return inTable[idx].mValue;
+ }
+ return 0;
+ }
+
+ PX_INLINE void stringToFlagsType( const char* strData, XmlMemoryAllocator& alloc, PxU32& ioType, const PxU32ToName* inTable )
+ {
+ if ( inTable == NULL )
+ return;
+ ioType = 0;
+ if ( strData && *strData)
+ {
+ //Destructively parse the string to get out the different flags.
+ char* theValue = const_cast<char*>( copyStr( &alloc, strData ) );
+ char* theMarker = theValue;
+ char* theNext = theValue;
+ while( theNext && *theNext )
+ {
+ ++theNext;
+ if( *theNext == '|' )
+ {
+ *theNext = 0;
+ ++theNext;
+ ioType |= static_cast< PxU32 > ( findEnumByName( theMarker, inTable ) );
+ theMarker = theNext;
+ }
+ }
+ if ( theMarker && *theMarker )
+ ioType |= static_cast< PxU32 > ( findEnumByName( theMarker, inTable ) );
+ alloc.deallocate( reinterpret_cast<PxU8*>( theValue ) );
+ }
+ }
+
+ template<typename TDataType>
+ PX_INLINE void stringToEnumType( const char* strData, TDataType& ioType, const PxU32ToName* inTable )
+ {
+ ioType = static_cast<TDataType>( findEnumByName( strData, inTable ) );
+ }
+
+ template<typename TDataType>
+ PX_INLINE bool readProperty( XmlReader& inReader, const char* pname, TDataType& ioType )
+ {
+ const char* value;
+ if ( inReader.read( pname, value ) )
+ {
+ stringToType( value, ioType );
+ return true;
+ }
+ return false;
+ }
+
+ template<typename TObjType>
+ inline TObjType* findReferencedObject( PxCollection& collection, PxSerialObjectId id)
+ {
+ PX_ASSERT(id > 0);
+ TObjType* outObject = static_cast<TObjType*>(const_cast<PxBase*>(collection.find(id)));
+ if (outObject == NULL)
+ {
+ Ps::getFoundation().error(PxErrorCode::eINVALID_PARAMETER, __FILE__, __LINE__,
+ "PxSerialization::createCollectionFromXml: "
+ "Reference to ID %d cannot be resolved. Make sure externalRefs collection is specified if required and "
+ "check Xml file for completeness.",
+ id);
+ }
+ return outObject;
+ }
+
+ template<typename TObjType>
+ inline bool readReference( XmlReader& inReader, PxCollection& collection, TObjType*& outObject )
+ {
+ PxSerialObjectId theId;
+ const char* theValue = inReader.getCurrentItemValue();
+ strto( theId, theValue );
+ if( theId == 0)
+ {
+ // the NULL pointer is a valid pointer if the input id is 0
+ outObject = NULL;
+ return true;
+ }
+ else
+ {
+ outObject = findReferencedObject<TObjType>(collection, theId);
+ return outObject != NULL;
+ }
+ }
+
+ template<typename TObjType>
+ inline bool readReference( XmlReader& inReader, PxCollection& inCollection, const char* pname, TObjType*& outObject )
+ {
+ outObject = NULL;
+ PxSerialObjectId theId = 0;
+ if (readProperty ( inReader, pname, theId ) && theId )
+ {
+ outObject = findReferencedObject<TObjType>(inCollection, theId);
+ }
+ // the NULL pointer is a valid pointer if the input id is 0
+ return (outObject != NULL) || 0 == theId;
+ }
+
+ template<typename TEnumType, typename TStorageType>
+ inline bool readFlagsProperty( XmlReader& reader, XmlMemoryAllocator& allocator, const char* pname, const PxU32ToName* inConversions, PxFlags<TEnumType,TStorageType>& outFlags )
+ {
+ const char* value;
+ if ( reader.read( pname, value ) )
+ {
+ PxU32 tempValue = 0;
+ stringToFlagsType( value, allocator, tempValue, inConversions );
+ outFlags = PxFlags<TEnumType,TStorageType>(Ps::to16(tempValue) );
+ return true;
+ }
+ return false;
+ }
+
+ template<typename TObjType, typename TReaderType, typename TInfoType>
+ inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, TInfoType& info);
+ template<typename TObjType, typename TReaderType>
+ inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj);
+
+ template<typename TReaderType, typename TGeomType>
+ inline PxGeometry* parseGeometry( TReaderType& reader, TGeomType& /*inGeom*/)
+ {
+ PxAllocatorCallback& inAllocator = reader.mAllocator.getAllocator();
+
+ TGeomType* shape = PX_PLACEMENT_NEW((inAllocator.allocate(sizeof(TGeomType), "parseGeometry", __FILE__, __LINE__ )), TGeomType);
+ PxClassInfoTraits<TGeomType> info;
+ readComplexObj( reader, shape);
+ return shape;
+ }
+
+
+ template<typename TReaderType>
+ inline void parseShape( TReaderType& visitor, PxGeometry*& outResult, Ps::Array<PxMaterial*>& outMaterials)
+ {
+ XmlReader& theReader( visitor.mReader );
+ PxCollection& collection = visitor.mCollection;
+ visitor.pushCurrentContext();
+ if ( visitor.gotoTopName() )
+ {
+ visitor.pushCurrentContext();
+ if ( visitor.gotoChild( "Materials" ) )
+ {
+ for( bool matSuccess = visitor.gotoFirstChild(); matSuccess;
+ matSuccess = visitor.gotoNextSibling() )
+ {
+ PxMaterial* material = NULL;
+ if(!readReference<PxMaterial>( theReader, collection, material ))
+ visitor.mHadError = true;
+ if ( material )
+ outMaterials.pushBack( material );
+ }
+ }
+ visitor.popCurrentContext();
+ visitor.pushCurrentContext();
+
+ PxPlaneGeometry plane;
+ PxHeightFieldGeometry heightField;
+ PxSphereGeometry sphere;
+ PxTriangleMeshGeometry mesh;
+ PxConvexMeshGeometry convex;
+ PxBoxGeometry box;
+ PxCapsuleGeometry capsule;
+ if ( visitor.gotoChild( "Geometry" ) )
+ {
+ if ( visitor.gotoFirstChild() )
+ {
+ const char* geomTypeName = visitor.getCurrentItemName();
+
+ if ( physx::shdfnd::stricmp( geomTypeName, "PxSphereGeometry" ) == 0 ) outResult = parseGeometry(visitor, sphere);
+ else if ( physx::shdfnd::stricmp( geomTypeName, "PxPlaneGeometry" ) == 0 ) outResult = parseGeometry(visitor, plane);
+ else if ( physx::shdfnd::stricmp( geomTypeName, "PxCapsuleGeometry" ) == 0 ) outResult = parseGeometry(visitor, capsule);
+ else if ( physx::shdfnd::stricmp( geomTypeName, "PxBoxGeometry" ) == 0 ) outResult = parseGeometry(visitor, box);
+ else if ( physx::shdfnd::stricmp( geomTypeName, "PxConvexMeshGeometry" ) == 0 ) outResult = parseGeometry(visitor, convex);
+ else if ( physx::shdfnd::stricmp( geomTypeName, "PxTriangleMeshGeometry" ) == 0 ) outResult = parseGeometry(visitor, mesh);
+ else if ( physx::shdfnd::stricmp( geomTypeName, "PxHeightFieldGeometry" ) == 0 ) outResult = parseGeometry(visitor, heightField);
+ else
+ PX_ASSERT( false );
+ }
+ }
+ visitor.popCurrentContext();
+ }
+ visitor.popCurrentContext();
+
+ return;
+ }
+
+ template<typename TReaderType, typename TObjType>
+ inline void readShapesProperty( TReaderType& visitor, TObjType* inObj, const PxRigidActorShapeCollection* inProp = NULL, bool isSharedShape = false )
+ {
+ PX_UNUSED(isSharedShape);
+ PX_UNUSED(inProp);
+
+ XmlReader& theReader( visitor.mReader );
+ PxCollection& collection( visitor.mCollection );
+
+ visitor.pushCurrentContext();
+ if ( visitor.gotoTopName() )
+ {
+ //uggh working around the shape collection api.
+ //read out materials and geometry
+ for ( bool success = visitor.gotoFirstChild(); success;
+ success = visitor.gotoNextSibling() )
+ {
+ if( 0 == physx::shdfnd::stricmp( visitor.getCurrentItemName(), "PxShapeRef" ) )
+ {
+ PxShape* shape = NULL;
+ if(!readReference<PxShape>( theReader, collection, shape ))
+ visitor.mHadError = true;
+ if(shape)
+ inObj->attachShape( *shape );
+ }
+ else
+ {
+ Ps::Array<PxMaterial*> materials;
+ PxGeometry* geometry = NULL;
+ parseShape( visitor, geometry, materials);
+ PxShape* theShape = NULL;
+ if ( materials.size() )
+ {
+ theShape = visitor.mArgs.physics.createShape( *geometry, materials.begin(), Ps::to16(materials.size()), true );
+ if ( theShape )
+ {
+ readComplexObj( visitor, theShape );
+
+ if(theShape)
+ {
+ inObj->attachShape(*theShape);
+ collection.add( *theShape );
+ }
+ }
+ }
+
+ switch(geometry->getType())
+ {
+ case PxGeometryType::eSPHERE :
+ static_cast<PxSphereGeometry*>(geometry)->~PxSphereGeometry();
+ break;
+ case PxGeometryType::ePLANE :
+ static_cast<PxPlaneGeometry*>(geometry)->~PxPlaneGeometry();
+ break;
+ case PxGeometryType::eCAPSULE :
+ static_cast<PxCapsuleGeometry*>(geometry)->~PxCapsuleGeometry();
+ break;
+ case PxGeometryType::eBOX :
+ static_cast<PxBoxGeometry*>(geometry)->~PxBoxGeometry();
+ break;
+ case PxGeometryType::eCONVEXMESH :
+ static_cast<PxConvexMeshGeometry*>(geometry)->~PxConvexMeshGeometry();
+ break;
+ case PxGeometryType::eTRIANGLEMESH :
+ static_cast<PxTriangleMeshGeometry*>(geometry)->~PxTriangleMeshGeometry();
+ break;
+ case PxGeometryType::eHEIGHTFIELD :
+ static_cast<PxHeightFieldGeometry*>(geometry)->~PxHeightFieldGeometry();
+ break;
+
+ case PxGeometryType::eGEOMETRY_COUNT:
+ case PxGeometryType::eINVALID:
+ PX_ASSERT(0);
+ }
+ visitor.mAllocator.getAllocator().deallocate(geometry);
+ }
+ }
+ }
+ visitor.popCurrentContext();
+ }
+
+ struct ReaderNameStackEntry : NameStackEntry
+ {
+ bool mValid;
+ ReaderNameStackEntry( const char* nm, bool valid ) : NameStackEntry(nm), mValid(valid) {}
+ };
+
+ typedef PxProfileArray<ReaderNameStackEntry> TReaderNameStack;
+
+ template<typename TObjType>
+ struct RepXVisitorReaderBase
+ {
+
+ protected:
+ RepXVisitorReaderBase<TObjType>& operator=(const RepXVisitorReaderBase<TObjType>&);
+ public:
+ TReaderNameStack& mNames;
+ PxProfileArray<PxU32>& mContexts;
+ PxRepXInstantiationArgs mArgs;
+ XmlReader& mReader;
+ TObjType* mObj;
+ XmlMemoryAllocator& mAllocator;
+ PxCollection& mCollection;
+ bool mValid;
+ bool& mHadError;
+
+ RepXVisitorReaderBase( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, TObjType* obj
+ , XmlMemoryAllocator& alloc, PxCollection& collection, bool& hadError )
+ : mNames( names )
+ , mContexts( contexts )
+ , mArgs( args )
+ , mReader( reader )
+ , mObj( obj )
+ , mAllocator( alloc )
+ , mCollection( collection )
+ , mValid( true )
+ , mHadError(hadError)
+ {
+ }
+ RepXVisitorReaderBase( const RepXVisitorReaderBase& other )
+ : mNames( other.mNames )
+ , mContexts( other.mContexts )
+ , mArgs( other.mArgs )
+ , mReader( other.mReader )
+ , mObj( other.mObj )
+ , mAllocator( other.mAllocator )
+ , mCollection( other.mCollection )
+ , mValid( other.mValid )
+ , mHadError( other.mHadError )
+ {
+ }
+
+
+ void pushName( const char* name )
+ {
+ gotoTopName();
+ mNames.pushBack( ReaderNameStackEntry( name, mValid ) );
+ }
+ void pushBracketedName( const char* name ) { pushName( name ); }
+ void popName()
+ {
+ if ( mNames.size() )
+ {
+ if ( mNames.back().mOpen && mNames.back().mValid )
+ mReader.leaveChild();
+ mNames.popBack();
+ }
+ mValid =true;
+ if ( mNames.size() && mNames.back().mValid == false )
+ mValid = false;
+ }
+
+ void pushCurrentContext()
+ {
+ mContexts.pushBack( static_cast<PxU32>( mNames.size() ) );
+ }
+ void popCurrentContext()
+ {
+ if ( mContexts.size() )
+ {
+ PxU32 depth = mContexts.back();
+ PX_ASSERT( mNames.size() >= depth );
+ while( mNames.size() > depth )
+ popName();
+ mContexts.popBack();
+ }
+ }
+
+ bool updateLastEntryAfterOpen()
+ {
+ mNames.back().mValid = mValid;
+ mNames.back().mOpen = mValid;
+ return mValid;
+ }
+
+ bool gotoTopName()
+ {
+ if ( mNames.size() && mNames.back().mOpen == false )
+ {
+ if ( mValid )
+ mValid = mReader.gotoChild( mNames.back().mName );
+ updateLastEntryAfterOpen();
+ }
+ return mValid;
+ }
+
+ bool isValid() const { return mValid; }
+
+ bool gotoChild( const char* name )
+ {
+ pushName( name );
+ return gotoTopName();
+ }
+
+ bool gotoFirstChild()
+ {
+ pushName( "__child" );
+ if ( mValid ) mValid = mReader.gotoFirstChild();
+ return updateLastEntryAfterOpen();
+ }
+
+ bool gotoNextSibling()
+ {
+ bool retval = mValid;
+ if ( mValid ) retval = mReader.gotoNextSibling();
+ return retval;
+ }
+
+ const char* getCurrentItemName() { if (mValid ) return mReader.getCurrentItemName(); return ""; }
+
+ const char* topName() const
+ {
+ if ( mNames.size() ) return mNames.back().mName;
+ PX_ASSERT( false );
+ return "bad__repx__name";
+ }
+
+ const char* getCurrentValue()
+ {
+ const char* value = NULL;
+ if ( isValid() && mReader.read( topName(), value ) )
+ return value;
+ return NULL;
+ }
+
+ template<typename TDataType>
+ bool readProperty(TDataType& outType)
+ {
+ const char* value = getCurrentValue();
+ if ( value && *value )
+ {
+ stringToType( value, outType );
+ return true;
+ }
+ return false;
+ }
+
+ template<typename TDataType>
+ bool readExtendedIndexProperty(TDataType& outType)
+ {
+ const char* value = mReader.getCurrentItemValue();
+ if ( value && *value )
+ {
+ stringToType( value, outType );
+ return true;
+ }
+ return false;
+ }
+
+
+ template<typename TRefType>
+ bool readReference(TRefType*& outRef)
+ {
+ return physx::Sn::readReference<TRefType>( mReader, mCollection, topName(), outRef );
+ }
+
+ inline bool readProperty(const char*& outProp )
+ {
+ outProp = "";
+ const char* value = getCurrentValue();
+ if ( value && *value && mArgs.stringTable )
+ {
+ outProp = mArgs.stringTable->allocateStr( value );
+ return true;
+ }
+ return false;
+ }
+
+ inline bool readProperty(PxConvexMesh*& outProp )
+ {
+ return readReference<PxConvexMesh>( outProp );
+ }
+
+ inline bool readProperty(PxTriangleMesh*& outProp )
+ {
+ return readReference<PxTriangleMesh>( outProp );
+ }
+ inline bool readProperty(PxBVH33TriangleMesh*& outProp )
+ {
+ return readReference<PxBVH33TriangleMesh>( outProp );
+ }
+ inline bool readProperty(PxBVH34TriangleMesh*& outProp )
+ {
+ return readReference<PxBVH34TriangleMesh>( outProp );
+ }
+
+ inline bool readProperty(PxHeightField*& outProp )
+ {
+ return readReference<PxHeightField>( outProp );
+ }
+
+ inline bool readProperty( PxRigidActor *& outProp )
+ {
+ return readReference<PxRigidActor>( outProp );
+ }
+
+ template<typename TAccessorType>
+ void simpleProperty( PxU32 /*key*/, TAccessorType& inProp )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ TPropertyType value;
+ if ( readProperty( value ) )
+ inProp.set( mObj, value );
+ }
+
+ template<typename TAccessorType>
+ void enumProperty( PxU32 /*key*/, TAccessorType& inProp, const PxU32ToName* inConversions )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ const char* strVal = getCurrentValue();
+ if ( strVal && *strVal )
+ {
+ TPropertyType pval;
+ stringToEnumType( strVal, pval, inConversions );
+ inProp.set( mObj, pval );
+ }
+ }
+
+ template<typename TAccessorType>
+ void flagsProperty( PxU32 /*key*/, const TAccessorType& inProp, const PxU32ToName* inConversions )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ typedef typename TPropertyType::InternalType TInternalType;
+
+ const char* strVal = getCurrentValue();
+ if ( strVal && *strVal )
+ {
+ PxU32 tempValue = 0;
+ stringToFlagsType( strVal, mAllocator, tempValue, inConversions );
+ inProp.set( mObj, TPropertyType(TInternalType( tempValue )));
+ }
+ }
+
+ template<typename TAccessorType, typename TInfoType>
+ void complexProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ if ( gotoTopName() )
+ {
+ TPropertyType propVal = inProp.get( mObj );
+ readComplexObj( *this, &propVal, inInfo );
+ inProp.set( mObj, propVal );
+ }
+ }
+
+ template<typename TAccessorType, typename TInfoType>
+ void bufferCollectionProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ Ps::InlineArray<TPropertyType,5> theData;
+
+ this->pushCurrentContext();
+ if ( this->gotoTopName() )
+ {
+ for ( bool success = this->gotoFirstChild(); success;
+ success = this->gotoNextSibling() )
+ {
+ TPropertyType propVal;
+ readComplexObj( *this, &propVal, inInfo );
+ theData.pushBack(propVal);
+ }
+ }
+ this->popCurrentContext();
+
+ inProp.set( mObj, theData.begin(), theData.size() );
+
+ }
+
+ template<typename TAccessorType, typename TInfoType>
+ void extendedIndexedProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+
+ this->pushCurrentContext();
+ if ( this->gotoTopName() )
+ {
+ PxU32 index = 0;
+ for ( bool success = this->gotoFirstChild(); success;
+ success = this->gotoNextSibling() )
+ {
+ TPropertyType propVal;
+ readComplexObj( *this, &propVal, inInfo );
+ inProp.set(mObj, index, propVal);
+ ++index;
+ }
+ }
+ this->popCurrentContext();
+ }
+
+ template<typename TAccessorType, typename TInfoType>
+ void PxFixedSizeLookupTableProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ const_cast<TAccessorType&>(inProp).clear( mObj );
+
+ this->pushCurrentContext();
+ if ( this->gotoTopName() )
+ {
+ for ( bool success = this->gotoFirstChild(); success;
+ success = this->gotoNextSibling() )
+ {
+ TPropertyType propXVal;
+ readComplexObj( *this, &propXVal, inInfo );
+
+ if(this->gotoNextSibling())
+ {
+ TPropertyType propYVal;
+ readComplexObj( *this, &propYVal, inInfo );
+ const_cast<TAccessorType&>(inProp).addPair(mObj, propXVal, propYVal);
+ }
+ }
+ }
+ this->popCurrentContext();
+ }
+
+ void handleShapes( const PxRigidActorShapeCollection& inProp )
+ {
+ physx::Sn::readShapesProperty( *this, mObj, &inProp );
+ }
+ };
+
+ template<typename TObjType>
+ struct RepXVisitorReader : public RepXVisitorReaderBase<TObjType>
+ {
+ RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, TObjType* obj
+ , XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret)
+ : RepXVisitorReaderBase<TObjType>( names, contexts, args, reader, obj, alloc, collection, ret)
+ {
+ }
+ RepXVisitorReader( const RepXVisitorReader<TObjType>& other )
+ : RepXVisitorReaderBase<TObjType>( other )
+ {
+ }
+ };
+
+ // Specialized template to load dynamic rigid, to determine the kinematic state first
+ template<>
+ struct RepXVisitorReader<PxRigidDynamic> : public RepXVisitorReaderBase<PxRigidDynamic>
+ {
+ RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxRigidDynamic* obj
+ , XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret)
+ : RepXVisitorReaderBase<PxRigidDynamic>( names, contexts, args, reader, obj, alloc, collection, ret)
+ {
+ }
+ RepXVisitorReader( const RepXVisitorReader<PxRigidDynamic>& other )
+ : RepXVisitorReaderBase<PxRigidDynamic>( other )
+ {
+ }
+
+ void handleShapes( const PxRigidActorShapeCollection& inProp )
+ {
+ // Need to read the parental actor to check if actor is kinematic
+ // in that case we need to apply the kinematic flag before a shape is set
+ XmlReaderWriter* parentReader = static_cast<XmlReaderWriter*>(mReader.getParentReader());
+ if(mObj)
+ {
+ const char* value;
+ if (parentReader->read( "RigidBodyFlags", value ))
+ {
+ if(strstr(value, "eKINEMATIC"))
+ {
+ mObj->setRigidBodyFlag(PxRigidBodyFlag::eKINEMATIC, true);
+ }
+ }
+ }
+ physx::Sn::readShapesProperty( *this, mObj, &inProp );
+ parentReader->release();
+ }
+
+
+ template<typename TAccessorType>
+ void simpleProperty( PxU32 /*key*/, TAccessorType& inProp )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ TPropertyType value;
+ if (readProperty(value))
+ {
+ // If the rigid body is kinematic, we cannot set the LinearVelocity or AngularVelocity
+ const bool kinematic = (mObj->getRigidBodyFlags() & PxRigidBodyFlag::eKINEMATIC);
+ if(kinematic && (inProp.mProperty.mKey == PxPropertyInfoName::PxRigidBody_LinearVelocity || inProp.mProperty.mKey == PxPropertyInfoName::PxRigidBody_AngularVelocity))
+ return;
+
+ inProp.set(mObj, value );
+ }
+ }
+ private:
+ RepXVisitorReader<PxRigidDynamic>& operator=(const RepXVisitorReader<PxRigidDynamic>&);
+ };
+
+ template<>
+ struct RepXVisitorReader<PxShape> : public RepXVisitorReaderBase<PxShape>
+ {
+ RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxShape* obj
+ , XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret )
+ : RepXVisitorReaderBase<PxShape>( names, contexts, args, reader, obj, alloc, collection, ret )
+ {
+ }
+ RepXVisitorReader( const RepXVisitorReader<PxShape>& other )
+ : RepXVisitorReaderBase<PxShape>( other )
+ {
+ }
+ void handleShapeMaterials( const PxShapeMaterialsProperty& ) //these were handled during construction.
+ {
+ }
+ void handleGeometryProperty( const PxShapeGeometryProperty& )
+ {
+ }
+ private:
+ RepXVisitorReader<PxShape>& operator=(const RepXVisitorReader<PxShape>&);
+ };
+
+ template<>
+ struct RepXVisitorReader<PxArticulationLink> : public RepXVisitorReaderBase<PxArticulationLink>
+ {
+ RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxArticulationLink* obj
+ , XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret )
+ : RepXVisitorReaderBase<PxArticulationLink>( names, contexts, args, reader, obj, alloc, collection, ret )
+ {
+ }
+ RepXVisitorReader( const RepXVisitorReader<PxArticulationLink>& other )
+ : RepXVisitorReaderBase<PxArticulationLink>( other )
+ {
+ }
+ void handleIncomingJoint( const TIncomingJointPropType& prop )
+ {
+ pushName( "Joint" );
+ if ( gotoTopName() )
+ {
+ PxArticulationJoint* theJoint( prop.get( mObj ) );
+ readComplexObj( *this, theJoint );
+
+ //Add joint to PxCollection, since PxArticulation requires PxArticulationLink and joint.
+ mCollection.add( *theJoint );
+ }
+ popName();
+ }
+ private:
+ RepXVisitorReader<PxArticulationLink>& operator=(const RepXVisitorReader<PxArticulationLink>&);
+ };
+
+ inline void readProperty( RepXVisitorReaderBase<PxArticulation>& inSerializer, PxArticulation* inObj, const PxArticulationLinkCollectionProp& /*inProp*/)
+ {
+ PxProfileAllocatorWrapper theWrapper( inSerializer.mAllocator.getAllocator() );
+ PxCollection& collection( inSerializer.mCollection );
+
+ TArticulationLinkLinkMap linkRemapMap( theWrapper );
+ inSerializer.pushCurrentContext();
+ if( inSerializer.gotoTopName() )
+ {
+ for ( bool links = inSerializer.gotoFirstChild();
+ links != false;
+ links = inSerializer.gotoNextSibling() )
+ {
+ //Need enough information to create the link...
+ PxSerialObjectId theParentPtr = 0;
+ const PxArticulationLink* theParentLink = NULL;
+ if ( inSerializer.mReader.read( "Parent", theParentPtr ) )
+ {
+ const TArticulationLinkLinkMap::Entry* theRemappedParent( linkRemapMap.find( theParentPtr ) );
+ //If we have a valid at write time, we had better have a valid parent at read time.
+ PX_ASSERT( theRemappedParent );
+ theParentLink = theRemappedParent->second;
+ }
+ PxArticulationLink* newLink = inObj->createLink( const_cast<PxArticulationLink*>( theParentLink ), PxTransform(PxIdentity) );
+ PxSerialObjectId theIdPtr = 0;
+ inSerializer.mReader.read( "Id", theIdPtr );
+
+ linkRemapMap.insert( theIdPtr, newLink );
+ readComplexObj( inSerializer, newLink );
+
+ //Add link to PxCollection, since PxArticulation requires PxArticulationLink and joint.
+ collection.add( *newLink, theIdPtr );
+ }
+ }
+ inSerializer.popCurrentContext();
+ }
+
+ template<>
+ struct RepXVisitorReader<PxArticulation> : public RepXVisitorReaderBase<PxArticulation>
+ {
+ RepXVisitorReader( TReaderNameStack& names, PxProfileArray<PxU32>& contexts, const PxRepXInstantiationArgs& args, XmlReader& reader, PxArticulation* obj
+ , XmlMemoryAllocator& alloc, PxCollection& collection, bool& ret)
+ : RepXVisitorReaderBase<PxArticulation>( names, contexts, args, reader, obj, alloc, collection, ret)
+ {
+ }
+ RepXVisitorReader( const RepXVisitorReader<PxArticulation>& other )
+ : RepXVisitorReaderBase<PxArticulation>( other )
+ {
+ }
+
+ void handleArticulationLinks( const PxArticulationLinkCollectionProp& inProp )
+ {
+ physx::Sn::readProperty( *this, mObj, inProp );
+ }
+ };
+
+ template<typename TObjType, typename TInfoType>
+ inline bool readAllProperties( PxRepXInstantiationArgs args, TReaderNameStack& names, PxProfileArray<PxU32>& contexts, XmlReader& reader, TObjType* obj, XmlMemoryAllocator& alloc, PxCollection& collection, TInfoType& info )
+ {
+ bool hadError = false;
+ RepXVisitorReader<TObjType> theReader( names, contexts, args, reader, obj, alloc, collection, hadError);
+ RepXPropertyFilter<RepXVisitorReader<TObjType> > theOp( theReader );
+ info.visitBaseProperties( theOp );
+ info.visitInstanceProperties( theOp );
+ return !hadError;
+ }
+
+
+ template<typename TObjType>
+ inline bool readAllProperties( PxRepXInstantiationArgs args, XmlReader& reader, TObjType* obj, XmlMemoryAllocator& alloc, PxCollection& collection )
+ {
+ PxProfileAllocatorWrapper wrapper( alloc.getAllocator() );
+ TReaderNameStack names( wrapper );
+ PxProfileArray<PxU32> contexts( wrapper );
+ PxClassInfoTraits<TObjType> info;
+ return readAllProperties( args, names, contexts, reader, obj, alloc, collection, info.Info );
+ }
+
+ template<typename TObjType, typename TReaderType, typename TInfoType>
+ inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, TInfoType& info)
+ {
+ if(!readAllProperties( oldVisitor.mArgs, oldVisitor.mNames, oldVisitor.mContexts, oldVisitor.mReader, inObj, oldVisitor.mAllocator, oldVisitor.mCollection, info ))
+ oldVisitor.mHadError = true;
+ }
+
+ template<typename TObjType, typename TReaderType, typename TInfoType>
+ inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, const TInfoType& info)
+ {
+ if(!readAllProperties( oldVisitor.mArgs, oldVisitor.mNames, oldVisitor.mContexts, oldVisitor.mReader, inObj, oldVisitor.mAllocator, oldVisitor.mCollection, info ))
+ oldVisitor.mHadError = true;
+ }
+
+ template<typename TObjType, typename TReaderType>
+ inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj, const PxUnknownClassInfo& /*info*/)
+ {
+ const char* value = oldVisitor.mReader.getCurrentItemValue();
+ if ( value && *value )
+ {
+ stringToType( value, *inObj );
+ return;
+ }
+ oldVisitor.mHadError = true;
+ }
+
+ template<typename TObjType, typename TReaderType>
+ inline void readComplexObj( TReaderType& oldVisitor, TObjType* inObj)
+ {
+ PxClassInfoTraits<TObjType> info;
+ if(!readAllProperties( oldVisitor.mArgs, oldVisitor.mNames, oldVisitor.mContexts, oldVisitor.mReader, inObj, oldVisitor.mAllocator, oldVisitor.mCollection, info.Info ))
+ oldVisitor.mHadError = true;
+ }
+
+} }
+
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorWriter.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorWriter.h
new file mode 100644
index 00000000..76bf66cd
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlVisitorWriter.h
@@ -0,0 +1,765 @@
+// 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_XML_VISITOR_WRITER_H
+#define PX_XML_VISITOR_WRITER_H
+
+#include "PsInlineArray.h"
+#include "CmPhysXCommon.h"
+#include "RepXMetaDataPropertyVisitor.h"
+#include "SnPxStreamOperators.h"
+#include "SnXmlMemoryPoolStreams.h"
+#include "SnXmlWriter.h"
+#include "SnXmlImpl.h"
+#include "PsFoundation.h"
+
+namespace physx { namespace Sn {
+
+ template<typename TDataType>
+ inline void writeReference( XmlWriter& writer, PxCollection& inCollection, const char* inPropName, const TDataType* inDatatype )
+ {
+ const PxBase* s = static_cast<const PxBase*>( inDatatype ) ;
+ if( inDatatype && !inCollection.contains( *const_cast<PxBase*>(s) ))
+ {
+ Ps::getFoundation().error(PxErrorCode::eINTERNAL_ERROR, __FILE__, __LINE__,
+ "PxSerialization::serializeCollectionToXml: Reference \"%s\" could not be resolved.", inPropName);
+ }
+
+ PxSerialObjectId theId = 0;
+ if( s )
+ {
+ theId = inCollection.getId( *s );
+ if( theId == 0 )
+ theId = PX_PROFILE_POINTER_TO_U64( inDatatype );
+ }
+
+ writer.write( inPropName, PxCreateRepXObject( inDatatype, theId ) );
+ }
+
+ inline void writeProperty( XmlWriter& inWriter, MemoryBuffer& inBuffer, const char* inProp )
+ {
+ PxU8 data = 0;
+ inBuffer.write( &data, sizeof(PxU8) );
+ inWriter.write( inProp, reinterpret_cast<const char*>( inBuffer.mBuffer ) );
+ inBuffer.clear();
+ }
+
+ template<typename TDataType>
+ inline void writeProperty( XmlWriter& inWriter, PxCollection&, MemoryBuffer& inBuffer, const char* inPropName, TDataType inValue )
+ {
+ inBuffer << inValue;
+ writeProperty( inWriter, inBuffer, inPropName );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxConvexMesh* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxConvexMesh* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+#ifdef REMOVED
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxTriangleMesh* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxTriangleMesh* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+#endif
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxBVH33TriangleMesh* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxBVH33TriangleMesh* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxBVH34TriangleMesh* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxBVH34TriangleMesh* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxHeightField* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxHeightField* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, const PxRigidActor* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxArticulation* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeProperty( XmlWriter& writer, PxCollection& inCollection, MemoryBuffer& /*inBuffer*/, const char* inPropName, PxRigidActor* inDatatype )
+ {
+ writeReference( writer, inCollection, inPropName, inDatatype );
+ }
+
+ inline void writeFlagsProperty( XmlWriter& inWriter, MemoryBuffer& tempBuf, const char* inPropName, PxU32 inFlags, const PxU32ToName* inTable )
+ {
+ if ( inTable )
+ {
+ PxU32 flagValue( inFlags );
+ if ( flagValue )
+ {
+ for ( PxU32 idx =0; inTable[idx].mName != NULL; ++idx )
+ {
+ if ( (inTable[idx].mValue & flagValue) == inTable[idx].mValue )
+ {
+ if ( tempBuf.mWriteOffset != 0 )
+ tempBuf << "|";
+ tempBuf << inTable[idx].mName;
+ }
+ }
+ writeProperty( inWriter, tempBuf, inPropName );
+ }
+ }
+ }
+
+ inline void writeFlagsBuffer( MemoryBuffer& tempBuf, PxU32 flagValue, const PxU32ToName* inTable )
+ {
+ PX_ASSERT(inTable);
+ bool added = false;
+
+ if ( flagValue )
+ {
+ for ( PxU32 item =0; inTable[item].mName != NULL; ++item )
+ {
+ if ( (inTable[item].mValue & flagValue) != 0 )
+ {
+ if ( added )
+ tempBuf << "|";
+ tempBuf << inTable[item].mName;
+ added = true;
+ }
+ }
+ }
+ }
+
+ inline void writePxVec3( PxOutputStream& inStream, const PxVec3& inVec ) { inStream << inVec; }
+
+
+ template<typename TDataType>
+ inline const TDataType& PtrAccess( const TDataType* inPtr, PxU32 inIndex )
+ {
+ return inPtr[inIndex];
+ }
+
+ template<typename TDataType>
+ inline void BasicDatatypeWrite( PxOutputStream& inStream, const TDataType& item ) { inStream << item; }
+
+ template<typename TObjType, typename TAccessOperator, typename TWriteOperator>
+ inline void writeBuffer( XmlWriter& inWriter, MemoryBuffer& inTempBuffer
+ , PxU32 inObjPerLine, const TObjType* inObjType, TAccessOperator inAccessOperator
+ , PxU32 inBufSize, const char* inPropName, TWriteOperator inOperator )
+ {
+ if ( inBufSize && inObjType )
+ {
+ for ( PxU32 idx = 0; idx < inBufSize; ++idx )
+ {
+ if ( idx && ( idx % inObjPerLine == 0 ) )
+ inTempBuffer << "\n\t\t\t";
+ else
+ inTempBuffer << " ";
+ inOperator( inTempBuffer, inAccessOperator( inObjType, idx ) );
+ }
+ writeProperty( inWriter, inTempBuffer, inPropName );
+ }
+ }
+
+ template<typename TDataType, typename TAccessOperator, typename TWriteOperator>
+ inline void writeStrideBuffer( XmlWriter& inWriter, MemoryBuffer& inTempBuffer
+ , PxU32 inObjPerLine, PxStrideIterator<const TDataType>& inData, TAccessOperator inAccessOperator
+ , PxU32 inBufSize, const char* inPropName, PxU32 /*inStride*/, TWriteOperator inOperator )
+ {
+ if ( inBufSize && &inData[0])
+ {
+ for ( PxU32 idx = 0; idx < inBufSize; ++idx )
+ {
+ if ( idx && ( idx % inObjPerLine == 0 ) )
+ inTempBuffer << "\n\t\t\t";
+ else
+ inTempBuffer << " ";
+
+ inOperator( inTempBuffer, inAccessOperator( &inData[idx], 0 ) );
+ }
+ writeProperty( inWriter, inTempBuffer, inPropName );
+ }
+ }
+
+
+ template<typename TDataType, typename TAccessOperator>
+ inline void writeStrideFlags( XmlWriter& inWriter, MemoryBuffer& inTempBuffer
+ , PxU32 inObjPerLine, PxStrideIterator<const TDataType>& inData, TAccessOperator /*inAccessOperator*/
+ , PxU32 inBufSize, const char* inPropName, const PxU32ToName* inTable)
+ {
+ if ( inBufSize && &inData[0])
+ {
+ for ( PxU32 idx = 0; idx < inBufSize; ++idx )
+ {
+ writeFlagsBuffer(inTempBuffer, inData[idx], inTable);
+
+ if ( idx && ( idx % inObjPerLine == 0 ) )
+ inTempBuffer << "\n\t\t\t";
+ else
+ inTempBuffer << " ";
+ }
+ writeProperty( inWriter, inTempBuffer, inPropName );
+ }
+ }
+
+ template<typename TDataType, typename TWriteOperator>
+ inline void writeBuffer( XmlWriter& inWriter, MemoryBuffer& inTempBuffer
+ , PxU32 inObjPerLine, const TDataType* inBuffer
+ , PxU32 inBufSize, const char* inPropName, TWriteOperator inOperator )
+ {
+ writeBuffer( inWriter, inTempBuffer, inObjPerLine, inBuffer, PtrAccess<TDataType>, inBufSize, inPropName, inOperator );
+ }
+
+ template<typename TEnumType>
+ inline void writeEnumProperty( XmlWriter& inWriter, const char* inPropName, TEnumType inEnumValue, const PxU32ToName* inConversions )
+ {
+ PxU32 theValue = static_cast<PxU32>( inEnumValue );
+ for ( const PxU32ToName* conv = inConversions; conv->mName != NULL; ++conv )
+ if ( conv->mValue == theValue ) inWriter.write( inPropName, conv->mName );
+ }
+
+
+
+ template<typename TObjType, typename TWriterType, typename TInfoType>
+ inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, TInfoType& info);
+
+ template<typename TCollectionType, typename TVisitor, typename TPropType, typename TInfoType >
+ void handleComplexCollection( TVisitor& visitor, const TPropType& inProp, const char* childName, TInfoType& inInfo )
+ {
+ PxU32 count( inProp.size( visitor.mObj ) );
+ if ( count )
+ {
+ Ps::InlineArray<TCollectionType*,5> theData;
+ theData.resize( count );
+ inProp.get( visitor.mObj, theData.begin(), count );
+ for( PxU32 idx =0; idx < count; ++idx )
+ {
+ visitor.pushName( childName );
+ handleComplexObj( visitor, theData[idx], inInfo );
+ visitor.popName();
+ }
+ }
+ }
+
+ template<typename TCollectionType, typename TVisitor, typename TPropType, typename TInfoType >
+ void handleBufferCollection( TVisitor& visitor, const TPropType& inProp, const char* childName, TInfoType& inInfo )
+ {
+ PxU32 count( inProp.size( visitor.mObj ) );
+ if ( count )
+ {
+ Ps::InlineArray<TCollectionType*,5> theData;
+ theData.resize( count );
+ inProp.get( visitor.mObj, theData.begin());
+
+ for( PxU32 idx =0; idx < count; ++idx )
+ {
+ visitor.pushName( childName );
+ handleComplexObj( visitor, theData[idx], inInfo );
+ visitor.popName();
+ }
+ }
+ }
+
+ template<typename TVisitor>
+ void handleShapes( TVisitor& visitor, const PxRigidActorShapeCollection& inProp )
+ {
+ PxShapeGeneratedInfo theInfo;
+
+ PxU32 count( inProp.size( visitor.mObj ) );
+ if ( count )
+ {
+ Ps::InlineArray<PxShape*,5> theData;
+ theData.resize( count );
+ inProp.get( visitor.mObj, theData.begin(), count );
+ for( PxU32 idx = 0; idx < count; ++idx )
+ {
+ const PxShape* shape = theData[idx];
+ visitor.pushName( "PxShape" );
+
+ if( !shape->isExclusive() )
+ {
+ writeReference( visitor.mWriter, visitor.mCollection, "PxShapeRef", shape );
+ }
+ else
+ {
+ handleComplexObj( visitor, shape, theInfo );
+ }
+ visitor.popName();
+ }
+ }
+ }
+
+ template<typename TVisitor>
+ void handleShapeMaterials( TVisitor& visitor, const PxShapeMaterialsProperty& inProp )
+ {
+ PxU32 count( inProp.size( visitor.mObj ) );
+ if ( count )
+ {
+ Ps::InlineArray<PxMaterial*,5> theData;
+ theData.resize( count );
+ inProp.get( visitor.mObj, theData.begin(), count );
+ visitor.pushName( "PxMaterialRef" );
+
+ for( PxU32 idx =0; idx < count; ++idx )
+ writeReference( visitor.mWriter, visitor.mCollection, "PxMaterialRef", theData[idx] );
+ visitor.popName();
+ }
+ }
+
+ template<typename TObjType>
+ struct RepXVisitorWriterBase
+ {
+ TNameStack& mNameStack;
+ XmlWriter& mWriter;
+ const TObjType* mObj;
+ MemoryBuffer& mTempBuffer;
+ PxCollection& mCollection;
+
+ RepXVisitorWriterBase( TNameStack& ns, XmlWriter& writer, const TObjType* obj, MemoryBuffer& buf, PxCollection& collection )
+ : mNameStack( ns )
+ , mWriter( writer )
+ , mObj( obj )
+ , mTempBuffer( buf )
+ , mCollection( collection )
+ {
+ }
+
+ RepXVisitorWriterBase( const RepXVisitorWriterBase<TObjType>& other )
+ : mNameStack( other.mNameStack )
+ , mWriter( other.mWriter )
+ , mObj( other.mObj )
+ , mTempBuffer( other.mTempBuffer )
+ , mCollection( other.mCollection )
+ {
+ }
+
+ RepXVisitorWriterBase& operator=( const RepXVisitorWriterBase& ){ PX_ASSERT( false ); return *this; }
+
+ void gotoTopName()
+ {
+ if ( mNameStack.size() && mNameStack.back().mOpen == false )
+ {
+ mWriter.addAndGotoChild( mNameStack.back().mName );
+ mNameStack.back().mOpen = true;
+ }
+ }
+
+ void pushName( const char* inName )
+ {
+ gotoTopName();
+ mNameStack.pushBack( inName );
+ }
+
+ void pushBracketedName( const char* inName ) { pushName( inName ); }
+ void popName()
+ {
+ if ( mNameStack.size() )
+ {
+ if ( mNameStack.back().mOpen )
+ mWriter.leaveChild();
+ mNameStack.popBack();
+ }
+ }
+
+ const char* topName() const
+ {
+ if ( mNameStack.size() ) return mNameStack.back().mName;
+ PX_ASSERT( false );
+ return "bad__repx__name";
+ }
+
+ template<typename TAccessorType>
+ void simpleProperty( PxU32 /*key*/, TAccessorType& inProp )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ TPropertyType propVal = inProp.get( mObj );
+ writeProperty( mWriter, mCollection, mTempBuffer, topName(), propVal );
+ }
+
+ template<typename TAccessorType>
+ void enumProperty( PxU32 /*key*/, TAccessorType& inProp, const PxU32ToName* inConversions )
+ {
+ writeEnumProperty( mWriter, topName(), inProp.get( mObj ), inConversions );
+ }
+
+ template<typename TAccessorType>
+ void flagsProperty( PxU32 /*key*/, const TAccessorType& inProp, const PxU32ToName* inConversions )
+ {
+ writeFlagsProperty( mWriter, mTempBuffer, topName(), inProp.get( mObj ), inConversions );
+ }
+
+ template<typename TAccessorType, typename TInfoType>
+ void complexProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ TPropertyType propVal = inProp.get( mObj );
+ handleComplexObj( *this, &propVal, inInfo );
+ }
+
+ template<typename TAccessorType, typename TInfoType>
+ void bufferCollectionProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+
+ PxU32 count( inProp.size( mObj ) );
+ Ps::InlineArray<TPropertyType,5> theData;
+ theData.resize( count );
+
+ PxClassInfoTraits<TInfoType> theTraits;
+ PX_UNUSED(theTraits);
+ PxU32 numItems = inProp.get( mObj, theData.begin(), count );
+ PX_ASSERT( numItems == count );
+ for( PxU32 idx =0; idx < numItems; ++idx )
+ {
+ pushName( inProp.name() );
+ handleComplexObj( *this, &theData[idx], inInfo );
+ popName();
+ }
+ }
+
+ template<typename TAccessorType, typename TInfoType>
+ void extendedIndexedProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& /*inInfo */)
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+
+ PxU32 count( inProp.size( mObj ) );
+ Ps::InlineArray<TPropertyType,5> theData;
+ theData.resize( count );
+
+ for(PxU32 i = 0; i < count; ++i)
+ {
+ char buffer[32] = { 0 };
+ sprintf( buffer, "id_%u", i );
+ pushName( buffer );
+
+ TPropertyType propVal = inProp.get( mObj, i );
+ TInfoType& infoType = PxClassInfoTraits<TPropertyType>().Info;
+ handleComplexObj(*this, &propVal, infoType);
+ popName();
+ }
+ }
+
+ template<typename TAccessorType, typename TInfoType>
+ void PxFixedSizeLookupTableProperty( PxU32* /*key*/, TAccessorType& inProp, TInfoType& /*inInfo */)
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ PxU32 count( inProp.size( mObj ) );
+
+ PxU32 index = 0;
+ for(PxU32 i = 0; i < count; ++i)
+ {
+ char buffer[32] = { 0 };
+ sprintf( buffer, "id_%u", index++ );
+ pushName( buffer );
+ TPropertyType propVal = inProp.getX( mObj , i);
+ writeProperty( mWriter, mCollection, mTempBuffer, topName(), propVal );
+ popName();
+
+ sprintf( buffer, "id_%u", index++ );
+ pushName( buffer );
+ propVal = inProp.getY( mObj , i);
+ writeProperty( mWriter, mCollection, mTempBuffer, topName(), propVal );
+ popName();
+ }
+ }
+
+
+ void handleShapes( const PxRigidActorShapeCollection& inProp )
+ {
+ physx::Sn::handleShapes( *this, inProp );
+ }
+
+ void handleShapeMaterials( const PxShapeMaterialsProperty& inProp )
+ {
+ physx::Sn::handleShapeMaterials( *this, inProp );
+ }
+ };
+
+ template<typename TObjType>
+ struct RepXVisitorWriter : RepXVisitorWriterBase<TObjType>
+ {
+ RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const TObjType* obj, MemoryBuffer& buf, PxCollection& collection )
+ : RepXVisitorWriterBase<TObjType>( ns, writer, obj, buf, collection )
+ {
+ }
+
+ RepXVisitorWriter( const RepXVisitorWriter<TObjType>& other )
+ : RepXVisitorWriterBase<TObjType>( other )
+ {
+ }
+ };
+
+ template<>
+ struct RepXVisitorWriter<PxArticulationLink> : RepXVisitorWriterBase<PxArticulationLink>
+ {
+ RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const PxArticulationLink* obj, MemoryBuffer& buf, PxCollection& collection )
+ : RepXVisitorWriterBase<PxArticulationLink>( ns, writer, obj, buf, collection )
+ {
+ }
+
+ RepXVisitorWriter( const RepXVisitorWriter<PxArticulationLink>& other )
+ : RepXVisitorWriterBase<PxArticulationLink>( other )
+ {
+ }
+
+ void handleIncomingJoint( const TIncomingJointPropType& prop )
+ {
+ const PxArticulationJoint* theJoint( prop.get( mObj ) );
+ if ( theJoint )
+ {
+ PxArticulationJointGeneratedInfo info;
+ pushName( "Joint" );
+ handleComplexObj( *this, theJoint, info );
+ popName();
+ }
+ }
+ };
+
+ typedef PxProfileHashMap< const PxSerialObjectId, const PxArticulationLink* > TArticulationLinkLinkMap;
+
+ template<>
+ struct RepXVisitorWriter<PxArticulation> : RepXVisitorWriterBase<PxArticulation>
+ {
+ TArticulationLinkLinkMap& mArticulationLinkParents;
+
+ RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const PxArticulation* inArticulation, MemoryBuffer& buf, PxCollection& collection, TArticulationLinkLinkMap* artMap = NULL )
+ : RepXVisitorWriterBase<PxArticulation>( ns, writer, inArticulation, buf, collection )
+ , mArticulationLinkParents( *artMap )
+ {
+ Ps::InlineArray<PxArticulationLink*, 64, PxProfileWrapperReflectionAllocator<PxArticulationLink*> > linkList( PxProfileWrapperReflectionAllocator<PxArticulationLink*>( buf.mManager->getWrapper() ) );
+ PxU32 numLinks = inArticulation->getNbLinks();
+ linkList.resize( numLinks );
+ inArticulation->getLinks( linkList.begin(), numLinks );
+ for ( PxU32 idx = 0; idx < numLinks; ++idx )
+ {
+ const PxArticulationLink* theLink( linkList[idx] );
+
+ Ps::InlineArray<PxArticulationLink*, 64> theChildList;
+ PxU32 numChildren = theLink->getNbChildren();
+ theChildList.resize( numChildren );
+ theLink->getChildren( theChildList.begin(), numChildren );
+ for ( PxU32 childIdx = 0; childIdx < numChildren; ++childIdx )
+ mArticulationLinkParents.insert( PX_PROFILE_POINTER_TO_U64(theChildList[childIdx]), theLink );
+ }
+ }
+
+ RepXVisitorWriter( const RepXVisitorWriter<PxArticulation>& other )
+ : RepXVisitorWriterBase<PxArticulation>( other )
+ , mArticulationLinkParents( other.mArticulationLinkParents )
+ {
+ }
+ template<typename TAccessorType, typename TInfoType>
+ void complexProperty( PxU32* /*key*/, const TAccessorType& inProp, TInfoType& inInfo )
+ {
+ typedef typename TAccessorType::prop_type TPropertyType;
+ TPropertyType propVal = inProp.get( mObj );
+ handleComplexObj( *this, &propVal, inInfo );
+ }
+
+ void writeArticulationLink( const PxArticulationLink* inLink )
+ {
+ pushName( "PxArticulationLink" );
+ gotoTopName();
+
+ const TArticulationLinkLinkMap::Entry* theParentPtr = mArticulationLinkParents.find( PX_PROFILE_POINTER_TO_U64(inLink) );
+ if ( theParentPtr != NULL )
+ writeProperty( mWriter, mCollection, mTempBuffer, "Parent", theParentPtr->second );
+ writeProperty( mWriter, mCollection, mTempBuffer, "Id", inLink );
+
+ PxArticulationLinkGeneratedInfo info;
+ handleComplexObj( *this, inLink, info );
+ popName();
+ }
+
+ void recurseAddLinkAndChildren( const PxArticulationLink* inLink, Ps::InlineArray<const PxArticulationLink*, 64>& ioLinks )
+ {
+ ioLinks.pushBack( inLink );
+ Ps::InlineArray<PxArticulationLink*, 8> theChildren;
+ PxU32 childCount( inLink->getNbChildren() );
+ theChildren.resize( childCount );
+ inLink->getChildren( theChildren.begin(), childCount );
+ for ( PxU32 idx = 0; idx < childCount; ++idx )
+ recurseAddLinkAndChildren( theChildren[idx], ioLinks );
+ }
+
+ void handleArticulationLinks( const PxArticulationLinkCollectionProp& inProp )
+ {
+ //topologically sort the links as per my discussion with Dilip because
+ //links aren't guaranteed to have the parents before the children in the
+ //overall link list and it is unlikely to be done by beta 1.
+ PxU32 count( inProp.size( mObj ) );
+ if ( count )
+ {
+ Ps::InlineArray<PxArticulationLink*, 64> theLinks;
+ theLinks.resize( count );
+ inProp.get( mObj, theLinks.begin(), count );
+
+ Ps::InlineArray<const PxArticulationLink*, 64> theSortedLinks;
+ for ( PxU32 idx = 0; idx < count; ++idx )
+ {
+ const PxArticulationLink* theLink( theLinks[idx] );
+ if ( mArticulationLinkParents.find( PX_PROFILE_POINTER_TO_U64(theLink) ) == NULL )
+ recurseAddLinkAndChildren( theLink, theSortedLinks );
+ }
+ PX_ASSERT( theSortedLinks.size() == count );
+ for ( PxU32 idx = 0; idx < count; ++idx )
+ writeArticulationLink( theSortedLinks[idx] );
+ popName();
+ }
+ }
+ private:
+ RepXVisitorWriter<PxArticulation>& operator=(const RepXVisitorWriter<PxArticulation>&);
+ };
+
+ template<>
+ struct RepXVisitorWriter<PxShape> : RepXVisitorWriterBase<PxShape>
+ {
+ RepXVisitorWriter( TNameStack& ns, XmlWriter& writer, const PxShape* obj, MemoryBuffer& buf, PxCollection& collection )
+ : RepXVisitorWriterBase<PxShape>( ns, writer, obj, buf, collection )
+ {
+ }
+
+ RepXVisitorWriter( const RepXVisitorWriter<PxShape>& other )
+ : RepXVisitorWriterBase<PxShape>( other )
+ {
+ }
+
+ template<typename GeometryType>
+ inline void writeGeometryProperty( const PxShapeGeometryProperty& inProp, const char* inTypeName )
+ {
+ pushName( "Geometry" );
+ pushName( inTypeName );
+ GeometryType theType;
+ inProp.getGeometry( mObj, theType );
+ PxClassInfoTraits<GeometryType> theTraits;
+ PxU32 count = theTraits.Info.totalPropertyCount();
+ if(count)
+ {
+ handleComplexObj( *this, &theType, theTraits.Info);
+ }
+ else
+ {
+ writeProperty(mWriter, mTempBuffer, inTypeName);
+ }
+ popName();
+ popName();
+ }
+
+ void handleGeometryProperty( const PxShapeGeometryProperty& inProp )
+ {
+ switch( mObj->getGeometryType() )
+ {
+ case PxGeometryType::eSPHERE: writeGeometryProperty<PxSphereGeometry>( inProp, "PxSphereGeometry" ); break;
+ case PxGeometryType::ePLANE: writeGeometryProperty<PxPlaneGeometry>( inProp, "PxPlaneGeometry" ); break;
+ case PxGeometryType::eCAPSULE: writeGeometryProperty<PxCapsuleGeometry>( inProp, "PxCapsuleGeometry" ); break;
+ case PxGeometryType::eBOX: writeGeometryProperty<PxBoxGeometry>( inProp, "PxBoxGeometry" ); break;
+ case PxGeometryType::eCONVEXMESH: writeGeometryProperty<PxConvexMeshGeometry>( inProp, "PxConvexMeshGeometry" ); break;
+ case PxGeometryType::eTRIANGLEMESH: writeGeometryProperty<PxTriangleMeshGeometry>( inProp, "PxTriangleMeshGeometry" ); break;
+ case PxGeometryType::eHEIGHTFIELD: writeGeometryProperty<PxHeightFieldGeometry>( inProp, "PxHeightFieldGeometry" ); break;
+ case PxGeometryType::eINVALID:
+ case PxGeometryType::eGEOMETRY_COUNT:
+ PX_ASSERT( false );
+ }
+ }
+ };
+
+ template<typename TObjType>
+ inline void writeAllProperties( TNameStack& inNameStack, const TObjType* inObj, XmlWriter& writer, MemoryBuffer& buffer, PxCollection& collection )
+ {
+ RepXVisitorWriter<TObjType> newVisitor( inNameStack, writer, inObj, buffer, collection );
+ RepXPropertyFilter<RepXVisitorWriter<TObjType> > theOp( newVisitor );
+ PxClassInfoTraits<TObjType> info;
+ info.Info.visitBaseProperties( theOp );
+ info.Info.visitInstanceProperties( theOp );
+ }
+
+ template<typename TObjType>
+ inline void writeAllProperties( TNameStack& inNameStack, TObjType* inObj, XmlWriter& writer, MemoryBuffer& buffer, PxCollection& collection )
+ {
+ RepXVisitorWriter<TObjType> newVisitor( inNameStack, writer, inObj, buffer, collection );
+ RepXPropertyFilter<RepXVisitorWriter<TObjType> > theOp( newVisitor );
+ PxClassInfoTraits<TObjType> info;
+ info.Info.visitBaseProperties( theOp );
+ info.Info.visitInstanceProperties( theOp );
+ }
+
+ template<typename TObjType>
+ inline void writeAllProperties( const TObjType* inObj, XmlWriter& writer, MemoryBuffer& buffer, PxCollection& collection )
+ {
+ TNameStack theNames( buffer.mManager->getWrapper() );
+ writeAllProperties( theNames, inObj, writer, buffer, collection );
+ }
+
+ template<typename TObjType, typename TWriterType, typename TInfoType>
+ inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, const TInfoType& /*info*/)
+ {
+ writeAllProperties( oldVisitor.mNameStack, inObj, oldVisitor.mWriter, oldVisitor.mTempBuffer, oldVisitor.mCollection );
+ }
+
+ template<typename TObjType, typename TWriterType, typename TInfoType>
+ inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, TInfoType& /*info*/)
+ {
+ writeAllProperties( oldVisitor.mNameStack, inObj, oldVisitor.mWriter, oldVisitor.mTempBuffer, oldVisitor.mCollection );
+ }
+
+ template<typename TObjType, typename TWriterType>
+ inline void handleComplexObj( TWriterType& oldVisitor, const TObjType* inObj, const PxUnknownClassInfo& /*info*/)
+ {
+ writeProperty( oldVisitor.mWriter, oldVisitor.mCollection, oldVisitor.mTempBuffer, oldVisitor.topName(), *inObj );
+ }
+
+} }
+#endif
diff --git a/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlWriter.h b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlWriter.h
new file mode 100644
index 00000000..afea8aa0
--- /dev/null
+++ b/PhysX_3.4/Source/PhysXExtensions/src/serialization/Xml/SnXmlWriter.h
@@ -0,0 +1,57 @@
+// 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_XML_WRITER_H
+#define PX_XML_WRITER_H
+
+#include "foundation/PxSimpleTypes.h"
+
+namespace physx {
+
+ struct PxRepXObject;
+
+ /**
+ * Writer used by extensions to write elements to a file or database
+ */
+ class XmlWriter
+ {
+ protected:
+ virtual ~XmlWriter(){}
+ public:
+ /** Write a key-value pair into the current item */
+ virtual void write( const char* inName, const char* inData ) = 0;
+ /** Write an object id into the current item */
+ virtual void write( const char* inName, const PxRepXObject& inLiveObject ) = 0;
+ /** Add a child that then becomes the current context */
+ virtual void addAndGotoChild( const char* inName ) = 0;
+ /** Leave the current child */
+ virtual void leaveChild() = 0;
+ };
+}
+
+#endif