diff options
| author | git perforce import user <a@b> | 2016-10-25 12:29:14 -0600 |
|---|---|---|
| committer | Sheikh Dawood Abdul Ajees <Sheikh Dawood Abdul Ajees> | 2016-10-25 18:56:37 -0500 |
| commit | 3dfe2108cfab31ba3ee5527e217d0d8e99a51162 (patch) | |
| tree | fa6485c169e50d7415a651bf838f5bcd0fd3bfbd /PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMTriangleContactGen.cpp | |
| download | physx-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.cpp | 1250 |
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 |