1use crate::math_functions::{Aabb, Vec3, VEC3_ONE};
10
11pub const MESH_VERSION: u64 = 0xABD11AB62A6E886D;
13
14pub const MESH_DATA_SIZE: usize = 88;
16
17pub const MESH_NODE_SIZE: usize = 32;
19
20pub const MESH_TRIANGLE_SIZE: usize = 12;
22
23pub const LEAF_NODE: u32 = 3;
25
26pub const MESH_STACK_SIZE: usize = 256;
28
29pub const CONCAVE_EDGE1: i32 = 0x01;
31pub const CONCAVE_EDGE2: i32 = 0x02;
32pub const CONCAVE_EDGE3: i32 = 0x04;
33pub const INVERSE_CONCAVE_EDGE1: i32 = 0x10;
34pub const INVERSE_CONCAVE_EDGE2: i32 = 0x20;
35pub const INVERSE_CONCAVE_EDGE3: i32 = 0x40;
36pub const ALL_CONCAVE_EDGES: i32 = CONCAVE_EDGE1 | CONCAVE_EDGE2 | CONCAVE_EDGE3;
37pub const FLAT_EDGE1: i32 = CONCAVE_EDGE1 | INVERSE_CONCAVE_EDGE1;
38pub const FLAT_EDGE2: i32 = CONCAVE_EDGE2 | INVERSE_CONCAVE_EDGE2;
39pub const FLAT_EDGE3: i32 = CONCAVE_EDGE3 | INVERSE_CONCAVE_EDGE3;
40pub const ALL_FLAT_EDGES: i32 = FLAT_EDGE1 | FLAT_EDGE2 | FLAT_EDGE3;
41
42#[derive(Debug, Clone, Default)]
44pub struct MeshDef {
45 pub vertices: Vec<Vec3>,
47 pub indices: Vec<i32>,
49 pub material_indices: Vec<u8>,
51 pub weld_tolerance: f32,
53 pub weld_vertices: bool,
55 pub use_median_split: bool,
57 pub identify_edges: bool,
59}
60
61#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
63#[repr(C)]
64pub struct MeshTriangle {
65 pub index1: i32,
66 pub index2: i32,
67 pub index3: i32,
68}
69
70#[derive(Debug, Clone, Copy, PartialEq, Default)]
76#[repr(C)]
77pub struct MeshNode {
78 pub lower_bound: Vec3,
79 pub data: u32,
80 pub upper_bound: Vec3,
81 pub triangle_offset: u32,
82}
83
84impl MeshNode {
85 #[inline]
86 pub fn is_leaf(&self) -> bool {
87 (self.data & 0x3) == LEAF_NODE
88 }
89
90 #[inline]
91 pub fn axis(&self) -> u32 {
92 self.data & 0x3
93 }
94
95 #[inline]
96 pub fn child_offset(&self) -> u32 {
97 self.data >> 2
98 }
99
100 #[inline]
101 pub fn triangle_count(&self) -> u32 {
102 self.data >> 2
103 }
104
105 #[inline]
106 pub fn store_leaf(aabb: Aabb, triangle_count: i32, triangle_offset: i32) -> Self {
107 debug_assert!(triangle_count >= 0);
108 Self {
109 lower_bound: aabb.lower_bound,
110 data: LEAF_NODE | ((triangle_count as u32) << 2),
111 upper_bound: aabb.upper_bound,
112 triangle_offset: triangle_offset as u32,
113 }
114 }
115
116 #[inline]
117 pub fn store_internal(aabb: Aabb, axis: i32, child_offset: i32) -> Self {
118 debug_assert!((0..3).contains(&axis));
119 debug_assert!(child_offset > 1);
120 Self {
121 lower_bound: aabb.lower_bound,
122 data: (axis as u32) | ((child_offset as u32) << 2),
123 upper_bound: aabb.upper_bound,
124 triangle_offset: 0,
125 }
126 }
127
128 #[inline]
129 pub fn aabb(&self) -> Aabb {
130 Aabb {
131 lower_bound: self.lower_bound,
132 upper_bound: self.upper_bound,
133 }
134 }
135}
136
137#[derive(Debug, Clone)]
142pub struct MeshData {
143 pub version: u64,
144 pub byte_count: i32,
145 pub hash: u32,
146 pub bounds: Aabb,
147 pub surface_area: f32,
148 pub tree_height: i32,
149 pub degenerate_count: i32,
150 pub node_offset: i32,
151 pub node_count: i32,
152 pub vertex_offset: i32,
153 pub vertex_count: i32,
154 pub triangle_offset: i32,
155 pub triangle_count: i32,
156 pub material_offset: i32,
157 pub material_count: i32,
158 pub flags_offset: i32,
159 pub nodes: Vec<MeshNode>,
160 pub vertices: Vec<Vec3>,
161 pub triangles: Vec<MeshTriangle>,
162 pub material_indices: Vec<u8>,
163 pub flags: Vec<u8>,
164}
165
166impl Default for MeshData {
167 fn default() -> Self {
168 Self {
169 version: MESH_VERSION,
170 byte_count: 0,
171 hash: 0,
172 bounds: Aabb::default(),
173 surface_area: 0.0,
174 tree_height: 0,
175 degenerate_count: 0,
176 node_offset: 0,
177 node_count: 0,
178 vertex_offset: 0,
179 vertex_count: 0,
180 triangle_offset: 0,
181 triangle_count: 0,
182 material_offset: 0,
183 material_count: 0,
184 flags_offset: 0,
185 nodes: Vec::new(),
186 vertices: Vec::new(),
187 triangles: Vec::new(),
188 material_indices: Vec::new(),
189 flags: Vec::new(),
190 }
191 }
192}
193
194#[derive(Debug, Clone, Copy)]
196pub struct Mesh<'a> {
197 pub data: &'a MeshData,
198 pub scale: Vec3,
199}
200
201impl<'a> Mesh<'a> {
202 pub fn new(data: &'a MeshData, scale: Vec3) -> Self {
203 Self { data, scale }
204 }
205
206 pub fn with_unit_scale(data: &'a MeshData) -> Self {
207 Self {
208 data,
209 scale: VEC3_ONE,
210 }
211 }
212}
213
214pub fn get_mesh_nodes(mesh: &MeshData) -> &[MeshNode] {
216 &mesh.nodes
217}
218
219pub fn get_mesh_vertices(mesh: &MeshData) -> &[Vec3] {
221 &mesh.vertices
222}
223
224pub fn get_mesh_triangles(mesh: &MeshData) -> &[MeshTriangle] {
226 &mesh.triangles
227}
228
229pub fn get_mesh_material_indices(mesh: &MeshData) -> &[u8] {
231 &mesh.material_indices
232}
233
234pub fn get_mesh_flags(mesh: &MeshData) -> &[u8] {
236 &mesh.flags
237}
238
239fn write_u64_le(buf: &mut Vec<u8>, v: u64) {
240 buf.extend_from_slice(&v.to_le_bytes());
241}
242
243fn read_u64_le(buf: &[u8], off: usize) -> u64 {
244 u64::from_le_bytes(buf[off..off + 8].try_into().unwrap())
245}
246
247fn read_u32_le(buf: &[u8], off: usize) -> u32 {
248 u32::from_le_bytes(buf[off..off + 4].try_into().unwrap())
249}
250
251fn read_i32_le(buf: &[u8], off: usize) -> i32 {
252 read_u32_le(buf, off) as i32
253}
254
255fn read_f32_le(buf: &[u8], off: usize) -> f32 {
256 f32::from_le_bytes(buf[off..off + 4].try_into().unwrap())
257}
258
259fn read_vec3_at(buf: &[u8], off: usize) -> Vec3 {
260 Vec3 {
261 x: read_f32_le(buf, off),
262 y: read_f32_le(buf, off + 4),
263 z: read_f32_le(buf, off + 8),
264 }
265}
266
267fn read_aabb_at(buf: &[u8], off: usize) -> Aabb {
268 Aabb {
269 lower_bound: read_vec3_at(buf, off),
270 upper_bound: read_vec3_at(buf, off + 12),
271 }
272}
273
274pub fn convert_bytes_to_mesh(bytes: &[u8]) -> Option<MeshData> {
276 if bytes.len() < MESH_DATA_SIZE {
277 return None;
278 }
279 let version = read_u64_le(bytes, 0);
280 if version != MESH_VERSION {
281 return None;
282 }
283 let byte_count = read_i32_le(bytes, 8);
284 if byte_count < MESH_DATA_SIZE as i32 || bytes.len() != byte_count as usize {
285 return None;
286 }
287 let hash = read_u32_le(bytes, 12);
288 let bounds = read_aabb_at(bytes, 16);
289 let surface_area = read_f32_le(bytes, 40);
290 let tree_height = read_i32_le(bytes, 44);
291 let degenerate_count = read_i32_le(bytes, 48);
292 let node_offset = read_i32_le(bytes, 52);
293 let node_count = read_i32_le(bytes, 56);
294 let vertex_offset = read_i32_le(bytes, 60);
295 let vertex_count = read_i32_le(bytes, 64);
296 let triangle_offset = read_i32_le(bytes, 68);
297 let triangle_count = read_i32_le(bytes, 72);
298 let material_offset = read_i32_le(bytes, 76);
299 let material_count = read_i32_le(bytes, 80);
300 let flags_offset = read_i32_le(bytes, 84);
301
302 if node_count < 0 || vertex_count < 0 || triangle_count < 0 || material_count < 0 {
303 return None;
304 }
305 let nc = node_count as usize;
306 let vc = vertex_count as usize;
307 let tc = triangle_count as usize;
308 let mc = material_count as usize;
309
310 let noff = node_offset as usize;
311 if noff + nc * MESH_NODE_SIZE > bytes.len() {
312 return None;
313 }
314 let mut nodes = Vec::with_capacity(nc);
315 for i in 0..nc {
316 let o = noff + i * MESH_NODE_SIZE;
317 nodes.push(MeshNode {
318 lower_bound: read_vec3_at(bytes, o),
319 data: read_u32_le(bytes, o + 12),
320 upper_bound: read_vec3_at(bytes, o + 16),
321 triangle_offset: read_u32_le(bytes, o + 28),
322 });
323 }
324
325 let voff = vertex_offset as usize;
326 if voff + vc * 12 > bytes.len() {
327 return None;
328 }
329 let mut vertices = Vec::with_capacity(vc);
330 for i in 0..vc {
331 vertices.push(read_vec3_at(bytes, voff + i * 12));
332 }
333
334 let toff = triangle_offset as usize;
335 if toff + tc * MESH_TRIANGLE_SIZE > bytes.len() {
336 return None;
337 }
338 let mut triangles = Vec::with_capacity(tc);
339 for i in 0..tc {
340 let o = toff + i * MESH_TRIANGLE_SIZE;
341 triangles.push(MeshTriangle {
342 index1: read_i32_le(bytes, o),
343 index2: read_i32_le(bytes, o + 4),
344 index3: read_i32_le(bytes, o + 8),
345 });
346 }
347
348 let moff = material_offset as usize;
349 if moff + mc > bytes.len() {
350 return None;
351 }
352 let material_indices = bytes[moff..moff + mc].to_vec();
353
354 let foff = flags_offset as usize;
355 if foff + tc > bytes.len() {
356 return None;
357 }
358 let flags = bytes[foff..foff + tc].to_vec();
359
360 Some(MeshData {
361 version,
362 byte_count,
363 hash,
364 bounds,
365 surface_area,
366 tree_height,
367 degenerate_count,
368 node_offset,
369 node_count,
370 vertex_offset,
371 vertex_count,
372 triangle_offset,
373 triangle_count,
374 material_offset,
375 material_count,
376 flags_offset,
377 nodes,
378 vertices,
379 triangles,
380 material_indices,
381 flags,
382 })
383}
384
385fn write_u32_le(buf: &mut Vec<u8>, v: u32) {
386 buf.extend_from_slice(&v.to_le_bytes());
387}
388
389fn write_i32_le(buf: &mut Vec<u8>, v: i32) {
390 buf.extend_from_slice(&v.to_le_bytes());
391}
392
393fn write_f32_le(buf: &mut Vec<u8>, v: f32) {
394 buf.extend_from_slice(&v.to_le_bytes());
395}
396
397fn write_vec3(buf: &mut Vec<u8>, v: Vec3) {
398 write_f32_le(buf, v.x);
399 write_f32_le(buf, v.y);
400 write_f32_le(buf, v.z);
401}
402
403fn write_aabb(buf: &mut Vec<u8>, a: Aabb) {
404 write_vec3(buf, a.lower_bound);
405 write_vec3(buf, a.upper_bound);
406}
407
408fn pad_to(buf: &mut Vec<u8>, len: usize) {
409 if buf.len() < len {
410 buf.resize(len, 0);
411 }
412}
413
414fn write_header(buf: &mut Vec<u8>, m: &MeshData, hash_override: Option<u32>) {
415 write_u64_le(buf, m.version);
416 write_i32_le(buf, m.byte_count);
417 write_u32_le(buf, hash_override.unwrap_or(m.hash));
418 write_aabb(buf, m.bounds);
419 write_f32_le(buf, m.surface_area);
420 write_i32_le(buf, m.tree_height);
421 write_i32_le(buf, m.degenerate_count);
422 write_i32_le(buf, m.node_offset);
423 write_i32_le(buf, m.node_count);
424 write_i32_le(buf, m.vertex_offset);
425 write_i32_le(buf, m.vertex_count);
426 write_i32_le(buf, m.triangle_offset);
427 write_i32_le(buf, m.triangle_count);
428 write_i32_le(buf, m.material_offset);
429 write_i32_le(buf, m.material_count);
430 write_i32_le(buf, m.flags_offset);
431 debug_assert_eq!(buf.len(), MESH_DATA_SIZE);
432}
433
434fn write_node(buf: &mut Vec<u8>, n: &MeshNode) {
435 write_vec3(buf, n.lower_bound);
436 write_u32_le(buf, n.data);
437 write_vec3(buf, n.upper_bound);
438 write_u32_le(buf, n.triangle_offset);
439}
440
441impl MeshData {
442 pub fn from_bytes(bytes: &[u8]) -> Option<MeshData> {
444 convert_bytes_to_mesh(bytes)
445 }
446
447 pub fn to_bytes(&self) -> Vec<u8> {
449 self.to_bytes_with_hash(self.hash)
450 }
451
452 pub fn to_bytes_with_hash(&self, hash: u32) -> Vec<u8> {
454 let mut buf = Vec::with_capacity(self.byte_count as usize);
455 write_header(&mut buf, self, Some(hash));
456 pad_to(&mut buf, self.node_offset as usize);
457 for n in &self.nodes {
458 write_node(&mut buf, n);
459 }
460 pad_to(&mut buf, self.vertex_offset as usize);
461 for v in &self.vertices {
462 write_vec3(&mut buf, *v);
463 }
464 pad_to(&mut buf, self.triangle_offset as usize);
465 for t in &self.triangles {
466 write_i32_le(&mut buf, t.index1);
467 write_i32_le(&mut buf, t.index2);
468 write_i32_le(&mut buf, t.index3);
469 }
470 pad_to(&mut buf, self.material_offset as usize);
471 buf.extend_from_slice(&self.material_indices);
472 pad_to(&mut buf, self.flags_offset as usize);
473 buf.extend_from_slice(&self.flags);
474 pad_to(&mut buf, self.byte_count as usize);
475 debug_assert_eq!(buf.len(), self.byte_count as usize);
476 buf
477 }
478}