Distance.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780
  1. /*
  2. * Farseer Physics Engine based on Box2D.XNA port:
  3. * Copyright (c) 2010 Ian Qvist
  4. *
  5. * Box2D.XNA port of Box2D:
  6. * Copyright (c) 2009 Brandon Furtwangler, Nathan Furtwangler
  7. *
  8. * Original source Box2D:
  9. * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
  10. *
  11. * This software is provided 'as-is', without any express or implied
  12. * warranty. In no event will the authors be held liable for any damages
  13. * arising from the use of this software.
  14. * Permission is granted to anyone to use this software for any purpose,
  15. * including commercial applications, and to alter it and redistribute it
  16. * freely, subject to the following restrictions:
  17. * 1. The origin of this software must not be misrepresented; you must not
  18. * claim that you wrote the original software. If you use this software
  19. * in a product, an acknowledgment in the product documentation would be
  20. * appreciated but is not required.
  21. * 2. Altered source versions must be plainly marked as such, and must not be
  22. * misrepresented as being the original software.
  23. * 3. This notice may not be removed or altered from any source distribution.
  24. */
  25. using System;
  26. using System.Diagnostics;
  27. using FarseerPhysics.Collision.Shapes;
  28. using FarseerPhysics.Common;
  29. using Microsoft.Xna.Framework;
  30. namespace FarseerPhysics.Collision
  31. {
  32. /// <summary>
  33. /// A distance proxy is used by the GJK algorithm.
  34. /// It encapsulates any shape.
  35. /// </summary>
  36. public class DistanceProxy
  37. {
  38. internal float Radius;
  39. internal Vertices Vertices = new Vertices();
  40. /// <summary>
  41. /// Initialize the proxy using the given shape. The shape
  42. /// must remain in scope while the proxy is in use.
  43. /// </summary>
  44. /// <param name="shape">The shape.</param>
  45. /// <param name="index">The index.</param>
  46. public void Set(Shape shape, int index)
  47. {
  48. switch (shape.ShapeType)
  49. {
  50. case ShapeType.Circle:
  51. {
  52. CircleShape circle = (CircleShape)shape;
  53. Vertices.Clear();
  54. Vertices.Add(circle.Position);
  55. Radius = circle.Radius;
  56. }
  57. break;
  58. case ShapeType.Polygon:
  59. {
  60. PolygonShape polygon = (PolygonShape)shape;
  61. Vertices.Clear();
  62. for (int i = 0; i < polygon.Vertices.Count; i++)
  63. {
  64. Vertices.Add(polygon.Vertices[i]);
  65. }
  66. Radius = polygon.Radius;
  67. }
  68. break;
  69. case ShapeType.Loop:
  70. {
  71. LoopShape loop = (LoopShape)shape;
  72. Debug.Assert(0 <= index && index < loop.Vertices.Count);
  73. Vertices.Clear();
  74. Vertices.Add(loop.Vertices[index]);
  75. Vertices.Add(index + 1 < loop.Vertices.Count ? loop.Vertices[index + 1] : loop.Vertices[0]);
  76. Radius = loop.Radius;
  77. }
  78. break;
  79. case ShapeType.Edge:
  80. {
  81. EdgeShape edge = (EdgeShape)shape;
  82. Vertices.Clear();
  83. Vertices.Add(edge.Vertex1);
  84. Vertices.Add(edge.Vertex2);
  85. Radius = edge.Radius;
  86. }
  87. break;
  88. default:
  89. Debug.Assert(false);
  90. break;
  91. }
  92. }
  93. /// <summary>
  94. /// Get the supporting vertex index in the given direction.
  95. /// </summary>
  96. /// <param name="direction">The direction.</param>
  97. /// <returns></returns>
  98. public int GetSupport(Vector2 direction)
  99. {
  100. int bestIndex = 0;
  101. float bestValue = Vector2.Dot(Vertices[0], direction);
  102. for (int i = 1; i < Vertices.Count; ++i)
  103. {
  104. float value = Vector2.Dot(Vertices[i], direction);
  105. if (value > bestValue)
  106. {
  107. bestIndex = i;
  108. bestValue = value;
  109. }
  110. }
  111. return bestIndex;
  112. }
  113. /// <summary>
  114. /// Get the supporting vertex in the given direction.
  115. /// </summary>
  116. /// <param name="direction">The direction.</param>
  117. /// <returns></returns>
  118. public Vector2 GetSupportVertex(Vector2 direction)
  119. {
  120. int bestIndex = 0;
  121. float bestValue = Vector2.Dot(Vertices[0], direction);
  122. for (int i = 1; i < Vertices.Count; ++i)
  123. {
  124. float value = Vector2.Dot(Vertices[i], direction);
  125. if (value > bestValue)
  126. {
  127. bestIndex = i;
  128. bestValue = value;
  129. }
  130. }
  131. return Vertices[bestIndex];
  132. }
  133. }
  134. /// <summary>
  135. /// Used to warm start ComputeDistance.
  136. /// Set count to zero on first call.
  137. /// </summary>
  138. public struct SimplexCache
  139. {
  140. /// <summary>
  141. /// Length or area
  142. /// </summary>
  143. public ushort Count;
  144. /// <summary>
  145. /// Vertices on shape A
  146. /// </summary>
  147. public FixedArray3<byte> IndexA;
  148. /// <summary>
  149. /// Vertices on shape B
  150. /// </summary>
  151. public FixedArray3<byte> IndexB;
  152. public float Metric;
  153. }
  154. /// <summary>
  155. /// Input for ComputeDistance.
  156. /// You have to option to use the shape radii
  157. /// in the computation.
  158. /// </summary>
  159. public class DistanceInput
  160. {
  161. public DistanceProxy ProxyA = new DistanceProxy();
  162. public DistanceProxy ProxyB = new DistanceProxy();
  163. public Transform TransformA;
  164. public Transform TransformB;
  165. public bool UseRadii;
  166. }
  167. /// <summary>
  168. /// Output for ComputeDistance.
  169. /// </summary>
  170. public struct DistanceOutput
  171. {
  172. public float Distance;
  173. /// <summary>
  174. /// Number of GJK iterations used
  175. /// </summary>
  176. public int Iterations;
  177. /// <summary>
  178. /// Closest point on shapeA
  179. /// </summary>
  180. public Vector2 PointA;
  181. /// <summary>
  182. /// Closest point on shapeB
  183. /// </summary>
  184. public Vector2 PointB;
  185. }
  186. internal struct SimplexVertex
  187. {
  188. /// <summary>
  189. /// Barycentric coordinate for closest point
  190. /// </summary>
  191. public float A;
  192. /// <summary>
  193. /// wA index
  194. /// </summary>
  195. public int IndexA;
  196. /// <summary>
  197. /// wB index
  198. /// </summary>
  199. public int IndexB;
  200. /// <summary>
  201. /// wB - wA
  202. /// </summary>
  203. public Vector2 W;
  204. /// <summary>
  205. /// Support point in proxyA
  206. /// </summary>
  207. public Vector2 WA;
  208. /// <summary>
  209. /// Support point in proxyB
  210. /// </summary>
  211. public Vector2 WB;
  212. }
  213. internal struct Simplex
  214. {
  215. internal int Count;
  216. internal FixedArray3<SimplexVertex> V;
  217. internal void ReadCache(ref SimplexCache cache,
  218. DistanceProxy proxyA, ref Transform transformA,
  219. DistanceProxy proxyB, ref Transform transformB)
  220. {
  221. Debug.Assert(cache.Count <= 3);
  222. // Copy data from cache.
  223. Count = cache.Count;
  224. for (int i = 0; i < Count; ++i)
  225. {
  226. SimplexVertex v = V[i];
  227. v.IndexA = cache.IndexA[i];
  228. v.IndexB = cache.IndexB[i];
  229. Vector2 wALocal = proxyA.Vertices[v.IndexA];
  230. Vector2 wBLocal = proxyB.Vertices[v.IndexB];
  231. v.WA = MathUtils.Multiply(ref transformA, wALocal);
  232. v.WB = MathUtils.Multiply(ref transformB, wBLocal);
  233. v.W = v.WB - v.WA;
  234. v.A = 0.0f;
  235. V[i] = v;
  236. }
  237. // Compute the new simplex metric, if it is substantially different than
  238. // old metric then flush the simplex.
  239. if (Count > 1)
  240. {
  241. float metric1 = cache.Metric;
  242. float metric2 = GetMetric();
  243. if (metric2 < 0.5f * metric1 || 2.0f * metric1 < metric2 || metric2 < Settings.Epsilon)
  244. {
  245. // Reset the simplex.
  246. Count = 0;
  247. }
  248. }
  249. // If the cache is empty or invalid ...
  250. if (Count == 0)
  251. {
  252. SimplexVertex v = V[0];
  253. v.IndexA = 0;
  254. v.IndexB = 0;
  255. Vector2 wALocal = proxyA.Vertices[0];
  256. Vector2 wBLocal = proxyB.Vertices[0];
  257. v.WA = MathUtils.Multiply(ref transformA, wALocal);
  258. v.WB = MathUtils.Multiply(ref transformB, wBLocal);
  259. v.W = v.WB - v.WA;
  260. V[0] = v;
  261. Count = 1;
  262. }
  263. }
  264. internal void WriteCache(ref SimplexCache cache)
  265. {
  266. cache.Metric = GetMetric();
  267. cache.Count = (UInt16)Count;
  268. for (int i = 0; i < Count; ++i)
  269. {
  270. cache.IndexA[i] = (byte)(V[i].IndexA);
  271. cache.IndexB[i] = (byte)(V[i].IndexB);
  272. }
  273. }
  274. internal Vector2 GetSearchDirection()
  275. {
  276. switch (Count)
  277. {
  278. case 1:
  279. return -V[0].W;
  280. case 2:
  281. {
  282. Vector2 e12 = V[1].W - V[0].W;
  283. float sgn = MathUtils.Cross(e12, -V[0].W);
  284. if (sgn > 0.0f)
  285. {
  286. // Origin is left of e12.
  287. return new Vector2(-e12.Y, e12.X);
  288. }
  289. else
  290. {
  291. // Origin is right of e12.
  292. return new Vector2(e12.Y, -e12.X);
  293. }
  294. }
  295. default:
  296. Debug.Assert(false);
  297. return Vector2.Zero;
  298. }
  299. }
  300. internal Vector2 GetClosestPoint()
  301. {
  302. switch (Count)
  303. {
  304. case 0:
  305. Debug.Assert(false);
  306. return Vector2.Zero;
  307. case 1:
  308. return V[0].W;
  309. case 2:
  310. return V[0].A * V[0].W + V[1].A * V[1].W;
  311. case 3:
  312. return Vector2.Zero;
  313. default:
  314. Debug.Assert(false);
  315. return Vector2.Zero;
  316. }
  317. }
  318. internal void GetWitnessPoints(out Vector2 pA, out Vector2 pB)
  319. {
  320. switch (Count)
  321. {
  322. case 0:
  323. pA = Vector2.Zero;
  324. pB = Vector2.Zero;
  325. Debug.Assert(false);
  326. break;
  327. case 1:
  328. pA = V[0].WA;
  329. pB = V[0].WB;
  330. break;
  331. case 2:
  332. pA = V[0].A * V[0].WA + V[1].A * V[1].WA;
  333. pB = V[0].A * V[0].WB + V[1].A * V[1].WB;
  334. break;
  335. case 3:
  336. pA = V[0].A * V[0].WA + V[1].A * V[1].WA + V[2].A * V[2].WA;
  337. pB = pA;
  338. break;
  339. default:
  340. throw new Exception();
  341. }
  342. }
  343. internal float GetMetric()
  344. {
  345. switch (Count)
  346. {
  347. case 0:
  348. Debug.Assert(false);
  349. return 0.0f;
  350. case 1:
  351. return 0.0f;
  352. case 2:
  353. return (V[0].W - V[1].W).Length();
  354. case 3:
  355. return MathUtils.Cross(V[1].W - V[0].W, V[2].W - V[0].W);
  356. default:
  357. Debug.Assert(false);
  358. return 0.0f;
  359. }
  360. }
  361. // Solve a line segment using barycentric coordinates.
  362. //
  363. // p = a1 * w1 + a2 * w2
  364. // a1 + a2 = 1
  365. //
  366. // The vector from the origin to the closest point on the line is
  367. // perpendicular to the line.
  368. // e12 = w2 - w1
  369. // dot(p, e) = 0
  370. // a1 * dot(w1, e) + a2 * dot(w2, e) = 0
  371. //
  372. // 2-by-2 linear system
  373. // [1 1 ][a1] = [1]
  374. // [w1.e12 w2.e12][a2] = [0]
  375. //
  376. // Define
  377. // d12_1 = dot(w2, e12)
  378. // d12_2 = -dot(w1, e12)
  379. // d12 = d12_1 + d12_2
  380. //
  381. // Solution
  382. // a1 = d12_1 / d12
  383. // a2 = d12_2 / d12
  384. internal void Solve2()
  385. {
  386. Vector2 w1 = V[0].W;
  387. Vector2 w2 = V[1].W;
  388. Vector2 e12 = w2 - w1;
  389. // w1 region
  390. float d12_2 = -Vector2.Dot(w1, e12);
  391. if (d12_2 <= 0.0f)
  392. {
  393. // a2 <= 0, so we clamp it to 0
  394. SimplexVertex v0 = V[0];
  395. v0.A = 1.0f;
  396. V[0] = v0;
  397. Count = 1;
  398. return;
  399. }
  400. // w2 region
  401. float d12_1 = Vector2.Dot(w2, e12);
  402. if (d12_1 <= 0.0f)
  403. {
  404. // a1 <= 0, so we clamp it to 0
  405. SimplexVertex v1 = V[1];
  406. v1.A = 1.0f;
  407. V[1] = v1;
  408. Count = 1;
  409. V[0] = V[1];
  410. return;
  411. }
  412. // Must be in e12 region.
  413. float inv_d12 = 1.0f / (d12_1 + d12_2);
  414. SimplexVertex v0_2 = V[0];
  415. SimplexVertex v1_2 = V[1];
  416. v0_2.A = d12_1 * inv_d12;
  417. v1_2.A = d12_2 * inv_d12;
  418. V[0] = v0_2;
  419. V[1] = v1_2;
  420. Count = 2;
  421. }
  422. // Possible regions:
  423. // - points[2]
  424. // - edge points[0]-points[2]
  425. // - edge points[1]-points[2]
  426. // - inside the triangle
  427. internal void Solve3()
  428. {
  429. Vector2 w1 = V[0].W;
  430. Vector2 w2 = V[1].W;
  431. Vector2 w3 = V[2].W;
  432. // Edge12
  433. // [1 1 ][a1] = [1]
  434. // [w1.e12 w2.e12][a2] = [0]
  435. // a3 = 0
  436. Vector2 e12 = w2 - w1;
  437. float w1e12 = Vector2.Dot(w1, e12);
  438. float w2e12 = Vector2.Dot(w2, e12);
  439. float d12_1 = w2e12;
  440. float d12_2 = -w1e12;
  441. // Edge13
  442. // [1 1 ][a1] = [1]
  443. // [w1.e13 w3.e13][a3] = [0]
  444. // a2 = 0
  445. Vector2 e13 = w3 - w1;
  446. float w1e13 = Vector2.Dot(w1, e13);
  447. float w3e13 = Vector2.Dot(w3, e13);
  448. float d13_1 = w3e13;
  449. float d13_2 = -w1e13;
  450. // Edge23
  451. // [1 1 ][a2] = [1]
  452. // [w2.e23 w3.e23][a3] = [0]
  453. // a1 = 0
  454. Vector2 e23 = w3 - w2;
  455. float w2e23 = Vector2.Dot(w2, e23);
  456. float w3e23 = Vector2.Dot(w3, e23);
  457. float d23_1 = w3e23;
  458. float d23_2 = -w2e23;
  459. // Triangle123
  460. float n123 = MathUtils.Cross(e12, e13);
  461. float d123_1 = n123 * MathUtils.Cross(w2, w3);
  462. float d123_2 = n123 * MathUtils.Cross(w3, w1);
  463. float d123_3 = n123 * MathUtils.Cross(w1, w2);
  464. // w1 region
  465. if (d12_2 <= 0.0f && d13_2 <= 0.0f)
  466. {
  467. SimplexVertex v0_1 = V[0];
  468. v0_1.A = 1.0f;
  469. V[0] = v0_1;
  470. Count = 1;
  471. return;
  472. }
  473. // e12
  474. if (d12_1 > 0.0f && d12_2 > 0.0f && d123_3 <= 0.0f)
  475. {
  476. float inv_d12 = 1.0f / (d12_1 + d12_2);
  477. SimplexVertex v0_2 = V[0];
  478. SimplexVertex v1_2 = V[1];
  479. v0_2.A = d12_1 * inv_d12;
  480. v1_2.A = d12_2 * inv_d12;
  481. V[0] = v0_2;
  482. V[1] = v1_2;
  483. Count = 2;
  484. return;
  485. }
  486. // e13
  487. if (d13_1 > 0.0f && d13_2 > 0.0f && d123_2 <= 0.0f)
  488. {
  489. float inv_d13 = 1.0f / (d13_1 + d13_2);
  490. SimplexVertex v0_3 = V[0];
  491. SimplexVertex v2_3 = V[2];
  492. v0_3.A = d13_1 * inv_d13;
  493. v2_3.A = d13_2 * inv_d13;
  494. V[0] = v0_3;
  495. V[2] = v2_3;
  496. Count = 2;
  497. V[1] = V[2];
  498. return;
  499. }
  500. // w2 region
  501. if (d12_1 <= 0.0f && d23_2 <= 0.0f)
  502. {
  503. SimplexVertex v1_4 = V[1];
  504. v1_4.A = 1.0f;
  505. V[1] = v1_4;
  506. Count = 1;
  507. V[0] = V[1];
  508. return;
  509. }
  510. // w3 region
  511. if (d13_1 <= 0.0f && d23_1 <= 0.0f)
  512. {
  513. SimplexVertex v2_5 = V[2];
  514. v2_5.A = 1.0f;
  515. V[2] = v2_5;
  516. Count = 1;
  517. V[0] = V[2];
  518. return;
  519. }
  520. // e23
  521. if (d23_1 > 0.0f && d23_2 > 0.0f && d123_1 <= 0.0f)
  522. {
  523. float inv_d23 = 1.0f / (d23_1 + d23_2);
  524. SimplexVertex v1_6 = V[1];
  525. SimplexVertex v2_6 = V[2];
  526. v1_6.A = d23_1 * inv_d23;
  527. v2_6.A = d23_2 * inv_d23;
  528. V[1] = v1_6;
  529. V[2] = v2_6;
  530. Count = 2;
  531. V[0] = V[2];
  532. return;
  533. }
  534. // Must be in triangle123
  535. float inv_d123 = 1.0f / (d123_1 + d123_2 + d123_3);
  536. SimplexVertex v0_7 = V[0];
  537. SimplexVertex v1_7 = V[1];
  538. SimplexVertex v2_7 = V[2];
  539. v0_7.A = d123_1 * inv_d123;
  540. v1_7.A = d123_2 * inv_d123;
  541. v2_7.A = d123_3 * inv_d123;
  542. V[0] = v0_7;
  543. V[1] = v1_7;
  544. V[2] = v2_7;
  545. Count = 3;
  546. }
  547. }
  548. public static class Distance
  549. {
  550. public static int GJKCalls, GJKIters, GJKMaxIters;
  551. public static void ComputeDistance(out DistanceOutput output,
  552. out SimplexCache cache,
  553. DistanceInput input)
  554. {
  555. cache = new SimplexCache();
  556. ++GJKCalls;
  557. // Initialize the simplex.
  558. Simplex simplex = new Simplex();
  559. simplex.ReadCache(ref cache, input.ProxyA, ref input.TransformA, input.ProxyB, ref input.TransformB);
  560. // Get simplex vertices as an array.
  561. const int k_maxIters = 20;
  562. // These store the vertices of the last simplex so that we
  563. // can check for duplicates and prevent cycling.
  564. FixedArray3<int> saveA = new FixedArray3<int>();
  565. FixedArray3<int> saveB = new FixedArray3<int>();
  566. Vector2 closestPoint = simplex.GetClosestPoint();
  567. float distanceSqr1 = closestPoint.LengthSquared();
  568. float distanceSqr2 = distanceSqr1;
  569. // Main iteration loop.
  570. int iter = 0;
  571. while (iter < k_maxIters)
  572. {
  573. // Copy simplex so we can identify duplicates.
  574. int saveCount = simplex.Count;
  575. for (int i = 0; i < saveCount; ++i)
  576. {
  577. saveA[i] = simplex.V[i].IndexA;
  578. saveB[i] = simplex.V[i].IndexB;
  579. }
  580. switch (simplex.Count)
  581. {
  582. case 1:
  583. break;
  584. case 2:
  585. simplex.Solve2();
  586. break;
  587. case 3:
  588. simplex.Solve3();
  589. break;
  590. default:
  591. Debug.Assert(false);
  592. break;
  593. }
  594. // If we have 3 points, then the origin is in the corresponding triangle.
  595. if (simplex.Count == 3)
  596. {
  597. break;
  598. }
  599. // Compute closest point.
  600. Vector2 p = simplex.GetClosestPoint();
  601. distanceSqr2 = p.LengthSquared();
  602. // Ensure progress
  603. if (distanceSqr2 >= distanceSqr1)
  604. {
  605. //break;
  606. }
  607. distanceSqr1 = distanceSqr2;
  608. // Get search direction.
  609. Vector2 d = simplex.GetSearchDirection();
  610. // Ensure the search direction is numerically fit.
  611. if (d.LengthSquared() < Settings.Epsilon * Settings.Epsilon)
  612. {
  613. // The origin is probably contained by a line segment
  614. // or triangle. Thus the shapes are overlapped.
  615. // We can't return zero here even though there may be overlap.
  616. // In case the simplex is a point, segment, or triangle it is difficult
  617. // to determine if the origin is contained in the CSO or very close to it.
  618. break;
  619. }
  620. // Compute a tentative new simplex vertex using support points.
  621. SimplexVertex vertex = simplex.V[simplex.Count];
  622. vertex.IndexA = input.ProxyA.GetSupport(MathUtils.MultiplyT(ref input.TransformA.R, -d));
  623. vertex.WA = MathUtils.Multiply(ref input.TransformA, input.ProxyA.Vertices[vertex.IndexA]);
  624. vertex.IndexB = input.ProxyB.GetSupport(MathUtils.MultiplyT(ref input.TransformB.R, d));
  625. vertex.WB = MathUtils.Multiply(ref input.TransformB, input.ProxyB.Vertices[vertex.IndexB]);
  626. vertex.W = vertex.WB - vertex.WA;
  627. simplex.V[simplex.Count] = vertex;
  628. // Iteration count is equated to the number of support point calls.
  629. ++iter;
  630. ++GJKIters;
  631. // Check for duplicate support points. This is the main termination criteria.
  632. bool duplicate = false;
  633. for (int i = 0; i < saveCount; ++i)
  634. {
  635. if (vertex.IndexA == saveA[i] && vertex.IndexB == saveB[i])
  636. {
  637. duplicate = true;
  638. break;
  639. }
  640. }
  641. // If we found a duplicate support point we must exit to avoid cycling.
  642. if (duplicate)
  643. {
  644. break;
  645. }
  646. // New vertex is ok and needed.
  647. ++simplex.Count;
  648. }
  649. GJKMaxIters = Math.Max(GJKMaxIters, iter);
  650. // Prepare output.
  651. simplex.GetWitnessPoints(out output.PointA, out output.PointB);
  652. output.Distance = (output.PointA - output.PointB).Length();
  653. output.Iterations = iter;
  654. // Cache the simplex.
  655. simplex.WriteCache(ref cache);
  656. // Apply radii if requested.
  657. if (input.UseRadii)
  658. {
  659. float rA = input.ProxyA.Radius;
  660. float rB = input.ProxyB.Radius;
  661. if (output.Distance > rA + rB && output.Distance > Settings.Epsilon)
  662. {
  663. // Shapes are still no overlapped.
  664. // Move the witness points to the outer surface.
  665. output.Distance -= rA + rB;
  666. Vector2 normal = output.PointB - output.PointA;
  667. normal.Normalize();
  668. output.PointA += rA * normal;
  669. output.PointB -= rB * normal;
  670. }
  671. else
  672. {
  673. // Shapes are overlapped when radii are considered.
  674. // Move the witness points to the middle.
  675. Vector2 p = 0.5f * (output.PointA + output.PointB);
  676. output.PointA = p;
  677. output.PointB = p;
  678. output.Distance = 0.0f;
  679. }
  680. }
  681. }
  682. }
  683. }