aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexConvex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexConvex.cpp')
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexConvex.cpp310
1 files changed, 310 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexConvex.cpp b/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexConvex.cpp
new file mode 100644
index 00000000..4d0fd351
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactConvexConvex.cpp
@@ -0,0 +1,310 @@
+// 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 "GuGJKPenetration.h"
+#include "GuEPA.h"
+#include "GuVecConvexHull.h"
+#include "GuVecShrunkConvexHull.h"
+#include "GuVecShrunkConvexHullNoScale.h"
+#include "GuVecConvexHullNoScale.h"
+#include "GuGeometryUnion.h"
+
+#include "GuContactMethodImpl.h"
+#include "GuPCMShapeConvex.h"
+#include "GuPCMContactGen.h"
+#include "GuContactBuffer.h"
+
+namespace physx
+{
+
+ using namespace Ps::aos;
+
+namespace Gu
+{
+
+static bool fullContactsGenerationConvexConvex(const ConvexHullV& convexHull0, Gu::ConvexHullV& convexHull1, const PsTransformV& transf0, const PsTransformV& transf1,
+ const bool idtScale0, const bool idtScale1, PersistentContact* manifoldContacts, ContactBuffer& contactBuffer,
+ PersistentContactManifold& manifold, Vec3VArg normal, const Vec3VArg closestA, const Vec3VArg closestB,
+ const FloatVArg contactDist, const bool doOverlapTest, Cm::RenderOutput* renderOutput, const FloatVArg toleranceScale)
+{
+ Gu::PolygonalData polyData0, polyData1;
+ getPCMConvexData(convexHull0, idtScale0, polyData0);
+ getPCMConvexData(convexHull1, idtScale1, polyData1);
+
+ PxU8 buff0[sizeof(SupportLocalImpl<ConvexHullV>)];
+ PxU8 buff1[sizeof(SupportLocalImpl<ConvexHullV>)];
+
+ SupportLocal* map0 = (idtScale0 ? static_cast<SupportLocal*>(PX_PLACEMENT_NEW(buff0, SupportLocalImpl<ConvexHullNoScaleV>)(static_cast<const ConvexHullNoScaleV&>(convexHull0), transf0, convexHull0.vertex2Shape, convexHull0.shape2Vertex, idtScale0)) :
+ static_cast<SupportLocal*>(PX_PLACEMENT_NEW(buff0, SupportLocalImpl<ConvexHullV>)(convexHull0, transf0, convexHull0.vertex2Shape, convexHull0.shape2Vertex, idtScale0)));
+
+ SupportLocal* map1 = (idtScale1 ? static_cast<SupportLocal*>(PX_PLACEMENT_NEW(buff1, SupportLocalImpl<ConvexHullNoScaleV>)(static_cast<const ConvexHullNoScaleV&>(convexHull1), transf1, convexHull1.vertex2Shape, convexHull1.shape2Vertex, idtScale1)) :
+ static_cast<SupportLocal*>(PX_PLACEMENT_NEW(buff1, SupportLocalImpl<ConvexHullV>)(convexHull1, transf1, convexHull1.vertex2Shape, convexHull1.shape2Vertex, idtScale1)));
+
+
+ PxU32 numContacts = 0;
+
+ if(generateFullContactManifold(polyData0, polyData1, map0, map1, manifoldContacts, numContacts, contactDist, normal, closestA, closestB, convexHull0.getMargin(),
+ convexHull1.getMargin(), doOverlapTest, renderOutput, toleranceScale))
+ {
+
+ if (numContacts > 0)
+ {
+ //reduce contacts
+ manifold.addBatchManifoldContacts(manifoldContacts, numContacts);
+
+ const Vec3V worldNormal = manifold.getWorldNormal(transf1);
+
+ //add the manifold contacts;
+ manifold.addManifoldContactsToContactBuffer(contactBuffer, worldNormal, transf1, contactDist);
+
+
+#if PCM_LOW_LEVEL_DEBUG
+ manifold.drawManifold(*renderOutput, transf0, transf1);
+#endif
+ }
+ else
+ {
+ //if doOverlapTest is true, which means GJK/EPA degenerate so we won't have any contact in the manifoldContacts array
+ if (!doOverlapTest)
+ {
+ const Vec3V worldNormal = manifold.getWorldNormal(transf1);
+
+ manifold.addManifoldContactsToContactBuffer(contactBuffer, worldNormal, transf1, contactDist);
+ }
+
+ }
+ return true;
+
+ }
+
+ return false;
+
+}
+
+static GjkStatus convexHullNoScale0(const ShrunkConvexHullV& convexHull0, const ShrunkConvexHullV& convexHull1, const bool idtScale1, const PsMatTransformV& aToB, const FloatVArg contactDist,
+ Vec3V& closestA, Vec3V& closestB, Vec3V& normal, FloatV& penDep, PersistentContactManifold& manifold)
+{
+ const RelativeConvex<ShrunkConvexHullNoScaleV> convexA(static_cast<const ShrunkConvexHullNoScaleV&>(convexHull0), aToB);
+ if(idtScale1)
+ {
+ const LocalConvex<ShrunkConvexHullNoScaleV> convexB(static_cast<const ShrunkConvexHullNoScaleV&>(convexHull1));
+ return gjkPenetration<RelativeConvex<ShrunkConvexHullNoScaleV>, LocalConvex<ShrunkConvexHullNoScaleV> >(convexA, convexB, aToB.p, contactDist, closestA, closestB, normal, penDep,
+ manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints, false);
+ }
+ else
+ {
+ const LocalConvex<ShrunkConvexHullV> convexB(convexHull1);
+ return gjkPenetration<RelativeConvex<ShrunkConvexHullNoScaleV>, LocalConvex<ShrunkConvexHullV> >(convexA, convexB, aToB.p, contactDist, closestA, closestB, normal, penDep,
+ manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints,false);
+ }
+}
+
+static GjkStatus convexHullHasScale0(ShrunkConvexHullV& convexHull0, ShrunkConvexHullV& convexHull1, const bool idtScale1, const PsMatTransformV& aToB,
+ const FloatVArg contactDist, Vec3V& closestA, Vec3V& closestB, Vec3V& normal, FloatV& penDep, PersistentContactManifold& manifold)
+{
+ RelativeConvex<ShrunkConvexHullV> convexA(convexHull0, aToB);
+ if(idtScale1)
+ {
+ LocalConvex<ShrunkConvexHullNoScaleV> convexB(static_cast<ShrunkConvexHullNoScaleV&>(convexHull1));
+ return gjkPenetration< RelativeConvex<ShrunkConvexHullV>, LocalConvex<ShrunkConvexHullNoScaleV> >(convexA, convexB, aToB.p, contactDist, closestA, closestB, normal, penDep,
+ manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints,false);
+ }
+ else
+ {
+ LocalConvex<ShrunkConvexHullV> convexB(convexHull1);
+ return gjkPenetration<RelativeConvex<ShrunkConvexHullV>, LocalConvex<ShrunkConvexHullV> >(convexA, convexB, aToB.p, contactDist, closestA, closestB, normal, penDep,
+ manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints, false);
+ }
+}
+
+
+static bool addGJKEPAContacts(Gu::ShrunkConvexHullV& convexHull0, Gu::ShrunkConvexHullV& convexHull1, const PsMatTransformV& aToB, GjkStatus status,
+ Gu::PersistentContact* manifoldContacts, const FloatV replaceBreakingThreshold, Vec3V& closestA, Vec3V& closestB, Vec3V& normal, FloatV& penDep,
+ Gu::PersistentContactManifold& manifold)
+{
+ bool doOverlapTest = false;
+ if (status == GJK_CONTACT)
+ {
+ const Vec3V localPointA = aToB.transformInv(closestA);//curRTrans.transformInv(closestA);
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(normal), penDep);
+
+ //Add contact to contact stream
+ manifoldContacts[0].mLocalPointA = localPointA;
+ manifoldContacts[0].mLocalPointB = closestB;
+ manifoldContacts[0].mLocalNormalPen = localNormalPen;
+
+ //Add contact to manifold
+ manifold.addManifoldPoint(localPointA, closestB, localNormalPen, replaceBreakingThreshold);
+ }
+ else
+ {
+ PX_ASSERT(status == EPA_CONTACT);
+
+ RelativeConvex<ConvexHullV> convexA1(convexHull0, aToB);
+ LocalConvex<ConvexHullV> convexB1(convexHull1);
+
+ status = epaPenetration(convexA1, convexB1, manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints,
+ closestA, closestB, normal, penDep);
+
+ if (status == EPA_CONTACT)
+ {
+ const Vec3V localPointA = aToB.transformInv(closestA);//curRTrans.transformInv(closestA);
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(normal), penDep);
+
+ //Add contact to contact stream
+ manifoldContacts[0].mLocalPointA = localPointA;
+ manifoldContacts[0].mLocalPointB = closestB;
+ manifoldContacts[0].mLocalNormalPen = localNormalPen;
+
+ //Add contact to manifold
+ manifold.addManifoldPoint(localPointA, closestB, localNormalPen, replaceBreakingThreshold);
+ }
+ else
+ {
+ doOverlapTest = true;
+ }
+ }
+
+ return doOverlapTest;
+}
+
+bool pcmContactConvexConvex(GU_CONTACT_METHOD_ARGS)
+{
+ const PxConvexMeshGeometryLL& shapeConvex0 = shape0.get<const PxConvexMeshGeometryLL>();
+ const PxConvexMeshGeometryLL& shapeConvex1 = shape1.get<const PxConvexMeshGeometryLL>();
+ PersistentContactManifold& manifold = cache.getManifold();
+
+ Ps::prefetchLine(shapeConvex0.hullData);
+ Ps::prefetchLine(shapeConvex1.hullData);
+
+ PX_ASSERT(transform1.q.isSane());
+ PX_ASSERT(transform0.q.isSane());
+
+ const Vec3V vScale0 = V3LoadU_SafeReadW(shapeConvex0.scale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale
+ const Vec3V vScale1 = V3LoadU_SafeReadW(shapeConvex1.scale.scale); // PT: safe because 'rotation' follows 'scale' in PxMeshScale
+ const FloatV contactDist = FLoad(params.mContactDistance);
+
+ //Transfer A into the local space of B
+ const PsTransformV transf0 = loadTransformA(transform0);
+ const PsTransformV transf1 = loadTransformA(transform1);
+ const PsTransformV curRTrans(transf1.transformInv(transf0));
+ const PsMatTransformV aToB(curRTrans);
+
+ const Gu::ConvexHullData* hullData0 = shapeConvex0.hullData;
+ const Gu::ConvexHullData* hullData1 = shapeConvex1.hullData;
+
+ const FloatV convexMargin0 = Gu::CalculatePCMConvexMargin(hullData0, vScale0);
+ const FloatV convexMargin1 = Gu::CalculatePCMConvexMargin(hullData1, vScale1);
+
+ const PxU32 initialContacts = manifold.mNumContacts;
+
+ const FloatV minMargin = FMin(convexMargin0, convexMargin1);
+ const FloatV projectBreakingThreshold = FMul(minMargin, FLoad(0.8f));
+
+ manifold.refreshContactPoints(aToB, projectBreakingThreshold, contactDist);
+
+ //ML: after refreshContactPoints, we might lose some contacts
+ const bool bLostContacts = (manifold.mNumContacts != initialContacts);
+
+ PX_UNUSED(bLostContacts);
+ if(bLostContacts || manifold.invalidate_BoxConvex(curRTrans, minMargin))
+ {
+ GjkStatus status = manifold.mNumContacts > 0 ? GJK_UNDEFINED : GJK_NON_INTERSECT;
+
+ const bool idtScale0 = shapeConvex0.scale.isIdentity();
+ const bool idtScale1 = shapeConvex1.scale.isIdentity();
+ const QuatV vQuat0 = QuatVLoadU(&shapeConvex0.scale.rotation.x);
+ const QuatV vQuat1 = QuatVLoadU(&shapeConvex1.scale.rotation.x);
+ const Vec3V zeroV = V3Zero();
+ Gu::ShrunkConvexHullV convexHull0(hullData0, zeroV, vScale0, vQuat0, idtScale0);
+ Gu::ShrunkConvexHullV convexHull1(hullData1, zeroV, vScale1, vQuat1, idtScale1);
+
+ Vec3V closestA(zeroV), closestB(zeroV), normal(zeroV); // from a to b
+ FloatV penDep = FZero();
+
+ if(idtScale0)
+ {
+ status = convexHullNoScale0(convexHull0, convexHull1, idtScale1, aToB, contactDist, closestA, closestB, normal, penDep, manifold);
+ }
+ else
+ {
+ status = convexHullHasScale0(convexHull0, convexHull1, idtScale1, aToB, contactDist, closestA, closestB, normal, penDep, manifold);
+ }
+
+ manifold.setRelativeTransform(curRTrans);
+
+ Gu::PersistentContact* manifoldContacts = PX_CP_TO_PCP(contactBuffer.contacts);
+
+ if(status == GJK_DEGENERATE)
+ {
+ return fullContactsGenerationConvexConvex(convexHull0, convexHull1, transf0, transf1, idtScale0, idtScale1, manifoldContacts, contactBuffer,
+ manifold, normal, closestA, closestB, contactDist, true, renderOutput, FLoad(params.mToleranceLength));
+ }
+ else if(status == GJK_NON_INTERSECT)
+ {
+ return false;
+ }
+ else
+ {
+ const FloatV replaceBreakingThreshold = FMul(minMargin, FLoad(0.05f));
+
+ const bool doOverlapTest = addGJKEPAContacts(convexHull0, convexHull1, aToB, status, manifoldContacts, replaceBreakingThreshold, closestA, closestB, normal, penDep, manifold);
+
+ //ML: after we refresh the contacts(newContacts) and generate a GJK/EPA contacts(we will store that in the manifold), if the number of contacts is still less than the original contacts,
+ //which means we lose too mang contacts and we should regenerate all the contacts in the current configuration
+ if (initialContacts == 0 || (manifold.mNumContacts < initialContacts) || doOverlapTest)
+ {
+ return fullContactsGenerationConvexConvex(convexHull0, convexHull1, transf0, transf1, idtScale0, idtScale1, manifoldContacts, contactBuffer,
+ manifold, normal, closestA, closestB, contactDist, doOverlapTest, renderOutput, FLoad(params.mToleranceLength));
+ }
+ else
+ {
+ const Vec3V worldNormal = manifold.getWorldNormal(transf1);
+ manifold.addManifoldContactsToContactBuffer(contactBuffer, worldNormal, transf1, contactDist);
+ return true;
+ }
+
+ }
+ }
+ else if(manifold.getNumContacts()> 0)
+ {
+ const Vec3V worldNormal = manifold.getWorldNormal(transf1);
+ manifold.addManifoldContactsToContactBuffer(contactBuffer, worldNormal, transf1, contactDist);
+#if PCM_LOW_LEVEL_DEBUG
+ manifold.drawManifold(*renderOutput, transf0, transf1);
+#endif
+ return true;
+ }
+
+ return false;
+
+}
+
+}
+}