btMprPenetration.h 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885
  1. /***
  2. * ---------------------------------
  3. * Copyright (c)2012 Daniel Fiser <danfis@danfis.cz>
  4. *
  5. * This file was ported from mpr.c file, part of libccd.
  6. * The Minkoski Portal Refinement implementation was ported
  7. * to OpenCL by Erwin Coumans for the Bullet 3 Physics library.
  8. * The original MPR idea and implementation is by Gary Snethen
  9. * in XenoCollide, see http://github.com/erwincoumans/xenocollide
  10. *
  11. * Distributed under the OSI-approved BSD License (the "License");
  12. * see <http://www.opensource.org/licenses/bsd-license.php>.
  13. * This software is distributed WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  15. * See the License for more information.
  16. */
  17. ///2014 Oct, Erwin Coumans, Use templates to avoid void* casts
  18. #ifndef BT_MPR_PENETRATION_H
  19. #define BT_MPR_PENETRATION_H
  20. #define BT_DEBUG_MPR1
  21. #include "LinearMath/btTransform.h"
  22. #include "LinearMath/btAlignedObjectArray.h"
  23. //#define MPR_AVERAGE_CONTACT_POSITIONS
  24. struct btMprCollisionDescription
  25. {
  26. btVector3 m_firstDir;
  27. int m_maxGjkIterations;
  28. btScalar m_maximumDistanceSquared;
  29. btScalar m_gjkRelError2;
  30. btMprCollisionDescription()
  31. : m_firstDir(0, 1, 0),
  32. m_maxGjkIterations(1000),
  33. m_maximumDistanceSquared(1e30f),
  34. m_gjkRelError2(1.0e-6)
  35. {
  36. }
  37. virtual ~btMprCollisionDescription()
  38. {
  39. }
  40. };
  41. struct btMprDistanceInfo
  42. {
  43. btVector3 m_pointOnA;
  44. btVector3 m_pointOnB;
  45. btVector3 m_normalBtoA;
  46. btScalar m_distance;
  47. };
  48. #ifdef __cplusplus
  49. #define BT_MPR_SQRT sqrtf
  50. #else
  51. #define BT_MPR_SQRT sqrt
  52. #endif
  53. #define BT_MPR_FMIN(x, y) ((x) < (y) ? (x) : (y))
  54. #define BT_MPR_FABS fabs
  55. #define BT_MPR_TOLERANCE 1E-6f
  56. #define BT_MPR_MAX_ITERATIONS 1000
  57. struct _btMprSupport_t
  58. {
  59. btVector3 v; //!< Support point in minkowski sum
  60. btVector3 v1; //!< Support point in obj1
  61. btVector3 v2; //!< Support point in obj2
  62. };
  63. typedef struct _btMprSupport_t btMprSupport_t;
  64. struct _btMprSimplex_t
  65. {
  66. btMprSupport_t ps[4];
  67. int last; //!< index of last added point
  68. };
  69. typedef struct _btMprSimplex_t btMprSimplex_t;
  70. inline btMprSupport_t *btMprSimplexPointW(btMprSimplex_t *s, int idx)
  71. {
  72. return &s->ps[idx];
  73. }
  74. inline void btMprSimplexSetSize(btMprSimplex_t *s, int size)
  75. {
  76. s->last = size - 1;
  77. }
  78. #ifdef DEBUG_MPR
  79. inline void btPrintPortalVertex(_btMprSimplex_t *portal, int index)
  80. {
  81. printf("portal[%d].v = %f,%f,%f, v1=%f,%f,%f, v2=%f,%f,%f\n", index, portal->ps[index].v.x(), portal->ps[index].v.y(), portal->ps[index].v.z(),
  82. portal->ps[index].v1.x(), portal->ps[index].v1.y(), portal->ps[index].v1.z(),
  83. portal->ps[index].v2.x(), portal->ps[index].v2.y(), portal->ps[index].v2.z());
  84. }
  85. #endif //DEBUG_MPR
  86. inline int btMprSimplexSize(const btMprSimplex_t *s)
  87. {
  88. return s->last + 1;
  89. }
  90. inline const btMprSupport_t *btMprSimplexPoint(const btMprSimplex_t *s, int idx)
  91. {
  92. // here is no check on boundaries
  93. return &s->ps[idx];
  94. }
  95. inline void btMprSupportCopy(btMprSupport_t *d, const btMprSupport_t *s)
  96. {
  97. *d = *s;
  98. }
  99. inline void btMprSimplexSet(btMprSimplex_t *s, size_t pos, const btMprSupport_t *a)
  100. {
  101. btMprSupportCopy(s->ps + pos, a);
  102. }
  103. inline void btMprSimplexSwap(btMprSimplex_t *s, size_t pos1, size_t pos2)
  104. {
  105. btMprSupport_t supp;
  106. btMprSupportCopy(&supp, &s->ps[pos1]);
  107. btMprSupportCopy(&s->ps[pos1], &s->ps[pos2]);
  108. btMprSupportCopy(&s->ps[pos2], &supp);
  109. }
  110. inline int btMprIsZero(float val)
  111. {
  112. return BT_MPR_FABS(val) < FLT_EPSILON;
  113. }
  114. inline int btMprEq(float _a, float _b)
  115. {
  116. float ab;
  117. float a, b;
  118. ab = BT_MPR_FABS(_a - _b);
  119. if (BT_MPR_FABS(ab) < FLT_EPSILON)
  120. return 1;
  121. a = BT_MPR_FABS(_a);
  122. b = BT_MPR_FABS(_b);
  123. if (b > a)
  124. {
  125. return ab < FLT_EPSILON * b;
  126. }
  127. else
  128. {
  129. return ab < FLT_EPSILON * a;
  130. }
  131. }
  132. inline int btMprVec3Eq(const btVector3 *a, const btVector3 *b)
  133. {
  134. return btMprEq((*a).x(), (*b).x()) && btMprEq((*a).y(), (*b).y()) && btMprEq((*a).z(), (*b).z());
  135. }
  136. template <typename btConvexTemplate>
  137. inline void btFindOrigin(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc, btMprSupport_t *center)
  138. {
  139. center->v1 = a.getObjectCenterInWorld();
  140. center->v2 = b.getObjectCenterInWorld();
  141. center->v = center->v1 - center->v2;
  142. }
  143. inline void btMprVec3Set(btVector3 *v, float x, float y, float z)
  144. {
  145. v->setValue(x, y, z);
  146. }
  147. inline void btMprVec3Add(btVector3 *v, const btVector3 *w)
  148. {
  149. *v += *w;
  150. }
  151. inline void btMprVec3Copy(btVector3 *v, const btVector3 *w)
  152. {
  153. *v = *w;
  154. }
  155. inline void btMprVec3Scale(btVector3 *d, float k)
  156. {
  157. *d *= k;
  158. }
  159. inline float btMprVec3Dot(const btVector3 *a, const btVector3 *b)
  160. {
  161. float dot;
  162. dot = btDot(*a, *b);
  163. return dot;
  164. }
  165. inline float btMprVec3Len2(const btVector3 *v)
  166. {
  167. return btMprVec3Dot(v, v);
  168. }
  169. inline void btMprVec3Normalize(btVector3 *d)
  170. {
  171. float k = 1.f / BT_MPR_SQRT(btMprVec3Len2(d));
  172. btMprVec3Scale(d, k);
  173. }
  174. inline void btMprVec3Cross(btVector3 *d, const btVector3 *a, const btVector3 *b)
  175. {
  176. *d = btCross(*a, *b);
  177. }
  178. inline void btMprVec3Sub2(btVector3 *d, const btVector3 *v, const btVector3 *w)
  179. {
  180. *d = *v - *w;
  181. }
  182. inline void btPortalDir(const btMprSimplex_t *portal, btVector3 *dir)
  183. {
  184. btVector3 v2v1, v3v1;
  185. btMprVec3Sub2(&v2v1, &btMprSimplexPoint(portal, 2)->v,
  186. &btMprSimplexPoint(portal, 1)->v);
  187. btMprVec3Sub2(&v3v1, &btMprSimplexPoint(portal, 3)->v,
  188. &btMprSimplexPoint(portal, 1)->v);
  189. btMprVec3Cross(dir, &v2v1, &v3v1);
  190. btMprVec3Normalize(dir);
  191. }
  192. inline int portalEncapsulesOrigin(const btMprSimplex_t *portal,
  193. const btVector3 *dir)
  194. {
  195. float dot;
  196. dot = btMprVec3Dot(dir, &btMprSimplexPoint(portal, 1)->v);
  197. return btMprIsZero(dot) || dot > 0.f;
  198. }
  199. inline int portalReachTolerance(const btMprSimplex_t *portal,
  200. const btMprSupport_t *v4,
  201. const btVector3 *dir)
  202. {
  203. float dv1, dv2, dv3, dv4;
  204. float dot1, dot2, dot3;
  205. // find the smallest dot product of dir and {v1-v4, v2-v4, v3-v4}
  206. dv1 = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, dir);
  207. dv2 = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, dir);
  208. dv3 = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, dir);
  209. dv4 = btMprVec3Dot(&v4->v, dir);
  210. dot1 = dv4 - dv1;
  211. dot2 = dv4 - dv2;
  212. dot3 = dv4 - dv3;
  213. dot1 = BT_MPR_FMIN(dot1, dot2);
  214. dot1 = BT_MPR_FMIN(dot1, dot3);
  215. return btMprEq(dot1, BT_MPR_TOLERANCE) || dot1 < BT_MPR_TOLERANCE;
  216. }
  217. inline int portalCanEncapsuleOrigin(const btMprSimplex_t *portal,
  218. const btMprSupport_t *v4,
  219. const btVector3 *dir)
  220. {
  221. float dot;
  222. dot = btMprVec3Dot(&v4->v, dir);
  223. return btMprIsZero(dot) || dot > 0.f;
  224. }
  225. inline void btExpandPortal(btMprSimplex_t *portal,
  226. const btMprSupport_t *v4)
  227. {
  228. float dot;
  229. btVector3 v4v0;
  230. btMprVec3Cross(&v4v0, &v4->v, &btMprSimplexPoint(portal, 0)->v);
  231. dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &v4v0);
  232. if (dot > 0.f)
  233. {
  234. dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &v4v0);
  235. if (dot > 0.f)
  236. {
  237. btMprSimplexSet(portal, 1, v4);
  238. }
  239. else
  240. {
  241. btMprSimplexSet(portal, 3, v4);
  242. }
  243. }
  244. else
  245. {
  246. dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &v4v0);
  247. if (dot > 0.f)
  248. {
  249. btMprSimplexSet(portal, 2, v4);
  250. }
  251. else
  252. {
  253. btMprSimplexSet(portal, 1, v4);
  254. }
  255. }
  256. }
  257. template <typename btConvexTemplate>
  258. inline void btMprSupport(const btConvexTemplate &a, const btConvexTemplate &b,
  259. const btMprCollisionDescription &colDesc,
  260. const btVector3 &dir, btMprSupport_t *supp)
  261. {
  262. btVector3 separatingAxisInA = dir * a.getWorldTransform().getBasis();
  263. btVector3 separatingAxisInB = -dir * b.getWorldTransform().getBasis();
  264. btVector3 pInA = a.getLocalSupportWithMargin(separatingAxisInA);
  265. btVector3 qInB = b.getLocalSupportWithMargin(separatingAxisInB);
  266. supp->v1 = a.getWorldTransform()(pInA);
  267. supp->v2 = b.getWorldTransform()(qInB);
  268. supp->v = supp->v1 - supp->v2;
  269. }
  270. template <typename btConvexTemplate>
  271. static int btDiscoverPortal(const btConvexTemplate &a, const btConvexTemplate &b,
  272. const btMprCollisionDescription &colDesc,
  273. btMprSimplex_t *portal)
  274. {
  275. btVector3 dir, va, vb;
  276. float dot;
  277. int cont;
  278. // vertex 0 is center of portal
  279. btFindOrigin(a, b, colDesc, btMprSimplexPointW(portal, 0));
  280. // vertex 0 is center of portal
  281. btMprSimplexSetSize(portal, 1);
  282. btVector3 zero = btVector3(0, 0, 0);
  283. btVector3 *org = &zero;
  284. if (btMprVec3Eq(&btMprSimplexPoint(portal, 0)->v, org))
  285. {
  286. // Portal's center lies on origin (0,0,0) => we know that objects
  287. // intersect but we would need to know penetration info.
  288. // So move center little bit...
  289. btMprVec3Set(&va, FLT_EPSILON * 10.f, 0.f, 0.f);
  290. btMprVec3Add(&btMprSimplexPointW(portal, 0)->v, &va);
  291. }
  292. // vertex 1 = support in direction of origin
  293. btMprVec3Copy(&dir, &btMprSimplexPoint(portal, 0)->v);
  294. btMprVec3Scale(&dir, -1.f);
  295. btMprVec3Normalize(&dir);
  296. btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 1));
  297. btMprSimplexSetSize(portal, 2);
  298. // test if origin isn't outside of v1
  299. dot = btMprVec3Dot(&btMprSimplexPoint(portal, 1)->v, &dir);
  300. if (btMprIsZero(dot) || dot < 0.f)
  301. return -1;
  302. // vertex 2
  303. btMprVec3Cross(&dir, &btMprSimplexPoint(portal, 0)->v,
  304. &btMprSimplexPoint(portal, 1)->v);
  305. if (btMprIsZero(btMprVec3Len2(&dir)))
  306. {
  307. if (btMprVec3Eq(&btMprSimplexPoint(portal, 1)->v, org))
  308. {
  309. // origin lies on v1
  310. return 1;
  311. }
  312. else
  313. {
  314. // origin lies on v0-v1 segment
  315. return 2;
  316. }
  317. }
  318. btMprVec3Normalize(&dir);
  319. btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 2));
  320. dot = btMprVec3Dot(&btMprSimplexPoint(portal, 2)->v, &dir);
  321. if (btMprIsZero(dot) || dot < 0.f)
  322. return -1;
  323. btMprSimplexSetSize(portal, 3);
  324. // vertex 3 direction
  325. btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
  326. &btMprSimplexPoint(portal, 0)->v);
  327. btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
  328. &btMprSimplexPoint(portal, 0)->v);
  329. btMprVec3Cross(&dir, &va, &vb);
  330. btMprVec3Normalize(&dir);
  331. // it is better to form portal faces to be oriented "outside" origin
  332. dot = btMprVec3Dot(&dir, &btMprSimplexPoint(portal, 0)->v);
  333. if (dot > 0.f)
  334. {
  335. btMprSimplexSwap(portal, 1, 2);
  336. btMprVec3Scale(&dir, -1.f);
  337. }
  338. while (btMprSimplexSize(portal) < 4)
  339. {
  340. btMprSupport(a, b, colDesc, dir, btMprSimplexPointW(portal, 3));
  341. dot = btMprVec3Dot(&btMprSimplexPoint(portal, 3)->v, &dir);
  342. if (btMprIsZero(dot) || dot < 0.f)
  343. return -1;
  344. cont = 0;
  345. // test if origin is outside (v1, v0, v3) - set v2 as v3 and
  346. // continue
  347. btMprVec3Cross(&va, &btMprSimplexPoint(portal, 1)->v,
  348. &btMprSimplexPoint(portal, 3)->v);
  349. dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
  350. if (dot < 0.f && !btMprIsZero(dot))
  351. {
  352. btMprSimplexSet(portal, 2, btMprSimplexPoint(portal, 3));
  353. cont = 1;
  354. }
  355. if (!cont)
  356. {
  357. // test if origin is outside (v3, v0, v2) - set v1 as v3 and
  358. // continue
  359. btMprVec3Cross(&va, &btMprSimplexPoint(portal, 3)->v,
  360. &btMprSimplexPoint(portal, 2)->v);
  361. dot = btMprVec3Dot(&va, &btMprSimplexPoint(portal, 0)->v);
  362. if (dot < 0.f && !btMprIsZero(dot))
  363. {
  364. btMprSimplexSet(portal, 1, btMprSimplexPoint(portal, 3));
  365. cont = 1;
  366. }
  367. }
  368. if (cont)
  369. {
  370. btMprVec3Sub2(&va, &btMprSimplexPoint(portal, 1)->v,
  371. &btMprSimplexPoint(portal, 0)->v);
  372. btMprVec3Sub2(&vb, &btMprSimplexPoint(portal, 2)->v,
  373. &btMprSimplexPoint(portal, 0)->v);
  374. btMprVec3Cross(&dir, &va, &vb);
  375. btMprVec3Normalize(&dir);
  376. }
  377. else
  378. {
  379. btMprSimplexSetSize(portal, 4);
  380. }
  381. }
  382. return 0;
  383. }
  384. template <typename btConvexTemplate>
  385. static int btRefinePortal(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc,
  386. btMprSimplex_t *portal)
  387. {
  388. btVector3 dir;
  389. btMprSupport_t v4;
  390. for (int i = 0; i < BT_MPR_MAX_ITERATIONS; i++)
  391. //while (1)
  392. {
  393. // compute direction outside the portal (from v0 through v1,v2,v3
  394. // face)
  395. btPortalDir(portal, &dir);
  396. // test if origin is inside the portal
  397. if (portalEncapsulesOrigin(portal, &dir))
  398. return 0;
  399. // get next support point
  400. btMprSupport(a, b, colDesc, dir, &v4);
  401. // test if v4 can expand portal to contain origin and if portal
  402. // expanding doesn't reach given tolerance
  403. if (!portalCanEncapsuleOrigin(portal, &v4, &dir) || portalReachTolerance(portal, &v4, &dir))
  404. {
  405. return -1;
  406. }
  407. // v1-v2-v3 triangle must be rearranged to face outside Minkowski
  408. // difference (direction from v0).
  409. btExpandPortal(portal, &v4);
  410. }
  411. return -1;
  412. }
  413. static void btFindPos(const btMprSimplex_t *portal, btVector3 *pos)
  414. {
  415. btVector3 zero = btVector3(0, 0, 0);
  416. btVector3 *origin = &zero;
  417. btVector3 dir;
  418. size_t i;
  419. float b[4], sum, inv;
  420. btVector3 vec, p1, p2;
  421. btPortalDir(portal, &dir);
  422. // use barycentric coordinates of tetrahedron to find origin
  423. btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
  424. &btMprSimplexPoint(portal, 2)->v);
  425. b[0] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
  426. btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
  427. &btMprSimplexPoint(portal, 2)->v);
  428. b[1] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
  429. btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 0)->v,
  430. &btMprSimplexPoint(portal, 1)->v);
  431. b[2] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 3)->v);
  432. btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
  433. &btMprSimplexPoint(portal, 1)->v);
  434. b[3] = btMprVec3Dot(&vec, &btMprSimplexPoint(portal, 0)->v);
  435. sum = b[0] + b[1] + b[2] + b[3];
  436. if (btMprIsZero(sum) || sum < 0.f)
  437. {
  438. b[0] = 0.f;
  439. btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 2)->v,
  440. &btMprSimplexPoint(portal, 3)->v);
  441. b[1] = btMprVec3Dot(&vec, &dir);
  442. btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 3)->v,
  443. &btMprSimplexPoint(portal, 1)->v);
  444. b[2] = btMprVec3Dot(&vec, &dir);
  445. btMprVec3Cross(&vec, &btMprSimplexPoint(portal, 1)->v,
  446. &btMprSimplexPoint(portal, 2)->v);
  447. b[3] = btMprVec3Dot(&vec, &dir);
  448. sum = b[1] + b[2] + b[3];
  449. }
  450. inv = 1.f / sum;
  451. btMprVec3Copy(&p1, origin);
  452. btMprVec3Copy(&p2, origin);
  453. for (i = 0; i < 4; i++)
  454. {
  455. btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v1);
  456. btMprVec3Scale(&vec, b[i]);
  457. btMprVec3Add(&p1, &vec);
  458. btMprVec3Copy(&vec, &btMprSimplexPoint(portal, i)->v2);
  459. btMprVec3Scale(&vec, b[i]);
  460. btMprVec3Add(&p2, &vec);
  461. }
  462. btMprVec3Scale(&p1, inv);
  463. btMprVec3Scale(&p2, inv);
  464. #ifdef MPR_AVERAGE_CONTACT_POSITIONS
  465. btMprVec3Copy(pos, &p1);
  466. btMprVec3Add(pos, &p2);
  467. btMprVec3Scale(pos, 0.5);
  468. #else
  469. btMprVec3Copy(pos, &p2);
  470. #endif //MPR_AVERAGE_CONTACT_POSITIONS
  471. }
  472. inline float btMprVec3Dist2(const btVector3 *a, const btVector3 *b)
  473. {
  474. btVector3 ab;
  475. btMprVec3Sub2(&ab, a, b);
  476. return btMprVec3Len2(&ab);
  477. }
  478. inline float _btMprVec3PointSegmentDist2(const btVector3 *P,
  479. const btVector3 *x0,
  480. const btVector3 *b,
  481. btVector3 *witness)
  482. {
  483. // The computation comes from solving equation of segment:
  484. // S(t) = x0 + t.d
  485. // where - x0 is initial point of segment
  486. // - d is direction of segment from x0 (|d| > 0)
  487. // - t belongs to <0, 1> interval
  488. //
  489. // Than, distance from a segment to some point P can be expressed:
  490. // D(t) = |x0 + t.d - P|^2
  491. // which is distance from any point on segment. Minimization
  492. // of this function brings distance from P to segment.
  493. // Minimization of D(t) leads to simple quadratic equation that's
  494. // solving is straightforward.
  495. //
  496. // Bonus of this method is witness point for free.
  497. float dist, t;
  498. btVector3 d, a;
  499. // direction of segment
  500. btMprVec3Sub2(&d, b, x0);
  501. // precompute vector from P to x0
  502. btMprVec3Sub2(&a, x0, P);
  503. t = -1.f * btMprVec3Dot(&a, &d);
  504. t /= btMprVec3Len2(&d);
  505. if (t < 0.f || btMprIsZero(t))
  506. {
  507. dist = btMprVec3Dist2(x0, P);
  508. if (witness)
  509. btMprVec3Copy(witness, x0);
  510. }
  511. else if (t > 1.f || btMprEq(t, 1.f))
  512. {
  513. dist = btMprVec3Dist2(b, P);
  514. if (witness)
  515. btMprVec3Copy(witness, b);
  516. }
  517. else
  518. {
  519. if (witness)
  520. {
  521. btMprVec3Copy(witness, &d);
  522. btMprVec3Scale(witness, t);
  523. btMprVec3Add(witness, x0);
  524. dist = btMprVec3Dist2(witness, P);
  525. }
  526. else
  527. {
  528. // recycling variables
  529. btMprVec3Scale(&d, t);
  530. btMprVec3Add(&d, &a);
  531. dist = btMprVec3Len2(&d);
  532. }
  533. }
  534. return dist;
  535. }
  536. inline float btMprVec3PointTriDist2(const btVector3 *P,
  537. const btVector3 *x0, const btVector3 *B,
  538. const btVector3 *C,
  539. btVector3 *witness)
  540. {
  541. // Computation comes from analytic expression for triangle (x0, B, C)
  542. // T(s, t) = x0 + s.d1 + t.d2, where d1 = B - x0 and d2 = C - x0 and
  543. // Then equation for distance is:
  544. // D(s, t) = | T(s, t) - P |^2
  545. // This leads to minimization of quadratic function of two variables.
  546. // The solution from is taken only if s is between 0 and 1, t is
  547. // between 0 and 1 and t + s < 1, otherwise distance from segment is
  548. // computed.
  549. btVector3 d1, d2, a;
  550. float u, v, w, p, q, r;
  551. float s, t, dist, dist2;
  552. btVector3 witness2;
  553. btMprVec3Sub2(&d1, B, x0);
  554. btMprVec3Sub2(&d2, C, x0);
  555. btMprVec3Sub2(&a, x0, P);
  556. u = btMprVec3Dot(&a, &a);
  557. v = btMprVec3Dot(&d1, &d1);
  558. w = btMprVec3Dot(&d2, &d2);
  559. p = btMprVec3Dot(&a, &d1);
  560. q = btMprVec3Dot(&a, &d2);
  561. r = btMprVec3Dot(&d1, &d2);
  562. btScalar div = (w * v - r * r);
  563. if (btMprIsZero(div))
  564. {
  565. s = -1;
  566. }
  567. else
  568. {
  569. s = (q * r - w * p) / div;
  570. t = (-s * r - q) / w;
  571. }
  572. if ((btMprIsZero(s) || s > 0.f) && (btMprEq(s, 1.f) || s < 1.f) && (btMprIsZero(t) || t > 0.f) && (btMprEq(t, 1.f) || t < 1.f) && (btMprEq(t + s, 1.f) || t + s < 1.f))
  573. {
  574. if (witness)
  575. {
  576. btMprVec3Scale(&d1, s);
  577. btMprVec3Scale(&d2, t);
  578. btMprVec3Copy(witness, x0);
  579. btMprVec3Add(witness, &d1);
  580. btMprVec3Add(witness, &d2);
  581. dist = btMprVec3Dist2(witness, P);
  582. }
  583. else
  584. {
  585. dist = s * s * v;
  586. dist += t * t * w;
  587. dist += 2.f * s * t * r;
  588. dist += 2.f * s * p;
  589. dist += 2.f * t * q;
  590. dist += u;
  591. }
  592. }
  593. else
  594. {
  595. dist = _btMprVec3PointSegmentDist2(P, x0, B, witness);
  596. dist2 = _btMprVec3PointSegmentDist2(P, x0, C, &witness2);
  597. if (dist2 < dist)
  598. {
  599. dist = dist2;
  600. if (witness)
  601. btMprVec3Copy(witness, &witness2);
  602. }
  603. dist2 = _btMprVec3PointSegmentDist2(P, B, C, &witness2);
  604. if (dist2 < dist)
  605. {
  606. dist = dist2;
  607. if (witness)
  608. btMprVec3Copy(witness, &witness2);
  609. }
  610. }
  611. return dist;
  612. }
  613. template <typename btConvexTemplate>
  614. static void btFindPenetr(const btConvexTemplate &a, const btConvexTemplate &b,
  615. const btMprCollisionDescription &colDesc,
  616. btMprSimplex_t *portal,
  617. float *depth, btVector3 *pdir, btVector3 *pos)
  618. {
  619. btVector3 dir;
  620. btMprSupport_t v4;
  621. unsigned long iterations;
  622. btVector3 zero = btVector3(0, 0, 0);
  623. btVector3 *origin = &zero;
  624. iterations = 1UL;
  625. for (int i = 0; i < BT_MPR_MAX_ITERATIONS; i++)
  626. //while (1)
  627. {
  628. // compute portal direction and obtain next support point
  629. btPortalDir(portal, &dir);
  630. btMprSupport(a, b, colDesc, dir, &v4);
  631. // reached tolerance -> find penetration info
  632. if (portalReachTolerance(portal, &v4, &dir) || iterations == BT_MPR_MAX_ITERATIONS)
  633. {
  634. *depth = btMprVec3PointTriDist2(origin, &btMprSimplexPoint(portal, 1)->v, &btMprSimplexPoint(portal, 2)->v, &btMprSimplexPoint(portal, 3)->v, pdir);
  635. *depth = BT_MPR_SQRT(*depth);
  636. if (btMprIsZero((*pdir).x()) && btMprIsZero((*pdir).y()) && btMprIsZero((*pdir).z()))
  637. {
  638. *pdir = dir;
  639. }
  640. btMprVec3Normalize(pdir);
  641. // barycentric coordinates:
  642. btFindPos(portal, pos);
  643. return;
  644. }
  645. btExpandPortal(portal, &v4);
  646. iterations++;
  647. }
  648. }
  649. static void btFindPenetrTouch(btMprSimplex_t *portal, float *depth, btVector3 *dir, btVector3 *pos)
  650. {
  651. // Touching contact on portal's v1 - so depth is zero and direction
  652. // is unimportant and pos can be guessed
  653. *depth = 0.f;
  654. btVector3 zero = btVector3(0, 0, 0);
  655. btVector3 *origin = &zero;
  656. btMprVec3Copy(dir, origin);
  657. #ifdef MPR_AVERAGE_CONTACT_POSITIONS
  658. btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
  659. btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
  660. btMprVec3Scale(pos, 0.5);
  661. #else
  662. btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
  663. #endif
  664. }
  665. static void btFindPenetrSegment(btMprSimplex_t *portal,
  666. float *depth, btVector3 *dir, btVector3 *pos)
  667. {
  668. // Origin lies on v0-v1 segment.
  669. // Depth is distance to v1, direction also and position must be
  670. // computed
  671. #ifdef MPR_AVERAGE_CONTACT_POSITIONS
  672. btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v1);
  673. btMprVec3Add(pos, &btMprSimplexPoint(portal, 1)->v2);
  674. btMprVec3Scale(pos, 0.5f);
  675. #else
  676. btMprVec3Copy(pos, &btMprSimplexPoint(portal, 1)->v2);
  677. #endif //MPR_AVERAGE_CONTACT_POSITIONS
  678. btMprVec3Copy(dir, &btMprSimplexPoint(portal, 1)->v);
  679. *depth = BT_MPR_SQRT(btMprVec3Len2(dir));
  680. btMprVec3Normalize(dir);
  681. }
  682. template <typename btConvexTemplate>
  683. inline int btMprPenetration(const btConvexTemplate &a, const btConvexTemplate &b,
  684. const btMprCollisionDescription &colDesc,
  685. float *depthOut, btVector3 *dirOut, btVector3 *posOut)
  686. {
  687. btMprSimplex_t portal;
  688. // Phase 1: Portal discovery
  689. int result = btDiscoverPortal(a, b, colDesc, &portal);
  690. //sepAxis[pairIndex] = *pdir;//or -dir?
  691. switch (result)
  692. {
  693. case 0:
  694. {
  695. // Phase 2: Portal refinement
  696. result = btRefinePortal(a, b, colDesc, &portal);
  697. if (result < 0)
  698. return -1;
  699. // Phase 3. Penetration info
  700. btFindPenetr(a, b, colDesc, &portal, depthOut, dirOut, posOut);
  701. break;
  702. }
  703. case 1:
  704. {
  705. // Touching contact on portal's v1.
  706. btFindPenetrTouch(&portal, depthOut, dirOut, posOut);
  707. result = 0;
  708. break;
  709. }
  710. case 2:
  711. {
  712. btFindPenetrSegment(&portal, depthOut, dirOut, posOut);
  713. result = 0;
  714. break;
  715. }
  716. default:
  717. {
  718. //if (res < 0)
  719. //{
  720. // Origin isn't inside portal - no collision.
  721. result = -1;
  722. //}
  723. }
  724. };
  725. return result;
  726. };
  727. template <typename btConvexTemplate, typename btMprDistanceTemplate>
  728. inline int btComputeMprPenetration(const btConvexTemplate &a, const btConvexTemplate &b, const btMprCollisionDescription &colDesc, btMprDistanceTemplate *distInfo)
  729. {
  730. btVector3 dir, pos;
  731. float depth;
  732. int res = btMprPenetration(a, b, colDesc, &depth, &dir, &pos);
  733. if (res == 0)
  734. {
  735. distInfo->m_distance = -depth;
  736. distInfo->m_pointOnB = pos;
  737. distInfo->m_normalBtoA = -dir;
  738. distInfo->m_pointOnA = pos - distInfo->m_distance * dir;
  739. return 0;
  740. }
  741. return -1;
  742. }
  743. #endif //BT_MPR_PENETRATION_H