raycast method
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;
}