collidePolygons method
void
collidePolygons(
- Manifold manifold,
- PolygonShape polyA,
- Transform xfA,
- PolygonShape polyB,
- Transform xfB,
Compute the collision manifold between two polygons.
Implementation
void collidePolygons(
Manifold manifold,
PolygonShape polyA,
Transform xfA,
PolygonShape polyB,
Transform xfB,
) {
// - Find edge normal of max separation on A - return if separating axis is
// found
// - Find edge normal of max separation on B - return if separation axis is
// found
// - Choose reference edge as min(minA, minB)
// - Find incident edge
// - Clip
// The normal points from 1 to 2
manifold.pointCount = 0;
final totalRadius = polyA.radius + polyB.radius;
findMaxSeparation(_results1, polyA, xfA, polyB, xfB);
if (_results1.separation > totalRadius) {
return;
}
findMaxSeparation(results2, polyB, xfB, polyA, xfA);
if (results2.separation > totalRadius) {
return;
}
PolygonShape poly1; // reference polygon
PolygonShape poly2; // incident polygon
Transform xf1;
Transform xf2;
int edge1; // reference edge
bool flip;
final kTol = 0.1 * settings.linearSlop;
if (results2.separation > _results1.separation + kTol) {
poly1 = polyB;
poly2 = polyA;
xf1 = xfB;
xf2 = xfA;
edge1 = results2.edgeIndex;
manifold.type = ManifoldType.faceB;
flip = true;
} else {
poly1 = polyA;
poly2 = polyB;
xf1 = xfA;
xf2 = xfB;
edge1 = _results1.edgeIndex;
manifold.type = ManifoldType.faceA;
flip = false;
}
final xf1q = xf1.q;
findIncidentEdge(_incidentEdge, poly1, xf1, edge1, poly2, xf2);
final count1 = poly1.vertices.length;
final vertices1 = poly1.vertices;
final iv1 = edge1;
final iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0;
_v11.setFrom(vertices1[iv1]);
_v12.setFrom(vertices1[iv2]);
_localTangent.x = _v12.x - _v11.x;
_localTangent.y = _v12.y - _v11.y;
_localTangent.normalize();
_localNormal.x = 1.0 * _localTangent.y;
_localNormal.y = -1.0 * _localTangent.x;
_planePoint.x = (_v11.x + _v12.x) * .5;
_planePoint.y = (_v11.y + _v12.y) * .5;
_tangent.x = xf1q.cos * _localTangent.x - xf1q.sin * _localTangent.y;
_tangent.y = xf1q.sin * _localTangent.x + xf1q.cos * _localTangent.y;
final normalx = 1.0 * _tangent.y;
final normaly = -1.0 * _tangent.x;
_v11.setFrom(Transform.mulVec2(xf1, _v11));
_v12.setFrom(Transform.mulVec2(xf1, _v12));
// Face offset
final frontOffset = normalx * _v11.x + normaly * _v11.y;
// Side offsets, extended by polytope skin thickness.
final sideOffset1 =
-(_tangent.x * _v11.x + _tangent.y * _v11.y) + totalRadius;
final sideOffset2 = _tangent.x * _v12.x + _tangent.y * _v12.y + totalRadius;
_tangent.negate();
// Clip to box side 1
if (clipSegmentToLine(
_clipPoints1,
_incidentEdge,
_tangent,
sideOffset1,
iv1,
) <
2) {
return;
}
_tangent.negate();
// Clip to negative box side 1
if (clipSegmentToLine(
_clipPoints2,
_clipPoints1,
_tangent,
sideOffset2,
iv2,
) <
2) {
return;
}
// Now _clipPoints2 contains the clipped points.
manifold.localNormal.setFrom(_localNormal);
manifold.localPoint.setFrom(_planePoint);
var pointCount = 0;
for (var i = 0; i < settings.maxManifoldPoints; ++i) {
final separation = normalx * _clipPoints2[i].v.x +
normaly * _clipPoints2[i].v.y -
frontOffset;
if (separation <= totalRadius) {
final cp = manifold.points[pointCount];
final out = cp.localPoint;
final px = _clipPoints2[i].v.x - xf2.p.x;
final py = _clipPoints2[i].v.y - xf2.p.y;
out.x = xf2.q.cos * px + xf2.q.sin * py;
out.y = -xf2.q.sin * px + xf2.q.cos * py;
cp.id.set(_clipPoints2[i].id);
if (flip) {
// Swap features
cp.id.flip();
}
++pointCount;
}
}
manifold.pointCount = pointCount;
}