vox_geometry_rust/
box2.rs1use crate::surface2::*;
10use crate::vector2::Vector2D;
11use crate::transform2::Transform2;
12use crate::bounding_box2::BoundingBox2D;
13use crate::ray2::Ray2D;
14use crate::plane2::Plane2;
15use std::sync::{RwLock, Arc};
16
17pub struct Box2 {
25 bound: BoundingBox2D,
27
28 pub surface_data: Surface2Data,
30}
31
32impl Box2 {
33 pub fn new_default(transform: Option<Transform2>,
35 is_normal_flipped: Option<bool>) -> Box2 {
36 return Box2 {
37 bound: BoundingBox2D::new(Vector2D::new_default(), Vector2D::new(1.0, 1.0)),
38 surface_data: Surface2Data::new(transform, is_normal_flipped),
39 };
40 }
41
42 pub fn new(lower_corner: Vector2D,
44 upper_corner: Vector2D,
45 transform: Option<Transform2>,
46 is_normal_flipped: Option<bool>) -> Box2 {
47 return Box2 {
48 bound: BoundingBox2D::new(lower_corner, upper_corner),
49 surface_data: Surface2Data::new(transform, is_normal_flipped),
50 };
51 }
52 pub fn new_aabb(bounding_box: BoundingBox2D,
54 transform: Option<Transform2>,
55 is_normal_flipped: Option<bool>) -> Box2 {
56 return Box2 {
57 bound: bounding_box,
58 surface_data: Surface2Data::new(transform, is_normal_flipped),
59 };
60 }
61
62 pub fn builder() -> Builder {
64 return Builder::new();
65 }
66}
67
68impl Surface2 for Box2 {
69 fn closest_point_local(&self, other_point: &Vector2D) -> Vector2D {
70 return if self.bound.contains(&other_point) {
71 let planes = [Plane2::new(Vector2D::new(1.0, 0.0), self.bound.upper_corner, None, None),
72 Plane2::new(Vector2D::new(0.0, 1.0), self.bound.upper_corner, None, None),
73 Plane2::new(Vector2D::new(-1.0, 0.0), self.bound.lower_corner, None, None),
74 Plane2::new(Vector2D::new(0.0, -1.0), self.bound.lower_corner, None, None)];
75
76 let mut result = planes[0].closest_point(other_point);
77 let mut distance_squared = result.distance_squared_to(*other_point);
78
79 for i in 1..4 {
80 let local_result = planes[i].closest_point(other_point);
81 let local_distance_squared =
82 local_result.distance_squared_to(*other_point);
83
84 if local_distance_squared < distance_squared {
85 result = local_result;
86 distance_squared = local_distance_squared;
87 }
88 }
89
90 result
91 } else {
92 crate::vector2::clamp(&other_point, &self.bound.lower_corner, &self.bound.upper_corner)
93 };
94 }
95
96 fn bounding_box_local(&self) -> BoundingBox2D {
97 return self.bound.clone();
98 }
99
100 fn closest_intersection_local(&self, ray: &Ray2D) -> SurfaceRayIntersection2 {
101 let mut intersection = SurfaceRayIntersection2::new();
102 let bb_ray_intersection =
103 self.bound.closest_intersection(&ray);
104 intersection.is_intersecting = bb_ray_intersection.is_intersecting;
105 if intersection.is_intersecting {
106 intersection.distance = bb_ray_intersection.t_near;
107 intersection.point = ray.point_at(bb_ray_intersection.t_near);
108 intersection.normal = self.closest_normal_local(&intersection.point);
109 }
110 return intersection;
111 }
112
113 fn closest_normal_local(&self, other_point: &Vector2D) -> Vector2D {
114 let planes = [Plane2::new(Vector2D::new(1.0, 0.0), self.bound.upper_corner, None, None),
115 Plane2::new(Vector2D::new(0.0, 1.0), self.bound.upper_corner, None, None),
116 Plane2::new(Vector2D::new(-1.0, 0.0), self.bound.lower_corner, None, None),
117 Plane2::new(Vector2D::new(0.0, -1.0), self.bound.lower_corner, None, None)];
118
119 return if self.bound.contains(other_point) {
120 let mut closest_normal = planes[0].normal;
121 let closest_point = planes[0].closest_point(other_point);
122 let mut min_distance_squared = (closest_point - *other_point).length_squared();
123
124 for i in 1..4 {
125 let local_closest_point = planes[i].closest_point(other_point);
126 let local_distance_squared =
127 (local_closest_point - *other_point).length_squared();
128
129 if local_distance_squared < min_distance_squared {
130 closest_normal = planes[i].normal;
131 min_distance_squared = local_distance_squared;
132 }
133 }
134
135 closest_normal
136 } else {
137 let closest_point =
138 crate::vector2::clamp(&other_point, &self.bound.lower_corner, &self.bound.upper_corner);
139 let closest_point_to_input_point = *other_point - closest_point;
140 let mut closest_normal = planes[0].normal;
141 let mut max_cosine_angle = closest_normal.dot(&closest_point_to_input_point);
142
143 for i in 1..4 {
144 let cosine_angle = planes[i].normal.dot(&closest_point_to_input_point);
145
146 if cosine_angle > max_cosine_angle {
147 closest_normal = planes[i].normal;
148 max_cosine_angle = cosine_angle;
149 }
150 }
151
152 closest_normal
153 };
154 }
155
156 fn intersects_local(&self, ray_local: &Ray2D) -> bool {
157 return self.bound.intersects(ray_local);
158 }
159
160 fn view(&self) -> &Surface2Data {
161 return &self.surface_data;
162 }
163}
164
165pub type Box2Ptr = Arc<RwLock<Box2>>;
167
168pub struct Builder {
172 _lower_corner: Vector2D,
173 _upper_corner: Vector2D,
174
175 _surface_data: Surface2Data,
176}
177
178impl Builder {
179 pub fn with_lower_corner(&mut self, pt: Vector2D) -> &mut Self {
181 self._lower_corner = pt;
182 return self;
183 }
184
185 pub fn with_upper_corner(&mut self, pt: Vector2D) -> &mut Self {
187 self._upper_corner = pt;
188 return self;
189 }
190
191 pub fn with_bounding_box(&mut self, bbox: BoundingBox2D) -> &mut Self {
193 self._lower_corner = bbox.lower_corner;
194 self._upper_corner = bbox.upper_corner;
195 return self;
196 }
197
198 pub fn build(&mut self) -> Box2 {
200 return Box2::new_aabb(
201 BoundingBox2D::new(self._lower_corner, self._upper_corner),
202 Some(self._surface_data.transform.clone()),
203 Some(self._surface_data.is_normal_flipped),
204 );
205 }
206
207 pub fn make_shared(&mut self) -> Box2Ptr {
209 return Box2Ptr::new(RwLock::new(self.build()));
210 }
211
212 pub fn new() -> Builder {
214 return Builder {
215 _lower_corner: Vector2D::new_default(),
216 _upper_corner: Vector2D::new(1.0, 1.0),
217 _surface_data: Surface2Data::new(None, None),
218 };
219 }
220}
221
222impl SurfaceBuilderBase2 for Builder {
223 fn view(&mut self) -> &mut Surface2Data {
224 return &mut self._surface_data;
225 }
226}