rayIntersection method
RaycastResult<ShapeHitbox> ?
rayIntersection(
- Ray2 ray, {
- RaycastResult<
ShapeHitbox> ? out,
override
Returns information about how the ray intersects the shape.
If you are only interested in the intersection point use RaycastResult.intersectionPoint of the result.
Implementation
@override
RaycastResult<ShapeHitbox>? rayIntersection(
Ray2 ray, {
RaycastResult<ShapeHitbox>? out,
}) {
var isInsideHitbox = false;
_temporaryLineSegment.from.setFrom(ray.origin);
// Adding a small value to the origin to avoid the ray to be on the edge
// of the circle and then directly intersecting and causing the reflecting
// ray to go in the wrong direction.
_temporaryOrigin.setValues(
ray.origin.x + ray.direction.x * 0.00001,
ray.origin.y + ray.direction.y * 0.00001,
);
_temporaryAbsoluteCenter.setFrom(absoluteCenter);
_temporaryCenter
..setFrom(_temporaryAbsoluteCenter)
..sub(ray.origin);
if (_temporaryCenter.isZero()) {
// If _temporaryCenter is zero, it's projection onto ray.direction
// will be zero. In that case, directly use ray.direction as temp
// end point of line segment.
_temporaryLineSegment.to.setFrom(ray.direction);
} else {
_temporaryCenter.projection(ray.direction, out: _temporaryLineSegment.to);
_temporaryLineSegment.to
..x *= (ray.direction.x.sign * _temporaryLineSegment.to.x.sign)
..y *= (ray.direction.y.sign * _temporaryLineSegment.to.y.sign);
}
if (_temporaryOrigin.distanceToSquared(_temporaryAbsoluteCenter) <
radius * radius) {
_temporaryLineSegment.to.scaleTo(2 * radius);
isInsideHitbox = true;
}
_temporaryLineSegment.to.add(ray.origin);
final intersections = lineSegmentIntersections(_temporaryLineSegment).where(
(i) => i.distanceToSquared(ray.origin) > 0.0000001,
);
if (intersections.isEmpty) {
out?.reset();
return null;
} else {
final result = out ?? RaycastResult();
final intersectionPoint = intersections.first;
_temporaryNormal
..setFrom(intersectionPoint)
..sub(_temporaryAbsoluteCenter)
..normalize();
if (isInsideHitbox) {
_temporaryNormal.invert();
}
final reflectionDirection =
(out?.reflectionRay?.direction ?? Vector2.zero())
..setFrom(ray.direction)
..reflect(_temporaryNormal);
final reflectionRay = (out?.reflectionRay
?..setWith(
origin: intersectionPoint,
direction: reflectionDirection,
)) ??
Ray2(
origin: intersectionPoint,
direction: reflectionDirection,
);
result.setWith(
hitbox: this,
reflectionRay: reflectionRay,
normal: _temporaryNormal,
distance: ray.origin.distanceTo(intersectionPoint),
isInsideHitbox: isInsideHitbox,
);
return result;
}
}