vox_geometry_rust/
plane3.rs1use crate::surface3::*;
10use crate::vector3::Vector3D;
11use crate::transform3::Transform3;
12use crate::bounding_box3::BoundingBox3D;
13use crate::ray3::Ray3D;
14use std::sync::{RwLock, Arc};
15
16pub struct Plane3 {
23 pub normal: Vector3D,
25
26 pub point: Vector3D,
28
29 pub surface_data: Surface3Data,
31}
32
33impl Plane3 {
34 pub fn new_default(transform: Option<Transform3>,
36 is_normal_flipped: Option<bool>) -> Plane3 {
37 return Plane3 {
38 normal: Vector3D::new(0.0, 1.0, 0.0),
39 point: Vector3D::new_default(),
40 surface_data: Surface3Data::new(transform, is_normal_flipped),
41 };
42 }
43
44 pub fn new(normal: Vector3D,
46 point: Vector3D,
47 transform: Option<Transform3>,
48 is_normal_flipped: Option<bool>) -> Plane3 {
49 return Plane3 {
50 normal,
51 point,
52 surface_data: Surface3Data::new(transform, is_normal_flipped),
53 };
54 }
55
56 pub fn builder() -> Builder {
58 return Builder::new();
59 }
60}
61
62impl Surface3 for Plane3 {
63 fn closest_point_local(&self, other_point: &Vector3D) -> Vector3D {
64 let r = *other_point - self.point;
65 return r - self.normal * self.normal.dot(&r) + self.point;
66 }
67
68 fn bounding_box_local(&self) -> BoundingBox3D {
69 let eps = f64::EPSILON;
70 let dmax = f64::MAX;
71
72 return if f64::abs(self.normal.dot(&Vector3D::new(1.0, 0.0, 0.0)) - 1.0) < eps {
73 BoundingBox3D::new(self.point - Vector3D::new(0.0, dmax, dmax),
74 self.point + Vector3D::new(0.0, dmax, dmax))
75 } else if f64::abs(self.normal.dot(&Vector3D::new(0.0, 1.0, 0.0)) - 1.0) < eps {
76 BoundingBox3D::new(self.point - Vector3D::new(dmax, 0.0, dmax),
77 self.point + Vector3D::new(dmax, 0.0, dmax))
78 } else if f64::abs(self.normal.dot(&Vector3D::new(0.0, 0.0, 1.0)) - 1.0) < eps {
79 BoundingBox3D::new(self.point - Vector3D::new(dmax, dmax, 0.0),
80 self.point + Vector3D::new(dmax, dmax, 0.0))
81 } else {
82 BoundingBox3D::new(Vector3D::new(dmax, dmax, dmax),
83 Vector3D::new(dmax, dmax, dmax))
84 };
85 }
86
87 fn closest_intersection_local(&self, ray: &Ray3D) -> SurfaceRayIntersection3 {
88 let mut intersection = SurfaceRayIntersection3::new();
89 let d_dot_n = ray.direction.dot(&self.normal);
90
91 if f64::abs(d_dot_n) > 0.0 {
93 let t = self.normal.dot(&(self.point - ray.origin)) / d_dot_n;
94 if t >= 0.0 {
95 intersection.is_intersecting = true;
96 intersection.distance = t;
97 intersection.point = ray.point_at(t);
98 intersection.normal = self.normal;
99 }
100 }
101
102 return intersection;
103 }
104
105 fn closest_normal_local(&self, _other_point: &Vector3D) -> Vector3D {
106 return self.normal;
107 }
108
109 fn intersects_local(&self, ray_local: &Ray3D) -> bool {
110 return f64::abs(ray_local.direction.dot(&self.normal)) > 0.0;
111 }
112
113 fn view(&self) -> &Surface3Data {
114 return &self.surface_data;
115 }
116}
117
118pub type Plane3Ptr = Arc<RwLock<Plane3>>;
120
121pub struct Builder {
125 _normal: Vector3D,
126 _point: Vector3D,
127
128 _surface_data: Surface3Data,
129}
130
131impl Builder {
132 pub fn with_normal(&mut self, normal: Vector3D) -> &mut Self {
134 self._normal = normal;
135 return self;
136 }
137
138 pub fn with_point(&mut self, point: Vector3D) -> &mut Self {
140 self._point = point;
141 return self;
142 }
143
144 pub fn build(&mut self) -> Plane3 {
146 return Plane3::new(self._normal,
147 self._point,
148 Some(self._surface_data.transform.clone()),
149 Some(self._surface_data.is_normal_flipped),
150 );
151 }
152
153 pub fn make_shared(&mut self) -> Plane3Ptr {
155 return Plane3Ptr::new(RwLock::new(self.build()));
156 }
157
158 pub fn new() -> Builder {
160 return Builder {
161 _normal: Vector3D::new(0.0, 1.0, 0.0),
162 _point: Vector3D::new_default(),
163 _surface_data: Surface3Data::new(None, None),
164 };
165 }
166}
167
168impl SurfaceBuilderBase3 for Builder {
169 fn view(&mut self) -> &mut Surface3Data {
170 return &mut self._surface_data;
171 }
172}