Bullet Collision Detection & Physics Library
btGjkPairDetector.cpp
Go to the documentation of this file.
1 /*
2 Bullet Continuous Collision Detection and Physics Library
3 Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/
4 
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 use of this software.
7 Permission is granted to anyone to use this software for any purpose,
8 including commercial applications, and to alter it and redistribute it freely,
9 subject to the following restrictions:
10 
11 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
12 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
13 3. This notice may not be removed or altered from any source distribution.
14 */
15 
16 #include "btGjkPairDetector.h"
20 
21 
22 
23 #if defined(DEBUG) || defined (_DEBUG)
24 //#define TEST_NON_VIRTUAL 1
25 #include <stdio.h> //for debug printf
26 #ifdef __SPU__
27 #include <spu_printf.h>
28 #define printf spu_printf
29 #endif //__SPU__
30 #endif
31 
32 //must be above the machine epsilon
33 #ifdef BT_USE_DOUBLE_PRECISION
34  #define REL_ERROR2 btScalar(1.0e-12)
36 #else
37  #define REL_ERROR2 btScalar(1.0e-6)
39 #endif
40 
41 //temp globals, to improve GJK/EPA/penetration calculations
43 int gNumGjkChecks = 0;
44 
45 
47 :m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
48 m_penetrationDepthSolver(penetrationDepthSolver),
49 m_simplexSolver(simplexSolver),
50 m_minkowskiA(objectA),
51 m_minkowskiB(objectB),
52 m_shapeTypeA(objectA->getShapeType()),
53 m_shapeTypeB(objectB->getShapeType()),
54 m_marginA(objectA->getMargin()),
55 m_marginB(objectB->getMargin()),
56 m_ignoreMargin(false),
57 m_lastUsedMethod(-1),
58 m_catchDegeneracies(1),
59 m_fixContactNormalDirection(1)
60 {
61 }
62 btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver)
64 m_penetrationDepthSolver(penetrationDepthSolver),
65 m_simplexSolver(simplexSolver),
66 m_minkowskiA(objectA),
67 m_minkowskiB(objectB),
68 m_shapeTypeA(shapeTypeA),
69 m_shapeTypeB(shapeTypeB),
70 m_marginA(marginA),
71 m_marginB(marginB),
72 m_ignoreMargin(false),
76 {
77 }
78 
79 void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
80 {
81  (void)swapResults;
82 
83  getClosestPointsNonVirtual(input,output,debugDraw);
84 }
85 
86 static void btComputeSupport(const btConvexShape* convexA, const btTransform& localTransA, const btConvexShape* convexB, const btTransform& localTransB, const btVector3& dir, bool check2d, btVector3& supAworld, btVector3& supBworld, btVector3& aMinb)
87 {
88  btVector3 seperatingAxisInA = (dir)* localTransA.getBasis();
89  btVector3 seperatingAxisInB = (-dir)* localTransB.getBasis();
90 
91  btVector3 pInANoMargin = convexA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
92  btVector3 qInBNoMargin = convexB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
93 
94  btVector3 pInA = pInANoMargin;
95  btVector3 qInB = qInBNoMargin;
96 
97  supAworld = localTransA(pInA);
98  supBworld = localTransB(qInB);
99 
100  if (check2d)
101  {
102  supAworld[2] = 0.f;
103  supBworld[2] = 0.f;
104  }
105 
106  aMinb = supAworld - supBworld;
107 }
108 
110 {
114 };
115 
116 struct btSimplex
117 {
119  int last;
120 };
121 
122 static btVector3 ccd_vec3_origin(0, 0, 0);
123 
124 
125 inline void btSimplexInit(btSimplex *s)
126 {
127  s->last = -1;
128 }
129 
130 inline int btSimplexSize(const btSimplex *s)
131 {
132  return s->last + 1;
133 }
134 
135 inline const btSupportVector *btSimplexPoint(const btSimplex *s, int idx)
136 {
137  // here is no check on boundaries
138  return &s->ps[idx];
139 }
141 {
142  *d = *s;
143 }
144 
145 inline void btVec3Copy(btVector3 *v, const btVector3* w)
146 {
147  *v = *w;
148 }
149 
150 inline void ccdVec3Add(btVector3*v, const btVector3*w)
151 {
152  v->m_floats[0] += w->m_floats[0];
153  v->m_floats[1] += w->m_floats[1];
154  v->m_floats[2] += w->m_floats[2];
155 }
156 
157 
158 inline void ccdVec3Sub(btVector3 *v, const btVector3 *w)
159 {
160  *v -= *w;
161 }
162 inline void btVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
163 {
164  *d = (*v) - (*w);
165 
166 }
167 inline btScalar btVec3Dot(const btVector3 *a, const btVector3 *b)
168 {
169  btScalar dot;
170  dot = a->dot(*b);
171 
172  return dot;
173 }
174 
175 inline btScalar ccdVec3Dist2(const btVector3 *a, const btVector3*b)
176 {
177  btVector3 ab;
178  btVec3Sub2(&ab, a, b);
179  return btVec3Dot(&ab, &ab);
180 }
181 
182 
183 inline void btVec3Scale(btVector3 *d, btScalar k)
184 {
185  d->m_floats[0] *= k;
186  d->m_floats[1] *= k;
187  d->m_floats[2] *= k;
188 }
189 
190 inline void btVec3Cross(btVector3 *d, const btVector3 *a, const btVector3 *b)
191 {
192  d->m_floats[0] = (a->m_floats[1] * b->m_floats[2]) - (a->m_floats[2] * b->m_floats[1]);
193  d->m_floats[1] = (a->m_floats[2] * b->m_floats[0]) - (a->m_floats[0] * b->m_floats[2]);
194  d->m_floats[2] = (a->m_floats[0] * b->m_floats[1]) - (a->m_floats[1] * b->m_floats[0]);
195 }
196 
197 inline void btTripleCross(const btVector3 *a, const btVector3 *b,
198  const btVector3 *c, btVector3 *d)
199 {
200  btVector3 e;
201  btVec3Cross(&e, a, b);
202  btVec3Cross(d, &e, c);
203 }
204 
205 inline int ccdEq(btScalar _a, btScalar _b)
206 {
207  btScalar ab;
208  btScalar a, b;
209 
210  ab = btFabs(_a - _b);
211  if (btFabs(ab) < SIMD_EPSILON)
212  return 1;
213 
214  a = btFabs(_a);
215  b = btFabs(_b);
216  if (b > a) {
217  return ab < SIMD_EPSILON * b;
218  }
219  else {
220  return ab < SIMD_EPSILON * a;
221  }
222 }
223 
225 {
226  return v->x();
227 }
228 
230 {
231  return v->y();
232 }
233 
235 {
236  return v->z();
237 }
238 inline int btVec3Eq(const btVector3 *a, const btVector3 *b)
239 {
240  return ccdEq(ccdVec3X(a), ccdVec3X(b))
241  && ccdEq(ccdVec3Y(a), ccdVec3Y(b))
242  && ccdEq(ccdVec3Z(a), ccdVec3Z(b));
243 }
244 
245 
246 inline void btSimplexAdd(btSimplex *s, const btSupportVector *v)
247 {
248  // here is no check on boundaries in sake of speed
249  ++s->last;
250  btSupportCopy(s->ps + s->last, v);
251 }
252 
253 
254 inline void btSimplexSet(btSimplex *s, size_t pos, const btSupportVector *a)
255 {
256  btSupportCopy(s->ps + pos, a);
257 }
258 
259 inline void btSimplexSetSize(btSimplex *s, int size)
260 {
261  s->last = size - 1;
262 }
263 
264 inline const btSupportVector *ccdSimplexLast(const btSimplex *s)
265 {
266  return btSimplexPoint(s, s->last);
267 }
268 
269 inline int ccdSign(btScalar val)
270 {
271  if (btFuzzyZero(val)) {
272  return 0;
273  }
274  else if (val < btScalar(0)) {
275  return -1;
276  }
277  return 1;
278 }
279 
280 
282  const btVector3 *x0,
283  const btVector3 *b,
284  btVector3 *witness)
285 {
286  // The computation comes from solving equation of segment:
287  // S(t) = x0 + t.d
288  // where - x0 is initial point of segment
289  // - d is direction of segment from x0 (|d| > 0)
290  // - t belongs to <0, 1> interval
291  //
292  // Than, distance from a segment to some point P can be expressed:
293  // D(t) = |x0 + t.d - P|^2
294  // which is distance from any point on segment. Minimization
295  // of this function brings distance from P to segment.
296  // Minimization of D(t) leads to simple quadratic equation that's
297  // solving is straightforward.
298  //
299  // Bonus of this method is witness point for free.
300 
301  btScalar dist, t;
302  btVector3 d, a;
303 
304  // direction of segment
305  btVec3Sub2(&d, b, x0);
306 
307  // precompute vector from P to x0
308  btVec3Sub2(&a, x0, P);
309 
310  t = -btScalar(1.) * btVec3Dot(&a, &d);
311  t /= btVec3Dot(&d, &d);
312 
313  if (t < btScalar(0) || btFuzzyZero(t)) {
314  dist = ccdVec3Dist2(x0, P);
315  if (witness)
316  btVec3Copy(witness, x0);
317  }
318  else if (t > btScalar(1) || ccdEq(t, btScalar(1))) {
319  dist = ccdVec3Dist2(b, P);
320  if (witness)
321  btVec3Copy(witness, b);
322  }
323  else {
324  if (witness) {
325  btVec3Copy(witness, &d);
326  btVec3Scale(witness, t);
327  ccdVec3Add(witness, x0);
328  dist = ccdVec3Dist2(witness, P);
329  }
330  else {
331  // recycling variables
332  btVec3Scale(&d, t);
333  ccdVec3Add(&d, &a);
334  dist = btVec3Dot(&d, &d);
335  }
336  }
337 
338  return dist;
339 }
340 
341 
343  const btVector3 *x0, const btVector3 *B,
344  const btVector3 *C,
345  btVector3 *witness)
346 {
347  // Computation comes from analytic expression for triangle (x0, B, C)
348  // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and
349  // Then equation for distance is:
350  // D(s, t) = | T(s, t) - P |^2
351  // This leads to minimization of quadratic function of two variables.
352  // The solution from is taken only if s is between 0 and 1, t is
353  // between 0 and 1 and t + s < 1, otherwise distance from segment is
354  // computed.
355 
356  btVector3 d1, d2, a;
357  double u, v, w, p, q, r;
358  double s, t, dist, dist2;
359  btVector3 witness2;
360 
361  btVec3Sub2(&d1, B, x0);
362  btVec3Sub2(&d2, C, x0);
363  btVec3Sub2(&a, x0, P);
364 
365  u = btVec3Dot(&a, &a);
366  v = btVec3Dot(&d1, &d1);
367  w = btVec3Dot(&d2, &d2);
368  p = btVec3Dot(&a, &d1);
369  q = btVec3Dot(&a, &d2);
370  r = btVec3Dot(&d1, &d2);
371 
372  s = (q * r - w * p) / (w * v - r * r);
373  t = (-s * r - q) / w;
374 
375  if ((btFuzzyZero(s) || s > btScalar(0))
376  && (ccdEq(s, btScalar(1)) || s < btScalar(1))
377  && (btFuzzyZero(t) || t > btScalar(0))
378  && (ccdEq(t, btScalar(1)) || t < btScalar(1))
379  && (ccdEq(t + s, btScalar(1)) || t + s < btScalar(1))) {
380 
381  if (witness)
382  {
383  btVec3Scale(&d1, s);
384  btVec3Scale(&d2, t);
385  btVec3Copy(witness, x0);
386  ccdVec3Add(witness, &d1);
387  ccdVec3Add(witness, &d2);
388 
389  dist = ccdVec3Dist2(witness, P);
390  }
391  else
392  {
393  dist = s * s * v;
394  dist += t * t * w;
395  dist += btScalar(2.) * s * t * r;
396  dist += btScalar(2.) * s * p;
397  dist += btScalar(2.) * t * q;
398  dist += u;
399  }
400  }
401  else {
402  dist = btVec3PointSegmentDist2(P, x0, B, witness);
403 
404  dist2 = btVec3PointSegmentDist2(P, x0, C, &witness2);
405  if (dist2 < dist) {
406  dist = dist2;
407  if (witness)
408  btVec3Copy(witness, &witness2);
409  }
410 
411  dist2 = btVec3PointSegmentDist2(P, B, C, &witness2);
412  if (dist2 < dist) {
413  dist = dist2;
414  if (witness)
415  btVec3Copy(witness, &witness2);
416  }
417  }
418 
419  return dist;
420 }
421 
422 
423 static int btDoSimplex2(btSimplex *simplex, btVector3 *dir)
424 {
425  const btSupportVector *A, *B;
426  btVector3 AB, AO, tmp;
427  btScalar dot;
428 
429  // get last added as A
430  A = ccdSimplexLast(simplex);
431  // get the other point
432  B = btSimplexPoint(simplex, 0);
433  // compute AB oriented segment
434  btVec3Sub2(&AB, &B->v, &A->v);
435  // compute AO vector
436  btVec3Copy(&AO, &A->v);
437  btVec3Scale(&AO, -btScalar(1));
438 
439  // dot product AB . AO
440  dot = btVec3Dot(&AB, &AO);
441 
442  // check if origin doesn't lie on AB segment
443  btVec3Cross(&tmp, &AB, &AO);
444  if (btFuzzyZero(btVec3Dot(&tmp, &tmp)) && dot > btScalar(0)) {
445  return 1;
446  }
447 
448  // check if origin is in area where AB segment is
449  if (btFuzzyZero(dot) || dot < btScalar(0)) {
450  // origin is in outside are of A
451  btSimplexSet(simplex, 0, A);
452  btSimplexSetSize(simplex, 1);
453  btVec3Copy(dir, &AO);
454  }
455  else {
456  // origin is in area where AB segment is
457 
458  // keep simplex untouched and set direction to
459  // AB x AO x AB
460  btTripleCross(&AB, &AO, &AB, dir);
461  }
462 
463  return 0;
464 }
465 
466 
467 
468 static int btDoSimplex3(btSimplex *simplex, btVector3 *dir)
469 {
470  const btSupportVector *A, *B, *C;
471  btVector3 AO, AB, AC, ABC, tmp;
472  btScalar dot, dist;
473 
474  // get last added as A
475  A = ccdSimplexLast(simplex);
476  // get the other points
477  B = btSimplexPoint(simplex, 1);
478  C = btSimplexPoint(simplex, 0);
479 
480  // check touching contact
481  dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &B->v, &C->v, 0);
482  if (btFuzzyZero(dist)) {
483  return 1;
484  }
485 
486  // check if triangle is really triangle (has area > 0)
487  // if not simplex can't be expanded and thus no itersection is found
488  if (btVec3Eq(&A->v, &B->v) || btVec3Eq(&A->v, &C->v)) {
489  return -1;
490  }
491 
492  // compute AO vector
493  btVec3Copy(&AO, &A->v);
494  btVec3Scale(&AO, -btScalar(1));
495 
496  // compute AB and AC segments and ABC vector (perpendircular to triangle)
497  btVec3Sub2(&AB, &B->v, &A->v);
498  btVec3Sub2(&AC, &C->v, &A->v);
499  btVec3Cross(&ABC, &AB, &AC);
500 
501  btVec3Cross(&tmp, &ABC, &AC);
502  dot = btVec3Dot(&tmp, &AO);
503  if (btFuzzyZero(dot) || dot > btScalar(0)) {
504  dot = btVec3Dot(&AC, &AO);
505  if (btFuzzyZero(dot) || dot > btScalar(0)) {
506  // C is already in place
507  btSimplexSet(simplex, 1, A);
508  btSimplexSetSize(simplex, 2);
509  btTripleCross(&AC, &AO, &AC, dir);
510  }
511  else {
512 
513  dot = btVec3Dot(&AB, &AO);
514  if (btFuzzyZero(dot) || dot > btScalar(0)) {
515  btSimplexSet(simplex, 0, B);
516  btSimplexSet(simplex, 1, A);
517  btSimplexSetSize(simplex, 2);
518  btTripleCross(&AB, &AO, &AB, dir);
519  }
520  else {
521  btSimplexSet(simplex, 0, A);
522  btSimplexSetSize(simplex, 1);
523  btVec3Copy(dir, &AO);
524  }
525  }
526  }
527  else {
528  btVec3Cross(&tmp, &AB, &ABC);
529  dot = btVec3Dot(&tmp, &AO);
530  if (btFuzzyZero(dot) || dot > btScalar(0))
531  {
532  dot = btVec3Dot(&AB, &AO);
533  if (btFuzzyZero(dot) || dot > btScalar(0)) {
534  btSimplexSet(simplex, 0, B);
535  btSimplexSet(simplex, 1, A);
536  btSimplexSetSize(simplex, 2);
537  btTripleCross(&AB, &AO, &AB, dir);
538  }
539  else {
540  btSimplexSet(simplex, 0, A);
541  btSimplexSetSize(simplex, 1);
542  btVec3Copy(dir, &AO);
543  }
544  }
545  else {
546  dot = btVec3Dot(&ABC, &AO);
547  if (btFuzzyZero(dot) || dot > btScalar(0)) {
548  btVec3Copy(dir, &ABC);
549  }
550  else {
551  btSupportVector tmp;
552  btSupportCopy(&tmp, C);
553  btSimplexSet(simplex, 0, B);
554  btSimplexSet(simplex, 1, &tmp);
555 
556  btVec3Copy(dir, &ABC);
557  btVec3Scale(dir, -btScalar(1));
558  }
559  }
560  }
561 
562  return 0;
563 }
564 
565 static int btDoSimplex4(btSimplex *simplex, btVector3 *dir)
566 {
567  const btSupportVector *A, *B, *C, *D;
568  btVector3 AO, AB, AC, AD, ABC, ACD, ADB;
569  int B_on_ACD, C_on_ADB, D_on_ABC;
570  int AB_O, AC_O, AD_O;
571  btScalar dist;
572 
573  // get last added as A
574  A = ccdSimplexLast(simplex);
575  // get the other points
576  B = btSimplexPoint(simplex, 2);
577  C = btSimplexPoint(simplex, 1);
578  D = btSimplexPoint(simplex, 0);
579 
580  // check if tetrahedron is really tetrahedron (has volume > 0)
581  // if it is not simplex can't be expanded and thus no intersection is
582  // found
583  dist = btVec3PointTriDist2(&A->v, &B->v, &C->v, &D->v, 0);
584  if (btFuzzyZero(dist)) {
585  return -1;
586  }
587 
588  // check if origin lies on some of tetrahedron's face - if so objects
589  // intersect
590  dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &B->v, &C->v, 0);
591  if (btFuzzyZero(dist))
592  return 1;
593  dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &C->v, &D->v, 0);
594  if (btFuzzyZero(dist))
595  return 1;
596  dist = btVec3PointTriDist2(&ccd_vec3_origin, &A->v, &B->v, &D->v, 0);
597  if (btFuzzyZero(dist))
598  return 1;
599  dist = btVec3PointTriDist2(&ccd_vec3_origin, &B->v, &C->v, &D->v, 0);
600  if (btFuzzyZero(dist))
601  return 1;
602 
603  // compute AO, AB, AC, AD segments and ABC, ACD, ADB normal vectors
604  btVec3Copy(&AO, &A->v);
605  btVec3Scale(&AO, -btScalar(1));
606  btVec3Sub2(&AB, &B->v, &A->v);
607  btVec3Sub2(&AC, &C->v, &A->v);
608  btVec3Sub2(&AD, &D->v, &A->v);
609  btVec3Cross(&ABC, &AB, &AC);
610  btVec3Cross(&ACD, &AC, &AD);
611  btVec3Cross(&ADB, &AD, &AB);
612 
613  // side (positive or negative) of B, C, D relative to planes ACD, ADB
614  // and ABC respectively
615  B_on_ACD = ccdSign(btVec3Dot(&ACD, &AB));
616  C_on_ADB = ccdSign(btVec3Dot(&ADB, &AC));
617  D_on_ABC = ccdSign(btVec3Dot(&ABC, &AD));
618 
619  // whether origin is on same side of ACD, ADB, ABC as B, C, D
620  // respectively
621  AB_O = ccdSign(btVec3Dot(&ACD, &AO)) == B_on_ACD;
622  AC_O = ccdSign(btVec3Dot(&ADB, &AO)) == C_on_ADB;
623  AD_O = ccdSign(btVec3Dot(&ABC, &AO)) == D_on_ABC;
624 
625  if (AB_O && AC_O && AD_O) {
626  // origin is in tetrahedron
627  return 1;
628  // rearrange simplex to triangle and call btDoSimplex3()
629  }
630  else if (!AB_O) {
631  // B is farthest from the origin among all of the tetrahedron's
632  // points, so remove it from the list and go on with the triangle
633  // case
634 
635  // D and C are in place
636  btSimplexSet(simplex, 2, A);
637  btSimplexSetSize(simplex, 3);
638  }
639  else if (!AC_O) {
640  // C is farthest
641  btSimplexSet(simplex, 1, D);
642  btSimplexSet(simplex, 0, B);
643  btSimplexSet(simplex, 2, A);
644  btSimplexSetSize(simplex, 3);
645  }
646  else { // (!AD_O)
647  btSimplexSet(simplex, 0, C);
648  btSimplexSet(simplex, 1, B);
649  btSimplexSet(simplex, 2, A);
650  btSimplexSetSize(simplex, 3);
651  }
652 
653  return btDoSimplex3(simplex, dir);
654 }
655 
656 static int btDoSimplex(btSimplex *simplex, btVector3 *dir)
657 {
658  if (btSimplexSize(simplex) == 2) {
659  // simplex contains segment only one segment
660  return btDoSimplex2(simplex, dir);
661  }
662  else if (btSimplexSize(simplex) == 3) {
663  // simplex contains triangle
664  return btDoSimplex3(simplex, dir);
665  }
666  else { // btSimplexSize(simplex) == 4
667  // tetrahedron - this is the only shape which can encapsule origin
668  // so btDoSimplex4() also contains test on it
669  return btDoSimplex4(simplex, dir);
670  }
671 }
672 
673 #ifdef __SPU__
674 void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
675 #else
677 #endif
678 {
680 
681  btScalar distance=btScalar(0.);
682  btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.));
683 
684  btVector3 pointOnA,pointOnB;
685  btTransform localTransA = input.m_transformA;
686  btTransform localTransB = input.m_transformB;
687  btVector3 positionOffset=(localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
688  localTransA.getOrigin() -= positionOffset;
689  localTransB.getOrigin() -= positionOffset;
690 
691  bool check2d = m_minkowskiA->isConvex2d() && m_minkowskiB->isConvex2d();
692 
693  btScalar marginA = m_marginA;
694  btScalar marginB = m_marginB;
695 
696  gNumGjkChecks++;
697 
698  //for CCD we don't use margins
699  if (m_ignoreMargin)
700  {
701  marginA = btScalar(0.);
702  marginB = btScalar(0.);
703  }
704 
705  m_curIter = 0;
706  int gGjkMaxIter = 1000;//this is to catch invalid input, perhaps check for #NaN?
708 
709  bool isValid = false;
710  bool checkSimplex = false;
711  bool checkPenetration = true;
713 
714  m_lastUsedMethod = -1;
715  int status = -2;
716  btVector3 orgNormalInB(0, 0, 0);
717  btScalar margin = marginA + marginB;
718 
719  //we add a separate implementation to check if the convex shapes intersect
720  //See also "Real-time Collision Detection with Implicit Objects" by Leif Olvang
721  //Todo: integrate the simplex penetration check directly inside the Bullet btVoronoiSimplexSolver
722  //and remove this temporary code from libCCD
723  //this fixes issue https://github.com/bulletphysics/bullet3/issues/1703
724  //note, for large differences in shapes, use double precision build!
725  {
726  btScalar squaredDistance = BT_LARGE_FLOAT;
727  btScalar delta = btScalar(0.);
728 
729 
730 
731 
732  btSimplex simplex1;
733  btSimplex* simplex = &simplex1;
734  btSimplexInit(simplex);
735 
736  btVector3 dir(1, 0, 0);
737 
738  {
739 
740  btVector3 lastSupV;
741  btVector3 supAworld;
742  btVector3 supBworld;
743  btComputeSupport(m_minkowskiA, localTransA, m_minkowskiB, localTransB, dir, check2d, supAworld, supBworld, lastSupV);
744 
745  btSupportVector last;
746  last.v = lastSupV;
747  last.v1 = supAworld;
748  last.v2 = supBworld;
749 
750  btSimplexAdd(simplex, &last);
751 
752  dir = -lastSupV;
753 
754 
755 
756  // start iterations
757  for (int iterations = 0; iterations <gGjkMaxIter; iterations++)
758  {
759  // obtain support point
760  btComputeSupport(m_minkowskiA, localTransA, m_minkowskiB, localTransB, dir, check2d, supAworld, supBworld, lastSupV);
761 
762  // check if farthest point in Minkowski difference in direction dir
763  // isn't somewhere before origin (the test on negative dot product)
764  // - because if it is, objects are not intersecting at all.
765  btScalar delta = lastSupV.dot(dir);
766  if (delta < 0)
767  {
768  //no intersection, besides margin
769  status = -1;
770  break;
771  }
772 
773  // add last support vector to simplex
774  last.v = lastSupV;
775  last.v1 = supAworld;
776  last.v2 = supBworld;
777 
778  btSimplexAdd(simplex, &last);
779 
780  // if btDoSimplex returns 1 if objects intersect, -1 if objects don't
781  // intersect and 0 if algorithm should continue
782 
783  btVector3 newDir;
784  int do_simplex_res = btDoSimplex(simplex, &dir);
785 
786  if (do_simplex_res == 1)
787  {
788  status = 0; // intersection found
789  break;
790  }
791  else if (do_simplex_res == -1)
792  {
793  // intersection not found
794  status = -1;
795  break;
796  }
797 
798  if (btFuzzyZero(btVec3Dot(&dir, &dir)))
799  {
800  // intersection not found
801  status = -1;
802  }
803 
804  if (dir.length2() < SIMD_EPSILON)
805  {
806  //no intersection, besides margin
807  status = -1;
808  break;
809  }
810 
811  if (dir.fuzzyZero())
812  {
813  // intersection not found
814  status = -1;
815  break;
816  }
817  }
818 
819  }
820 
821  m_simplexSolver->reset();
822  if (status == 0)
823  {
824  //status = 0;
825  //printf("Intersect!\n");
826  }
827 
828  if (status==-1)
829  {
830  //printf("not intersect\n");
831  }
832  //printf("dir=%f,%f,%f\n",dir[0],dir[1],dir[2]);
833  if (1)
834  {
835  for (; ; )
836  //while (true)
837  {
838 
839  btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* localTransA.getBasis();
840  btVector3 seperatingAxisInB = m_cachedSeparatingAxis* localTransB.getBasis();
841 
842 
845 
846  btVector3 pWorld = localTransA(pInA);
847  btVector3 qWorld = localTransB(qInB);
848 
849 
850  if (check2d)
851  {
852  pWorld[2] = 0.f;
853  qWorld[2] = 0.f;
854  }
855 
856  btVector3 w = pWorld - qWorld;
857  delta = m_cachedSeparatingAxis.dot(w);
858 
859  // potential exit, they don't overlap
860  if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared))
861  {
862  m_degenerateSimplex = 10;
863  checkSimplex = true;
864  //checkPenetration = false;
865  break;
866  }
867 
868  //exit 0: the new point is already in the simplex, or we didn't come any closer
869  if (m_simplexSolver->inSimplex(w))
870  {
872  checkSimplex = true;
873  break;
874  }
875  // are we getting any closer ?
876  btScalar f0 = squaredDistance - delta;
877  btScalar f1 = squaredDistance * REL_ERROR2;
878 
879  if (f0 <= f1)
880  {
881  if (f0 <= btScalar(0.))
882  {
884  }
885  else
886  {
887  m_degenerateSimplex = 11;
888  }
889  checkSimplex = true;
890  break;
891  }
892 
893  //add current vertex to simplex
894  m_simplexSolver->addVertex(w, pWorld, qWorld);
895  btVector3 newCachedSeparatingAxis;
896 
897  //calculate the closest point to the origin (update vector v)
898  if (!m_simplexSolver->closest(newCachedSeparatingAxis))
899  {
901  checkSimplex = true;
902  break;
903  }
904 
905  if (newCachedSeparatingAxis.length2() < REL_ERROR2)
906  {
907  m_cachedSeparatingAxis = newCachedSeparatingAxis;
909  checkSimplex = true;
910  break;
911  }
912 
913  btScalar previousSquaredDistance = squaredDistance;
914  squaredDistance = newCachedSeparatingAxis.length2();
915 #if 0
916  if (squaredDistance > previousSquaredDistance)
918  {
920  squaredDistance = previousSquaredDistance;
921  checkSimplex = false;
922  break;
923  }
924 #endif //
925 
926 
927  //redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
928 
929  //are we getting any closer ?
930  if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
931  {
932  // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
933  checkSimplex = true;
934  m_degenerateSimplex = 12;
935 
936  break;
937  }
938 
939  m_cachedSeparatingAxis = newCachedSeparatingAxis;
940 
941  //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
942  if (m_curIter++ > gGjkMaxIter)
943  {
944 #if defined(DEBUG) || defined (_DEBUG)
945 
946  printf("btGjkPairDetector maxIter exceeded:%i\n", m_curIter);
947  printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n",
951  squaredDistance,
954 
955 #endif
956  break;
957 
958  }
959 
960 
961  bool check = (!m_simplexSolver->fullSimplex());
962  //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
963 
964  if (!check)
965  {
966  //do we need this backup_closest here ?
967  // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
968  m_degenerateSimplex = 13;
969  break;
970  }
971  }
972 
973  if (checkSimplex)
974  {
975  m_simplexSolver->compute_points(pointOnA, pointOnB);
976  normalInB = m_cachedSeparatingAxis;
977 
979 
980  //valid normal
981  if (lenSqr < REL_ERROR2)
982  {
984  }
985  if (lenSqr > SIMD_EPSILON*SIMD_EPSILON)
986  {
987  btScalar rlen = btScalar(1.) / btSqrt(lenSqr);
988  normalInB *= rlen; //normalize
989 
990  btScalar s = btSqrt(squaredDistance);
991 
992  btAssert(s > btScalar(0.0));
993  pointOnA -= m_cachedSeparatingAxis * (marginA / s);
994  pointOnB += m_cachedSeparatingAxis * (marginB / s);
995  distance = ((btScalar(1.) / rlen) - margin);
996  isValid = true;
997  orgNormalInB = normalInB;
998 
999  m_lastUsedMethod = 1;
1000  }
1001  else
1002  {
1003  m_lastUsedMethod = 2;
1004  }
1005  }
1006  }
1007 
1008 
1009 
1010  bool catchDegeneratePenetrationCase =
1012 
1013  //if (checkPenetration && !isValid)
1014  if ((checkPenetration && (!isValid || catchDegeneratePenetrationCase )) || (status == 0))
1015  {
1016  //penetration case
1017 
1018  //if there is no way to handle penetrations, bail out
1020  {
1021  // Penetration depth case.
1022  btVector3 tmpPointOnA,tmpPointOnB;
1023 
1026 
1027  bool isValid2 = m_penetrationDepthSolver->calcPenDepth(
1028  *m_simplexSolver,
1030  localTransA,localTransB,
1031  m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB,
1032  debugDraw
1033  );
1034 
1035 
1037  {
1038  if (isValid2)
1039  {
1040  btVector3 tmpNormalInB = tmpPointOnB - tmpPointOnA;
1041  btScalar lenSqr = tmpNormalInB.length2();
1042  if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
1043  {
1044  tmpNormalInB = m_cachedSeparatingAxis;
1045  lenSqr = m_cachedSeparatingAxis.length2();
1046  }
1047 
1048  if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
1049  {
1050  tmpNormalInB /= btSqrt(lenSqr);
1051  btScalar distance2 = -(tmpPointOnA - tmpPointOnB).length();
1052  m_lastUsedMethod = 3;
1053  //only replace valid penetrations when the result is deeper (check)
1054  if (!isValid || (distance2 < distance))
1055  {
1056  distance = distance2;
1057  pointOnA = tmpPointOnA;
1058  pointOnB = tmpPointOnB;
1059  normalInB = tmpNormalInB;
1060  isValid = true;
1061 
1062  }
1063  else
1064  {
1065  m_lastUsedMethod = 8;
1066  }
1067  }
1068  else
1069  {
1070  m_lastUsedMethod = 9;
1071  }
1072  }
1073  else
1074 
1075  {
1081 
1082 
1084  {
1085  btScalar distance2 = (tmpPointOnA - tmpPointOnB).length() - margin;
1086  //only replace valid distances when the distance is less
1087  if (!isValid || (distance2 < distance))
1088  {
1089  distance = distance2;
1090  pointOnA = tmpPointOnA;
1091  pointOnB = tmpPointOnB;
1092  pointOnA -= m_cachedSeparatingAxis * marginA;
1093  pointOnB += m_cachedSeparatingAxis * marginB;
1094  normalInB = m_cachedSeparatingAxis;
1095  normalInB.normalize();
1096 
1097  isValid = true;
1098  m_lastUsedMethod = 6;
1099  }
1100  else
1101  {
1102  m_lastUsedMethod = 5;
1103  }
1104  }
1105  }
1106  } else
1107  {
1108  //printf("EPA didn't return a valid value\n");
1109  }
1110 
1111  }
1112 
1113  }
1114  }
1115 
1116 
1117 
1118  if (isValid && ((distance < 0) || (distance*distance < input.m_maximumDistanceSquared)))
1119  {
1120 
1121  m_cachedSeparatingAxis = normalInB;
1122  m_cachedSeparatingDistance = distance;
1123  if (1)
1124  {
1129 
1130  btScalar d2 = 0.f;
1131  {
1132  btVector3 seperatingAxisInA = (-orgNormalInB)* localTransA.getBasis();
1133  btVector3 seperatingAxisInB = orgNormalInB* localTransB.getBasis();
1134 
1135 
1138 
1139  btVector3 pWorld = localTransA(pInA);
1140  btVector3 qWorld = localTransB(qInB);
1141  btVector3 w = pWorld - qWorld;
1142  d2 = orgNormalInB.dot(w)- margin;
1143  }
1144 
1145  btScalar d1=0;
1146  {
1147 
1148  btVector3 seperatingAxisInA = (normalInB)* localTransA.getBasis();
1149  btVector3 seperatingAxisInB = -normalInB* localTransB.getBasis();
1150 
1151 
1154 
1155  btVector3 pWorld = localTransA(pInA);
1156  btVector3 qWorld = localTransB(qInB);
1157  btVector3 w = pWorld - qWorld;
1158  d1 = (-normalInB).dot(w)- margin;
1159 
1160  }
1161  btScalar d0 = 0.f;
1162  {
1163  btVector3 seperatingAxisInA = (-normalInB)* input.m_transformA.getBasis();
1164  btVector3 seperatingAxisInB = normalInB* input.m_transformB.getBasis();
1165 
1166 
1169 
1170  btVector3 pWorld = localTransA(pInA);
1171  btVector3 qWorld = localTransB(qInB);
1172  btVector3 w = pWorld - qWorld;
1173  d0 = normalInB.dot(w)-margin;
1174  }
1175 
1176  if (d1>d0)
1177  {
1178  m_lastUsedMethod = 10;
1179  normalInB*=-1;
1180  }
1181 
1182  if (orgNormalInB.length2())
1183  {
1184  if (d2 > d0 && d2 > d1 && d2 > distance)
1185  {
1186 
1187  normalInB = orgNormalInB;
1188  distance = d2;
1189  }
1190  }
1191  }
1192 
1193 
1194  output.addContactPoint(
1195  normalInB,
1196  pointOnB+positionOffset,
1197  distance);
1198 
1199  }
1200  else
1201  {
1202  //printf("invalid gjk query\n");
1203  }
1204 
1205 
1206 }
1207 
1208 
1209 
1210 
1211 
btConvexPenetrationDepthSolver * m_penetrationDepthSolver
btVector3 m_cachedSeparatingAxis
btSimplexSolverInterface * m_simplexSolver
void btVec3Scale(btVector3 *d, btScalar k)
btGjkPairDetector(const btConvexShape *objectA, const btConvexShape *objectB, btSimplexSolverInterface *simplexSolver, btConvexPenetrationDepthSolver *penetrationDepthSolver)
#define SIMD_EPSILON
Definition: btScalar.h:521
btScalar length(const btQuaternion &q)
Return the length of a quaternion.
Definition: btQuaternion.h:906
int getShapeType() const
#define BT_LARGE_FLOAT
Definition: btScalar.h:294
void setValue(const btScalar &_x, const btScalar &_y, const btScalar &_z)
Definition: btVector3.h:652
btScalar m_cachedSeparatingDistance
void btSimplexSet(btSimplex *s, size_t pos, const btSupportVector *a)
btScalar m_floats[4]
Definition: btVector3.h:112
btScalar gGjkEpaPenetrationTolerance
ConvexPenetrationDepthSolver provides an interface for penetration depth calculation.
static int btDoSimplex(btSimplex *simplex, btVector3 *dir)
static btVector3 ccd_vec3_origin(0, 0, 0)
btScalar btVec3PointSegmentDist2(const btVector3 *P, const btVector3 *x0, const btVector3 *b, btVector3 *witness)
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
btScalar btSqrt(btScalar y)
Definition: btScalar.h:444
static int btDoSimplex3(btSimplex *simplex, btVector3 *dir)
#define btAssert(x)
Definition: btScalar.h:131
const btSupportVector * btSimplexPoint(const btSimplex *s, int idx)
int ccdEq(btScalar _a, btScalar _b)
void ccdVec3Add(btVector3 *v, const btVector3 *w)
btVector3 localGetSupportVertexWithoutMarginNonVirtual(const btVector3 &vec) const
int btVec3Eq(const btVector3 *a, const btVector3 *b)
btVector3 v1
Support point in obj1.
void btVec3Cross(btVector3 *d, const btVector3 *a, const btVector3 *b)
btScalar dot(const btVector3 &v) const
Return the dot product.
Definition: btVector3.h:235
btVector3 & normalize()
Normalize this vector x^2 + y^2 + z^2 = 1.
Definition: btVector3.h:309
static int btDoSimplex4(btSimplex *simplex, btVector3 *dir)
const btScalar & x() const
Return the x value.
Definition: btVector3.h:587
const btScalar & getZ() const
Return the z value.
Definition: btVector3.h:577
The btConvexShape is an abstract shape interface, implemented by all convex shapes such as btBoxShape...
Definition: btConvexShape.h:31
int gNumDeepPenetrationChecks
virtual bool calcPenDepth(btSimplexSolverInterface &simplexSolver, const btConvexShape *convexA, const btConvexShape *convexB, const btTransform &transA, const btTransform &transB, btVector3 &v, btVector3 &pa, btVector3 &pb, class btIDebugDraw *debugDraw)=0
void btSimplexSetSize(btSimplex *s, int size)
void btSimplexInit(btSimplex *s)
btVector3 & getOrigin()
Return the origin vector translation.
Definition: btTransform.h:117
#define btSimplexSolverInterface
#define output
void btSupportCopy(btSupportVector *d, const btSupportVector *s)
const btScalar & getY() const
Return the y value.
Definition: btVector3.h:575
btMatrix3x3 & getBasis()
Return the basis matrix for the rotation.
Definition: btTransform.h:112
const btScalar & getX() const
Return the x value.
Definition: btVector3.h:573
void btSimplexAdd(btSimplex *s, const btSupportVector *v)
void setZero()
Definition: btVector3.h:683
The btIDebugDraw interface class allows hooking up a debug renderer to visually debug simulations...
Definition: btIDebugDraw.h:29
bool fuzzyZero() const
Definition: btVector3.h:701
int last
index of last added point
const btConvexShape * m_minkowskiB
const btScalar & y() const
Return the y value.
Definition: btVector3.h:589
void btTripleCross(const btVector3 *a, const btVector3 *b, const btVector3 *c, btVector3 *d)
btVector3 v2
Support point in obj2.
void btVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
btScalar ccdVec3Dist2(const btVector3 *a, const btVector3 *b)
btVector3 can be used to represent 3D points and vectors.
Definition: btVector3.h:83
btScalar length2() const
Return the length of the vector squared.
Definition: btVector3.h:257
btScalar ccdVec3Z(const btVector3 *v)
btScalar btVec3PointTriDist2(const btVector3 *P, const btVector3 *x0, const btVector3 *B, const btVector3 *C, btVector3 *witness)
btVector3 v
Support point in minkowski sum.
#define REL_ERROR2
The btTransform class supports rigid transforms with only translation and rotation and no scaling/she...
Definition: btTransform.h:34
virtual void addContactPoint(const btVector3 &normalOnBInWorld, const btVector3 &pointInWorld, btScalar depth)=0
void ccdVec3Sub(btVector3 *v, const btVector3 *w)
int btSimplexSize(const btSimplex *s)
bool btFuzzyZero(btScalar x)
Definition: btScalar.h:550
int ccdSign(btScalar val)
const btSupportVector * ccdSimplexLast(const btSimplex *s)
bool isConvex2d() const
btScalar dot(const btQuaternion &q1, const btQuaternion &q2)
Calculate the dot product between two quaternions.
Definition: btQuaternion.h:898
btScalar ccdVec3Y(const btVector3 *v)
btSupportVector ps[4]
void btVec3Copy(btVector3 *v, const btVector3 *w)
const btConvexShape * m_minkowskiA
int gNumGjkChecks
btScalar ccdVec3X(const btVector3 *v)
btScalar btVec3Dot(const btVector3 *a, const btVector3 *b)
float btScalar
The btScalar type abstracts floating point numbers, to easily switch between double and single floati...
Definition: btScalar.h:292
virtual void getClosestPoints(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw, bool swapResults=false)
static void btComputeSupport(const btConvexShape *convexA, const btTransform &localTransA, const btConvexShape *convexB, const btTransform &localTransB, const btVector3 &dir, bool check2d, btVector3 &supAworld, btVector3 &supBworld, btVector3 &aMinb)
static int btDoSimplex2(btSimplex *simplex, btVector3 *dir)
void getClosestPointsNonVirtual(const ClosestPointInput &input, Result &output, class btIDebugDraw *debugDraw)
btScalar btFabs(btScalar x)
Definition: btScalar.h:475
const btScalar & z() const
Return the z value.
Definition: btVector3.h:591