1use super::*;
2
3#[derive(Copy, Clone, Debug, Eq, PartialEq)]
5#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
6#[repr(C)]
7pub struct Plane<T> {
8 pub normal: Vec3<T>,
10 pub distance: T,
12}
13
14#[allow(non_snake_case)]
16#[inline]
17pub fn Plane<T>(normal: Vec3<T>, distance: T) -> Plane<T> {
18 Plane { normal, distance }
19}
20
21#[cfg(feature = "dataview")]
22unsafe impl<T: dataview::Pod> dataview::Pod for Plane<T> {}
23
24impl<T> Plane<T> {
25 #[inline]
27 pub const fn new(normal: Vec3<T>, distance: T) -> Plane<T> {
28 Plane { normal, distance }
29 }
30
31 #[inline]
33 pub fn from_point(normal: Vec3<T>, pt: Point3<T>) -> Plane<T> where T: Float {
34 let distance = -normal.dot(pt);
35 Plane { normal, distance }
36 }
37
38 #[inline]
42 pub fn from_points(pt1: Point3<T>, pt2: Point3<T>, pt3: Point3<T>) -> Plane<T> where T: Float {
43 let normal = (pt2 - pt1).cross(pt3 - pt1).normalize();
44 let distance = -normal.dot(pt1);
45 Plane { normal, distance }
46 }
47}
48
49impl<T: Float> Plane<T> {
50 #[inline]
60 pub fn project_point(&self, pt: Point3<T>) -> Point3<T> {
61 pt - self.normal * self.distance_to_point(pt)
62 }
63
64 #[inline]
74 pub fn distance_to_point(&self, pt: Point3<T>) -> T {
75 self.normal.dot(pt) + self.distance
76 }
77}
78
79impl<T: Float> TraceRay<T> for Plane<T> {
82 fn inside(&self, ray: &Ray<T>) -> bool {
83 self.normal.dot(ray.origin) + self.distance <= T::ZERO
84 }
85
86 fn trace(&self, ray: &Ray<T>, hits: &mut [TraceHit<T>]) -> usize {
87 let denom = self.normal.dot(ray.direction);
88 if denom.abs() < T::EPSILON {
89 return 0;
90 }
91
92 let distance = -self.normal.dot(ray.origin) / denom;
93 if distance < T::ZERO {
94 return 0;
95 }
96
97 if let Some(hit) = hits.get_mut(0) {
98 *hit = TraceHit { distance, normal: self.normal };
99 }
100
101 return 1;
102 }
103}