b2Distance.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614
  1. /*
  2. * Copyright (c) 2007-2009 Erin Catto http://www.box2d.org
  3. * Copyright (c) 2014 Google, Inc.
  4. *
  5. * This software is provided 'as-is', without any express or implied
  6. * warranty. In no event will the authors be held liable for any damages
  7. * arising from the use of this software.
  8. * Permission is granted to anyone to use this software for any purpose,
  9. * including commercial applications, and to alter it and redistribute it
  10. * freely, subject to the following restrictions:
  11. * 1. The origin of this software must not be misrepresented; you must not
  12. * claim that you wrote the original software. If you use this software
  13. * in a product, an acknowledgment in the product documentation would be
  14. * appreciated but is not required.
  15. * 2. Altered source versions must be plainly marked as such, and must not be
  16. * misrepresented as being the original software.
  17. * 3. This notice may not be removed or altered from any source distribution.
  18. */
  19. #include <string.h>
  20. #include <memory.h>
  21. #include <Box2D/Collision/b2Distance.h>
  22. #include <Box2D/Collision/Shapes/b2CircleShape.h>
  23. #include <Box2D/Collision/Shapes/b2EdgeShape.h>
  24. #include <Box2D/Collision/Shapes/b2ChainShape.h>
  25. #include <Box2D/Collision/Shapes/b2PolygonShape.h>
  26. // GJK using Voronoi regions (Christer Ericson) and Barycentric coordinates.
  27. int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters;
  28. void b2DistanceProxy::Set(const b2Shape* shape, int32 index)
  29. {
  30. switch (shape->GetType())
  31. {
  32. case b2Shape::e_circle:
  33. {
  34. const b2CircleShape* circle = static_cast<const b2CircleShape*>(shape);
  35. m_vertices = &circle->m_p;
  36. m_count = 1;
  37. m_radius = circle->m_radius;
  38. }
  39. break;
  40. case b2Shape::e_polygon:
  41. {
  42. const b2PolygonShape* polygon = static_cast<const b2PolygonShape*>(shape);
  43. m_vertices = polygon->m_vertices;
  44. m_count = polygon->m_count;
  45. m_radius = polygon->m_radius;
  46. }
  47. break;
  48. case b2Shape::e_chain:
  49. {
  50. const b2ChainShape* chain = static_cast<const b2ChainShape*>(shape);
  51. b2Assert(0 <= index && index < chain->m_count);
  52. m_buffer[0] = chain->m_vertices[index];
  53. if (index + 1 < chain->m_count)
  54. {
  55. m_buffer[1] = chain->m_vertices[index + 1];
  56. }
  57. else
  58. {
  59. m_buffer[1] = chain->m_vertices[0];
  60. }
  61. m_vertices = m_buffer;
  62. m_count = 2;
  63. m_radius = chain->m_radius;
  64. }
  65. break;
  66. case b2Shape::e_edge:
  67. {
  68. const b2EdgeShape* edge = static_cast<const b2EdgeShape*>(shape);
  69. m_vertices = &edge->m_vertex1;
  70. m_count = 2;
  71. m_radius = edge->m_radius;
  72. }
  73. break;
  74. default:
  75. b2Assert(false);
  76. }
  77. }
  78. struct b2SimplexVertex
  79. {
  80. b2Vec2 wA; // support point in proxyA
  81. b2Vec2 wB; // support point in proxyB
  82. b2Vec2 w; // wB - wA
  83. float32 a; // barycentric coordinate for closest point
  84. int32 indexA; // wA index
  85. int32 indexB; // wB index
  86. };
  87. struct b2Simplex
  88. {
  89. void ReadCache( const b2SimplexCache* cache,
  90. const b2DistanceProxy* proxyA, const b2Transform& transformA,
  91. const b2DistanceProxy* proxyB, const b2Transform& transformB)
  92. {
  93. b2Assert(cache->count <= 3);
  94. // Copy data from cache.
  95. m_count = cache->count;
  96. b2SimplexVertex* vertices = &m_v1;
  97. for (int32 i = 0; i < m_count; ++i)
  98. {
  99. b2SimplexVertex* v = vertices + i;
  100. v->indexA = cache->indexA[i];
  101. v->indexB = cache->indexB[i];
  102. b2Vec2 wALocal = proxyA->GetVertex(v->indexA);
  103. b2Vec2 wBLocal = proxyB->GetVertex(v->indexB);
  104. v->wA = b2Mul(transformA, wALocal);
  105. v->wB = b2Mul(transformB, wBLocal);
  106. v->w = v->wB - v->wA;
  107. v->a = 0.0f;
  108. }
  109. // Compute the new simplex metric, if it is substantially different than
  110. // old metric then flush the simplex.
  111. if (m_count > 1)
  112. {
  113. float32 metric1 = cache->metric;
  114. float32 metric2 = GetMetric();
  115. if (metric2 < 0.5f * metric1 || 2.0f * metric1 < metric2 || metric2 < b2_epsilon)
  116. {
  117. // Reset the simplex.
  118. m_count = 0;
  119. }
  120. }
  121. // If the cache is empty or invalid ...
  122. if (m_count == 0)
  123. {
  124. b2SimplexVertex* v = vertices + 0;
  125. v->indexA = 0;
  126. v->indexB = 0;
  127. b2Vec2 wALocal = proxyA->GetVertex(0);
  128. b2Vec2 wBLocal = proxyB->GetVertex(0);
  129. v->wA = b2Mul(transformA, wALocal);
  130. v->wB = b2Mul(transformB, wBLocal);
  131. v->w = v->wB - v->wA;
  132. v->a = 1.0f;
  133. m_count = 1;
  134. }
  135. }
  136. void WriteCache(b2SimplexCache* cache) const
  137. {
  138. cache->metric = GetMetric();
  139. cache->count = uint16(m_count);
  140. const b2SimplexVertex* vertices = &m_v1;
  141. for (int32 i = 0; i < m_count; ++i)
  142. {
  143. cache->indexA[i] = uint8(vertices[i].indexA);
  144. cache->indexB[i] = uint8(vertices[i].indexB);
  145. }
  146. }
  147. b2Vec2 GetSearchDirection() const
  148. {
  149. switch (m_count)
  150. {
  151. case 1:
  152. return -m_v1.w;
  153. case 2:
  154. {
  155. b2Vec2 e12 = m_v2.w - m_v1.w;
  156. float32 sgn = b2Cross(e12, -m_v1.w);
  157. if (sgn > 0.0f)
  158. {
  159. // Origin is left of e12.
  160. return b2Cross(1.0f, e12);
  161. }
  162. else
  163. {
  164. // Origin is right of e12.
  165. return b2Cross(e12, 1.0f);
  166. }
  167. }
  168. default:
  169. b2Assert(false);
  170. return b2Vec2_zero;
  171. }
  172. }
  173. b2Vec2 GetClosestPoint() const
  174. {
  175. switch (m_count)
  176. {
  177. case 0:
  178. b2Assert(false);
  179. return b2Vec2_zero;
  180. case 1:
  181. return m_v1.w;
  182. case 2:
  183. return m_v1.a * m_v1.w + m_v2.a * m_v2.w;
  184. case 3:
  185. return b2Vec2_zero;
  186. default:
  187. b2Assert(false);
  188. return b2Vec2_zero;
  189. }
  190. }
  191. void GetWitnessPoints(b2Vec2* pA, b2Vec2* pB) const
  192. {
  193. switch (m_count)
  194. {
  195. case 0:
  196. b2Assert(false);
  197. break;
  198. case 1:
  199. *pA = m_v1.wA;
  200. *pB = m_v1.wB;
  201. break;
  202. case 2:
  203. *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA;
  204. *pB = m_v1.a * m_v1.wB + m_v2.a * m_v2.wB;
  205. break;
  206. case 3:
  207. *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA + m_v3.a * m_v3.wA;
  208. *pB = *pA;
  209. break;
  210. default:
  211. b2Assert(false);
  212. break;
  213. }
  214. }
  215. float32 GetMetric() const
  216. {
  217. switch (m_count)
  218. {
  219. case 0:
  220. b2Assert(false);
  221. return 0.0f;
  222. case 1:
  223. return 0.0f;
  224. case 2:
  225. return b2Distance(m_v1.w, m_v2.w);
  226. case 3:
  227. return b2Cross(m_v2.w - m_v1.w, m_v3.w - m_v1.w);
  228. default:
  229. b2Assert(false);
  230. return 0.0f;
  231. }
  232. }
  233. void Solve2();
  234. void Solve3();
  235. b2SimplexVertex m_v1, m_v2, m_v3;
  236. int32 m_count;
  237. };
  238. // Solve a line segment using barycentric coordinates.
  239. //
  240. // p = a1 * w1 + a2 * w2
  241. // a1 + a2 = 1
  242. //
  243. // The vector from the origin to the closest point on the line is
  244. // perpendicular to the line.
  245. // e12 = w2 - w1
  246. // dot(p, e) = 0
  247. // a1 * dot(w1, e) + a2 * dot(w2, e) = 0
  248. //
  249. // 2-by-2 linear system
  250. // [1 1 ][a1] = [1]
  251. // [w1.e12 w2.e12][a2] = [0]
  252. //
  253. // Define
  254. // d12_1 = dot(w2, e12)
  255. // d12_2 = -dot(w1, e12)
  256. // d12 = d12_1 + d12_2
  257. //
  258. // Solution
  259. // a1 = d12_1 / d12
  260. // a2 = d12_2 / d12
  261. void b2Simplex::Solve2()
  262. {
  263. b2Vec2 w1 = m_v1.w;
  264. b2Vec2 w2 = m_v2.w;
  265. b2Vec2 e12 = w2 - w1;
  266. // w1 region
  267. float32 d12_2 = -b2Dot(w1, e12);
  268. if (d12_2 <= 0.0f)
  269. {
  270. // a2 <= 0, so we clamp it to 0
  271. m_v1.a = 1.0f;
  272. m_count = 1;
  273. return;
  274. }
  275. // w2 region
  276. float32 d12_1 = b2Dot(w2, e12);
  277. if (d12_1 <= 0.0f)
  278. {
  279. // a1 <= 0, so we clamp it to 0
  280. m_v2.a = 1.0f;
  281. m_count = 1;
  282. m_v1 = m_v2;
  283. return;
  284. }
  285. // Must be in e12 region.
  286. float32 inv_d12 = 1.0f / (d12_1 + d12_2);
  287. m_v1.a = d12_1 * inv_d12;
  288. m_v2.a = d12_2 * inv_d12;
  289. m_count = 2;
  290. }
  291. // Possible regions:
  292. // - points[2]
  293. // - edge points[0]-points[2]
  294. // - edge points[1]-points[2]
  295. // - inside the triangle
  296. void b2Simplex::Solve3()
  297. {
  298. b2Vec2 w1 = m_v1.w;
  299. b2Vec2 w2 = m_v2.w;
  300. b2Vec2 w3 = m_v3.w;
  301. // Edge12
  302. // [1 1 ][a1] = [1]
  303. // [w1.e12 w2.e12][a2] = [0]
  304. // a3 = 0
  305. b2Vec2 e12 = w2 - w1;
  306. float32 w1e12 = b2Dot(w1, e12);
  307. float32 w2e12 = b2Dot(w2, e12);
  308. float32 d12_1 = w2e12;
  309. float32 d12_2 = -w1e12;
  310. // Edge13
  311. // [1 1 ][a1] = [1]
  312. // [w1.e13 w3.e13][a3] = [0]
  313. // a2 = 0
  314. b2Vec2 e13 = w3 - w1;
  315. float32 w1e13 = b2Dot(w1, e13);
  316. float32 w3e13 = b2Dot(w3, e13);
  317. float32 d13_1 = w3e13;
  318. float32 d13_2 = -w1e13;
  319. // Edge23
  320. // [1 1 ][a2] = [1]
  321. // [w2.e23 w3.e23][a3] = [0]
  322. // a1 = 0
  323. b2Vec2 e23 = w3 - w2;
  324. float32 w2e23 = b2Dot(w2, e23);
  325. float32 w3e23 = b2Dot(w3, e23);
  326. float32 d23_1 = w3e23;
  327. float32 d23_2 = -w2e23;
  328. // Triangle123
  329. float32 n123 = b2Cross(e12, e13);
  330. float32 d123_1 = n123 * b2Cross(w2, w3);
  331. float32 d123_2 = n123 * b2Cross(w3, w1);
  332. float32 d123_3 = n123 * b2Cross(w1, w2);
  333. // w1 region
  334. if (d12_2 <= 0.0f && d13_2 <= 0.0f)
  335. {
  336. m_v1.a = 1.0f;
  337. m_count = 1;
  338. return;
  339. }
  340. // e12
  341. if (d12_1 > 0.0f && d12_2 > 0.0f && d123_3 <= 0.0f)
  342. {
  343. float32 inv_d12 = 1.0f / (d12_1 + d12_2);
  344. m_v1.a = d12_1 * inv_d12;
  345. m_v2.a = d12_2 * inv_d12;
  346. m_count = 2;
  347. return;
  348. }
  349. // e13
  350. if (d13_1 > 0.0f && d13_2 > 0.0f && d123_2 <= 0.0f)
  351. {
  352. float32 inv_d13 = 1.0f / (d13_1 + d13_2);
  353. m_v1.a = d13_1 * inv_d13;
  354. m_v3.a = d13_2 * inv_d13;
  355. m_count = 2;
  356. m_v2 = m_v3;
  357. return;
  358. }
  359. // w2 region
  360. if (d12_1 <= 0.0f && d23_2 <= 0.0f)
  361. {
  362. m_v2.a = 1.0f;
  363. m_count = 1;
  364. m_v1 = m_v2;
  365. return;
  366. }
  367. // w3 region
  368. if (d13_1 <= 0.0f && d23_1 <= 0.0f)
  369. {
  370. m_v3.a = 1.0f;
  371. m_count = 1;
  372. m_v1 = m_v3;
  373. return;
  374. }
  375. // e23
  376. if (d23_1 > 0.0f && d23_2 > 0.0f && d123_1 <= 0.0f)
  377. {
  378. float32 inv_d23 = 1.0f / (d23_1 + d23_2);
  379. m_v2.a = d23_1 * inv_d23;
  380. m_v3.a = d23_2 * inv_d23;
  381. m_count = 2;
  382. m_v1 = m_v3;
  383. return;
  384. }
  385. // Must be in triangle123
  386. float32 inv_d123 = 1.0f / (d123_1 + d123_2 + d123_3);
  387. m_v1.a = d123_1 * inv_d123;
  388. m_v2.a = d123_2 * inv_d123;
  389. m_v3.a = d123_3 * inv_d123;
  390. m_count = 3;
  391. }
  392. void b2Distance(b2DistanceOutput* output,
  393. b2SimplexCache* cache,
  394. const b2DistanceInput* input)
  395. {
  396. ++b2_gjkCalls;
  397. const b2DistanceProxy* proxyA = &input->proxyA;
  398. const b2DistanceProxy* proxyB = &input->proxyB;
  399. b2Transform transformA = input->transformA;
  400. b2Transform transformB = input->transformB;
  401. // Initialize the simplex.
  402. b2Simplex simplex;
  403. simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB);
  404. // Get simplex vertices as an array.
  405. b2SimplexVertex* vertices = &simplex.m_v1;
  406. const int32 k_maxIters = 20;
  407. // These store the vertices of the last simplex so that we
  408. // can check for duplicates and prevent cycling.
  409. int32 saveA[3], saveB[3];
  410. int32 saveCount = 0;
  411. // Work around spurious gcc-4.8.2 warnings when -Wmaybe-uninitialized is
  412. // enabled by initializing saveA / saveB arrays when they're referenced
  413. // at the end of the main iteration loop below even though saveCount
  414. // entries of each array are initialized at the start of the main
  415. // iteration loop.
  416. memset(saveA, 0, sizeof(saveA));
  417. memset(saveB, 0, sizeof(saveB));
  418. float32 distanceSqr1 = b2_maxFloat;
  419. float32 distanceSqr2;
  420. // Main iteration loop.
  421. int32 iter = 0;
  422. while (iter < k_maxIters)
  423. {
  424. // Copy simplex so we can identify duplicates.
  425. saveCount = simplex.m_count;
  426. for (int32 i = 0; i < saveCount; ++i)
  427. {
  428. saveA[i] = vertices[i].indexA;
  429. saveB[i] = vertices[i].indexB;
  430. }
  431. switch (simplex.m_count)
  432. {
  433. case 1:
  434. break;
  435. case 2:
  436. simplex.Solve2();
  437. break;
  438. case 3:
  439. simplex.Solve3();
  440. break;
  441. default:
  442. b2Assert(false);
  443. }
  444. // If we have 3 points, then the origin is in the corresponding triangle.
  445. if (simplex.m_count == 3)
  446. {
  447. break;
  448. }
  449. // Compute closest point.
  450. b2Vec2 p = simplex.GetClosestPoint();
  451. distanceSqr2 = p.LengthSquared();
  452. // Ensure progress
  453. if (distanceSqr2 >= distanceSqr1)
  454. {
  455. //break;
  456. }
  457. distanceSqr1 = distanceSqr2;
  458. // Get search direction.
  459. b2Vec2 d = simplex.GetSearchDirection();
  460. // Ensure the search direction is numerically fit.
  461. if (d.LengthSquared() < b2_epsilon * b2_epsilon)
  462. {
  463. // The origin is probably contained by a line segment
  464. // or triangle. Thus the shapes are overlapped.
  465. // We can't return zero here even though there may be overlap.
  466. // In case the simplex is a point, segment, or triangle it is difficult
  467. // to determine if the origin is contained in the CSO or very close to it.
  468. break;
  469. }
  470. // Compute a tentative new simplex vertex using support points.
  471. b2SimplexVertex* vertex = vertices + simplex.m_count;
  472. vertex->indexA = proxyA->GetSupport(b2MulT(transformA.q, -d));
  473. vertex->wA = b2Mul(transformA, proxyA->GetVertex(vertex->indexA));
  474. b2Vec2 wBLocal;
  475. vertex->indexB = proxyB->GetSupport(b2MulT(transformB.q, d));
  476. vertex->wB = b2Mul(transformB, proxyB->GetVertex(vertex->indexB));
  477. vertex->w = vertex->wB - vertex->wA;
  478. // Iteration count is equated to the number of support point calls.
  479. ++iter;
  480. ++b2_gjkIters;
  481. // Check for duplicate support points. This is the main termination criteria.
  482. bool duplicate = false;
  483. for (int32 i = 0; i < saveCount; ++i)
  484. {
  485. if (vertex->indexA == saveA[i] && vertex->indexB == saveB[i])
  486. {
  487. duplicate = true;
  488. break;
  489. }
  490. }
  491. // If we found a duplicate support point we must exit to avoid cycling.
  492. if (duplicate)
  493. {
  494. break;
  495. }
  496. // New vertex is ok and needed.
  497. ++simplex.m_count;
  498. }
  499. b2_gjkMaxIters = b2Max(b2_gjkMaxIters, iter);
  500. // Prepare output.
  501. simplex.GetWitnessPoints(&output->pointA, &output->pointB);
  502. output->distance = b2Distance(output->pointA, output->pointB);
  503. output->iterations = iter;
  504. // Cache the simplex.
  505. simplex.WriteCache(cache);
  506. // Apply radii if requested.
  507. if (input->useRadii)
  508. {
  509. float32 rA = proxyA->m_radius;
  510. float32 rB = proxyB->m_radius;
  511. if (output->distance > rA + rB && output->distance > b2_epsilon)
  512. {
  513. // Shapes are still no overlapped.
  514. // Move the witness points to the outer surface.
  515. output->distance -= rA + rB;
  516. b2Vec2 normal = output->pointB - output->pointA;
  517. normal.Normalize();
  518. output->pointA += rA * normal;
  519. output->pointB -= rB * normal;
  520. }
  521. else
  522. {
  523. // Shapes are overlapped when radii are considered.
  524. // Move the witness points to the middle.
  525. b2Vec2 p = 0.5f * (output->pointA + output->pointB);
  526. output->pointA = p;
  527. output->pointB = p;
  528. output->distance = 0.0f;
  529. }
  530. }
  531. }