1use crate::linalg::Vec3;
11use crate::types::Box;
12
13pub trait MeshPrecision: Copy + Default {
19 const IS_SINGLE: bool;
23 fn to_f64(self) -> f64;
24 fn from_f64(v: f64) -> Self;
25}
26
27impl MeshPrecision for f32 {
28 const IS_SINGLE: bool = true;
29 fn to_f64(self) -> f64 { self as f64 }
30 fn from_f64(v: f64) -> Self { v as f32 }
31}
32
33impl MeshPrecision for f64 {
34 const IS_SINGLE: bool = false;
35 fn to_f64(self) -> f64 { self }
36 fn from_f64(v: f64) -> Self { v }
37}
38
39pub trait MeshIndex: Copy + Default {
45 fn to_u64(self) -> u64;
46 fn from_usize(v: usize) -> Self;
47 fn from_i32(v: i32) -> Self;
50}
51
52impl MeshIndex for u32 {
53 fn to_u64(self) -> u64 { self as u64 }
54 fn from_usize(v: usize) -> Self { v as u32 }
55 fn from_i32(v: i32) -> Self { v as u32 }
56}
57
58impl MeshIndex for u64 {
59 fn to_u64(self) -> u64 { self }
60 fn from_usize(v: usize) -> Self { v as u64 }
61 fn from_i32(v: i32) -> Self { v as i64 as u64 }
62}
63
64#[derive(Clone, Debug, Default)]
66pub struct MeshGLP<P: Copy + Default, I: Copy + Default = u32> {
67 pub num_prop: I,
69 pub vert_properties: Vec<P>,
71 pub tri_verts: Vec<I>,
73 pub merge_from_vert: Vec<I>,
75 pub merge_to_vert: Vec<I>,
77 pub run_index: Vec<I>,
79 pub run_original_id: Vec<u32>,
81 pub run_transform: Vec<P>,
83 pub face_id: Vec<I>,
85 pub halfedge_tangent: Vec<P>,
87 pub run_flags: Vec<u8>,
89 pub tolerance: P,
91}
92
93impl<P: MeshPrecision, I: MeshIndex> MeshGLP<P, I> {
94 pub fn num_vert(&self) -> usize {
95 if self.num_prop.to_u64() == 0 {
96 0
97 } else {
98 self.vert_properties.len() / self.num_prop.to_u64() as usize
99 }
100 }
101
102 pub fn num_tri(&self) -> usize {
103 self.tri_verts.len() / 3
104 }
105
106 pub fn get_vert_pos(&self, v: usize) -> [P; 3] {
107 let offset = v * self.num_prop.to_u64() as usize;
108 [self.vert_properties[offset], self.vert_properties[offset + 1], self.vert_properties[offset + 2]]
109 }
110
111 pub fn get_tri_verts(&self, t: usize) -> [I; 3] {
112 let offset = 3 * t;
113 [self.tri_verts[offset], self.tri_verts[offset + 1], self.tri_verts[offset + 2]]
114 }
115
116 pub fn get_tangent(&self, h: usize) -> [P; 4] {
117 let offset = 4 * h;
118 [
119 self.halfedge_tangent[offset],
120 self.halfedge_tangent[offset + 1],
121 self.halfedge_tangent[offset + 2],
122 self.halfedge_tangent[offset + 3],
123 ]
124 }
125}
126
127impl MeshGLP<f32, u32> {
128 pub fn merge(&mut self) -> bool {
133 use crate::collider::Collider;
134 use crate::disjoint_sets::DisjointSets;
135 use crate::sort::morton_code;
136 use std::collections::BTreeSet;
137
138 let num_vert = self.num_vert();
139 let num_tri = self.num_tri();
140
141 let mut merge_map: Vec<usize> = (0..num_vert).collect();
143 for i in 0..self.merge_from_vert.len() {
144 merge_map[self.merge_from_vert[i] as usize] = self.merge_to_vert[i] as usize;
145 }
146
147 let next = [1usize, 2, 0];
149 let mut open_edges: BTreeSet<(usize, usize)> = BTreeSet::new();
150 for tri in 0..num_tri {
151 for i in 0..3 {
152 let a = merge_map[self.tri_verts[3 * tri + next[i]] as usize];
153 let b = merge_map[self.tri_verts[3 * tri + i] as usize];
154 let edge = (a, b);
155 let rev = (b, a);
157 if open_edges.contains(&rev) {
158 open_edges.remove(&rev);
159 } else {
160 open_edges.insert(edge);
161 }
162 }
163 }
164
165 if open_edges.is_empty() {
166 return false;
167 }
168
169 let open_verts: Vec<usize> = {
173 let mut vset = std::collections::BTreeSet::new();
174 for (_a, b) in &open_edges {
175 vset.insert(*b);
176 }
177 vset.into_iter().collect()
178 };
179 let num_open = open_verts.len();
180
181 let mut bbox = Box::default();
183 for v in 0..num_vert {
184 let pos = self.get_vert_pos(v);
185 let p = Vec3::new(pos[0] as f64, pos[1] as f64, pos[2] as f64);
186 bbox.union_point(p);
187 }
188
189 let tolerance = f64::max(
190 self.tolerance as f64,
191 f32::EPSILON as f64 * bbox.scale(),
192 );
193
194 let mut vert_box: Vec<Box> = Vec::with_capacity(num_open);
196 let mut vert_morton: Vec<u32> = Vec::with_capacity(num_open);
197 for &v in &open_verts {
198 let pos = self.get_vert_pos(v);
199 let center = Vec3::new(pos[0] as f64, pos[1] as f64, pos[2] as f64);
200 let half_tol = tolerance / 2.0;
201 let bx = Box::from_points(
202 center - Vec3::new(half_tol, half_tol, half_tol),
203 center + Vec3::new(half_tol, half_tol, half_tol),
204 );
205 vert_box.push(bx);
206 vert_morton.push(morton_code(center, &bbox));
207 }
208
209 let mut order: Vec<usize> = (0..num_open).collect();
211 order.sort_by_key(|&i| vert_morton[i]);
212
213 let sorted_box: Vec<Box> = order.iter().map(|&i| vert_box[i]).collect();
214 let sorted_morton: Vec<u32> = order.iter().map(|&i| vert_morton[i]).collect();
215 let sorted_verts: Vec<usize> = order.iter().map(|&i| open_verts[i]).collect();
216
217 let collider = Collider::new(sorted_box.clone(), sorted_morton);
219 let uf = DisjointSets::new(num_vert as u32);
220
221 collider.collisions_with_boxes(&sorted_box, false, |a, b| {
222 uf.unite(sorted_verts[a] as u32, sorted_verts[b] as u32);
223 });
224
225 for i in 0..self.merge_from_vert.len() {
227 uf.unite(self.merge_from_vert[i], self.merge_to_vert[i]);
228 }
229
230 self.merge_from_vert.clear();
232 self.merge_to_vert.clear();
233 for v in 0..num_vert {
234 let merge_to = uf.find(v as u32) as usize;
235 if merge_to != v {
236 self.merge_from_vert.push(v as u32);
237 self.merge_to_vert.push(merge_to as u32);
238 }
239 }
240
241 true
242 }
243
244 pub fn backside(&self, run: usize) -> bool {
248 run < self.run_flags.len() && (self.run_flags[run] & 1) != 0
249 }
250
251 pub fn has_normals(&self, run: usize) -> bool {
256 run < self.run_flags.len() && (self.run_flags[run] & 2) != 0
257 }
258
259 pub fn update_normals(&mut self, normal_idx: usize) {
265 if normal_idx < 3 || normal_idx + 3 > self.num_prop as usize {
266 return;
267 }
268 let num_vert = self.num_vert();
269 let num_run = self.run_original_id.len();
270 let np = self.num_prop as usize;
271 let mut vert_updated = vec![false; num_vert];
272
273 for run in 0..num_run {
274 let offset = 12 * run;
276 let has_transform = offset + 12 <= self.run_transform.len();
277
278 let (m00, m01, m02,
280 m10, m11, m12,
281 m20, m21, m22) = if has_transform {
282 let t = &self.run_transform[offset..offset + 12];
283 (t[0] as f64, t[3] as f64, t[6] as f64,
285 t[1] as f64, t[4] as f64, t[7] as f64,
286 t[2] as f64, t[5] as f64, t[8] as f64)
287 } else {
288 (1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
289 };
290
291 let det = m00*(m11*m22 - m12*m21) - m01*(m10*m22 - m12*m20) + m02*(m10*m21 - m11*m20);
296 let (n00, n01, n02, n10, n11, n12, n20, n21, n22) = if det.abs() < 1e-30 {
297 (1.0f64, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0)
298 } else {
299 let inv = 1.0 / det;
300 let a00 = (m11*m22 - m12*m21) * inv;
302 let a01 = (m02*m21 - m01*m22) * inv;
303 let a02 = (m01*m12 - m02*m11) * inv;
304 let a10 = (m12*m20 - m10*m22) * inv;
305 let a11 = (m00*m22 - m02*m20) * inv;
306 let a12 = (m02*m10 - m00*m12) * inv;
307 let a20 = (m10*m21 - m11*m20) * inv;
308 let a21 = (m01*m20 - m00*m21) * inv;
309 let a22 = (m00*m11 - m01*m10) * inv;
310 (a00, a01, a02, a10, a11, a12, a20, a21, a22)
311 };
312
313 let sign = if self.backside(run) { -1.0f64 } else { 1.0 };
314
315 let start = if run < self.run_index.len() { self.run_index[run] as usize } else { 0 };
317 let end = if run + 1 < self.run_index.len() { self.run_index[run + 1] as usize } else { self.tri_verts.len() };
318
319 for idx in (start..end).step_by(1) {
320 let vert = self.tri_verts[idx] as usize;
321 if vert >= num_vert || vert_updated[vert] { continue; }
322 vert_updated[vert] = true;
323 let prop_start = vert * np + normal_idx;
324 let nx = self.vert_properties[prop_start] as f64;
325 let ny = self.vert_properties[prop_start + 1] as f64;
326 let nz = self.vert_properties[prop_start + 2] as f64;
327 let tx = n00*nx + n01*ny + n02*nz;
329 let ty = n10*nx + n11*ny + n12*nz;
330 let tz = n20*nx + n21*ny + n22*nz;
331 let len = (tx*tx + ty*ty + tz*tz).sqrt();
333 let (tx, ty, tz) = if len > 0.0 {
334 (sign * tx / len, sign * ty / len, sign * tz / len)
335 } else {
336 (0.0, 0.0, 0.0)
337 };
338 self.vert_properties[prop_start] = tx as f32;
339 self.vert_properties[prop_start + 1] = ty as f32;
340 self.vert_properties[prop_start + 2] = tz as f32;
341 }
342 }
343 self.run_transform.clear();
344 self.run_flags.clear();
345 }
346}
347
348pub type MeshGL = MeshGLP<f32, u32>;
350
351pub type MeshGL64 = MeshGLP<f64, u64>;