b2CollideEdge.cpp 15 KB

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