Skip to content

Commit c7d2cb1

Browse files
committed
Add methods intersect_plane and get_point to Ray (#6179)
Co-authored-by: devil-ira <[email protected]>
1 parent 9b72780 commit c7d2cb1

File tree

1 file changed

+54
-1
lines changed

1 file changed

+54
-1
lines changed

crates/bevy_math/src/ray.rs

Lines changed: 54 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,59 @@ use crate::Vec3;
66
pub struct Ray {
77
/// The origin of the ray.
88
pub origin: Vec3,
9-
/// The direction of the ray.
9+
/// A normalized vector representing the direction of the ray.
1010
pub direction: Vec3,
1111
}
12+
13+
impl Ray {
14+
/// Returns the distance to the plane if the ray intersects it.
15+
#[inline]
16+
pub fn intersect_plane(&self, plane_origin: Vec3, plane_normal: Vec3) -> Option<f32> {
17+
let denominator = plane_normal.dot(self.direction);
18+
if denominator.abs() > f32::EPSILON {
19+
let distance = (plane_origin - self.origin).dot(plane_normal) / denominator;
20+
if distance >= f32::EPSILON {
21+
return Some(distance);
22+
}
23+
}
24+
None
25+
}
26+
27+
/// Retrieve a point at the given distance along the ray.
28+
#[inline]
29+
pub fn get_point(&self, distance: f32) -> Vec3 {
30+
self.origin + self.direction * distance
31+
}
32+
}
33+
34+
#[cfg(test)]
35+
mod test {
36+
use super::*;
37+
38+
#[test]
39+
fn intersects_plane() {
40+
let ray = Ray {
41+
origin: Vec3::ZERO,
42+
direction: Vec3::Z,
43+
};
44+
45+
// Orthogonal, and test that plane_normal direction doesn't matter
46+
assert_eq!(Some(1.), ray.intersect_plane(Vec3::Z, Vec3::Z));
47+
assert_eq!(Some(1.), ray.intersect_plane(Vec3::Z, Vec3::NEG_Z));
48+
assert_eq!(None, ray.intersect_plane(Vec3::NEG_Z, Vec3::Z));
49+
assert_eq!(None, ray.intersect_plane(Vec3::NEG_Z, Vec3::NEG_Z));
50+
51+
// Diagonal
52+
assert_eq!(Some(1.), ray.intersect_plane(Vec3::Z, Vec3::ONE));
53+
assert_eq!(None, ray.intersect_plane(Vec3::NEG_Z, Vec3::ONE));
54+
55+
// Parralel
56+
assert_eq!(None, ray.intersect_plane(Vec3::X, Vec3::X));
57+
58+
// Parralel with simulated rounding error
59+
assert_eq!(
60+
None,
61+
ray.intersect_plane(Vec3::X, Vec3::X + Vec3::Z * f32::EPSILON)
62+
);
63+
}
64+
}

0 commit comments

Comments
 (0)