parry3d/query/ray/
ray_halfspace.rs1use na;
2
3use crate::math::{Point, Real, Vector};
4use crate::query::{Ray, RayCast, RayIntersection};
5use crate::shape::{FeatureId, HalfSpace};
6
7#[inline]
9pub fn line_toi_with_halfspace(
10 halfspace_center: &Point<Real>,
11 halfspace_normal: &Vector<Real>,
12 line_origin: &Point<Real>,
13 line_dir: &Vector<Real>,
14) -> Option<Real> {
15 let dpos = *halfspace_center - *line_origin;
16 let denom = halfspace_normal.dot(line_dir);
17
18 if relative_eq!(denom, 0.0) {
19 None
20 } else {
21 Some(halfspace_normal.dot(&dpos) / denom)
22 }
23}
24
25#[inline]
27pub fn ray_toi_with_halfspace(
28 center: &Point<Real>,
29 normal: &Vector<Real>,
30 ray: &Ray,
31) -> Option<Real> {
32 if let Some(t) = line_toi_with_halfspace(center, normal, &ray.origin, &ray.dir) {
33 if t >= 0.0 {
34 return Some(t);
35 }
36 }
37
38 None
39}
40
41impl RayCast for HalfSpace {
42 #[inline]
43 fn cast_local_ray_and_get_normal(
44 &self,
45 ray: &Ray,
46 max_time_of_impact: Real,
47 solid: bool,
48 ) -> Option<RayIntersection> {
49 let dpos = -ray.origin;
50
51 let dot_normal_dpos = self.normal.dot(&dpos.coords);
52
53 if solid && dot_normal_dpos > 0.0 {
54 return Some(RayIntersection::new(0.0, na::zero(), FeatureId::Face(0)));
56 }
57
58 let t = dot_normal_dpos / self.normal.dot(&ray.dir);
59
60 if t >= 0.0 && t <= max_time_of_impact {
61 let n = if dot_normal_dpos > 0.0 {
62 -self.normal
63 } else {
64 self.normal
65 };
66
67 Some(RayIntersection::new(t, *n, FeatureId::Face(0)))
68 } else {
69 None
70 }
71 }
72}