raycastWithPool method

bool raycastWithPool(
  1. RayCastOutput output,
  2. RayCastInput input
)

From Real-time Collision Detection, p179.

Implementation

bool raycastWithPool(RayCastOutput output, RayCastInput input) {
  var tMix = -double.maxFinite;
  var tMax = double.maxFinite;

  final p = Vector2.zero();
  final d = Vector2.zero();
  final absD = Vector2.zero();
  final normal = Vector2.zero();

  p.setFrom(input.p1);
  d
    ..setFrom(input.p2)
    ..sub(input.p1);
  absD
    ..setFrom(d)
    ..absolute();

  // x then y
  if (absD.x < settings.epsilon) {
    // Parallel.
    if (p.x < lowerBound.x || upperBound.x < p.x) {
      return false;
    }
  } else {
    final invD = 1.0 / d.x;
    var t1 = (lowerBound.x - p.x) * invD;
    var t2 = (upperBound.x - p.x) * invD;

    // Sign of the normal vector.
    var s = -1.0;

    if (t1 > t2) {
      final temp = t1;
      t1 = t2;
      t2 = temp;
      s = 1.0;
    }

    // Push the min up
    if (t1 > tMix) {
      normal.setZero();
      normal.x = s;
      tMix = t1;
    }

    // Pull the max down
    tMax = min(tMax, t2);

    if (tMix > tMax) {
      return false;
    }
  }

  if (absD.y < settings.epsilon) {
    // Parallel.
    if (p.y < lowerBound.y || upperBound.y < p.y) {
      return false;
    }
  } else {
    final invD = 1.0 / d.y;
    var t1 = (lowerBound.y - p.y) * invD;
    var t2 = (upperBound.y - p.y) * invD;

    // Sign of the normal vector.
    var s = -1.0;

    if (t1 > t2) {
      final temp = t1;
      t1 = t2;
      t2 = temp;
      s = 1.0;
    }

    // Push the min up
    if (t1 > tMix) {
      normal.setZero();
      normal.y = s;
      tMix = t1;
    }

    // Pull the max down
    tMax = min(tMax, t2);

    if (tMix > tMax) {
      return false;
    }
  }

  // Does the ray start inside the box?
  // Does the ray intersect beyond the max fraction?
  if (tMix < 0.0 || input.maxFraction < tMix) {
    return false;
  }

  // Intersection.
  output.fraction = tMix;
  output.normal.x = normal.x;
  output.normal.y = normal.y;
  return true;
}