raycast method

  1. @override
bool raycast(
  1. RayCastOutput output,
  2. RayCastInput input,
  3. Transform xf,
  4. int childIndex,
)
override

Cast a ray against a child shape.

output is the ray-cast results. input the ray-cast input parameters. transform to be applied to the shape. childIndex the child shape index Returns true if the child shape is hit.

Implementation

@override
bool raycast(
  RayCastOutput output,
  RayCastInput input,
  Transform xf,
  int childIndex,
) {
  final xfqc = xf.q.cos;
  final xfqs = xf.q.sin;
  final xfp = xf.p;
  var tempX = input.p1.x - xfp.x;
  var tempY = input.p1.y - xfp.y;
  final p1x = xfqc * tempX + xfqs * tempY;
  final p1y = -xfqs * tempX + xfqc * tempY;

  tempX = input.p2.x - xfp.x;
  tempY = input.p2.y - xfp.y;
  final p2x = xfqc * tempX + xfqs * tempY;
  final p2y = -xfqs * tempX + xfqc * tempY;

  final dx = p2x - p1x;
  final dy = p2y - p1y;

  var lower = 0.0;
  var upper = input.maxFraction;

  var index = -1;

  for (var i = 0; i < vertices.length; ++i) {
    final normal = normals[i];
    final vertex = vertices[i];
    final tempX = vertex.x - p1x;
    final tempY = vertex.y - p1y;
    final numerator = normal.x * tempX + normal.y * tempY;
    final denominator = normal.x * dx + normal.y * dy;

    if (denominator == 0.0) {
      if (numerator < 0.0) {
        return false;
      }
    } else {
      // Note: we want this predicate without division:
      // lower < numerator / denominator, where denominator < 0
      // Since denominator < 0, we have to flip the inequality:
      // lower < numerator / denominator <==> denominator * lower >
      // numerator.
      if (denominator < 0.0 && numerator < lower * denominator) {
        // Increase lower.
        // The segment enters this half-space.
        lower = numerator / denominator;
        index = i;
      } else if (denominator > 0.0 && numerator < upper * denominator) {
        // Decrease upper.
        // The segment exits this half-space.
        upper = numerator / denominator;
      }
    }

    if (upper < lower) {
      return false;
    }
  }

  assert(0.0 <= lower && lower <= input.maxFraction);

  if (index >= 0) {
    output.fraction = lower;
    final normal = normals[index];
    final out = output.normal;
    out.x = xfqc * normal.x - xfqs * normal.y;
    out.y = xfqs * normal.x + xfqc * normal.y;
    return true;
  }
  return false;
}