viewport_lib/geometry/
intersect.rs1pub fn ray_plane_intersection(
11 ray_origin: glam::Vec3,
12 ray_dir: glam::Vec3,
13 plane_normal: glam::Vec3,
14 plane_distance: f32,
15) -> Option<glam::Vec3> {
16 let denom = plane_normal.dot(ray_dir);
17 if denom.abs() < 1e-6 {
18 return None;
19 }
20 let t = -(plane_normal.dot(ray_origin) + plane_distance) / denom;
22 if t < 0.0 {
23 return None;
24 }
25 Some(ray_origin + ray_dir * t)
26}
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31
32 #[test]
33 fn ray_plane_intersection_hits() {
34 let origin = glam::Vec3::new(0.0, 5.0, 0.0);
36 let dir = glam::Vec3::new(0.0, -1.0, 0.0);
37 let hit = ray_plane_intersection(origin, dir, glam::Vec3::Y, -2.0);
38 assert!(hit.is_some());
39 let p = hit.unwrap();
40 assert!((p.y - 2.0).abs() < 1e-5);
41 }
42
43 #[test]
44 fn ray_plane_intersection_parallel_returns_none() {
45 let origin = glam::Vec3::new(0.0, 1.0, 0.0);
46 let dir = glam::Vec3::new(1.0, 0.0, 0.0);
47 assert!(ray_plane_intersection(origin, dir, glam::Vec3::Y, 0.0).is_none());
48 }
49
50 #[test]
51 fn ray_plane_intersection_behind_returns_none() {
52 let origin = glam::Vec3::new(0.0, 5.0, 0.0);
54 let dir = glam::Vec3::new(0.0, 1.0, 0.0);
55 assert!(ray_plane_intersection(origin, dir, glam::Vec3::Y, 0.0).is_none());
56 }
57}