btGjkPairDetector.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480
  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 "bullet/BulletCollision//CollisionShapes/btConvexShape.h"
  15. #include "bullet/BulletCollision//NarrowPhaseCollision/btSimplexSolverInterface.h"
  16. #include "bullet/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. //#define DEBUG_SPU_COLLISION_DETECTION 1
  24. #endif //__SPU__
  25. #endif
  26. //must be above the machine epsilon
  27. #define REL_ERROR2 btScalar(1.0e-6)
  28. //temp globals, to improve GJK/EPA/penetration calculations
  29. int gNumDeepPenetrationChecks = 0;
  30. int gNumGjkChecks = 0;
  31. btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver)
  32. :m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
  33. m_penetrationDepthSolver(penetrationDepthSolver),
  34. m_simplexSolver(simplexSolver),
  35. m_minkowskiA(objectA),
  36. m_minkowskiB(objectB),
  37. m_shapeTypeA(objectA->getShapeType()),
  38. m_shapeTypeB(objectB->getShapeType()),
  39. m_marginA(objectA->getMargin()),
  40. m_marginB(objectB->getMargin()),
  41. m_ignoreMargin(false),
  42. m_lastUsedMethod(-1),
  43. m_catchDegeneracies(1),
  44. m_fixContactNormalDirection(1)
  45. {
  46. }
  47. btGjkPairDetector::btGjkPairDetector(const btConvexShape* objectA,const btConvexShape* objectB,int shapeTypeA,int shapeTypeB,btScalar marginA, btScalar marginB, btSimplexSolverInterface* simplexSolver,btConvexPenetrationDepthSolver* penetrationDepthSolver)
  48. :m_cachedSeparatingAxis(btScalar(0.),btScalar(1.),btScalar(0.)),
  49. m_penetrationDepthSolver(penetrationDepthSolver),
  50. m_simplexSolver(simplexSolver),
  51. m_minkowskiA(objectA),
  52. m_minkowskiB(objectB),
  53. m_shapeTypeA(shapeTypeA),
  54. m_shapeTypeB(shapeTypeB),
  55. m_marginA(marginA),
  56. m_marginB(marginB),
  57. m_ignoreMargin(false),
  58. m_lastUsedMethod(-1),
  59. m_catchDegeneracies(1),
  60. m_fixContactNormalDirection(1)
  61. {
  62. }
  63. void btGjkPairDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw,bool swapResults)
  64. {
  65. (void)swapResults;
  66. getClosestPointsNonVirtual(input,output,debugDraw);
  67. }
  68. #ifdef __SPU__
  69. void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
  70. #else
  71. void btGjkPairDetector::getClosestPointsNonVirtual(const ClosestPointInput& input,Result& output,class btIDebugDraw* debugDraw)
  72. #endif
  73. {
  74. m_cachedSeparatingDistance = 0.f;
  75. btScalar distance=btScalar(0.);
  76. btVector3 normalInB(btScalar(0.),btScalar(0.),btScalar(0.));
  77. btVector3 pointOnA,pointOnB;
  78. btTransform localTransA = input.m_transformA;
  79. btTransform localTransB = input.m_transformB;
  80. btVector3 positionOffset = (localTransA.getOrigin() + localTransB.getOrigin()) * btScalar(0.5);
  81. localTransA.getOrigin() -= positionOffset;
  82. localTransB.getOrigin() -= positionOffset;
  83. bool check2d = m_minkowskiA->isConvex2d() && m_minkowskiB->isConvex2d();
  84. btScalar marginA = m_marginA;
  85. btScalar marginB = m_marginB;
  86. gNumGjkChecks++;
  87. #ifdef DEBUG_SPU_COLLISION_DETECTION
  88. spu_printf("inside gjk\n");
  89. #endif
  90. //for CCD we don't use margins
  91. if (m_ignoreMargin)
  92. {
  93. marginA = btScalar(0.);
  94. marginB = btScalar(0.);
  95. #ifdef DEBUG_SPU_COLLISION_DETECTION
  96. spu_printf("ignoring margin\n");
  97. #endif
  98. }
  99. m_curIter = 0;
  100. int gGjkMaxIter = 1000;//this is to catch invalid input, perhaps check for #NaN?
  101. m_cachedSeparatingAxis.setValue(0,1,0);
  102. bool isValid = false;
  103. bool checkSimplex = false;
  104. bool checkPenetration = true;
  105. m_degenerateSimplex = 0;
  106. m_lastUsedMethod = -1;
  107. {
  108. btScalar squaredDistance = BT_LARGE_FLOAT;
  109. btScalar delta = btScalar(0.);
  110. btScalar margin = marginA + marginB;
  111. m_simplexSolver->reset();
  112. for ( ; ; )
  113. //while (true)
  114. {
  115. btVector3 seperatingAxisInA = (-m_cachedSeparatingAxis)* input.m_transformA.getBasis();
  116. btVector3 seperatingAxisInB = m_cachedSeparatingAxis* input.m_transformB.getBasis();
  117. #if 1
  118. btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
  119. btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
  120. // btVector3 pInA = localGetSupportingVertexWithoutMargin(m_shapeTypeA, m_minkowskiA, seperatingAxisInA,input.m_convexVertexData[0]);//, &featureIndexA);
  121. // btVector3 qInB = localGetSupportingVertexWithoutMargin(m_shapeTypeB, m_minkowskiB, seperatingAxisInB,input.m_convexVertexData[1]);//, &featureIndexB);
  122. #else
  123. #ifdef __SPU__
  124. btVector3 pInA = m_minkowskiA->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInA);
  125. btVector3 qInB = m_minkowskiB->localGetSupportVertexWithoutMarginNonVirtual(seperatingAxisInB);
  126. #else
  127. btVector3 pInA = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA);
  128. btVector3 qInB = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB);
  129. #ifdef TEST_NON_VIRTUAL
  130. btVector3 pInAv = m_minkowskiA->localGetSupportingVertexWithoutMargin(seperatingAxisInA);
  131. btVector3 qInBv = m_minkowskiB->localGetSupportingVertexWithoutMargin(seperatingAxisInB);
  132. btAssert((pInAv-pInA).length() < 0.0001);
  133. btAssert((qInBv-qInB).length() < 0.0001);
  134. #endif //
  135. #endif //__SPU__
  136. #endif
  137. btVector3 pWorld = localTransA(pInA);
  138. btVector3 qWorld = localTransB(qInB);
  139. #ifdef DEBUG_SPU_COLLISION_DETECTION
  140. spu_printf("got local supporting vertices\n");
  141. #endif
  142. if (check2d)
  143. {
  144. pWorld[2] = 0.f;
  145. qWorld[2] = 0.f;
  146. }
  147. btVector3 w = pWorld - qWorld;
  148. delta = m_cachedSeparatingAxis.dot(w);
  149. // potential exit, they don't overlap
  150. if ((delta > btScalar(0.0)) && (delta * delta > squaredDistance * input.m_maximumDistanceSquared))
  151. {
  152. m_degenerateSimplex = 10;
  153. checkSimplex=true;
  154. //checkPenetration = false;
  155. break;
  156. }
  157. //exit 0: the new point is already in the simplex, or we didn't come any closer
  158. if (m_simplexSolver->inSimplex(w))
  159. {
  160. m_degenerateSimplex = 1;
  161. checkSimplex = true;
  162. break;
  163. }
  164. // are we getting any closer ?
  165. btScalar f0 = squaredDistance - delta;
  166. btScalar f1 = squaredDistance * REL_ERROR2;
  167. if (f0 <= f1)
  168. {
  169. if (f0 <= btScalar(0.))
  170. {
  171. m_degenerateSimplex = 2;
  172. } else
  173. {
  174. m_degenerateSimplex = 11;
  175. }
  176. checkSimplex = true;
  177. break;
  178. }
  179. #ifdef DEBUG_SPU_COLLISION_DETECTION
  180. spu_printf("addVertex 1\n");
  181. #endif
  182. //add current vertex to simplex
  183. m_simplexSolver->addVertex(w, pWorld, qWorld);
  184. #ifdef DEBUG_SPU_COLLISION_DETECTION
  185. spu_printf("addVertex 2\n");
  186. #endif
  187. btVector3 newCachedSeparatingAxis;
  188. //calculate the closest point to the origin (update vector v)
  189. if (!m_simplexSolver->closest(newCachedSeparatingAxis))
  190. {
  191. m_degenerateSimplex = 3;
  192. checkSimplex = true;
  193. break;
  194. }
  195. if(newCachedSeparatingAxis.length2()<REL_ERROR2)
  196. {
  197. m_cachedSeparatingAxis = newCachedSeparatingAxis;
  198. m_degenerateSimplex = 6;
  199. checkSimplex = true;
  200. break;
  201. }
  202. btScalar previousSquaredDistance = squaredDistance;
  203. squaredDistance = newCachedSeparatingAxis.length2();
  204. #if 0
  205. ///warning: this termination condition leads to some problems in 2d test case see Bullet/Demos/Box2dDemo
  206. if (squaredDistance>previousSquaredDistance)
  207. {
  208. m_degenerateSimplex = 7;
  209. squaredDistance = previousSquaredDistance;
  210. checkSimplex = false;
  211. break;
  212. }
  213. #endif //
  214. //redundant m_simplexSolver->compute_points(pointOnA, pointOnB);
  215. //are we getting any closer ?
  216. if (previousSquaredDistance - squaredDistance <= SIMD_EPSILON * previousSquaredDistance)
  217. {
  218. // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
  219. checkSimplex = true;
  220. m_degenerateSimplex = 12;
  221. break;
  222. }
  223. m_cachedSeparatingAxis = newCachedSeparatingAxis;
  224. //degeneracy, this is typically due to invalid/uninitialized worldtransforms for a btCollisionObject
  225. if (m_curIter++ > gGjkMaxIter)
  226. {
  227. #if defined(DEBUG) || defined (_DEBUG) || defined (DEBUG_SPU_COLLISION_DETECTION)
  228. printf("btGjkPairDetector maxIter exceeded:%i\n",m_curIter);
  229. printf("sepAxis=(%f,%f,%f), squaredDistance = %f, shapeTypeA=%i,shapeTypeB=%i\n",
  230. m_cachedSeparatingAxis.getX(),
  231. m_cachedSeparatingAxis.getY(),
  232. m_cachedSeparatingAxis.getZ(),
  233. squaredDistance,
  234. m_minkowskiA->getShapeType(),
  235. m_minkowskiB->getShapeType());
  236. #endif
  237. break;
  238. }
  239. bool check = (!m_simplexSolver->fullSimplex());
  240. //bool check = (!m_simplexSolver->fullSimplex() && squaredDistance > SIMD_EPSILON * m_simplexSolver->maxVertex());
  241. if (!check)
  242. {
  243. //do we need this backup_closest here ?
  244. // m_simplexSolver->backup_closest(m_cachedSeparatingAxis);
  245. m_degenerateSimplex = 13;
  246. break;
  247. }
  248. }
  249. if (checkSimplex)
  250. {
  251. m_simplexSolver->compute_points(pointOnA, pointOnB);
  252. normalInB = m_cachedSeparatingAxis;
  253. btScalar lenSqr =m_cachedSeparatingAxis.length2();
  254. //valid normal
  255. if (lenSqr < 0.0001)
  256. {
  257. m_degenerateSimplex = 5;
  258. }
  259. if (lenSqr > SIMD_EPSILON*SIMD_EPSILON)
  260. {
  261. btScalar rlen = btScalar(1.) / btSqrt(lenSqr );
  262. normalInB *= rlen; //normalize
  263. btScalar s = btSqrt(squaredDistance);
  264. btAssert(s > btScalar(0.0));
  265. pointOnA -= m_cachedSeparatingAxis * (marginA / s);
  266. pointOnB += m_cachedSeparatingAxis * (marginB / s);
  267. distance = ((btScalar(1.)/rlen) - margin);
  268. isValid = true;
  269. m_lastUsedMethod = 1;
  270. } else
  271. {
  272. m_lastUsedMethod = 2;
  273. }
  274. }
  275. bool catchDegeneratePenetrationCase =
  276. (m_catchDegeneracies && m_penetrationDepthSolver && m_degenerateSimplex && ((distance+margin) < 0.01));
  277. //if (checkPenetration && !isValid)
  278. if (checkPenetration && (!isValid || catchDegeneratePenetrationCase ))
  279. {
  280. //penetration case
  281. //if there is no way to handle penetrations, bail out
  282. if (m_penetrationDepthSolver)
  283. {
  284. // Penetration depth case.
  285. btVector3 tmpPointOnA,tmpPointOnB;
  286. gNumDeepPenetrationChecks++;
  287. m_cachedSeparatingAxis.setZero();
  288. bool isValid2 = m_penetrationDepthSolver->calcPenDepth(
  289. *m_simplexSolver,
  290. m_minkowskiA,m_minkowskiB,
  291. localTransA,localTransB,
  292. m_cachedSeparatingAxis, tmpPointOnA, tmpPointOnB,
  293. debugDraw
  294. );
  295. if (isValid2)
  296. {
  297. btVector3 tmpNormalInB = tmpPointOnB-tmpPointOnA;
  298. btScalar lenSqr = tmpNormalInB.length2();
  299. if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
  300. {
  301. tmpNormalInB = m_cachedSeparatingAxis;
  302. lenSqr = m_cachedSeparatingAxis.length2();
  303. }
  304. if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
  305. {
  306. tmpNormalInB /= btSqrt(lenSqr);
  307. btScalar distance2 = -(tmpPointOnA-tmpPointOnB).length();
  308. //only replace valid penetrations when the result is deeper (check)
  309. if (!isValid || (distance2 < distance))
  310. {
  311. distance = distance2;
  312. pointOnA = tmpPointOnA;
  313. pointOnB = tmpPointOnB;
  314. normalInB = tmpNormalInB;
  315. isValid = true;
  316. m_lastUsedMethod = 3;
  317. } else
  318. {
  319. m_lastUsedMethod = 8;
  320. }
  321. } else
  322. {
  323. m_lastUsedMethod = 9;
  324. }
  325. } else
  326. {
  327. ///this is another degenerate case, where the initial GJK calculation reports a degenerate case
  328. ///EPA reports no penetration, and the second GJK (using the supporting vector without margin)
  329. ///reports a valid positive distance. Use the results of the second GJK instead of failing.
  330. ///thanks to Jacob.Langford for the reproduction case
  331. ///http://code.google.com/p/bullet/issues/detail?id=250
  332. if (m_cachedSeparatingAxis.length2() > btScalar(0.))
  333. {
  334. btScalar distance2 = (tmpPointOnA-tmpPointOnB).length()-margin;
  335. //only replace valid distances when the distance is less
  336. if (!isValid || (distance2 < distance))
  337. {
  338. distance = distance2;
  339. pointOnA = tmpPointOnA;
  340. pointOnB = tmpPointOnB;
  341. pointOnA -= m_cachedSeparatingAxis * marginA ;
  342. pointOnB += m_cachedSeparatingAxis * marginB ;
  343. normalInB = m_cachedSeparatingAxis;
  344. normalInB.normalize();
  345. isValid = true;
  346. m_lastUsedMethod = 6;
  347. } else
  348. {
  349. m_lastUsedMethod = 5;
  350. }
  351. }
  352. }
  353. }
  354. }
  355. }
  356. if (isValid && ((distance < 0) || (distance*distance < input.m_maximumDistanceSquared)))
  357. {
  358. #if 0
  359. ///some debugging
  360. // if (check2d)
  361. {
  362. printf("n = %2.3f,%2.3f,%2.3f. ",normalInB[0],normalInB[1],normalInB[2]);
  363. printf("distance = %2.3f exit=%d deg=%d\n",distance,m_lastUsedMethod,m_degenerateSimplex);
  364. }
  365. #endif
  366. if (m_fixContactNormalDirection)
  367. {
  368. ///@workaround for sticky convex collisions
  369. //in some degenerate cases (usually when the use uses very small margins)
  370. //the contact normal is pointing the wrong direction
  371. //so fix it now (until we can deal with all degenerate cases in GJK and EPA)
  372. //contact normals need to point from B to A in all cases, so we can simply check if the contact normal really points from B to A
  373. //We like to use a dot product of the normal against the difference of the centroids,
  374. //once the centroid is available in the API
  375. //until then we use the center of the aabb to approximate the centroid
  376. btVector3 aabbMin,aabbMax;
  377. m_minkowskiA->getAabb(localTransA,aabbMin,aabbMax);
  378. btVector3 posA = (aabbMax+aabbMin)*btScalar(0.5);
  379. m_minkowskiB->getAabb(localTransB,aabbMin,aabbMax);
  380. btVector3 posB = (aabbMin+aabbMax)*btScalar(0.5);
  381. btVector3 diff = posA-posB;
  382. if (diff.dot(normalInB) < 0.f)
  383. normalInB *= -1.f;
  384. }
  385. m_cachedSeparatingAxis = normalInB;
  386. m_cachedSeparatingDistance = distance;
  387. output.addContactPoint(
  388. normalInB,
  389. pointOnB+positionOffset,
  390. distance);
  391. }
  392. }