1pub const MESHLET_DESCRIPTOR_STRIDE: usize = 4;
9
10pub const MESHLET_BOUNDS_STRIDE: usize = 16;
13
14pub const MESHLET_SCHEMA_VERSION: u32 = 1;
16
17pub const MESHLET_MAX_VERTICES_LIMIT: u32 = 64;
19
20pub const MESHLET_MAX_TRIANGLES_LIMIT: u32 = 126;
22
23pub const SOURCE_VERTICES_BUDGET: u64 = 16_777_216;
25
26pub const SOURCE_TRIANGLES_BUDGET: u64 = 4_000_000;
28
29pub const OUTPUT_MESHLETS_BUDGET: u64 = 4_000_000;
31
32pub const OUTPUT_TRIANGLE_BUDGET_DEFAULT: u64 = 8_000_000;
34
35#[derive(Debug, Clone)]
37pub struct IndexedGeometry {
38 pub positions: Vec<f32>,
40 pub indices: Vec<u32>,
42}
43
44impl IndexedGeometry {
45 #[must_use]
47 pub fn vertex_count(&self) -> usize {
48 self.positions.len() / 3
49 }
50
51 #[must_use]
53 pub fn triangle_count(&self) -> usize {
54 self.indices.len() / 3
55 }
56}
57
58#[derive(Debug, Default)]
60pub(crate) struct PendingMeshlet {
61 local_by_global: rustc_hash_lite::FxHashMap<u32, u32>,
63 pub(crate) vertices: Vec<u32>,
65 pub(crate) triangles: Vec<u32>,
67 pub(crate) normals: Vec<[f64; 3]>,
69 pub(crate) has_degenerate: bool,
71}
72
73impl PendingMeshlet {
74 pub(crate) fn new() -> Self {
75 Self::default()
76 }
77
78 #[inline]
80 pub(crate) fn contains_global(&self, global: u32) -> bool {
81 self.local_by_global.contains_key(&global)
82 }
83
84 pub(crate) fn local_vertex(&mut self, global: u32) -> u32 {
86 if let Some(&existing) = self.local_by_global.get(&global) {
87 return existing;
88 }
89 let local = self.vertices.len() as u32;
90 self.local_by_global.insert(global, local);
91 self.vertices.push(global);
92 local
93 }
94}
95
96pub(crate) mod rustc_hash_lite {
99 #[derive(Default)]
101 pub(crate) struct FxHasher(u64);
102
103 impl std::hash::Hasher for FxHasher {
104 #[inline]
105 fn write_u32(&mut self, v: u32) {
106 self.0 = (self.0.rotate_left(5) ^ u64::from(v)).wrapping_mul(0x517c_c1b7_2722_0a95);
107 }
108
109 #[inline]
110 fn write_usize(&mut self, v: usize) {
111 self.write_u64(v as u64);
112 }
113
114 #[inline]
115 fn write_u64(&mut self, v: u64) {
116 self.0 = (self.0.rotate_left(5) ^ v).wrapping_mul(0x517c_c1b7_2722_0a95);
117 }
118
119 #[inline]
120 fn write(&mut self, bytes: &[u8]) {
121 for &b in bytes {
122 self.0 = (self.0.rotate_left(5) ^ u64::from(b)).wrapping_mul(0x517c_c1b7_2722_0a95);
123 }
124 }
125
126 #[inline]
127 fn finish(&self) -> u64 {
128 self.0
129 }
130 }
131
132 pub(crate) type FxHashMap<K, V> = std::collections::HashMap<K, V, std::hash::BuildHasherDefault<FxHasher>>;
134
135 pub(crate) type FxHashSet<K> = std::collections::HashSet<K, std::hash::BuildHasherDefault<FxHasher>>;
137}