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