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


tesseract_collision
Author(s): Levi Armstrong
autogenerated on Sun May 18 2025 03:01:52