21 #include <BulletCollision/CollisionShapes/btConvexShape.h>
22 #include <BulletCollision/NarrowPhaseCollision/btSimplexSolverInterface.h>
23 #include <BulletCollision/NarrowPhaseCollision/btConvexPenetrationDepthSolver.h>
26 #if defined(DEBUG) || defined(_DEBUG)
30 #include <spu_printf.h>
31 #define printf spu_printf
36 #ifdef BT_USE_DOUBLE_PRECISION
37 #define REL_ERROR2 btScalar(1.0e-12)
40 #define REL_ERROR2 btScalar(1.0e-6)
47 const btConvexShape* objectB,
48 btSimplexSolverInterface* simplexSolver,
49 btConvexPenetrationDepthSolver* penetrationDepthSolver,
51 : m_cachedSeparatingAxis(btScalar(0.), btScalar(1.), btScalar(0.))
52 , m_penetrationDepthSolver(penetrationDepthSolver)
53 , m_simplexSolver(simplexSolver)
54 , m_minkowskiA(objectA)
55 , m_minkowskiB(objectB)
56 , m_shapeTypeA(objectA->getShapeType())
57 , m_shapeTypeB(objectB->getShapeType())
58 , m_marginA(objectA->getMargin())
59 , m_marginB(objectB->getMargin())
60 , m_ignoreMargin(false)
62 , m_lastUsedMethod(-1)
63 , m_catchDegeneracies(1)
64 , m_fixContactNormalDirection(1)
68 const btConvexShape* objectB,
73 btSimplexSolverInterface* simplexSolver,
74 btConvexPenetrationDepthSolver* penetrationDepthSolver,
76 : m_cachedSeparatingAxis(btScalar(0.), btScalar(1.), btScalar(0.))
77 , m_penetrationDepthSolver(penetrationDepthSolver)
78 , m_simplexSolver(simplexSolver)
79 , m_minkowskiA(objectA)
80 , m_minkowskiB(objectB)
81 , m_shapeTypeA(shapeTypeA)
82 , m_shapeTypeB(shapeTypeB)
85 , m_ignoreMargin(false)
87 , m_lastUsedMethod(-1)
88 , m_catchDegeneracies(1)
89 , m_fixContactNormalDirection(1)
95 class btIDebugDraw* debugDraw,
104 const btTransform& localTransA,
105 const btConvexShape* convexB,
106 const btTransform& localTransB,
107 const btVector3& dir,
109 btVector3& supAworld,
110 btVector3& supBworld,
113 btVector3 separatingAxisInA = (dir)*localTransA.getBasis();
114 btVector3 separatingAxisInB = (-dir) * localTransB.getBasis();
116 btVector3 pInANoMargin = convexA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
117 btVector3 qInBNoMargin = convexB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
119 btVector3 pInA = pInANoMargin;
120 btVector3 qInB = qInBNoMargin;
122 supAworld = localTransA(pInA);
123 supBworld = localTransB(qInB);
127 supAworld[2] = btScalar(0.);
128 supBworld[2] = btScalar(0.);
131 aMinb = supAworld - supBworld;
160 inline void btVec3Copy(btVector3* v,
const btVector3* w) { *v = *w; }
164 v->m_floats[0] += w->m_floats[0];
165 v->m_floats[1] += w->m_floats[1];
166 v->m_floats[2] += w->m_floats[2];
169 inline void ccdVec3Sub(btVector3* v,
const btVector3* w) { *v -= *w; }
170 inline void btVec3Sub2(btVector3* d,
const btVector3* v,
const btVector3* w) { *d = (*v) - (*w); }
171 inline btScalar
btVec3Dot(
const btVector3* a,
const btVector3* b)
173 btScalar dot = a->dot(*b);
192 inline void btVec3Cross(btVector3* d,
const btVector3* a,
const btVector3* b)
194 d->m_floats[0] = (a->m_floats[1] * b->m_floats[2]) - (a->m_floats[2] * b->m_floats[1]);
195 d->m_floats[1] = (a->m_floats[2] * b->m_floats[0]) - (a->m_floats[0] * b->m_floats[2]);
196 d->m_floats[2] = (a->m_floats[0] * b->m_floats[1]) - (a->m_floats[1] * b->m_floats[0]);
199 inline void btTripleCross(
const btVector3* a,
const btVector3* b,
const btVector3* c, btVector3* d)
206 inline int ccdEq(btScalar _a, btScalar _b)
208 btScalar ab = btFabs(_a - _b);
209 if (btFabs(ab) < SIMD_EPSILON)
212 btScalar a = btFabs(_a);
213 btScalar b = btFabs(_b);
216 return ab < SIMD_EPSILON * b;
220 return ab < SIMD_EPSILON * a;
224 btScalar
ccdVec3X(
const btVector3* v) {
return v->x(); }
226 btScalar
ccdVec3Y(
const btVector3* v) {
return v->y(); }
228 btScalar
ccdVec3Z(
const btVector3* v) {
return v->z(); }
229 inline int btVec3Eq(
const btVector3* a,
const btVector3* b)
250 if (btFuzzyZero(val))
254 else if (val < btScalar(0))
278 btScalar dist{ std::numeric_limits<btScalar>::max() }, t{ std::numeric_limits<btScalar>::max() };
290 if (t < btScalar(0) || btFuzzyZero(t))
293 if (witness !=
nullptr)
296 else if (t > btScalar(1) ||
ccdEq(t, btScalar(1)))
299 if (witness !=
nullptr)
304 if (witness !=
nullptr)
324 btVec3PointTriDist2(
const btVector3* P,
const btVector3* x0,
const btVector3* B,
const btVector3* C, btVector3* witness)
336 double dist{ std::numeric_limits<double>::max() }, dist2{ std::numeric_limits<double>::max() };
350 double s = (q *
r - w * p) / (w * v -
r *
r);
351 double t = (-s *
r - q) / w;
353 if ((btFuzzyZero(
static_cast<btScalar
>(s)) || s > 0) && (
ccdEq(
static_cast<btScalar
>(s), 1) || s < 1) &&
354 (btFuzzyZero(
static_cast<btScalar
>(t)) || t > 0) && (
ccdEq(
static_cast<btScalar
>(t), 1) || t < 1) &&
355 (
ccdEq(
static_cast<btScalar
>(t + s), 1) ||
static_cast<btScalar
>(t + s) < 1))
357 if (witness !=
nullptr)
371 dist += btScalar(2.) * s * t *
r;
372 dist += btScalar(2.) * s * p;
373 dist += btScalar(2.) * t * q;
385 if (witness !=
nullptr)
393 if (witness !=
nullptr)
398 return static_cast<btScalar
>(dist);
403 btVector3 AB, AO, tmp;
420 if (btFuzzyZero(
btVec3Dot(&tmp, &tmp)) && dot > btScalar(0))
426 if (btFuzzyZero(dot) || dot < btScalar(0))
447 btVector3 AO, AB, AC, ABC, tmp;
457 if (btFuzzyZero(dist))
480 if (btFuzzyZero(dot) || dot > btScalar(0))
483 if (btFuzzyZero(dot) || dot > btScalar(0))
493 if (btFuzzyZero(dot) || dot > btScalar(0))
512 if (btFuzzyZero(dot) || dot > btScalar(0))
515 if (btFuzzyZero(dot) || dot > btScalar(0))
532 if (btFuzzyZero(dot) || dot > btScalar(0))
554 btVector3 AO, AB, AC, AD, ABC, ACD, ADB;
567 if (btFuzzyZero(dist))
575 if (btFuzzyZero(dist))
578 if (btFuzzyZero(dist))
581 if (btFuzzyZero(dist))
584 if (btFuzzyZero(dist))
609 if (AB_O && AC_O && AD_O)
667 class btIDebugDraw* debugDraw)
671 class btIDebugDraw* debugDraw)
674 m_cachedSeparatingDistance = btScalar(0.);
677 btVector3 normalInB(btScalar(0.), btScalar(0.), btScalar(0.));
679 btVector3 pointOnA, pointOnB;
680 btTransform localTransA = input.m_transformA;
681 btTransform localTransB = input.m_transformB;
682 btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
683 localTransA.getOrigin() -= positionOffset;
684 localTransB.getOrigin() -= positionOffset;
686 bool check2d = m_minkowskiA->isConvex2d() && m_minkowskiB->isConvex2d();
688 btScalar marginA = m_marginA;
689 btScalar marginB = m_marginB;
694 marginA = btScalar(0.);
695 marginB = btScalar(0.);
699 int gGjkMaxIter = 1000;
700 m_cachedSeparatingAxis.setValue(0, 1, 0);
702 bool isValid =
false;
703 bool checkSimplex =
false;
704 bool checkPenetration =
true;
705 m_degenerateSimplex = 0;
707 m_lastUsedMethod = -1;
709 btVector3 orgNormalInB(0, 0, 0);
710 btScalar margin = marginA + marginB;
719 btScalar squaredDistance = BT_LARGE_FLOAT;
720 auto delta = btScalar(0.);
726 btVector3 dir(1, 0, 0);
733 m_minkowskiA, localTransA, m_minkowskiB, localTransB, dir, check2d, supAworld, supBworld, lastSupV);
745 for (
int iterations = 0; iterations < gGjkMaxIter; iterations++)
749 m_minkowskiA, localTransA, m_minkowskiB, localTransB, dir, check2d, supAworld, supBworld, lastSupV);
754 btScalar delta = lastSupV.dot(dir);
775 if (do_simplex_res == 1)
780 else if (do_simplex_res == -1)
793 if (dir.length2() < SIMD_EPSILON)
809 if (status == 0 && !m_cdata->req.calculate_penetration)
812 output.addContactPoint(normalInB, pointOnB + positionOffset, -std::numeric_limits<btScalar>::min());
816 if (status == -1 && !m_cdata->req.calculate_distance)
822 m_simplexSolver->reset();
829 btVector3 separatingAxisInA = (-m_cachedSeparatingAxis) * localTransA.getBasis();
830 btVector3 separatingAxisInB = m_cachedSeparatingAxis * localTransB.getBasis();
832 btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
833 btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
835 btVector3 pWorld = localTransA(pInA);
836 btVector3 qWorld = localTransB(qInB);
840 pWorld[2] = btScalar(0.);
841 qWorld[2] = btScalar(0.);
844 btVector3 w = pWorld - qWorld;
845 delta = m_cachedSeparatingAxis.dot(w);
848 if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared))
850 m_degenerateSimplex = 10;
857 if (m_simplexSolver->inSimplex(w))
859 m_degenerateSimplex = 1;
864 btScalar f0 = squaredDistance - delta;
869 if (f0 <= btScalar(0.))
871 m_degenerateSimplex = 2;
875 m_degenerateSimplex = 11;
882 m_simplexSolver->addVertex(w, pWorld, qWorld);
883 btVector3 newCachedSeparatingAxis;
886 if (!m_simplexSolver->closest(newCachedSeparatingAxis))
888 m_degenerateSimplex = 3;
893 if (newCachedSeparatingAxis.length2() <
REL_ERROR2)
895 m_cachedSeparatingAxis = newCachedSeparatingAxis;
896 m_degenerateSimplex = 6;
901 btScalar previousSquaredDistance = squaredDistance;
902 squaredDistance = newCachedSeparatingAxis.length2();
904 if (squaredDistance > previousSquaredDistance)
907 m_degenerateSimplex = 7;
908 squaredDistance = previousSquaredDistance;
909 checkSimplex =
false;
917 if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
921 m_degenerateSimplex = 12;
926 m_cachedSeparatingAxis = newCachedSeparatingAxis;
929 if (m_curIter++ > gGjkMaxIter)
931 #if defined(DEBUG) || defined(_DEBUG)
933 printf(
"btGjkPairDetector maxIter exceeded:%i\n", m_curIter);
934 printf(
"sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n",
935 m_cachedSeparatingAxis.getX(),
936 m_cachedSeparatingAxis.getY(),
937 m_cachedSeparatingAxis.getZ(),
939 m_minkowskiA->getShapeType(),
940 m_minkowskiB->getShapeType());
946 bool check = (!m_simplexSolver->fullSimplex());
954 m_degenerateSimplex = 13;
961 m_simplexSolver->compute_points(pointOnA, pointOnB);
962 normalInB = m_cachedSeparatingAxis;
964 btScalar lenSqr = m_cachedSeparatingAxis.length2();
969 m_degenerateSimplex = 5;
971 if (lenSqr > SIMD_EPSILON * SIMD_EPSILON)
973 btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
976 btScalar s = btSqrt(squaredDistance);
978 btAssert(s > btScalar(0.0));
979 pointOnA -= m_cachedSeparatingAxis * (marginA / s);
980 pointOnB += m_cachedSeparatingAxis * (marginB / s);
981 distance = ((btScalar(1.) / rlen) - margin);
983 orgNormalInB = normalInB;
985 m_lastUsedMethod = 1;
989 m_lastUsedMethod = 2;
994 bool catchDegeneratePenetrationCase =
995 (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex &&
999 if ((checkPenetration && (!isValid || catchDegeneratePenetrationCase)) || (status == 0))
1004 if (m_penetrationDepthSolver !=
nullptr)
1007 btVector3 tmpPointOnA, tmpPointOnB;
1009 m_cachedSeparatingAxis.setZero();
1011 bool isValid2 = m_penetrationDepthSolver->calcPenDepth(*m_simplexSolver,
1016 m_cachedSeparatingAxis,
1021 if (m_cachedSeparatingAxis.length2() > 0)
1025 btVector3 tmpNormalInB = tmpPointOnB - tmpPointOnA;
1026 btScalar lenSqr = tmpNormalInB.length2();
1027 if (lenSqr <= (SIMD_EPSILON * SIMD_EPSILON))
1029 tmpNormalInB = m_cachedSeparatingAxis;
1030 lenSqr = m_cachedSeparatingAxis.length2();
1033 if (lenSqr > (SIMD_EPSILON * SIMD_EPSILON))
1035 tmpNormalInB /= btSqrt(lenSqr);
1036 btScalar distance2 = -(tmpPointOnA - tmpPointOnB).length();
1037 m_lastUsedMethod = 3;
1039 if (!isValid || (distance2 <
distance))
1042 pointOnA = tmpPointOnA;
1043 pointOnB = tmpPointOnB;
1044 normalInB = tmpNormalInB;
1049 m_lastUsedMethod = 8;
1054 m_lastUsedMethod = 9;
1066 if (m_cachedSeparatingAxis.length2() > btScalar(0.))
1068 btScalar distance2 = (tmpPointOnA - tmpPointOnB).length() - margin;
1070 if (!isValid || (distance2 <
distance))
1073 pointOnA = tmpPointOnA;
1074 pointOnB = tmpPointOnB;
1075 pointOnA -= m_cachedSeparatingAxis * marginA;
1076 pointOnB += m_cachedSeparatingAxis * marginB;
1077 normalInB = m_cachedSeparatingAxis;
1078 normalInB.normalize();
1081 m_lastUsedMethod = 6;
1085 m_lastUsedMethod = 5;
1100 m_cachedSeparatingAxis = normalInB;
1101 m_cachedSeparatingDistance =
distance;
1109 auto d2 = btScalar(0.);
1111 btVector3 separatingAxisInA = (-orgNormalInB) * localTransA.getBasis();
1112 btVector3 separatingAxisInB = orgNormalInB * localTransB.getBasis();
1114 btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
1115 btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
1117 btVector3 pWorld = localTransA(pInA);
1118 btVector3 qWorld = localTransB(qInB);
1119 btVector3 w = pWorld - qWorld;
1120 d2 = orgNormalInB.dot(w) - margin;
1125 btVector3 separatingAxisInA = (normalInB)*localTransA.getBasis();
1126 btVector3 separatingAxisInB = -normalInB * localTransB.getBasis();
1128 btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
1129 btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
1131 btVector3 pWorld = localTransA(pInA);
1132 btVector3 qWorld = localTransB(qInB);
1133 btVector3 w = pWorld - qWorld;
1134 d1 = (-normalInB).dot(w) - margin;
1136 auto d0 = btScalar(0.);
1138 btVector3 separatingAxisInA = (-normalInB) * input.m_transformA.getBasis();
1139 btVector3 separatingAxisInB = normalInB * input.m_transformB.getBasis();
1141 btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInA);
1142 btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(separatingAxisInB);
1144 btVector3 pWorld = localTransA(pInA);
1145 btVector3 qWorld = localTransB(qInB);
1146 btVector3 w = pWorld - qWorld;
1147 d0 = normalInB.dot(w) - margin;
1152 m_lastUsedMethod = 10;
1156 if (orgNormalInB.length2() > 0)
1158 if (d2 > d0 && d2 > d1 && d2 >
distance)
1160 normalInB = orgNormalInB;
1166 output.addContactPoint(normalInB, pointOnB + positionOffset,
distance);