collidePolygons method

void collidePolygons(
  1. Manifold manifold,
  2. PolygonShape polyA,
  3. Transform xfA,
  4. PolygonShape polyB,
  5. 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;
}