1use super::types::{
4 BoxHull, HullData, HullFace, HullHalfEdge, HullVertex, BOX_HULL_SIZE, HULL_VERSION,
5};
6use crate::constants::linear_slop;
7use crate::core::{hash, non_zero_hash, HASH_INIT};
8use crate::math_functions::{
9 aabb_transform, abs, box_inertia, inv_rotate_vector, make_matrix_from_quat,
10 make_plane_from_normal_and_point, make_quat_from_matrix, max, min, min_float, mul, mul_sv, neg,
11 normalize, rotate_inertia, rotate_vector, transform_plane, transform_point, Aabb, Transform,
12 Vec3, QUAT_IDENTITY, TRANSFORM_IDENTITY, VEC3_AXIS_X, VEC3_AXIS_Y, VEC3_AXIS_Z, VEC3_ZERO,
13};
14
15fn box_hull_template() -> BoxHull {
16 let edges: [HullHalfEdge; 24] = [
17 HullHalfEdge {
18 next: 2,
19 twin: 1,
20 origin: 2,
21 face: 0,
22 },
23 HullHalfEdge {
24 next: 17,
25 twin: 0,
26 origin: 1,
27 face: 5,
28 },
29 HullHalfEdge {
30 next: 4,
31 twin: 3,
32 origin: 1,
33 face: 0,
34 },
35 HullHalfEdge {
36 next: 20,
37 twin: 2,
38 origin: 5,
39 face: 3,
40 },
41 HullHalfEdge {
42 next: 6,
43 twin: 5,
44 origin: 5,
45 face: 0,
46 },
47 HullHalfEdge {
48 next: 23,
49 twin: 4,
50 origin: 6,
51 face: 4,
52 },
53 HullHalfEdge {
54 next: 0,
55 twin: 7,
56 origin: 6,
57 face: 0,
58 },
59 HullHalfEdge {
60 next: 18,
61 twin: 6,
62 origin: 2,
63 face: 2,
64 },
65 HullHalfEdge {
66 next: 10,
67 twin: 9,
68 origin: 0,
69 face: 1,
70 },
71 HullHalfEdge {
72 next: 21,
73 twin: 8,
74 origin: 3,
75 face: 5,
76 },
77 HullHalfEdge {
78 next: 12,
79 twin: 11,
80 origin: 3,
81 face: 1,
82 },
83 HullHalfEdge {
84 next: 16,
85 twin: 10,
86 origin: 7,
87 face: 2,
88 },
89 HullHalfEdge {
90 next: 14,
91 twin: 13,
92 origin: 7,
93 face: 1,
94 },
95 HullHalfEdge {
96 next: 19,
97 twin: 12,
98 origin: 4,
99 face: 4,
100 },
101 HullHalfEdge {
102 next: 8,
103 twin: 15,
104 origin: 4,
105 face: 1,
106 },
107 HullHalfEdge {
108 next: 22,
109 twin: 14,
110 origin: 0,
111 face: 3,
112 },
113 HullHalfEdge {
114 next: 7,
115 twin: 17,
116 origin: 3,
117 face: 2,
118 },
119 HullHalfEdge {
120 next: 9,
121 twin: 16,
122 origin: 2,
123 face: 5,
124 },
125 HullHalfEdge {
126 next: 11,
127 twin: 19,
128 origin: 6,
129 face: 2,
130 },
131 HullHalfEdge {
132 next: 5,
133 twin: 18,
134 origin: 7,
135 face: 4,
136 },
137 HullHalfEdge {
138 next: 15,
139 twin: 21,
140 origin: 1,
141 face: 3,
142 },
143 HullHalfEdge {
144 next: 1,
145 twin: 20,
146 origin: 0,
147 face: 5,
148 },
149 HullHalfEdge {
150 next: 3,
151 twin: 23,
152 origin: 4,
153 face: 3,
154 },
155 HullHalfEdge {
156 next: 13,
157 twin: 22,
158 origin: 5,
159 face: 4,
160 },
161 ];
162
163 let vertex_offset = 136;
165 let point_offset = 144;
166 let edge_offset = 240;
167 let face_offset = 336;
168 let plane_offset = 344;
169
170 BoxHull {
171 base: HullData {
172 version: HULL_VERSION,
173 byte_count: BOX_HULL_SIZE as i32,
174 hash: 0,
175 aabb: Aabb::default(),
176 surface_area: 0.0,
177 volume: 0.0,
178 inner_radius: 0.0,
179 center: VEC3_ZERO,
180 central_inertia: crate::math_functions::MAT3_ZERO,
181 vertex_count: 8,
182 vertex_offset,
183 point_offset,
184 edge_count: 24,
185 edge_offset,
186 face_count: 6,
187 face_offset,
188 plane_offset,
189 padding: 0,
190 vertices: Vec::new(),
191 points: Vec::new(),
192 edges: Vec::new(),
193 faces: Vec::new(),
194 planes: Vec::new(),
195 },
196 box_vertices: [
197 HullVertex { edge: 8 },
198 HullVertex { edge: 1 },
199 HullVertex { edge: 0 },
200 HullVertex { edge: 9 },
201 HullVertex { edge: 13 },
202 HullVertex { edge: 3 },
203 HullVertex { edge: 5 },
204 HullVertex { edge: 11 },
205 ],
206 box_points: [VEC3_ZERO; 8],
207 box_edges: edges,
208 box_faces: [
209 HullFace { edge: 0 },
210 HullFace { edge: 8 },
211 HullFace { edge: 16 },
212 HullFace { edge: 20 },
213 HullFace { edge: 19 },
214 HullFace { edge: 21 },
215 ],
216 padding: [0, 0],
217 box_planes: [crate::math_functions::Plane {
218 normal: VEC3_ZERO,
219 offset: 0.0,
220 }; 6],
221 }
222}
223
224pub fn make_transformed_box_hull(hx: f32, hy: f32, hz: f32, transform: Transform) -> BoxHull {
226 let mut box_hull = box_hull_template();
227
228 let min_h = 0.2 * linear_slop();
229 let h = max(
230 Vec3 {
231 x: min_h,
232 y: min_h,
233 z: min_h,
234 },
235 Vec3 {
236 x: hx,
237 y: hy,
238 z: hz,
239 },
240 );
241
242 box_hull.base.aabb = aabb_transform(
243 transform,
244 Aabb {
245 lower_bound: neg(h),
246 upper_bound: h,
247 },
248 );
249 box_hull.base.surface_area = 8.0 * (h.x * h.y + h.x * h.z + h.y * h.z);
250 box_hull.base.volume = 8.0 * h.x * h.y * h.z;
251 box_hull.base.inner_radius = min_float(h.x, min_float(h.y, h.z));
252 box_hull.base.center = transform.p;
253
254 let box_inertia = box_inertia(box_hull.base.volume, neg(h), h);
255 box_hull.base.central_inertia = rotate_inertia(transform.q, box_inertia);
256
257 let lower = neg(h);
258 let upper = h;
259
260 box_hull.box_planes[0] = transform_plane(
261 transform,
262 make_plane_from_normal_and_point(neg(VEC3_AXIS_X), lower),
263 );
264 box_hull.box_planes[1] = transform_plane(
265 transform,
266 make_plane_from_normal_and_point(VEC3_AXIS_X, upper),
267 );
268 box_hull.box_planes[2] = transform_plane(
269 transform,
270 make_plane_from_normal_and_point(neg(VEC3_AXIS_Y), lower),
271 );
272 box_hull.box_planes[3] = transform_plane(
273 transform,
274 make_plane_from_normal_and_point(VEC3_AXIS_Y, upper),
275 );
276 box_hull.box_planes[4] = transform_plane(
277 transform,
278 make_plane_from_normal_and_point(neg(VEC3_AXIS_Z), lower),
279 );
280 box_hull.box_planes[5] = transform_plane(
281 transform,
282 make_plane_from_normal_and_point(VEC3_AXIS_Z, upper),
283 );
284
285 box_hull.box_points[0] = transform_point(
286 transform,
287 Vec3 {
288 x: h.x,
289 y: h.y,
290 z: h.z,
291 },
292 );
293 box_hull.box_points[1] = transform_point(
294 transform,
295 Vec3 {
296 x: -h.x,
297 y: h.y,
298 z: h.z,
299 },
300 );
301 box_hull.box_points[2] = transform_point(
302 transform,
303 Vec3 {
304 x: -h.x,
305 y: -h.y,
306 z: h.z,
307 },
308 );
309 box_hull.box_points[3] = transform_point(
310 transform,
311 Vec3 {
312 x: h.x,
313 y: -h.y,
314 z: h.z,
315 },
316 );
317 box_hull.box_points[4] = transform_point(
318 transform,
319 Vec3 {
320 x: h.x,
321 y: h.y,
322 z: -h.z,
323 },
324 );
325 box_hull.box_points[5] = transform_point(
326 transform,
327 Vec3 {
328 x: -h.x,
329 y: h.y,
330 z: -h.z,
331 },
332 );
333 box_hull.box_points[6] = transform_point(
334 transform,
335 Vec3 {
336 x: -h.x,
337 y: -h.y,
338 z: -h.z,
339 },
340 );
341 box_hull.box_points[7] = transform_point(
342 transform,
343 Vec3 {
344 x: h.x,
345 y: -h.y,
346 z: -h.z,
347 },
348 );
349
350 box_hull.sync_base_arrays();
353
354 box_hull.base.hash = 0;
355 let bytes = box_hull.to_bytes_with_hash(0);
356 box_hull.base.hash = non_zero_hash(hash(HASH_INIT, &bytes));
357
358 box_hull
359}
360
361pub fn make_cube_hull(half_width: f32) -> BoxHull {
363 make_box_hull(half_width, half_width, half_width)
364}
365
366pub fn make_offset_box_hull(hx: f32, hy: f32, hz: f32, offset: Vec3) -> BoxHull {
368 let transform = Transform {
369 p: offset,
370 q: QUAT_IDENTITY,
371 };
372 make_transformed_box_hull(hx, hy, hz, transform)
373}
374
375pub fn make_box_hull(hx: f32, hy: f32, hz: f32) -> BoxHull {
377 make_transformed_box_hull(hx, hy, hz, TRANSFORM_IDENTITY)
378}
379
380pub fn scale_box(
382 half_widths: &mut Vec3,
383 transform: &mut Transform,
384 post_scale: Vec3,
385 min_half_width: f32,
386) {
387 debug_assert!(crate::math_functions::is_valid_float(min_half_width) && min_half_width > 0.0);
388
389 let mut q = transform.q;
390
391 if post_scale.x < 0.0 || post_scale.y < 0.0 || post_scale.z < 0.0 {
392 let mut m = make_matrix_from_quat(q);
393 m.cx.x *= post_scale.x;
394 m.cy.x *= post_scale.x;
395 m.cz.x *= post_scale.x;
396 m.cx.y *= post_scale.y;
397 m.cy.y *= post_scale.y;
398 m.cz.y *= post_scale.y;
399 m.cx.z *= post_scale.z;
400 m.cy.z *= post_scale.z;
401 m.cz.z *= post_scale.z;
402 m.cx = normalize(m.cx);
403 m.cy = normalize(m.cy);
404 m.cz = normalize(m.cz);
405 m.cx = if post_scale.x < 0.0 { neg(m.cx) } else { m.cx };
406 m.cy = if post_scale.y < 0.0 { neg(m.cy) } else { m.cy };
407 m.cz = if post_scale.z < 0.0 { neg(m.cz) } else { m.cz };
408 q = make_quat_from_matrix(&m);
409 }
410
411 let abs_scale = abs(post_scale);
412 let h = *half_widths;
413 let p1 = mul(abs_scale, rotate_vector(q, neg(h)));
414 let p2 = mul(abs_scale, rotate_vector(q, h));
415
416 let local_p1 = inv_rotate_vector(q, p1);
417 let local_p2 = inv_rotate_vector(q, p2);
418
419 let lower = min(local_p1, local_p2);
420 let upper = max(local_p1, local_p2);
421
422 let scaled_half_width = mul_sv(0.5, crate::math_functions::sub(upper, lower));
423 let m_limit = Vec3 {
424 x: min_half_width,
425 y: min_half_width,
426 z: min_half_width,
427 };
428 *half_widths = max(scaled_half_width, m_limit);
429 transform.p = mul(post_scale, transform.p);
430 transform.q = q;
431}
432
433pub fn make_scaled_box_hull(half_widths: Vec3, transform: Transform, post_scale: Vec3) -> BoxHull {
435 let mut h = half_widths;
436 let mut xf = transform;
437 scale_box(&mut h, &mut xf, post_scale, 4.0 * linear_slop());
438 make_transformed_box_hull(h.x, h.y, h.z, xf)
439}