trace method
Trace ray through the world, bouncing off reflective surfaces.
filterTag — when non-null only entities with a matching
RaycastColliderComponent.tag are considered at each segment.
Implementation
RayTrace trace(Ray ray, {String? filterTag}) {
final segments = <RayTraceSegment>[];
var currentRay = ray;
for (int bounce = 0; bounce <= maxBounces; bounce++) {
final hit = raycastSystem.castRay(currentRay, filterTag: filterTag);
if (hit == null) {
// Ray reached max distance without hitting anything.
segments.add(
RayTraceSegment(
from: currentRay.origin,
to: currentRay.at(currentRay.maxDistance),
),
);
break;
}
segments.add(
RayTraceSegment(from: currentRay.origin, to: hit.point, hit: hit),
);
final collider = hit.entity.getComponent<RaycastColliderComponent>()!;
// Terminate if the surface is non-reflective or we've used all bounces.
if (!collider.isReflective ||
collider.reflectivity < minReflectivity ||
bounce == maxBounces) {
break;
}
// Reflect direction: r = d - 2(d·n)n
final d = currentRay.direction;
final n = hit.normal;
final dDotN = d.dx * n.dx + d.dy * n.dy;
final reflected = d - Offset(n.dx * 2.0 * dDotN, n.dy * 2.0 * dDotN);
// Advance the origin slightly past the hit point to avoid self-intersection.
currentRay = Ray(
origin: hit.point + reflected * 1.0,
direction: reflected,
maxDistance: currentRay.maxDistance * collider.reflectivity,
);
}
return RayTrace(segments: segments);
}