aboutsummaryrefslogtreecommitdiff
path: root/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactBoxBox.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/GuPCMContactBoxBox.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/GuPCMContactBoxBox.cpp')
-rw-r--r--PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactBoxBox.cpp1029
1 files changed, 1029 insertions, 0 deletions
diff --git a/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactBoxBox.cpp b/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactBoxBox.cpp
new file mode 100644
index 00000000..28417e66
--- /dev/null
+++ b/PhysX_3.4/Source/GeomUtils/src/pcm/GuPCMContactBoxBox.cpp
@@ -0,0 +1,1029 @@
+// 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 "GuVecBox.h"
+#include "GuVecShrunkBox.h"
+#include "GuGeometryUnion.h"
+
+#include "GuConvexHelper.h"
+#include "GuPCMShapeConvex.h"
+#include "GuContactMethodImpl.h"
+#include "GuContactBuffer.h"
+#include "GuPCMContactGenUtil.h"
+
+
+namespace physx
+{
+
+namespace Gu
+{
+
+ static void getIncidentPolygon(Ps::aos::Vec3V* pts, Ps::aos::Vec3V& faceNormal, const Ps::aos::Vec3VArg axis, const Ps::aos::PsMatTransformV& transf1To0,
+ const Ps::aos::Vec3VArg extents)
+ {
+
+ using namespace Ps::aos;
+
+ const FloatV zero = FZero();
+
+ FloatV ex = V3GetX(extents);
+ FloatV ey = V3GetY(extents);
+ FloatV ez = V3GetZ(extents);
+
+ const Vec3V u0 = transf1To0.getCol0();
+ const Vec3V u1 = transf1To0.getCol1();
+ const Vec3V u2 = transf1To0.getCol2();
+
+ //calcaulte the insident face for b
+ const FloatV d0 = V3Dot(u0, axis);
+ const FloatV d1 = V3Dot(u1, axis);
+ const FloatV d2 = V3Dot(u2, axis);
+
+ const FloatV absd0 = FAbs(d0);
+ const FloatV absd1 = FAbs(d1);
+ const FloatV absd2 = FAbs(d2);
+
+ Vec3V r0, r1, r2;
+
+
+ if(FAllGrtrOrEq(absd0, absd1) && FAllGrtrOrEq(absd0, absd2))
+ {
+ //the incident face is on u0
+ const BoolV con = FIsGrtr(d0, zero);
+ faceNormal = V3Sel(con, V3Neg(u0), u0);
+ ex = FSel(con, FNeg(ex), ex);
+ r0 = V3Scale(u0, ex);
+ r1 = V3Scale(u1, ey);
+ r2 = V3Scale(u2, ez);
+
+ const Vec3V temp0 = V3Add(transf1To0.p, r0);
+ const Vec3V temp1 = V3Add(r1, r2);
+ const Vec3V temp2 = V3Sub(r1, r2);
+
+
+ pts[0] = V3Add(temp0, temp1); // (-x/x, y, z)
+ pts[1] = V3Add(temp0, temp2); // (-x/x, y, -z)
+ pts[2] = V3Sub(temp0, temp1); // (-x/x, -y, -z)
+ pts[3] = V3Sub(temp0, temp2); // (-x/x, -y, z)
+
+ }
+ else if(FAllGrtrOrEq(absd1, absd2))
+ {
+ //the incident face is on u1
+ const BoolV con = FIsGrtr(d1, zero);
+ faceNormal = V3Sel(con, V3Neg(u1), u1);
+ ey = FSel(con, FNeg(ey), ey);
+ r0 = V3Scale(u0, ex);
+ r1 = V3Scale(u1, ey);
+ r2 = V3Scale(u2, ez);
+
+ const Vec3V temp0 = V3Add(transf1To0.p, r1);
+ const Vec3V temp1 = V3Add(r0, r2);
+ const Vec3V temp2 = V3Sub(r0, r2);
+
+ pts[0] = V3Add(temp0, temp1); // (x, -y/y, z)
+ pts[1] = V3Add(temp0, temp2); // (x, -y/y, -z)
+ pts[2] = V3Sub(temp0, temp1); // (-x, -y/y, -z)
+ pts[3] = V3Sub(temp0, temp2); // (-x, -y/y, z)
+
+ }
+ else
+ {
+ //the incident face is on u2
+ const BoolV con = FIsGrtr(d2, zero);
+ faceNormal = V3Sel(con, V3Neg(u2), u2);
+ ez = FSel(con, FNeg(ez), ez);
+ r0 = V3Scale(u0, ex);
+ r1 = V3Scale(u1, ey);
+ r2 = V3Scale(u2, ez);
+
+ const Vec3V temp0 = V3Add(transf1To0.p, r2);
+ const Vec3V temp1 = V3Add(r0, r1);
+ const Vec3V temp2 = V3Sub(r0, r1);
+
+ pts[0] = V3Add(temp0, temp1); // ( x, y, z)
+ pts[1] = V3Add(temp0, temp2); // ( x, -y, z)
+ pts[2] = V3Sub(temp0, temp1); // (-x, -y, z)
+ pts[3] = V3Sub(temp0, temp2); // (-x, y, z)
+ }
+ }
+
+
+ //p0 and p1 is in the local space of AABB
+ static bool intersectSegmentAABB(const Ps::aos::Vec3VArg p0, const Ps::aos::Vec3VArg d, const Ps::aos::Vec3VArg max, const Ps::aos::Vec3VArg min, Ps::aos::FloatV& tmin, Ps::aos::FloatV& tmax)
+ {
+ using namespace Ps::aos;
+
+ const Vec3V eps = V3Load(1e-6);
+ const Vec3V absV = V3Abs(d);
+ const FloatV one = FOne();
+ const Vec3V zero = V3Zero();
+ const Vec3V fMax = Vec3V_From_FloatV(FMax());
+
+ FloatV tminf = FZero();
+ FloatV tmaxf = one;
+ const BoolV isParallel = V3IsGrtr(eps, absV);
+ const BoolV isOutsideOfRange = BOr(V3IsGrtr(p0, max), V3IsGrtr(min, p0));
+ //const BoolV isParallelAndOutOfRange = BAnd(isParallel, isOutsideOfRange);
+
+ if(!BAllEqFFFF(BAnd(isParallel, isOutsideOfRange)))
+ {
+ return false;
+ }
+
+ const Vec3V odd = V3RecipFast(d);
+ const Vec3V t1 = V3Sel(isParallel, zero, V3Mul(V3Sub(min, p0), odd));
+ const Vec3V t2 = V3Sel(isParallel, fMax, V3Mul(V3Sub(max, p0), odd));
+
+ const Vec3V tt1 = V3Min(t1, t2);
+ const Vec3V tt2 = V3Max(t1, t2);
+
+ const FloatV ft1 = V3ExtractMax(tt1);
+ const FloatV ft2 = V3ExtractMin(tt2);
+
+ tminf = FMax(ft1, tminf);
+ tmaxf = FMin(tmaxf, ft2);
+
+ tmin = tminf;
+ tmax = tmaxf;
+
+ const BoolV con0 = FIsGrtr(tminf, tmaxf);
+ const BoolV con1 = FIsGrtr(tminf, one);
+ const BoolV isNotIntersect = BOr(con0, con1);
+ return BAllEqFFFF(isNotIntersect) == 1;
+ }
+
+
+ //pts, faceNormal and contact normal are in the local space of new space
+ static void calculateContacts( const Ps::aos::FloatVArg extentX, const Ps::aos::FloatVArg extentY, Ps::aos::Vec3V* pts, const Ps::aos::Vec3VArg incidentFaceNormalInNew, const Ps::aos::Vec3VArg localNormal, Gu::PersistentContact* manifoldContacts, PxU32& numContacts, const Ps::aos::FloatVArg contactDist)
+ {
+ using namespace Ps::aos;
+
+ const FloatV zero = FZero();
+ const FloatV max = FMax();
+
+ const FloatV nExtentX = FNeg(extentX);
+ const FloatV nExtentY = FNeg(extentY);
+
+ bool pPenetration[4];
+ bool pArea[4];
+
+ Vec3V bmin = V3Splat(max);
+ Vec3V bmax = V3Neg(bmin);
+
+ const Vec3V bound = V3Merge(extentX, extentY, max);
+
+
+ //get the projection point of pts
+ for(PxU32 i=0; i< 4; ++i)
+ {
+ bmin = V3Min(bmin, pts[i]);
+ bmax = V3Max(bmax, pts[i]);
+ const FloatV z = FNeg(V3GetZ(pts[i]));
+ if(FAllGrtr(contactDist, z))
+ {
+
+ pPenetration[i] = true;
+
+ const Vec3V absPt= V3Abs(pts[i]);
+ const BoolV con = V3IsGrtrOrEq(bound, absPt);
+ if(BAllEqTTTT(con))
+ {
+ pArea[i] = true;
+
+ //Add the point to the manifold
+ manifoldContacts[numContacts].mLocalPointA = V3SetZ(pts[i], zero); //transformNewTo0.transform(localPointA);
+ manifoldContacts[numContacts].mLocalPointB = pts[i];//transform1ToNew.transformInv(pts[i]);
+ manifoldContacts[numContacts++].mLocalNormalPen = V4SetW(Vec4V_From_Vec3V(localNormal), z);
+ }
+ else
+ {
+ pArea[i] = false;
+ }
+ }
+ else
+ {
+ pPenetration[i] = false;
+ pArea[i] = false;
+ }
+
+ }
+
+ if(numContacts == 4)
+ return;
+
+ //if(pPenetration[0] && pPenetration[1] && pPenetration[2] && pPenetration[3])
+ {
+ //if(!pArea[0] || !pArea[1] || !pArea[2] || !pArea[3])
+ {
+ const FloatV denom = V3GetZ(incidentFaceNormalInNew);
+ {
+ const Vec3V q0 = V3Merge(extentX, extentY, zero);
+
+ if(contains(pts, 4, q0, bmin, bmax))
+ {
+ const FloatV nom = V3Dot(incidentFaceNormalInNew, V3Sub(pts[0], q0));
+ const FloatV t = FDiv(nom, denom);
+ const FloatV pen = FNeg(t);
+ if(FAllGrtr(contactDist, pen))
+ {
+ manifoldContacts[numContacts].mLocalPointA = q0;
+ manifoldContacts[numContacts].mLocalPointB = V3SetZ(q0, t);
+ manifoldContacts[numContacts++].mLocalNormalPen = V4SetW(Vec4V_From_Vec3V(localNormal), pen);
+ }
+ }
+ }
+
+ {
+ const Vec3V q0 = V3Merge(extentX, nExtentY, zero);
+ if(contains(pts, 4, q0, bmin, bmax))
+ {
+ const FloatV nom = V3Dot(incidentFaceNormalInNew, V3Sub(pts[0], q0));
+ const FloatV t = FDiv(nom, denom);
+ const FloatV pen = FNeg(t);
+ if(FAllGrtr(contactDist, pen))
+ {
+ manifoldContacts[numContacts].mLocalPointA = q0;
+ manifoldContacts[numContacts].mLocalPointB = V3SetZ(q0, t);
+ manifoldContacts[numContacts++].mLocalNormalPen = V4SetW(Vec4V_From_Vec3V(localNormal), pen);
+ }
+ }
+ }
+
+ {
+ const Vec3V q0 = V3Merge( nExtentX, extentY, zero);
+ if(contains(pts, 4, q0, bmin, bmax))
+ {
+ const FloatV nom = V3Dot(incidentFaceNormalInNew, V3Sub(pts[0], q0));
+ const FloatV t = FDiv(nom, denom);
+ const FloatV pen = FNeg(t);
+ if(FAllGrtr(contactDist, pen))
+ {
+ manifoldContacts[numContacts].mLocalPointA = q0;
+ manifoldContacts[numContacts].mLocalPointB = V3SetZ(q0, t);
+ manifoldContacts[numContacts++].mLocalNormalPen = V4SetW(Vec4V_From_Vec3V(localNormal), pen);
+ }
+ }
+ }
+
+ {
+ const Vec3V q0 = V3Merge(nExtentX, nExtentY, zero);
+
+ if(contains(pts, 4, q0, bmin, bmax))
+ {
+ const FloatV nom = V3Dot(incidentFaceNormalInNew, V3Sub(pts[0], q0));
+ const FloatV t = FDiv(nom, denom);
+ const FloatV pen = FNeg(t);
+ if(FAllGrtr(contactDist, pen))
+ {
+ manifoldContacts[numContacts].mLocalPointA = q0;
+ manifoldContacts[numContacts].mLocalPointB = V3SetZ(q0, t);
+ manifoldContacts[numContacts++].mLocalNormalPen = V4SetW(Vec4V_From_Vec3V(localNormal), pen);
+ }
+ }
+ }
+ }
+ }
+
+
+
+ const Vec3V ext = V3Merge(extentX, extentY, max);
+ const Vec3V negExt = V3Merge(nExtentX, nExtentY, FNeg(FAdd(contactDist, FEps())));
+
+ for (PxU32 rStart = 0, rEnd = 3; rStart < 4; rEnd = rStart++)
+ {
+ const Vec3V p0 = pts[rStart];
+ const Vec3V p1 = pts[rEnd];
+
+ if(!pPenetration[rStart] && !pPenetration[rEnd])
+ continue;
+
+ const bool con0 = pPenetration[rStart] && pArea[rStart];
+ const bool con1 = pPenetration[rEnd] && pArea[rEnd];
+ if(con0 && con1)
+ continue;
+
+ //intersect t value with x plane
+ const Vec3V p0p1 = V3Sub(p1, p0);
+
+ FloatV tmin, tmax;
+ if(Gu::intersectSegmentAABB(p0, p0p1, ext, negExt, tmin, tmax))
+ {
+ if(!con0)
+ {
+ const Vec3V intersectP = V3ScaleAdd(p0p1, tmin, p0);
+ manifoldContacts[numContacts].mLocalPointA = V3SetZ(intersectP, zero);
+ manifoldContacts[numContacts].mLocalPointB = intersectP;
+ manifoldContacts[numContacts++].mLocalNormalPen = V4SetW(Vec4V_From_Vec3V(localNormal), FNeg(V3GetZ(intersectP)));
+ }
+ if(!con1)
+ {
+ const Vec3V intersectP = V3ScaleAdd(p0p1, tmax, p0);
+ manifoldContacts[numContacts].mLocalPointA = V3SetZ(intersectP, zero);
+ manifoldContacts[numContacts].mLocalPointB = intersectP;
+ manifoldContacts[numContacts++].mLocalNormalPen = V4SetW(Vec4V_From_Vec3V(localNormal), FNeg(V3GetZ(intersectP)));
+ }
+ }
+ }
+}
+
+
+static PxU32 doBoxBoxGenerateContacts(const Ps::aos::Vec3VArg box0Extent, const Ps::aos::Vec3VArg box1Extent, const Ps::aos::PsMatTransformV& transform0, const Ps::aos::PsMatTransformV& transform1, const Ps::aos::FloatVArg contactDist, Gu::PersistentContact* manifoldContacts, PxU32& numContacts)
+{
+ using namespace Ps::aos;
+
+ const FloatV ea0 = V3GetX(box0Extent);
+ const FloatV ea1 = V3GetY(box0Extent);
+ const FloatV ea2 = V3GetZ(box0Extent);
+
+ const FloatV eb0 = V3GetX(box1Extent);
+ const FloatV eb1 = V3GetY(box1Extent);
+ const FloatV eb2 = V3GetZ(box1Extent);
+
+
+ const PsMatTransformV transform1To0 = transform0.transformInv(transform1);
+ const Mat33V rot0To1 =M33Trnsps(transform1To0.rot);
+
+ const Vec3V uEps = V3Load(1e-6f);
+
+ const FloatV zero = FZero();
+
+ const FloatV tx = V3GetX(transform1To0.p);
+ const FloatV ty = V3GetY(transform1To0.p);
+ const FloatV tz = V3GetZ(transform1To0.p);
+ const Vec3V col0 = transform1To0.getCol0();
+ const Vec3V col1 = transform1To0.getCol1();
+ const Vec3V col2 = transform1To0.getCol2();
+
+ const Vec3V abs1To0Col0 = V3Add(V3Abs(col0), uEps);
+ const Vec3V abs1To0Col1 = V3Add(V3Abs(col1), uEps);
+ const Vec3V abs1To0Col2 = V3Add(V3Abs(col2), uEps);
+
+ const Vec3V abs0To1Col0 = V3Add(V3Abs(rot0To1.col0), uEps);
+ const Vec3V abs0To1Col1 = V3Add(V3Abs(rot0To1.col1), uEps);
+ const Vec3V abs0To1Col2 = V3Add(V3Abs(rot0To1.col2), uEps);
+
+
+ FloatV sign[6];
+ FloatV overlap[6];
+
+ FloatV ra, rb, radiusSum;
+ //ua0
+ {
+
+ sign[0] = tx;
+
+ const Vec3V vtemp3 = V3Mul(abs0To1Col0, box1Extent);
+ rb = FAdd(V3GetX(vtemp3), FAdd(V3GetY(vtemp3), V3GetZ(vtemp3)));
+
+ radiusSum = FAdd(ea0, rb);
+ overlap[0] = FAdd(FSub(radiusSum, FAbs(sign[0])), contactDist);
+ if(FAllGrtr(zero, overlap[0]))
+ return false;
+ }
+
+ //ua1
+ {
+ sign[1] = ty;
+
+ const Vec3V vtemp3 = V3Mul(abs0To1Col1, box1Extent);
+ rb = FAdd(V3GetX(vtemp3), FAdd(V3GetY(vtemp3), V3GetZ(vtemp3)));
+
+ radiusSum = FAdd(ea1, rb);
+ overlap[1] = FAdd(FSub(radiusSum, FAbs(sign[1])), contactDist);
+ if(FAllGrtr(zero, overlap[1]))
+ return false;
+
+ }
+
+
+ //ua2
+ {
+ sign[2] = tz;
+ ra = ea2;
+
+ const Vec3V vtemp3 = V3Mul(abs0To1Col2, box1Extent);
+ rb = FAdd(V3GetX(vtemp3), FAdd(V3GetY(vtemp3), V3GetZ(vtemp3)));
+
+ radiusSum = FAdd(ea2, rb);
+ overlap[2] = FAdd(FSub(radiusSum, FAbs(sign[2])), contactDist);
+ if(FAllGrtr(zero, overlap[2]))
+ return false;
+
+ }
+
+ //ub0
+ {
+ sign[3] = V3Dot(transform1To0.p, col0);
+
+ const Vec3V vtemp3 = V3Mul(abs1To0Col0, box0Extent);
+ ra = FAdd(V3GetX(vtemp3), FAdd(V3GetY(vtemp3), V3GetZ(vtemp3)));
+
+ radiusSum = FAdd(ra, eb0);
+ overlap[3] = FAdd(FSub(radiusSum, FAbs(sign[3])), contactDist);
+ if(FAllGrtr(zero, overlap[3]))
+ return false;
+
+ }
+
+ //ub1
+ {
+ sign[4] = V3Dot(transform1To0.p, col1);
+
+ const Vec3V vtemp3 = V3Mul(abs1To0Col1, box0Extent);
+ ra = FAdd(V3GetX(vtemp3), FAdd(V3GetY(vtemp3), V3GetZ(vtemp3)));
+
+ radiusSum = FAdd(ra, eb1);
+ overlap[4] = FAdd(FSub(radiusSum, FAbs(sign[4])), contactDist);
+ if(FAllGrtr(zero, overlap[4]))
+ return false;
+ }
+
+ //ub2
+ {
+ sign[5] = V3Dot(transform1To0.p, col2);
+
+ const Vec3V vtemp3 = V3Mul(abs1To0Col2, box0Extent);
+ ra = FAdd(V3GetX(vtemp3), FAdd(V3GetY(vtemp3), V3GetZ(vtemp3)));
+
+ radiusSum = FAdd(ra, eb2);
+ overlap[5] = FAdd(FSub(radiusSum, FAbs(sign[5])), contactDist);
+ if(FAllGrtr(zero, overlap[5]))
+ return false;
+ }
+
+
+ //ua0 X ub0
+ {
+ //B into A's space, ua0Xub0[0,-b3, b2]
+ const FloatV absSign = FAbs(FSub(FMul(V3GetY(col0), tz), FMul(V3GetZ(col0), ty)));
+
+ //B into A's space, ua0Xub0[0,-b3, b2]
+ const FloatV vtemp0 = FMul(V3GetZ(abs1To0Col0), ea1);
+ const FloatV vtemp1 = FMul(V3GetY(abs1To0Col0), ea2);
+ ra = FAdd(vtemp0, vtemp1);
+
+ //A into B's space, ua0Xub0[0, a3, -a2]
+ const FloatV vtemp01 = FMul(V3GetZ(abs0To1Col0), eb1);
+ const FloatV vtemp02 = FMul(V3GetY(abs0To1Col0), eb2);
+ rb = FAdd(vtemp01, vtemp02);
+
+ radiusSum = FAdd(FAdd(ra, rb), contactDist);
+ if(FAllGrtr(absSign, radiusSum)) return false;
+ }
+
+ //ua0 X ub1
+ {
+ //B into A's space, ua0Xub0[0, -b3, b2]
+ const FloatV absSign = FAbs(FSub(FMul(V3GetY(col1), tz), FMul(V3GetZ(col1), ty)));
+
+ //B into A's space, ua0Xub0[0, -b3, b2]
+ const FloatV vtemp0 = FMul(V3GetZ(abs1To0Col1), ea1);
+ const FloatV vtemp1 = FMul(V3GetY(abs1To0Col1), ea2);
+ ra = FAdd(vtemp0, vtemp1);
+
+ //A into B's space, ua0Xub1[-a3, 0, a1]
+ const FloatV vtemp01 = FMul(V3GetZ(abs0To1Col0), eb0);
+ const FloatV vtemp02 = FMul(V3GetX(abs0To1Col0), eb2);
+ rb = FAdd(vtemp01, vtemp02);
+
+ radiusSum = FAdd(FAdd(ra, rb), contactDist);
+
+ if(FAllGrtr(absSign, radiusSum)) return false;
+
+ }
+
+ //ua0 X ub2
+ {
+ //B into A's space, ua0Xub0[0, -b3, b2]
+ const FloatV absSign = FAbs(FSub(FMul(V3GetY(col2), tz), FMul(V3GetZ(col2), ty)));
+
+
+ //B into A's space, ua0Xub0[0, -b3, b2]
+ const FloatV vtemp0 = FMul(V3GetZ(abs1To0Col2), ea1);
+ const FloatV vtemp1 = FMul(V3GetY(abs1To0Col2), ea2);
+ ra = FAdd(vtemp0, vtemp1);
+
+ //A into B's space, ua0Xub1[a2, -a1, 0]
+ const FloatV vtemp01 = FMul(V3GetY(abs0To1Col0), eb0);
+ const FloatV vtemp02 = FMul(V3GetX(abs0To1Col0), eb1);
+ rb = FAdd(vtemp01, vtemp02);
+
+ radiusSum = FAdd(FAdd(ra, rb), contactDist);
+ if(FAllGrtr(absSign, radiusSum)) return false;
+
+ }
+
+ //ua1 X ub0
+ {
+ //B into A's space, ua0Xub0[b3, 0, -b1]
+ const FloatV absSign = FAbs(FSub(FMul(V3GetZ(col0), tx), FMul(V3GetX(col0), tz)));
+
+ //B into A's space, ua0Xub0[b3, 0, -b1]
+ const FloatV vtemp0 = FMul(V3GetZ(abs1To0Col0), ea0);
+ const FloatV vtemp1 = FMul(V3GetX(abs1To0Col0), ea2);
+ ra = FAdd(vtemp0, vtemp1);
+
+ //A into B's space, ua0Xub1[0, a3, -a2]
+ const FloatV vtemp01 = FMul(V3GetZ(abs0To1Col1), eb1);
+ const FloatV vtemp02 = FMul(V3GetY(abs0To1Col1), eb2);
+ rb = FAdd(vtemp01, vtemp02);
+
+ radiusSum = FAdd(FAdd(ra, rb), contactDist);
+ if(FAllGrtr(absSign, radiusSum))return false;
+
+ }
+
+ //ua1 X ub1
+ {
+ //B into A's space, ua0Xub0[b3, 0, -b1]
+ const FloatV absSign = FAbs(FSub(FMul(V3GetZ(col1), tx), FMul(V3GetX(col1), tz)));
+
+ //B into A's space, ua0Xub0[b3, 0, -b1]
+ const FloatV vtemp0 = FMul(V3GetZ(abs1To0Col1), ea0);
+ const FloatV vtemp1 = FMul(V3GetX(abs1To0Col1), ea2);
+ ra = FAdd(vtemp0, vtemp1);
+
+ //A into B's space, ua0Xub1[-a3, 0, -a1]
+ const FloatV vtemp01 = FMul(V3GetZ(abs0To1Col1), eb0);
+ const FloatV vtemp02 = FMul(V3GetX(abs0To1Col1), eb2);
+ rb = FAdd(vtemp01, vtemp02);
+
+ radiusSum = FAdd(FAdd(ra, rb), contactDist);
+ if(FAllGrtr(absSign, radiusSum))return false;
+ }
+
+ //ua1 X ub2
+ {
+ //B into A's space, ua0Xub0[b3, 0, -b1]
+ const FloatV absSign=FAbs(FSub(FMul(V3GetZ(col2), tx), FMul(V3GetX(col2), tz)));
+
+ //B into A's space, ua0Xub0[b3, 0, -b1]
+ const FloatV vtemp0 = FMul(V3GetZ(abs1To0Col2), ea0);
+ const FloatV vtemp1 = FMul(V3GetX(abs1To0Col2), ea2);
+ ra = FAdd(vtemp0, vtemp1);
+
+ //A into B's space, ua0Xub1[a2, -a1, 0]
+ const FloatV vtemp01 = FMul(V3GetY(abs0To1Col1), eb0);
+ const FloatV vtemp02 = FMul(V3GetX(abs0To1Col1), eb1);
+ rb = FAdd(vtemp01, vtemp02);
+
+ radiusSum = FAdd(FAdd(ra, rb), contactDist);
+ if(FAllGrtr(absSign, radiusSum))return false;
+ }
+
+ //ua2 X ub0
+ {
+ //B into A's space, ua2Xub0[-b2, b1, 0]
+ const FloatV absSign = FAbs(FSub(FMul(V3GetX(col0), ty), FMul(V3GetY(col0), tx)));
+
+
+ //B into A's space, ua2Xub0[-b2, b1, 0]
+ const FloatV vtemp0 = FMul(V3GetY(abs1To0Col0), ea0);
+ const FloatV vtemp1 = FMul(V3GetX(abs1To0Col0), ea1);
+ ra = FAdd(vtemp0, vtemp1);
+
+ //A into B's space, ua0Xub1[0, a3, -a2]
+ const FloatV vtemp01 = FMul(V3GetZ(abs0To1Col2), eb1);
+ const FloatV vtemp02 = FMul(V3GetY(abs0To1Col2), eb2);
+ rb = FAdd(vtemp01, vtemp02);
+
+ radiusSum = FAdd(FAdd(ra, rb), contactDist);
+ if(FAllGrtr(absSign, radiusSum))return false;
+ }
+
+ //ua2 X ub1
+ {
+ //B into A's space, ua2Xub0[-b2, b1, 0]
+ const FloatV absSign = FAbs(FSub(FMul(V3GetX(col1), ty), FMul(V3GetY(col1), tx)));
+
+ //B into A's space, ua2Xub0[-b2, b1, 0]
+ const FloatV vtemp0 = FMul(V3GetY(abs1To0Col1), ea0);
+ const FloatV vtemp1 = FMul(V3GetX(abs1To0Col1), ea1);
+ ra = FAdd(vtemp0, vtemp1);
+
+ //A into B's space, ua0Xub1[-a3, 0, a1]
+ const FloatV vtemp01 = FMul(V3GetZ(abs0To1Col2), eb0);
+ const FloatV vtemp02 = FMul(V3GetX(abs0To1Col2), eb2);
+ rb = FAdd(vtemp01, vtemp02);
+
+ radiusSum = FAdd(FAdd(ra, rb), contactDist);
+ if(FAllGrtr(absSign, radiusSum))return false;
+ }
+
+ //ua2 X ub2
+ {
+ //B into A's space, ua2Xub0[-b2, b1, 0]
+ const FloatV absSign=FAbs(FSub(FMul(V3GetX(col2), ty), FMul(V3GetY(col2), tx)));
+
+ //B into A's space, ua2Xub0[-b2, b1, 0]
+ const FloatV vtemp0 = FMul(V3GetY(abs1To0Col2), ea0);
+ const FloatV vtemp1 = FMul(V3GetX(abs1To0Col2), ea1);
+ ra = FAdd(vtemp0, vtemp1);
+
+ //A into B's space, ua0Xub1[a2, -a1, 0]
+ const FloatV vtemp01 = FMul(V3GetY(abs0To1Col2), eb0);
+ const FloatV vtemp02 = FMul(V3GetX(abs0To1Col2), eb1);
+ rb = FAdd(vtemp01, vtemp02);
+
+ radiusSum = FAdd(FAdd(ra, rb), contactDist);
+ if(FAllGrtr(absSign, radiusSum))return false;
+ }
+
+ Vec3V mtd;
+
+ PxU32 feature = 0;
+ FloatV minOverlap = overlap[0];
+
+ for(PxU32 i=1; i<6; ++i)
+ {
+ if(FAllGrtr(minOverlap, overlap[i]))
+ {
+ minOverlap = overlap[i];
+ feature = i;
+ }
+ }
+
+
+ PsMatTransformV newTransformV;
+ const Vec3V axis00 = transform0.getCol0();
+ const Vec3V axis01 = transform0.getCol1();
+ const Vec3V axis02 = transform0.getCol2();
+ const Vec3V axis10 = transform1.getCol0();
+ const Vec3V axis11 = transform1.getCol1();
+ const Vec3V axis12 = transform1.getCol2();
+
+ Vec3V incidentFaceNormalInNew;
+ Vec3V pts[4];
+ bool flip = false;
+ switch(feature)
+ {
+ case 0: //ua0
+ {
+
+
+ if(FAllGrtrOrEq(zero, sign[0]))
+ {
+ mtd = axis00;
+ newTransformV.rot.col0 = V3Neg(axis02);
+ newTransformV.rot.col1 = axis01;
+ newTransformV.rot.col2 = axis00;
+ newTransformV.p = V3NegScaleSub(axis00, ea0, transform0.p);
+ }
+ else
+ {
+
+ const Vec3V nAxis00 = V3Neg(axis00);
+ mtd = nAxis00;
+ newTransformV.rot.col0 = axis02;
+ newTransformV.rot.col1 = axis01;
+ newTransformV.rot.col2 = nAxis00;
+ newTransformV.p = V3ScaleAdd(axis00, ea0, transform0.p);
+
+ }
+
+ const Ps::aos::PsMatTransformV transform1ToNew = newTransformV.transformInv(transform1);
+ const Vec3V localNormal =newTransformV.rotateInv(mtd);
+ getIncidentPolygon(pts, incidentFaceNormalInNew, V3Neg(localNormal), transform1ToNew, box1Extent);
+
+ calculateContacts(ea2, ea1, pts, incidentFaceNormalInNew, localNormal, manifoldContacts, numContacts, contactDist);
+
+
+ break;
+ };
+ case 1: //ua1
+ {
+
+ if(FAllGrtrOrEq(zero, sign[1]))
+ {
+ mtd = axis01;
+ newTransformV.rot.col0 = axis00;
+ newTransformV.rot.col1 = V3Neg(axis02);
+ newTransformV.rot.col2 = axis01;
+ newTransformV.p = V3NegScaleSub(axis01, ea1, transform0.p);
+
+ }
+ else
+ {
+
+
+ const Vec3V nAxis01 = V3Neg(axis01);
+ mtd = nAxis01;
+ newTransformV.rot.col0 = axis00;
+ newTransformV.rot.col1 = axis02;
+ newTransformV.rot.col2 = nAxis01;
+ newTransformV.p = V3ScaleAdd(axis01, ea1, transform0.p);
+ }
+
+ const Ps::aos::PsMatTransformV transform1ToNew = newTransformV.transformInv(transform1);
+ const Vec3V localNormal =newTransformV.rotateInv(mtd);
+ getIncidentPolygon(pts, incidentFaceNormalInNew, V3Neg(localNormal), transform1ToNew, box1Extent);
+
+ calculateContacts(ea0, ea2, pts, incidentFaceNormalInNew, localNormal, manifoldContacts, numContacts, contactDist);
+
+ break;
+
+ };
+ case 2: //ua2
+ {
+
+ if(FAllGrtrOrEq(zero, sign[2]))
+ {
+ mtd = axis02;
+ newTransformV.rot.col0 = axis00;
+ newTransformV.rot.col1 = axis01;
+ newTransformV.rot.col2 = axis02;
+
+ newTransformV.p = V3NegScaleSub(axis02, ea2, transform0.p);
+ }
+ else
+ {
+ const Vec3V nAxis02 = V3Neg(axis02);
+ mtd = nAxis02;
+ newTransformV.rot.col0 = axis00;
+ newTransformV.rot.col1 = V3Neg(axis01);
+ newTransformV.rot.col2 = nAxis02;
+ newTransformV.p = V3ScaleAdd(axis02, ea2, transform0.p);
+
+ }
+
+ const Ps::aos::PsMatTransformV transform1ToNew = newTransformV.transformInv(transform1);
+ const Vec3V localNormal =newTransformV.rotateInv(mtd);
+ getIncidentPolygon(pts, incidentFaceNormalInNew, V3Neg(localNormal), transform1ToNew, box1Extent);
+
+ calculateContacts(ea0, ea1, pts, incidentFaceNormalInNew, localNormal, manifoldContacts, numContacts, contactDist);
+
+
+ break;
+ };
+ case 3: //ub0
+ {
+
+ flip = true;
+ if(FAllGrtrOrEq(zero, sign[3]))
+ {
+ mtd = axis10;
+ newTransformV.rot.col0 = axis12;
+ newTransformV.rot.col1 = axis11;
+ newTransformV.rot.col2 = V3Neg(axis10);
+ newTransformV.p = V3ScaleAdd(axis10, eb0, transform1.p); //transform0.p - extents0.x*axis00;
+ }
+ else
+ {
+ mtd = V3Neg(axis10);
+ newTransformV.rot.col0 = V3Neg(axis12);
+ newTransformV.rot.col1 = axis11;
+ newTransformV.rot.col2 = axis10;
+ newTransformV.p =V3NegScaleSub(axis10, eb0, transform1.p);//transform0.p + extents0.x*axis00;
+ }
+
+ const Ps::aos::PsMatTransformV transform1ToNew = newTransformV.transformInv(transform0);
+ const Vec3V localNormal =newTransformV.rotateInv(mtd);
+ getIncidentPolygon(pts, incidentFaceNormalInNew, localNormal, transform1ToNew, box0Extent);
+
+ calculateContacts(eb2, eb1, pts, incidentFaceNormalInNew, localNormal, manifoldContacts, numContacts, contactDist);
+
+ break;
+ };
+ case 4: //ub1;
+ {
+ flip = true;
+ if(FAllGrtrOrEq(zero, sign[4]))
+ {
+ mtd = axis11;
+ newTransformV.rot.col0 = axis10;
+ newTransformV.rot.col1 = axis12;
+ newTransformV.rot.col2 = V3Neg(axis11);
+
+ newTransformV.p = V3ScaleAdd(axis11, eb1, transform1.p);
+
+ }
+ else
+ {
+ mtd = V3Neg(axis11);
+
+ newTransformV.rot.col0 = axis10;
+ newTransformV.rot.col1 = V3Neg(axis12);
+ newTransformV.rot.col2 = axis11;
+ newTransformV.p = V3NegScaleSub(axis11, eb1, transform1.p); //transform0.p + extents0.x*axis00;
+
+ }
+
+ const Ps::aos::PsMatTransformV transform1ToNew = newTransformV.transformInv(transform0);
+ const Vec3V localNormal =newTransformV.rotateInv(mtd);
+ getIncidentPolygon(pts, incidentFaceNormalInNew, localNormal, transform1ToNew, box0Extent);
+ calculateContacts(eb0, eb2, pts, incidentFaceNormalInNew, localNormal, manifoldContacts, numContacts, contactDist);
+ break;
+ }
+ case 5: //ub2;
+ {
+
+ flip = true;
+ if(FAllGrtrOrEq(zero, sign[5]))
+ {
+ mtd = axis12;
+ newTransformV.rot.col0 = axis10;
+ newTransformV.rot.col1 = V3Neg(axis11);
+ newTransformV.rot.col2 = V3Neg(axis12);
+ newTransformV.p = V3ScaleAdd(axis12, eb2, transform1.p);
+ }
+ else
+ {
+ mtd = V3Neg(axis12);
+
+ newTransformV.rot.col0 = axis10;
+ newTransformV.rot.col1 = axis11;
+ newTransformV.rot.col2 = axis12;
+ newTransformV.p = V3NegScaleSub(axis12, eb2, transform1.p);
+ }
+
+ const Ps::aos::PsMatTransformV transform1ToNew = newTransformV.transformInv(transform0);
+ const Vec3V localNormal =newTransformV.rotateInv(mtd);
+ getIncidentPolygon(pts, incidentFaceNormalInNew, localNormal, transform1ToNew, box0Extent);
+
+ calculateContacts(eb0, eb1, pts, incidentFaceNormalInNew, localNormal, manifoldContacts, numContacts, contactDist);
+ break;
+ };
+ default:
+ return false;
+ }
+
+ if(flip)
+ {
+ for(PxU32 i=0; i<numContacts; ++i)
+ {
+ const Vec3V localB = manifoldContacts[i].mLocalPointB;
+ manifoldContacts[i].mLocalPointB = manifoldContacts[i].mLocalPointA;
+ manifoldContacts[i].mLocalPointA = localB;
+ }
+ }
+ const Ps::aos::PsMatTransformV transformNewTo1 = transform1.transformInv(newTransformV);
+ const Ps::aos::PsMatTransformV transformNewTo0 = transform0.transformInv(newTransformV);
+ //transform points to the local space of transform0 and transform1
+ const Ps::aos::Vec3V localNormalInB = transformNewTo1.rotate(Vec3V_From_Vec4V(manifoldContacts[0].mLocalNormalPen));
+
+ for(PxU32 i=0; i<numContacts; ++i)
+ {
+ manifoldContacts[i].mLocalPointA = transformNewTo0.transform(manifoldContacts[i].mLocalPointA);
+ manifoldContacts[i].mLocalPointB = transformNewTo1.transform(manifoldContacts[i].mLocalPointB);
+ manifoldContacts[i].mLocalNormalPen = V4SetW(localNormalInB, V4GetW(manifoldContacts[i].mLocalNormalPen));
+ }
+
+ return true;
+}
+
+
+
+bool pcmContactBoxBox(GU_CONTACT_METHOD_ARGS)
+{
+ PX_UNUSED(renderOutput);
+
+ using namespace Ps::aos;
+ // Get actual shape data
+ Gu::PersistentContactManifold& manifold = cache.getManifold();
+ Ps::prefetchLine(&manifold, 256);
+ const PxBoxGeometry& shapeBox0 = shape0.get<const PxBoxGeometry>();
+ const PxBoxGeometry& shapeBox1 = shape1.get<const PxBoxGeometry>();
+
+ PX_ASSERT(transform1.q.isSane());
+ PX_ASSERT(transform0.q.isSane());
+
+
+ const FloatV contactDist = FLoad(params.mContactDistance);
+ const Vec3V boxExtents0 = V3LoadU(shapeBox0.halfExtents);
+ const Vec3V boxExtents1 = V3LoadU(shapeBox1.halfExtents);
+
+ //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 FloatV boxMargin0 = Gu::CalculatePCMBoxMargin(boxExtents0);
+ const FloatV boxMargin1 = Gu::CalculatePCMBoxMargin(boxExtents1);
+ const FloatV minMargin = FMin(boxMargin0, boxMargin1);
+
+ const PxU32 initialContacts = manifold.mNumContacts;
+ const FloatV projectBreakingThreshold = FMul(minMargin, FLoad(0.8f));
+
+ manifold.refreshContactPoints(aToB, projectBreakingThreshold, contactDist);
+
+ const PxU32 newContacts = manifold.mNumContacts;
+
+ const bool bLostContacts = (newContacts != initialContacts);
+
+ PX_UNUSED(bLostContacts);
+
+ if(bLostContacts || manifold.invalidate_BoxConvex(curRTrans, minMargin))
+ {
+
+ manifold.setRelativeTransform(curRTrans);
+
+ const PsMatTransformV transfV0(transf0);
+ const PsMatTransformV transfV1(transf1);
+
+ Gu::PersistentContact* manifoldContacts = PX_CP_TO_PCP(contactBuffer.contacts);
+ PxU32 numContacts = 0;
+
+ if(doBoxBoxGenerateContacts(boxExtents0, boxExtents1, transfV0, transfV1, contactDist, manifoldContacts, numContacts))
+ {
+ if(numContacts > 0)
+ {
+
+ manifold.addBatchManifoldContacts(manifoldContacts, numContacts);
+ const Vec3V worldNormal = transfV1.rotate(Vec3V_From_Vec4V(manifold.mContactPoints[0].mLocalNormalPen));
+ manifold.addManifoldContactsToContactBuffer(contactBuffer, worldNormal, transfV1);
+#if PCM_LOW_LEVEL_DEBUG
+ manifold.drawManifold(*renderOutput, transf0, transf1);
+#endif
+ return true;
+ }
+ else
+ {
+ const Vec3V zeroV = V3Zero();
+ ShrunkBoxV box0(zeroV, boxExtents0);
+ ShrunkBoxV box1(zeroV, boxExtents1);
+ Vec3V closestA(zeroV), closestB(zeroV), normal(zeroV); // these will be in the local space of B
+ FloatV penDep = FZero();
+ manifold.mNumWarmStartPoints = 0;
+ RelativeConvex<ShrunkBoxV> convexA(box0, aToB);
+ LocalConvex<ShrunkBoxV> convexB(box1);
+ GjkStatus status = gjkPenetration<RelativeConvex<ShrunkBoxV>, LocalConvex<ShrunkBoxV> >(convexA, convexB, aToB.p, contactDist, closestA, closestB, normal, penDep,
+ manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints, false);
+
+ if(status == EPA_CONTACT)
+ {
+
+ RelativeConvex<BoxV> convexA1(box0, aToB);
+ LocalConvex<BoxV> convexB1(box1);
+
+ status= epaPenetration(convexA1, convexB1, manifold.mAIndice, manifold.mBIndice, manifold.mNumWarmStartPoints,
+ closestA, closestB, normal, penDep);
+ }
+
+ if(status == GJK_CONTACT || status == EPA_CONTACT)
+ {
+ const FloatV replaceBreakingThreshold = FMul(minMargin, FLoad(0.05f));
+ const Vec3V localPointA = aToB.transformInv(closestA);//curRTrans.transformInv(closestA);
+ const Vec3V localPointB = closestB;
+ const Vec4V localNormalPen = V4SetW(Vec4V_From_Vec3V(normal), penDep);
+ numContacts += manifold.addManifoldPoint(localPointA, localPointB, localNormalPen, replaceBreakingThreshold);
+
+ //transform the normal back to world space
+ normal = transf1.rotate(normal);
+
+ manifold.addManifoldContactsToContactBuffer(contactBuffer, normal, transf1, contactDist);
+
+#if PCM_LOW_LEVEL_DEBUG
+ manifold.drawManifold(*renderOutput, transf0, transf1);
+#endif
+
+ 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;
+}
+
+}
+}