b2CollideEdge.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673
  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/b2Collision.h>
  19. #include <Box2D/Collision/Shapes/b2CircleShape.h>
  20. #include <Box2D/Collision/Shapes/b2EdgeShape.h>
  21. #include <Box2D/Collision/Shapes/b2PolygonShape.h>
  22. enum b2EdgeType
  23. {
  24. b2_isolated,
  25. b2_concave,
  26. b2_flat,
  27. b2_convex
  28. };
  29. // Compute contact points for edge versus circle.
  30. // This accounts for edge connectivity.
  31. void b2CollideEdgeAndCircle(b2Manifold* manifold,
  32. const b2EdgeShape* edgeA, const b2Transform& xfA,
  33. const b2CircleShape* circleB, const b2Transform& xfB)
  34. {
  35. manifold->pointCount = 0;
  36. // Compute circle in frame of edge
  37. b2Vec2 Q = b2MulT(xfA, b2Mul(xfB, circleB->m_p));
  38. b2Vec2 A = edgeA->m_vertex1, B = edgeA->m_vertex2;
  39. b2Vec2 e = B - A;
  40. // Barycentric coordinates
  41. float32 u = b2Dot(e, B - Q);
  42. float32 v = b2Dot(e, Q - A);
  43. float32 radius = edgeA->m_radius + circleB->m_radius;
  44. b2ContactFeature cf;
  45. cf.indexB = 0;
  46. cf.typeB = b2ContactFeature::e_vertex;
  47. // Region A
  48. if (v <= 0.0f)
  49. {
  50. b2Vec2 P = A;
  51. b2Vec2 d = Q - P;
  52. float32 dd = b2Dot(d, d);
  53. if (dd > radius * radius)
  54. {
  55. return;
  56. }
  57. // Is there an edge connected to A?
  58. if (edgeA->m_hasVertex0)
  59. {
  60. b2Vec2 A1 = edgeA->m_vertex0;
  61. b2Vec2 B1 = A;
  62. b2Vec2 e1 = B1 - A1;
  63. float32 u1 = b2Dot(e1, B1 - Q);
  64. // Is the circle in Region AB of the previous edge?
  65. if (u1 > 0.0f)
  66. {
  67. return;
  68. }
  69. }
  70. cf.indexA = 0;
  71. cf.typeA = b2ContactFeature::e_vertex;
  72. manifold->pointCount = 1;
  73. manifold->type = b2Manifold::e_circles;
  74. manifold->localNormal.SetZero();
  75. manifold->localPoint = P;
  76. manifold->points[0].id.key = 0;
  77. manifold->points[0].id.cf = cf;
  78. manifold->points[0].localPoint = circleB->m_p;
  79. return;
  80. }
  81. // Region B
  82. if (u <= 0.0f)
  83. {
  84. b2Vec2 P = B;
  85. b2Vec2 d = Q - P;
  86. float32 dd = b2Dot(d, d);
  87. if (dd > radius * radius)
  88. {
  89. return;
  90. }
  91. // Is there an edge connected to B?
  92. if (edgeA->m_hasVertex3)
  93. {
  94. b2Vec2 B2 = edgeA->m_vertex3;
  95. b2Vec2 A2 = B;
  96. b2Vec2 e2 = B2 - A2;
  97. float32 v2 = b2Dot(e2, Q - A2);
  98. // Is the circle in Region AB of the next edge?
  99. if (v2 > 0.0f)
  100. {
  101. return;
  102. }
  103. }
  104. cf.indexA = 1;
  105. cf.typeA = b2ContactFeature::e_vertex;
  106. manifold->pointCount = 1;
  107. manifold->type = b2Manifold::e_circles;
  108. manifold->localNormal.SetZero();
  109. manifold->localPoint = P;
  110. manifold->points[0].id.key = 0;
  111. manifold->points[0].id.cf = cf;
  112. manifold->points[0].localPoint = circleB->m_p;
  113. return;
  114. }
  115. // Region AB
  116. float32 den = b2Dot(e, e);
  117. b2Assert(den > 0.0f);
  118. b2Vec2 P = (1.0f / den) * (u * A + v * B);
  119. b2Vec2 d = Q - P;
  120. float32 dd = b2Dot(d, d);
  121. if (dd > radius * radius)
  122. {
  123. return;
  124. }
  125. b2Vec2 n(-e.y, e.x);
  126. if (b2Dot(n, Q - A) < 0.0f)
  127. {
  128. n.Set(-n.x, -n.y);
  129. }
  130. n.Normalize();
  131. cf.indexA = 0;
  132. cf.typeA = b2ContactFeature::e_face;
  133. manifold->pointCount = 1;
  134. manifold->type = b2Manifold::e_faceA;
  135. manifold->localNormal = n;
  136. manifold->localPoint = A;
  137. manifold->points[0].id.key = 0;
  138. manifold->points[0].id.cf = cf;
  139. manifold->points[0].localPoint = circleB->m_p;
  140. }
  141. struct b2EPAxis
  142. {
  143. enum Type
  144. {
  145. e_unknown,
  146. e_edgeA,
  147. e_edgeB
  148. };
  149. Type type;
  150. int32 index;
  151. float32 separation;
  152. };
  153. // Edge shape plus more stuff.
  154. struct b2FatEdge
  155. {
  156. b2Vec2 v0, v1, v2, v3;
  157. b2Vec2 normal;
  158. bool hasVertex0, hasVertex3;
  159. };
  160. // This lets us treate and edge shape and a polygon in the same
  161. // way in the SAT collider.
  162. struct b2EPProxy
  163. {
  164. b2Vec2 vertices[b2_maxPolygonVertices];
  165. b2Vec2 normals[b2_maxPolygonVertices];
  166. b2Vec2 centroid;
  167. int32 count;
  168. };
  169. // This class collides and edge and a polygon, taking into account edge adjacency.
  170. struct b2EPCollider
  171. {
  172. b2EPCollider(const b2EdgeShape* edgeA, const b2Transform& xfA,
  173. const b2PolygonShape* polygonB_in, const b2Transform& xfB);
  174. void Collide(b2Manifold* manifold);
  175. void ComputeAdjacency();
  176. b2EPAxis ComputeEdgeSeparation();
  177. b2EPAxis ComputePolygonSeparation();
  178. void FindIncidentEdge(b2ClipVertex c[2], const b2EPProxy* proxy1, int32 edge1, const b2EPProxy* proxy2);
  179. b2FatEdge m_edgeA;
  180. b2EPProxy m_proxyA, m_proxyB;
  181. b2Transform m_xf;
  182. b2Vec2 m_normal0, m_normal2;
  183. b2Vec2 m_limit11, m_limit12;
  184. b2Vec2 m_limit21, m_limit22;
  185. float32 m_radius;
  186. };
  187. b2EPCollider::b2EPCollider(const b2EdgeShape* edgeA, const b2Transform& xfA,
  188. const b2PolygonShape* polygonB, const b2Transform& xfB)
  189. {
  190. m_xf = b2MulT(xfA, xfB);
  191. // Edge geometry
  192. m_edgeA.v0 = edgeA->m_vertex0;
  193. m_edgeA.v1 = edgeA->m_vertex1;
  194. m_edgeA.v2 = edgeA->m_vertex2;
  195. m_edgeA.v3 = edgeA->m_vertex3;
  196. b2Vec2 e = m_edgeA.v2 - m_edgeA.v1;
  197. // Normal points outwards in CCW order.
  198. m_edgeA.normal.Set(e.y, -e.x);
  199. m_edgeA.normal.Normalize();
  200. m_edgeA.hasVertex0 = edgeA->m_hasVertex0;
  201. m_edgeA.hasVertex3 = edgeA->m_hasVertex3;
  202. // Proxy for edge
  203. m_proxyA.vertices[0] = m_edgeA.v1;
  204. m_proxyA.vertices[1] = m_edgeA.v2;
  205. m_proxyA.normals[0] = m_edgeA.normal;
  206. m_proxyA.normals[1] = -m_edgeA.normal;
  207. m_proxyA.centroid = 0.5f * (m_edgeA.v1 + m_edgeA.v2);
  208. m_proxyA.count = 2;
  209. // Proxy for polygon
  210. m_proxyB.count = polygonB->m_vertexCount;
  211. m_proxyB.centroid = b2Mul(m_xf, polygonB->m_centroid);
  212. for (int32 i = 0; i < polygonB->m_vertexCount; ++i)
  213. {
  214. m_proxyB.vertices[i] = b2Mul(m_xf, polygonB->m_vertices[i]);
  215. m_proxyB.normals[i] = b2Mul(m_xf.q, polygonB->m_normals[i]);
  216. }
  217. m_radius = 2.0f * b2_polygonRadius;
  218. m_limit11.SetZero();
  219. m_limit12.SetZero();
  220. m_limit21.SetZero();
  221. m_limit22.SetZero();
  222. }
  223. // Collide an edge and polygon. This uses the SAT and clipping to produce up to 2 contact points.
  224. // Edge adjacency is handle to produce locally valid contact points and normals. This is intended
  225. // to allow the polygon to slide smoothly over an edge chain.
  226. //
  227. // Algorithm
  228. // 1. Classify front-side or back-side collision with edge.
  229. // 2. Compute separation
  230. // 3. Process adjacent edges
  231. // 4. Classify adjacent edge as convex, flat, null, or concave
  232. // 5. Skip null or concave edges. Concave edges get a separate manifold.
  233. // 6. If the edge is flat, compute contact points as normal. Discard boundary points.
  234. // 7. If the edge is convex, compute it's separation.
  235. // 8. Use the minimum separation of up to three edges. If the minimum separation
  236. // is not the primary edge, return.
  237. // 9. If the minimum separation is the primary edge, compute the contact points and return.
  238. void b2EPCollider::Collide(b2Manifold* manifold)
  239. {
  240. manifold->pointCount = 0;
  241. ComputeAdjacency();
  242. b2EPAxis edgeAxis = ComputeEdgeSeparation();
  243. // If no valid normal can be found than this edge should not collide.
  244. // This can happen on the middle edge of a 3-edge zig-zag chain.
  245. if (edgeAxis.type == b2EPAxis::e_unknown)
  246. {
  247. return;
  248. }
  249. if (edgeAxis.separation > m_radius)
  250. {
  251. return;
  252. }
  253. b2EPAxis polygonAxis = ComputePolygonSeparation();
  254. if (polygonAxis.type != b2EPAxis::e_unknown && polygonAxis.separation > m_radius)
  255. {
  256. return;
  257. }
  258. // Use hysteresis for jitter reduction.
  259. const float32 k_relativeTol = 0.98f;
  260. const float32 k_absoluteTol = 0.001f;
  261. b2EPAxis primaryAxis;
  262. if (polygonAxis.type == b2EPAxis::e_unknown)
  263. {
  264. primaryAxis = edgeAxis;
  265. }
  266. else if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol)
  267. {
  268. primaryAxis = polygonAxis;
  269. }
  270. else
  271. {
  272. primaryAxis = edgeAxis;
  273. }
  274. b2EPProxy* proxy1;
  275. b2EPProxy* proxy2;
  276. b2ClipVertex incidentEdge[2];
  277. if (primaryAxis.type == b2EPAxis::e_edgeA)
  278. {
  279. proxy1 = &m_proxyA;
  280. proxy2 = &m_proxyB;
  281. manifold->type = b2Manifold::e_faceA;
  282. }
  283. else
  284. {
  285. proxy1 = &m_proxyB;
  286. proxy2 = &m_proxyA;
  287. manifold->type = b2Manifold::e_faceB;
  288. }
  289. int32 edge1 = primaryAxis.index;
  290. FindIncidentEdge(incidentEdge, proxy1, primaryAxis.index, proxy2);
  291. int32 count1 = proxy1->count;
  292. const b2Vec2* vertices1 = proxy1->vertices;
  293. int32 iv1 = edge1;
  294. int32 iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0;
  295. b2Vec2 v11 = vertices1[iv1];
  296. b2Vec2 v12 = vertices1[iv2];
  297. b2Vec2 tangent = v12 - v11;
  298. tangent.Normalize();
  299. b2Vec2 normal = b2Cross(tangent, 1.0f);
  300. b2Vec2 planePoint = 0.5f * (v11 + v12);
  301. // Face offset.
  302. float32 frontOffset = b2Dot(normal, v11);
  303. // Side offsets, extended by polytope skin thickness.
  304. float32 sideOffset1 = -b2Dot(tangent, v11) + m_radius;
  305. float32 sideOffset2 = b2Dot(tangent, v12) + m_radius;
  306. // Clip incident edge against extruded edge1 side edges.
  307. b2ClipVertex clipPoints1[2];
  308. b2ClipVertex clipPoints2[2];
  309. int np;
  310. // Clip to box side 1
  311. np = b2ClipSegmentToLine(clipPoints1, incidentEdge, -tangent, sideOffset1, iv1);
  312. if (np < b2_maxManifoldPoints)
  313. {
  314. return;
  315. }
  316. // Clip to negative box side 1
  317. np = b2ClipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2, iv2);
  318. if (np < b2_maxManifoldPoints)
  319. {
  320. return;
  321. }
  322. // Now clipPoints2 contains the clipped points.
  323. if (primaryAxis.type == b2EPAxis::e_edgeA)
  324. {
  325. manifold->localNormal = normal;
  326. manifold->localPoint = planePoint;
  327. }
  328. else
  329. {
  330. manifold->localNormal = b2MulT(m_xf.q, normal);
  331. manifold->localPoint = b2MulT(m_xf, planePoint);
  332. }
  333. int32 pointCount = 0;
  334. for (int32 i = 0; i < b2_maxManifoldPoints; ++i)
  335. {
  336. float32 separation;
  337. separation = b2Dot(normal, clipPoints2[i].v) - frontOffset;
  338. if (separation <= m_radius)
  339. {
  340. b2ManifoldPoint* cp = manifold->points + pointCount;
  341. if (primaryAxis.type == b2EPAxis::e_edgeA)
  342. {
  343. cp->localPoint = b2MulT(m_xf, clipPoints2[i].v);
  344. cp->id = clipPoints2[i].id;
  345. }
  346. else
  347. {
  348. cp->localPoint = clipPoints2[i].v;
  349. cp->id.cf.typeA = clipPoints2[i].id.cf.typeB;
  350. cp->id.cf.typeB = clipPoints2[i].id.cf.typeA;
  351. cp->id.cf.indexA = clipPoints2[i].id.cf.indexB;
  352. cp->id.cf.indexB = clipPoints2[i].id.cf.indexA;
  353. }
  354. ++pointCount;
  355. }
  356. }
  357. manifold->pointCount = pointCount;
  358. }
  359. // Compute allowable normal ranges based on adjacency.
  360. // A normal n is allowable iff:
  361. // cross(n, n1) >= 0.0f && cross(n2, n) >= 0.0f
  362. // n points from A to B (edge to polygon)
  363. void b2EPCollider::ComputeAdjacency()
  364. {
  365. b2Vec2 v0 = m_edgeA.v0;
  366. b2Vec2 v1 = m_edgeA.v1;
  367. b2Vec2 v2 = m_edgeA.v2;
  368. b2Vec2 v3 = m_edgeA.v3;
  369. // Determine allowable the normal regions based on adjacency.
  370. // Note: it may be possible that no normal is admissable.
  371. b2Vec2 centerB = m_proxyB.centroid;
  372. if (m_edgeA.hasVertex0)
  373. {
  374. b2Vec2 e0 = v1 - v0;
  375. b2Vec2 e1 = v2 - v1;
  376. b2Vec2 n0(e0.y, -e0.x);
  377. b2Vec2 n1(e1.y, -e1.x);
  378. n0.Normalize();
  379. n1.Normalize();
  380. bool convex = b2Cross(n0, n1) >= 0.0f;
  381. bool front0 = b2Dot(n0, centerB - v0) >= 0.0f;
  382. bool front1 = b2Dot(n1, centerB - v1) >= 0.0f;
  383. if (convex)
  384. {
  385. if (front0 || front1)
  386. {
  387. m_limit11 = n1;
  388. m_limit12 = n0;
  389. }
  390. else
  391. {
  392. m_limit11 = -n1;
  393. m_limit12 = -n0;
  394. }
  395. }
  396. else
  397. {
  398. if (front0 && front1)
  399. {
  400. m_limit11 = n0;
  401. m_limit12 = n1;
  402. }
  403. else
  404. {
  405. m_limit11 = -n0;
  406. m_limit12 = -n1;
  407. }
  408. }
  409. }
  410. else
  411. {
  412. m_limit11.SetZero();
  413. m_limit12.SetZero();
  414. }
  415. if (m_edgeA.hasVertex3)
  416. {
  417. b2Vec2 e1 = v2 - v1;
  418. b2Vec2 e2 = v3 - v2;
  419. b2Vec2 n1(e1.y, -e1.x);
  420. b2Vec2 n2(e2.y, -e2.x);
  421. n1.Normalize();
  422. n2.Normalize();
  423. bool convex = b2Cross(n1, n2) >= 0.0f;
  424. bool front1 = b2Dot(n1, centerB - v1) >= 0.0f;
  425. bool front2 = b2Dot(n2, centerB - v2) >= 0.0f;
  426. if (convex)
  427. {
  428. if (front1 || front2)
  429. {
  430. m_limit21 = n2;
  431. m_limit22 = n1;
  432. }
  433. else
  434. {
  435. m_limit21 = -n2;
  436. m_limit22 = -n1;
  437. }
  438. }
  439. else
  440. {
  441. if (front1 && front2)
  442. {
  443. m_limit21 = n1;
  444. m_limit22 = n2;
  445. }
  446. else
  447. {
  448. m_limit21 = -n1;
  449. m_limit22 = -n2;
  450. }
  451. }
  452. }
  453. else
  454. {
  455. m_limit21.SetZero();
  456. m_limit22.SetZero();
  457. }
  458. }
  459. b2EPAxis b2EPCollider::ComputeEdgeSeparation()
  460. {
  461. // EdgeA separation
  462. b2EPAxis bestAxis;
  463. bestAxis.type = b2EPAxis::e_unknown;
  464. bestAxis.index = -1;
  465. bestAxis.separation = -FLT_MAX;
  466. b2Vec2 normals[2] = {m_edgeA.normal, -m_edgeA.normal};
  467. for (int32 i = 0; i < 2; ++i)
  468. {
  469. b2Vec2 n = normals[i];
  470. // Adjacency
  471. bool valid1 = b2Cross(n, m_limit11) >= -b2_angularSlop && b2Cross(m_limit12, n) >= -b2_angularSlop;
  472. bool valid2 = b2Cross(n, m_limit21) >= -b2_angularSlop && b2Cross(m_limit22, n) >= -b2_angularSlop;
  473. if (valid1 == false || valid2 == false)
  474. {
  475. continue;
  476. }
  477. b2EPAxis axis;
  478. axis.type = b2EPAxis::e_edgeA;
  479. axis.index = i;
  480. axis.separation = FLT_MAX;
  481. for (int32 j = 0; j < m_proxyB.count; ++j)
  482. {
  483. float32 s = b2Dot(n, m_proxyB.vertices[j] - m_edgeA.v1);
  484. if (s < axis.separation)
  485. {
  486. axis.separation = s;
  487. }
  488. }
  489. if (axis.separation > m_radius)
  490. {
  491. return axis;
  492. }
  493. if (axis.separation > bestAxis.separation)
  494. {
  495. bestAxis = axis;
  496. }
  497. }
  498. return bestAxis;
  499. }
  500. b2EPAxis b2EPCollider::ComputePolygonSeparation()
  501. {
  502. b2EPAxis axis;
  503. axis.type = b2EPAxis::e_unknown;
  504. axis.index = -1;
  505. axis.separation = -FLT_MAX;
  506. for (int32 i = 0; i < m_proxyB.count; ++i)
  507. {
  508. b2Vec2 n = -m_proxyB.normals[i];
  509. // Adjacency
  510. bool valid1 = b2Cross(n, m_limit11) >= -b2_angularSlop && b2Cross(m_limit12, n) >= -b2_angularSlop;
  511. bool valid2 = b2Cross(n, m_limit21) >= -b2_angularSlop && b2Cross(m_limit22, n) >= -b2_angularSlop;
  512. if (valid1 == false && valid2 == false)
  513. {
  514. continue;
  515. }
  516. float32 s1 = b2Dot(n, m_proxyB.vertices[i] - m_edgeA.v1);
  517. float32 s2 = b2Dot(n, m_proxyB.vertices[i] - m_edgeA.v2);
  518. float32 s = b2Min(s1, s2);
  519. if (s > m_radius)
  520. {
  521. axis.type = b2EPAxis::e_edgeB;
  522. axis.index = i;
  523. axis.separation = s;
  524. }
  525. if (s > axis.separation)
  526. {
  527. axis.type = b2EPAxis::e_edgeB;
  528. axis.index = i;
  529. axis.separation = s;
  530. }
  531. }
  532. return axis;
  533. }
  534. void b2EPCollider::FindIncidentEdge(b2ClipVertex c[2], const b2EPProxy* proxy1, int32 edge1, const b2EPProxy* proxy2)
  535. {
  536. int32 count1 = proxy1->count;
  537. const b2Vec2* normals1 = proxy1->normals;
  538. int32 count2 = proxy2->count;
  539. const b2Vec2* vertices2 = proxy2->vertices;
  540. const b2Vec2* normals2 = proxy2->normals;
  541. b2Assert(0 <= edge1 && edge1 < count1);
  542. // Get the normal of the reference edge in proxy2's frame.
  543. b2Vec2 normal1 = normals1[edge1];
  544. // Find the incident edge on proxy2.
  545. int32 index = 0;
  546. float32 minDot = b2_maxFloat;
  547. for (int32 i = 0; i < count2; ++i)
  548. {
  549. float32 dot = b2Dot(normal1, normals2[i]);
  550. if (dot < minDot)
  551. {
  552. minDot = dot;
  553. index = i;
  554. }
  555. }
  556. // Build the clip vertices for the incident edge.
  557. int32 i1 = index;
  558. int32 i2 = i1 + 1 < count2 ? i1 + 1 : 0;
  559. c[0].v = vertices2[i1];
  560. c[0].id.cf.indexA = (uint8)edge1;
  561. c[0].id.cf.indexB = (uint8)i1;
  562. c[0].id.cf.typeA = b2ContactFeature::e_face;
  563. c[0].id.cf.typeB = b2ContactFeature::e_vertex;
  564. c[1].v = vertices2[i2];
  565. c[1].id.cf.indexA = (uint8)edge1;
  566. c[1].id.cf.indexB = (uint8)i2;
  567. c[1].id.cf.typeA = b2ContactFeature::e_face;
  568. c[1].id.cf.typeB = b2ContactFeature::e_vertex;
  569. }
  570. void b2CollideEdgeAndPolygon( b2Manifold* manifold,
  571. const b2EdgeShape* edgeA, const b2Transform& xfA,
  572. const b2PolygonShape* polygonB, const b2Transform& xfB)
  573. {
  574. b2EPCollider collider(edgeA, xfA, polygonB, xfB);
  575. collider.Collide(manifold);
  576. }