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
28 #include "b3SupportMappings.h"
30 namespace gjkepa2_impl2
35 #define GJK_MAX_ITERATIONS 128
36 #define GJK_ACCURACY ((b3Scalar)0.0001)
37 #define GJK_MIN_DISTANCE ((b3Scalar)0.0001)
38 #define GJK_DUPLICATED_EPS ((b3Scalar)0.0001)
39 #define GJK_SIMPLEX2_EPS ((b3Scalar)0.0)
40 #define GJK_SIMPLEX3_EPS ((b3Scalar)0.0)
41 #define GJK_SIMPLEX4_EPS ((b3Scalar)0.0)
44 #define EPA_MAX_VERTICES 64
45 #define EPA_MAX_FACES (EPA_MAX_VERTICES * 2)
46 #define EPA_MAX_ITERATIONS 255
47 #define EPA_ACCURACY ((b3Scalar)0.0001)
48 #define EPA_FALLBACK (10 * EPA_ACCURACY)
49 #define EPA_PLANE_EPS ((b3Scalar)0.00001)
50 #define EPA_INSIDE_EPS ((b3Scalar)0.01)
55 struct b3MinkowskiDiff
57 const b3ConvexPolyhedronData* m_shapes[2];
59 b3Matrix3x3 m_toshape1;
60 b3Transform m_toshape0;
64 void EnableMargin(bool enable)
66 m_enableMargin = enable;
68 inline b3Vector3 Support0(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA) const
72 return localGetSupportVertexWithMargin(d, m_shapes[0], verticesA, 0.f);
76 return localGetSupportVertexWithoutMargin(d, m_shapes[0], verticesA);
79 inline b3Vector3 Support1(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesB) const
83 return m_toshape0 * (localGetSupportVertexWithMargin(m_toshape1 * d, m_shapes[1], verticesB, 0.f));
87 return m_toshape0 * (localGetSupportVertexWithoutMargin(m_toshape1 * d, m_shapes[1], verticesB));
91 inline b3Vector3 Support(const b3Vector3& d, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
93 return (Support0(d, verticesA) - Support1(-d, verticesB));
95 b3Vector3 Support(const b3Vector3& d, unsigned int index, const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB) const
98 return (Support1(d, verticesA));
100 return (Support0(d, verticesB));
104 typedef b3MinkowskiDiff tShape;
131 const b3AlignedObjectArray<b3Vector3>& m_verticesA;
132 const b3AlignedObjectArray<b3Vector3>& m_verticesB;
135 sSimplex m_simplices[2];
138 unsigned int m_nfree;
139 unsigned int m_current;
143 b3GJK(const b3AlignedObjectArray<b3Vector3>& verticesA, const b3AlignedObjectArray<b3Vector3>& verticesB)
144 : m_verticesA(verticesA), m_verticesB(verticesB)
150 m_ray = b3MakeVector3(0, 0, 0);
152 m_status = eStatus::Failed;
156 eStatus::_ Evaluate(const tShape& shapearg, const b3Vector3& guess)
158 unsigned int iterations = 0;
162 unsigned int clastw = 0;
163 /* Initialize solver */
164 m_free[0] = &m_store[0];
165 m_free[1] = &m_store[1];
166 m_free[2] = &m_store[2];
167 m_free[3] = &m_store[3];
170 m_status = eStatus::Valid;
173 /* Initialize simplex */
174 m_simplices[0].rank = 0;
176 const b3Scalar sqrl = m_ray.length2();
177 appendvertice(m_simplices[0], sqrl > 0 ? -m_ray : b3MakeVector3(1, 0, 0));
178 m_simplices[0].p[0] = 1;
179 m_ray = m_simplices[0].c[0]->w;
188 const unsigned int next = 1 - m_current;
189 sSimplex& cs = m_simplices[m_current];
190 sSimplex& ns = m_simplices[next];
192 const b3Scalar rl = m_ray.length();
193 if (rl < GJK_MIN_DISTANCE)
194 { /* Touching or inside */
195 m_status = eStatus::Inside;
198 /* Append new vertice in -'v' direction */
199 appendvertice(cs, -m_ray);
200 const b3Vector3& w = cs.c[cs.rank - 1]->w;
202 for (unsigned int i = 0; i < 4; ++i)
204 if ((w - lastw[i]).length2() < GJK_DUPLICATED_EPS)
211 { /* Return old simplex */
212 removevertice(m_simplices[m_current]);
217 lastw[clastw = (clastw + 1) & 3] = w;
219 /* Check for termination */
220 const b3Scalar omega = b3Dot(m_ray, w) / rl;
221 alpha = b3Max(omega, alpha);
222 if (((rl - alpha) - (GJK_ACCURACY * rl)) <= 0)
223 { /* Return old simplex */
224 removevertice(m_simplices[m_current]);
229 unsigned int mask = 0;
233 sqdist = projectorigin(cs.c[0]->w,
238 sqdist = projectorigin(cs.c[0]->w,
244 sqdist = projectorigin(cs.c[0]->w,
254 m_ray = b3MakeVector3(0, 0, 0);
256 for (unsigned int i = 0, ni = cs.rank; i < ni; ++i)
260 ns.c[ns.rank] = cs.c[i];
261 ns.p[ns.rank++] = weights[i];
262 m_ray += cs.c[i]->w * weights[i];
266 m_free[m_nfree++] = cs.c[i];
269 if (mask == 15) m_status = eStatus::Inside;
272 { /* Return old simplex */
273 removevertice(m_simplices[m_current]);
276 m_status = ((++iterations) < GJK_MAX_ITERATIONS) ? m_status : eStatus::Failed;
277 } while (m_status == eStatus::Valid);
278 m_simplex = &m_simplices[m_current];
282 m_distance = m_ray.length();
284 case eStatus::Inside:
295 switch (m_simplex->rank)
299 for (unsigned int i = 0; i < 3; ++i)
301 b3Vector3 axis = b3MakeVector3(0, 0, 0);
303 appendvertice(*m_simplex, axis);
304 if (EncloseOrigin()) return (true);
305 removevertice(*m_simplex);
306 appendvertice(*m_simplex, -axis);
307 if (EncloseOrigin()) return (true);
308 removevertice(*m_simplex);
314 const b3Vector3 d = m_simplex->c[1]->w - m_simplex->c[0]->w;
315 for (unsigned int i = 0; i < 3; ++i)
317 b3Vector3 axis = b3MakeVector3(0, 0, 0);
319 const b3Vector3 p = b3Cross(d, axis);
322 appendvertice(*m_simplex, p);
323 if (EncloseOrigin()) return (true);
324 removevertice(*m_simplex);
325 appendvertice(*m_simplex, -p);
326 if (EncloseOrigin()) return (true);
327 removevertice(*m_simplex);
334 const b3Vector3 n = b3Cross(m_simplex->c[1]->w - m_simplex->c[0]->w,
335 m_simplex->c[2]->w - m_simplex->c[0]->w);
338 appendvertice(*m_simplex, n);
339 if (EncloseOrigin()) return (true);
340 removevertice(*m_simplex);
341 appendvertice(*m_simplex, -n);
342 if (EncloseOrigin()) return (true);
343 removevertice(*m_simplex);
349 if (b3Fabs(det(m_simplex->c[0]->w - m_simplex->c[3]->w,
350 m_simplex->c[1]->w - m_simplex->c[3]->w,
351 m_simplex->c[2]->w - m_simplex->c[3]->w)) > 0)
359 void getsupport(const b3Vector3& d, sSV& sv) const
361 sv.d = d / d.length();
362 sv.w = m_shape.Support(sv.d, m_verticesA, m_verticesB);
364 void removevertice(sSimplex& simplex)
366 m_free[m_nfree++] = simplex.c[--simplex.rank];
368 void appendvertice(sSimplex& simplex, const b3Vector3& v)
370 simplex.p[simplex.rank] = 0;
371 simplex.c[simplex.rank] = m_free[--m_nfree];
372 getsupport(v, *simplex.c[simplex.rank++]);
374 static b3Scalar det(const b3Vector3& a, const b3Vector3& b, const b3Vector3& c)
376 return (a.y * b.z * c.x + a.z * b.x * c.y -
377 a.x * b.z * c.y - a.y * b.x * c.z +
378 a.x * b.y * c.z - a.z * b.y * c.x);
380 static b3Scalar projectorigin(const b3Vector3& a,
382 b3Scalar* w, unsigned int& m)
384 const b3Vector3 d = b - a;
385 const b3Scalar l = d.length2();
386 if (l > GJK_SIMPLEX2_EPS)
388 const b3Scalar t(l > 0 ? -b3Dot(a, d) / l : 0);
394 return (b.length2());
401 return (a.length2());
405 w[0] = 1 - (w[1] = t);
407 return ((a + d * t).length2());
412 static b3Scalar projectorigin(const b3Vector3& a,
415 b3Scalar* w, unsigned int& m)
417 static const unsigned int imd3[] = {1, 2, 0};
418 const b3Vector3* vt[] = {&a, &b, &c};
419 const b3Vector3 dl[] = {a - b, b - c, c - a};
420 const b3Vector3 n = b3Cross(dl[0], dl[1]);
421 const b3Scalar l = n.length2();
422 if (l > GJK_SIMPLEX3_EPS)
424 b3Scalar mindist = -1;
425 b3Scalar subw[2] = {0.f, 0.f};
426 unsigned int subm(0);
427 for (unsigned int i = 0; i < 3; ++i)
429 if (b3Dot(*vt[i], b3Cross(dl[i], n)) > 0)
431 const unsigned int j = imd3[i];
432 const b3Scalar subd(projectorigin(*vt[i], *vt[j], subw, subm));
433 if ((mindist < 0) || (subd < mindist))
436 m = static_cast<unsigned int>(((subm & 1) ? 1 << i : 0) + ((subm & 2) ? 1 << j : 0));
445 const b3Scalar d = b3Dot(a, n);
446 const b3Scalar s = b3Sqrt(l);
447 const b3Vector3 p = n * (d / l);
448 mindist = p.length2();
450 w[0] = (b3Cross(dl[1], b - p)).length() / s;
451 w[1] = (b3Cross(dl[2], c - p)).length() / s;
452 w[2] = 1 - (w[0] + w[1]);
458 static b3Scalar projectorigin(const b3Vector3& a,
462 b3Scalar* w, unsigned int& m)
464 static const unsigned int imd3[] = {1, 2, 0};
465 const b3Vector3* vt[] = {&a, &b, &c, &d};
466 const b3Vector3 dl[] = {a - d, b - d, c - d};
467 const b3Scalar vl = det(dl[0], dl[1], dl[2]);
468 const bool ng = (vl * b3Dot(a, b3Cross(b - c, a - b))) <= 0;
469 if (ng && (b3Fabs(vl) > GJK_SIMPLEX4_EPS))
471 b3Scalar mindist = -1;
472 b3Scalar subw[3] = {0.f, 0.f, 0.f};
473 unsigned int subm(0);
474 for (unsigned int i = 0; i < 3; ++i)
476 const unsigned int j = imd3[i];
477 const b3Scalar s = vl * b3Dot(d, b3Cross(dl[i], dl[j]));
480 const b3Scalar subd = projectorigin(*vt[i], *vt[j], d, subw, subm);
481 if ((mindist < 0) || (subd < mindist))
484 m = static_cast<unsigned int>((subm & 1 ? 1 << i : 0) +
485 (subm & 2 ? 1 << j : 0) +
498 w[0] = det(c, b, d) / vl;
499 w[1] = det(a, c, d) / vl;
500 w[2] = det(b, a, d) / vl;
501 w[3] = 1 - (w[0] + w[1] + w[2]);
513 typedef b3GJK::sSV sSV;
528 sList() : root(0), count(0) {}
535 sHorizon() : cf(0), ff(0), nf(0) {}
555 b3GJK::sSimplex m_result;
558 sSV m_sv_store[EPA_MAX_VERTICES];
559 sFace m_fc_store[EPA_MAX_FACES];
560 unsigned int m_nextsv;
569 static inline void bind(sFace* fa, unsigned int ea, sFace* fb, unsigned int eb)
571 fa->e[ea] = (unsigned char)eb;
573 fb->e[eb] = (unsigned char)ea;
576 static inline void append(sList& list, sFace* face)
579 face->l[1] = list.root;
580 if (list.root) list.root->l[0] = face;
584 static inline void remove(sList& list, sFace* face)
586 if (face->l[1]) face->l[1]->l[0] = face->l[0];
587 if (face->l[0]) face->l[0]->l[1] = face->l[1];
588 if (face == list.root) list.root = face->l[1];
594 m_status = eStatus::Failed;
595 m_normal = b3MakeVector3(0, 0, 0);
598 for (unsigned int i = 0; i < EPA_MAX_FACES; ++i)
600 append(m_stock, &m_fc_store[EPA_MAX_FACES - i - 1]);
603 eStatus::_ Evaluate(b3GJK& gjk, const b3Vector3& guess)
605 b3GJK::sSimplex& simplex = *gjk.m_simplex;
606 if ((simplex.rank > 1) && gjk.EncloseOrigin())
611 sFace* f = m_hull.root;
615 m_status = eStatus::Valid;
618 if (gjk.det(simplex.c[0]->w - simplex.c[3]->w,
619 simplex.c[1]->w - simplex.c[3]->w,
620 simplex.c[2]->w - simplex.c[3]->w) < 0)
622 b3Swap(simplex.c[0], simplex.c[1]);
623 b3Swap(simplex.p[0], simplex.p[1]);
625 /* Build initial hull */
626 sFace* tetra[] = {newface(simplex.c[0], simplex.c[1], simplex.c[2], true),
627 newface(simplex.c[1], simplex.c[0], simplex.c[3], true),
628 newface(simplex.c[2], simplex.c[1], simplex.c[3], true),
629 newface(simplex.c[0], simplex.c[2], simplex.c[3], true)};
630 if (m_hull.count == 4)
632 sFace* best = findbest();
634 unsigned int pass = 0;
635 unsigned int iterations = 0;
636 bind(tetra[0], 0, tetra[1], 0);
637 bind(tetra[0], 1, tetra[2], 0);
638 bind(tetra[0], 2, tetra[3], 0);
639 bind(tetra[1], 1, tetra[3], 2);
640 bind(tetra[1], 2, tetra[2], 1);
641 bind(tetra[2], 2, tetra[3], 1);
642 m_status = eStatus::Valid;
643 for (; iterations < EPA_MAX_ITERATIONS; ++iterations)
645 if (m_nextsv < EPA_MAX_VERTICES)
648 sSV* w = &m_sv_store[m_nextsv++];
650 best->pass = (unsigned char)(++pass);
651 gjk.getsupport(best->n, *w);
652 const b3Scalar wdist = b3Dot(best->n, w->w) - best->d;
653 if (wdist > EPA_ACCURACY)
655 for (unsigned int j = 0; (j < 3) && valid; ++j)
657 valid &= expand(pass, w,
658 best->f[j], best->e[j],
661 if (valid && (horizon.nf >= 3))
663 bind(horizon.cf, 1, horizon.ff, 2);
664 remove(m_hull, best);
665 append(m_stock, best);
671 m_status = eStatus::Failed;
672 //m_status=eStatus::InvalidHull;
678 m_status = eStatus::AccuraryReached;
684 m_status = eStatus::OutOfVertices;
688 const b3Vector3 projection = outer.n * outer.d;
692 m_result.c[0] = outer.c[0];
693 m_result.c[1] = outer.c[1];
694 m_result.c[2] = outer.c[2];
695 m_result.p[0] = b3Cross(outer.c[1]->w - projection,
696 outer.c[2]->w - projection)
698 m_result.p[1] = b3Cross(outer.c[2]->w - projection,
699 outer.c[0]->w - projection)
701 m_result.p[2] = b3Cross(outer.c[0]->w - projection,
702 outer.c[1]->w - projection)
704 const b3Scalar sum = m_result.p[0] + m_result.p[1] + m_result.p[2];
705 m_result.p[0] /= sum;
706 m_result.p[1] /= sum;
707 m_result.p[2] /= sum;
712 m_status = eStatus::FallBack;
714 const b3Scalar nl = m_normal.length();
716 m_normal = m_normal / nl;
718 m_normal = b3MakeVector3(1, 0, 0);
721 m_result.c[0] = simplex.c[0];
725 bool getedgedist(sFace* face, sSV* a, sSV* b, b3Scalar& dist)
727 const b3Vector3 ba = b->w - a->w;
728 const b3Vector3 n_ab = b3Cross(ba, face->n); // Outward facing edge normal direction, on triangle plane
729 const b3Scalar a_dot_nab = b3Dot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
733 // Outside of edge a->b
735 const b3Scalar ba_l2 = ba.length2();
736 const b3Scalar a_dot_ba = b3Dot(a->w, ba);
737 const b3Scalar b_dot_ba = b3Dot(b->w, ba);
741 // Pick distance vertex a
742 dist = a->w.length();
744 else if (b_dot_ba < 0)
746 // Pick distance vertex b
747 dist = b->w.length();
751 // Pick distance to edge a->b
752 const b3Scalar a_dot_b = b3Dot(a->w, b->w);
753 dist = b3Sqrt(b3Max((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (b3Scalar)0));
761 sFace* newface(sSV* a, sSV* b, sSV* c, bool forced)
765 sFace* face = m_stock.root;
766 remove(m_stock, face);
767 append(m_hull, face);
772 face->n = b3Cross(b->w - a->w, c->w - a->w);
773 const b3Scalar l = face->n.length();
774 const bool v = l > EPA_ACCURACY;
778 if (!(getedgedist(face, a, b, face->d) ||
779 getedgedist(face, b, c, face->d) ||
780 getedgedist(face, c, a, face->d)))
782 // Origin projects to the interior of the triangle
783 // Use distance to triangle plane
784 face->d = b3Dot(a->w, face->n) / l;
788 if (forced || (face->d >= -EPA_PLANE_EPS))
793 m_status = eStatus::NonConvex;
796 m_status = eStatus::Degenerated;
798 remove(m_hull, face);
799 append(m_stock, face);
802 m_status = m_stock.root ? eStatus::OutOfVertices : eStatus::OutOfFaces;
807 sFace* minf = m_hull.root;
808 b3Scalar mind = minf->d * minf->d;
809 for (sFace* f = minf->l[1]; f; f = f->l[1])
811 const b3Scalar sqd = f->d * f->d;
820 bool expand(unsigned int pass, sSV* w, sFace* f, unsigned int e, sHorizon& horizon)
822 static const unsigned int i1m3[] = {1, 2, 0};
823 static const unsigned int i2m3[] = {2, 0, 1};
826 const unsigned int e1 = i1m3[e];
827 if ((b3Dot(f->n, w->w) - f->d) < -EPA_PLANE_EPS)
829 sFace* nf = newface(f->c[e1], f->c[e], w, false);
834 bind(horizon.cf, 1, nf, 2);
844 const unsigned int e2 = i2m3[e];
845 f->pass = (unsigned char)pass;
846 if (expand(pass, w, f->f[e1], f->e[e1], horizon) &&
847 expand(pass, w, f->f[e2], f->e[e2], horizon))
860 static void Initialize(const b3Transform& transA, const b3Transform& transB,
861 const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
862 const b3AlignedObjectArray<b3Vector3>& verticesA,
863 const b3AlignedObjectArray<b3Vector3>& verticesB,
864 b3GjkEpaSolver2::sResults& results,
869 results.witnesses[0] =
870 results.witnesses[1] = b3MakeVector3(0, 0, 0);
871 results.status = b3GjkEpaSolver2::sResults::Separated;
873 shape.m_shapes[0] = hullA;
874 shape.m_shapes[1] = hullB;
875 shape.m_toshape1 = transB.getBasis().transposeTimes(transA.getBasis());
876 shape.m_toshape0 = transA.inverseTimes(transB);
877 shape.EnableMargin(withmargins);
880 } // namespace gjkepa2_impl2
886 using namespace gjkepa2_impl2;
889 int b3GjkEpaSolver2::StackSizeRequirement()
891 return (sizeof(b3GJK) + sizeof(b3EPA));
895 bool b3GjkEpaSolver2::Distance(const b3Transform& transA, const b3Transform& transB,
896 const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
897 const b3AlignedObjectArray<b3Vector3>& verticesA,
898 const b3AlignedObjectArray<b3Vector3>& verticesB,
899 const b3Vector3& guess,
903 Initialize(transA, transB, hullA, hullB, verticesA, verticesB, results, shape, false);
904 b3GJK gjk(verticesA, verticesB);
905 b3GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
906 if (gjk_status == b3GJK::eStatus::Valid)
908 b3Vector3 w0 = b3MakeVector3(0, 0, 0);
909 b3Vector3 w1 = b3MakeVector3(0, 0, 0);
910 for (unsigned int i = 0; i < gjk.m_simplex->rank; ++i)
912 const b3Scalar p = gjk.m_simplex->p[i];
913 w0 += shape.Support(gjk.m_simplex->c[i]->d, 0, verticesA, verticesB) * p;
914 w1 += shape.Support(-gjk.m_simplex->c[i]->d, 1, verticesA, verticesB) * p;
916 results.witnesses[0] = transA * w0;
917 results.witnesses[1] = transA * w1;
918 results.normal = w0 - w1;
919 results.distance = results.normal.length();
920 results.normal /= results.distance > GJK_MIN_DISTANCE ? results.distance : 1;
925 results.status = gjk_status == b3GJK::eStatus::Inside ? sResults::Penetrating : sResults::GJK_Failed;
931 bool b3GjkEpaSolver2::Penetration(const b3Transform& transA, const b3Transform& transB,
932 const b3ConvexPolyhedronData* hullA, const b3ConvexPolyhedronData* hullB,
933 const b3AlignedObjectArray<b3Vector3>& verticesA,
934 const b3AlignedObjectArray<b3Vector3>& verticesB,
935 const b3Vector3& guess,
940 Initialize(transA, transB, hullA, hullB, verticesA, verticesB, results, shape, usemargins);
941 b3GJK gjk(verticesA, verticesB);
942 b3GJK::eStatus::_ gjk_status = gjk.Evaluate(shape, guess);
945 case b3GJK::eStatus::Inside:
948 b3EPA::eStatus::_ epa_status = epa.Evaluate(gjk, -guess);
949 if (epa_status != b3EPA::eStatus::Failed)
951 b3Vector3 w0 = b3MakeVector3(0, 0, 0);
952 for (unsigned int i = 0; i < epa.m_result.rank; ++i)
954 w0 += shape.Support(epa.m_result.c[i]->d, 0, verticesA, verticesB) * epa.m_result.p[i];
956 results.status = sResults::Penetrating;
957 results.witnesses[0] = transA * w0;
958 results.witnesses[1] = transA * (w0 - epa.m_normal * epa.m_depth);
959 results.normal = -epa.m_normal;
960 results.distance = -epa.m_depth;
964 results.status = sResults::EPA_Failed;
967 case b3GJK::eStatus::Failed:
968 results.status = sResults::GJK_Failed;
979 b3Scalar b3GjkEpaSolver2::SignedDistance(const b3Vector3& position,
981 const b3Transform& transA,
982 const b3ConvexPolyhedronData& hullA,
983 const b3AlignedObjectArray<b3Vector3>& verticesA,
987 btSphereShape shape1(margin);
988 b3Transform wtrs1(b3Quaternion(0,0,0,1),position);
989 Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
991 GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,b3Vector3(1,1,1));
992 if(gjk_status==GJK::eStatus::Valid)
994 b3Vector3 w0=b3Vector3(0,0,0);
995 b3Vector3 w1=b3Vector3(0,0,0);
996 for(unsigned int i=0;i<gjk.m_simplex->rank;++i)
998 const b3Scalar p=gjk.m_simplex->p[i];
999 w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
1000 w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
1002 results.witnesses[0] = wtrs0*w0;
1003 results.witnesses[1] = wtrs0*w1;
1004 const b3Vector3 delta= results.witnesses[1]-
1005 results.witnesses[0];
1006 const b3Scalar margin= shape0->getMarginNonVirtual()+
1007 shape1.getMarginNonVirtual();
1008 const b3Scalar length= delta.length();
1009 results.normal = delta/length;
1010 results.witnesses[0] += results.normal*margin;
1011 return(length-margin);
1015 if(gjk_status==GJK::eStatus::Inside)
1017 if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results))
1019 const b3Vector3 delta= results.witnesses[0]-
1020 results.witnesses[1];
1021 const b3Scalar length= delta.length();
1022 if (length >= B3_EPSILON)
1023 results.normal = delta/length;
1028 return(B3_INFINITY);
1032 bool b3GjkEpaSolver2::SignedDistance(const btConvexShape* shape0,
1033 const b3Transform& wtrs0,
1034 const btConvexShape* shape1,
1035 const b3Transform& wtrs1,
1036 const b3Vector3& guess,
1039 if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
1040 return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
1046 /* Symbols cleanup */
1048 #undef GJK_MAX_ITERATIONS
1050 #undef GJK_MIN_DISTANCE
1051 #undef GJK_DUPLICATED_EPS
1052 #undef GJK_SIMPLEX2_EPS
1053 #undef GJK_SIMPLEX3_EPS
1054 #undef GJK_SIMPLEX4_EPS
1056 #undef EPA_MAX_VERTICES
1057 #undef EPA_MAX_FACES
1058 #undef EPA_MAX_ITERATIONS
1061 #undef EPA_PLANE_EPS
1062 #undef EPA_INSIDE_EPS