b2Distance.cpp 13 KB

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