ncollide3d/query/ray/
ray_plane.rs

1use na::{self, RealField};
2
3use crate::math::{Isometry, Point, Vector};
4use crate::query::{Ray, RayCast, RayIntersection};
5use crate::shape::{FeatureId, Plane};
6
7/// Computes the toi of an unbounded line with a plane described by its center and normal.
8#[inline]
9pub fn line_toi_with_plane<N: RealField + Copy>(
10    plane_center: &Point<N>,
11    plane_normal: &Vector<N>,
12    line_origin: &Point<N>,
13    line_dir: &Vector<N>,
14) -> Option<N> {
15    let dpos = *plane_center - *line_origin;
16    let denom = plane_normal.dot(line_dir);
17
18    if relative_eq!(denom, N::zero()) {
19        None
20    } else {
21        Some(plane_normal.dot(&dpos) / denom)
22    }
23}
24
25/// Computes the toi of a ray with a plane described by its center and normal.
26#[inline]
27pub fn ray_toi_with_plane<N: RealField + Copy>(
28    center: &Point<N>,
29    normal: &Vector<N>,
30    ray: &Ray<N>,
31) -> Option<N> {
32    if let Some(t) = line_toi_with_plane(center, normal, &ray.origin, &ray.dir) {
33        if t >= na::zero() {
34            return Some(t);
35        }
36    }
37
38    None
39}
40
41impl<N: RealField + Copy> RayCast<N> for Plane<N> {
42    #[inline]
43    fn toi_and_normal_with_ray(
44        &self,
45        m: &Isometry<N>,
46        ray: &Ray<N>,
47        max_toi: N,
48        solid: bool,
49    ) -> Option<RayIntersection<N>> {
50        let ls_ray = ray.inverse_transform_by(m);
51
52        let dpos = -ls_ray.origin;
53
54        let dot_normal_dpos = self.normal.dot(&dpos.coords);
55
56        if solid && dot_normal_dpos > na::zero() {
57            // The ray is inside of the solid half-space.
58            return Some(RayIntersection::new(
59                na::zero(),
60                na::zero(),
61                FeatureId::Face(0),
62            ));
63        }
64
65        let t = dot_normal_dpos / self.normal.dot(&ls_ray.dir);
66
67        if t >= na::zero() && t <= max_toi {
68            let n = if dot_normal_dpos > na::zero() {
69                -self.normal
70            } else {
71                self.normal
72            };
73
74            Some(RayIntersection::new(t, m * *n, FeatureId::Face(0)))
75        } else {
76            None
77        }
78    }
79}