ncollide3d/query/ray/
ray_plane.rsuse na::{self, RealField};
use crate::math::{Isometry, Point, Vector};
use crate::query::{Ray, RayCast, RayIntersection};
use crate::shape::{FeatureId, Plane};
#[inline]
pub fn line_toi_with_plane<N: RealField + Copy>(
plane_center: &Point<N>,
plane_normal: &Vector<N>,
line_origin: &Point<N>,
line_dir: &Vector<N>,
) -> Option<N> {
let dpos = *plane_center - *line_origin;
let denom = plane_normal.dot(line_dir);
if relative_eq!(denom, N::zero()) {
None
} else {
Some(plane_normal.dot(&dpos) / denom)
}
}
#[inline]
pub fn ray_toi_with_plane<N: RealField + Copy>(
center: &Point<N>,
normal: &Vector<N>,
ray: &Ray<N>,
) -> Option<N> {
if let Some(t) = line_toi_with_plane(center, normal, &ray.origin, &ray.dir) {
if t >= na::zero() {
return Some(t);
}
}
None
}
impl<N: RealField + Copy> RayCast<N> for Plane<N> {
#[inline]
fn toi_and_normal_with_ray(
&self,
m: &Isometry<N>,
ray: &Ray<N>,
max_toi: N,
solid: bool,
) -> Option<RayIntersection<N>> {
let ls_ray = ray.inverse_transform_by(m);
let dpos = -ls_ray.origin;
let dot_normal_dpos = self.normal.dot(&dpos.coords);
if solid && dot_normal_dpos > na::zero() {
return Some(RayIntersection::new(
na::zero(),
na::zero(),
FeatureId::Face(0),
));
}
let t = dot_normal_dpos / self.normal.dot(&ls_ray.dir);
if t >= na::zero() && t <= max_toi {
let n = if dot_normal_dpos > na::zero() {
-self.normal
} else {
self.normal
};
Some(RayIntersection::new(t, m * *n, FeatureId::Face(0)))
} else {
None
}
}
}