b2_distance.cpp
Go to the documentation of this file.
1 // MIT License
2 
3 // Copyright (c) 2019 Erin Catto
4 
5 // Permission is hereby granted, free of charge, to any person obtaining a copy
6 // of this software and associated documentation files (the "Software"), to deal
7 // in the Software without restriction, including without limitation the rights
8 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 // copies of the Software, and to permit persons to whom the Software is
10 // furnished to do so, subject to the following conditions:
11 
12 // The above copyright notice and this permission notice shall be included in all
13 // copies or substantial portions of the Software.
14 
15 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 // SOFTWARE.
22 
23 #include "box2d/b2_circle_shape.h"
24 #include "box2d/b2_distance.h"
25 #include "box2d/b2_edge_shape.h"
26 #include "box2d/b2_chain_shape.h"
27 #include "box2d/b2_polygon_shape.h"
28 
29 // GJK using Voronoi regions (Christer Ericson) and Barycentric coordinates.
31 
32 void b2DistanceProxy::Set(const b2Shape* shape, int32 index)
33 {
34  switch (shape->GetType())
35  {
36  case b2Shape::e_circle:
37  {
38  const b2CircleShape* circle = static_cast<const b2CircleShape*>(shape);
39  m_vertices = &circle->m_p;
40  m_count = 1;
41  m_radius = circle->m_radius;
42  }
43  break;
44 
45  case b2Shape::e_polygon:
46  {
47  const b2PolygonShape* polygon = static_cast<const b2PolygonShape*>(shape);
48  m_vertices = polygon->m_vertices;
49  m_count = polygon->m_count;
50  m_radius = polygon->m_radius;
51  }
52  break;
53 
54  case b2Shape::e_chain:
55  {
56  const b2ChainShape* chain = static_cast<const b2ChainShape*>(shape);
57  b2Assert(0 <= index && index < chain->m_count);
58 
59  m_buffer[0] = chain->m_vertices[index];
60  if (index + 1 < chain->m_count)
61  {
62  m_buffer[1] = chain->m_vertices[index + 1];
63  }
64  else
65  {
66  m_buffer[1] = chain->m_vertices[0];
67  }
68 
70  m_count = 2;
71  m_radius = chain->m_radius;
72  }
73  break;
74 
75  case b2Shape::e_edge:
76  {
77  const b2EdgeShape* edge = static_cast<const b2EdgeShape*>(shape);
78  m_vertices = &edge->m_vertex1;
79  m_count = 2;
80  m_radius = edge->m_radius;
81  }
82  break;
83 
84  default:
85  b2Assert(false);
86  }
87 }
88 
89 void b2DistanceProxy::Set(const b2Vec2* vertices, int32 count, float radius)
90 {
91  m_vertices = vertices;
92  m_count = count;
93  m_radius = radius;
94 }
95 
97 {
98  b2Vec2 wA; // support point in proxyA
99  b2Vec2 wB; // support point in proxyB
100  b2Vec2 w; // wB - wA
101  float a; // barycentric coordinate for closest point
102  int32 indexA; // wA index
103  int32 indexB; // wB index
104 };
105 
106 struct b2Simplex
107 {
108  void ReadCache( const b2SimplexCache* cache,
109  const b2DistanceProxy* proxyA, const b2Transform& transformA,
110  const b2DistanceProxy* proxyB, const b2Transform& transformB)
111  {
112  b2Assert(cache->count <= 3);
113 
114  // Copy data from cache.
115  m_count = cache->count;
116  b2SimplexVertex* vertices = &m_v1;
117  for (int32 i = 0; i < m_count; ++i)
118  {
119  b2SimplexVertex* v = vertices + i;
120  v->indexA = cache->indexA[i];
121  v->indexB = cache->indexB[i];
122  b2Vec2 wALocal = proxyA->GetVertex(v->indexA);
123  b2Vec2 wBLocal = proxyB->GetVertex(v->indexB);
124  v->wA = b2Mul(transformA, wALocal);
125  v->wB = b2Mul(transformB, wBLocal);
126  v->w = v->wB - v->wA;
127  v->a = 0.0f;
128  }
129 
130  // Compute the new simplex metric, if it is substantially different than
131  // old metric then flush the simplex.
132  if (m_count > 1)
133  {
134  float metric1 = cache->metric;
135  float metric2 = GetMetric();
136  if (metric2 < 0.5f * metric1 || 2.0f * metric1 < metric2 || metric2 < b2_epsilon)
137  {
138  // Reset the simplex.
139  m_count = 0;
140  }
141  }
142 
143  // If the cache is empty or invalid ...
144  if (m_count == 0)
145  {
146  b2SimplexVertex* v = vertices + 0;
147  v->indexA = 0;
148  v->indexB = 0;
149  b2Vec2 wALocal = proxyA->GetVertex(0);
150  b2Vec2 wBLocal = proxyB->GetVertex(0);
151  v->wA = b2Mul(transformA, wALocal);
152  v->wB = b2Mul(transformB, wBLocal);
153  v->w = v->wB - v->wA;
154  v->a = 1.0f;
155  m_count = 1;
156  }
157  }
158 
159  void WriteCache(b2SimplexCache* cache) const
160  {
161  cache->metric = GetMetric();
162  cache->count = uint16(m_count);
163  const b2SimplexVertex* vertices = &m_v1;
164  for (int32 i = 0; i < m_count; ++i)
165  {
166  cache->indexA[i] = uint8(vertices[i].indexA);
167  cache->indexB[i] = uint8(vertices[i].indexB);
168  }
169  }
170 
172  {
173  switch (m_count)
174  {
175  case 1:
176  return -m_v1.w;
177 
178  case 2:
179  {
180  b2Vec2 e12 = m_v2.w - m_v1.w;
181  float sgn = b2Cross(e12, -m_v1.w);
182  if (sgn > 0.0f)
183  {
184  // Origin is left of e12.
185  return b2Cross(1.0f, e12);
186  }
187  else
188  {
189  // Origin is right of e12.
190  return b2Cross(e12, 1.0f);
191  }
192  }
193 
194  default:
195  b2Assert(false);
196  return b2Vec2_zero;
197  }
198  }
199 
201  {
202  switch (m_count)
203  {
204  case 0:
205  b2Assert(false);
206  return b2Vec2_zero;
207 
208  case 1:
209  return m_v1.w;
210 
211  case 2:
212  return m_v1.a * m_v1.w + m_v2.a * m_v2.w;
213 
214  case 3:
215  return b2Vec2_zero;
216 
217  default:
218  b2Assert(false);
219  return b2Vec2_zero;
220  }
221  }
222 
223  void GetWitnessPoints(b2Vec2* pA, b2Vec2* pB) const
224  {
225  switch (m_count)
226  {
227  case 0:
228  b2Assert(false);
229  break;
230 
231  case 1:
232  *pA = m_v1.wA;
233  *pB = m_v1.wB;
234  break;
235 
236  case 2:
237  *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA;
238  *pB = m_v1.a * m_v1.wB + m_v2.a * m_v2.wB;
239  break;
240 
241  case 3:
242  *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA + m_v3.a * m_v3.wA;
243  *pB = *pA;
244  break;
245 
246  default:
247  b2Assert(false);
248  break;
249  }
250  }
251 
252  float GetMetric() const
253  {
254  switch (m_count)
255  {
256  case 0:
257  b2Assert(false);
258  return 0.0f;
259 
260  case 1:
261  return 0.0f;
262 
263  case 2:
264  return b2Distance(m_v1.w, m_v2.w);
265 
266  case 3:
267  return b2Cross(m_v2.w - m_v1.w, m_v3.w - m_v1.w);
268 
269  default:
270  b2Assert(false);
271  return 0.0f;
272  }
273  }
274 
275  void Solve2();
276  void Solve3();
277 
278  b2SimplexVertex m_v1, m_v2, m_v3;
280 };
281 
282 
283 // Solve a line segment using barycentric coordinates.
284 //
285 // p = a1 * w1 + a2 * w2
286 // a1 + a2 = 1
287 //
288 // The vector from the origin to the closest point on the line is
289 // perpendicular to the line.
290 // e12 = w2 - w1
291 // dot(p, e) = 0
292 // a1 * dot(w1, e) + a2 * dot(w2, e) = 0
293 //
294 // 2-by-2 linear system
295 // [1 1 ][a1] = [1]
296 // [w1.e12 w2.e12][a2] = [0]
297 //
298 // Define
299 // d12_1 = dot(w2, e12)
300 // d12_2 = -dot(w1, e12)
301 // d12 = d12_1 + d12_2
302 //
303 // Solution
304 // a1 = d12_1 / d12
305 // a2 = d12_2 / d12
307 {
308  b2Vec2 w1 = m_v1.w;
309  b2Vec2 w2 = m_v2.w;
310  b2Vec2 e12 = w2 - w1;
311 
312  // w1 region
313  float d12_2 = -b2Dot(w1, e12);
314  if (d12_2 <= 0.0f)
315  {
316  // a2 <= 0, so we clamp it to 0
317  m_v1.a = 1.0f;
318  m_count = 1;
319  return;
320  }
321 
322  // w2 region
323  float d12_1 = b2Dot(w2, e12);
324  if (d12_1 <= 0.0f)
325  {
326  // a1 <= 0, so we clamp it to 0
327  m_v2.a = 1.0f;
328  m_count = 1;
329  m_v1 = m_v2;
330  return;
331  }
332 
333  // Must be in e12 region.
334  float inv_d12 = 1.0f / (d12_1 + d12_2);
335  m_v1.a = d12_1 * inv_d12;
336  m_v2.a = d12_2 * inv_d12;
337  m_count = 2;
338 }
339 
340 // Possible regions:
341 // - points[2]
342 // - edge points[0]-points[2]
343 // - edge points[1]-points[2]
344 // - inside the triangle
346 {
347  b2Vec2 w1 = m_v1.w;
348  b2Vec2 w2 = m_v2.w;
349  b2Vec2 w3 = m_v3.w;
350 
351  // Edge12
352  // [1 1 ][a1] = [1]
353  // [w1.e12 w2.e12][a2] = [0]
354  // a3 = 0
355  b2Vec2 e12 = w2 - w1;
356  float w1e12 = b2Dot(w1, e12);
357  float w2e12 = b2Dot(w2, e12);
358  float d12_1 = w2e12;
359  float d12_2 = -w1e12;
360 
361  // Edge13
362  // [1 1 ][a1] = [1]
363  // [w1.e13 w3.e13][a3] = [0]
364  // a2 = 0
365  b2Vec2 e13 = w3 - w1;
366  float w1e13 = b2Dot(w1, e13);
367  float w3e13 = b2Dot(w3, e13);
368  float d13_1 = w3e13;
369  float d13_2 = -w1e13;
370 
371  // Edge23
372  // [1 1 ][a2] = [1]
373  // [w2.e23 w3.e23][a3] = [0]
374  // a1 = 0
375  b2Vec2 e23 = w3 - w2;
376  float w2e23 = b2Dot(w2, e23);
377  float w3e23 = b2Dot(w3, e23);
378  float d23_1 = w3e23;
379  float d23_2 = -w2e23;
380 
381  // Triangle123
382  float n123 = b2Cross(e12, e13);
383 
384  float d123_1 = n123 * b2Cross(w2, w3);
385  float d123_2 = n123 * b2Cross(w3, w1);
386  float d123_3 = n123 * b2Cross(w1, w2);
387 
388  // w1 region
389  if (d12_2 <= 0.0f && d13_2 <= 0.0f)
390  {
391  m_v1.a = 1.0f;
392  m_count = 1;
393  return;
394  }
395 
396  // e12
397  if (d12_1 > 0.0f && d12_2 > 0.0f && d123_3 <= 0.0f)
398  {
399  float inv_d12 = 1.0f / (d12_1 + d12_2);
400  m_v1.a = d12_1 * inv_d12;
401  m_v2.a = d12_2 * inv_d12;
402  m_count = 2;
403  return;
404  }
405 
406  // e13
407  if (d13_1 > 0.0f && d13_2 > 0.0f && d123_2 <= 0.0f)
408  {
409  float inv_d13 = 1.0f / (d13_1 + d13_2);
410  m_v1.a = d13_1 * inv_d13;
411  m_v3.a = d13_2 * inv_d13;
412  m_count = 2;
413  m_v2 = m_v3;
414  return;
415  }
416 
417  // w2 region
418  if (d12_1 <= 0.0f && d23_2 <= 0.0f)
419  {
420  m_v2.a = 1.0f;
421  m_count = 1;
422  m_v1 = m_v2;
423  return;
424  }
425 
426  // w3 region
427  if (d13_1 <= 0.0f && d23_1 <= 0.0f)
428  {
429  m_v3.a = 1.0f;
430  m_count = 1;
431  m_v1 = m_v3;
432  return;
433  }
434 
435  // e23
436  if (d23_1 > 0.0f && d23_2 > 0.0f && d123_1 <= 0.0f)
437  {
438  float inv_d23 = 1.0f / (d23_1 + d23_2);
439  m_v2.a = d23_1 * inv_d23;
440  m_v3.a = d23_2 * inv_d23;
441  m_count = 2;
442  m_v1 = m_v3;
443  return;
444  }
445 
446  // Must be in triangle123
447  float inv_d123 = 1.0f / (d123_1 + d123_2 + d123_3);
448  m_v1.a = d123_1 * inv_d123;
449  m_v2.a = d123_2 * inv_d123;
450  m_v3.a = d123_3 * inv_d123;
451  m_count = 3;
452 }
453 
455  b2SimplexCache* cache,
456  const b2DistanceInput* input)
457 {
458  ++b2_gjkCalls;
459 
460  const b2DistanceProxy* proxyA = &input->proxyA;
461  const b2DistanceProxy* proxyB = &input->proxyB;
462 
463  b2Transform transformA = input->transformA;
464  b2Transform transformB = input->transformB;
465 
466  // Initialize the simplex.
467  b2Simplex simplex;
468  simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB);
469 
470  // Get simplex vertices as an array.
471  b2SimplexVertex* vertices = &simplex.m_v1;
472  const int32 k_maxIters = 20;
473 
474  // These store the vertices of the last simplex so that we
475  // can check for duplicates and prevent cycling.
476  int32 saveA[3], saveB[3];
477  int32 saveCount = 0;
478 
479  // Main iteration loop.
480  int32 iter = 0;
481  while (iter < k_maxIters)
482  {
483  // Copy simplex so we can identify duplicates.
484  saveCount = simplex.m_count;
485  for (int32 i = 0; i < saveCount; ++i)
486  {
487  saveA[i] = vertices[i].indexA;
488  saveB[i] = vertices[i].indexB;
489  }
490 
491  switch (simplex.m_count)
492  {
493  case 1:
494  break;
495 
496  case 2:
497  simplex.Solve2();
498  break;
499 
500  case 3:
501  simplex.Solve3();
502  break;
503 
504  default:
505  b2Assert(false);
506  }
507 
508  // If we have 3 points, then the origin is in the corresponding triangle.
509  if (simplex.m_count == 3)
510  {
511  break;
512  }
513 
514  // Get search direction.
515  b2Vec2 d = simplex.GetSearchDirection();
516 
517  // Ensure the search direction is numerically fit.
518  if (d.LengthSquared() < b2_epsilon * b2_epsilon)
519  {
520  // The origin is probably contained by a line segment
521  // or triangle. Thus the shapes are overlapped.
522 
523  // We can't return zero here even though there may be overlap.
524  // In case the simplex is a point, segment, or triangle it is difficult
525  // to determine if the origin is contained in the CSO or very close to it.
526  break;
527  }
528 
529  // Compute a tentative new simplex vertex using support points.
530  b2SimplexVertex* vertex = vertices + simplex.m_count;
531  vertex->indexA = proxyA->GetSupport(b2MulT(transformA.q, -d));
532  vertex->wA = b2Mul(transformA, proxyA->GetVertex(vertex->indexA));
533  vertex->indexB = proxyB->GetSupport(b2MulT(transformB.q, d));
534  vertex->wB = b2Mul(transformB, proxyB->GetVertex(vertex->indexB));
535  vertex->w = vertex->wB - vertex->wA;
536 
537  // Iteration count is equated to the number of support point calls.
538  ++iter;
539  ++b2_gjkIters;
540 
541  // Check for duplicate support points. This is the main termination criteria.
542  bool duplicate = false;
543  for (int32 i = 0; i < saveCount; ++i)
544  {
545  if (vertex->indexA == saveA[i] && vertex->indexB == saveB[i])
546  {
547  duplicate = true;
548  break;
549  }
550  }
551 
552  // If we found a duplicate support point we must exit to avoid cycling.
553  if (duplicate)
554  {
555  break;
556  }
557 
558  // New vertex is ok and needed.
559  ++simplex.m_count;
560  }
561 
563 
564  // Prepare output.
565  simplex.GetWitnessPoints(&output->pointA, &output->pointB);
566  output->distance = b2Distance(output->pointA, output->pointB);
567  output->iterations = iter;
568 
569  // Cache the simplex.
570  simplex.WriteCache(cache);
571 
572  // Apply radii if requested.
573  if (input->useRadii)
574  {
575  float rA = proxyA->m_radius;
576  float rB = proxyB->m_radius;
577 
578  if (output->distance > rA + rB && output->distance > b2_epsilon)
579  {
580  // Shapes are still no overlapped.
581  // Move the witness points to the outer surface.
582  output->distance -= rA + rB;
583  b2Vec2 normal = output->pointB - output->pointA;
584  normal.Normalize();
585  output->pointA += rA * normal;
586  output->pointB -= rB * normal;
587  }
588  else
589  {
590  // Shapes are overlapped when radii are considered.
591  // Move the witness points to the middle.
592  b2Vec2 p = 0.5f * (output->pointA + output->pointB);
593  output->pointA = p;
594  output->pointB = p;
595  output->distance = 0.0f;
596  }
597  }
598 }
599 
600 // GJK-raycast
601 // Algorithm by Gino van den Bergen.
602 // "Smooth Mesh Contacts with GJK" in Game Physics Pearls. 2010
603 bool b2ShapeCast(b2ShapeCastOutput * output, const b2ShapeCastInput * input)
604 {
605  output->iterations = 0;
606  output->lambda = 1.0f;
607  output->normal.SetZero();
608  output->point.SetZero();
609 
610  const b2DistanceProxy* proxyA = &input->proxyA;
611  const b2DistanceProxy* proxyB = &input->proxyB;
612 
613  float radiusA = b2Max(proxyA->m_radius, b2_polygonRadius);
614  float radiusB = b2Max(proxyB->m_radius, b2_polygonRadius);
615  float radius = radiusA + radiusB;
616 
617  b2Transform xfA = input->transformA;
618  b2Transform xfB = input->transformB;
619 
620  b2Vec2 r = input->translationB;
621  b2Vec2 n(0.0f, 0.0f);
622  float lambda = 0.0f;
623 
624  // Initial simplex
625  b2Simplex simplex;
626  simplex.m_count = 0;
627 
628  // Get simplex vertices as an array.
629  b2SimplexVertex* vertices = &simplex.m_v1;
630 
631  // Get support point in -r direction
632  int32 indexA = proxyA->GetSupport(b2MulT(xfA.q, -r));
633  b2Vec2 wA = b2Mul(xfA, proxyA->GetVertex(indexA));
634  int32 indexB = proxyB->GetSupport(b2MulT(xfB.q, r));
635  b2Vec2 wB = b2Mul(xfB, proxyB->GetVertex(indexB));
636  b2Vec2 v = wA - wB;
637 
638  // Sigma is the target distance between polygons
639  float sigma = b2Max(b2_polygonRadius, radius - b2_polygonRadius);
640  const float tolerance = 0.5f * b2_linearSlop;
641 
642  // Main iteration loop.
643  const int32 k_maxIters = 20;
644  int32 iter = 0;
645  while (iter < k_maxIters && v.Length() - sigma > tolerance)
646  {
647  b2Assert(simplex.m_count < 3);
648 
649  output->iterations += 1;
650 
651  // Support in direction -v (A - B)
652  indexA = proxyA->GetSupport(b2MulT(xfA.q, -v));
653  wA = b2Mul(xfA, proxyA->GetVertex(indexA));
654  indexB = proxyB->GetSupport(b2MulT(xfB.q, v));
655  wB = b2Mul(xfB, proxyB->GetVertex(indexB));
656  b2Vec2 p = wA - wB;
657 
658  // -v is a normal at p
659  v.Normalize();
660 
661  // Intersect ray with plane
662  float vp = b2Dot(v, p);
663  float vr = b2Dot(v, r);
664  if (vp - sigma > lambda * vr)
665  {
666  if (vr <= 0.0f)
667  {
668  return false;
669  }
670 
671  lambda = (vp - sigma) / vr;
672  if (lambda > 1.0f)
673  {
674  return false;
675  }
676 
677  n = -v;
678  simplex.m_count = 0;
679  }
680 
681  // Reverse simplex since it works with B - A.
682  // Shift by lambda * r because we want the closest point to the current clip point.
683  // Note that the support point p is not shifted because we want the plane equation
684  // to be formed in unshifted space.
685  b2SimplexVertex* vertex = vertices + simplex.m_count;
686  vertex->indexA = indexB;
687  vertex->wA = wB + lambda * r;
688  vertex->indexB = indexA;
689  vertex->wB = wA;
690  vertex->w = vertex->wB - vertex->wA;
691  vertex->a = 1.0f;
692  simplex.m_count += 1;
693 
694  switch (simplex.m_count)
695  {
696  case 1:
697  break;
698 
699  case 2:
700  simplex.Solve2();
701  break;
702 
703  case 3:
704  simplex.Solve3();
705  break;
706 
707  default:
708  b2Assert(false);
709  }
710 
711  // If we have 3 points, then the origin is in the corresponding triangle.
712  if (simplex.m_count == 3)
713  {
714  // Overlap
715  return false;
716  }
717 
718  // Get search direction.
719  v = simplex.GetClosestPoint();
720 
721  // Iteration count is equated to the number of support point calls.
722  ++iter;
723  }
724 
725  if (iter == 0)
726  {
727  // Initial overlap
728  return false;
729  }
730 
731  // Prepare output.
732  b2Vec2 pointA, pointB;
733  simplex.GetWitnessPoints(&pointB, &pointA);
734 
735  if (v.LengthSquared() > 0.0f)
736  {
737  n = -v;
738  n.Normalize();
739  }
740 
741  output->point = pointA + radiusA * n;
742  output->normal = n;
743  output->lambda = lambda;
744  output->iterations = iter;
745  return true;
746 }
#define b2_polygonRadius
Definition: b2_common.h:74
d
b2Transform transformB
Definition: b2_distance.h:107
b2Vec2 * m_vertices
The vertices. Owned by this class.
void Set(const b2Shape *shape, int32 index)
Definition: b2_distance.cpp:32
b2Vec2 b2Mul(const b2Mat22 &A, const b2Vec2 &v)
Definition: b2_math.h:422
void ReadCache(const b2SimplexCache *cache, const b2DistanceProxy *proxyA, const b2Transform &transformA, const b2DistanceProxy *proxyB, const b2Transform &transformB)
b2DistanceProxy proxyA
Definition: b2_distance.h:104
B2_API const b2Vec2 b2Vec2_zero
Useful constant.
float b2Dot(const b2Vec2 &a, const b2Vec2 &b)
Perform the dot product on two vectors.
Definition: b2_math.h:395
b2Rot q
Definition: b2_math.h:361
f
b2SimplexVertex m_v1
unsigned short uint16
Definition: b2_types.h:30
#define B2_API
Definition: b2_api.h:49
uint8 indexA[3]
vertices on shape A
Definition: b2_distance.h:69
B2_API int32 b2_gjkMaxIters
Definition: b2_distance.cpp:30
B2_API int32 b2_gjkCalls
Definition: b2_distance.cpp:30
b2DistanceProxy proxyA
Definition: b2_distance.h:78
Input parameters for b2ShapeCast.
Definition: b2_distance.h:102
#define b2_linearSlop
Definition: b2_common.h:65
int32 iterations
number of GJK iterations used
Definition: b2_distance.h:91
void SetZero()
Set this vector to all zeros.
Definition: b2_math.h:50
A solid circle shape.
A 2D column vector.
Definition: b2_math.h:41
b2Vec2 pointB
closest point on shapeB
Definition: b2_distance.h:89
signed int int32
Definition: b2_types.h:28
b2Vec2 m_p
Position.
b2Vec2 pointA
closest point on shapeA
Definition: b2_distance.h:88
void GetWitnessPoints(b2Vec2 *pA, b2Vec2 *pB) const
int32 m_count
int32 GetSupport(const b2Vec2 &d) const
Get the supporting vertex index in the given direction.
Definition: b2_distance.h:137
float m_radius
Definition: b2_shape.h:102
b2Vec2 m_buffer[2]
Definition: b2_distance.h:57
float LengthSquared() const
Definition: b2_math.h:96
Type GetType() const
Definition: b2_shape.h:105
b2SimplexVertex m_v3
b2Transform transformA
Definition: b2_distance.h:80
T b2Max(T a, T b)
Definition: b2_math.h:637
float b2Cross(const b2Vec2 &a, const b2Vec2 &b)
Perform the cross product on two vectors. In 2D this produces a scalar.
Definition: b2_math.h:401
b2Transform transformB
Definition: b2_distance.h:81
B2_API int32 b2_gjkIters
Definition: b2_distance.cpp:30
b2Vec2 m_vertices[b2_maxPolygonVertices]
b2Transform transformA
Definition: b2_distance.h:106
Output results for b2ShapeCast.
Definition: b2_distance.h:112
const b2Vec2 * m_vertices
Definition: b2_distance.h:58
uint8 indexB[3]
vertices on shape B
Definition: b2_distance.h:70
void Solve3()
unsigned char uint8
Definition: b2_types.h:29
void WriteCache(b2SimplexCache *cache) const
Output for b2Distance.
Definition: b2_distance.h:86
b2Vec2 GetClosestPoint() const
b2Vec2 b2MulT(const b2Mat22 &A, const b2Vec2 &v)
Definition: b2_math.h:429
b2Vec2 m_vertex1
These are the edge vertices.
Definition: b2_edge_shape.h:66
float Normalize()
Convert this vector into a unit vector. Returns the length.
Definition: b2_math.h:102
int32 m_count
The vertex count.
bool b2ShapeCast(b2ShapeCastOutput *output, const b2ShapeCastInput *input)
#define b2_epsilon
Definition: b2_common.h:40
void Solve2()
const b2Vec2 & GetVertex(int32 index) const
Get a vertex by index. Used by b2Distance.
Definition: b2_distance.h:131
#define b2Assert(A)
Definition: b2_common.h:37
b2Vec2 GetSearchDirection() const
b2DistanceProxy proxyB
Definition: b2_distance.h:105
b2DistanceProxy proxyB
Definition: b2_distance.h:79
float GetMetric() const
void b2Distance(b2DistanceOutput *output, b2SimplexCache *cache, const b2DistanceInput *input)
float metric
length or area
Definition: b2_distance.h:67


mvsim
Author(s):
autogenerated on Tue Jul 4 2023 03:08:19