Distance.cs 22 KB

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