aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/LowLevel/common
diff options
context:
space:
mode:
Diffstat (limited to 'PhysX_3.4/Source/LowLevel/common')
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/collision/PxcContactMethodImpl.h98
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcCCDStateStreamPair.h29
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcConstraintBlockStream.h166
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcContactCache.h64
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcMaterialMethodImpl.h69
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpBatch.h65
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpCache.h154
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpCacheStreamPair.h63
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpContactPrepShared.h59
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpMemBlockPool.h119
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpThreadContext.h216
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpWorkUnit.h162
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcRigidBody.h117
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/utils/PxcScratchAllocator.h138
-rw-r--r--PhysX_3.4/Source/LowLevel/common/include/utils/PxcThreadCoherentCache.h150
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/collision/PxcContact.cpp289
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactCache.cpp393
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactMethodImpl.cpp279
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialHeightField.cpp116
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialMesh.cpp107
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialMethodImpl.cpp140
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialShape.cpp62
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpBatch.cpp413
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpCacheStreamPair.cpp75
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpContactPrepShared.cpp623
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp351
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpThreadContext.cpp93
27 files changed, 4610 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/LowLevel/common/include/collision/PxcContactMethodImpl.h b/PhysX_3.4/Source/LowLevel/common/include/collision/PxcContactMethodImpl.h
new file mode 100644
index 00000000..193b20a5
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/collision/PxcContactMethodImpl.h
@@ -0,0 +1,98 @@
+// 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 PXC_CONTACTMETHODIMPL_H
+#define PXC_CONTACTMETHODIMPL_H
+
+#include "GuGeometryUnion.h"
+#include "CmPhysXCommon.h"
+#include "GuContactMethodImpl.h"
+
+namespace physx
+{
+namespace Cm
+{
+ class RenderOutput;
+}
+
+namespace Gu
+{
+ class ContactBuffer;
+ struct Cache;
+ struct NarrowPhaseParams;
+}
+
+struct PxcNpCache;
+class PxcNpThreadContext;
+class PxsContext;
+class PxcConvexTriangles;
+class PxsRigidBody;
+struct PxsCCDShape;
+
+namespace Cm
+{
+ class FastVertex2ShapeScaling;
+}
+
+/*!\file
+This file contains forward declarations of all implemented contact methods.
+*/
+
+
+/*! Parameter list without names to avoid unused parameter warnings
+*/
+#define CONTACT_METHOD_ARGS_UNUSED \
+ const Gu::GeometryUnion&, \
+ const Gu::GeometryUnion&, \
+ const PxTransform&, \
+ const PxTransform&, \
+ const Gu::NarrowPhaseParams&, \
+ Gu::Cache&, \
+ Gu::ContactBuffer&, \
+ Cm::RenderOutput*
+
+
+/*!
+Method prototype for contact generation routines
+*/
+typedef bool (*PxcContactMethod) (GU_CONTACT_METHOD_ARGS);
+
+
+// Matrix of types
+extern PxcContactMethod g_ContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT];
+extern const bool g_CanUseContactCache[][PxGeometryType::eGEOMETRY_COUNT];
+extern PxcContactMethod g_PCMContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT];
+
+extern bool gEnablePCMCaching[][PxGeometryType::eGEOMETRY_COUNT];
+
+extern bool gUnifiedHeightfieldCollision;
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcCCDStateStreamPair.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcCCDStateStreamPair.h
new file mode 100644
index 00000000..cf29bad0
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcCCDStateStreamPair.h
@@ -0,0 +1,29 @@
+// 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.
+
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcConstraintBlockStream.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcConstraintBlockStream.h
new file mode 100644
index 00000000..37c0ba8e
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcConstraintBlockStream.h
@@ -0,0 +1,166 @@
+// 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 PXC_CONSTRAINTBLOCKPOOL_H
+#define PXC_CONSTRAINTBLOCKPOOL_H
+
+#include "PxvConfig.h"
+#include "PsArray.h"
+#include "PsMutex.h"
+#include "PxcNpMemBlockPool.h"
+
+namespace physx
+{
+
+class PxsConstraintBlockManager
+{
+public:
+ PxsConstraintBlockManager(PxcNpMemBlockPool & blockPool):
+ mBlockPool(blockPool)
+ {
+ }
+
+
+ PX_FORCE_INLINE void reset()
+ {
+ mBlockPool.releaseConstraintBlocks(mTrackingArray);
+ }
+
+
+ PxcNpMemBlockArray mTrackingArray;
+ PxcNpMemBlockPool& mBlockPool;
+
+private:
+ PxsConstraintBlockManager& operator=(const PxsConstraintBlockManager&);
+};
+
+class PxcConstraintBlockStream
+{
+ PX_NOCOPY(PxcConstraintBlockStream)
+public:
+ PxcConstraintBlockStream(PxcNpMemBlockPool & blockPool):
+ mBlockPool(blockPool),
+ mBlock(NULL),
+ mUsed(0)
+ {
+ }
+
+ PX_FORCE_INLINE PxU8* reserve(PxU32 size, PxsConstraintBlockManager& manager)
+ {
+ size = (size+15)&~15;
+ if(size>PxcNpMemBlock::SIZE)
+ return mBlockPool.acquireExceptionalConstraintMemory(size);
+
+ if(mBlock == NULL || size+mUsed>PxcNpMemBlock::SIZE)
+ {
+ mBlock = mBlockPool.acquireConstraintBlock(manager.mTrackingArray);
+ PX_ASSERT(0==mBlock || mBlock->data == reinterpret_cast<PxU8*>(mBlock));
+ mUsed = size;
+ return reinterpret_cast<PxU8*>(mBlock);
+ }
+ PX_ASSERT(mBlock && mBlock->data == reinterpret_cast<PxU8*>(mBlock));
+ PxU8* PX_RESTRICT result = mBlock->data+mUsed;
+ mUsed += size;
+ return result;
+ }
+
+ PX_FORCE_INLINE void reset()
+ {
+ mBlock = NULL;
+ mUsed = 0;
+ }
+
+ PX_FORCE_INLINE PxcNpMemBlockPool& getMemBlockPool()
+ {
+ return mBlockPool;
+ }
+
+private:
+ PxcNpMemBlockPool& mBlockPool;
+ PxcNpMemBlock* mBlock; // current constraint block
+ PxU32 mUsed; // number of bytes used in constraint block
+ //Tracking peak allocations
+ PxU32 mPeakUsed;
+};
+
+class PxcContactBlockStream
+{
+ PX_NOCOPY(PxcContactBlockStream)
+public:
+ PxcContactBlockStream(PxcNpMemBlockPool & blockPool):
+ mBlockPool(blockPool),
+ mBlock(NULL),
+ mUsed(0)
+ {
+ }
+
+ PX_FORCE_INLINE PxU8* reserve(PxU32 size)
+ {
+ size = (size+15)&~15;
+
+ if(size>PxcNpMemBlock::SIZE)
+ return mBlockPool.acquireExceptionalConstraintMemory(size);
+
+ PX_ASSERT(size <= PxcNpMemBlock::SIZE);
+
+ if(mBlock == NULL || size+mUsed>PxcNpMemBlock::SIZE)
+ {
+ mBlock = mBlockPool.acquireContactBlock();
+ PX_ASSERT(0==mBlock || mBlock->data == reinterpret_cast<PxU8*>(mBlock));
+ mUsed = size;
+ return reinterpret_cast<PxU8*>(mBlock);
+ }
+ PX_ASSERT(mBlock && mBlock->data == reinterpret_cast<PxU8*>(mBlock));
+ PxU8* PX_RESTRICT result = mBlock->data+mUsed;
+ mUsed += size;
+ return result;
+ }
+
+ PX_FORCE_INLINE void reset()
+ {
+ mBlock = NULL;
+ mUsed = 0;
+ }
+
+ PX_FORCE_INLINE PxcNpMemBlockPool& getMemBlockPool()
+ {
+ return mBlockPool;
+ }
+
+private:
+ PxcNpMemBlockPool& mBlockPool;
+ PxcNpMemBlock* mBlock; // current constraint block
+ PxU32 mUsed; // number of bytes used in constraint block
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcContactCache.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcContactCache.h
new file mode 100644
index 00000000..34174b35
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcContactCache.h
@@ -0,0 +1,64 @@
+// 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 PXC_CONTACT_CACHE_H
+#define PXC_CONTACT_CACHE_H
+
+#include "foundation/PxTransform.h"
+#include "PxvConfig.h"
+#include "PxcContactMethodImpl.h"
+
+namespace physx
+{
+ bool PxcCacheLocalContacts( PxcNpThreadContext& context, Gu::Cache& pairContactCache,
+ const PxTransform& tm0, const PxTransform& tm1,
+ const PxcContactMethod conMethod,
+ const Gu::GeometryUnion& shape0, const Gu::GeometryUnion& shape1);
+
+ struct PxcLocalContactsCache
+ {
+ PxTransform mTransform0;
+ PxTransform mTransform1;
+ PxU16 mNbCachedContacts;
+ bool mUseFaceIndices;
+ bool mSameNormal;
+
+ PX_FORCE_INLINE void operator = (const PxcLocalContactsCache& other)
+ {
+ mTransform0 = other.mTransform0;
+ mTransform1 = other.mTransform1;
+ mNbCachedContacts = other.mNbCachedContacts;
+ mUseFaceIndices = other.mUseFaceIndices;
+ mSameNormal = other.mSameNormal;
+ }
+ };
+
+}
+
+#endif // PXC_CONTACT_CACHE_H
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcMaterialMethodImpl.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcMaterialMethodImpl.h
new file mode 100644
index 00000000..b7260aa4
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcMaterialMethodImpl.h
@@ -0,0 +1,69 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#ifndef PXC_MATERIALMETHOD_H
+#define PXC_MATERIALMETHOD_H
+
+#include "CmPhysXCommon.h"
+#include "PxGeometry.h"
+
+namespace physx
+{
+
+struct PxsShapeCore;
+struct PxsMaterialInfo;
+class PxcNpThreadContext;
+
+#define MATERIAL_METHOD_ARGS \
+ const PxsShapeCore* shape0, \
+ const PxsShapeCore* shape1, \
+ PxcNpThreadContext& pairContext, \
+ PxsMaterialInfo* materialInfo
+
+
+#define SINGLE_MATERIAL_METHOD_ARGS \
+ const PxsShapeCore* shape, \
+ const PxU32 index, \
+ PxcNpThreadContext& pairContext, \
+ PxsMaterialInfo* materialInfo
+
+/*!
+Method prototype for fetch material routines
+*/
+typedef bool (*PxcGetMaterialMethod) (MATERIAL_METHOD_ARGS);
+
+typedef bool (*PxcGetSingleMaterialMethod) (SINGLE_MATERIAL_METHOD_ARGS);
+
+extern PxcGetMaterialMethod g_GetMaterialMethodTable[][PxGeometryType::eGEOMETRY_COUNT];
+
+extern PxcGetSingleMaterialMethod g_GetSingleMaterialMethodTable[PxGeometryType::eGEOMETRY_COUNT];
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpBatch.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpBatch.h
new file mode 100644
index 00000000..fe243aed
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpBatch.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 PXC_NP_BATCH_H
+#define PXC_NP_BATCH_H
+
+#include "PxvConfig.h"
+
+namespace physx
+{
+ struct PxcNpWorkUnit;
+ class PxcNpThreadContext;
+
+struct PxcNpWorkUnit;
+class PxsContactManager;
+struct PxsContactManagerOutput;
+
+namespace Gu
+{
+ struct Cache;
+}
+
+namespace Cm
+{
+ class FlushPool;
+}
+
+class PxLightCpuTask;
+
+namespace Gu
+{
+ class PxgGpuNarrowphaseCoreInterface;
+}
+
+void PxcDiscreteNarrowPhase(PxcNpThreadContext& context, PxcNpWorkUnit& cmInput, Gu::Cache& cache, PxsContactManagerOutput& output);
+void PxcDiscreteNarrowPhasePCM(PxcNpThreadContext& context, PxcNpWorkUnit& cmInput, Gu::Cache& cache, PxsContactManagerOutput& output);
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpCache.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpCache.h
new file mode 100644
index 00000000..2ac7dde8
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpCache.h
@@ -0,0 +1,154 @@
+// 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 PXC_NPCACHE_H
+#define PXC_NPCACHE_H
+
+#include "foundation/PxMemory.h"
+
+#include "PsIntrinsics.h"
+#include "PxcNpCacheStreamPair.h"
+
+#include "PsPool.h"
+#include "PsFoundation.h"
+#include "GuContactMethodImpl.h"
+#include "PsUtilities.h"
+
+namespace physx
+{
+
+template <typename T>
+void PxcNpCacheWrite(PxcNpCacheStreamPair& streams,
+ Gu::Cache& cache,
+ const T& payload,
+ PxU32 bytes,
+ const PxU8* data)
+{
+ const PxU32 payloadSize = (sizeof(payload)+3)&~3;
+ cache.mCachedSize = Ps::to16((payloadSize + 4 + bytes + 0xF)&~0xF);
+
+ PxU8* ls = streams.reserve(cache.mCachedSize);
+ cache.mCachedData = ls;
+ if(ls==NULL || (reinterpret_cast<PxU8*>(-1))==ls)
+ {
+ if(ls==NULL)
+ {
+ PX_WARN_ONCE(
+ "Reached limit set by PxSceneDesc::maxNbContactDataBlocks - ran out of buffer space for narrow phase. "
+ "Either accept dropped contacts or increase buffer size allocated for narrow phase by increasing PxSceneDesc::maxNbContactDataBlocks.");
+ return;
+ }
+ else
+ {
+ PX_WARN_ONCE(
+ "Attempting to allocate more than 16K of contact data for a single contact pair in narrowphase. "
+ "Either accept dropped contacts or simplify collision geometry.");
+ cache.mCachedData = NULL;
+ ls = NULL;
+ return;
+ }
+ }
+
+ *reinterpret_cast<T*>(ls) = payload;
+ *reinterpret_cast<PxU32*>(ls+payloadSize) = bytes;
+ if(data)
+ PxMemCopy(ls+payloadSize+sizeof(PxU32), data, bytes);
+}
+
+
+template <typename T>
+PxU8* PxcNpCacheWriteInitiate(PxcNpCacheStreamPair& streams, Gu::Cache& cache, const T& payload, PxU32 bytes)
+{
+ PX_UNUSED(payload);
+
+ const PxU32 payloadSize = (sizeof(payload)+3)&~3;
+ cache.mCachedSize = Ps::to16((payloadSize + 4 + bytes + 0xF)&~0xF);
+
+ PxU8* ls = streams.reserve(cache.mCachedSize);
+ cache.mCachedData = ls;
+ if(NULL==ls || reinterpret_cast<PxU8*>(-1)==ls)
+ {
+ if(NULL==ls)
+ {
+ PX_WARN_ONCE(
+ "Reached limit set by PxSceneDesc::maxNbContactDataBlocks - ran out of buffer space for narrow phase. "
+ "Either accept dropped contacts or increase buffer size allocated for narrow phase by increasing PxSceneDesc::maxNbContactDataBlocks.");
+ }
+ else
+ {
+ PX_WARN_ONCE(
+ "Attempting to allocate more than 16K of contact data for a single contact pair in narrowphase. "
+ "Either accept dropped contacts or simplify collision geometry.");
+ cache.mCachedData = NULL;
+ ls = NULL;
+ }
+ }
+ return ls;
+}
+
+template <typename T>
+PX_FORCE_INLINE void PxcNpCacheWriteFinalize(PxU8* ls, const T& payload, PxU32 bytes, const PxU8* data)
+{
+ const PxU32 payloadSize = (sizeof(payload)+3)&~3;
+ *reinterpret_cast<T*>(ls) = payload;
+ *reinterpret_cast<PxU32*>(ls+payloadSize) = bytes;
+ if(data)
+ PxMemCopy(ls+payloadSize+sizeof(PxU32), data, bytes);
+}
+
+
+template <typename T>
+PX_FORCE_INLINE PxU8* PxcNpCacheRead(Gu::Cache& cache, T*& payload)
+{
+ PxU8* ls = cache.mCachedData;
+ payload = reinterpret_cast<T*>(ls);
+ const PxU32 payloadSize = (sizeof(T)+3)&~3;
+ return reinterpret_cast<PxU8*>(ls+payloadSize+sizeof(PxU32));
+}
+
+template <typename T>
+const PxU8* PxcNpCacheRead2(Gu::Cache& cache, T& payload, PxU32& bytes)
+{
+ const PxU8* ls = cache.mCachedData;
+ if(ls==NULL)
+ {
+ bytes = 0;
+ return NULL;
+ }
+
+ const PxU32 payloadSize = (sizeof(payload)+3)&~3;
+ payload = *reinterpret_cast<const T*>(ls);
+ bytes = *reinterpret_cast<const PxU32*>(ls+payloadSize);
+ PX_ASSERT(cache.mCachedSize == ((payloadSize + 4 + bytes+0xF)&~0xF));
+ return reinterpret_cast<const PxU8*>(ls+payloadSize+sizeof(PxU32));
+}
+
+}
+
+#endif // #ifndef PXC_NPCACHE_H
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpCacheStreamPair.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpCacheStreamPair.h
new file mode 100644
index 00000000..08757b8c
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpCacheStreamPair.h
@@ -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.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+
+#ifndef PXC_NPCACHESTREAMPAIR_H
+#define PXC_NPCACHESTREAMPAIR_H
+
+#include "foundation/PxSimpleTypes.h"
+#include "PxvConfig.h"
+#include "PxcNpMemBlockPool.h"
+
+namespace physx
+{
+
+static const PxU32 PXC_NPCACHE_BLOCK_SIZE = 16384;
+
+
+struct PxcNpCacheStreamPair
+{
+public:
+ PxcNpCacheStreamPair(PxcNpMemBlockPool& blockPool);
+
+ // reserve can fail and return null.
+ PxU8* reserve(PxU32 byteCount);
+ void reset();
+private:
+ PxcNpMemBlockPool& mBlockPool;
+ PxcNpMemBlock* mBlock;
+ PxU32 mUsed;
+private:
+ PxcNpCacheStreamPair& operator=(const PxcNpCacheStreamPair&);
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpContactPrepShared.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpContactPrepShared.h
new file mode 100644
index 00000000..4fc9c122
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpContactPrepShared.h
@@ -0,0 +1,59 @@
+// 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 PXC_NPCONTACTPREPSHARED_H
+#define PXC_NPCONTACTPREPSHARED_H
+
+namespace physx
+{
+class PxcNpThreadContext;
+struct PxsMaterialInfo;
+class PxsMaterialManager;
+class PxsConstraintBlockManager;
+class PxcConstraintBlockStream;
+struct PxsContactManagerOutput;
+
+namespace Gu
+{
+ struct ContactPoint;
+}
+
+static const PxReal PXC_SAME_NORMAL = 0.999f; //Around 6 degrees
+
+bool finishContacts(PxcNpWorkUnit& input, PxsContactManagerOutput& npOutput, PxcNpThreadContext& threadContext, PxsMaterialInfo* pMaterialInfo, const bool isMeshType);
+
+PxU32 writeCompressedContact(const Gu::ContactPoint* const PX_RESTRICT contactPoints, const PxU32 numContactPoints, PxcNpThreadContext* threadContext,
+ PxU8& writtenContactCount, PxU8*& outContactPatches, PxU8*& outContactPoints, PxU16& compressedContactSize, PxReal*& contactForces, PxU32 contactForceByteSize,
+ const PxsMaterialManager* materialManager, bool hasModifiableContacts, bool forceNoResponse, PxsMaterialInfo* PX_RESTRICT pMaterial, PxU8& numPatches,
+ PxU32 additionalHeaderSize = 0, PxsConstraintBlockManager* manager = NULL, PxcConstraintBlockStream* blockStream = NULL, bool insertAveragePoint = false,
+ PxcDataStreamPool* pool = NULL, PxcDataStreamPool* patchStreamPool = NULL, PxcDataStreamPool* forcePool = NULL, const bool isMeshType = false);
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpMemBlockPool.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpMemBlockPool.h
new file mode 100644
index 00000000..8374cfa9
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpMemBlockPool.h
@@ -0,0 +1,119 @@
+// 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 PXC_NP_MEM_BLOCK_POOL_H
+#define PXC_NP_MEM_BLOCK_POOL_H
+
+#include "PxvConfig.h"
+#include "PsArray.h"
+#include "PxcScratchAllocator.h"
+
+namespace physx
+{
+struct PxcNpMemBlock
+{
+ enum
+ {
+ SIZE = 16384
+ };
+ PxU8 data[SIZE];
+};
+
+typedef Ps::Array<PxcNpMemBlock*> PxcNpMemBlockArray;
+
+class PxcNpMemBlockPool
+{
+ PX_NOCOPY(PxcNpMemBlockPool)
+public:
+ PxcNpMemBlockPool(PxcScratchAllocator& allocator);
+ ~PxcNpMemBlockPool();
+
+ void init(PxU32 initial16KDataBlocks, PxU32 maxBlocks);
+ void flush();
+ void setBlockCount(PxU32 count);
+ PxU32 getUsedBlockCount() const;
+ PxU32 getMaxUsedBlockCount() const;
+ PxU32 getPeakConstraintBlockCount() const;
+ void releaseUnusedBlocks();
+
+ PxcNpMemBlock* acquireConstraintBlock();
+ PxcNpMemBlock* acquireConstraintBlock(PxcNpMemBlockArray& memBlocks);
+ PxcNpMemBlock* acquireContactBlock();
+ PxcNpMemBlock* acquireFrictionBlock();
+ PxcNpMemBlock* acquireNpCacheBlock();
+
+ PxU8* acquireExceptionalConstraintMemory(PxU32 size);
+
+ void acquireConstraintMemory();
+ void releaseConstraintMemory();
+ void releaseConstraintBlocks(PxcNpMemBlockArray& memBlocks);
+ void releaseContacts();
+ void swapFrictionStreams();
+ void swapNpCacheStreams();
+
+ void flushUnused();
+
+private:
+
+
+ Ps::Mutex mLock;
+ PxcNpMemBlockArray mConstraints;
+ PxcNpMemBlockArray mContacts[2];
+ PxcNpMemBlockArray mFriction[2];
+ PxcNpMemBlockArray mNpCache[2];
+ PxcNpMemBlockArray mScratchBlocks;
+ Ps::Array<PxU8*> mExceptionalConstraints;
+
+ PxcNpMemBlockArray mUnused;
+
+ PxU32 mNpCacheActiveStream;
+ PxU32 mFrictionActiveStream;
+ PxU32 mCCDCacheActiveStream;
+ PxU32 mContactIndex;
+ PxU32 mAllocatedBlocks;
+ PxU32 mMaxBlocks;
+ PxU32 mInitialBlocks;
+ PxU32 mUsedBlocks;
+ PxU32 mMaxUsedBlocks;
+ PxcNpMemBlock* mScratchBlockAddr;
+ PxU32 mNbScratchBlocks;
+ PxcScratchAllocator& mScratchAllocator;
+
+ PxU32 mPeakConstraintAllocations;
+ PxU32 mConstraintAllocations;
+
+ PxcNpMemBlock* acquire(PxcNpMemBlockArray& trackingArray, PxU32* allocationCount = NULL, PxU32* peakAllocationCount = NULL, bool isScratchAllocation = false);
+ void release(PxcNpMemBlockArray& deadArray, PxU32* allocationCount = NULL);
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpThreadContext.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpThreadContext.h
new file mode 100644
index 00000000..ef731066
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpThreadContext.h
@@ -0,0 +1,216 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#ifndef PXC_NPTHREADCONTEXT_H
+#define PXC_NPTHREADCONTEXT_H
+
+#include "PxvConfig.h"
+#include "CmScaling.h"
+#include "CmRenderOutput.h"
+#include "PxcNpCacheStreamPair.h"
+#include "PxcConstraintBlockStream.h"
+#include "GuContactBuffer.h"
+#include "PxvContext.h"
+#include "PxcThreadCoherentCache.h"
+#include "CmBitMap.h"
+#include "../pcm/GuPersistentContactManifold.h"
+
+namespace physx
+{
+
+class PxsTransformCache;
+class PxsMaterialManager;
+
+namespace Bp
+{
+ class AABBManagerImpl;
+}
+
+namespace Sc
+{
+ class BodySim;
+}
+
+/*!
+Per-thread context used by contact generation routines.
+*/
+
+struct PxcDataStreamPool
+{
+ PxU8* mDataStream;
+ PxI32 mSharedDataIndex;
+ PxU32 mDataStreamSize;
+ PxU32 mSharedDataIndexGPU;
+
+ bool isOverflown() const
+ {
+ //FD: my expectaton is that reading those variables is atomic, shared indices are non-decreasing,
+ //so we can only get a false overflow alert because of concurrency issues, which is not a big deal as it means
+ //it did overflow a bit later
+ return mSharedDataIndex + mSharedDataIndexGPU >= mDataStreamSize;
+ }
+};
+
+struct PxcNpContext
+{
+ private:
+ PX_NOCOPY(PxcNpContext)
+ public:
+
+ PxcNpContext() :
+ mNpMemBlockPool (mScratchAllocator),
+ mMeshContactMargin (0.0f),
+ mToleranceLength (0.0f),
+ mCreateContactStream (false),
+ mContactStreamPool (NULL),
+ mPatchStreamPool (NULL),
+ mForceAndIndiceStreamPool(NULL),
+ mMaterialManager (NULL)
+ {
+ }
+
+ PxcScratchAllocator mScratchAllocator;
+ PxcNpMemBlockPool mNpMemBlockPool;
+ PxReal mMeshContactMargin;
+ PxReal mToleranceLength;
+ Cm::RenderBuffer mRenderBuffer;
+ bool mCreateContactStream; // flag to enforce that contacts are stored persistently per workunit. Used for PVD.
+ PxcDataStreamPool* mContactStreamPool;
+ PxcDataStreamPool* mPatchStreamPool;
+ PxcDataStreamPool* mForceAndIndiceStreamPool;
+ PxcDataStreamPool* mConstraintWriteBackStreamPool;
+ PxsMaterialManager* mMaterialManager;
+
+ PX_FORCE_INLINE PxReal getToleranceLength() const { return mToleranceLength; }
+ PX_FORCE_INLINE void setToleranceLength(PxReal x) { mToleranceLength = x; }
+ PX_FORCE_INLINE PxReal getMeshContactMargin() const { return mMeshContactMargin; }
+ PX_FORCE_INLINE void setMeshContactMargin(PxReal x) { mMeshContactMargin = x; }
+ PX_FORCE_INLINE bool getCreateContactStream() { return mCreateContactStream; }
+
+ PX_FORCE_INLINE PxcNpMemBlockPool& getNpMemBlockPool() { return mNpMemBlockPool; }
+ PX_FORCE_INLINE const PxcNpMemBlockPool& getNpMemBlockPool() const { return mNpMemBlockPool; }
+ PX_FORCE_INLINE void setMaterialManager(PxsMaterialManager* m){ mMaterialManager = m; }
+ PX_FORCE_INLINE PxsMaterialManager* getMaterialManager() const { return mMaterialManager; }
+
+ Cm::RenderOutput getRenderOutput() { return Cm::RenderOutput(mRenderBuffer); }
+};
+
+class PxcNpThreadContext : public PxcThreadCoherentCache<PxcNpThreadContext, PxcNpContext>::EntryBase
+{
+ PX_NOCOPY(PxcNpThreadContext)
+public:
+ PxcNpThreadContext(PxcNpContext* params);
+ ~PxcNpThreadContext();
+
+#if PX_ENABLE_SIM_STATS
+ void clearStats();
+#endif
+
+ PX_FORCE_INLINE void setCreateContactStream(bool to) { mCreateContactStream = to; }
+
+ PX_FORCE_INLINE void addLocalNewTouchCount(PxU32 newTouchCMCount) { mLocalNewTouchCount += newTouchCMCount; }
+ PX_FORCE_INLINE void addLocalLostTouchCount(PxU32 lostTouchCMCount) { mLocalLostTouchCount += lostTouchCMCount; }
+ PX_FORCE_INLINE PxU32 getLocalNewTouchCount() const { return mLocalNewTouchCount; }
+ PX_FORCE_INLINE PxU32 getLocalLostTouchCount() const { return mLocalLostTouchCount; }
+
+ PX_FORCE_INLINE void addLocalFoundPatchCount(PxU32 foundPatchCount) { mLocalFoundPatchCount += foundPatchCount; }
+ PX_FORCE_INLINE void addLocalLostPatchCount(PxU32 lostPatchCount) { mLocalLostPatchCount += lostPatchCount; }
+ PX_FORCE_INLINE PxU32 getLocalFoundPatchCount() const { return mLocalFoundPatchCount; }
+ PX_FORCE_INLINE PxU32 getLocalLostPatchCount() const { return mLocalLostPatchCount; }
+
+ PX_FORCE_INLINE Cm::BitMap& getLocalChangeTouch() { return mLocalChangeTouch; }
+
+ PX_FORCE_INLINE Cm::BitMap& getLocalPatchChangeMap() { return mLocalPatchCountChange; }
+
+ void reset(PxU32 cmCount);
+ // debugging
+ Cm::RenderOutput mRenderOutput;
+
+ // dsequeira: Need to think about this block pool allocation a bit more. Ideally we'd be
+ // taking blocks from a single pool, except that we want to be able to selectively reclaim
+ // blocks if the user needs to defragment, depending on which artifacts they're willing
+ // to tolerate, such that the blocks we don't reclaim are contiguous.
+#if PX_ENABLE_SIM_STATS
+ PxU32 mDiscreteContactPairs [PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT];
+ PxU32 mModifiedContactPairs [PxGeometryType::eGEOMETRY_COUNT][PxGeometryType::eGEOMETRY_COUNT];
+#endif
+ PxcContactBlockStream mContactBlockStream; // constraint block pool
+ PxcNpCacheStreamPair mNpCacheStreamPair; // narrow phase pairwise data cache
+
+ // Everything below here is scratch state. Most of it can even overlap.
+
+ // temporary contact buffer
+ Gu::ContactBuffer mContactBuffer;
+
+ PX_ALIGN(16, Gu::MultiplePersistentContactManifold mTempManifold);
+
+ Gu::NarrowPhaseParams mNarrowPhaseParams;
+
+ // DS: this stuff got moved here from the PxcNpPairContext. As Pierre says:
+ ////////// PT: those members shouldn't be there in the end, it's not necessary
+ Ps::Array<Sc::BodySim*> mBodySimPool;
+ PxsTransformCache* mTransformCache;
+ PxReal* mContactDistance;
+ bool mPCM;
+ bool mContactCache;
+ bool mCreateContactStream; // flag to enforce that contacts are stored persistently per workunit. Used for PVD.
+ bool mCreateAveragePoint; // flag to enforce whether we create average points
+#if PX_ENABLE_SIM_STATS
+ PxU32 mCompressedCacheSize;
+ PxU32 mNbDiscreteContactPairsWithCacheHits;
+ PxU32 mNbDiscreteContactPairsWithContacts;
+#endif
+ PxReal mDt; // AP: still needed for ccd
+ PxU32 mCCDPass;
+ PxU32 mCCDFaceIndex;
+
+ PxU32 mMaxPatches;
+ //PxU32 mTotalContactCount;
+ PxU32 mTotalCompressedCacheSize;
+ //PxU32 mTotalPatchCount;
+
+ PxcDataStreamPool* mContactStreamPool;
+ PxcDataStreamPool* mPatchStreamPool;
+ PxcDataStreamPool* mForceAndIndiceStreamPool; //this stream is used to store the force buffer and triangle index if we are performing mesh/heightfield contact gen
+ PxcDataStreamPool* mConstraintWriteBackStreamPool;
+ PxsMaterialManager* mMaterialManager;
+private:
+ // change touch handling.
+ Cm::BitMap mLocalChangeTouch;
+ Cm::BitMap mLocalPatchCountChange;
+ PxU32 mLocalNewTouchCount;
+ PxU32 mLocalLostTouchCount;
+ PxU32 mLocalFoundPatchCount;
+ PxU32 mLocalLostPatchCount;
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpWorkUnit.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpWorkUnit.h
new file mode 100644
index 00000000..bfc4f0da
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcNpWorkUnit.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 PXC_NPWORKUNIT_H
+#define PXC_NPWORKUNIT_H
+
+#include "PxcNpThreadContext.h"
+#include "PxcMaterialMethodImpl.h"
+#include "PxcNpCache.h"
+
+namespace physx
+{
+
+class PxvContact;
+
+struct PxsRigidCore;
+struct PxsShapeCore;
+
+class PxsMaterialManager;
+
+struct PxcNpWorkUnitFlag
+{
+ enum Enum
+ {
+ eOUTPUT_CONTACTS = 1,
+ eOUTPUT_CONSTRAINTS = 2,
+ eDISABLE_STRONG_FRICTION = 4,
+ eARTICULATION_BODY0 = 8,
+ eARTICULATION_BODY1 = 16,
+ eDYNAMIC_BODY0 = 32,
+ eDYNAMIC_BODY1 = 64,
+ eMODIFIABLE_CONTACT = 128,
+ eFORCE_THRESHOLD = 256,
+ eDETECT_DISCRETE_CONTACT = 512,
+ eHAS_KINEMATIC_ACTOR = 1024,
+ eDISABLE_RESPONSE = 2048,
+ eDETECT_CCD_CONTACTS = 4096
+ };
+};
+
+struct PxcNpWorkUnitStatusFlag
+{
+ enum Enum
+ {
+ eHAS_NO_TOUCH = (1 << 0),
+ eHAS_TOUCH = (1 << 1),
+ //eHAS_SOLVER_CONSTRAINTS = (1 << 2),
+ eREQUEST_CONSTRAINTS = (1 << 3),
+ eHAS_CCD_RETOUCH = (1 << 4), // Marks pairs that are touching at a CCD pass and were touching at discrete collision or at a previous CCD pass already
+ // but we can not tell whether they lost contact in a pass before. We send them as pure eNOTIFY_TOUCH_CCD events to the
+ // contact report callback if requested.
+ eDIRTY_MANAGER = (1 << 5),
+ eREFRESHED_WITH_TOUCH = (1 << 6),
+ eTOUCH_KNOWN = eHAS_NO_TOUCH | eHAS_TOUCH // The touch status is known (if narrowphase never ran for a pair then no flag will be set)
+ };
+};
+
+/*
+ * A struct to record the number of work units a particular constraint pointer references.
+ * This is created at the beginning of the constriant data and is used to bypass constraint preparation when the
+ * bodies are not moving a lot. In this case, we can recycle the constraints and save ourselves some cycles.
+*/
+struct PxcNpWorkUnit;
+struct PxcNpWorkUnitBatch
+{
+ PxcNpWorkUnit* mUnits[4];
+ PxU32 mSize;
+};
+
+struct PxcNpWorkUnit
+{
+
+ const PxsRigidCore* rigidCore0; // INPUT //4 //8
+ const PxsRigidCore* rigidCore1; // INPUT //8 //16
+
+ const PxsShapeCore* shapeCore0; // INPUT //12 //24
+ const PxsShapeCore* shapeCore1; // INPUT //16 //32
+
+ PxU8* ccdContacts; // OUTPUT //20 //40
+
+ PxU8* frictionDataPtr; // INOUT //24 //48
+
+ PxU16 flags; // INPUT //26 //50
+ PxU8 frictionPatchCount; // INOUT //27 //51
+ PxU8 statusFlags; // OUTPUT (see PxcNpWorkUnitStatusFlag) //28 //52
+
+ PxU8 dominance0; // INPUT //29 //53
+ PxU8 dominance1; // INPUT //30 //54
+ PxU8 geomType0; // INPUT //31 //55
+ PxU8 geomType1; // INPUT //32 //56
+
+ PxU32 index; // INPUT //36 //60
+
+ PxReal restDistance; // INPUT //40 //64
+
+ PxU32 mTransformCache0; // //44 //68
+ PxU32 mTransformCache1; // //48 //72
+
+ PxU32 mEdgeIndex; //inout the island gen edge index //52 //76
+ PxU32 mNpIndex; //INPUT //56 //80
+
+};
+
+//#if !defined(PX_P64)
+//PX_COMPILE_TIME_ASSERT(0 == (sizeof(PxcNpWorkUnit) & 0x0f));
+//#endif
+
+PX_FORCE_INLINE void PxcNpWorkUnitClearContactState(PxcNpWorkUnit& n)
+{
+ n.ccdContacts = NULL;
+}
+
+
+PX_FORCE_INLINE void PxcNpWorkUnitClearCachedState(PxcNpWorkUnit& n)
+{
+ n.frictionDataPtr = 0;
+ n.frictionPatchCount = 0;
+ n.ccdContacts = NULL;
+}
+
+PX_FORCE_INLINE void PxcNpWorkUnitClearFrictionCachedState(PxcNpWorkUnit& n)
+{
+ n.frictionDataPtr = 0;
+ n.frictionPatchCount = 0;
+ n.ccdContacts = NULL;
+}
+
+#if !defined(PX_P64)
+//PX_COMPILE_TIME_ASSERT(sizeof(PxcNpWorkUnit)==128);
+#endif
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcRigidBody.h b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcRigidBody.h
new file mode 100644
index 00000000..03870e4f
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/pipeline/PxcRigidBody.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 PXC_RIGIDBODY_H
+#define PXC_RIGIDBODY_H
+
+#include "foundation/PxVec3.h"
+#include "foundation/PxTransform.h"
+#include "PxvDynamics.h"
+#include "CmSpatialVector.h"
+
+namespace physx
+{
+
+class PxsContactManager;
+struct PxsCCDPair;
+struct PxsCCDBody;
+
+#define PX_INTERNAL_LOCK_FLAG_START 7
+
+PX_ALIGN_PREFIX(16)
+class PxcRigidBody
+{
+public:
+
+ enum PxcRigidBodyFlag
+ {
+ eFROZEN = 1 << 0, //This flag indicates that the stabilization is enabled and the body is
+ //"frozen". By "frozen", we mean that the body's transform is unchanged
+ //from the previous frame. This permits various optimizations.
+ eFREEZE_THIS_FRAME = 1 << 1,
+ eUNFREEZE_THIS_FRAME = 1 << 2,
+ eACTIVATE_THIS_FRAME = 1 << 3,
+ eDEACTIVATE_THIS_FRAME = 1 << 4,
+ eDISABLE_GRAVITY = 1 << 5,
+ eSPECULATIVE_CCD = 1 << 6,
+ //KS - copied here for GPU simulation to avoid needing to pass another set of flags around.
+ eLOCK_LINEAR_X = 1 << (PX_INTERNAL_LOCK_FLAG_START),
+ eLOCK_LINEAR_Y = 1 << (PX_INTERNAL_LOCK_FLAG_START + 1),
+ eLOCK_LINEAR_Z = 1 << (PX_INTERNAL_LOCK_FLAG_START + 2),
+ eLOCK_ANGULAR_X = 1 << (PX_INTERNAL_LOCK_FLAG_START + 3),
+ eLOCK_ANGULAR_Y = 1 << (PX_INTERNAL_LOCK_FLAG_START + 4),
+ eLOCK_ANGULAR_Z = 1 << (PX_INTERNAL_LOCK_FLAG_START + 5)
+
+ };
+
+ PX_FORCE_INLINE PxcRigidBody(PxsBodyCore* core)
+ : mLastTransform(core->body2World),
+ mCCD(NULL),
+ mCore(core)
+ {
+ }
+
+ void adjustCCDLastTransform();
+
+protected:
+
+ ~PxcRigidBody()
+ {
+ }
+
+public:
+
+ PxTransform mLastTransform; //28 (28)
+
+ PxU16 mInternalFlags; //30 (30)
+ PxU16 solverIterationCounts; //32 (32)
+
+ PxsCCDBody* mCCD; //36 (40) // only valid during CCD
+
+ PxsBodyCore* mCore; //40 (48)
+
+#if !PX_P64_FAMILY
+ PxU32 alignmentPad[2]; //48 (48)
+#endif
+
+ PxVec3 sleepLinVelAcc; //60 (60)
+ PxReal freezeCount; //64 (64)
+
+ PxVec3 sleepAngVelAcc; //76 (76)
+ PxReal accelScale; //80 (80)
+
+
+}
+PX_ALIGN_SUFFIX(16);
+PX_COMPILE_TIME_ASSERT(0 == (sizeof(PxcRigidBody) & 0x0f));
+
+}
+
+#endif //PXC_RIGIDBODY_H
diff --git a/PhysX_3.4/Source/LowLevel/common/include/utils/PxcScratchAllocator.h b/PhysX_3.4/Source/LowLevel/common/include/utils/PxcScratchAllocator.h
new file mode 100644
index 00000000..aaf43626
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/utils/PxcScratchAllocator.h
@@ -0,0 +1,138 @@
+// 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 PXC_SCRATCHALLOCATOR_H
+#define PXC_SCRATCHALLOCATOR_H
+
+#include "foundation/PxAssert.h"
+#include "PxvConfig.h"
+#include "PsMutex.h"
+#include "PsArray.h"
+#include "PsAllocator.h"
+
+namespace physx
+{
+class PxcScratchAllocator
+{
+ PX_NOCOPY(PxcScratchAllocator)
+public:
+ PxcScratchAllocator() : mStack(PX_DEBUG_EXP("PxcScratchAllocator")), mStart(NULL), mSize(0)
+ {
+ mStack.reserve(64);
+ mStack.pushBack(0);
+ }
+
+ void setBlock(void* addr, PxU32 size)
+ {
+ // if the stack is not empty then some scratch memory was not freed on the previous frame. That's
+ // likely indicative of a problem, because when the scratch block is too small the memory will have
+ // come from the heap
+
+ PX_ASSERT(mStack.size()==1);
+ mStack.popBack();
+
+ mStart = reinterpret_cast<PxU8*>(addr);
+ mSize = size;
+ mStack.pushBack(mStart + size);
+ }
+
+ void* allocAll(PxU32& size)
+ {
+ Ps::Mutex::ScopedLock lock(mLock);
+ PX_ASSERT(mStack.size()>0);
+ size = PxU32(mStack.back()-mStart);
+
+ if(size==0)
+ return NULL;
+
+ mStack.pushBack(mStart);
+ return mStart;
+ }
+
+
+ void* alloc(PxU32 requestedSize, bool fallBackToHeap = false)
+ {
+ requestedSize = (requestedSize+15)&~15;
+
+ Ps::Mutex::ScopedLock lock(mLock);
+ PX_ASSERT(mStack.size()>=1);
+
+ PxU8* top = mStack.back();
+
+ if(top - mStart >= ptrdiff_t(requestedSize))
+ {
+ PxU8* addr = top - requestedSize;
+ mStack.pushBack(addr);
+ return addr;
+ }
+
+ if(!fallBackToHeap)
+ return NULL;
+
+ return PX_ALLOC(requestedSize, "Scratch Block Fallback");
+ }
+
+ void free(void* addr)
+ {
+ PX_ASSERT(addr!=NULL);
+ if(!isScratchAddr(addr))
+ {
+ PX_FREE(addr);
+ return;
+ }
+
+ Ps::Mutex::ScopedLock lock(mLock);
+ PX_ASSERT(mStack.size()>1);
+
+ PxU32 i=mStack.size()-1;
+ while(mStack[i]<addr)
+ i--;
+
+ PX_ASSERT(mStack[i]==addr);
+ mStack.remove(i);
+ }
+
+
+ bool isScratchAddr(void* addr) const
+ {
+ PxU8* a = reinterpret_cast<PxU8*>(addr);
+ return a>= mStart && a<mStart+mSize;
+ }
+
+private:
+ Ps::Mutex mLock;
+ Ps::Array<PxU8*> mStack;
+ PxU8* mStart;
+ PxU32 mSize;
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/include/utils/PxcThreadCoherentCache.h b/PhysX_3.4/Source/LowLevel/common/include/utils/PxcThreadCoherentCache.h
new file mode 100644
index 00000000..ed8a37a5
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/include/utils/PxcThreadCoherentCache.h
@@ -0,0 +1,150 @@
+// 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 PXC_THREADCOHERENTCACHE_H
+#define PXC_THREADCOHERENTCACHE_H
+
+#include "PsMutex.h"
+#include "PsAllocator.h"
+#include "PsSList.h"
+
+namespace physx
+{
+
+class PxsContext;
+/*!
+Controls a pool of large objects which must be thread safe.
+Tries to return the object most recently used by the thread(for better cache coherancy).
+Assumes the object has a default contructor.
+
+(Note the semantics are different to a pool because we dont want to construct/destroy each time
+an object is requested, which may be expensive).
+
+TODO: add thread coherancy.
+*/
+template<class T, class Params>
+class PxcThreadCoherentCache : public Ps::AlignedAllocator<16, Ps::ReflectionAllocator<T> >
+{
+ typedef Ps::AlignedAllocator<16, Ps::ReflectionAllocator<T> > Allocator;
+ PX_NOCOPY(PxcThreadCoherentCache)
+public:
+
+ typedef Ps::SListEntry EntryBase;
+
+ PX_INLINE PxcThreadCoherentCache(Params* params, const Allocator& alloc = Allocator()) : Allocator(alloc), mParams(params)
+ {
+ }
+
+ PX_INLINE ~PxcThreadCoherentCache()
+ {
+ T* np = static_cast<T*>(root.pop());
+
+ while(np!=NULL)
+ {
+ np->~T();
+ Allocator::deallocate(np);
+ np = static_cast<T*>(root.pop());
+ }
+ }
+
+ PX_INLINE T* get()
+ {
+ T* rv = static_cast<T*>(root.pop());
+ if(rv==NULL)
+ {
+ rv = reinterpret_cast<T*>(Allocator::allocate(sizeof(T), __FILE__, __LINE__));
+ new (rv) T(mParams);
+ }
+
+ return rv;
+ }
+
+ PX_INLINE void put(T* item)
+ {
+ root.push(*item);
+ }
+
+
+private:
+ Ps::SList root;
+ Params* mParams;
+
+ template<class T2, class P2>
+ friend class PxcThreadCoherentCacheIterator;
+};
+
+/*!
+Used to iterate over all objects controlled by the cache.
+
+Note: The iterator flushes the cache(extracts all items on construction and adds them back on
+destruction so we can iterate the list in a safe manner).
+*/
+template<class T, class Params>
+class PxcThreadCoherentCacheIterator
+{
+public:
+ PxcThreadCoherentCacheIterator(PxcThreadCoherentCache<T, Params>& cache) : mCache(cache)
+ {
+ mNext = cache.root.flush();
+ mFirst = mNext;
+ }
+ ~PxcThreadCoherentCacheIterator()
+ {
+ Ps::SListEntry* np = mFirst;
+ while(np != NULL)
+ {
+ Ps::SListEntry* npNext = np->next();
+ mCache.root.push(*np);
+ np = npNext;
+ }
+ }
+
+ PX_INLINE T* getNext()
+ {
+ if(mNext == NULL)
+ return NULL;
+
+ T* rv = static_cast<T*>(mNext);
+ mNext = mNext->next();
+
+ return rv;
+ }
+private:
+
+ PxcThreadCoherentCacheIterator<T, Params>& operator=(const PxcThreadCoherentCacheIterator<T, Params>&);
+ PxcThreadCoherentCache<T, Params> &mCache;
+ Ps::SListEntry* mNext;
+ Ps::SListEntry* mFirst;
+
+};
+
+}
+
+#endif
diff --git a/PhysX_3.4/Source/LowLevel/common/src/collision/PxcContact.cpp b/PhysX_3.4/Source/LowLevel/common/src/collision/PxcContact.cpp
new file mode 100644
index 00000000..c37b3af7
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/collision/PxcContact.cpp
@@ -0,0 +1,289 @@
+// 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 "PxcContactMethodImpl.h"
+
+namespace physx
+{
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////
+//non-pcm sphere function
+bool PxcContactSphereSphere(GU_CONTACT_METHOD_ARGS)
+{
+ return contactSphereSphere(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactSphereCapsule(GU_CONTACT_METHOD_ARGS)
+{
+ return contactSphereCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactSphereBox(GU_CONTACT_METHOD_ARGS)
+{
+ return contactSphereBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactSpherePlane(GU_CONTACT_METHOD_ARGS)
+{
+ return contactSpherePlane(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactSphereConvex(GU_CONTACT_METHOD_ARGS)
+{
+ return contactCapsuleConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactSphereHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return contactSphereHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactSphereMesh(GU_CONTACT_METHOD_ARGS)
+{
+ return contactSphereMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+//non-pcm plane functions
+bool PxcContactPlaneBox(GU_CONTACT_METHOD_ARGS)
+{
+ return contactPlaneBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactPlaneCapsule(GU_CONTACT_METHOD_ARGS)
+{
+ return contactPlaneCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactPlaneConvex(GU_CONTACT_METHOD_ARGS)
+{
+ return contactPlaneConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+//non-pcm capsule funtions
+bool PxcContactCapsuleCapsule(GU_CONTACT_METHOD_ARGS)
+{
+ return contactCapsuleCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactCapsuleBox(GU_CONTACT_METHOD_ARGS)
+{
+ return contactCapsuleBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactCapsuleConvex(GU_CONTACT_METHOD_ARGS)
+{
+ return contactCapsuleConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactCapsuleHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return contactCapsuleHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactCapsuleMesh(GU_CONTACT_METHOD_ARGS)
+{
+ return contactCapsuleMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+//non-pcm box functions
+bool PxcContactBoxBox(GU_CONTACT_METHOD_ARGS)
+{
+ return contactBoxBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactBoxConvex(GU_CONTACT_METHOD_ARGS)
+{
+ return contactBoxConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactBoxHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return contactBoxHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactBoxMesh(GU_CONTACT_METHOD_ARGS)
+{
+ return contactBoxMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+//non-pcm convex functions
+bool PxcContactConvexConvex(GU_CONTACT_METHOD_ARGS)
+{
+ return contactConvexConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactConvexHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return contactConvexHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcContactConvexMesh(GU_CONTACT_METHOD_ARGS)
+{
+ return contactConvexMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//legacy height field functions
+bool PxcLegacyContactSphereHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return legacyContactSphereHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcLegacyContactCapsuleHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return legacyContactCapsuleHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcLegacyContactBoxHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return legacyContactBoxHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcLegacyContactConvexHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return legacyContactConvexHeightfield(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+//pcm sphere functions
+bool PxcPCMContactSphereSphere(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactSphereSphere(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactSpherePlane(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactSpherePlane(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactSphereCapsule(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactSphereCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactSphereBox(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactSphereBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactSphereConvex(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactSphereConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactSphereHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactSphereHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactSphereMesh(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactSphereMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+//pcm plane functions
+bool PxcPCMContactPlaneBox(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactPlaneBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactPlaneCapsule(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactPlaneCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactPlaneConvex(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactPlaneConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+//pcm capsule functions
+bool PxcPCMContactCapsuleCapsule(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactCapsuleCapsule(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactCapsuleBox(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactCapsuleBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactCapsuleConvex(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactCapsuleConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactCapsuleHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactCapsuleHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactCapsuleMesh(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactCapsuleMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+//pcm box functions
+bool PxcPCMContactBoxBox(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactBoxBox(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactBoxConvex(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactBoxConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactBoxHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactBoxHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactBoxMesh(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactBoxMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+//pcm convex functions
+bool PxcPCMContactConvexConvex(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactConvexConvex(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactConvexHeightField(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactConvexHeightField(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+bool PxcPCMContactConvexMesh(GU_CONTACT_METHOD_ARGS)
+{
+ return pcmContactConvexMesh(shape0, shape1, transform0, transform1, params, cache, contactBuffer, renderOutput);
+}
+
+}
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactCache.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactCache.cpp
new file mode 100644
index 00000000..26ea90a5
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactCache.cpp
@@ -0,0 +1,393 @@
+// 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 "PxcContactCache.h"
+#include "PxsContactManager.h"
+#include "PsUtilities.h"
+#include "PxcNpCache.h"
+
+using namespace physx;
+using namespace Gu;
+
+//#define ENABLE_CONTACT_CACHE_STATS
+
+#ifdef ENABLE_CONTACT_CACHE_STATS
+ static PxU32 gNbCalls;
+ static PxU32 gNbHits;
+#endif
+
+void PxcClearContactCacheStats()
+{
+#ifdef ENABLE_CONTACT_CACHE_STATS
+ gNbCalls = 0;
+ gNbHits = 0;
+#endif
+}
+
+void PxcDisplayContactCacheStats()
+{
+#ifdef ENABLE_CONTACT_CACHE_STATS
+ pxPrintf("%d|%d (%f)\n", gNbHits, gNbCalls, gNbCalls ? float(gNbHits)/float(gNbCalls) : 0.0f);
+#endif
+}
+
+namespace physx
+{
+ const bool g_CanUseContactCache[][PxGeometryType::eGEOMETRY_COUNT] =
+ {
+ //PxGeometryType::eSPHERE
+ {
+ false, //PxcContactSphereSphere
+ false, //PxcContactSpherePlane
+ true, //PxcContactSphereCapsule
+ false, //PxcContactSphereBox
+ true, //PxcContactSphereConvex
+ true, //PxcContactSphereMesh
+ true, //PxcContactSphereHeightField
+ },
+
+ //PxGeometryType::ePLANE
+ {
+ false, //-
+ false, //PxcInvalidContactPair
+ true, //PxcContactPlaneCapsule
+ true, //PxcContactPlaneBox
+ true, //PxcContactPlaneConvex
+ false, //PxcInvalidContactPair
+ false, //PxcInvalidContactPair
+ },
+
+ //PxGeometryType::eCAPSULE
+ {
+ false, //-
+ false, //-
+ true, //PxcContactCapsuleCapsule
+ true, //PxcContactCapsuleBox
+ true, //PxcContactCapsuleConvex
+ true, //PxcContactCapsuleMesh
+ true, //PxcContactCapsuleHeightField
+ },
+
+ //PxGeometryType::eBOX
+ {
+ false, //-
+ false, //-
+ false, //-
+ true, //PxcContactBoxBox
+ true, //PxcContactBoxConvex
+ true, //PxcContactBoxMesh
+ true, //PxcContactBoxHeightField
+ },
+
+ //PxGeometryType::eCONVEXMESH
+ {
+ false, //-
+ false, //-
+ false, //-
+ false, //-
+ true, //PxcContactConvexConvex
+ true, //PxcContactConvexMesh2
+ true, //PxcContactConvexHeightField
+ },
+
+ //PxGeometryType::eTRIANGLEMESH
+ {
+ false, //-
+ false, //-
+ false, //-
+ false, //-
+ false, //-
+ false, //PxcInvalidContactPair
+ false, //PxcInvalidContactPair
+ },
+
+ //PxGeometryType::eHEIGHTFIELD
+ {
+ false, //-
+ false, //-
+ false, //-
+ false, //-
+ false, //-
+ false, //-
+ false, //PxcInvalidContactPair
+ },
+ };
+}
+
+static PX_FORCE_INLINE void updateContact( Gu::ContactPoint& dst, const PxcLocalContactsCache& contactsData,
+ const Cm::Matrix34& world0, const Cm::Matrix34& world1,
+ const PxVec3& point, const PxVec3& normal, float separation)
+{
+ const PxVec3 tmp0 = contactsData.mTransform0.transformInv(point);
+ const PxVec3 worldpt0 = world0.transform(tmp0);
+
+ const PxVec3 tmp1 = contactsData.mTransform1.transformInv(point);
+ const PxVec3 worldpt1 = world1.transform(tmp1);
+
+ const PxVec3 motion = worldpt0 - worldpt1;
+ dst.normal = normal;
+ dst.point = (worldpt0 + worldpt1)*0.5f;
+ //dst.point = point;
+ dst.separation = separation + motion.dot(normal);
+}
+
+static PX_FORCE_INLINE void prefetchData128(PxU8* PX_RESTRICT ptr, PxU32 size)
+{
+ // PT: always prefetch the cache line containing our address (which unfortunately won't be aligned to 128 most of the time)
+ Ps::prefetchLine(ptr, 0);
+ // PT: compute start offset of our data within its cache line
+ const PxU32 startOffset = PxU32(size_t(ptr)&127);
+ // PT: prefetch next cache line if needed
+ if(startOffset+size>128)
+ Ps::prefetchLine(ptr+128, 0);
+}
+
+static PX_FORCE_INLINE PxU8* outputToCache(PxU8* PX_RESTRICT bytes, const PxVec3& v)
+{
+ *reinterpret_cast<PxVec3*>(bytes) = v;
+ return bytes + sizeof(PxVec3);
+}
+
+static PX_FORCE_INLINE PxU8* outputToCache(PxU8* PX_RESTRICT bytes, PxReal v)
+{
+ *reinterpret_cast<PxReal*>(bytes) = v;
+ return bytes + sizeof(PxReal);
+}
+
+static PX_FORCE_INLINE PxU8* outputToCache(PxU8* PX_RESTRICT bytes, PxU32 v)
+{
+ *reinterpret_cast<PxU32*>(bytes) = v;
+ return bytes + sizeof(PxU32);
+}
+
+//PxU32 gContactCache_NbCalls = 0;
+//PxU32 gContactCache_NbHits = 0;
+
+static PX_FORCE_INLINE PxReal maxComponentDeltaPos(const PxTransform& t0, const PxTransform& t1)
+{
+ PxReal delta = PxAbs(t0.p.x - t1.p.x);
+ delta = PxMax(delta, PxAbs(t0.p.y - t1.p.y));
+ delta = PxMax(delta, PxAbs(t0.p.z - t1.p.z));
+ return delta;
+}
+
+static PX_FORCE_INLINE PxReal maxComponentDeltaRot(const PxTransform& t0, const PxTransform& t1)
+{
+ PxReal delta = PxAbs(t0.q.x - t1.q.x);
+ delta = PxMax(delta, PxAbs(t0.q.y - t1.q.y));
+ delta = PxMax(delta, PxAbs(t0.q.z - t1.q.z));
+ delta = PxMax(delta, PxAbs(t0.q.w - t1.q.w));
+ return delta;
+}
+
+bool physx::PxcCacheLocalContacts( PxcNpThreadContext& context, Gu::Cache& pairContactCache,
+ const PxTransform& tm0, const PxTransform& tm1,
+ const PxcContactMethod conMethod,
+ const Gu::GeometryUnion& shape0, const Gu::GeometryUnion& shape1)
+{
+ const Gu::NarrowPhaseParams& params = context.mNarrowPhaseParams;
+
+// gContactCache_NbCalls++;
+
+ if(pairContactCache.mCachedData)
+ prefetchData128(pairContactCache.mCachedData, pairContactCache.mCachedSize);
+
+ ContactBuffer& contactBuffer = context.mContactBuffer;
+ contactBuffer.reset();
+
+ PxcLocalContactsCache contactsData;
+ PxU32 nbCachedBytes;
+ const PxU8* cachedBytes = PxcNpCacheRead2(pairContactCache, contactsData, nbCachedBytes);
+
+ pairContactCache.mCachedData = NULL;
+ pairContactCache.mCachedSize = 0;
+
+#ifdef ENABLE_CONTACT_CACHE_STATS
+ gNbCalls++;
+#endif
+
+ const PxU32 payloadSize = (sizeof(PxcLocalContactsCache)+3)&~3;
+
+ if(cachedBytes)
+ {
+ // PT: we used to store the relative TM but it's better to save memory and recompute it
+ const PxTransform t0to1 = tm1.transformInv(tm0);
+ const PxTransform relTM = contactsData.mTransform1.transformInv(contactsData.mTransform0);
+
+ const PxReal epsilon = 0.01f;
+ if( maxComponentDeltaPos(t0to1, relTM)<epsilon*params.mToleranceLength
+ && maxComponentDeltaRot(t0to1, relTM)<epsilon)
+ {
+// gContactCache_NbHits++;
+ const PxU32 nbContacts = contactsData.mNbCachedContacts;
+
+ PxU8* ls = PxcNpCacheWriteInitiate(context.mNpCacheStreamPair, pairContactCache, contactsData, nbCachedBytes);
+ prefetchData128(ls, (payloadSize + 4 + nbCachedBytes + 0xF)&~0xF);
+
+ contactBuffer.count = nbContacts;
+ if(nbContacts)
+ {
+ Gu::ContactPoint* PX_RESTRICT dst = contactBuffer.contacts;
+
+ const Cm::Matrix34 world1(tm1);
+ const Cm::Matrix34 world0(tm0);
+
+ const bool sameNormal = contactsData.mSameNormal;
+
+ const PxU8* contacts = reinterpret_cast<const PxU8*>(cachedBytes);
+ const PxVec3* normal0 = NULL;
+ for(PxU32 i=0;i<nbContacts;i++)
+ {
+ if(i!=nbContacts-1)
+ Ps::prefetchLine(contacts, 128);
+
+ const PxVec3* cachedNormal;
+ if(!i || !sameNormal)
+ {
+ cachedNormal = reinterpret_cast<const PxVec3*>(contacts); contacts += sizeof(PxVec3);
+ normal0 = cachedNormal;
+ }
+ else
+ {
+ cachedNormal = normal0;
+ }
+
+ const PxVec3* cachedPoint = reinterpret_cast<const PxVec3*>(contacts); contacts += sizeof(PxVec3);
+ const PxReal* cachedPD = reinterpret_cast<const PxReal*>(contacts); contacts += sizeof(PxReal);
+
+ updateContact(*dst, contactsData, world0, world1, *cachedPoint, *cachedNormal, *cachedPD);
+
+ if(contactsData.mUseFaceIndices)
+ {
+ const PxU32* cachedIndex1 = reinterpret_cast<const PxU32*>(contacts); contacts += sizeof(PxU32);
+
+ dst->internalFaceIndex1 = *cachedIndex1;
+ }
+ else
+ {
+ dst->internalFaceIndex1 = PXC_CONTACT_NO_FACE_INDEX;
+ }
+ dst++;
+ }
+ }
+ if(ls)
+ PxcNpCacheWriteFinalize(ls, contactsData, nbCachedBytes, cachedBytes);
+#ifdef ENABLE_CONTACT_CACHE_STATS
+ gNbHits++;
+#endif
+ return true;
+ }
+ else
+ {
+ // PT: if we reach this point we cached the contacts but we couldn't use them next frame
+ // => waste of time and memory
+ }
+ }
+
+ conMethod(shape0, shape1, tm0, tm1, params, pairContactCache, context.mContactBuffer, &context.mRenderOutput);
+
+ //if(contactBuffer.count)
+ {
+ contactsData.mTransform0 = tm0;
+ contactsData.mTransform1 = tm1;
+
+ PxU32 nbBytes = 0;
+ const PxU8* bytes = NULL;
+ const PxU32 count = contactBuffer.count;
+ if(count)
+ {
+ const bool useFaceIndices = contactBuffer.contacts[0].internalFaceIndex1!=PXC_CONTACT_NO_FACE_INDEX;
+ contactsData.mNbCachedContacts = Ps::to16(count);
+ contactsData.mUseFaceIndices = useFaceIndices;
+
+ const Gu::ContactPoint* PX_RESTRICT srcContacts = contactBuffer.contacts;
+ // PT: this loop should not be here. We should output the contacts directly compressed, as we used to.
+ bool sameNormal = true;
+ {
+ const PxVec3 normal0 = srcContacts->normal;
+ for(PxU32 i=1;i<count;i++)
+ {
+ if(srcContacts[i].normal!=normal0)
+ {
+ sameNormal = false;
+ break;
+ }
+ }
+ }
+ contactsData.mSameNormal = sameNormal;
+
+ if(!sameNormal)
+ {
+ const PxU32 sizeof_CachedContactPoint = sizeof(PxVec3) + sizeof(PxVec3) + sizeof(PxReal);
+ const PxU32 sizeof_CachedContactPointAndFaceIndices = sizeof_CachedContactPoint + sizeof(PxU32);
+ const PxU32 sizeOfItem = useFaceIndices ? sizeof_CachedContactPointAndFaceIndices : sizeof_CachedContactPoint;
+ nbBytes = count * sizeOfItem;
+ }
+ else
+ {
+ const PxU32 sizeof_CachedContactPoint = sizeof(PxVec3) + sizeof(PxReal);
+ const PxU32 sizeof_CachedContactPointAndFaceIndices = sizeof_CachedContactPoint + sizeof(PxU32);
+ const PxU32 sizeOfItem = useFaceIndices ? sizeof_CachedContactPointAndFaceIndices : sizeof_CachedContactPoint;
+ nbBytes = sizeof(PxVec3) + count * sizeOfItem;
+ }
+ PxU8* ls = PxcNpCacheWriteInitiate(context.mNpCacheStreamPair, pairContactCache, contactsData, nbBytes);
+ if(ls)
+ {
+ *reinterpret_cast<PxcLocalContactsCache*>(ls) = contactsData;
+ *reinterpret_cast<PxU32*>(ls+payloadSize) = nbBytes;
+ bytes = ls+payloadSize+sizeof(PxU32);
+ PxU8* dest = const_cast<PxU8*>(bytes);
+ for(PxU32 i=0;i<count;i++)
+ {
+ if(!i || !sameNormal)
+ dest = outputToCache(dest, srcContacts[i].normal);
+ dest = outputToCache(dest, srcContacts[i].point);
+ dest = outputToCache(dest, srcContacts[i].separation);
+ if(useFaceIndices)
+ {
+ dest = outputToCache(dest, srcContacts[i].internalFaceIndex1);
+ }
+ }
+ PX_ASSERT(size_t(dest) - size_t(bytes)==nbBytes);
+ }
+ else
+ {
+ contactsData.mNbCachedContacts = 0;
+ PxcNpCacheWrite(context.mNpCacheStreamPair, pairContactCache, contactsData, 0, bytes);
+ }
+ }
+ else
+ {
+ contactsData.mNbCachedContacts = 0;
+ contactsData.mUseFaceIndices = false;
+ PxcNpCacheWrite(context.mNpCacheStreamPair, pairContactCache, contactsData, nbBytes, bytes);
+ }
+ }
+ return false;
+}
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactMethodImpl.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactMethodImpl.cpp
new file mode 100644
index 00000000..53eb5d88
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactMethodImpl.cpp
@@ -0,0 +1,279 @@
+// 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 "PxGeometry.h"
+#include "PxcContactMethodImpl.h"
+
+namespace physx
+{
+
+// PT: those prototypes shouldn't be public. Keep them here.
+
+// Sphere - other
+bool PxcContactSphereSphere (GU_CONTACT_METHOD_ARGS);
+bool PxcContactSpherePlane (GU_CONTACT_METHOD_ARGS);
+bool PxcContactSphereCapsule (GU_CONTACT_METHOD_ARGS);
+bool PxcContactSphereBox (GU_CONTACT_METHOD_ARGS);
+bool PxcContactSphereConvex (GU_CONTACT_METHOD_ARGS);
+bool PxcContactSphereMesh (GU_CONTACT_METHOD_ARGS);
+bool PxcContactSphereHeightField (GU_CONTACT_METHOD_ARGS);
+
+// Plane - other
+bool PxcContactPlaneCapsule (GU_CONTACT_METHOD_ARGS);
+bool PxcContactPlaneBox (GU_CONTACT_METHOD_ARGS);
+bool PxcContactPlaneConvex (GU_CONTACT_METHOD_ARGS);
+
+// Capsule - other
+bool PxcContactCapsuleCapsule (GU_CONTACT_METHOD_ARGS);
+bool PxcContactCapsuleBox (GU_CONTACT_METHOD_ARGS);
+bool PxcContactCapsuleConvex (GU_CONTACT_METHOD_ARGS);
+bool PxcContactCapsuleMesh (GU_CONTACT_METHOD_ARGS);
+bool PxcContactCapsuleHeightField (GU_CONTACT_METHOD_ARGS);
+
+// Box - other
+bool PxcContactBoxBox (GU_CONTACT_METHOD_ARGS);
+bool PxcContactBoxConvex (GU_CONTACT_METHOD_ARGS);
+bool PxcContactBoxMesh (GU_CONTACT_METHOD_ARGS);
+bool PxcContactBoxHeightField (GU_CONTACT_METHOD_ARGS);
+
+// Convex - other
+bool PxcContactConvexConvex (GU_CONTACT_METHOD_ARGS);
+bool PxcContactConvexMesh (GU_CONTACT_METHOD_ARGS);
+bool PxcContactConvexHeightField (GU_CONTACT_METHOD_ARGS);
+
+
+static bool PxcInvalidContactPair (CONTACT_METHOD_ARGS_UNUSED)
+{
+ return false;
+}
+
+//PCM Sphere - other
+bool PxcPCMContactSphereSphere (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactSpherePlane (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactSphereBox (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactSphereCapsule (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactSphereConvex (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactSphereMesh (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactSphereHeightField (GU_CONTACT_METHOD_ARGS);
+
+// Plane - other
+bool PxcPCMContactPlaneCapsule (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactPlaneBox (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactPlaneConvex (GU_CONTACT_METHOD_ARGS);
+
+//PCM Capsule - other
+bool PxcPCMContactCapsuleCapsule (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactCapsuleBox (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactCapsuleConvex (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactCapsuleMesh (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactCapsuleHeightField (GU_CONTACT_METHOD_ARGS);
+
+//PCM Box - other
+bool PxcPCMContactBoxBox (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactBoxConvex (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactBoxMesh (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactBoxHeightField (GU_CONTACT_METHOD_ARGS);
+
+//PCM Convex
+bool PxcPCMContactConvexConvex (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactConvexMesh (GU_CONTACT_METHOD_ARGS);
+bool PxcPCMContactConvexHeightField (GU_CONTACT_METHOD_ARGS);
+
+
+#define DYNAMIC_CONTACT_REGISTRATION(x) PxcInvalidContactPair
+//#define DYNAMIC_CONTACT_REGISTRATION(x) x
+
+//Table of contact methods for different shape-type combinations
+PxcContactMethod g_ContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT] =
+{
+ //PxGeometryType::eSPHERE
+ {
+ PxcContactSphereSphere, //PxGeometryType::eSPHERE
+ PxcContactSpherePlane, //PxGeometryType::ePLANE
+ PxcContactSphereCapsule, //PxGeometryType::eCAPSULE
+ PxcContactSphereBox, //PxGeometryType::eBOX
+ PxcContactSphereConvex, //PxGeometryType::eCONVEXMESH
+ PxcContactSphereMesh, //PxGeometryType::eTRIANGLEMESH
+ DYNAMIC_CONTACT_REGISTRATION(PxcContactSphereHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+
+ },
+
+ //PxGeometryType::ePLANE
+ {
+ 0, //PxGeometryType::eSPHERE
+ PxcInvalidContactPair, //PxGeometryType::ePLANE
+ PxcContactPlaneCapsule, //PxGeometryType::eCAPSULE
+ PxcContactPlaneBox, //PxGeometryType::eBOX
+ PxcContactPlaneConvex, //PxGeometryType::eCONVEXMESH
+ PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
+ PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eCAPSULE
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ PxcContactCapsuleCapsule, //PxGeometryType::eCAPSULE
+ PxcContactCapsuleBox, //PxGeometryType::eBOX
+ PxcContactCapsuleConvex, //PxGeometryType::eCONVEXMESH
+ PxcContactCapsuleMesh, //PxGeometryType::eTRIANGLEMESH
+ DYNAMIC_CONTACT_REGISTRATION(PxcContactCapsuleHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+ },
+
+ //PxGeometryType::eBOX
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ PxcContactBoxBox, //PxGeometryType::eBOX
+ PxcContactBoxConvex, //PxGeometryType::eCONVEXMESH
+ PxcContactBoxMesh, //PxGeometryType::eTRIANGLEMESH
+ DYNAMIC_CONTACT_REGISTRATION(PxcContactBoxHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+ },
+
+ //PxGeometryType::eCONVEXMESH
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ PxcContactConvexConvex, //PxGeometryType::eCONVEXMESH
+ PxcContactConvexMesh, //PxGeometryType::eTRIANGLEMESH
+ DYNAMIC_CONTACT_REGISTRATION(PxcContactConvexHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+ },
+
+ //PxGeometryType::eTRIANGLEMESH
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ 0, //PxGeometryType::eCONVEXMESH
+ PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
+ PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eHEIGHTFIELD
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ 0, //PxGeometryType::eCONVEXMESH
+ 0, //PxGeometryType::eTRIANGLEMESH
+ PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
+ },
+};
+
+
+//#if PERSISTENT_CONTACT_MANIFOLD
+//Table of contact methods for different shape-type combinations
+PxcContactMethod g_PCMContactMethodTable[][PxGeometryType::eGEOMETRY_COUNT] =
+{
+ //PxGeometryType::eSPHERE
+ {
+ PxcPCMContactSphereSphere, //PxGeometryType::eSPHERE
+ PxcPCMContactSpherePlane, //PxGeometryType::ePLANE
+ PxcPCMContactSphereCapsule, //PxGeometryType::eCAPSULE
+ PxcPCMContactSphereBox, //PxGeometryType::eBOX
+ PxcPCMContactSphereConvex, //PxGeometryType::eCONVEXMESH
+ PxcPCMContactSphereMesh, //PxGeometryType::eTRIANGLEMESH
+ DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactSphereHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+ },
+
+ //PxGeometryType::ePLANE
+ {
+ 0, //PxGeometryType::eSPHERE
+ PxcInvalidContactPair, //PxGeometryType::ePLANE
+ PxcPCMContactPlaneCapsule, //PxGeometryType::eCAPSULE
+ PxcPCMContactPlaneBox, //PxGeometryType::eBOX
+ PxcPCMContactPlaneConvex, //PxGeometryType::eCONVEXMESH
+ PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
+ PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eCAPSULE
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ PxcPCMContactCapsuleCapsule, //PxGeometryType::eCAPSULE
+ PxcPCMContactCapsuleBox, //PxGeometryType::eBOX
+ PxcPCMContactCapsuleConvex, //PxGeometryType::eCONVEXMESH
+ PxcPCMContactCapsuleMesh, //PxGeometryType::eTRIANGLEMESH
+ DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactCapsuleHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+ },
+
+ //PxGeometryType::eBOX
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ PxcPCMContactBoxBox, //PxGeometryType::eBOX
+ PxcPCMContactBoxConvex, //PxGeometryType::eCONVEXMESH
+ PxcPCMContactBoxMesh, //PxGeometryType::eTRIANGLEMESH
+ DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactBoxHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+
+ },
+
+ //PxGeometryType::eCONVEXMESH
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ PxcPCMContactConvexConvex, //PxGeometryType::eCONVEXMESH
+ PxcPCMContactConvexMesh, //PxGeometryType::eTRIANGLEMESH
+ DYNAMIC_CONTACT_REGISTRATION(PxcPCMContactConvexHeightField), //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+ },
+
+ //PxGeometryType::eTRIANGLEMESH
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ 0, //PxGeometryType::eCONVEXMESH
+ PxcInvalidContactPair, //PxGeometryType::eTRIANGLEMESH
+ PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eHEIGHTFIELD
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ 0, //PxGeometryType::eCONVEXMESH
+ 0, //PxGeometryType::eTRIANGLEMESH
+ PxcInvalidContactPair, //PxGeometryType::eHEIGHTFIELD
+ },
+
+};
+}
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialHeightField.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialHeightField.cpp
new file mode 100644
index 00000000..89b347c2
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialHeightField.cpp
@@ -0,0 +1,116 @@
+// 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 "PxTriangleMesh.h"
+#include "PxvGeometry.h"
+#include "PxsMaterialManager.h"
+#include "PxcNpThreadContext.h"
+#include "GuHeightField.h"
+
+using namespace physx;
+using namespace Gu;
+
+namespace physx
+{
+ bool PxcGetMaterialShapeHeightField(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
+ bool PxcGetMaterialHeightField(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
+ PxU32 GetMaterialIndex(const Gu::HeightFieldData* hfData, PxU32 triangleIndex);
+}
+
+physx::PxU32 physx::GetMaterialIndex(const Gu::HeightFieldData* hfData, PxU32 triangleIndex)
+{
+ const PxU32 sampleIndex = triangleIndex >> 1;
+ const bool isFirstTriangle = (triangleIndex & 0x1) == 0;
+
+ //get sample
+ const PxHeightFieldSample* hf = &hfData->samples[sampleIndex];
+ return isFirstTriangle ? hf->materialIndex0 : hf->materialIndex1;
+}
+
+bool physx::PxcGetMaterialHeightField(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
+{
+ PX_ASSERT(index == 1);
+ PX_UNUSED(index);
+ const ContactBuffer& contactBuffer = context.mContactBuffer;
+ const PxHeightFieldGeometryLL& hfGeom = shape->geometry.get<const PxHeightFieldGeometryLL>();
+ if(hfGeom.materials.numIndices <= 1)
+ {
+ for(PxU32 i=0; i< contactBuffer.count; ++i)
+ {
+ (&materialInfo[i].mMaterialIndex0)[index] = shape->materialIndex;
+ }
+ }
+ else
+ {
+ const PxU16* materialIndices = hfGeom.materials.indices;
+
+ const Gu::HeightFieldData* hf = hfGeom.heightFieldData;
+
+ for(PxU32 i=0; i< contactBuffer.count; ++i)
+ {
+ const Gu::ContactPoint& contact = contactBuffer.contacts[i];
+ const PxU32 localMaterialIndex = GetMaterialIndex(hf, contact.internalFaceIndex1);
+ (&materialInfo[i].mMaterialIndex0)[index] = materialIndices[localMaterialIndex];
+ }
+ }
+ return true;
+}
+
+bool physx::PxcGetMaterialShapeHeightField(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
+{
+ const ContactBuffer& contactBuffer = context.mContactBuffer;
+ const PxHeightFieldGeometryLL& hfGeom = shape1->geometry.get<const PxHeightFieldGeometryLL>();
+ if(hfGeom.materials.numIndices <= 1)
+ {
+ for(PxU32 i=0; i< contactBuffer.count; ++i)
+ {
+ materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
+ materialInfo[i].mMaterialIndex1 = shape1->materialIndex;
+ }
+ }
+ else
+ {
+ const PxU16* materialIndices = hfGeom.materials.indices;
+
+ const Gu::HeightFieldData* hf = hfGeom.heightFieldData;
+
+ for(PxU32 i=0; i< contactBuffer.count; ++i)
+ {
+ const Gu::ContactPoint& contact = contactBuffer.contacts[i];
+ materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
+ //contact.featureIndex0 = shape0->materialIndex;
+ const PxU32 localMaterialIndex = GetMaterialIndex(hf, contact.internalFaceIndex1);
+ //contact.featureIndex1 = materialIndices[localMaterialIndex];
+ PX_ASSERT(localMaterialIndex<hfGeom.materials.numIndices);
+ materialInfo[i].mMaterialIndex1 = materialIndices[localMaterialIndex];
+ }
+ }
+ return true;
+}
+
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialMesh.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialMesh.cpp
new file mode 100644
index 00000000..17b16712
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialMesh.cpp
@@ -0,0 +1,107 @@
+// 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 "PxTriangleMesh.h"
+#include "PxvGeometry.h"
+#include "PxsMaterialManager.h"
+#include "PxcNpThreadContext.h"
+#include "GuHeightField.h"
+#include "GuTriangleMesh.h"
+
+using namespace physx;
+using namespace Gu;
+
+namespace physx
+{
+ bool PxcGetMaterialShapeMesh(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
+ bool PxcGetMaterialMesh(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo);
+}
+
+bool physx::PxcGetMaterialMesh(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
+{
+ PX_ASSERT(index == 1);
+ PX_UNUSED(index);
+ ContactBuffer& contactBuffer = context.mContactBuffer;
+ const PxTriangleMeshGeometryLL& shapeMesh = shape->geometry.get<const PxTriangleMeshGeometryLL>();
+ if(shapeMesh.materials.numIndices <= 1)
+ {
+ for(PxU32 i=0; i< contactBuffer.count; ++i)
+ {
+ (&materialInfo[i].mMaterialIndex0)[index] = shape->materialIndex;
+ }
+ }
+ else
+ {
+ for(PxU32 i=0; i< contactBuffer.count; ++i)
+ {
+
+ Gu::ContactPoint& contact = contactBuffer.contacts[i];
+ const PxU16* eaMaterialIndices = shapeMesh.materialIndices;
+
+ const PxU32 localMaterialIndex = eaMaterialIndices[contact.internalFaceIndex1];//shapeMesh.triangleMesh->getTriangleMaterialIndex(contact.featureIndex1);
+ (&materialInfo[i].mMaterialIndex0)[index] = shapeMesh.materials.indices[localMaterialIndex];
+ }
+ }
+ return true;
+}
+
+bool physx::PxcGetMaterialShapeMesh(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
+{
+
+ ContactBuffer& contactBuffer = context.mContactBuffer;
+ const PxTriangleMeshGeometryLL& shapeMesh = shape1->geometry.get<const PxTriangleMeshGeometryLL>();
+// const Gu::TriangleMesh* meshData = shapeMesh.meshData;
+ if(shapeMesh.materials.numIndices <= 1)
+ {
+ for(PxU32 i=0; i< contactBuffer.count; ++i)
+ {
+ materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
+ materialInfo[i].mMaterialIndex1 = shape1->materialIndex;
+ }
+ }
+ else
+ {
+
+ for(PxU32 i=0; i< contactBuffer.count; ++i)
+ {
+
+ Gu::ContactPoint& contact = contactBuffer.contacts[i];
+ //contact.featureIndex0 = shape0->materialIndex;
+ materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
+ const PxU16* eaMaterialIndices = shapeMesh.materialIndices;
+
+ const PxU32 localMaterialIndex = eaMaterialIndices[contact.internalFaceIndex1];//shapeMesh.triangleMesh->getTriangleMaterialIndex(contact.featureIndex1);
+ //contact.featureIndex1 = shapeMesh.materials.indices[localMaterialIndex];
+ materialInfo[i].mMaterialIndex1 = shapeMesh.materials.indices[localMaterialIndex];
+
+ }
+ }
+
+ return true;
+}
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialMethodImpl.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialMethodImpl.cpp
new file mode 100644
index 00000000..61195bf0
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialMethodImpl.cpp
@@ -0,0 +1,140 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+
+#include "PxGeometry.h"
+#include "PxcMaterialMethodImpl.h"
+
+namespace physx
+{
+bool PxcGetMaterialShapeShape (MATERIAL_METHOD_ARGS);
+bool PxcGetMaterialShapeMesh (MATERIAL_METHOD_ARGS);
+bool PxcGetMaterialShapeHeightField (MATERIAL_METHOD_ARGS);
+bool PxcGetMaterialShape (SINGLE_MATERIAL_METHOD_ARGS);
+bool PxcGetMaterialMesh (SINGLE_MATERIAL_METHOD_ARGS);
+bool PxcGetMaterialHeightField (SINGLE_MATERIAL_METHOD_ARGS);
+
+
+PxcGetSingleMaterialMethod g_GetSingleMaterialMethodTable[PxGeometryType::eGEOMETRY_COUNT] =
+{
+ PxcGetMaterialShape, //PxGeometryType::eSPHERE
+ PxcGetMaterialShape, //PxGeometryType::ePLANE
+ PxcGetMaterialShape, //PxGeometryType::eCAPSULE
+ PxcGetMaterialShape, //PxGeometryType::eBOX
+ PxcGetMaterialShape, //PxGeometryType::eCONVEXMESH
+ PxcGetMaterialMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
+ PxcGetMaterialHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+
+};
+
+//Table of contact methods for different shape-type combinations
+PxcGetMaterialMethod g_GetMaterialMethodTable[][PxGeometryType::eGEOMETRY_COUNT] =
+{
+
+ //PxGeometryType::eSPHERE
+ {
+ PxcGetMaterialShapeShape, //PxGeometryType::eSPHERE
+ PxcGetMaterialShapeShape, //PxGeometryType::ePLANE
+ PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
+ PxcGetMaterialShapeShape, //PxGeometryType::eBOX
+ PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
+ PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
+ PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+
+ },
+
+ //PxGeometryType::ePLANE
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
+ PxcGetMaterialShapeShape, //PxGeometryType::eBOX
+ PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
+ 0, //PxGeometryType::eTRIANGLEMESH
+ 0, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eCAPSULE
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ PxcGetMaterialShapeShape, //PxGeometryType::eCAPSULE
+ PxcGetMaterialShapeShape, //PxGeometryType::eBOX
+ PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
+ PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
+ PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+ },
+
+ //PxGeometryType::eBOX
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ PxcGetMaterialShapeShape, //PxGeometryType::eBOX
+ PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
+ PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
+ PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+ },
+
+ //PxGeometryType::eCONVEXMESH
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ PxcGetMaterialShapeShape, //PxGeometryType::eCONVEXMESH
+ PxcGetMaterialShapeMesh, //PxGeometryType::eTRIANGLEMESH //not used: mesh always uses swept method for midphase.
+ PxcGetMaterialShapeHeightField, //PxGeometryType::eHEIGHTFIELD //TODO: make HF midphase that will mask this
+ },
+
+ //PxGeometryType::eTRIANGLEMESH
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ 0, //PxGeometryType::eCONVEXMESH
+ 0, //PxGeometryType::eTRIANGLEMESH
+ 0, //PxGeometryType::eHEIGHTFIELD
+ },
+
+ //PxGeometryType::eHEIGHTFIELD
+ {
+ 0, //PxGeometryType::eSPHERE
+ 0, //PxGeometryType::ePLANE
+ 0, //PxGeometryType::eCAPSULE
+ 0, //PxGeometryType::eBOX
+ 0, //PxGeometryType::eCONVEXMESH
+ 0, //PxGeometryType::eTRIANGLEMESH
+ 0, //PxGeometryType::eHEIGHTFIELD
+ },
+
+};
+
+}
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialShape.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialShape.cpp
new file mode 100644
index 00000000..1c8c3849
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcMaterialShape.cpp
@@ -0,0 +1,62 @@
+// 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 "PxTriangleMesh.h"
+#include "PxvGeometry.h"
+#include "PxsMaterialManager.h"
+#include "PxcNpThreadContext.h"
+#include "GuHeightField.h"
+
+using namespace physx;
+using namespace Gu;
+
+namespace physx
+{
+bool PxcGetMaterialShape(const PxsShapeCore* shape, const PxU32 index, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
+{
+ ContactBuffer& contactBuffer = context.mContactBuffer;
+ for(PxU32 i=0; i< contactBuffer.count; ++i)
+ {
+ (&materialInfo[i].mMaterialIndex0)[index] = shape->materialIndex;
+ }
+ return true;
+}
+
+bool PxcGetMaterialShapeShape(const PxsShapeCore* shape0, const PxsShapeCore* shape1, PxcNpThreadContext& context, PxsMaterialInfo* materialInfo)
+{
+ ContactBuffer& contactBuffer = context.mContactBuffer;
+ for(PxU32 i=0; i< contactBuffer.count; ++i)
+ {
+ materialInfo[i].mMaterialIndex0 = shape0->materialIndex;
+ materialInfo[i].mMaterialIndex1 = shape1->materialIndex;
+ }
+ return true;
+}
+}
+
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpBatch.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpBatch.cpp
new file mode 100644
index 00000000..7ed87b05
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpBatch.cpp
@@ -0,0 +1,413 @@
+// 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 "PxcNpBatch.h"
+#include "PxcNpWorkUnit.h"
+#include "PxsContactManager.h"
+#include "GuGeometryUnion.h"
+#include "PxcContactCache.h"
+#include "PxcMaterialMethodImpl.h"
+#include "PxcNpContactPrepShared.h"
+#include "PxvDynamics.h" // for PxsBodyCore
+#include "PxvGeometry.h" // for PxsShapeCore
+#include "CmFlushPool.h"
+#include "CmTask.h"
+#include "PxTriangleMesh.h"
+#include "PxsMaterialManager.h"
+#include "PxsTransformCache.h"
+#include "GuPersistentContactManifold.h"
+#include "PxsContactManagerState.h"
+#include "PsFoundation.h"
+
+using namespace physx;
+using namespace Gu;
+
+
+static void startContacts(PxsContactManagerOutput& output, PxcNpThreadContext& context)
+{
+ context.mContactBuffer.reset();
+
+ output.contactForces = NULL;
+ output.contactPatches = NULL;
+ output.contactPoints = NULL;
+ output.nbContacts = 0;
+ output.nbPatches = 0;
+ output.statusFlag = 0;
+}
+
+static void flipContacts(PxcNpThreadContext& threadContext, PxsMaterialInfo* PX_RESTRICT materialInfo)
+{
+ ContactBuffer& buffer = threadContext.mContactBuffer;
+ for(PxU32 i=0; i<buffer.count; ++i)
+ {
+ Gu::ContactPoint& contactPoint = buffer.contacts[i];
+ contactPoint.normal = -contactPoint.normal;
+ Ps::swap(materialInfo[i].mMaterialIndex0, materialInfo[i].mMaterialIndex1);
+ }
+}
+
+static PX_FORCE_INLINE void updateDiscreteContactStats(PxcNpThreadContext& context, PxGeometryType::Enum type0, PxGeometryType::Enum type1)
+{
+#if PX_ENABLE_SIM_STATS
+ PX_ASSERT(type0<=type1);
+ context.mDiscreteContactPairs[type0][type1]++;
+#endif
+}
+
+static bool copyBuffers(PxsContactManagerOutput& cmOutput, Gu::Cache& cache, PxcNpThreadContext& context, const bool useContactCache, const bool isMeshType)
+{
+ bool ret = false;
+ //Copy the contact stream from previous buffer to current buffer...
+ PxU32 oldSize = sizeof(PxContact) * cmOutput.nbContacts + sizeof(PxContactPatch)*cmOutput.nbPatches;
+ if(oldSize)
+ {
+ ret = true;
+ PxU8* oldPatches = cmOutput.contactPatches;
+ PxU8* oldContacts = cmOutput.contactPoints;
+
+ PxU32 forceSize = cmOutput.nbContacts * sizeof(PxReal);
+
+ PxU8* PX_RESTRICT contactPatches = NULL;
+ PxU8* PX_RESTRICT contactPoints = NULL;
+
+ PxReal* forceBuffer = NULL;
+
+ bool isOverflown = false;
+
+ //ML: if we are using contactStreamPool, which means we are running the GPU codepath
+ if(context.mContactStreamPool)
+ {
+ const PxU32 patchSize = cmOutput.nbPatches * sizeof(PxContactPatch);
+ const PxU32 contactSize = cmOutput.nbContacts * sizeof(PxContact);
+
+ PxU32 index = PxU32(Ps::atomicAdd(&context.mContactStreamPool->mSharedDataIndex, PxI32(contactSize)));
+
+ if(context.mContactStreamPool->isOverflown())
+ {
+ PX_WARN_ONCE("Contact buffer overflow detected, please increase its size in the scene desc!\n");
+ isOverflown = true;
+ }
+ contactPoints = context.mContactStreamPool->mDataStream + context.mContactStreamPool->mDataStreamSize - index;
+
+ const PxU32 patchIndex = PxU32(Ps::atomicAdd(&context.mPatchStreamPool->mSharedDataIndex, PxI32(patchSize)));
+
+ if(context.mPatchStreamPool->isOverflown())
+ {
+ PX_WARN_ONCE("Patch buffer overflow detected, please increase its size in the scene desc!\n");
+ isOverflown = true;
+ }
+ contactPatches = context.mPatchStreamPool->mDataStream + context.mPatchStreamPool->mDataStreamSize - patchIndex;
+
+ if(forceSize)
+ {
+ forceSize = isMeshType ? (forceSize * 2) : forceSize;
+
+ index = PxU32(Ps::atomicAdd(&context.mForceAndIndiceStreamPool->mSharedDataIndex, PxI32(forceSize)));
+
+ if(context.mForceAndIndiceStreamPool->isOverflown())
+ {
+ PX_WARN_ONCE("Force buffer overflow detected, please increase its size in the scene desc!\n");
+ isOverflown = true;
+ }
+ forceBuffer = reinterpret_cast<PxReal*>(context.mForceAndIndiceStreamPool->mDataStream + context.mForceAndIndiceStreamPool->mDataStreamSize - index);
+ }
+
+ if(isOverflown)
+ {
+ contactPatches = NULL;
+ contactPoints = NULL;
+ forceBuffer = NULL;
+ cmOutput.nbContacts = cmOutput.nbPatches = 0;
+ }
+ else
+ {
+ PxMemCopy(contactPatches, oldPatches, patchSize);
+ PxMemCopy(contactPoints, oldContacts, contactSize);
+ }
+ }
+ else
+ {
+ const PxU32 alignedOldSize = (oldSize + 0xf) & 0xfffffff0;
+
+ PxU8* data = context.mContactBlockStream.reserve(alignedOldSize + forceSize);
+ if(forceSize)
+ forceBuffer = reinterpret_cast<PxReal*>(data + alignedOldSize);
+
+ contactPatches = data;
+ contactPoints = data + cmOutput.nbPatches * sizeof(PxContactPatch);
+
+ PxMemCopy(data, oldPatches, oldSize);
+ }
+
+ if(forceSize)
+ {
+ PxMemZero(forceBuffer, forceSize);
+ }
+
+ cmOutput.contactPatches= contactPatches;
+ cmOutput.contactPoints = contactPoints;
+ cmOutput.contactForces = forceBuffer;
+ }
+
+ if(cache.mCachedSize)
+ {
+ if(cache.isMultiManifold())
+ {
+ PX_ASSERT((cache.mCachedSize & 0xF) == 0);
+ PxU8* newData = context.mNpCacheStreamPair.reserve(cache.mCachedSize);
+ PX_ASSERT((reinterpret_cast<uintptr_t>(newData)& 0xF) == 0);
+ PxMemCopy(newData, & cache.getMultipleManifold(), cache.mCachedSize);
+ cache.setMultiManifold(newData);
+ }
+ else if(useContactCache)
+ {
+ //Copy cache information as well...
+ const PxU8* cachedData = cache.mCachedData;
+ PxU8* newData = context.mNpCacheStreamPair.reserve(PxU32(cache.mCachedSize + 0xf) & 0xfff0);
+ PxMemCopy(newData, cachedData, cache.mCachedSize);
+ cache.mCachedData = newData;
+ }
+ }
+ return ret;
+}
+
+void physx::PxcDiscreteNarrowPhase(PxcNpThreadContext& context, PxcNpWorkUnit& input, Gu::Cache& cache, PxsContactManagerOutput& output)
+{
+ //ML : if user doesn't raise the eDETECT_DISCRETE_CONTACT, we should not generate contacts
+ if(!(input.flags & PxcNpWorkUnitFlag::eDETECT_DISCRETE_CONTACT))
+ return;
+
+ PxGeometryType::Enum type0 = static_cast<PxGeometryType::Enum>(input.geomType0);
+ PxGeometryType::Enum type1 = static_cast<PxGeometryType::Enum>(input.geomType1);
+
+ const bool flip = (type1<type0);
+
+ const PxsCachedTransform* cachedTransform0 = &context.mTransformCache->getTransformCache(input.mTransformCache0);
+ const PxsCachedTransform* cachedTransform1 = &context.mTransformCache->getTransformCache(input.mTransformCache1);
+
+ if(!(output.statusFlag & PxcNpWorkUnitStatusFlag::eDIRTY_MANAGER) && !(input.flags & PxcNpWorkUnitFlag::eMODIFIABLE_CONTACT))
+ {
+ const PxU32 body0Dynamic = PxU32(input.flags & PxcNpWorkUnitFlag::eDYNAMIC_BODY0);
+ const PxU32 body1Dynamic = PxU32(input.flags & PxcNpWorkUnitFlag::eDYNAMIC_BODY1);
+
+ const PxU32 active0 = PxU32(body0Dynamic && !cachedTransform0->isFrozen());
+ const PxU32 active1 = PxU32(body1Dynamic && !cachedTransform1->isFrozen());
+
+ if(!(active0 || active1))
+ {
+ if(flip)
+ Ps::swap(type0, type1);
+
+ const bool useContactCache = context.mContactCache && g_CanUseContactCache[type0][type1];
+
+#if PX_ENABLE_SIM_STATS
+ if(output.nbContacts)
+ context.mNbDiscreteContactPairsWithContacts++;
+#endif
+ const bool isMeshType = type1 > PxGeometryType::eCONVEXMESH;
+ copyBuffers(output, cache, context, useContactCache, isMeshType);
+ return;
+ }
+ }
+
+ output.statusFlag &= (~PxcNpWorkUnitStatusFlag::eDIRTY_MANAGER);
+
+ PxsShapeCore* shape0 = const_cast<PxsShapeCore*>(input.shapeCore0);
+ PxsShapeCore* shape1 = const_cast<PxsShapeCore*>(input.shapeCore1);
+
+ if(flip)
+ {
+ Ps::swap(type0, type1);
+ Ps::swap(shape0, shape1);
+ Ps::swap(cachedTransform0, cachedTransform1);
+ }
+
+ // PT: many cache misses here...
+ // PT: TODO: refactor this change with runNpBatchPPU
+
+ Ps::prefetchLine(shape1, 0); // PT: at least get rid of L2s for shape1
+
+ const PxTransform* tm0 = &cachedTransform0->transform;
+ const PxTransform* tm1 = &cachedTransform1->transform;
+ PX_ASSERT(tm0->isSane() && tm1->isSane());
+
+ updateDiscreteContactStats(context, type0, type1);
+
+ const PxReal contactDist0 = context.mContactDistance[input.mTransformCache0];
+ const PxReal contactDist1 = context.mContactDistance[input.mTransformCache1];
+ //context.mNarrowPhaseParams.mContactDistance = shape0->contactOffset + shape1->contactOffset;
+ context.mNarrowPhaseParams.mContactDistance = contactDist0 + contactDist1;
+
+ startContacts(output, context);
+
+ const PxcContactMethod conMethod = g_ContactMethodTable[type0][type1];
+ PX_ASSERT(conMethod);
+
+ const bool useContactCache = context.mContactCache && g_CanUseContactCache[type0][type1];
+ if(useContactCache)
+ {
+#if PX_ENABLE_SIM_STATS
+ if(PxcCacheLocalContacts(context, cache, *tm0, *tm1, conMethod, shape0->geometry, shape1->geometry))
+ context.mNbDiscreteContactPairsWithCacheHits++;
+#else
+ PxcCacheLocalContacts(context, n.pairCache, *tm0, *tm1, conMethod, shape0->geometry, shape1->geometry);
+#endif
+ }
+ else
+ {
+ conMethod(shape0->geometry, shape1->geometry, *tm0, *tm1, context.mNarrowPhaseParams, cache, context.mContactBuffer, &context.mRenderOutput);
+ }
+
+ PxsMaterialInfo materialInfo[ContactBuffer::MAX_CONTACTS];
+
+ const PxcGetMaterialMethod materialMethod = g_GetMaterialMethodTable[type0][type1];
+ PX_ASSERT(materialMethod);
+
+ materialMethod(shape0, shape1, context, materialInfo);
+
+ if(flip)
+ flipContacts(context, materialInfo);
+
+ const bool isMeshType = type1 > PxGeometryType::eCONVEXMESH;
+ finishContacts(input, output, context, materialInfo, isMeshType);
+}
+
+void physx::PxcDiscreteNarrowPhasePCM(PxcNpThreadContext& context, PxcNpWorkUnit& cmInput, Gu::Cache& cache, PxsContactManagerOutput& output)
+{
+ //ML : if user doesn't raise the eDETECT_DISCRETE_CONTACT, we should not generate contacts
+ if(!(cmInput.flags & PxcNpWorkUnitFlag::eDETECT_DISCRETE_CONTACT))
+ return;
+
+ PxGeometryType::Enum type0 = static_cast<PxGeometryType::Enum>(cmInput.geomType0);
+ PxGeometryType::Enum type1 = static_cast<PxGeometryType::Enum>(cmInput.geomType1);
+
+ const bool flip = type1<type0;
+
+ const PxsCachedTransform* tm0 = &context.mTransformCache->getTransformCache(cmInput.mTransformCache0);
+ const PxsCachedTransform* tm1 = &context.mTransformCache->getTransformCache(cmInput.mTransformCache1);
+
+ if(!(output.statusFlag & PxcNpWorkUnitStatusFlag::eDIRTY_MANAGER) && !(cmInput.flags & PxcNpWorkUnitFlag::eMODIFIABLE_CONTACT))
+ {
+ const PxU32 body0Dynamic = PxU32(cmInput.flags & PxcNpWorkUnitFlag::eDYNAMIC_BODY0);
+ const PxU32 body1Dynamic = PxU32(cmInput.flags & PxcNpWorkUnitFlag::eDYNAMIC_BODY1);
+
+ const PxU32 active0 = PxU32(body0Dynamic && !(tm0->isFrozen()));
+ const PxU32 active1 = PxU32(body1Dynamic && !(tm1->isFrozen()));
+
+ if(!(active0 || active1))
+ {
+ if(flip)
+ Ps::swap(type0, type1);
+
+#if PX_ENABLE_SIM_STATS
+ if(output.nbContacts)
+ context.mNbDiscreteContactPairsWithContacts++;
+#endif
+ const bool isMeshType = type1 > PxGeometryType::eCONVEXMESH;
+ copyBuffers(output, cache, context, false, isMeshType);
+ return;
+ }
+ }
+
+ output.statusFlag &= (~PxcNpWorkUnitStatusFlag::eDIRTY_MANAGER);
+
+ Gu::MultiplePersistentContactManifold& manifold = context.mTempManifold;
+ bool isMultiManifold = false;
+
+ if(cache.isMultiManifold())
+ {
+ //We are using a multi-manifold. This is cached in a reduced npCache...
+ isMultiManifold = true;
+ uintptr_t address = uintptr_t(&cache.getMultipleManifold());
+ manifold.fromBuffer(reinterpret_cast<PxU8*>(address));
+ cache.setMultiManifold(&manifold);
+ }
+ else if(cache.isManifold())
+ {
+ void* address = reinterpret_cast<void*>(&cache.getManifold());
+ Ps::prefetch(address);
+ Ps::prefetch(address, 128);
+ Ps::prefetch(address, 256);
+ }
+
+ PxsShapeCore* shape0 = const_cast<PxsShapeCore*>(cmInput.shapeCore0);
+ PxsShapeCore* shape1 = const_cast<PxsShapeCore*>(cmInput.shapeCore1);
+
+ if(flip)
+ {
+ Ps::swap(tm0, tm1);
+ Ps::swap(shape0, shape1);
+ Ps::swap(type0, type1);
+ }
+
+ const PxReal contactDist0 = context.mContactDistance[cmInput.mTransformCache0];
+ const PxReal contactDist1 = context.mContactDistance[cmInput.mTransformCache1];
+// context.mNarrowPhaseParams.mContactDistance = shape0->contactOffset + shape1->contactOffset;
+ context.mNarrowPhaseParams.mContactDistance = contactDist0 + contactDist1;
+
+ PX_ASSERT(tm0->transform.isSane() && tm1->transform.isSane());
+
+ updateDiscreteContactStats(context, type0, type1);
+
+ const PxcContactMethod conMethod = g_PCMContactMethodTable[type0][type1];
+ PX_ASSERT(conMethod);
+
+ startContacts(output, context);
+
+ conMethod(shape0->geometry, shape1->geometry, tm0->transform, tm1->transform, context.mNarrowPhaseParams, cache, context.mContactBuffer, &context.mRenderOutput);
+
+ PxsMaterialInfo materialInfo[ContactBuffer::MAX_CONTACTS];
+
+ const PxcGetMaterialMethod materialMethod = g_GetMaterialMethodTable[type0][type1];
+ PX_ASSERT(materialMethod);
+
+ materialMethod(shape0, shape1, context, materialInfo);
+
+ if(flip)
+ flipContacts(context, materialInfo);
+
+ if(isMultiManifold)
+ {
+ //Store the manifold back...
+ const PxU32 size = (sizeof(MultiPersistentManifoldHeader) +
+ manifold.mNumManifolds * sizeof(SingleManifoldHeader) +
+ manifold.mNumTotalContacts * sizeof(Gu::CachedMeshPersistentContact));
+
+ PxU8* buffer = context.mNpCacheStreamPair.reserve(size);
+
+ PX_ASSERT((reinterpret_cast<uintptr_t>(buffer)& 0xf) == 0);
+ manifold.toBuffer(buffer);
+ cache.setMultiManifold(buffer);
+ cache.mCachedSize = Ps::to16(size);
+ }
+
+ const bool isMeshType = type1 > PxGeometryType::eCONVEXMESH;
+ finishContacts(cmInput, output, context, materialInfo, isMeshType);
+}
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpCacheStreamPair.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpCacheStreamPair.cpp
new file mode 100644
index 00000000..54096677
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpCacheStreamPair.cpp
@@ -0,0 +1,75 @@
+// 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 "PxcNpCacheStreamPair.h"
+#include "PsUserAllocated.h"
+#include "PxcNpMemBlockPool.h"
+
+using namespace physx;
+
+void PxcNpCacheStreamPair::reset()
+{
+ mBlock = NULL;
+ mUsed = 0;
+}
+
+PxcNpCacheStreamPair::PxcNpCacheStreamPair(PxcNpMemBlockPool& blockPool):
+ mBlockPool(blockPool), mBlock(NULL), mUsed(0)
+{
+}
+
+// reserve can fail and return null. Read should never fail
+PxU8* PxcNpCacheStreamPair::reserve(PxU32 size)
+{
+ size = (size+15)&~15;
+
+ if(size>PxcNpMemBlock::SIZE)
+ {
+ return reinterpret_cast<PxU8*>(-1);
+ }
+
+ if(mBlock == NULL || mUsed + size > PxcNpMemBlock::SIZE)
+ {
+ mBlock = mBlockPool.acquireNpCacheBlock();
+ mUsed = 0;
+ }
+
+ PxU8* ptr;
+ if(mBlock == NULL)
+ ptr = 0;
+ else
+ {
+ ptr = mBlock->data+mUsed;
+ mUsed += size;
+ }
+
+ return ptr;
+}
+
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpContactPrepShared.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpContactPrepShared.cpp
new file mode 100644
index 00000000..e0fa6262
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpContactPrepShared.cpp
@@ -0,0 +1,623 @@
+// 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 "PsMathUtils.h"
+#include "PxcNpWorkUnit.h"
+#include "PxvDynamics.h"
+
+using namespace physx;
+using namespace Gu;
+
+#include "PxsMaterialManager.h"
+#include "PxsMaterialCombiner.h"
+
+#include "PxcNpContactPrepShared.h"
+#include "PsAtomic.h"
+#include "PxsContactManagerState.h"
+
+#include "PsVecMath.h"
+using namespace physx;
+using namespace Ps::aos;
+
+static PX_FORCE_INLINE void copyContactPoint(PxContact* PX_RESTRICT point, const Gu::ContactPoint* PX_RESTRICT cp)
+{
+ // PT: TODO: consider moving "separation" right after "point" in both structures, to copy both at the same time.
+// point->contact = cp->point;
+ const Vec4V contactV = V4LoadA(&cp->point.x); // PT: V4LoadA safe because 'point' is aligned.
+ V4StoreU(contactV, &point->contact.x);
+
+ point->separation = cp->separation;
+}
+
+struct StridePatch
+{
+ PxU8 startIndex;
+ PxU8 endIndex;
+ PxU8 nextIndex;
+ PxU8 totalCount;
+ bool isRoot;
+};
+
+PxU32 physx::writeCompressedContact(const Gu::ContactPoint* const PX_RESTRICT contactPoints, const PxU32 numContactPoints, PxcNpThreadContext* threadContext,
+ PxU8& writtenContactCount, PxU8*& outContactPatches, PxU8*& outContactPoints, PxU16& compressedContactSize, PxReal*& outContactForces, PxU32 contactForceByteSize,
+ const PxsMaterialManager* materialManager, bool hasModifiableContacts, bool forceNoResponse, PxsMaterialInfo* PX_RESTRICT pMaterial, PxU8& numPatches,
+ PxU32 additionalHeaderSize, PxsConstraintBlockManager* manager, PxcConstraintBlockStream* blockStream, bool insertAveragePoint,
+ PxcDataStreamPool* contactStreamPool, PxcDataStreamPool* patchStreamPool, PxcDataStreamPool* forceStreamPool, const bool isMeshType)
+{
+ if(numContactPoints == 0)
+ {
+ writtenContactCount = 0;
+ outContactPatches = NULL;
+ outContactPoints = NULL;
+ outContactForces = NULL;
+ compressedContactSize = 0;
+ numPatches = 0;
+ return 0;
+ }
+
+ //Calculate the size of the contact buffer...
+ PX_ALLOCA(strPatches, StridePatch, numContactPoints);
+
+ StridePatch* stridePatches = &strPatches[0];
+
+ PxU32 numStrideHeaders = 1;
+
+ /*const bool hasInternalFaceIndex = contactPoints[0].internalFaceIndex0 != PXC_CONTACT_NO_FACE_INDEX ||
+ contactPoints[0].internalFaceIndex1 != PXC_CONTACT_NO_FACE_INDEX;*/
+ const bool isModifiable = !forceNoResponse && hasModifiableContacts;
+
+ PxU32 totalUniquePatches = 1;
+
+ PxU32 totalContactPoints = numContactPoints;
+
+ PxU32 strideStart = 0;
+ bool root = true;
+ StridePatch* parentRootPatch = NULL;
+ {
+ const PxReal closeNormalThresh = PXC_SAME_NORMAL;
+ //Go through and tag how many patches we have...
+ PxVec3 normal = contactPoints[0].normal;
+ PxU16 mat0 = pMaterial[0].mMaterialIndex0;
+ PxU16 mat1 = pMaterial[0].mMaterialIndex1;
+
+ for(PxU32 a = 1; a < numContactPoints; ++a)
+ {
+ if(normal.dot(contactPoints[a].normal) < closeNormalThresh ||
+ pMaterial[a].mMaterialIndex0 != mat0 || pMaterial[a].mMaterialIndex1 != mat1)
+ {
+ StridePatch& patch = stridePatches[numStrideHeaders-1];
+
+ patch.startIndex = PxU8(strideStart);
+ patch.endIndex = PxU8(a);
+ patch.nextIndex = 0xFF;
+ patch.totalCount = PxU8(a - strideStart);
+ patch.isRoot = root;
+ if(parentRootPatch)
+ parentRootPatch->totalCount += PxU8(a - strideStart);
+
+ root = true;
+ parentRootPatch = NULL;
+ for(PxU32 b = 1; b < numStrideHeaders; ++b)
+ {
+ StridePatch& thisPatch = stridePatches[b-1];
+ if(thisPatch.isRoot)
+ {
+ PxU32 ind = thisPatch.startIndex;
+ PxReal dp2 = contactPoints[a].normal.dot(contactPoints[ind].normal);
+ if(dp2 >= closeNormalThresh && pMaterial[a].mMaterialIndex0 == pMaterial[ind].mMaterialIndex0 &&
+ pMaterial[a].mMaterialIndex1 == pMaterial[ind].mMaterialIndex1)
+ {
+ PxU32 nextInd = b-1;
+ while(stridePatches[nextInd].nextIndex != 0xFF)
+ nextInd = stridePatches[nextInd].nextIndex;
+ stridePatches[nextInd].nextIndex = PxU8(numStrideHeaders);
+ root = false;
+ parentRootPatch = &stridePatches[b-1];
+ break;
+ }
+ }
+ }
+
+ normal = contactPoints[a].normal;
+
+ mat0 = pMaterial[a].mMaterialIndex0;
+ mat1 = pMaterial[a].mMaterialIndex1;
+ totalContactPoints = insertAveragePoint && (a - strideStart) > 1 ? totalContactPoints + 1 : totalContactPoints;
+ strideStart = a;
+ numStrideHeaders++;
+ if(root)
+ totalUniquePatches++;
+ }
+ }
+ totalContactPoints = insertAveragePoint &&(numContactPoints - strideStart) > 1 ? totalContactPoints + 1 : totalContactPoints;
+ contactForceByteSize = insertAveragePoint && contactForceByteSize != 0 ? contactForceByteSize + sizeof(PxF32) * (totalContactPoints - numContactPoints) : contactForceByteSize;
+ }
+ {
+ StridePatch& patch = stridePatches[numStrideHeaders-1];
+ patch.startIndex = PxU8(strideStart);
+ patch.endIndex = PxU8(numContactPoints);
+ patch.nextIndex = 0xFF;
+ patch.totalCount = PxU8(numContactPoints - strideStart);
+ patch.isRoot = root;
+ if(parentRootPatch)
+ parentRootPatch->totalCount += PxU8(numContactPoints - strideStart);
+ }
+
+ numPatches = PxU8(totalUniquePatches);
+
+ //Calculate the number of patches/points required
+
+ const PxU32 patchHeaderSize = sizeof(PxContactPatch) * (isModifiable ? totalContactPoints : totalUniquePatches) + additionalHeaderSize;
+ const PxU32 pointSize = totalContactPoints * (isModifiable ? sizeof(PxModifiableContact) : sizeof(PxContact));
+
+ PxU32 requiredContactSize = pointSize;
+ PxU32 requiredPatchSize = patchHeaderSize;
+ PxU32 totalRequiredSize;
+
+ PxU8* PX_RESTRICT contactData = NULL;
+ PxU8* PX_RESTRICT patchData = NULL;
+ PxReal* PX_RESTRICT forceData = NULL;
+ PxU32* PX_RESTRICT triangleIndice = NULL;
+
+ if(contactStreamPool && !isModifiable && additionalHeaderSize == 0) //If the contacts are modifiable, we **DON'T** allocate them in GPU pinned memory. This will be handled later when they're modified
+ {
+ bool isOverflown = false;
+
+ PxU32 contactIndex = PxU32(Ps::atomicAdd(&contactStreamPool->mSharedDataIndex, PxI32(requiredContactSize)));
+
+ if (contactStreamPool->isOverflown())
+ {
+ PX_WARN_ONCE("Contact buffer overflow detected, please increase its size in the scene desc!\n");
+ isOverflown = true;
+ }
+
+ contactData = contactStreamPool->mDataStream + contactStreamPool->mDataStreamSize - contactIndex;
+
+ PxU32 patchIndex = PxU32(Ps::atomicAdd(&patchStreamPool->mSharedDataIndex, PxI32(requiredPatchSize)));
+
+ if (patchStreamPool->isOverflown())
+ {
+ PX_WARN_ONCE("Patch buffer overflow detected, please increase its size in the scene desc!\n");
+ isOverflown = true;
+ }
+
+ patchData = patchStreamPool->mDataStream + patchStreamPool->mDataStreamSize - patchIndex;
+
+ if(contactForceByteSize)
+ {
+ contactForceByteSize = isMeshType ? contactForceByteSize * 2 : contactForceByteSize;
+ contactIndex = PxU32(Ps::atomicAdd(&forceStreamPool->mSharedDataIndex, PxI32(contactForceByteSize)));
+
+ if (forceStreamPool->isOverflown())
+ {
+ PX_WARN_ONCE("Force buffer overflow detected, please increase its size in the scene desc!\n");
+ isOverflown = true;
+ }
+ forceData = reinterpret_cast<PxReal*>(forceStreamPool->mDataStream + forceStreamPool->mDataStreamSize - contactIndex);
+ if (isMeshType)
+ triangleIndice = reinterpret_cast<PxU32*>(forceData + numContactPoints);
+ }
+
+ totalRequiredSize = requiredContactSize + requiredPatchSize;
+
+ if (isOverflown)
+ {
+ patchData = NULL;
+ contactData = NULL;
+ forceData = NULL;
+ triangleIndice = NULL;
+ }
+ }
+ else
+ {
+ PxU32 alignedRequiredSize = (requiredContactSize + requiredPatchSize + 0xf) & 0xfffffff0;
+ contactForceByteSize = (isMeshType ? contactForceByteSize * 2 : contactForceByteSize);
+ PxU32 totalSize = alignedRequiredSize + contactForceByteSize;
+ PxU8* data = manager ? blockStream->reserve(totalSize, *manager) : threadContext->mContactBlockStream.reserve(totalSize);
+
+ patchData = data;
+ contactData = patchData + requiredPatchSize;
+
+ if(contactForceByteSize)
+ {
+ forceData = reinterpret_cast<PxReal*>((data + alignedRequiredSize));
+
+ if (isMeshType)
+ triangleIndice = reinterpret_cast<PxU32*>(forceData + numContactPoints);
+
+ if(data)
+ {
+ PxMemZero(forceData, contactForceByteSize);
+ }
+ }
+
+ totalRequiredSize = alignedRequiredSize;
+
+ }
+
+ Ps::prefetchLine(patchData);
+ Ps::prefetchLine(contactData);
+
+ if(patchData == NULL)
+ {
+ writtenContactCount = 0;
+ outContactPatches = NULL;
+ outContactPoints = NULL;
+ outContactForces = NULL;
+ compressedContactSize = 0;
+ numPatches = 0;
+ return 0;
+ }
+
+#if PX_ENABLE_SIM_STATS
+ if(threadContext)
+ {
+ threadContext->mCompressedCacheSize += totalRequiredSize;
+ threadContext->mTotalCompressedCacheSize += totalRequiredSize;
+ }
+#endif
+ compressedContactSize = Ps::to16(totalRequiredSize);
+
+
+
+ //PxU32 startIndex = 0;
+
+ //Extract first material
+ PxU16 origMatIndex0 = pMaterial[0].mMaterialIndex0;
+ PxU16 origMatIndex1 = pMaterial[0].mMaterialIndex1;
+
+ PxReal staticFriction, dynamicFriction, combinedRestitution;
+ PxU32 materialFlags;
+ {
+ const PxsMaterialData& data0 = *materialManager->getMaterial(origMatIndex0);
+ const PxsMaterialData& data1 = *materialManager->getMaterial(origMatIndex1);
+
+ combinedRestitution = PxsMaterialCombiner::combineRestitution(data0, data1);
+ PxsMaterialCombiner combiner(1.0f, 1.0f);
+ PxsMaterialCombiner::PxsCombinedMaterial combinedMat = combiner.combineIsotropicFriction(data0, data1);
+ staticFriction = combinedMat.staFriction;
+ dynamicFriction = combinedMat.dynFriction;
+ materialFlags = combinedMat.flags;
+ }
+
+
+ PxU8* PX_RESTRICT dataPlusOffset = patchData + additionalHeaderSize;
+ PxContactPatch* PX_RESTRICT patches = reinterpret_cast<PxContactPatch*>(dataPlusOffset);
+ PxU32* PX_RESTRICT faceIndice = triangleIndice;
+
+ outContactPatches = patchData;
+ outContactPoints = contactData;
+ outContactForces = forceData;
+
+ if(isModifiable)
+ {
+
+ PxU32 flags = PxU32(isModifiable ? PxContactPatch::eMODIFIABLE : 0) |
+ (forceNoResponse ? PxContactPatch::eFORCE_NO_RESPONSE : 0) |
+ (isMeshType ? PxContactPatch::eHAS_FACE_INDICES : 0);
+
+ PxU32 currentIndex = 0;
+
+ PxModifiableContact* PX_RESTRICT point = reinterpret_cast<PxModifiableContact*>(contactData);
+
+ for(PxU32 a = 0; a < numStrideHeaders; ++a)
+ {
+ StridePatch& rootPatch = stridePatches[a];
+ if(rootPatch.isRoot)
+ {
+ PxContactPatch* PX_RESTRICT patch = patches++;
+
+ PxU32 startIndex = rootPatch.startIndex;
+
+ const PxU16 matIndex0 = pMaterial[startIndex].mMaterialIndex0;
+ const PxU16 matIndex1 = pMaterial[startIndex].mMaterialIndex1;
+ if(matIndex0 != origMatIndex0 || matIndex1 != origMatIndex1)
+ {
+ const PxsMaterialData& data0 = *materialManager->getMaterial(matIndex0);
+ const PxsMaterialData& data1 = *materialManager->getMaterial(matIndex1);
+
+ combinedRestitution = PxsMaterialCombiner::combineRestitution(data0, data1);
+ PxsMaterialCombiner combiner(1.0f, 1.0f);
+ PxsMaterialCombiner::PxsCombinedMaterial combinedMat = combiner.combineIsotropicFriction(data0, data1);
+ staticFriction = combinedMat.staFriction;
+ dynamicFriction = combinedMat.dynFriction;
+ materialFlags = combinedMat.flags;
+ origMatIndex0 = matIndex0;
+ origMatIndex1 = matIndex1;
+ }
+
+ patch->nbContacts = rootPatch.totalCount;
+
+ patch->startContactIndex = Ps::to8(currentIndex);
+ patch->materialFlags = PxU8(materialFlags);
+ patch->staticFriction = staticFriction;
+ patch->dynamicFriction = dynamicFriction;
+ patch->restitution = combinedRestitution;
+ patch->materialIndex0 = matIndex0;
+ patch->materialIndex1 = matIndex1;
+ patch->normal = contactPoints[0].normal;
+ patch->mMassModification.mInvMassScale0 = 1.0f;
+ patch->mMassModification.mInvMassScale1 = 1.0f;
+ patch->mMassModification.mInvInertiaScale0 = 1.0f;
+ patch->mMassModification.mInvInertiaScale1 = 1.0f;
+ patch->internalFlags = PxU8(flags);
+
+ //const PxU32 endIndex = strideHeader[a];
+ const PxU32 totalCountThisPatch = rootPatch.totalCount;
+ if(insertAveragePoint && totalCountThisPatch > 1)
+ {
+ PxVec3 avgPt(0.0f);
+ PxF32 avgPen(0.0f);
+ PxF32 recipCount = 1.0f/(PxF32(rootPatch.totalCount));
+
+ PxU32 index = a;
+ while(index != 0xFF)
+ {
+ StridePatch& p = stridePatches[index];
+ for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
+ {
+ avgPt += contactPoints[b].point;
+ avgPen += contactPoints[b].separation;
+ }
+ index = p.nextIndex;
+ }
+
+ if (faceIndice)
+ {
+ StridePatch& p = stridePatches[index];
+ *faceIndice = contactPoints[p.startIndex].internalFaceIndex1;
+ faceIndice++;
+ }
+
+ patch->nbContacts++;
+ point->contact = avgPt * recipCount;
+ point->separation = avgPen * recipCount;
+ point->normal = contactPoints[0].normal;
+ point->maxImpulse = PX_MAX_REAL;
+ point->targetVelocity = PxVec3(0.0f);
+ point->staticFriction = staticFriction;
+ point->dynamicFriction = dynamicFriction;
+ point->restitution = combinedRestitution;
+ point->materialFlags = materialFlags;
+ point->materialIndex0 = matIndex0;
+ point->materialIndex1 = matIndex1;
+ point++;
+ currentIndex++;
+ Ps::prefetchLine(point, 128);
+ }
+
+ PxU32 index = a;
+ while(index != 0xFF)
+ {
+ StridePatch& p = stridePatches[index];
+
+ for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
+ {
+ copyContactPoint(point, &contactPoints[b]);
+ point->normal = contactPoints[b].normal;
+ point->maxImpulse = PX_MAX_REAL;
+ point->targetVelocity = PxVec3(0.0f);
+ point->staticFriction = staticFriction;
+ point->dynamicFriction = dynamicFriction;
+ point->restitution = combinedRestitution;
+ point->materialFlags = materialFlags;
+ point->materialIndex0 = matIndex0;
+ point->materialIndex1 = matIndex1;
+ if (faceIndice)
+ {
+ *faceIndice = contactPoints[b].internalFaceIndex1;
+ faceIndice++;
+ }
+ point++;
+ currentIndex++;
+ Ps::prefetchLine(point, 128);
+ }
+ index = p.nextIndex;
+ }
+ }
+ }
+ }
+ else
+ {
+ PxU32 flags = PxU32(isMeshType ? PxContactPatch::eHAS_FACE_INDICES : 0);
+
+ PxContact* PX_RESTRICT point = reinterpret_cast<PxContact*>(contactData);
+
+ PxU32 currentIndex = 0;
+ {
+ for(PxU32 a = 0; a < numStrideHeaders; ++a)
+ {
+ StridePatch& rootPatch = stridePatches[a];
+
+ if(rootPatch.isRoot)
+ {
+ const PxU16 matIndex0 = pMaterial[rootPatch.startIndex].mMaterialIndex0;
+ const PxU16 matIndex1 = pMaterial[rootPatch.startIndex].mMaterialIndex1;
+ if(matIndex0 != origMatIndex0 || matIndex1 != origMatIndex1)
+ {
+ const PxsMaterialData& data0 = *materialManager->getMaterial(matIndex0);
+ const PxsMaterialData& data1 = *materialManager->getMaterial(matIndex1);
+
+ combinedRestitution = PxsMaterialCombiner::combineRestitution(data0, data1);
+ PxsMaterialCombiner combiner(1.0f, 1.0f);
+ PxsMaterialCombiner::PxsCombinedMaterial combinedMat = combiner.combineIsotropicFriction(data0, data1);
+ staticFriction = combinedMat.staFriction;
+ dynamicFriction = combinedMat.dynFriction;
+ materialFlags = combinedMat.flags;
+ origMatIndex0 = matIndex0;
+ origMatIndex1 = matIndex1;
+ }
+
+ PxContactPatch* PX_RESTRICT patch = patches++;
+ patch->normal = contactPoints[rootPatch.startIndex].normal;
+ patch->nbContacts = rootPatch.totalCount;
+ patch->startContactIndex = Ps::to8(currentIndex);
+ //KS - we could probably compress this further into the header but the complexity might not be worth it
+ patch->staticFriction = staticFriction;
+ patch->dynamicFriction = dynamicFriction;
+ patch->restitution = combinedRestitution;
+ patch->materialIndex0 = matIndex0;
+ patch->materialIndex1 = matIndex1;
+ patch->materialFlags = PxU8(materialFlags);
+ patch->internalFlags = PxU8(flags);
+ patch->mMassModification.mInvMassScale0 = 1.0f;
+ patch->mMassModification.mInvMassScale1 = 1.0f;
+ patch->mMassModification.mInvInertiaScale0 = 1.0f;
+ patch->mMassModification.mInvInertiaScale1 = 1.0f;
+ if(insertAveragePoint && (rootPatch.totalCount) > 1)
+ {
+ patch->nbContacts++;
+ PxVec3 avgPt(0.0f);
+ PxF32 avgPen(0.0f);
+ PxF32 recipCount = 1.0f/(PxF32(rootPatch.totalCount));
+ PxU32 index = a;
+
+ while(index != 0xFF)
+ {
+ StridePatch& p = stridePatches[index];
+ for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
+ {
+ avgPt += contactPoints[b].point;
+ avgPen += contactPoints[b].separation;
+ }
+ index = stridePatches[index].nextIndex;
+ }
+
+ if (faceIndice)
+ {
+ StridePatch& p = stridePatches[index];
+ *faceIndice = contactPoints[p.startIndex].internalFaceIndex1;
+ faceIndice++;
+ }
+ point->contact = avgPt * recipCount;
+ point->separation = avgPen * recipCount;
+
+ point++;
+ currentIndex++;
+ Ps::prefetchLine(point, 128);
+ }
+
+ PxU32 index = a;
+ while(index != 0xFF)
+ {
+ StridePatch& p = stridePatches[index];
+ for(PxU32 b = p.startIndex; b < p.endIndex; ++b)
+ {
+ copyContactPoint(point, &contactPoints[b]);
+ if (faceIndice)
+ {
+ *faceIndice = contactPoints[b].internalFaceIndex1;
+ faceIndice++;
+ }
+ point++;
+ currentIndex++;
+ Ps::prefetchLine(point, 128);
+ }
+ index = stridePatches[index].nextIndex;
+ }
+ }
+ }
+ }
+ }
+
+ writtenContactCount = Ps::to8(totalContactPoints);
+
+ return totalRequiredSize;
+}
+
+//ML: isMeshType is used in the GPU codepath. If the collision pair is mesh/heightfield vs primitives, we need to allocate enough memory for the mForceAndIndiceStreamPool in the threadContext.
+bool physx::finishContacts(PxcNpWorkUnit& input, PxsContactManagerOutput& npOutput, PxcNpThreadContext& threadContext, PxsMaterialInfo* PX_RESTRICT pMaterials, const bool isMeshType)
+{
+ ContactBuffer& buffer = threadContext.mContactBuffer;
+
+ PX_ASSERT((npOutput.statusFlag & PxsContactManagerStatusFlag::eTOUCH_KNOWN) != PxsContactManagerStatusFlag::eTOUCH_KNOWN);
+ PxU8 statusFlags = PxU16(npOutput.statusFlag & (~PxsContactManagerStatusFlag::eTOUCH_KNOWN));
+ if (buffer.count != 0)
+ statusFlags |= PxsContactManagerStatusFlag::eHAS_TOUCH;
+ else
+ statusFlags |= PxsContactManagerStatusFlag::eHAS_NO_TOUCH;
+
+ npOutput.nbContacts = Ps::to8(buffer.count);
+
+ if(buffer.count==0)
+ {
+ npOutput.statusFlag = statusFlags;
+ npOutput.nbContacts = 0;
+ npOutput.nbPatches = 0;
+ return true;
+ }
+
+
+#if PX_ENABLE_SIM_STATS
+ if(buffer.count)
+ threadContext.mNbDiscreteContactPairsWithContacts++;
+#endif
+
+ npOutput.statusFlag = statusFlags;
+
+ PxU32 contactForceByteSize = buffer.count * sizeof(PxReal);
+
+ //Regardless of the flags, we need to now record the compressed contact stream
+
+ PxU16 compressedContactSize;
+
+ const bool createReports =
+ input.flags & PxcNpWorkUnitFlag::eOUTPUT_CONTACTS
+ || threadContext.mCreateContactStream
+ || (input.flags & PxcNpWorkUnitFlag::eFORCE_THRESHOLD);
+
+ if (!buffer.count || (!isMeshType && !createReports))
+ {
+ contactForceByteSize = 0;
+ }
+
+ bool res = (writeCompressedContact(buffer.contacts, buffer.count, &threadContext, npOutput.nbContacts, npOutput.contactPatches, npOutput.contactPoints, compressedContactSize,
+ reinterpret_cast<PxReal*&>(npOutput.contactForces), contactForceByteSize, threadContext.mMaterialManager, ((input.flags & PxcNpWorkUnitFlag::eMODIFIABLE_CONTACT) != 0),
+ false, pMaterials, npOutput.nbPatches, 0, NULL, NULL, threadContext.mCreateAveragePoint, threadContext.mContactStreamPool,
+ threadContext.mPatchStreamPool, threadContext.mForceAndIndiceStreamPool, isMeshType) != 0) || (buffer.count == 0);
+
+ //handle buffer overflow
+ if (buffer.count && !npOutput.nbContacts)
+ {
+ PxU8 thisStatusFlags = PxU16(npOutput.statusFlag & (~PxsContactManagerStatusFlag::eTOUCH_KNOWN));
+ thisStatusFlags |= PxsContactManagerStatusFlag::eHAS_NO_TOUCH;
+
+ npOutput.statusFlag = thisStatusFlags;
+ npOutput.nbContacts = 0;
+ npOutput.nbPatches = 0;
+#if PX_ENABLE_SIM_STATS
+ if(buffer.count)
+ threadContext.mNbDiscreteContactPairsWithContacts--;
+#endif
+ }
+
+ return res;
+}
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp
new file mode 100644
index 00000000..51eb0110
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpMemBlockPool.cpp
@@ -0,0 +1,351 @@
+// 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/PxMath.h"
+#include "PxcNpMemBlockPool.h"
+#include "PsUserAllocated.h"
+#include "PsInlineArray.h"
+#include "PsFoundation.h"
+
+using namespace physx;
+
+PxcNpMemBlockPool::PxcNpMemBlockPool(PxcScratchAllocator& allocator):
+ mConstraints(PX_DEBUG_EXP("PxcNpMemBlockPool::mConstraints")),
+ mExceptionalConstraints(PX_DEBUG_EXP("PxcNpMemBlockPool::mExceptionalConstraints")),
+ mNpCacheActiveStream(0),
+ mFrictionActiveStream(0),
+ mCCDCacheActiveStream(0),
+ mContactIndex(0),
+ mAllocatedBlocks(0),
+ mMaxBlocks(0),
+ mUsedBlocks(0),
+ mMaxUsedBlocks(0),
+ mScratchBlockAddr(0),
+ mNbScratchBlocks(0),
+ mScratchAllocator(allocator),
+ mPeakConstraintAllocations(0),
+ mConstraintAllocations(0)
+{
+}
+
+void PxcNpMemBlockPool::init(PxU32 initialBlockCount, PxU32 maxBlocks)
+{
+ mMaxBlocks = maxBlocks;
+ mInitialBlocks = initialBlockCount;
+
+ PxU32 reserve = PxMax<PxU32>(initialBlockCount, 64);
+
+ mConstraints.reserve(reserve);
+ mExceptionalConstraints.reserve(16);
+
+ mFriction[0].reserve(reserve);
+ mFriction[1].reserve(reserve);
+ mNpCache[0].reserve(reserve);
+ mNpCache[1].reserve(reserve);
+ mUnused.reserve(reserve);
+
+ setBlockCount(initialBlockCount);
+}
+
+PxU32 PxcNpMemBlockPool::getUsedBlockCount() const
+{
+ return mUsedBlocks;
+}
+
+PxU32 PxcNpMemBlockPool::getMaxUsedBlockCount() const
+{
+ return mMaxUsedBlocks;
+}
+
+PxU32 PxcNpMemBlockPool::getPeakConstraintBlockCount() const
+{
+ return mPeakConstraintAllocations;
+}
+
+
+void PxcNpMemBlockPool::setBlockCount(PxU32 blockCount)
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+ PxU32 current = getUsedBlockCount();
+ for(PxU32 i=current;i<blockCount;i++)
+ {
+ mUnused.pushBack(reinterpret_cast<PxcNpMemBlock *>(PX_ALLOC(PxcNpMemBlock::SIZE, "PxcNpMemBlock")));
+ mAllocatedBlocks++;
+ }
+}
+
+void PxcNpMemBlockPool::releaseUnusedBlocks()
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+ while(mUnused.size())
+ {
+ PX_FREE(mUnused.popBack());
+ mAllocatedBlocks--;
+ }
+}
+
+
+PxcNpMemBlockPool::~PxcNpMemBlockPool()
+{
+ // swapping twice guarantees all blocks are released from the stream pairs
+ swapFrictionStreams();
+ swapFrictionStreams();
+
+ swapNpCacheStreams();
+ swapNpCacheStreams();
+
+ releaseConstraintMemory();
+ releaseContacts();
+ releaseContacts();
+
+ PX_ASSERT(mUsedBlocks == 0);
+
+ flushUnused();
+}
+
+void PxcNpMemBlockPool::acquireConstraintMemory()
+{
+ PxU32 size;
+ void* addr = mScratchAllocator.allocAll(size);
+ size = size&~(PxcNpMemBlock::SIZE-1);
+
+ PX_ASSERT(mScratchBlocks.size()==0);
+ mScratchBlockAddr = reinterpret_cast<PxcNpMemBlock*>(addr);
+ mNbScratchBlocks = size/PxcNpMemBlock::SIZE;
+
+ mScratchBlocks.resize(mNbScratchBlocks);
+ for(PxU32 i=0;i<mNbScratchBlocks;i++)
+ mScratchBlocks[i] = mScratchBlockAddr+i;
+}
+
+void PxcNpMemBlockPool::releaseConstraintMemory()
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+
+ mPeakConstraintAllocations = mConstraintAllocations = 0;
+
+ while(mConstraints.size())
+ {
+ PxcNpMemBlock* block = mConstraints.popBack();
+ if(mScratchAllocator.isScratchAddr(block))
+ mScratchBlocks.pushBack(block);
+ else
+ {
+ mUnused.pushBack(block);
+ PX_ASSERT(mUsedBlocks>0);
+ mUsedBlocks--;
+ }
+ }
+
+ for(PxU32 i=0;i<mExceptionalConstraints.size();i++)
+ PX_FREE(mExceptionalConstraints[i]);
+ mExceptionalConstraints.clear();
+
+ PX_ASSERT(mScratchBlocks.size()==mNbScratchBlocks); // check we released them all
+ mScratchBlocks.clear();
+
+ if(mScratchBlockAddr)
+ {
+ mScratchAllocator.free(mScratchBlockAddr);
+ mScratchBlockAddr = 0;
+ mNbScratchBlocks = 0;
+ }
+}
+
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquire(PxcNpMemBlockArray& trackingArray, PxU32* allocationCount, PxU32* peakAllocationCount, bool isScratchAllocation)
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+ if(allocationCount && peakAllocationCount)
+ {
+ *peakAllocationCount = PxMax(*allocationCount + 1, *peakAllocationCount);
+ (*allocationCount)++;
+ }
+
+ // this is a bit of hack - the logic would be better placed in acquireConstraintBlock, but then we'd have to grab the mutex
+ // once there to check the scratch block array and once here if we fail - or, we'd need a larger refactor to separate out
+ // locking and acquisition.
+
+ if(isScratchAllocation && mScratchBlocks.size()>0)
+ {
+ PxcNpMemBlock* block = mScratchBlocks.popBack();
+ trackingArray.pushBack(block);
+ return block;
+ }
+
+
+ if(mUnused.size())
+ {
+ PxcNpMemBlock* block = mUnused.popBack();
+ trackingArray.pushBack(block);
+ mMaxUsedBlocks = PxMax<PxU32>(mUsedBlocks+1, mMaxUsedBlocks);
+ mUsedBlocks++;
+ return block;
+ }
+
+
+ if(mAllocatedBlocks == mMaxBlocks)
+ {
+#if PX_CHECKED
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "Reached maximum number of allocated blocks so 16k block allocation will fail!");
+#endif
+ return NULL;
+ }
+
+#if PX_CHECKED
+ if(mInitialBlocks)
+ {
+ Ps::getFoundation().error(PxErrorCode::eDEBUG_WARNING, __FILE__, __LINE__,
+ "Number of required 16k memory blocks has exceeded the initial number of blocks. Allocator is being called. Consider increasing the number of pre-allocated 16k blocks.");
+ }
+#endif
+
+ // increment here so that if we hit the limit in separate threads we won't overallocated
+ mAllocatedBlocks++;
+
+ PxcNpMemBlock* block = reinterpret_cast<PxcNpMemBlock*>(PX_ALLOC(sizeof(PxcNpMemBlock), "PxcNpMemBlock"));
+
+ if(block)
+ {
+ trackingArray.pushBack(block);
+ mMaxUsedBlocks = PxMax<PxU32>(mUsedBlocks+1, mMaxUsedBlocks);
+ mUsedBlocks++;
+ }
+ else
+ mAllocatedBlocks--;
+
+ return block;
+}
+
+PxU8* PxcNpMemBlockPool::acquireExceptionalConstraintMemory(PxU32 size)
+{
+ PxU8* memory = reinterpret_cast<PxU8*>(PX_ALLOC(size, "PxcNpExceptionalMemory"));
+ if(memory)
+ {
+ Ps::Mutex::ScopedLock lock(mLock);
+ mExceptionalConstraints.pushBack(memory);
+ }
+ return memory;
+}
+
+void PxcNpMemBlockPool::release(PxcNpMemBlockArray& deadArray, PxU32* allocationCount)
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+ PX_ASSERT(mUsedBlocks >= deadArray.size());
+ mUsedBlocks -= deadArray.size();
+ if(allocationCount)
+ {
+ *allocationCount -= deadArray.size();
+ }
+ while(deadArray.size())
+ {
+ PxcNpMemBlock* block = deadArray.popBack();
+ for(PxU32 a = 0; a < mUnused.size(); ++a)
+ {
+ PX_ASSERT(mUnused[a] != block);
+ }
+ mUnused.pushBack(block);
+ }
+}
+
+void PxcNpMemBlockPool::flushUnused()
+{
+ while(mUnused.size())
+ PX_FREE(mUnused.popBack());
+}
+
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquireConstraintBlock()
+{
+ // we track the scratch blocks in the constraint block array, because the code in acquireMultipleConstraintBlocks
+ // assumes that acquired blocks are listed there.
+
+ return acquire(mConstraints);
+}
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquireConstraintBlock(PxcNpMemBlockArray& memBlocks)
+{
+ return acquire(memBlocks, &mConstraintAllocations, &mPeakConstraintAllocations, true);
+}
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquireContactBlock()
+{
+ return acquire(mContacts[mContactIndex], NULL, NULL, true);
+}
+
+
+void PxcNpMemBlockPool::releaseConstraintBlocks(PxcNpMemBlockArray& memBlocks)
+{
+ Ps::Mutex::ScopedLock lock(mLock);
+
+ while(memBlocks.size())
+ {
+ PxcNpMemBlock* block = memBlocks.popBack();
+ if(mScratchAllocator.isScratchAddr(block))
+ mScratchBlocks.pushBack(block);
+ else
+ {
+ mUnused.pushBack(block);
+ PX_ASSERT(mUsedBlocks>0);
+ mUsedBlocks--;
+ }
+ }
+}
+
+void PxcNpMemBlockPool::releaseContacts()
+{
+ //releaseConstraintBlocks(mContacts);
+ release(mContacts[1-mContactIndex]);
+ mContactIndex = 1-mContactIndex;
+}
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquireFrictionBlock()
+{
+ return acquire(mFriction[mFrictionActiveStream]);
+}
+
+void PxcNpMemBlockPool::swapFrictionStreams()
+{
+ release(mFriction[1-mFrictionActiveStream]);
+ mFrictionActiveStream = 1-mFrictionActiveStream;
+}
+
+PxcNpMemBlock* PxcNpMemBlockPool::acquireNpCacheBlock()
+{
+ return acquire(mNpCache[mNpCacheActiveStream]);
+}
+
+void PxcNpMemBlockPool::swapNpCacheStreams()
+{
+ release(mNpCache[1-mNpCacheActiveStream]);
+ mNpCacheActiveStream = 1-mNpCacheActiveStream;
+}
+
diff --git a/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpThreadContext.cpp b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpThreadContext.cpp
new file mode 100644
index 00000000..9738e5da
--- /dev/null
+++ b/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcNpThreadContext.cpp
@@ -0,0 +1,93 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as critical
+// components in life support devices or systems without express written approval of
+// NVIDIA Corporation.
+//
+// Copyright (c) 2008-2016 NVIDIA Corporation. All rights reserved.
+// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
+// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
+
+#include "PxcConstraintBlockStream.h"
+#include "PxcNpThreadContext.h"
+
+using namespace physx;
+
+PxcNpThreadContext::PxcNpThreadContext(PxcNpContext* params) :
+ mRenderOutput (params->mRenderBuffer),
+ mContactBlockStream (params->mNpMemBlockPool),
+ mNpCacheStreamPair (params->mNpMemBlockPool),
+ mNarrowPhaseParams (0.0f, params->mMeshContactMargin, params->mToleranceLength),
+ mPCM (false),
+ mContactCache (false),
+ mCreateContactStream (params->mCreateContactStream),
+ mCreateAveragePoint (false),
+#if PX_ENABLE_SIM_STATS
+ mCompressedCacheSize (0),
+ mNbDiscreteContactPairsWithCacheHits(0),
+ mNbDiscreteContactPairsWithContacts (0),
+#endif
+ mMaxPatches (0),
+ mTotalCompressedCacheSize (0),
+ mContactStreamPool (params->mContactStreamPool),
+ mPatchStreamPool (params->mPatchStreamPool),
+ mForceAndIndiceStreamPool (params->mForceAndIndiceStreamPool),
+ mMaterialManager(params->mMaterialManager),
+ mLocalNewTouchCount (0),
+ mLocalLostTouchCount (0),
+ mLocalFoundPatchCount (0),
+ mLocalLostPatchCount (0)
+{
+#if PX_ENABLE_SIM_STATS
+ clearStats();
+#endif
+}
+
+PxcNpThreadContext::~PxcNpThreadContext()
+{
+}
+
+#if PX_ENABLE_SIM_STATS
+void PxcNpThreadContext::clearStats()
+{
+ PxMemSet(mDiscreteContactPairs, 0, sizeof(mDiscreteContactPairs));
+ PxMemSet(mModifiedContactPairs, 0, sizeof(mModifiedContactPairs));
+ mCompressedCacheSize = 0;
+ mNbDiscreteContactPairsWithCacheHits = 0;
+ mNbDiscreteContactPairsWithContacts = 0;
+}
+#endif
+
+void PxcNpThreadContext::reset(PxU32 cmCount)
+{
+ mContactBlockStream.reset();
+ mNpCacheStreamPair.reset();
+
+ mLocalChangeTouch.clear();
+ mLocalChangeTouch.resize(cmCount);
+ mLocalPatchCountChange.clear();
+ mLocalPatchCountChange.resize(cmCount);
+ mLocalNewTouchCount = 0;
+ mLocalLostTouchCount = 0;
+ mLocalFoundPatchCount = 0;
+ mLocalLostPatchCount = 0;
+}