btGjkPairDetector.cpp 31 KB

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