b2CollideEdge.cpp
Go to the documentation of this file.
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 
23 
24 
25 // Compute contact points for edge versus circle.
26 // This accounts for edge connectivity.
28  const b2EdgeShape* edgeA, const b2Transform& xfA,
29  const b2CircleShape* circleB, const b2Transform& xfB)
30 {
31  manifold->pointCount = 0;
32 
33  // Compute circle in frame of edge
34  b2Vec2 Q = b2MulT(xfA, b2Mul(xfB, circleB->m_p));
35 
36  b2Vec2 A = edgeA->m_vertex1, B = edgeA->m_vertex2;
37  b2Vec2 e = B - A;
38 
39  // Barycentric coordinates
40  float32 u = b2Dot(e, B - Q);
41  float32 v = b2Dot(e, Q - A);
42 
43  float32 radius = edgeA->m_radius + circleB->m_radius;
44 
46  cf.indexB = 0;
48 
49  // Region A
50  if (v <= 0.0f)
51  {
52  b2Vec2 P = A;
53  b2Vec2 d = Q - P;
54  float32 dd = b2Dot(d, d);
55  if (dd > radius * radius)
56  {
57  return;
58  }
59 
60  // Is there an edge connected to A?
61  if (edgeA->m_hasVertex0)
62  {
63  b2Vec2 A1 = edgeA->m_vertex0;
64  b2Vec2 B1 = A;
65  b2Vec2 e1 = B1 - A1;
66  float32 u1 = b2Dot(e1, B1 - Q);
67 
68  // Is the circle in Region AB of the previous edge?
69  if (u1 > 0.0f)
70  {
71  return;
72  }
73  }
74 
75  cf.indexA = 0;
77  manifold->pointCount = 1;
78  manifold->type = b2Manifold::e_circles;
79  manifold->localNormal.SetZero();
80  manifold->localPoint = P;
81  manifold->points[0].id.key = 0;
82  manifold->points[0].id.cf = cf;
83  manifold->points[0].localPoint = circleB->m_p;
84  return;
85  }
86 
87  // Region B
88  if (u <= 0.0f)
89  {
90  b2Vec2 P = B;
91  b2Vec2 d = Q - P;
92  float32 dd = b2Dot(d, d);
93  if (dd > radius * radius)
94  {
95  return;
96  }
97 
98  // Is there an edge connected to B?
99  if (edgeA->m_hasVertex3)
100  {
101  b2Vec2 B2 = edgeA->m_vertex3;
102  b2Vec2 A2 = B;
103  b2Vec2 e2 = B2 - A2;
104  float32 v2 = b2Dot(e2, Q - A2);
105 
106  // Is the circle in Region AB of the next edge?
107  if (v2 > 0.0f)
108  {
109  return;
110  }
111  }
112 
113  cf.indexA = 1;
115  manifold->pointCount = 1;
116  manifold->type = b2Manifold::e_circles;
117  manifold->localNormal.SetZero();
118  manifold->localPoint = P;
119  manifold->points[0].id.key = 0;
120  manifold->points[0].id.cf = cf;
121  manifold->points[0].localPoint = circleB->m_p;
122  return;
123  }
124 
125  // Region AB
126  float32 den = b2Dot(e, e);
127  b2Assert(den > 0.0f);
128  b2Vec2 P = (1.0f / den) * (u * A + v * B);
129  b2Vec2 d = Q - P;
130  float32 dd = b2Dot(d, d);
131  if (dd > radius * radius)
132  {
133  return;
134  }
135 
136  b2Vec2 n(-e.y, e.x);
137  if (b2Dot(n, Q - A) < 0.0f)
138  {
139  n.Set(-n.x, -n.y);
140  }
141  n.Normalize();
142 
143  cf.indexA = 0;
145  manifold->pointCount = 1;
146  manifold->type = b2Manifold::e_faceA;
147  manifold->localNormal = n;
148  manifold->localPoint = A;
149  manifold->points[0].id.key = 0;
150  manifold->points[0].id.cf = cf;
151  manifold->points[0].localPoint = circleB->m_p;
152 }
153 
154 // This structure is used to keep track of the best separating axis.
155 struct b2EPAxis
156 {
157  enum Type
158  {
162  };
163 
167 };
168 
169 // This holds polygon B expressed in frame A.
171 {
175 };
176 
177 // Reference face used for clipping
179 {
180  int32 i1, i2;
181 
182  b2Vec2 v1, v2;
183 
185 
188 
191 };
192 
193 // This class collides and edge and a polygon, taking into account edge adjacency.
195 {
196  void Collide(b2Manifold* manifold, const b2EdgeShape* edgeA, const b2Transform& xfA,
197  const b2PolygonShape* polygonB, const b2Transform& xfB);
198  b2EPAxis ComputeEdgeSeparation();
199  b2EPAxis ComputePolygonSeparation();
200 
202  {
205  e_convex
206  };
207 
209 
212  b2Vec2 m_v0, m_v1, m_v2, m_v3;
213  b2Vec2 m_normal0, m_normal1, m_normal2;
215  VertexType m_type1, m_type2;
216  b2Vec2 m_lowerLimit, m_upperLimit;
218  bool m_front;
219 };
220 
221 // Algorithm:
222 // 1. Classify v1 and v2
223 // 2. Classify polygon centroid as front or back
224 // 3. Flip normal if necessary
225 // 4. Initialize normal range to [-pi, pi] about face normal
226 // 5. Adjust normal range according to adjacent edges
227 // 6. Visit each separating axes, only accept axes within the range
228 // 7. Return if _any_ axis indicates separation
229 // 8. Clip
230 void b2EPCollider::Collide(b2Manifold* manifold, const b2EdgeShape* edgeA, const b2Transform& xfA,
231  const b2PolygonShape* polygonB, const b2Transform& xfB)
232 {
233  m_xf = b2MulT(xfA, xfB);
234 
235  m_centroidB = b2Mul(m_xf, polygonB->m_centroid);
236 
237  m_v0 = edgeA->m_vertex0;
238  m_v1 = edgeA->m_vertex1;
239  m_v2 = edgeA->m_vertex2;
240  m_v3 = edgeA->m_vertex3;
241 
242  bool hasVertex0 = edgeA->m_hasVertex0;
243  bool hasVertex3 = edgeA->m_hasVertex3;
244 
245  b2Vec2 edge1 = m_v2 - m_v1;
246  edge1.Normalize();
247  m_normal1.Set(edge1.y, -edge1.x);
248  float32 offset1 = b2Dot(m_normal1, m_centroidB - m_v1);
249  float32 offset0 = 0.0f, offset2 = 0.0f;
250  bool convex1 = false, convex2 = false;
251 
252  // Is there a preceding edge?
253  if (hasVertex0)
254  {
255  b2Vec2 edge0 = m_v1 - m_v0;
256  edge0.Normalize();
257  m_normal0.Set(edge0.y, -edge0.x);
258  convex1 = b2Cross(edge0, edge1) >= 0.0f;
259  offset0 = b2Dot(m_normal0, m_centroidB - m_v0);
260  }
261 
262  // Is there a following edge?
263  if (hasVertex3)
264  {
265  b2Vec2 edge2 = m_v3 - m_v2;
266  edge2.Normalize();
267  m_normal2.Set(edge2.y, -edge2.x);
268  convex2 = b2Cross(edge1, edge2) > 0.0f;
269  offset2 = b2Dot(m_normal2, m_centroidB - m_v2);
270  }
271 
272  // Determine front or back collision. Determine collision normal limits.
273  if (hasVertex0 && hasVertex3)
274  {
275  if (convex1 && convex2)
276  {
277  m_front = offset0 >= 0.0f || offset1 >= 0.0f || offset2 >= 0.0f;
278  if (m_front)
279  {
280  m_normal = m_normal1;
281  m_lowerLimit = m_normal0;
282  m_upperLimit = m_normal2;
283  }
284  else
285  {
286  m_normal = -m_normal1;
287  m_lowerLimit = -m_normal1;
288  m_upperLimit = -m_normal1;
289  }
290  }
291  else if (convex1)
292  {
293  m_front = offset0 >= 0.0f || (offset1 >= 0.0f && offset2 >= 0.0f);
294  if (m_front)
295  {
296  m_normal = m_normal1;
297  m_lowerLimit = m_normal0;
298  m_upperLimit = m_normal1;
299  }
300  else
301  {
302  m_normal = -m_normal1;
303  m_lowerLimit = -m_normal2;
304  m_upperLimit = -m_normal1;
305  }
306  }
307  else if (convex2)
308  {
309  m_front = offset2 >= 0.0f || (offset0 >= 0.0f && offset1 >= 0.0f);
310  if (m_front)
311  {
312  m_normal = m_normal1;
313  m_lowerLimit = m_normal1;
314  m_upperLimit = m_normal2;
315  }
316  else
317  {
318  m_normal = -m_normal1;
319  m_lowerLimit = -m_normal1;
320  m_upperLimit = -m_normal0;
321  }
322  }
323  else
324  {
325  m_front = offset0 >= 0.0f && offset1 >= 0.0f && offset2 >= 0.0f;
326  if (m_front)
327  {
328  m_normal = m_normal1;
329  m_lowerLimit = m_normal1;
330  m_upperLimit = m_normal1;
331  }
332  else
333  {
334  m_normal = -m_normal1;
335  m_lowerLimit = -m_normal2;
336  m_upperLimit = -m_normal0;
337  }
338  }
339  }
340  else if (hasVertex0)
341  {
342  if (convex1)
343  {
344  m_front = offset0 >= 0.0f || offset1 >= 0.0f;
345  if (m_front)
346  {
347  m_normal = m_normal1;
348  m_lowerLimit = m_normal0;
349  m_upperLimit = -m_normal1;
350  }
351  else
352  {
353  m_normal = -m_normal1;
354  m_lowerLimit = m_normal1;
355  m_upperLimit = -m_normal1;
356  }
357  }
358  else
359  {
360  m_front = offset0 >= 0.0f && offset1 >= 0.0f;
361  if (m_front)
362  {
363  m_normal = m_normal1;
364  m_lowerLimit = m_normal1;
365  m_upperLimit = -m_normal1;
366  }
367  else
368  {
369  m_normal = -m_normal1;
370  m_lowerLimit = m_normal1;
371  m_upperLimit = -m_normal0;
372  }
373  }
374  }
375  else if (hasVertex3)
376  {
377  if (convex2)
378  {
379  m_front = offset1 >= 0.0f || offset2 >= 0.0f;
380  if (m_front)
381  {
382  m_normal = m_normal1;
383  m_lowerLimit = -m_normal1;
384  m_upperLimit = m_normal2;
385  }
386  else
387  {
388  m_normal = -m_normal1;
389  m_lowerLimit = -m_normal1;
390  m_upperLimit = m_normal1;
391  }
392  }
393  else
394  {
395  m_front = offset1 >= 0.0f && offset2 >= 0.0f;
396  if (m_front)
397  {
398  m_normal = m_normal1;
399  m_lowerLimit = -m_normal1;
400  m_upperLimit = m_normal1;
401  }
402  else
403  {
404  m_normal = -m_normal1;
405  m_lowerLimit = -m_normal2;
406  m_upperLimit = m_normal1;
407  }
408  }
409  }
410  else
411  {
412  m_front = offset1 >= 0.0f;
413  if (m_front)
414  {
415  m_normal = m_normal1;
416  m_lowerLimit = -m_normal1;
417  m_upperLimit = -m_normal1;
418  }
419  else
420  {
421  m_normal = -m_normal1;
422  m_lowerLimit = m_normal1;
423  m_upperLimit = m_normal1;
424  }
425  }
426 
427  // Get polygonB in frameA
428  m_polygonB.count = polygonB->m_count;
429  for (int32 i = 0; i < polygonB->m_count; ++i)
430  {
431  m_polygonB.vertices[i] = b2Mul(m_xf, polygonB->m_vertices[i]);
432  m_polygonB.normals[i] = b2Mul(m_xf.q, polygonB->m_normals[i]);
433  }
434 
435  m_radius = 2.0f * b2_polygonRadius;
436 
437  manifold->pointCount = 0;
438 
439  b2EPAxis edgeAxis = ComputeEdgeSeparation();
440 
441  // If no valid normal can be found than this edge should not collide.
442  if (edgeAxis.type == b2EPAxis::e_unknown)
443  {
444  return;
445  }
446 
447  if (edgeAxis.separation > m_radius)
448  {
449  return;
450  }
451 
452  b2EPAxis polygonAxis = ComputePolygonSeparation();
453  if (polygonAxis.type != b2EPAxis::e_unknown && polygonAxis.separation > m_radius)
454  {
455  return;
456  }
457 
458  // Use hysteresis for jitter reduction.
459  const float32 k_relativeTol = 0.98f;
460  const float32 k_absoluteTol = 0.001f;
461 
462  b2EPAxis primaryAxis;
463  if (polygonAxis.type == b2EPAxis::e_unknown)
464  {
465  primaryAxis = edgeAxis;
466  }
467  else if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol)
468  {
469  primaryAxis = polygonAxis;
470  }
471  else
472  {
473  primaryAxis = edgeAxis;
474  }
475 
476  b2ClipVertex ie[2];
477  b2ReferenceFace rf;
478  if (primaryAxis.type == b2EPAxis::e_edgeA)
479  {
480  manifold->type = b2Manifold::e_faceA;
481 
482  // Search for the polygon normal that is most anti-parallel to the edge normal.
483  int32 bestIndex = 0;
484  float32 bestValue = b2Dot(m_normal, m_polygonB.normals[0]);
485  for (int32 i = 1; i < m_polygonB.count; ++i)
486  {
487  float32 value = b2Dot(m_normal, m_polygonB.normals[i]);
488  if (value < bestValue)
489  {
490  bestValue = value;
491  bestIndex = i;
492  }
493  }
494 
495  int32 i1 = bestIndex;
496  int32 i2 = i1 + 1 < m_polygonB.count ? i1 + 1 : 0;
497 
498  ie[0].v = m_polygonB.vertices[i1];
499  ie[0].id.cf.indexA = 0;
500  ie[0].id.cf.indexB = static_cast<uint8>(i1);
503 
504  ie[1].v = m_polygonB.vertices[i2];
505  ie[1].id.cf.indexA = 0;
506  ie[1].id.cf.indexB = static_cast<uint8>(i2);
509 
510  if (m_front)
511  {
512  rf.i1 = 0;
513  rf.i2 = 1;
514  rf.v1 = m_v1;
515  rf.v2 = m_v2;
516  rf.normal = m_normal1;
517  }
518  else
519  {
520  rf.i1 = 1;
521  rf.i2 = 0;
522  rf.v1 = m_v2;
523  rf.v2 = m_v1;
524  rf.normal = -m_normal1;
525  }
526  }
527  else
528  {
529  manifold->type = b2Manifold::e_faceB;
530 
531  ie[0].v = m_v1;
532  ie[0].id.cf.indexA = 0;
533  ie[0].id.cf.indexB = static_cast<uint8>(primaryAxis.index);
536 
537  ie[1].v = m_v2;
538  ie[1].id.cf.indexA = 0;
539  ie[1].id.cf.indexB = static_cast<uint8>(primaryAxis.index);
542 
543  rf.i1 = primaryAxis.index;
544  rf.i2 = rf.i1 + 1 < m_polygonB.count ? rf.i1 + 1 : 0;
545  rf.v1 = m_polygonB.vertices[rf.i1];
546  rf.v2 = m_polygonB.vertices[rf.i2];
547  rf.normal = m_polygonB.normals[rf.i1];
548  }
549 
550  rf.sideNormal1.Set(rf.normal.y, -rf.normal.x);
551  rf.sideNormal2 = -rf.sideNormal1;
552  rf.sideOffset1 = b2Dot(rf.sideNormal1, rf.v1);
553  rf.sideOffset2 = b2Dot(rf.sideNormal2, rf.v2);
554 
555  // Clip incident edge against extruded edge1 side edges.
556  b2ClipVertex clipPoints1[2];
557  b2ClipVertex clipPoints2[2];
558  int32 np;
559 
560  // Clip to box side 1
561  np = b2ClipSegmentToLine(clipPoints1, ie, rf.sideNormal1, rf.sideOffset1, rf.i1);
562 
563  if (np < b2_maxManifoldPoints)
564  {
565  return;
566  }
567 
568  // Clip to negative box side 1
569  np = b2ClipSegmentToLine(clipPoints2, clipPoints1, rf.sideNormal2, rf.sideOffset2, rf.i2);
570 
571  if (np < b2_maxManifoldPoints)
572  {
573  return;
574  }
575 
576  // Now clipPoints2 contains the clipped points.
577  if (primaryAxis.type == b2EPAxis::e_edgeA)
578  {
579  manifold->localNormal = rf.normal;
580  manifold->localPoint = rf.v1;
581  }
582  else
583  {
584  manifold->localNormal = polygonB->m_normals[rf.i1];
585  manifold->localPoint = polygonB->m_vertices[rf.i1];
586  }
587 
588  int32 pointCount = 0;
589  for (int32 i = 0; i < b2_maxManifoldPoints; ++i)
590  {
592 
593  separation = b2Dot(rf.normal, clipPoints2[i].v - rf.v1);
594 
595  if (separation <= m_radius)
596  {
597  b2ManifoldPoint* cp = manifold->points + pointCount;
598 
599  if (primaryAxis.type == b2EPAxis::e_edgeA)
600  {
601  cp->localPoint = b2MulT(m_xf, clipPoints2[i].v);
602  cp->id = clipPoints2[i].id;
603  }
604  else
605  {
606  cp->localPoint = clipPoints2[i].v;
607  cp->id.cf.typeA = clipPoints2[i].id.cf.typeB;
608  cp->id.cf.typeB = clipPoints2[i].id.cf.typeA;
609  cp->id.cf.indexA = clipPoints2[i].id.cf.indexB;
610  cp->id.cf.indexB = clipPoints2[i].id.cf.indexA;
611  }
612 
613  ++pointCount;
614  }
615  }
616 
617  manifold->pointCount = pointCount;
618 }
619 
621 {
622  b2EPAxis axis;
623  axis.type = b2EPAxis::e_edgeA;
624  axis.index = m_front ? 0 : 1;
625  axis.separation = FLT_MAX;
626 
627  for (int32 i = 0; i < m_polygonB.count; ++i)
628  {
629  float32 s = b2Dot(m_normal, m_polygonB.vertices[i] - m_v1);
630  if (s < axis.separation)
631  {
632  axis.separation = s;
633  }
634  }
635 
636  return axis;
637 }
638 
640 {
641  b2EPAxis axis;
642  axis.type = b2EPAxis::e_unknown;
643  axis.index = -1;
644  axis.separation = -FLT_MAX;
645 
646  b2Vec2 perp(-m_normal.y, m_normal.x);
647 
648  for (int32 i = 0; i < m_polygonB.count; ++i)
649  {
650  b2Vec2 n = -m_polygonB.normals[i];
651 
652  float32 s1 = b2Dot(n, m_polygonB.vertices[i] - m_v1);
653  float32 s2 = b2Dot(n, m_polygonB.vertices[i] - m_v2);
654  float32 s = b2Min(s1, s2);
655 
656  if (s > m_radius)
657  {
658  // No collision
659  axis.type = b2EPAxis::e_edgeB;
660  axis.index = i;
661  axis.separation = s;
662  return axis;
663  }
664 
665  // Adjacency
666  if (b2Dot(n, perp) >= 0.0f)
667  {
668  if (b2Dot(n - m_upperLimit, m_normal) < -b2_angularSlop)
669  {
670  continue;
671  }
672  }
673  else
674  {
675  if (b2Dot(n - m_lowerLimit, m_normal) < -b2_angularSlop)
676  {
677  continue;
678  }
679  }
680 
681  if (s > axis.separation)
682  {
683  axis.type = b2EPAxis::e_edgeB;
684  axis.index = i;
685  axis.separation = s;
686  }
687  }
688 
689  return axis;
690 }
691 
693  const b2EdgeShape* edgeA, const b2Transform& xfA,
694  const b2PolygonShape* polygonB, const b2Transform& xfB)
695 {
696  b2EPCollider collider;
697  collider.Collide(manifold, edgeA, xfA, polygonB, xfB);
698 }
d
float32 b2Dot(const b2Vec2 &a, const b2Vec2 &b)
Perform the dot product on two vectors.
Definition: b2Math.h:406
uint8 indexB
Feature index on shapeB.
Definition: b2Collision.h:47
uint8 typeA
The feature type on shapeA.
Definition: b2Collision.h:48
b2Vec2 b2Mul(const b2Mat22 &A, const b2Vec2 &v)
Definition: b2Math.h:433
Used for computing contact manifolds.
Definition: b2Collision.h:140
b2Vec2 localNormal
not use for Type::e_points
Definition: b2Collision.h:103
f
XmlRpcServer s
b2ContactID id
uniquely identifies a contact point between two shapes
Definition: b2Collision.h:74
uint8 typeB
The feature type on shapeB.
Definition: b2Collision.h:49
#define b2_polygonRadius
Definition: b2Settings.h:77
b2ContactFeature cf
Definition: b2Collision.h:55
#define b2_maxManifoldPoints
Definition: b2Settings.h:50
uint32 key
Used to quickly compare contact ids.
Definition: b2Collision.h:56
void Collide(b2Manifold *manifold, const b2EdgeShape *edgeA, const b2Transform &xfA, const b2PolygonShape *polygonB, const b2Transform &xfB)
b2Vec2 m_vertex0
Optional adjacent vertices. These are used for smooth collision.
Definition: b2EdgeShape.h:58
void b2CollideEdgeAndCircle(b2Manifold *manifold, const b2EdgeShape *edgeA, const b2Transform &xfA, const b2CircleShape *circleB, const b2Transform &xfB)
Compute the collision manifold between an edge and a circle.
float32 m_radius
Definition: b2Shape.h:93
void SetZero()
Set this vector to all zeros.
Definition: b2Math.h:62
A circle shape.
Definition: b2CircleShape.h:25
A 2D column vector.
Definition: b2Math.h:53
b2ContactID id
Definition: b2Collision.h:143
b2Vec2 m_p
Position.
Definition: b2CircleShape.h:62
signed int int32
Definition: b2Settings.h:31
float32 b2Cross(const b2Vec2 &a, const b2Vec2 &b)
Perform the cross product on two vectors. In 2D this produces a scalar.
Definition: b2Math.h:412
b2TempPolygon m_polygonB
bool m_hasVertex0
Definition: b2EdgeShape.h:59
b2Vec2 m_vertices[b2_maxPolygonVertices]
int32 pointCount
the number of manifold points
Definition: b2Collision.h:106
#define b2_maxPolygonVertices
Definition: b2Settings.h:54
void b2CollideEdgeAndPolygon(b2Manifold *manifold, const b2EdgeShape *edgeA, const b2Transform &xfA, const b2PolygonShape *polygonB, const b2Transform &xfB)
Compute the collision manifold between an edge and a circle.
b2Vec2 m_vertex3
Definition: b2EdgeShape.h:58
b2Vec2 localPoint
usage depends on manifold type
Definition: b2Collision.h:71
#define b2_angularSlop
Definition: b2Settings.h:72
uint8 indexA
Feature index on shapeA.
Definition: b2Collision.h:46
b2Vec2 b2MulT(const b2Mat22 &A, const b2Vec2 &v)
Definition: b2Math.h:440
unsigned char uint8
Definition: b2Settings.h:32
float32 y
Definition: b2Math.h:140
b2Vec2 localPoint
usage depends on manifold type
Definition: b2Collision.h:104
b2ManifoldPoint points[b2_maxManifoldPoints]
the points of contact
Definition: b2Collision.h:102
b2Transform m_xf
#define b2Assert(A)
Definition: b2Settings.h:27
float32 separation
b2EPAxis ComputePolygonSeparation()
b2Vec2 m_vertex1
These are the edge vertices.
Definition: b2EdgeShape.h:55
int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], const b2Vec2 &normal, float32 offset, int32 vertexIndexA)
Clipping for contact manifolds.
b2Vec2 m_vertex2
Definition: b2EdgeShape.h:55
b2EPAxis ComputeEdgeSeparation()
T b2Min(T a, T b)
Definition: b2Math.h:632
float32 x
Definition: b2Math.h:140
float32 Normalize()
Convert this vector into a unit vector. Returns the length.
Definition: b2Math.h:114
void Set(float32 x_, float32 y_)
Set this vector to some specified coordinates.
Definition: b2Math.h:65
VertexType m_type2
b2Vec2 m_normals[b2_maxPolygonVertices]
float float32
Definition: b2Settings.h:35
bool m_hasVertex3
Definition: b2EdgeShape.h:59


mvsim
Author(s):
autogenerated on Thu Jun 6 2019 19:36:39