aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMTriangleContactGen.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/GeomUtils/src/pcm/GuPCMTriangleContactGen.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/GeomUtils/src/pcm/GuPCMTriangleContactGen.cpp')
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMTriangleContactGen.cpp1250
1 files changed, 1250 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMTriangleContactGen.cpp b/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMTriangleContactGen.cpp
new file mode 100644
index 00000000..ea400b94
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMTriangleContactGen.cpp
@@ -0,0 +1,1250 @@
+// 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 "GuGeometryUnion.h"
+#include "GuPCMTriangleContactGen.h"
+#include "GuPCMContactConvexCommon.h"
+#include "GuVecTriangle.h"
+#include "GuBarycentricCoordinates.h"
+
+#if PCM_LOW_LEVEL_DEBUG
+#include "PxRenderBuffer.h"
+#endif
+
+#define EDGE_EDGE_GAUSS_MAP 0
+#define BRUTE_FORCE_EDGE_EDGE 0
+
+using namespace physx;
+using namespace Gu;
+using namespace Ps::aos;
+
+namespace physx
+{
+ static bool testPolyFaceNormal(const Gu::TriangleV& triangle, const PolygonalData& polyData, SupportLocalImpl<TriangleV>* triMap, SupportLocal* polyMap, const FloatVArg contactDist,
+ FloatV& minOverlap, PxU32& feature, Vec3V& faceNormal, const FeatureStatus faceStatus, FeatureStatus& status)
+ {
+ PX_UNUSED(triangle);
+
+ FloatV _minOverlap = FMax();
+ PxU32 _feature = 0;
+ Vec3V _faceNormal = faceNormal;
+ FloatV min0, max0;
+ FloatV min1, max1;
+ const FloatV eps = FEps();
+
+ if(polyMap->isIdentityScale)
+ {
+ //in the local space of polyData0
+ for(PxU32 i=0; i<polyData.mNbPolygons; ++i)
+ {
+ const Gu::HullPolygonData& polygon = polyData.mPolygons[i];
+
+ const Vec3V minVert = V3LoadU_SafeReadW(polyData.mVerts[polygon.mMinIndex]); // PT: safe because of the way vertex memory is allocated in ConvexHullData
+ const FloatV planeDist = FLoad(polygon.mPlane.d);
+ //shapeSpace and vertexSpace are the same
+ const Vec3V planeNormal = V3LoadU_SafeReadW(polygon.mPlane.n); // PT: safe because 'd' follows 'n' in the plane class
+
+ //ML::avoid lHS, don't use the exiting function
+ min0 = V3Dot(planeNormal, minVert);
+ max0 = FNeg(planeDist);
+
+ triMap->doSupport(planeNormal, min1, max1);
+
+ const BoolV con = BOr(FIsGrtr(min1, FAdd(max0, contactDist)), FIsGrtr(min0, FAdd(max1, contactDist)));
+
+ if(BAllEqTTTT(con))
+ return false;
+
+ const FloatV tempOverlap = FSub(max0, min1);
+
+ if(FAllGrtr(_minOverlap, tempOverlap))
+ {
+ _minOverlap = tempOverlap;
+ _feature = i;
+ _faceNormal = planeNormal;
+ }
+ }
+ }
+ else
+ {
+
+ //in the local space of polyData0
+ for(PxU32 i=0; i<polyData.mNbPolygons; ++i)
+ {
+ const Gu::HullPolygonData& polygon = polyData.mPolygons[i];
+
+ const Vec3V minVert = V3LoadU_SafeReadW(polyData.mVerts[polygon.mMinIndex]); // PT: safe because of the way vertex memory is allocated in ConvexHullData
+ const FloatV planeDist = FLoad(polygon.mPlane.d);
+ const Vec3V vertexSpacePlaneNormal = V3LoadU_SafeReadW(polygon.mPlane.n); // PT: safe because 'd' follows 'n' in the plane class
+ //transform plane n to shape space
+ const Vec3V shapeSpacePlaneNormal = M33TrnspsMulV3(polyMap->shape2Vertex, vertexSpacePlaneNormal);
+
+ const FloatV magnitude = FRsqrtFast(V3LengthSq(shapeSpacePlaneNormal)); //FRecip(V3Length(shapeSpacePlaneNormal));
+
+ //ML::avoid lHS, don't use the exiting function
+ min0 = FMul(V3Dot(vertexSpacePlaneNormal, minVert), magnitude);
+ max0 = FMul(FNeg(planeDist), magnitude);
+
+ //normalize the shapeSpacePlaneNormal
+ const Vec3V planeN = V3Scale(shapeSpacePlaneNormal, magnitude);
+
+ triMap->doSupport(planeN, min1, max1);
+
+ const BoolV con = BOr(FIsGrtr(min1, FAdd(max0, contactDist)), FIsGrtr(min0, FAdd(max1, contactDist)));
+
+ if(BAllEqTTTT(con))
+ return false;
+
+ const FloatV tempOverlap = FSub(max0, min1);
+
+ if(FAllGrtr(_minOverlap, tempOverlap))
+ {
+ _minOverlap = tempOverlap;
+ _feature = i;
+ _faceNormal = planeN;
+ }
+ }
+ }
+
+ if(FAllGrtr(minOverlap, FAdd(_minOverlap, eps)))
+ {
+ faceNormal = _faceNormal;
+ minOverlap = _minOverlap;
+ status = faceStatus;
+ }
+
+ feature = _feature;
+
+ return true;
+
+ }
+
+
+
+ //triangle is in the local space of polyData
+ static bool testTriangleFaceNormal(const TriangleV& triangle, const PolygonalData& polyData, SupportLocalImpl<TriangleV>* triMap, SupportLocal* polyMap, const FloatVArg contactDist,
+ FloatV& minOverlap, PxU32& feature, Vec3V& faceNormal, const FeatureStatus faceStatus, FeatureStatus& status)
+ {
+ PX_UNUSED(triMap);
+ PX_UNUSED(polyData);
+
+ FloatV min1, max1;
+ const FloatV eps = FEps();
+
+ const Vec3V triangleLocNormal = triangle.normal();
+
+ const FloatV min0 = V3Dot(triangleLocNormal, triangle.verts[0]);
+ const FloatV max0 = min0;
+
+ //triangle normal is in the vertex space
+ polyMap->doSupport(triangleLocNormal, min1, max1);
+
+ const BoolV con = BOr(FIsGrtr(min1, FAdd(max0, contactDist)), FIsGrtr(min0, FAdd(max1, contactDist)));
+
+ if(BAllEqTTTT(con))
+ return false;
+
+ minOverlap = FSub(FSub(max0, min1), eps);
+ status = faceStatus;
+ feature = 0;
+ faceNormal=triangleLocNormal;
+
+ return true;
+
+ }
+
+ static bool testPolyEdgeNormal(const TriangleV& triangle, const PxU8 triFlags, const PolygonalData& polyData, SupportLocalImpl<TriangleV>* triMap, SupportLocal* polyMap, const FloatVArg contactDist,
+ FloatV& minOverlap, Vec3V& minNormal, const FeatureStatus edgeStatus, FeatureStatus& status)
+ {
+ PX_UNUSED(triFlags);
+ FloatV overlap = minOverlap;
+ FloatV min0, max0;
+ FloatV min1, max1;
+ const FloatV zero = FZero();
+ const Vec3V eps2 = V3Splat(FLoad(1e-6));
+
+ const Vec3V v0 = M33MulV3(polyMap->shape2Vertex, triangle.verts[0]);
+ const Vec3V v1 = M33MulV3(polyMap->shape2Vertex, triangle.verts[1]);
+ const Vec3V v2 = M33MulV3(polyMap->shape2Vertex, triangle.verts[2]);
+
+ TriangleV vertexSpaceTriangle(v0, v1, v2);
+
+ PxU32 nbTriangleAxes = 0;
+ Vec3V triangleAxes[3];
+ for(PxI8 kStart = 0, kEnd =2; kStart<3; kEnd = kStart++)
+ {
+ bool active = (triFlags & (1 << (kEnd+3))) != 0;
+
+ if(active)
+ {
+ const Vec3V p00 = vertexSpaceTriangle.verts[kStart];
+ const Vec3V p01 = vertexSpaceTriangle.verts[kEnd];
+ triangleAxes[nbTriangleAxes++] = V3Sub(p01, p00);
+ }
+ }
+
+ if(nbTriangleAxes == 0)
+ return true;
+
+ //create localTriPlane in the vertex space
+ const Vec3V vertexSpaceTriangleNormal = vertexSpaceTriangle.normal();
+
+ for(PxU32 i =0; i<polyData.mNbPolygons; ++i)
+ {
+ const Gu::HullPolygonData& polygon = polyData.mPolygons[i];
+ const PxU8* inds = polyData.mPolygonVertexRefs + polygon.mVRef8;
+ const Vec3V vertexSpacePlaneNormal = V3LoadU(polygon.mPlane.n);
+
+ //fast culling.
+ if(FAllGrtr(V3Dot(vertexSpacePlaneNormal, vertexSpaceTriangleNormal), zero))
+ continue;
+
+ // Loop through polygon vertices == polygon edges;
+ for(PxU32 lStart = 0, lEnd =PxU32(polygon.mNbVerts-1); lStart<polygon.mNbVerts; lEnd = PxU32(lStart++))
+ {
+ //in the vertex space
+ const Vec3V p10 = V3LoadU_SafeReadW(polyData.mVerts[inds[lStart]]); // PT: safe because of the way vertex memory is allocated in ConvexHullData
+ const Vec3V p11 = V3LoadU_SafeReadW(polyData.mVerts[inds[lEnd]]); // PT: safe because of the way vertex memory is allocated in ConvexHullData
+
+ const Vec3V convexEdge = V3Sub(p11, p10);
+
+ for (PxU32 j = 0; j < nbTriangleAxes; ++j)
+ {
+
+ const Vec3V currentPolyEdge = triangleAxes[j];
+ const Vec3V v = V3Cross(convexEdge, currentPolyEdge);
+
+ //two edges aren't parallel
+ if ((!V3AllGrtr(eps2, V3Abs(v))) && (FAllGrtr(V3Dot(v, vertexSpaceTriangleNormal), zero)))
+ {
+ //transform the v back to the shape space
+ const Vec3V shapeSpaceV = M33TrnspsMulV3(polyMap->shape2Vertex, v);
+ const Vec3V n0 = V3Normalize(shapeSpaceV);
+ triMap->doSupport(n0, min0, max0);
+ polyMap->doSupport(n0, min1, max1);
+ const BoolV con = BOr(FIsGrtr(min1, FAdd(max0, contactDist)), FIsGrtr(min0, FAdd(max1, contactDist)));
+ if (BAllEqTTTT(con))
+ return false;
+
+ const FloatV tempOverlap = FSub(max0, min1);
+
+ if (FAllGrtr(overlap, tempOverlap))
+ {
+ overlap = tempOverlap;
+ minNormal = n0;
+ status = edgeStatus;
+ }
+
+ }
+ }
+
+ }
+ }
+ minOverlap = overlap;
+
+ return true;
+
+ }
+
+#if BRUTE_FORCE_EDGE_EDGE
+
+
+ bool testPolyEdgeNormalBruteForce(const TriangleV& triangle, const PxU8 triFlags, const PolygonalData& polyData, SupportLocalImpl<TriangleV>* triMap, SupportLocal* polyMap, const FloatVArg contactDist,
+ FloatV& minOverlap, Vec3V& minNormal, const FeatureStatus edgeStatus, FeatureStatus& status)
+ {
+ PX_UNUSED(triFlags);
+ FloatV min0, max0;
+ FloatV min1, max1;
+
+ FloatV bestDist = FLoad(PX_MAX_F32);
+ Vec3V bestAxis = V3Zero();
+
+ const Vec3V eps2 = V3Splat(FLoad(1e-6));
+
+ PxU32 bestPolyIndex = 0;
+ PxU32 bestStart = 0;
+ PxU32 bestEnd = 0;
+ PxI8 bestTriStart = 0;
+ PxI8 bestTriEnd = 0;
+
+ for(PxU32 i =0; i<polyData.mNbPolygons; ++i)
+ {
+ const Gu::HullPolygonData& polygon = polyData.mPolygons[i];
+ const PxU8* inds = polyData.mPolygonVertexRefs + polygon.mVRef8;
+
+ // Loop through polygon vertices == polygon edges;
+ for(PxU32 lStart = 0, lEnd =PxU32(polygon.mNbVerts-1); lStart<polygon.mNbVerts; lEnd = PxU32(lStart++))
+ {
+ //in the vertex space
+ const Vec3V p10 = V3LoadU_SafeReadW(polyData.mVerts[inds[lStart]]); // PT: safe because of the way vertex memory is allocated in ConvexHullData
+ const Vec3V p11 = V3LoadU_SafeReadW(polyData.mVerts[inds[lEnd]]); // PT: safe because of the way vertex memory is allocated in ConvexHullData
+
+ //shape sapce
+ const Vec3V vertex10 = M33MulV3(polyMap->vertex2Shape, p10);
+ const Vec3V vertex11 = M33MulV3(polyMap->vertex2Shape, p11);
+
+ const Vec3V convexEdge = V3Sub(vertex11, vertex10);
+
+ for (PxI8 kEnd = 0, kStart = 2; kEnd<3; kStart = kEnd++)
+ {
+
+ const Vec3V triVert0 = triangle.verts[kStart];
+ const Vec3V triVert1 = triangle.verts[kEnd];
+
+ const Vec3V triangleEdge = V3Sub(triVert1, triVert0);
+ const Vec3V v = V3Cross(convexEdge, triangleEdge);
+
+ if (!V3AllGrtr(eps2, V3Abs(v)))
+ {
+ //transform the v back to the shape space
+ const Vec3V n0 = V3Normalize(v);
+ triMap->doSupport(n0, min0, max0);
+ polyMap->doSupport(n0, min1, max1);
+ const BoolV con = BOr(FIsGrtr(min1, FAdd(max0, contactDist)), FIsGrtr(min0, FAdd(max1, contactDist)));
+ if(BAllEqTTTT(con))
+ return false;
+
+ const FloatV tempOverlap = FSub(max0, min1);
+
+ if (FAllGrtr(bestDist, tempOverlap))
+ {
+ bestDist = tempOverlap;
+ bestAxis = n0;
+ bestPolyIndex = i;
+ bestStart = lStart;
+ bestEnd = lEnd;
+ bestTriStart = kStart;
+ bestTriEnd = kEnd;
+ }
+
+ }
+ }
+ }
+ }
+
+ if (FAllGrtr(minOverlap, bestDist))
+ {
+ minOverlap = bestDist;
+ minNormal = bestAxis;
+ status = edgeStatus;
+ }
+
+ return true;
+
+ }
+
+ bool testPolyEdgeNormalBruteForceVertsByEdges(const TriangleV& triangle, const PxU8 triFlags, const PolygonalData& polyData, SupportLocalImpl<TriangleV>* triMap, SupportLocal* polyMap, const FloatVArg contactDist,
+ FloatV& minOverlap, Vec3V& minNormal, const FeatureStatus edgeStatus, FeatureStatus& status, PxU32& bestEdgeIndex, PxI8& bestTriStart, PxI8& bestTriEnd)
+ {
+
+ PX_UNUSED(triFlags);
+
+ const PxU32 numConvexEdges = polyData.mNbEdges;
+ const PxU16* verticesByEdges16 = polyData.mVerticesByEdges;
+ const PxVec3* vertices = polyData.mVerts;
+
+ FloatV bestDist = FLoad(PX_MAX_F32);
+ Vec3V bestAxis = V3Zero();
+ const Vec3V eps2 = V3Splat(FLoad(1e-6));
+
+ for (PxU32 convexEdgeIdx = 0; convexEdgeIdx < numConvexEdges; ++convexEdgeIdx)
+ {
+ const PxU16 v0idx1 = verticesByEdges16[convexEdgeIdx * 2];
+ const PxU32 v1idx1 = verticesByEdges16[convexEdgeIdx * 2 + 1];
+
+ //shape sapce
+ const Vec3V vertex10 = M33MulV3(polyMap->vertex2Shape, V3LoadU(vertices[v0idx1]));
+ const Vec3V vertex11 = M33MulV3(polyMap->vertex2Shape, V3LoadU(vertices[v1idx1]));
+
+ Vec3V convexEdge = V3Sub(vertex11, vertex10);
+
+
+ for (PxI8 kEnd = 0, kStart = 2; kEnd<3; kStart = kEnd++)
+ {
+ const Vec3V triVert0 = triangle.verts[kStart];
+ const Vec3V triVert1 = triangle.verts[kEnd];
+ const Vec3V triEdge = V3Sub(triVert1, triVert0);
+
+ // compute the separation along this axis in vertex space
+ Vec3V axis = V3Cross(convexEdge, triEdge);
+
+ if (!V3AllGrtr(eps2, V3Abs(axis)))
+ {
+ axis = V3Normalize(axis);
+
+ FloatV min0, max0;
+ FloatV min1, max1;
+ triMap->doSupport(axis, min0, max0);
+ polyMap->doSupport(axis, min1, max1);
+ const BoolV con = BOr(FIsGrtr(min1, FAdd(max0, contactDist)), FIsGrtr(min0, FAdd(max1, contactDist)));
+ if (BAllEqTTTT(con))
+ return false;
+
+ const FloatV dist0 = FSub(max0, min1);
+ const FloatV dist1 = FSub(max1, min0);
+
+ if (FAllGrtr(dist0, dist1))
+ axis = V3Neg(axis);
+
+ const FloatV dist = FMin(dist0, dist1);
+
+ if (FAllGrtr(bestDist, dist))
+ {
+ bestDist = dist;
+ bestAxis = axis;
+
+ bestEdgeIndex = convexEdgeIdx;
+ bestTriStart = kStart;
+ bestTriEnd = kEnd;
+ }
+ }
+ }
+
+ }
+
+ if (FAllGrtr(minOverlap, bestDist))
+ {
+ minOverlap = bestDist;
+ minNormal = bestAxis;
+ status = edgeStatus;
+
+ }
+ return true;
+
+ }
+
+
+#endif
+
+#if EDGE_EDGE_GAUSS_MAP
+
+
+
+ bool isMinkowskiFace(const Vec3V& A, const Vec3V& B, const Vec3V& B_x_A, const Vec3V& C, const Vec3V& D, const Vec3V& D_x_C)
+ {
+
+ const FloatV zero = FZero();
+ // Two edges build a face on the Minkowski sum if the associated arcs AB and CD intersect on the Gauss map.
+ // The associated arcs are defined by the adjacent face normals of each edge.
+ const FloatV CBA = V3Dot(C, B_x_A);
+ const FloatV DBA = V3Dot(D, B_x_A);
+ const FloatV ADC = V3Dot(A, D_x_C);
+ const FloatV BDC = V3Dot(B, D_x_C);
+
+ const BoolV con0 = FIsGrtrOrEq(zero, FMul(CBA, DBA));
+ const BoolV con1 = FIsGrtrOrEq(zero, FMul(ADC, BDC));
+ const BoolV con2 = FIsGrtr(FMul(CBA, BDC), zero);
+
+ const BoolV con = BAnd(con2, BAnd(con0, con1));
+
+ return (BAllEqTTTT(con) != 0);
+
+ //return CBA * DBA < 0.0f && ADC * BDC < 0.0f && CBA * BDC > 0.0f;
+ }
+
+#define SAT_VARIFY 0
+
+ bool testPolyEdgeNormalGaussMap(const TriangleV& triangle, const PxU8 triFlags, const PolygonalData& polyData, SupportLocalImpl<TriangleV>* triMap, SupportLocal* polyMap, const FloatVArg contactDist,
+ FloatV& minOverlap, Vec3V& minNormal, const FeatureStatus edgeStatus, FeatureStatus& status, PxU32& gaussMapBestEdgeIndex, PxI8& gaussMapBestTriStart, PxI8& gaussMapBestTriEnd)
+ {
+
+ PX_UNUSED(triFlags);
+ const FloatV zero = FZero();
+
+ const Vec3V triNormal = triangle.normal();
+
+ const PxU32 numConvexEdges = polyData.mNbEdges;
+ const PxU16* verticesByEdges16 = polyData.mVerticesByEdges;
+ const PxU8* facesByEdges8 = polyData.mFacesByEdges;
+ const PxVec3* vertices = polyData.mVerts;
+
+ FloatV bestDist = FLoad(-PX_MAX_F32);
+ Vec3V axis = V3Zero();
+ Vec3V bestAxis = V3Zero();
+ const Vec3V eps2 = V3Splat(FLoad(1e-6));
+
+
+ //Center is in shape space
+ const Vec3V shapeSpaceCOM =V3LoadU(polyData.mCenter);
+ const Vec3V vertexSpaceCOM = M33MulV3(polyMap->shape2Vertex, shapeSpaceCOM);
+
+ PxVec3 vertexCOM;
+ V3StoreU(vertexSpaceCOM, vertexCOM);
+
+ for (PxU32 convexEdgeIdx = 0; convexEdgeIdx < numConvexEdges; ++convexEdgeIdx)
+ {
+
+ const PxU16 v0idx1 = verticesByEdges16[convexEdgeIdx*2];
+ const PxU32 v1idx1 = verticesByEdges16[convexEdgeIdx * 2 + 1];
+
+ const PxU8 f10 = facesByEdges8[convexEdgeIdx * 2];
+ const PxU8 f11 = facesByEdges8[convexEdgeIdx * 2 + 1];
+
+ //shape sapce
+ const Vec3V vertex10 = M33MulV3(polyMap->vertex2Shape, V3LoadU(vertices[v0idx1]));
+ const Vec3V vertex11 = M33MulV3(polyMap->vertex2Shape, V3LoadU(vertices[v1idx1]));
+
+ Vec3V convexEdge = V3Sub(vertex11, vertex10);
+
+ const Gu::HullPolygonData& face0 = polyData.mPolygons[f10];
+ const Gu::HullPolygonData& face1 = polyData.mPolygons[f11];
+
+ const Vec3V convexNormal0 = M33TrnspsMulV3(polyMap->shape2Vertex, V3LoadU(face0.mPlane.n));
+ const Vec3V convexNormal1 = M33TrnspsMulV3(polyMap->shape2Vertex, V3LoadU(face1.mPlane.n));
+
+ float signDist0 = face0.mPlane.distance(vertexCOM);
+ float signDist1 = face1.mPlane.distance(vertexCOM);
+
+ PX_ASSERT(signDist0 < 0.f);
+ PX_ASSERT(signDist1 < 0.f);
+
+ for (PxI8 kEnd = 0, kStart = 2; kEnd<3; kStart = kEnd++)
+ {
+
+ const Vec3V triVert0 = triangle.verts[kStart];
+ const Vec3V triVert1 = triangle.verts[kEnd];
+ const Vec3V triEdge = V3Sub(triVert1, triVert0);
+
+ //if (isMinkowskiFace(convexNormal0, convexNormal1, V3Neg(convexEdge), V3Neg(triNormal), triNormal, V3Neg(triEdge)))
+ if (isMinkowskiFace(convexNormal0, convexNormal1, convexEdge, V3Neg(triNormal), triNormal, triEdge))
+ {
+
+ // compute the separation along this axis in vertex space
+ axis = V3Cross(convexEdge, triEdge);
+
+ if (!V3AllGrtr(eps2, V3Abs(axis)))
+ {
+ axis = V3Normalize(axis);
+
+ const Vec3V v = V3Sub(vertex10, shapeSpaceCOM);
+
+ // ensure the axis is outward pointing on the edge on the minkowski sum. Assure normal points from convex hull to triangle
+ const FloatV temp = V3Dot(axis, v);
+ if (FAllGrtr(zero, temp))
+ axis = V3Neg(axis);
+
+ //compute the distance from any of the verts in the triangle to plane(axis, vertex10)(n.dot(p-a))
+ const Vec3V ap = V3Sub(triVert0, vertex10);
+
+ const FloatV dist = V3Dot(axis, ap);
+
+ if (FAllGrtr(dist, contactDist))
+ return false;
+
+#if SAT_VARIFY
+ FloatV min0, max0;
+ FloatV min1, max1;
+ triMap->doSupport(V3Neg(axis), min0, max0);
+ polyMap->doSupport(V3Neg(axis), min1, max1);
+ const BoolV con = BOr(FIsGrtr(min1, FAdd(max0, contactDist)), FIsGrtr(min0, FAdd(max1, contactDist)));
+ if (BAllEqTTTT(con))
+ return false;
+
+ /*const FloatV dist = FSub(max0, min1);
+
+ if (FAllGrtr(bestDist, dist))
+ {
+ bestDist = dist;
+ bestAxis = axis;
+ }*/
+ const FloatV tempDist = FSub(max0, min1);
+
+ const FloatV dif = FAbs(FAdd(tempDist, dist));
+ PX_UNUSED(dif);
+ PX_ASSERT(FAllGrtr(FLoad(1e-4f), dif));
+
+#endif
+
+ if (FAllGrtr(dist, bestDist))
+ {
+ bestDist = dist;
+ bestAxis = axis;
+
+ gaussMapBestEdgeIndex = convexEdgeIdx;
+ gaussMapBestTriStart = kStart;
+ gaussMapBestTriEnd = kEnd;
+ }
+ }
+ }
+ }
+
+ }
+
+ if (FAllGrtr(minOverlap, bestDist))
+ {
+ minOverlap = bestDist;
+ minNormal = bestAxis;
+ status = edgeStatus;
+ }
+ return true;
+
+ }
+
+#endif
+
+ static PX_FORCE_INLINE PxU32 addMeshContacts(MeshPersistentContact* manifoldContacts, const Vec3V& pA, const Vec3V& pB, const Vec4V& normalPen, const PxU32 triangleIndex, const PxU32 numContacts)
+ {
+ manifoldContacts[numContacts].mLocalPointA = pA;
+ manifoldContacts[numContacts].mLocalPointB = pB;
+ manifoldContacts[numContacts].mLocalNormalPen = normalPen;
+ manifoldContacts[numContacts].mFaceIndex = triangleIndex;
+ return numContacts+1;
+ }
+
+
+ static void generatedTriangleContacts(const Gu::TriangleV& triangle, const PxU32 triangleIndex, const PxU8/* _triFlags*/, const Gu::PolygonalData& polyData1, const Gu::HullPolygonData& incidentPolygon, Gu::SupportLocal* map1, Gu::MeshPersistentContact* manifoldContacts, PxU32& numManifoldContacts,
+ const Ps::aos::FloatVArg contactDist, const Ps::aos::Vec3VArg contactNormal, Cm::RenderOutput* renderOutput)
+ {
+
+ PX_UNUSED(renderOutput);
+ using namespace Ps::aos;
+
+ //PxU8 triFlags = _triFlags;
+ const PxU32 previousContacts = numManifoldContacts;
+
+ const FloatV zero = FZero();
+
+ const Mat33V rot = findRotationMatrixFromZAxis(contactNormal);
+
+ const PxU8* inds1 = polyData1.mPolygonVertexRefs + incidentPolygon.mVRef8;
+
+ Vec3V points0In0[3];
+ Vec3V* points1In0 = reinterpret_cast<Vec3V*>(PxAllocaAligned(sizeof(Vec3V)*incidentPolygon.mNbVerts, 16));
+ FloatV* points1In0TValue = reinterpret_cast<FloatV*>(PxAllocaAligned(sizeof(FloatV)*incidentPolygon.mNbVerts, 16));
+ bool* points1In0Penetration = reinterpret_cast<bool*>(PxAlloca(sizeof(bool)*incidentPolygon.mNbVerts));
+
+
+ points0In0[0] = triangle.verts[0];
+ points0In0[1] = triangle.verts[1];
+ points0In0[2] = triangle.verts[2];
+
+
+
+ //Transform all the verts from vertex space to shape space
+ map1->populateVerts(inds1, incidentPolygon.mNbVerts, polyData1.mVerts, points1In0);
+
+#if PCM_LOW_LEVEL_DEBUG
+ Gu::PersistentContactManifold::drawPolygon(*renderOutput, map1->transform, points1In0, incidentPolygon.mNbVerts, (PxU32)PxDebugColor::eARGB_RED);
+ //Gu::PersistentContactManifold::drawTriangle(*renderOutput, map1->transform.transform(points1In0[0]), map1->transform.transform(points0In0[1]), map1->transform.transform(points0In0[2]), (PxU32)PxDebugColor::eARGB_BLUE);
+#endif
+
+ Vec3V eps = Vec3V_From_FloatV(FEps());
+ Vec3V max = Vec3V_From_FloatV(FMax());
+ Vec3V nmax = V3Neg(max);
+
+ //transform reference polygon to 2d, calculate min and max
+ Vec3V rPolygonMin= max;
+ Vec3V rPolygonMax = nmax;
+ for(PxU32 i=0; i<3; ++i)
+ {
+ points0In0[i] = M33MulV3(rot, points0In0[i]);
+ rPolygonMin = V3Min(rPolygonMin, points0In0[i]);
+ rPolygonMax = V3Max(rPolygonMax, points0In0[i]);
+ }
+
+
+ rPolygonMin = V3Sub(rPolygonMin, eps);
+ rPolygonMax = V3Add(rPolygonMax, eps);
+
+ const FloatV d = V3GetZ(points0In0[0]);
+ const FloatV rd = FAdd(d, contactDist);
+
+ Vec3V iPolygonMin= max;
+ Vec3V iPolygonMax = nmax;
+
+
+ PxU32 inside = 0;
+ for(PxU32 i=0; i<incidentPolygon.mNbVerts; ++i)
+ {
+ const Vec3V vert1 =points1In0[i]; //this still in polyData1's local space
+ points1In0[i] = M33MulV3(rot, vert1);
+ const FloatV z = V3GetZ(points1In0[i]);
+ points1In0TValue[i] = FSub(z, d);
+ points1In0[i] = V3SetZ(points1In0[i], d);
+ iPolygonMin = V3Min(iPolygonMin, points1In0[i]);
+ iPolygonMax = V3Max(iPolygonMax, points1In0[i]);
+ if(FAllGrtr(rd, z))
+ {
+ points1In0Penetration[i] = true;
+
+ if(contains(points0In0, 3, points1In0[i], rPolygonMin, rPolygonMax))
+ {
+ inside++;
+
+ //add this contact to the buffer
+ const FloatV t = V3Dot(contactNormal, V3Sub(triangle.verts[0], vert1));
+ const Vec3V projectPoint = V3ScaleAdd(contactNormal, t, vert1);
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(contactNormal), FNeg(t));
+ numManifoldContacts = addMeshContacts(manifoldContacts, vert1, projectPoint, localNormalPen, triangleIndex, numManifoldContacts);
+
+ //if the numContacts are more than GU_MESH_CONTACT_REDUCTION_THRESHOLD, we need to do contact reduction
+ const PxU32 numContacts = numManifoldContacts - previousContacts;
+ if(numContacts >= GU_MESH_CONTACT_REDUCTION_THRESHOLD)
+ {
+ //a polygon has more than GU_MESH_CONTACT_REDUCTION_THRESHOLD(16) contacts with this triangle, we will reduce
+ //the contacts to GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE(4) points
+ Gu::SinglePersistentContactManifold::reduceContacts(&manifoldContacts[previousContacts], numContacts);
+ numManifoldContacts = previousContacts + GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE;
+ }
+ }
+ }
+
+ }
+
+
+
+ if(inside == incidentPolygon.mNbVerts)
+ {
+ return;
+ }
+
+ inside = 0;
+ iPolygonMin = V3Sub(iPolygonMin, eps);
+ iPolygonMax = V3Add(iPolygonMax, eps);
+
+ const Vec3V incidentNormal = V3Normalize(M33TrnspsMulV3(map1->shape2Vertex, V3LoadU(incidentPolygon.mPlane.n)));
+ const FloatV iPlaneD = V3Dot(incidentNormal, M33MulV3(map1->vertex2Shape, V3LoadU(polyData1.mVerts[inds1[0]])));
+
+ for(PxU32 i=0; i<3; ++i)
+ {
+ if(contains(points1In0, incidentPolygon.mNbVerts, points0In0[i], iPolygonMin, iPolygonMax))
+ {
+
+ inside++;
+
+ const Vec3V vert0 = M33TrnspsMulV3(rot, points0In0[i]);
+ const FloatV t = FSub(V3Dot(incidentNormal, vert0), iPlaneD);
+
+ if(FAllGrtr(t, contactDist))
+ continue;
+
+
+ const Vec3V projPoint = V3NegScaleSub(incidentNormal, t, vert0);
+
+ const Vec3V v = V3Sub(projPoint, vert0);
+ const FloatV t3 = V3Dot(v, contactNormal);
+
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(contactNormal), t3);
+ numManifoldContacts = addMeshContacts(manifoldContacts, projPoint, vert0, localNormalPen, triangleIndex, numManifoldContacts);
+
+ //if the numContacts are more than GU_MESH_CONTACT_REDUCTION_THRESHOLD, we need to do contact reduction
+ const PxU32 numContacts = numManifoldContacts - previousContacts;
+ if(numContacts >= GU_MESH_CONTACT_REDUCTION_THRESHOLD)
+ {
+ //a polygon has more than GU_MESH_CONTACT_REDUCTION_THRESHOLD(16) contacts with this triangle, we will reduce
+ //the contacts to GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE(4) points
+ Gu::SinglePersistentContactManifold::reduceContacts(&manifoldContacts[previousContacts], numContacts);
+ numManifoldContacts = previousContacts + GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE;
+ }
+ }
+
+ }
+
+
+ if(inside == 3)
+ return;
+
+ //(2) segment intesection
+ for (PxU32 rStart = 0, rEnd = 2; rStart < 3; rEnd = rStart++)
+ {
+
+
+ const Vec3V rpA = points0In0[rStart];
+ const Vec3V rpB = points0In0[rEnd];
+
+ const Vec3V rMin = V3Min(rpA, rpB);
+ const Vec3V rMax = V3Max(rpA, rpB);
+
+ for (PxU32 iStart = 0, iEnd = PxU32(incidentPolygon.mNbVerts - 1); iStart < incidentPolygon.mNbVerts; iEnd = iStart++)
+ {
+ if ((!points1In0Penetration[iStart] && !points1In0Penetration[iEnd]))//|| (points1In0[i].status == POINT_OUTSIDE && points1In0[incidentIndex].status == POINT_OUTSIDE))
+ continue;
+
+ const Vec3V ipA = points1In0[iStart];
+ const Vec3V ipB = points1In0[iEnd];
+
+ const Vec3V iMin = V3Min(ipA, ipB);
+ const Vec3V iMax = V3Max(ipA, ipB);
+
+ const BoolV tempCon = BOr(V3IsGrtr(iMin, rMax), V3IsGrtr(rMin, iMax));
+ const BoolV con = BOr(BGetX(tempCon), BGetY(tempCon));
+
+ if (BAllEqTTTT(con))
+ continue;
+
+ FloatV a1 = signed2DTriArea(rpA, rpB, ipA);
+ FloatV a2 = signed2DTriArea(rpA, rpB, ipB);
+
+ if (FAllGrtr(zero, FMul(a1, a2)))
+ {
+ FloatV a3 = signed2DTriArea(ipA, ipB, rpA);
+ FloatV a4 = signed2DTriArea(ipA, ipB, rpB);
+
+ if (FAllGrtr(zero, FMul(a3, a4)))
+ {
+
+ //these two segment intersect in 2d
+ const FloatV t = FMul(a1, FRecip(FSub(a2, a1)));
+
+ const Vec3V ipAOri = V3SetZ(points1In0[iStart], FAdd(points1In0TValue[iStart], d));
+ const Vec3V ipBOri = V3SetZ(points1In0[iEnd], FAdd(points1In0TValue[iEnd], d));
+
+ const Vec3V pBB = V3NegScaleSub(V3Sub(ipBOri, ipAOri), t, ipAOri);
+ const Vec3V pAA = V3SetZ(pBB, d);
+ const Vec3V pA = M33TrnspsMulV3(rot, pAA);
+ const Vec3V pB = M33TrnspsMulV3(rot, pBB);
+ const FloatV pen = FSub(V3GetZ(pBB), V3GetZ(pAA));
+
+ if (FAllGrtr(pen, contactDist))
+ continue;
+
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(contactNormal), pen);
+ numManifoldContacts = addMeshContacts(manifoldContacts, pB, pA, localNormalPen, triangleIndex, numManifoldContacts);
+
+ //if the numContacts are more than GU_MESH_CONTACT_REDUCTION_THRESHOLD, we need to do contact reduction
+ const PxU32 numContacts = numManifoldContacts - previousContacts;
+ if (numContacts >= GU_MESH_CONTACT_REDUCTION_THRESHOLD)
+ {
+ //a polygon has more than GU_MESH_CONTACT_REDUCTION_THRESHOLD(16) contacts with this triangle, we will reduce
+ //the contacts to GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE(4) points
+ Gu::SinglePersistentContactManifold::reduceContacts(&manifoldContacts[previousContacts], numContacts);
+ numManifoldContacts = previousContacts + GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE;
+ }
+ }
+ }
+ }
+
+ }
+
+ }
+
+
+ static void generatedPolyContacts(const Gu::PolygonalData& polyData0, const Gu::HullPolygonData& referencePolygon, const Gu::TriangleV& triangle, const PxU32 triangleIndex, const PxU8 triFlags,
+ Gu::SupportLocal* map0, Gu::MeshPersistentContact* manifoldContacts, PxU32& numManifoldContacts, const Ps::aos::FloatVArg contactDist, const Ps::aos::Vec3VArg contactNormal,
+ Cm::RenderOutput* renderOutput)
+ {
+ PX_UNUSED(triFlags);
+ PX_UNUSED(renderOutput);
+
+ using namespace Ps::aos;
+
+ const FloatV zero = FZero();
+
+ const PxU32 previousContacts = numManifoldContacts;
+
+ const PxU8* inds0 = polyData0.mPolygonVertexRefs + referencePolygon.mVRef8;
+
+ const Vec3V nContactNormal = V3Neg(contactNormal);
+
+ //this is the matrix transform all points to the 2d plane
+ const Mat33V rot = findRotationMatrixFromZAxis(contactNormal);
+
+ Vec3V* points0In0=reinterpret_cast<Vec3V*>(PxAllocaAligned(sizeof(Vec3V)*referencePolygon.mNbVerts, 16));
+ Vec3V points1In0[3];
+ FloatV points1In0TValue[3];
+
+ bool points1In0Penetration[3];
+
+ //Transform all the verts from vertex space to shape space
+ map0->populateVerts(inds0, referencePolygon.mNbVerts, polyData0.mVerts, points0In0);
+
+ points1In0[0] = triangle.verts[0];
+ points1In0[1] = triangle.verts[1];
+ points1In0[2] = triangle.verts[2];
+
+
+#if PCM_LOW_LEVEL_DEBUG
+ Gu::PersistentContactManifold::drawPolygon(*renderOutput, map0->transform, points0In0, referencePolygon.mNbVerts, (PxU32)PxDebugColor::eARGB_GREEN);
+ //Gu::PersistentContactManifold::drawTriangle(*gRenderOutPut, map0->transform.transform(points1In0[0]), map0->transform.transform(points1In0[1]), map0->transform.transform(points1In0[2]), (PxU32)PxDebugColor::eARGB_BLUE);
+#endif
+
+ //the first point in the reference plane
+ const Vec3V referencePoint = points0In0[0];
+
+ Vec3V eps = Vec3V_From_FloatV(FEps());
+ Vec3V max = Vec3V_From_FloatV(FMax());
+ Vec3V nmax = V3Neg(max);
+
+ //transform reference polygon to 2d, calculate min and max
+ Vec3V rPolygonMin= max;
+ Vec3V rPolygonMax = nmax;
+ for(PxU32 i=0; i<referencePolygon.mNbVerts; ++i)
+ {
+ //points0In0[i].vertext = M33TrnspsMulV3(rot, Vec3V_From_PxVec3(polyData0.mVerts[inds0[i]]));
+ points0In0[i] = M33MulV3(rot, points0In0[i]);
+ rPolygonMin = V3Min(rPolygonMin, points0In0[i]);
+ rPolygonMax = V3Max(rPolygonMax, points0In0[i]);
+ }
+
+ rPolygonMin = V3Sub(rPolygonMin, eps);
+ rPolygonMax = V3Add(rPolygonMax, eps);
+
+
+
+ const FloatV d = V3GetZ(points0In0[0]);
+
+ const FloatV rd = FAdd(d, contactDist);
+
+ Vec3V iPolygonMin= max;
+ Vec3V iPolygonMax = nmax;
+
+ PxU32 inside = 0;
+ for(PxU32 i=0; i<3; ++i)
+ {
+ const Vec3V vert1 =points1In0[i]; //this still in polyData1's local space
+ points1In0[i] = M33MulV3(rot, vert1);
+ const FloatV z = V3GetZ(points1In0[i]);
+ points1In0TValue[i] = FSub(z, d);
+ points1In0[i] = V3SetZ(points1In0[i], d);
+ iPolygonMin = V3Min(iPolygonMin, points1In0[i]);
+ iPolygonMax = V3Max(iPolygonMax, points1In0[i]);
+ if(FAllGrtr(rd, z))
+ {
+ points1In0Penetration[i] = true;
+
+ //ML : check to see whether all the points of triangles in 2D space are within reference polygon's range
+ if(contains(points0In0, referencePolygon.mNbVerts, points1In0[i], rPolygonMin, rPolygonMax))
+ {
+ inside++;
+
+ //calculate projection point
+ const FloatV t = V3Dot(contactNormal, V3Sub(vert1, referencePoint));
+ const Vec3V projectPoint = V3NegScaleSub(contactNormal, t, vert1);
+
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(nContactNormal), t);
+ numManifoldContacts = addMeshContacts(manifoldContacts, projectPoint, vert1, localNormalPen, triangleIndex, numManifoldContacts);
+
+ //if the numContacts are more than GU_MESH_CONTACT_REDUCTION_THRESHOLD, we need to do contact reduction
+ const PxU32 numContacts = numManifoldContacts - previousContacts;
+ if(numContacts >= GU_MESH_CONTACT_REDUCTION_THRESHOLD)
+ {
+ //a polygon has more than GU_MESH_CONTACT_REDUCTION_THRESHOLD(16) contacts with this triangle, we will reduce
+ //the contacts to GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE(4) points
+ Gu::SinglePersistentContactManifold::reduceContacts(&manifoldContacts[previousContacts], numContacts);
+ numManifoldContacts = previousContacts + GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE;
+ }
+ }
+ }
+
+ }
+
+
+ if(inside == 3)
+ {
+ return;
+ }
+
+ inside = 0;
+ iPolygonMin = V3Sub(iPolygonMin, eps);
+ iPolygonMax = V3Add(iPolygonMax, eps);
+
+ const Vec3V incidentNormal = triangle.normal();
+ const FloatV iPlaneD = V3Dot(incidentNormal, triangle.verts[0]);
+ const FloatV one = FOne();
+ for(PxU32 i=0; i<referencePolygon.mNbVerts; ++i)
+ {
+ if(contains(points1In0, 3, points0In0[i], iPolygonMin, iPolygonMax))
+ {
+
+ const Vec3V vert0 = M33TrnspsMulV3(rot, points0In0[i]);
+
+ const FloatV t =FSub(V3Dot(incidentNormal, vert0), iPlaneD);
+
+ if(FAllGrtr(t, contactDist))
+ continue;
+
+ const Vec3V projPoint = V3NegScaleSub(incidentNormal, t, vert0);
+
+ FloatV u, w;
+ barycentricCoordinates(projPoint, triangle.verts[0], triangle.verts[1], triangle.verts[2], u, w);
+ const BoolV con = BAnd(FIsGrtrOrEq(u, zero), BAnd(FIsGrtrOrEq(w, zero), FIsGrtrOrEq(one, FAdd(u, w))));
+
+ if(BAllEqTTTT(con))
+ {
+ inside++;
+
+ const Vec3V v = V3Sub(projPoint, vert0);
+ const FloatV t3 = V3Dot(v, contactNormal);
+
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(nContactNormal), t3);
+ numManifoldContacts = addMeshContacts(manifoldContacts, vert0, projPoint, localNormalPen, triangleIndex, numManifoldContacts);
+
+ //if the numContacts are more than GU_MESH_CONTACT_REDUCTION_THRESHOLD, we need to do contact reduction
+ const PxU32 numContacts = numManifoldContacts - previousContacts;
+ if(numContacts >= GU_MESH_CONTACT_REDUCTION_THRESHOLD)
+ {
+ //a polygon has more than GU_MESH_CONTACT_REDUCTION_THRESHOLD(16) contacts with this triangle, we will reduce
+ //the contacts to GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE(4) points
+ Gu::SinglePersistentContactManifold::reduceContacts(&manifoldContacts[previousContacts], numContacts);
+ numManifoldContacts = previousContacts + GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE;
+ }
+ }
+
+ }
+
+ }
+
+ if(inside == referencePolygon.mNbVerts)
+ return;
+
+
+
+ //Always generate segment contacts
+ //(2) segment intesection
+ for (PxU32 iStart = 0, iEnd = 2; iStart < 3; iEnd = iStart++)
+ {
+ if((!points1In0Penetration[iStart] && !points1In0Penetration[iEnd] ) )
+ continue;
+
+ const Vec3V ipA = points1In0[iStart];
+ const Vec3V ipB = points1In0[iEnd];
+
+ const Vec3V iMin = V3Min(ipA, ipB);
+ const Vec3V iMax = V3Max(ipA, ipB);
+
+ for (PxU32 rStart = 0, rEnd = PxU32(referencePolygon.mNbVerts - 1); rStart < referencePolygon.mNbVerts; rEnd = rStart++)
+ {
+
+ const Vec3V rpA = points0In0[rStart];
+ const Vec3V rpB = points0In0[rEnd];
+
+ const Vec3V rMin = V3Min(rpA, rpB);
+ const Vec3V rMax = V3Max(rpA, rpB);
+
+ const BoolV tempCon =BOr(V3IsGrtr(iMin, rMax), V3IsGrtr(rMin, iMax));
+ const BoolV con = BOr(BGetX(tempCon), BGetY(tempCon));
+
+ if(BAllEqTTTT(con))
+ continue;
+
+
+ FloatV a1 = signed2DTriArea(rpA, rpB, ipA);
+ FloatV a2 = signed2DTriArea(rpA, rpB, ipB);
+
+
+ if(FAllGrtr(zero, FMul(a1, a2)))
+ {
+ FloatV a3 = signed2DTriArea(ipA, ipB, rpA);
+ FloatV a4 = signed2DTriArea(ipA, ipB, rpB);
+
+ if(FAllGrtr(zero, FMul(a3, a4)))
+ {
+
+ //these two segment intersect
+ const FloatV t = FMul(a1, FRecip(FSub(a2, a1)));
+
+ const Vec3V ipAOri = V3SetZ(points1In0[iStart], FAdd(points1In0TValue[iStart], d));
+ const Vec3V ipBOri = V3SetZ(points1In0[iEnd], FAdd(points1In0TValue[iEnd], d));
+
+ const Vec3V pBB = V3NegScaleSub(V3Sub(ipBOri, ipAOri), t, ipAOri);
+ const Vec3V pAA = V3SetZ(pBB, d);
+ const Vec3V pA = M33TrnspsMulV3(rot, pAA);
+ const Vec3V pB = M33TrnspsMulV3(rot, pBB);
+ const FloatV pen = FSub(V3GetZ(pBB), V3GetZ(pAA));
+
+ if(FAllGrtr(pen, contactDist))
+ continue;
+
+
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(nContactNormal), pen);
+ numManifoldContacts = addMeshContacts(manifoldContacts, pA, pB, localNormalPen, triangleIndex, numManifoldContacts);
+
+ //if the numContacts are more than GU_MESH_CONTACT_REDUCTION_THRESHOLD, we need to do contact reduction
+ const PxU32 numContacts = numManifoldContacts - previousContacts;
+ if(numContacts >= GU_MESH_CONTACT_REDUCTION_THRESHOLD)
+ {
+ //a polygon has more than GU_MESH_CONTACT_REDUCTION_THRESHOLD(16) contacts with this triangle, we will reduce
+ //the contacts to GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE(4) points
+ Gu::SinglePersistentContactManifold::reduceContacts(&manifoldContacts[previousContacts], numContacts);
+ numManifoldContacts = previousContacts + GU_SINGLE_MANIFOLD_SINGLE_POLYGONE_CACHE_SIZE;
+ }
+ }
+ }
+ }
+ }
+
+ }
+
+
+ bool Gu::PCMConvexVsMeshContactGeneration::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)
+ {
+
+ using namespace Ps::aos;
+
+ const FloatV threshold = FLoad(0.7071f);//about 45 degree0
+ PX_UNUSED(threshold);
+ {
+
+ FeatureStatus status = POLYDATA0;
+ FloatV minOverlap = FMax();
+ //minNormal will be in the local space of polyData
+ Vec3V minNormal = V3Zero();
+
+
+ PxU32 feature0;
+ if(!testTriangleFaceNormal(localTriangle, polyData, localTriMap, polyMap, contactDist, minOverlap, feature0, minNormal, POLYDATA0, status))
+ return false;
+
+ PxU32 feature1;
+ if(!testPolyFaceNormal(localTriangle, polyData, localTriMap, polyMap, contactDist, minOverlap, feature1, minNormal, POLYDATA1, status))
+ return false;
+
+
+ if (!testPolyEdgeNormal(localTriangle, triFlags, polyData, localTriMap, polyMap, contactDist, minOverlap, minNormal, EDGE, status))
+ return false;
+
+
+ const Vec3V triNormal = localTriangle.normal();
+
+ if(status == POLYDATA0)
+ {
+ //minNormal is the triangle normal and it is in the local space of polydata0
+ const Gu::HullPolygonData& referencePolygon = polyData.mPolygons[getPolygonIndex(polyData, polyMap, minNormal)];
+
+ patchNormal = triNormal;
+ generatedTriangleContacts(localTriangle, triangleIndex, triFlags, polyData, referencePolygon, polyMap, manifoldContacts, numContacts, contactDist, triNormal, mRenderOutput);
+
+ }
+ else
+ {
+
+ if(status == POLYDATA1)
+ {
+ const Gu::HullPolygonData* referencePolygon = &polyData.mPolygons[feature1];
+
+ const Vec3V contactNormal = V3Normalize(M33TrnspsMulV3(polyMap->shape2Vertex, V3LoadU(referencePolygon->mPlane.n)));
+ const Vec3V nContactNormal = V3Neg(contactNormal);
+ const FloatV cosTheta = V3Dot(nContactNormal, triNormal);
+
+ if(FAllGrtr(cosTheta, threshold))
+ {
+ patchNormal = triNormal;
+ generatedTriangleContacts(localTriangle, triangleIndex, triFlags, polyData, *referencePolygon, polyMap, manifoldContacts, numContacts, contactDist, triNormal, mRenderOutput);
+ }
+ else
+ {
+ //ML : defer the contacts generation
+ const PxU32 nb = sizeof(PCMDeferredPolyData)/sizeof(PxU32);
+ PxU32 newSize = nb + mDeferredContacts.size();
+ mDeferredContacts.reserve(newSize);
+ PCMDeferredPolyData* PX_RESTRICT data = reinterpret_cast<PCMDeferredPolyData*>(mDeferredContacts.end());
+ mDeferredContacts.forceSize_Unsafe(newSize);
+
+ data->mTriangleIndex = triangleIndex;
+ data->mFeatureIndex = feature1;
+ data->triFlags = triFlags;
+ data->mInds[0] = triIndices[0];
+ data->mInds[1] = triIndices[1];
+ data->mInds[2] = triIndices[2];
+ V3StoreU(localTriangle.verts[0], data->mVerts[0]);
+ V3StoreU(localTriangle.verts[1], data->mVerts[1]);
+ V3StoreU(localTriangle.verts[2], data->mVerts[2]);
+ return true;
+
+ }
+ }
+ else
+ {
+ feature1 = PxU32(getPolygonIndex(polyData, polyMap, minNormal));
+ const Gu::HullPolygonData* referencePolygon = &polyData.mPolygons[feature1];
+
+ const Vec3V contactNormal = V3Normalize(M33TrnspsMulV3(polyMap->shape2Vertex, V3LoadU(referencePolygon->mPlane.n)));
+ const Vec3V nContactNormal = V3Neg(contactNormal);
+
+ //if the minimum sperating axis is edge case, we don't defer it because it is an activeEdge
+ patchNormal = nContactNormal;
+ generatedPolyContacts(polyData, *referencePolygon, localTriangle, triangleIndex, triFlags, polyMap, manifoldContacts, numContacts, contactDist, contactNormal, mRenderOutput);
+
+ }
+
+
+ }
+
+ }
+
+ return true;
+ }
+
+
+ bool Gu::PCMConvexVsMeshContactGeneration::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)
+ {
+
+ using namespace Ps::aos;
+
+ const FloatV threshold = FLoad(0.7071f);//about 45 degree
+ PX_UNUSED(threshold);
+ {
+
+ FeatureStatus status = POLYDATA0;
+ FloatV minOverlap = FMax();
+ //minNormal will be in the local space of polyData
+ Vec3V minNormal = V3Zero();
+
+ PxU32 feature0;
+ if(!testTriangleFaceNormal(localTriangle, polyData, localTriMap, polyMap, contactDist, minOverlap, feature0, minNormal, POLYDATA0, status))
+ return false;
+
+ PxU32 feature1;
+ if(!testPolyFaceNormal(localTriangle, polyData, localTriMap, polyMap, contactDist, minOverlap, feature1, minNormal, POLYDATA1, status))
+ return false;
+
+ if(!testPolyEdgeNormal(localTriangle, triFlags, polyData, localTriMap, polyMap, contactDist, minOverlap, minNormal, EDGE, status))
+ return false;
+
+ const Vec3V triNormal = localTriangle.normal();
+ patchNormal = triNormal;
+
+ const Gu::HullPolygonData* referencePolygon = &polyData.mPolygons[getPolygonIndex(polyData, polyMap, triNormal)];
+ generatedTriangleContacts(localTriangle, triangleIndex, triFlags, polyData, *referencePolygon, polyMap, manifoldContacts, numContacts, contactDist, triNormal, renderOutput);
+
+ }
+
+ return true;
+ }
+
+ bool Gu::PCMConvexVsMeshContactGeneration::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)
+ {
+
+ using namespace Ps::aos;
+
+ const Gu::HullPolygonData* referencePolygon = &mPolyData.mPolygons[featureIndex];
+
+ const Vec3V contactNormal = V3Normalize(M33TrnspsMulV3(mPolyMap->shape2Vertex, V3LoadU(referencePolygon->mPlane.n)));
+ const Vec3V nContactNormal = V3Neg(contactNormal);
+
+ patchNormal = nContactNormal;
+ generatedPolyContacts(mPolyData, *referencePolygon, localTriangle, triangleIndex, triFlags, mPolyMap, manifoldContacts, numContacts, contactDist, contactNormal, mRenderOutput);
+
+ return true;
+ }
+
+
+}//physx