2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2008 Erwin Coumans https://bulletphysics.org
5 This software is provided 'as-is', without any express or implied warranty.
6 In no event will the authors be held liable for any damages arising from the
8 Permission is granted to anyone to use this software for any purpose,
9 including commercial applications, and to alter it and redistribute it
11 subject to the following restrictions:
13 1. The origin of this software must not be misrepresented; you must not
14 claim that you wrote the original software. If you use this software in a
15 product, an acknowledgment in the product documentation would be appreciated
17 2. Altered source versions must be plainly marked as such, and must not be
18 misrepresented as being the original software.
19 3. This notice may not be removed or altered from any source distribution.
23 GJK-EPA collision solver by Nathanael Presson, 2008
25 #include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
26 #include "BulletCollision/CollisionShapes/btSphereShape.h"
27 #include "btGjkEpa2.h"
29 #if defined(DEBUG) || defined(_DEBUG)
30 #include <stdio.h> //for debug printf
32 #include <spu_printf.h>
33 #define printf spu_printf
37 namespace gjkepa2_impl
42 #define GJK_MAX_ITERATIONS 128
44 #ifdef BT_USE_DOUBLE_PRECISION
45 #define GJK_ACCURACY ((btScalar)1e-12)
46 #define GJK_MIN_DISTANCE ((btScalar)1e-12)
47 #define GJK_DUPLICATED_EPS ((btScalar)1e-12)
49 #define GJK_ACCURACY ((btScalar)0.0001)
50 #define GJK_MIN_DISTANCE ((btScalar)0.0001)
51 #define GJK_DUPLICATED_EPS ((btScalar)0.0001)
52 #endif //BT_USE_DOUBLE_PRECISION
54 #define GJK_SIMPLEX2_EPS ((btScalar)0.0)
55 #define GJK_SIMPLEX3_EPS ((btScalar)0.0)
56 #define GJK_SIMPLEX4_EPS ((btScalar)0.0)
59 #define EPA_MAX_VERTICES 128
60 #define EPA_MAX_ITERATIONS 255
62 #ifdef BT_USE_DOUBLE_PRECISION
63 #define EPA_ACCURACY ((btScalar)1e-12)
64 #define EPA_PLANE_EPS ((btScalar)1e-14)
65 #define EPA_INSIDE_EPS ((btScalar)1e-9)
67 #define EPA_ACCURACY ((btScalar)0.0001)
68 #define EPA_PLANE_EPS ((btScalar)0.00001)
69 #define EPA_INSIDE_EPS ((btScalar)0.01)
72 #define EPA_FALLBACK (10 * EPA_ACCURACY)
73 #define EPA_MAX_FACES (EPA_MAX_VERTICES * 2)
76 typedef unsigned int U;
77 typedef unsigned char U1;
82 const btConvexShape* m_shapes[2];
83 btMatrix3x3 m_toshape1;
84 btTransform m_toshape0;
88 btVector3 (btConvexShape::*Ls)(const btVector3&) const;
95 void EnableMargin(bool enable)
97 m_enableMargin = enable;
99 inline btVector3 Support0(const btVector3& d) const
103 return m_shapes[0]->localGetSupportVertexNonVirtual(d);
107 return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d);
110 inline btVector3 Support1(const btVector3& d) const
114 return m_toshape0 * (m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1 * d));
118 return m_toshape0 * (m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1 * d));
122 void EnableMargin(bool enable)
125 Ls = &btConvexShape::localGetSupportVertexNonVirtual;
127 Ls = &btConvexShape::localGetSupportVertexWithoutMarginNonVirtual;
129 inline btVector3 Support0(const btVector3& d) const
131 return (((m_shapes[0])->*(Ls))(d));
133 inline btVector3 Support1(const btVector3& d) const
135 return (m_toshape0 * ((m_shapes[1])->*(Ls))(m_toshape1 * d));
139 inline btVector3 Support(const btVector3& d) const
141 return (Support0(d) - Support1(-d));
143 btVector3 Support(const btVector3& d, U index) const
146 return (Support1(d));
148 return (Support0(d));
152 typedef MinkowskiDiff tShape;
181 sSimplex m_simplices[2];
195 m_ray = btVector3(0, 0, 0);
197 m_status = eStatus::Failed;
201 eStatus::_ Evaluate(const tShape& shapearg, const btVector3& guess)
208 /* Initialize solver */
209 m_free[0] = &m_store[0];
210 m_free[1] = &m_store[1];
211 m_free[2] = &m_store[2];
212 m_free[3] = &m_store[3];
215 m_status = eStatus::Valid;
218 /* Initialize simplex */
219 m_simplices[0].rank = 0;
221 const btScalar sqrl = m_ray.length2();
222 appendvertice(m_simplices[0], sqrl > 0 ? -m_ray : btVector3(1, 0, 0));
223 m_simplices[0].p[0] = 1;
224 m_ray = m_simplices[0].c[0]->w;
233 const U next = 1 - m_current;
234 sSimplex& cs = m_simplices[m_current];
235 sSimplex& ns = m_simplices[next];
237 const btScalar rl = m_ray.length();
238 if (rl < GJK_MIN_DISTANCE)
239 { /* Touching or inside */
240 m_status = eStatus::Inside;
243 /* Append new vertice in -'v' direction */
244 appendvertice(cs, -m_ray);
245 const btVector3& w = cs.c[cs.rank - 1]->w;
247 for (U i = 0; i < 4; ++i)
249 if ((w - lastw[i]).length2() < GJK_DUPLICATED_EPS)
256 { /* Return old simplex */
257 removevertice(m_simplices[m_current]);
262 lastw[clastw = (clastw + 1) & 3] = w;
264 /* Check for termination */
265 const btScalar omega = btDot(m_ray, w) / rl;
266 alpha = btMax(omega, alpha);
267 if (((rl - alpha) - (GJK_ACCURACY * rl)) <= 0)
268 { /* Return old simplex */
269 removevertice(m_simplices[m_current]);
278 sqdist = projectorigin(cs.c[0]->w,
283 sqdist = projectorigin(cs.c[0]->w,
289 sqdist = projectorigin(cs.c[0]->w,
299 m_ray = btVector3(0, 0, 0);
301 for (U i = 0, ni = cs.rank; i < ni; ++i)
305 ns.c[ns.rank] = cs.c[i];
306 ns.p[ns.rank++] = weights[i];
307 m_ray += cs.c[i]->w * weights[i];
311 m_free[m_nfree++] = cs.c[i];
314 if (mask == 15) m_status = eStatus::Inside;
317 { /* Return old simplex */
318 removevertice(m_simplices[m_current]);
321 m_status = ((++iterations) < GJK_MAX_ITERATIONS) ? m_status : eStatus::Failed;
322 } while (m_status == eStatus::Valid);
323 m_simplex = &m_simplices[m_current];
327 m_distance = m_ray.length();
329 case eStatus::Inside:
340 switch (m_simplex->rank)
344 for (U i = 0; i < 3; ++i)
346 btVector3 axis = btVector3(0, 0, 0);
348 appendvertice(*m_simplex, axis);
349 if (EncloseOrigin()) return (true);
350 removevertice(*m_simplex);
351 appendvertice(*m_simplex, -axis);
352 if (EncloseOrigin()) return (true);
353 removevertice(*m_simplex);
359 const btVector3 d = m_simplex->c[1]->w - m_simplex->c[0]->w;
360 for (U i = 0; i < 3; ++i)
362 btVector3 axis = btVector3(0, 0, 0);
364 const btVector3 p = btCross(d, axis);
367 appendvertice(*m_simplex, p);
368 if (EncloseOrigin()) return (true);
369 removevertice(*m_simplex);
370 appendvertice(*m_simplex, -p);
371 if (EncloseOrigin()) return (true);
372 removevertice(*m_simplex);
379 const btVector3 n = btCross(m_simplex->c[1]->w - m_simplex->c[0]->w,
380 m_simplex->c[2]->w - m_simplex->c[0]->w);
383 appendvertice(*m_simplex, n);
384 if (EncloseOrigin()) return (true);
385 removevertice(*m_simplex);
386 appendvertice(*m_simplex, -n);
387 if (EncloseOrigin()) return (true);
388 removevertice(*m_simplex);
394 if (btFabs(det(m_simplex->c[0]->w - m_simplex->c[3]->w,
395 m_simplex->c[1]->w - m_simplex->c[3]->w,
396 m_simplex->c[2]->w - m_simplex->c[3]->w)) > 0)
404 void getsupport(const btVector3& d, sSV& sv) const
406 sv.d = d / d.length();
407 sv.w = m_shape.Support(sv.d);
409 void removevertice(sSimplex& simplex)
411 m_free[m_nfree++] = simplex.c[--simplex.rank];
413 void appendvertice(sSimplex& simplex, const btVector3& v)
415 simplex.p[simplex.rank] = 0;
416 simplex.c[simplex.rank] = m_free[--m_nfree];
417 getsupport(v, *simplex.c[simplex.rank++]);
419 static btScalar det(const btVector3& a, const btVector3& b, const btVector3& c)
421 return (a.y() * b.z() * c.x() + a.z() * b.x() * c.y() -
422 a.x() * b.z() * c.y() - a.y() * b.x() * c.z() +
423 a.x() * b.y() * c.z() - a.z() * b.y() * c.x());
425 static btScalar projectorigin(const btVector3& a,
429 const btVector3 d = b - a;
430 const btScalar l = d.length2();
431 if (l > GJK_SIMPLEX2_EPS)
433 const btScalar t(l > 0 ? -btDot(a, d) / l : 0);
439 return (b.length2());
446 return (a.length2());
450 w[0] = 1 - (w[1] = t);
452 return ((a + d * t).length2());
457 static btScalar projectorigin(const btVector3& a,
462 static const U imd3[] = {1, 2, 0};
463 const btVector3* vt[] = {&a, &b, &c};
464 const btVector3 dl[] = {a - b, b - c, c - a};
465 const btVector3 n = btCross(dl[0], dl[1]);
466 const btScalar l = n.length2();
467 if (l > GJK_SIMPLEX3_EPS)
469 btScalar mindist = -1;
470 btScalar subw[2] = {0.f, 0.f};
472 for (U i = 0; i < 3; ++i)
474 if (btDot(*vt[i], btCross(dl[i], n)) > 0)
477 const btScalar subd(projectorigin(*vt[i], *vt[j], subw, subm));
478 if ((mindist < 0) || (subd < mindist))
481 m = static_cast<U>(((subm & 1) ? 1 << i : 0) + ((subm & 2) ? 1 << j : 0));
490 const btScalar d = btDot(a, n);
491 const btScalar s = btSqrt(l);
492 const btVector3 p = n * (d / l);
493 mindist = p.length2();
495 w[0] = (btCross(dl[1], b - p)).length() / s;
496 w[1] = (btCross(dl[2], c - p)).length() / s;
497 w[2] = 1 - (w[0] + w[1]);
503 static btScalar projectorigin(const btVector3& a,
509 static const U imd3[] = {1, 2, 0};
510 const btVector3* vt[] = {&a, &b, &c, &d};
511 const btVector3 dl[] = {a - d, b - d, c - d};
512 const btScalar vl = det(dl[0], dl[1], dl[2]);
513 const bool ng = (vl * btDot(a, btCross(b - c, a - b))) <= 0;
514 if (ng && (btFabs(vl) > GJK_SIMPLEX4_EPS))
516 btScalar mindist = -1;
517 btScalar subw[3] = {0.f, 0.f, 0.f};
519 for (U i = 0; i < 3; ++i)
522 const btScalar s = vl * btDot(d, btCross(dl[i], dl[j]));
525 const btScalar subd = projectorigin(*vt[i], *vt[j], d, subw, subm);
526 if ((mindist < 0) || (subd < mindist))
529 m = static_cast<U>((subm & 1 ? 1 << i : 0) +
530 (subm & 2 ? 1 << j : 0) +
543 w[0] = det(c, b, d) / vl;
544 w[1] = det(a, c, d) / vl;
545 w[2] = det(b, a, d) / vl;
546 w[3] = 1 - (w[0] + w[1] + w[2]);
558 typedef GJK::sSV sSV;
573 sList() : root(0), count(0) {}
580 sHorizon() : cf(0), ff(0), nf(0) {}
600 GJK::sSimplex m_result;
603 sSV m_sv_store[EPA_MAX_VERTICES];
604 sFace m_fc_store[EPA_MAX_FACES];
614 static inline void bind(sFace* fa, U ea, sFace* fb, U eb)
621 static inline void append(sList& list, sFace* face)
624 face->l[1] = list.root;
625 if (list.root) list.root->l[0] = face;
629 static inline void remove(sList& list, sFace* face)
631 if (face->l[1]) face->l[1]->l[0] = face->l[0];
632 if (face->l[0]) face->l[0]->l[1] = face->l[1];
633 if (face == list.root) list.root = face->l[1];
639 m_status = eStatus::Failed;
640 m_normal = btVector3(0, 0, 0);
643 for (U i = 0; i < EPA_MAX_FACES; ++i)
645 append(m_stock, &m_fc_store[EPA_MAX_FACES - i - 1]);
648 eStatus::_ Evaluate(GJK& gjk, const btVector3& guess)
650 GJK::sSimplex& simplex = *gjk.m_simplex;
651 if ((simplex.rank > 1) && gjk.EncloseOrigin())
656 sFace* f = m_hull.root;
660 m_status = eStatus::Valid;
663 if (gjk.det(simplex.c[0]->w - simplex.c[3]->w,
664 simplex.c[1]->w - simplex.c[3]->w,
665 simplex.c[2]->w - simplex.c[3]->w) < 0)
667 btSwap(simplex.c[0], simplex.c[1]);
668 btSwap(simplex.p[0], simplex.p[1]);
670 /* Build initial hull */
671 sFace* tetra[] = {newface(simplex.c[0], simplex.c[1], simplex.c[2], true),
672 newface(simplex.c[1], simplex.c[0], simplex.c[3], true),
673 newface(simplex.c[2], simplex.c[1], simplex.c[3], true),
674 newface(simplex.c[0], simplex.c[2], simplex.c[3], true)};
675 if (m_hull.count == 4)
677 sFace* best = findbest();
681 bind(tetra[0], 0, tetra[1], 0);
682 bind(tetra[0], 1, tetra[2], 0);
683 bind(tetra[0], 2, tetra[3], 0);
684 bind(tetra[1], 1, tetra[3], 2);
685 bind(tetra[1], 2, tetra[2], 1);
686 bind(tetra[2], 2, tetra[3], 1);
687 m_status = eStatus::Valid;
688 for (; iterations < EPA_MAX_ITERATIONS; ++iterations)
690 if (m_nextsv < EPA_MAX_VERTICES)
693 sSV* w = &m_sv_store[m_nextsv++];
695 best->pass = (U1)(++pass);
696 gjk.getsupport(best->n, *w);
697 const btScalar wdist = btDot(best->n, w->w) - best->d;
698 if (wdist > EPA_ACCURACY)
700 for (U j = 0; (j < 3) && valid; ++j)
702 valid &= expand(pass, w,
703 best->f[j], best->e[j],
706 if (valid && (horizon.nf >= 3))
708 bind(horizon.cf, 1, horizon.ff, 2);
709 remove(m_hull, best);
710 append(m_stock, best);
716 m_status = eStatus::InvalidHull;
722 m_status = eStatus::AccuraryReached;
728 m_status = eStatus::OutOfVertices;
732 const btVector3 projection = outer.n * outer.d;
736 m_result.c[0] = outer.c[0];
737 m_result.c[1] = outer.c[1];
738 m_result.c[2] = outer.c[2];
739 m_result.p[0] = btCross(outer.c[1]->w - projection,
740 outer.c[2]->w - projection)
742 m_result.p[1] = btCross(outer.c[2]->w - projection,
743 outer.c[0]->w - projection)
745 m_result.p[2] = btCross(outer.c[0]->w - projection,
746 outer.c[1]->w - projection)
748 const btScalar sum = m_result.p[0] + m_result.p[1] + m_result.p[2];
749 m_result.p[0] /= sum;
750 m_result.p[1] /= sum;
751 m_result.p[2] /= sum;
756 m_status = eStatus::FallBack;
758 const btScalar nl = m_normal.length();
760 m_normal = m_normal / nl;
762 m_normal = btVector3(1, 0, 0);
765 m_result.c[0] = simplex.c[0];
769 bool getedgedist(sFace* face, sSV* a, sSV* b, btScalar& dist)
771 const btVector3 ba = b->w - a->w;
772 const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane
773 const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
777 // Outside of edge a->b
779 const btScalar ba_l2 = ba.length2();
780 const btScalar a_dot_ba = btDot(a->w, ba);
781 const btScalar b_dot_ba = btDot(b->w, ba);
785 // Pick distance vertex a
786 dist = a->w.length();
788 else if (b_dot_ba < 0)
790 // Pick distance vertex b
791 dist = b->w.length();
795 // Pick distance to edge a->b
796 const btScalar a_dot_b = btDot(a->w, b->w);
797 dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
805 sFace* newface(sSV* a, sSV* b, sSV* c, bool forced)
809 sFace* face = m_stock.root;
810 remove(m_stock, face);
811 append(m_hull, face);
816 face->n = btCross(b->w - a->w, c->w - a->w);
817 const btScalar l = face->n.length();
818 const bool v = l > EPA_ACCURACY;
822 if (!(getedgedist(face, a, b, face->d) ||
823 getedgedist(face, b, c, face->d) ||
824 getedgedist(face, c, a, face->d)))
826 // Origin projects to the interior of the triangle
827 // Use distance to triangle plane
828 face->d = btDot(a->w, face->n) / l;
832 if (forced || (face->d >= -EPA_PLANE_EPS))
837 m_status = eStatus::NonConvex;
840 m_status = eStatus::Degenerated;
842 remove(m_hull, face);
843 append(m_stock, face);
846 m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces;
851 sFace* minf = m_hull.root;
852 btScalar mind = minf->d * minf->d;
853 for (sFace* f = minf->l[1]; f; f = f->l[1])
855 const btScalar sqd = f->d * f->d;
864 bool expand(U pass, sSV* w, sFace* f, U e, sHorizon& horizon)
866 static const U i1m3[] = {1, 2, 0};
867 static const U i2m3[] = {2, 0, 1};
870 const U e1 = i1m3[e];
871 if ((btDot(f->n, w->w) - f->d) < -EPA_PLANE_EPS)
873 sFace* nf = newface(f->c[e1], f->c[e], w, false);
878 bind(horizon.cf, 1, nf, 2);
888 const U e2 = i2m3[e];
890 if (expand(pass, w, f->f[e1], f->e[e1], horizon) &&
891 expand(pass, w, f->f[e2], f->e[e2], horizon))
904 static void Initialize(const btConvexShape* shape0, const btTransform& wtrs0,
905 const btConvexShape* shape1, const btTransform& wtrs1,
906 btGjkEpaSolver2::sResults& results,
911 results.witnesses[0] =
912 results.witnesses[1] = btVector3(0, 0, 0);
913 results.status = btGjkEpaSolver2::sResults::Separated;
915 shape.m_shapes[0] = shape0;
916 shape.m_shapes[1] = shape1;
917 shape.m_toshape1 = wtrs1.getBasis().transposeTimes(wtrs0.getBasis());
918 shape.m_toshape0 = wtrs0.inverseTimes(wtrs1);
919 shape.EnableMargin(withmargins);
922 } // namespace gjkepa2_impl
928 using namespace gjkepa2_impl;
931 int btGjkEpaSolver2::StackSizeRequirement()
933 return (sizeof(GJK) + sizeof(EPA));
937 bool btGjkEpaSolver2::Distance(const btConvexShape* shape0,
938 const btTransform& wtrs0,
939 const btConvexShape* shape1,
940 const btTransform& wtrs1,
941 const btVector3& guess,
945 Initialize(shape0, wtrs0, shape1, wtrs1, results, shape, false);
947 GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
948 if (gjk_status == GJK::eStatus::Valid)
950 btVector3 w0 = btVector3(0, 0, 0);
951 btVector3 w1 = btVector3(0, 0, 0);
952 for (U i = 0; i < gjk.m_simplex->rank; ++i)
954 const btScalar p = gjk.m_simplex->p[i];
955 w0 += shape.Support(gjk.m_simplex->c[i]->d, 0) * p;
956 w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1) * p;
958 results.witnesses[0] = wtrs0 * w0;
959 results.witnesses[1] = wtrs0 * w1;
960 results.normal = w0 - w1;
961 results.distance = results.normal.length();
962 results.normal /= results.distance > GJK_MIN_DISTANCE ? results.distance : 1;
967 results.status = gjk_status == GJK::eStatus::Inside ? sResults::Penetrating : sResults::GJK_Failed;
973 bool btGjkEpaSolver2::Penetration(const btConvexShape* shape0,
974 const btTransform& wtrs0,
975 const btConvexShape* shape1,
976 const btTransform& wtrs1,
977 const btVector3& guess,
982 Initialize(shape0, wtrs0, shape1, wtrs1, results, shape, usemargins);
984 GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, -guess);
987 case GJK::eStatus::Inside:
990 EPA::eStatus::_ epa_status = epa.Evaluate(gjk, -guess);
991 if (epa_status != EPA::eStatus::Failed)
993 btVector3 w0 = btVector3(0, 0, 0);
994 for (U i = 0; i < epa.m_result.rank; ++i)
996 w0 += shape.Support(epa.m_result.c[i]->d, 0) * epa.m_result.p[i];
998 results.status = sResults::Penetrating;
999 results.witnesses[0] = wtrs0 * w0;
1000 results.witnesses[1] = wtrs0 * (w0 - epa.m_normal * epa.m_depth);
1001 results.normal = -epa.m_normal;
1002 results.distance = -epa.m_depth;
1006 results.status = sResults::EPA_Failed;
1009 case GJK::eStatus::Failed:
1010 results.status = sResults::GJK_Failed;
1021 btScalar btGjkEpaSolver2::SignedDistance(const btVector3& position,
1023 const btConvexShape* shape0,
1024 const btTransform& wtrs0,
1028 btSphereShape shape1(margin);
1029 btTransform wtrs1(btQuaternion(0, 0, 0, 1), position);
1030 Initialize(shape0, wtrs0, &shape1, wtrs1, results, shape, false);
1032 GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, btVector3(1, 1, 1));
1033 if (gjk_status == GJK::eStatus::Valid)
1035 btVector3 w0 = btVector3(0, 0, 0);
1036 btVector3 w1 = btVector3(0, 0, 0);
1037 for (U i = 0; i < gjk.m_simplex->rank; ++i)
1039 const btScalar p = gjk.m_simplex->p[i];
1040 w0 += shape.Support(gjk.m_simplex->c[i]->d, 0) * p;
1041 w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1) * p;
1043 results.witnesses[0] = wtrs0 * w0;
1044 results.witnesses[1] = wtrs0 * w1;
1045 const btVector3 delta = results.witnesses[1] -
1046 results.witnesses[0];
1047 const btScalar margin = shape0->getMarginNonVirtual() +
1048 shape1.getMarginNonVirtual();
1049 const btScalar length = delta.length();
1050 results.normal = delta / length;
1051 results.witnesses[0] += results.normal * margin;
1052 results.distance = length - margin;
1053 return results.distance;
1057 if (gjk_status == GJK::eStatus::Inside)
1059 if (Penetration(shape0, wtrs0, &shape1, wtrs1, gjk.m_ray, results))
1061 const btVector3 delta = results.witnesses[0] -
1062 results.witnesses[1];
1063 const btScalar length = delta.length();
1064 if (length >= SIMD_EPSILON)
1065 results.normal = delta / length;
1070 return (SIMD_INFINITY);
1074 bool btGjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
1075 const btTransform& wtrs0,
1076 const btConvexShape* shape1,
1077 const btTransform& wtrs1,
1078 const btVector3& guess,
1081 if (!Distance(shape0, wtrs0, shape1, wtrs1, guess, results))
1082 return (Penetration(shape0, wtrs0, shape1, wtrs1, guess, results, false));
1088 /* Symbols cleanup */
1090 #undef GJK_MAX_ITERATIONS
1092 #undef GJK_MIN_DISTANCE
1093 #undef GJK_DUPLICATED_EPS
1094 #undef GJK_SIMPLEX2_EPS
1095 #undef GJK_SIMPLEX3_EPS
1096 #undef GJK_SIMPLEX4_EPS
1098 #undef EPA_MAX_VERTICES
1099 #undef EPA_MAX_FACES
1100 #undef EPA_MAX_ITERATIONS
1103 #undef EPA_PLANE_EPS
1104 #undef EPA_INSIDE_EPS