diff --git a/crates/bevy_math/src/ray.rs b/crates/bevy_math/src/ray.rs index 5fe9c3740a846..0240ba2a71353 100644 --- a/crates/bevy_math/src/ray.rs +++ b/crates/bevy_math/src/ray.rs @@ -29,19 +29,21 @@ pub struct Ray2d { } impl Ray2d { - /// Create a new `Ray2d` from a given origin and direction + /// Creates a new `Ray2d` from a given origin and direction #[inline] pub const fn new(origin: Vec2, direction: Dir2) -> Self { Self { origin, direction } } - /// Get a point at a given distance along the ray + /// Returns the point at a given distance along the ray. #[inline] pub fn get_point(&self, distance: f32) -> Vec2 { self.origin + *self.direction * distance } - /// Get the distance to a plane if the ray intersects it + /// Returns the distance to a plane if the ray intersects it. + /// + /// Use [`Ray2d::plane_intersection_point`] to get the intersection point directly. #[inline] pub fn intersect_plane(&self, plane_origin: Vec2, plane: Plane2d) -> Option { let denominator = plane.normal.dot(*self.direction); @@ -53,6 +55,15 @@ impl Ray2d { } None } + + /// Returns the intersection point with a plane, if it exists. + /// + /// Calls [`Ray2d::get_point`] on the result of [`Ray2d::intersect_plane`]. + #[inline] + pub fn plane_intersection_point(&self, plane_origin: Vec2, plane: Plane2d) -> Option { + self.intersect_plane(plane_origin, plane) + .map(|distance| self.get_point(distance)) + } } /// An infinite half-line starting at `origin` and going in `direction` in 3D space. @@ -75,19 +86,21 @@ pub struct Ray3d { } impl Ray3d { - /// Create a new `Ray3d` from a given origin and direction + /// Creates a new `Ray3d` from a given origin and direction #[inline] pub const fn new(origin: Vec3, direction: Dir3) -> Self { Self { origin, direction } } - /// Get a point at a given distance along the ray + /// Returns the point at a given distance along the ray #[inline] pub fn get_point(&self, distance: f32) -> Vec3 { self.origin + *self.direction * distance } - /// Get the distance to a plane if the ray intersects it + /// Returns the distance to a plane if the ray intersects it + /// + /// Use [`Ray3d::plane_intersection_point`] to get the intersection point directly. #[inline] pub fn intersect_plane(&self, plane_origin: Vec3, plane: InfinitePlane3d) -> Option { let denominator = plane.normal.dot(*self.direction); @@ -99,6 +112,19 @@ impl Ray3d { } None } + + /// Returns the intersection point of the ray with a plane, if it exists. + /// + /// Calls [`Ray3d::get_point`] on the result of [`Ray3d::intersect_plane`]. + #[inline] + pub fn plane_intersection_point( + &self, + plane_origin: Vec3, + plane: InfinitePlane3d, + ) -> Option { + self.intersect_plane(plane_origin, plane) + .map(|distance| self.get_point(distance)) + } } #[cfg(test)] diff --git a/examples/3d/3d_viewport_to_world.rs b/examples/3d/3d_viewport_to_world.rs index 883121779a635..231306bd2b6dc 100644 --- a/examples/3d/3d_viewport_to_world.rs +++ b/examples/3d/3d_viewport_to_world.rs @@ -21,12 +21,9 @@ fn draw_cursor( if let Some(cursor_position) = window.cursor_position() // Calculate a ray pointing from the camera into the world based on the cursor's position. && let Ok(ray) = camera.viewport_to_world(camera_transform, cursor_position) - // Calculate if and at what distance the ray is hitting the ground plane. - && let Some(distance) = - ray.intersect_plane(ground.translation(), InfinitePlane3d::new(ground.up())) + // Calculate if and where the ray is hitting the ground plane. + && let Some(point) = ray.plane_intersection_point(ground.translation(), InfinitePlane3d::new(ground.up())) { - let point = ray.get_point(distance); - // Draw a circle just above the ground plane at that position. gizmos.circle( Isometry3d::new( diff --git a/examples/3d/irradiance_volumes.rs b/examples/3d/irradiance_volumes.rs index 257cfb7354648..1937dc3f2e754 100644 --- a/examples/3d/irradiance_volumes.rs +++ b/examples/3d/irradiance_volumes.rs @@ -466,11 +466,11 @@ fn handle_mouse_clicks( let Ok(ray) = camera.viewport_to_world(camera_transform, mouse_position) else { return; }; - let Some(ray_distance) = ray.intersect_plane(Vec3::ZERO, InfinitePlane3d::new(Vec3::Y)) else { + let Some(plane_intersection) = + ray.plane_intersection_point(Vec3::ZERO, InfinitePlane3d::new(Vec3::Y)) + else { return; }; - let plane_intersection = ray.origin + ray.direction.normalize() * ray_distance; - // Move all the main objects. for mut transform in main_objects.iter_mut() { transform.translation = vec3(