1use crate::math_functions::{Aabb, Matrix3, Plane, Vec3, MAT3_ZERO, VEC3_ZERO};
14
15pub const HULL_VERSION: u64 = 0x9D4716CE3793900E;
17
18pub const HULL_DATA_SIZE: usize = 136;
20
21pub const BOX_HULL_SIZE: usize = 440;
23
24#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
26#[repr(C)]
27pub struct HullVertex {
28 pub edge: u8,
30}
31
32#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
34#[repr(C)]
35pub struct HullHalfEdge {
36 pub next: u8,
38 pub twin: u8,
40 pub origin: u8,
42 pub face: u8,
44}
45
46#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
49#[repr(C)]
50pub struct HullFace {
51 pub edge: u8,
53}
54
55#[derive(Debug, Clone)]
59pub struct HullData {
60 pub version: u64,
61 pub byte_count: i32,
62 pub hash: u32,
63 pub aabb: Aabb,
64 pub surface_area: f32,
65 pub volume: f32,
66 pub inner_radius: f32,
67 pub center: Vec3,
68 pub central_inertia: Matrix3,
69 pub vertex_count: i32,
70 pub vertex_offset: i32,
71 pub point_offset: i32,
72 pub edge_count: i32,
73 pub edge_offset: i32,
74 pub face_count: i32,
75 pub face_offset: i32,
76 pub plane_offset: i32,
77 pub padding: i32,
78 pub vertices: Vec<HullVertex>,
79 pub points: Vec<Vec3>,
80 pub edges: Vec<HullHalfEdge>,
81 pub faces: Vec<HullFace>,
82 pub planes: Vec<Plane>,
83}
84
85impl Default for HullData {
86 fn default() -> Self {
87 Self {
88 version: HULL_VERSION,
89 byte_count: 0,
90 hash: 0,
91 aabb: Aabb::default(),
92 surface_area: 0.0,
93 volume: 0.0,
94 inner_radius: 0.0,
95 center: VEC3_ZERO,
96 central_inertia: MAT3_ZERO,
97 vertex_count: 0,
98 vertex_offset: 0,
99 point_offset: 0,
100 edge_count: 0,
101 edge_offset: 0,
102 face_count: 0,
103 face_offset: 0,
104 plane_offset: 0,
105 padding: 0,
106 vertices: Vec::new(),
107 points: Vec::new(),
108 edges: Vec::new(),
109 faces: Vec::new(),
110 planes: Vec::new(),
111 }
112 }
113}
114
115#[derive(Debug, Clone)]
117pub struct BoxHull {
118 pub base: HullData,
119 pub box_vertices: [HullVertex; 8],
120 pub box_points: [Vec3; 8],
121 pub box_edges: [HullHalfEdge; 24],
122 pub box_faces: [HullFace; 6],
123 pub padding: [u8; 2],
124 pub box_planes: [Plane; 6],
125}
126
127impl BoxHull {
128 pub fn as_hull_data(&self) -> HullDataView<'_> {
130 HullDataView {
131 header: &self.base,
132 vertices: &self.box_vertices,
133 points: &self.box_points,
134 edges: &self.box_edges,
135 faces: &self.box_faces,
136 planes: &self.box_planes,
137 }
138 }
139
140 pub fn sync_base_arrays(&mut self) {
145 self.base.vertices = self.box_vertices.to_vec();
146 self.base.points = self.box_points.to_vec();
147 self.base.edges = self.box_edges.to_vec();
148 self.base.faces = self.box_faces.to_vec();
149 self.base.planes = self.box_planes.to_vec();
150 }
151}
152
153pub struct HullDataView<'a> {
155 pub header: &'a HullData,
156 pub vertices: &'a [HullVertex],
157 pub points: &'a [Vec3],
158 pub edges: &'a [HullHalfEdge],
159 pub faces: &'a [HullFace],
160 pub planes: &'a [Plane],
161}
162
163pub fn get_hull_vertices(hull: &HullData) -> &[HullVertex] {
165 &hull.vertices[..hull.vertex_count as usize]
166}
167
168pub fn get_hull_points(hull: &HullData) -> &[Vec3] {
170 &hull.points[..hull.vertex_count as usize]
171}
172
173pub fn get_hull_edges(hull: &HullData) -> &[HullHalfEdge] {
175 &hull.edges[..hull.edge_count as usize]
176}
177
178pub fn get_hull_faces(hull: &HullData) -> &[HullFace] {
180 &hull.faces[..hull.face_count as usize]
181}
182
183pub fn get_hull_planes(hull: &HullData) -> &[Plane] {
185 &hull.planes[..hull.face_count as usize]
186}
187
188fn write_u32_le(buf: &mut Vec<u8>, v: u32) {
189 buf.extend_from_slice(&v.to_le_bytes());
190}
191
192fn write_i32_le(buf: &mut Vec<u8>, v: i32) {
193 buf.extend_from_slice(&v.to_le_bytes());
194}
195
196fn write_f32_le(buf: &mut Vec<u8>, v: f32) {
197 buf.extend_from_slice(&v.to_le_bytes());
198}
199
200fn write_u64_le(buf: &mut Vec<u8>, v: u64) {
201 buf.extend_from_slice(&v.to_le_bytes());
202}
203
204fn write_vec3(buf: &mut Vec<u8>, v: Vec3) {
205 write_f32_le(buf, v.x);
206 write_f32_le(buf, v.y);
207 write_f32_le(buf, v.z);
208}
209
210fn write_aabb(buf: &mut Vec<u8>, a: Aabb) {
211 write_vec3(buf, a.lower_bound);
212 write_vec3(buf, a.upper_bound);
213}
214
215fn write_matrix3(buf: &mut Vec<u8>, m: Matrix3) {
216 write_vec3(buf, m.cx);
217 write_vec3(buf, m.cy);
218 write_vec3(buf, m.cz);
219}
220
221fn write_plane(buf: &mut Vec<u8>, p: Plane) {
222 write_vec3(buf, p.normal);
223 write_f32_le(buf, p.offset);
224}
225
226fn write_header(buf: &mut Vec<u8>, h: &HullData, hash_override: Option<u32>) {
227 write_u64_le(buf, h.version);
228 write_i32_le(buf, h.byte_count);
229 write_u32_le(buf, hash_override.unwrap_or(h.hash));
230 write_aabb(buf, h.aabb);
231 write_f32_le(buf, h.surface_area);
232 write_f32_le(buf, h.volume);
233 write_f32_le(buf, h.inner_radius);
234 write_vec3(buf, h.center);
235 write_matrix3(buf, h.central_inertia);
236 write_i32_le(buf, h.vertex_count);
237 write_i32_le(buf, h.vertex_offset);
238 write_i32_le(buf, h.point_offset);
239 write_i32_le(buf, h.edge_count);
240 write_i32_le(buf, h.edge_offset);
241 write_i32_le(buf, h.face_count);
242 write_i32_le(buf, h.face_offset);
243 write_i32_le(buf, h.plane_offset);
244 write_i32_le(buf, h.padding);
245 debug_assert_eq!(buf.len(), HULL_DATA_SIZE);
246}
247
248fn pad_to(buf: &mut Vec<u8>, len: usize) {
249 if buf.len() < len {
250 buf.resize(len, 0);
251 }
252}
253
254fn read_u32_le(buf: &[u8], off: usize) -> u32 {
255 u32::from_le_bytes(buf[off..off + 4].try_into().unwrap())
256}
257
258fn read_i32_le(buf: &[u8], off: usize) -> i32 {
259 read_u32_le(buf, off) as i32
260}
261
262fn read_u64_le(buf: &[u8], off: usize) -> u64 {
263 u64::from_le_bytes(buf[off..off + 8].try_into().unwrap())
264}
265
266fn read_f32_le(buf: &[u8], off: usize) -> f32 {
267 f32::from_le_bytes(buf[off..off + 4].try_into().unwrap())
268}
269
270fn read_vec3(buf: &[u8], off: usize) -> Vec3 {
271 Vec3 {
272 x: read_f32_le(buf, off),
273 y: read_f32_le(buf, off + 4),
274 z: read_f32_le(buf, off + 8),
275 }
276}
277
278fn read_aabb(buf: &[u8], off: usize) -> Aabb {
279 Aabb {
280 lower_bound: read_vec3(buf, off),
281 upper_bound: read_vec3(buf, off + 12),
282 }
283}
284
285fn read_matrix3(buf: &[u8], off: usize) -> Matrix3 {
286 Matrix3 {
287 cx: read_vec3(buf, off),
288 cy: read_vec3(buf, off + 12),
289 cz: read_vec3(buf, off + 24),
290 }
291}
292
293fn read_plane(buf: &[u8], off: usize) -> Plane {
294 Plane {
295 normal: read_vec3(buf, off),
296 offset: read_f32_le(buf, off + 12),
297 }
298}
299
300pub fn convert_bytes_to_hull(bytes: &[u8]) -> Option<HullData> {
302 if bytes.len() < HULL_DATA_SIZE {
303 return None;
304 }
305 let version = read_u64_le(bytes, 0);
306 if version != HULL_VERSION {
307 return None;
308 }
309 let byte_count = read_i32_le(bytes, 8);
310 if byte_count < HULL_DATA_SIZE as i32 || bytes.len() != byte_count as usize {
311 return None;
312 }
313 let hash = read_u32_le(bytes, 12);
314 let aabb = read_aabb(bytes, 16);
315 let surface_area = read_f32_le(bytes, 40);
316 let volume = read_f32_le(bytes, 44);
317 let inner_radius = read_f32_le(bytes, 48);
318 let center = read_vec3(bytes, 52);
319 let central_inertia = read_matrix3(bytes, 64);
320 let vertex_count = read_i32_le(bytes, 100);
321 let vertex_offset = read_i32_le(bytes, 104);
322 let point_offset = read_i32_le(bytes, 108);
323 let edge_count = read_i32_le(bytes, 112);
324 let edge_offset = read_i32_le(bytes, 116);
325 let face_count = read_i32_le(bytes, 120);
326 let face_offset = read_i32_le(bytes, 124);
327 let plane_offset = read_i32_le(bytes, 128);
328 let padding = read_i32_le(bytes, 132);
329
330 if vertex_count < 0 || edge_count < 0 || face_count < 0 {
331 return None;
332 }
333 let vc = vertex_count as usize;
334 let ec = edge_count as usize;
335 let fc = face_count as usize;
336
337 let mut vertices = Vec::with_capacity(vc);
338 let voff = vertex_offset as usize;
339 if voff + vc > bytes.len() {
340 return None;
341 }
342 for i in 0..vc {
343 vertices.push(HullVertex {
344 edge: bytes[voff + i],
345 });
346 }
347
348 let mut points = Vec::with_capacity(vc);
349 let poff = point_offset as usize;
350 if poff + vc * 12 > bytes.len() {
351 return None;
352 }
353 for i in 0..vc {
354 points.push(read_vec3(bytes, poff + i * 12));
355 }
356
357 let mut edges = Vec::with_capacity(ec);
358 let eoff = edge_offset as usize;
359 if eoff + ec * 4 > bytes.len() {
360 return None;
361 }
362 for i in 0..ec {
363 let o = eoff + i * 4;
364 edges.push(HullHalfEdge {
365 next: bytes[o],
366 twin: bytes[o + 1],
367 origin: bytes[o + 2],
368 face: bytes[o + 3],
369 });
370 }
371
372 let mut faces = Vec::with_capacity(fc);
373 let foff = face_offset as usize;
374 if foff + fc > bytes.len() {
375 return None;
376 }
377 for i in 0..fc {
378 faces.push(HullFace {
379 edge: bytes[foff + i],
380 });
381 }
382
383 let mut planes = Vec::with_capacity(fc);
384 let ploff = plane_offset as usize;
385 if ploff + fc * 16 > bytes.len() {
386 return None;
387 }
388 for i in 0..fc {
389 planes.push(read_plane(bytes, ploff + i * 16));
390 }
391
392 Some(HullData {
393 version,
394 byte_count,
395 hash,
396 aabb,
397 surface_area,
398 volume,
399 inner_radius,
400 center,
401 central_inertia,
402 vertex_count,
403 vertex_offset,
404 point_offset,
405 edge_count,
406 edge_offset,
407 face_count,
408 face_offset,
409 plane_offset,
410 padding,
411 vertices,
412 points,
413 edges,
414 faces,
415 planes,
416 })
417}
418
419impl HullData {
420 pub fn to_bytes(&self) -> Vec<u8> {
422 self.to_bytes_with_hash(self.hash)
423 }
424
425 pub fn to_bytes_with_hash(&self, hash: u32) -> Vec<u8> {
427 let mut buf = Vec::with_capacity(self.byte_count as usize);
428 write_header(&mut buf, self, Some(hash));
429 pad_to(&mut buf, self.vertex_offset as usize);
430 for v in &self.vertices {
431 buf.push(v.edge);
432 }
433 pad_to(&mut buf, self.point_offset as usize);
434 for p in &self.points {
435 write_vec3(&mut buf, *p);
436 }
437 pad_to(&mut buf, self.edge_offset as usize);
438 for e in &self.edges {
439 buf.push(e.next);
440 buf.push(e.twin);
441 buf.push(e.origin);
442 buf.push(e.face);
443 }
444 pad_to(&mut buf, self.face_offset as usize);
445 for f in &self.faces {
446 buf.push(f.edge);
447 }
448 pad_to(&mut buf, self.plane_offset as usize);
449 for p in &self.planes {
450 write_plane(&mut buf, *p);
451 }
452 pad_to(&mut buf, self.byte_count as usize);
453 debug_assert_eq!(buf.len(), self.byte_count as usize);
454 buf
455 }
456}
457
458impl BoxHull {
459 pub fn to_bytes(&self) -> Vec<u8> {
461 self.to_bytes_with_hash(self.base.hash)
462 }
463
464 pub fn to_bytes_with_hash(&self, hash: u32) -> Vec<u8> {
465 let mut buf = Vec::with_capacity(BOX_HULL_SIZE);
466 write_header(&mut buf, &self.base, Some(hash));
467 for v in &self.box_vertices {
468 buf.push(v.edge);
469 }
470 for p in &self.box_points {
471 write_vec3(&mut buf, *p);
472 }
473 for e in &self.box_edges {
474 buf.push(e.next);
475 buf.push(e.twin);
476 buf.push(e.origin);
477 buf.push(e.face);
478 }
479 for f in &self.box_faces {
480 buf.push(f.edge);
481 }
482 buf.extend_from_slice(&self.padding);
483 for p in &self.box_planes {
484 write_plane(&mut buf, *p);
485 }
486 debug_assert_eq!(buf.len(), BOX_HULL_SIZE);
487 buf
488 }
489}