diff options
Diffstat (limited to 'PhysX_3.4/Source/LowLevel/common')
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; +} |