aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactCache.cpp
diff options
context:
space:
mode:
authorgit perforce import user <a@b>2016-10-25 12:29:14 -0600
committerSheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees>2016-10-25 18:56:37 -0500
commit3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch)
treefa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactCache.cpp
downloadphysx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.tar.xz
physx-3.4-3dfe2108cfab31ba3ee5527e217d0d8e99a51162.zip
Initial commit:
PhysX 3.4.0 Update @ 21294896 APEX 1.4.0 Update @ 21275617 [CL 21300167]
Diffstat (limited to 'PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactCache.cpp')
-rw-r--r--PhysX_3.4/Source/LowLevel/common/src/pipeline/PxcContactCache.cpp393
1 files changed, 393 insertions, 0 deletions
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;
+}