1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
use 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>(
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>(
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> 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
}
}
}