aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexCommon.h
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/GeomUtils/src/pcm/GuPCMContactConvexCommon.h
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/GeomUtils/src/pcm/GuPCMContactConvexCommon.h')
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexCommon.h419
1 files changed, 419 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexCommon.h b/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexCommon.h
new file mode 100644
index 00000000..c2af8d6f
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexCommon.h
@@ -0,0 +1,419 @@
+// This code contains NVIDIA Confidential Information and is disclosed to you
+// under a form of NVIDIA software license agreement provided separately to you.
+//
+// Notice
+// NVIDIA Corporation and its licensors retain all intellectual property and
+// proprietary rights in and to this software and related documentation and
+// any modifications thereto. Any use, reproduction, disclosure, or
+// distribution of this software and related documentation without an express
+// license agreement from NVIDIA Corporation is strictly prohibited.
+//
+// ALL NVIDIA DESIGN SPECIFICATIONS, CODE ARE PROVIDED "AS IS.". NVIDIA MAKES
+// NO WARRANTIES, EXPRESSED, IMPLIED, STATUTORY, OR OTHERWISE WITH RESPECT TO
+// THE MATERIALS, AND EXPRESSLY DISCLAIMS ALL IMPLIED WARRANTIES OF NONINFRINGEMENT,
+// MERCHANTABILITY, AND FITNESS FOR A PARTICULAR PURPOSE.
+//
+// Information and code furnished is believed to be accurate and reliable.
+// However, NVIDIA Corporation assumes no responsibility for the consequences of use of such
+// information or for any infringement of patents or other rights of third parties that may
+// result from its use. No license is granted by implication or otherwise under any patent
+// or patent rights of NVIDIA Corporation. Details are subject to change without notice.
+// This code supersedes and replaces all information previously supplied.
+// NVIDIA Corporation products are not authorized for use as 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 GU_PCM_CONTACT_CONVEX_COMMON_H
+#define GU_PCM_CONTACT_CONVEX_COMMON_H
+
+#define PCM_MAX_CONTACTPATCH_SIZE 32
+
+#include "GuContactBuffer.h"
+#include "GuVecCapsule.h"
+#include "GuPCMTriangleContactGen.h"
+#include "PsInlineArray.h"
+#include "GuTriangleCache.h"
+
+namespace physx
+{
+
+namespace Gu
+{
+
+class PCMMeshContactGeneration
+{
+ PX_NOCOPY(PCMMeshContactGeneration)
+public:
+ PCMContactPatch mContactPatch[PCM_MAX_CONTACTPATCH_SIZE];
+ PCMContactPatch* mContactPatchPtr[PCM_MAX_CONTACTPATCH_SIZE];
+ const Ps::aos::FloatV mContactDist;
+ const Ps::aos::FloatV mReplaceBreakingThreshold;
+ const Ps::aos::PsTransformV& mConvexTransform;
+ const Ps::aos::PsTransformV& mMeshTransform;
+ Gu::MultiplePersistentContactManifold& mMultiManifold;
+ Gu::ContactBuffer& mContactBuffer;
+
+ Ps::aos::FloatV mAcceptanceEpsilon;
+ Ps::aos::FloatV mSqReplaceBreakingThreshold;
+ Ps::aos::PsMatTransformV mMeshToConvex;
+ Gu::MeshPersistentContact* mManifoldContacts;
+ PxU32 mNumContacts;
+ PxU32 mNumContactPatch;
+ PxU32 mNumCalls;
+ Cm::RenderOutput* mRenderOutput;
+
+ PCMMeshContactGeneration(
+ const Ps::aos::FloatVArg contactDist,
+ const Ps::aos::FloatVArg replaceBreakingThreshold,
+ const Ps::aos::PsTransformV& convexTransform,
+ const Ps::aos::PsTransformV& meshTransform,
+ Gu::MultiplePersistentContactManifold& multiManifold,
+ Gu::ContactBuffer& contactBuffer,
+ Cm::RenderOutput* renderOutput
+
+ ) :
+ mContactDist(contactDist),
+ mReplaceBreakingThreshold(replaceBreakingThreshold),
+ mConvexTransform(convexTransform),
+ mMeshTransform(meshTransform),
+ mMultiManifold(multiManifold),
+ mContactBuffer(contactBuffer),
+ mRenderOutput(renderOutput)
+
+ {
+ using namespace Ps::aos;
+ mNumContactPatch = 0;
+ mNumContacts = 0;
+ mNumCalls = 0;
+
+ mMeshToConvex = mConvexTransform.transformInv(mMeshTransform);
+
+ //Assign the PCMContactPatch to the PCMContactPathPtr
+ for(PxU32 i=0; i<PCM_MAX_CONTACTPATCH_SIZE; ++i)
+ {
+ mContactPatchPtr[i] = &mContactPatch[i];
+ }
+ mManifoldContacts = PX_CP_TO_MPCP(contactBuffer.contacts);
+
+ mSqReplaceBreakingThreshold = FMul(replaceBreakingThreshold, replaceBreakingThreshold);
+
+ mAcceptanceEpsilon = FLoad(0.996);//5 degree
+ //mAcceptanceEpsilon = FloatV_From_F32(0.9999);//5 degree
+ }
+
+ template <PxU32 TriangleCount, typename Derived>
+ bool processTriangleCache(Gu::TriangleCache<TriangleCount>& cache)
+ {
+ PxU32 count = cache.mNumTriangles;
+ PxVec3* verts = cache.mVertices;
+ PxU32* vertInds = cache.mIndices;
+ PxU32* triInds = cache.mTriangleIndex;
+ PxU8* edgeFlags = cache.mEdgeFlags;
+ while(count--)
+ {
+ (static_cast<Derived*>(this))->processTriangle(verts, *triInds, *edgeFlags, vertInds);
+ verts += 3;
+ vertInds += 3;
+ triInds++;
+ edgeFlags++;
+ }
+ return true;
+ }
+ void prioritizeContactPatches();
+ void addManifoldPointToPatch(const Ps::aos::Vec3VArg currentPatchNormal, const Ps::aos::FloatVArg maxPen, const PxU32 previousNumContacts);
+ void processContacts(const PxU8 maxContactPerManifold, const bool isNotLastPatch = true);
+};
+
+/*
+ This function is based on the current patch normal to either create a new patch or merge the manifold contacts in this patch with the manifold contacts in the last existing
+ patch. This means there might be more than GU_SINGLE_MANIFOLD_CACHE_SIZE in a SinglePersistentContactManifold.
+*/
+PX_FORCE_INLINE void PCMMeshContactGeneration::addManifoldPointToPatch(const Ps::aos::Vec3VArg currentPatchNormal, const Ps::aos::FloatVArg maxPen, const PxU32 previousNumContacts)
+{
+ using namespace Ps::aos;
+
+ bool foundPatch = false;
+ //we have existing patch
+ if(mNumContactPatch > 0)
+ {
+ //if the direction between the last existing patch normal and the current patch normal are within acceptance epsilon, which means we will be
+ //able to merge the last patch's contacts with the current patch's contacts. This is just to avoid to create an extra patch. We have some logic
+ //later to refine the patch again
+ if(FAllGrtr(V3Dot(mContactPatch[mNumContactPatch-1].mPatchNormal, currentPatchNormal), mAcceptanceEpsilon))
+ {
+ //get the last patch
+ PCMContactPatch& patch = mContactPatch[mNumContactPatch-1];
+
+ //remove duplicate contacts
+ for(PxU32 i = patch.mStartIndex; i<patch.mEndIndex; ++i)
+ {
+ for(PxU32 j = previousNumContacts; j<mNumContacts; ++j)
+ {
+ Vec3V dif = V3Sub(mManifoldContacts[j].mLocalPointB, mManifoldContacts[i].mLocalPointB);
+ FloatV d = V3Dot(dif, dif);
+ if(FAllGrtr(mSqReplaceBreakingThreshold, d))
+ {
+ if(FAllGrtr(V4GetW(mManifoldContacts[i].mLocalNormalPen), V4GetW(mManifoldContacts[j].mLocalNormalPen)))
+ {
+ //The new contact is deeper than the old contact so we keep the deeper contact
+ mManifoldContacts[i] = mManifoldContacts[j];
+ }
+ mManifoldContacts[j] = mManifoldContacts[mNumContacts-1];
+ mNumContacts--;
+ j--;
+ }
+ }
+ }
+ patch.mEndIndex = mNumContacts;
+ patch.mPatchMaxPen = FMin(patch.mPatchMaxPen, maxPen);
+ foundPatch = true;
+ }
+ }
+
+ //If there are no existing patch which match the currentPatchNormal, we will create a new patch
+ if(!foundPatch)
+ {
+ mContactPatch[mNumContactPatch].mStartIndex = previousNumContacts;
+ mContactPatch[mNumContactPatch].mEndIndex = mNumContacts;
+ mContactPatch[mNumContactPatch].mPatchMaxPen = maxPen;
+ mContactPatch[mNumContactPatch++].mPatchNormal = currentPatchNormal;
+ }
+}
+
+/*
+ This function sort the contact patch based on the max penetration so that deepest penetration contact patch will be in front of the less penetration contact
+ patch
+*/
+PX_FORCE_INLINE void PCMMeshContactGeneration::prioritizeContactPatches()
+{
+ //we are using insertion sort to prioritize contact patchs
+ using namespace Ps::aos;
+ //sort the contact patch based on the max penetration
+ for(PxU32 i=1; i<mNumContactPatch; ++i)
+ {
+ const PxU32 indexi = i-1;
+ if(FAllGrtr(mContactPatchPtr[indexi]->mPatchMaxPen, mContactPatchPtr[i]->mPatchMaxPen))
+ {
+ //swap
+ PCMContactPatch* tmp = mContactPatchPtr[indexi];
+ mContactPatchPtr[indexi] = mContactPatchPtr[i];
+ mContactPatchPtr[i] = tmp;
+
+ for(PxI32 j=PxI32(i-2); j>=0; j--)
+ {
+ const PxU32 indexj = PxU32(j+1);
+ if(FAllGrtrOrEq(mContactPatchPtr[indexj]->mPatchMaxPen, mContactPatchPtr[j]->mPatchMaxPen))
+ break;
+ //swap
+ PCMContactPatch* temp = mContactPatchPtr[indexj];
+ mContactPatchPtr[indexj] = mContactPatchPtr[j];
+ mContactPatchPtr[j] = temp;
+ }
+ }
+ }
+}
+
+
+PX_FORCE_INLINE void PCMMeshContactGeneration::processContacts(const PxU8 maxContactPerManifold, bool isNotLastPatch)
+{
+ using namespace Ps::aos;
+
+ if(mNumContacts != 0)
+ {
+ //reorder the contact patches based on the max penetration
+ prioritizeContactPatches();
+ //connect the patches which's angle between patch normals are within 5 degree
+ mMultiManifold.refineContactPatchConnective(mContactPatchPtr, mNumContactPatch, mManifoldContacts, mAcceptanceEpsilon);
+ //get rid of duplicate manifold contacts in connected contact patches
+ mMultiManifold.reduceManifoldContactsInDifferentPatches(mContactPatchPtr, mNumContactPatch, mManifoldContacts, mNumContacts, mSqReplaceBreakingThreshold);
+ //add the manifold contact to the corresponding manifold
+ mMultiManifold.addManifoldContactPoints(mManifoldContacts, mNumContacts, mContactPatchPtr, mNumContactPatch, mSqReplaceBreakingThreshold, mAcceptanceEpsilon, maxContactPerManifold);
+
+ mNumContacts = 0;
+ mNumContactPatch = 0;
+
+ if(isNotLastPatch)
+ {
+ //remap the contact patch pointer to contact patch
+ for(PxU32 i=0; i<PCM_MAX_CONTACTPATCH_SIZE; ++i)
+ {
+ mContactPatchPtr[i] = &mContactPatch[i];
+ }
+ }
+ }
+}
+
+struct PCMDeferredPolyData
+{
+public:
+ PxVec3 mVerts[3]; //36
+ PxU32 mInds[3]; //48
+ PxU32 mTriangleIndex; //52
+ PxU32 mFeatureIndex; //56
+ PxU8 triFlags; //57
+};
+
+#define MAX_CACHE_SIZE 128
+
+#if PX_VC
+ #pragma warning(push)
+ #pragma warning( disable : 4324 ) // Padding was added at the end of a structure because of a __declspec(align) value.
+#endif
+
+class PCMConvexVsMeshContactGeneration : public PCMMeshContactGeneration
+{
+ PCMConvexVsMeshContactGeneration &operator=(PCMConvexVsMeshContactGeneration &);
+
+public:
+
+ Gu::CacheMap<Gu::CachedEdge, MAX_CACHE_SIZE> mEdgeCache;
+ Gu::CacheMap<Gu::CachedVertex, MAX_CACHE_SIZE> mVertexCache;
+ Ps::aos::Vec3V mHullCenterMesh;
+
+ Ps::InlineArray<PxU32,LOCAL_CONTACTS_SIZE>& mDeferredContacts;
+ const Gu::PolygonalData& mPolyData;
+ SupportLocal* mPolyMap;
+ const Cm::FastVertex2ShapeScaling& mConvexScaling;
+ bool mIdtConvexScale;
+ Cm::RenderOutput* mRenderOutput;
+
+
+ PCMConvexVsMeshContactGeneration(
+ const Ps::aos::FloatVArg contactDistance,
+ const Ps::aos::FloatVArg replaceBreakingThreshold,
+ const Ps::aos::PsTransformV& convexTransform,
+ const Ps::aos::PsTransformV& meshTransform,
+ Gu::MultiplePersistentContactManifold& multiManifold,
+ Gu::ContactBuffer& contactBuffer,
+
+ const Gu::PolygonalData& polyData,
+ SupportLocal* polyMap,
+ Ps::InlineArray<PxU32,LOCAL_CONTACTS_SIZE>& delayedContacts,
+ const Cm::FastVertex2ShapeScaling& convexScaling,
+ bool idtConvexScale,
+ Cm::RenderOutput* renderOutput
+
+ ) : PCMMeshContactGeneration(contactDistance, replaceBreakingThreshold, convexTransform, meshTransform, multiManifold, contactBuffer, renderOutput),
+ mDeferredContacts(delayedContacts),
+ mPolyData(polyData),
+ mPolyMap(polyMap),
+ mConvexScaling(convexScaling),
+ mIdtConvexScale(idtConvexScale),
+ mRenderOutput(renderOutput)
+ {
+ using namespace Ps::aos;
+
+ // Hull center in local space
+ const Vec3V hullCenterLocal = V3LoadU(mPolyData.mCenter);
+ // Hull center in mesh space
+ mHullCenterMesh = mMeshToConvex.transformInv(hullCenterLocal);
+
+ }
+
+ bool generateTriangleFullContactManifold(Gu::TriangleV& localTriangle, const PxU32 triangleIndex, const PxU32* triIndices, const PxU8 triFlags, const Gu::PolygonalData& polyData, Gu::SupportLocalImpl<Gu::TriangleV>* localTriMap, Gu::SupportLocal* polyMap, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts,
+ const Ps::aos::FloatVArg contactDist, Ps::aos::Vec3V& patchNormal);
+
+ bool generatePolyDataContactManifold(Gu::TriangleV& localTriangle, const PxU32 featureIndex, const PxU32 triangleIndex, const PxU8 triFlags, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts, const Ps::aos::FloatVArg contactDist, Ps::aos::Vec3V& patchNormal);
+ void generateLastContacts();
+ void addContactsToPatch(const Ps::aos::Vec3VArg patchNormal, const PxU32 previousNumContacts);
+
+ bool processTriangle(const PxVec3* verts, PxU32 triangleIndex, PxU8 triFlags, const PxU32* vertInds);
+
+ static bool generateTriangleFullContactManifold(Gu::TriangleV& localTriangle, const PxU32 triangleIndex, const PxU8 triFlags, const Gu::PolygonalData& polyData, Gu::SupportLocalImpl<Gu::TriangleV>* localTriMap, Gu::SupportLocal* polyMap, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts,
+ const Ps::aos::FloatVArg contactDist, Ps::aos::Vec3V& patchNormal, Cm::RenderOutput* renderOutput = NULL);
+
+ static bool processTriangle(const Gu::PolygonalData& polyData, SupportLocal* polyMap, const PxVec3* verts, const PxU32 triangleIndex, PxU8 triFlags, const Ps::aos::FloatVArg inflation, const bool isDoubleSided,
+ const Ps::aos::PsTransformV& convexTransform, const Ps::aos::PsMatTransformV& meshToConvex, Gu::MeshPersistentContact* manifoldContact, PxU32& numContacts);
+};
+
+#if PX_VC
+ #pragma warning(pop)
+#endif
+
+class PCMSphereVsMeshContactGeneration : public PCMMeshContactGeneration
+{
+public:
+ Ps::aos::Vec3V mSphereCenter;
+ Ps::aos::FloatV mSphereRadius;
+ Ps::aos::FloatV mSqInflatedSphereRadius;
+
+
+ PCMSphereVsMeshContactGeneration(
+ const Ps::aos::Vec3VArg sphereCenter,
+ const Ps::aos::FloatVArg sphereRadius,
+ const Ps::aos::FloatVArg contactDist,
+ const Ps::aos::FloatVArg replaceBreakingThreshold,
+ const Ps::aos::PsTransformV& sphereTransform,
+ const Ps::aos::PsTransformV& meshTransform,
+ Gu::MultiplePersistentContactManifold& multiManifold,
+ Gu::ContactBuffer& contactBuffer,
+ Cm::RenderOutput* renderOutput = NULL
+
+ ) : PCMMeshContactGeneration(contactDist, replaceBreakingThreshold, sphereTransform, meshTransform, multiManifold, contactBuffer, renderOutput),
+ mSphereCenter(sphereCenter),
+ mSphereRadius(sphereRadius)
+ {
+ using namespace Ps::aos;
+ const FloatV inflatedSphereRadius = FAdd(sphereRadius, contactDist);
+ mSqInflatedSphereRadius = FMul(inflatedSphereRadius, inflatedSphereRadius);
+ }
+
+
+ bool processTriangle(const PxVec3* verts, PxU32 triangleIndex, PxU8 triFlags, const PxU32* vertInds);
+};
+
+class PCMCapsuleVsMeshContactGeneration : public PCMMeshContactGeneration
+{
+ PCMCapsuleVsMeshContactGeneration &operator=(PCMCapsuleVsMeshContactGeneration &);
+public:
+ Ps::aos::FloatV mInflatedRadius;
+ Ps::aos::FloatV mSqInflatedRadius;
+ const CapsuleV& mCapsule;
+
+
+ PCMCapsuleVsMeshContactGeneration(
+ const CapsuleV& capsule,
+ const Ps::aos::FloatVArg contactDist,
+ const Ps::aos::FloatVArg replaceBreakingThreshold,
+ const Ps::aos::PsTransformV& sphereTransform,
+ const Ps::aos::PsTransformV& meshTransform,
+ Gu::MultiplePersistentContactManifold& multiManifold,
+ Gu::ContactBuffer& contactBuffer,
+ Cm::RenderOutput* renderOutput = NULL
+
+ ) : PCMMeshContactGeneration(contactDist, replaceBreakingThreshold, sphereTransform, meshTransform, multiManifold, contactBuffer, renderOutput),
+ mCapsule(capsule)
+ {
+ using namespace Ps::aos;
+ mInflatedRadius = FAdd(capsule.radius, contactDist);
+ mSqInflatedRadius = FMul(mInflatedRadius, mInflatedRadius);
+ }
+
+ void generateEEContacts(const Ps::aos::Vec3VArg a, const Ps::aos::Vec3VArg b,const Ps::aos::Vec3VArg c, const Ps::aos::Vec3VArg normal, const PxU32 triangleIndex,
+ const Ps::aos::Vec3VArg p, const Ps::aos::Vec3VArg q, const Ps::aos::FloatVArg sqInflatedRadius, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
+
+ void generateEE(const Ps::aos::Vec3VArg p, const Ps::aos::Vec3VArg q, const Ps::aos::FloatVArg sqInflatedRadius, const Ps::aos::Vec3VArg normal, const PxU32 triangleIndex,
+ const Ps::aos::Vec3VArg a, const Ps::aos::Vec3VArg b, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
+
+ static bool generateContacts(const Ps::aos::Vec3VArg a, const Ps::aos::Vec3VArg b,const Ps::aos::Vec3VArg c, const Ps::aos::Vec3VArg planeNormal, const Ps::aos::Vec3VArg normal,
+ const PxU32 triangleIndex, const Ps::aos::Vec3VArg p, const Ps::aos::Vec3VArg q, const Ps::aos::FloatVArg inflatedRadius, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
+
+ static void generateEEContactsMTD(const Ps::aos::Vec3VArg a, const Ps::aos::Vec3VArg b,const Ps::aos::Vec3VArg c, const Ps::aos::Vec3VArg normal, const PxU32 triangleIndex,
+ const Ps::aos::Vec3VArg p, const Ps::aos::Vec3VArg q, const Ps::aos::FloatVArg inflatedRadius, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
+
+ static void generateEEMTD(const Ps::aos::Vec3VArg p, const Ps::aos::Vec3VArg q, const Ps::aos::FloatVArg inflatedRadius, const Ps::aos::Vec3VArg normal, const PxU32 trianlgeIndex,
+ const Ps::aos::Vec3VArg a, const Ps::aos::Vec3VArg b, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
+
+ bool processTriangle(const PxVec3* verts, const PxU32 triangleIndex, PxU8 triFlags, const PxU32* vertInds);
+
+ static bool processTriangle(const TriangleV& triangle, const PxU32 triangleIndex, const CapsuleV& capsule, const Ps::aos::FloatVArg inflatedRadius, const PxU8 triFlag, Gu::MeshPersistentContact* manifoldContacts, PxU32& numContacts);
+};
+
+}
+}
+
+#endif