1use crate::linalg::Vec3;
7use crate::types::{Box as BBox, Halfedge};
8use crate::impl_mesh::ManifoldImpl;
9
10const K_NO_CODE: u32 = 0xFFFF_FFFFu32;
15
16#[inline]
19fn spread_bits3(mut v: u32) -> u32 {
20 v = 0xFF0000FFu32 & v.wrapping_mul(0x00010001u32);
21 v = 0x0F00F00Fu32 & v.wrapping_mul(0x00000101u32);
22 v = 0xC30C30C3u32 & v.wrapping_mul(0x00000011u32);
23 v = 0x49249249u32 & v.wrapping_mul(0x00000005u32);
24 v
25}
26
27pub fn morton_code(position: Vec3, bbox: &BBox) -> u32 {
30 if position.x.is_nan() {
31 return K_NO_CODE;
32 }
33 morton_code_impl(position, bbox)
34}
35
36fn morton_code_impl(position: Vec3, bbox: &BBox) -> u32 {
37 let range = bbox.max - bbox.min;
38 let xyz = (position - bbox.min) / range;
39 let x_f = (1024.0 * xyz.x).min(1023.0).max(0.0);
40 let y_f = (1024.0 * xyz.y).min(1023.0).max(0.0);
41 let z_f = (1024.0 * xyz.z).min(1023.0).max(0.0);
42 let x = spread_bits3(x_f as u32);
43 let y = spread_bits3(y_f as u32);
44 let z = spread_bits3(z_f as u32);
45 x * 4 + y * 2 + z
46}
47
48pub fn sort_verts(mesh: &mut ManifoldImpl) {
55 let num_vert = mesh.vert_pos.len();
56 let bbox = mesh.bbox;
57
58 let vert_morton: Vec<u32> = mesh.vert_pos.iter()
60 .map(|&p| morton_code(p, &bbox))
61 .collect();
62
63 let mut vert_new2old: Vec<i32> = (0..num_vert as i32).collect();
65 vert_new2old.sort_by(|&a, &b| vert_morton[a as usize].cmp(&vert_morton[b as usize]));
66
67 let new_num_vert = vert_new2old.partition_point(|&v| vert_morton[v as usize] < K_NO_CODE);
69 let vert_new2old_trimmed = &vert_new2old[..new_num_vert];
70
71 reindex_verts(mesh, vert_new2old_trimmed, num_vert);
72
73 let old_pos = mesh.vert_pos.clone();
75 mesh.vert_pos.resize(new_num_vert, Vec3::new(0.0, 0.0, 0.0));
76 for (new_idx, &old_idx) in vert_new2old_trimmed.iter().enumerate() {
77 mesh.vert_pos[new_idx] = old_pos[old_idx as usize];
78 }
79
80 if mesh.vert_normal.len() == num_vert {
82 let old_n = mesh.vert_normal.clone();
83 mesh.vert_normal.resize(new_num_vert, Vec3::new(0.0, 0.0, 0.0));
84 for (new_idx, &old_idx) in vert_new2old_trimmed.iter().enumerate() {
85 mesh.vert_normal[new_idx] = old_n[old_idx as usize];
86 }
87 }
88}
89
90pub fn reindex_verts(mesh: &mut ManifoldImpl, vert_new2old: &[i32], old_num_vert: usize) {
93 let mut vert_old2new = vec![-1i32; old_num_vert];
94 for (new_idx, &old_idx) in vert_new2old.iter().enumerate() {
95 vert_old2new[old_idx as usize] = new_idx as i32;
96 }
97 let has_prop = mesh.num_prop > 0;
98 for edge in mesh.halfedge.iter_mut() {
99 if edge.start_vert < 0 {
100 continue;
101 }
102 edge.start_vert = vert_old2new[edge.start_vert as usize];
103 edge.end_vert = vert_old2new[edge.end_vert as usize];
104 if !has_prop {
105 edge.prop_vert = edge.start_vert;
106 }
107 }
108}
109
110pub fn get_face_box_morton(mesh: &ManifoldImpl) -> (Vec<BBox>, Vec<u32>) {
117 let num_tri = mesh.num_tri();
118 let bbox = mesh.bbox;
119 let mut face_box = vec![BBox::default(); num_tri];
120 let mut face_morton = vec![0u32; num_tri];
121
122 for face in 0..num_tri {
123 if mesh.halfedge[3 * face].paired_halfedge < 0 {
124 face_morton[face] = K_NO_CODE;
125 continue;
126 }
127 let mut center = Vec3::new(0.0, 0.0, 0.0);
128 for i in 0..3 {
129 let pos = mesh.vert_pos[mesh.halfedge[3 * face + i].start_vert as usize];
130 center = center + pos;
131 face_box[face].union_point(pos);
132 }
133 center = center / 3.0;
134 face_morton[face] = morton_code_impl(center, &bbox);
135 }
136
137 (face_box, face_morton)
138}
139
140pub fn sort_faces(mesh: &mut ManifoldImpl, face_box: &mut Vec<BBox>, face_morton: &mut Vec<u32>) {
147 let num_tri = face_box.len();
148 let mut face_new2old: Vec<usize> = (0..num_tri).collect();
149
150 face_new2old.sort_by(|&a, &b| face_morton[a].cmp(&face_morton[b]));
152
153 let new_num_tri = face_new2old.partition_point(|&f| face_morton[f] < K_NO_CODE);
155 face_new2old.truncate(new_num_tri);
156
157 let old_morton = face_morton.clone();
159 let old_box = face_box.clone();
160 face_morton.resize(new_num_tri, 0);
161 face_box.resize(new_num_tri, BBox::default());
162 for (new_f, &old_f) in face_new2old.iter().enumerate() {
163 face_morton[new_f] = old_morton[old_f];
164 face_box[new_f] = old_box[old_f];
165 }
166
167 gather_faces(mesh, &face_new2old);
168}
169
170pub fn gather_faces(mesh: &mut ManifoldImpl, face_new2old: &[usize]) {
172 let num_tri = face_new2old.len();
173 let old_num_tri = mesh.num_tri();
174
175 if mesh.mesh_relation.tri_ref.len() == old_num_tri {
177 let old_tri_ref = mesh.mesh_relation.tri_ref.clone();
178 mesh.mesh_relation.tri_ref.resize(num_tri, Default::default());
179 for (new_f, &old_f) in face_new2old.iter().enumerate() {
180 mesh.mesh_relation.tri_ref[new_f] = old_tri_ref[old_f];
181 }
182 }
183
184 if mesh.face_normal.len() == old_num_tri {
186 let old_normals = mesh.face_normal.clone();
187 mesh.face_normal.resize(num_tri, Vec3::new(0.0, 0.0, 0.0));
188 for (new_f, &old_f) in face_new2old.iter().enumerate() {
189 mesh.face_normal[new_f] = old_normals[old_f];
190 }
191 }
192
193 let mut face_old2new = vec![-1i32; old_num_tri];
195 for (new_f, &old_f) in face_new2old.iter().enumerate() {
196 face_old2new[old_f] = new_f as i32;
197 }
198
199 let old_halfedge = mesh.halfedge.clone();
201 let old_tangent = mesh.halfedge_tangent.clone();
202 let has_tangent = !old_tangent.is_empty();
203
204 mesh.halfedge.resize(3 * num_tri, Halfedge::default());
205 if has_tangent {
206 mesh.halfedge_tangent.resize(3 * num_tri, Default::default());
207 }
208
209 for new_face in 0..num_tri {
210 let old_face = face_new2old[new_face];
211 for i in 0..3 {
212 let old_edge_idx = 3 * old_face + i;
213 let new_edge_idx = 3 * new_face + i;
214 let mut edge = old_halfedge[old_edge_idx];
215 if edge.paired_halfedge >= 0 {
217 let paired_old_face = (edge.paired_halfedge / 3) as usize;
218 let offset = edge.paired_halfedge % 3;
219 edge.paired_halfedge = 3 * face_old2new[paired_old_face] + offset;
220 }
221 mesh.halfedge[new_edge_idx] = edge;
222 if has_tangent {
223 mesh.halfedge_tangent[new_edge_idx] = old_tangent[old_edge_idx];
224 }
225 }
226 }
227}
228
229pub fn compact_props(mesh: &mut ManifoldImpl) {
235 if mesh.num_prop == 0 {
236 return;
237 }
238 let num_prop = mesh.num_prop;
239 let num_prop_verts = mesh.properties.len() / num_prop;
240
241 let mut keep = vec![false; num_prop_verts];
243 for edge in &mesh.halfedge {
244 if edge.prop_vert >= 0 && (edge.prop_vert as usize) < num_prop_verts {
245 keep[edge.prop_vert as usize] = true;
246 }
247 }
248
249 let mut prop_old2new = vec![0i32; num_prop_verts + 1];
251 for i in 0..num_prop_verts {
252 prop_old2new[i + 1] = prop_old2new[i] + if keep[i] { 1 } else { 0 };
253 }
254 let new_num_prop_verts = prop_old2new[num_prop_verts] as usize;
255
256 let old_prop = mesh.properties.clone();
258 mesh.properties.resize(num_prop * new_num_prop_verts, 0.0);
259 for old_idx in 0..num_prop_verts {
260 if !keep[old_idx] {
261 continue;
262 }
263 let new_idx = prop_old2new[old_idx] as usize;
264 for p in 0..num_prop {
265 mesh.properties[new_idx * num_prop + p] = old_prop[old_idx * num_prop + p];
266 }
267 }
268
269 for edge in mesh.halfedge.iter_mut() {
271 if edge.prop_vert >= 0 {
272 edge.prop_vert = prop_old2new[edge.prop_vert as usize];
273 }
274 }
275}
276
277pub fn sort_geometry(mesh: &mut ManifoldImpl) {
287 if mesh.halfedge.is_empty() {
288 return;
289 }
290 sort_verts(mesh);
291 let (mut face_box, mut face_morton) = get_face_box_morton(mesh);
292 sort_faces(mesh, &mut face_box, &mut face_morton);
293 if mesh.halfedge.is_empty() {
294 return;
295 }
296 compact_props(mesh);
297
298 debug_assert!(
299 mesh.halfedge.len() % 6 == 0,
300 "Not an even number of halfedges after sorting (expected multiple of 6, got {})",
301 mesh.halfedge.len()
302 );
303}
304
305#[cfg(test)]
310mod tests {
311 use super::*;
312 use crate::linalg::Mat3x4;
313 use crate::impl_mesh::ManifoldImpl;
314
315 #[test]
316 fn test_spread_bits3() {
317 assert_eq!(spread_bits3(0), 0);
320 assert_eq!(spread_bits3(1), 1);
321 assert_eq!(spread_bits3(0b10), 0b1000);
323 assert_eq!(spread_bits3(0b11), 0b1001);
324 assert_eq!(spread_bits3(0b100), 0b1000000);
325 }
326
327 #[test]
328 fn test_morton_code_basic() {
329 let bbox = BBox {
330 min: Vec3::new(0.0, 0.0, 0.0),
331 max: Vec3::new(1.0, 1.0, 1.0),
332 };
333 let code_origin = morton_code(Vec3::new(0.0, 0.0, 0.0), &bbox);
335 assert_eq!(code_origin, 0);
336
337 let code_nan = morton_code(Vec3::new(f64::NAN, 0.0, 0.0), &bbox);
339 assert_eq!(code_nan, K_NO_CODE);
340
341 let code_center = morton_code(Vec3::new(0.5, 0.5, 0.5), &bbox);
343 assert!(code_center > 0 && code_center < K_NO_CODE);
344 }
345
346 #[test]
347 fn test_morton_code_ordering() {
348 let bbox = BBox {
351 min: Vec3::new(0.0, 0.0, 0.0),
352 max: Vec3::new(8.0, 8.0, 8.0),
353 };
354 let p0 = morton_code(Vec3::new(0.0, 0.0, 0.0), &bbox);
355 let p1 = morton_code(Vec3::new(1.0, 0.0, 0.0), &bbox);
356 let p2 = morton_code(Vec3::new(2.0, 0.0, 0.0), &bbox);
357 assert!(p0 < p1);
359 assert!(p1 < p2);
360 }
361
362 #[test]
363 fn test_sort_geometry_tetrahedron() {
364 let mut m = ManifoldImpl::tetrahedron(&Mat3x4::identity());
365 assert_eq!(m.vert_pos.len(), 4);
367 assert_eq!(m.halfedge.len(), 12);
368 sort_geometry(&mut m);
369 assert_eq!(m.vert_pos.len(), 4);
371 assert_eq!(m.halfedge.len(), 12);
372 }
373
374 #[test]
375 fn test_sort_geometry_cube() {
376 let mut m = ManifoldImpl::cube(&Mat3x4::identity());
377 let vert_count = m.vert_pos.len();
378 let halfedge_count = m.halfedge.len();
379 sort_geometry(&mut m);
380 assert_eq!(m.vert_pos.len(), vert_count);
381 assert_eq!(m.halfedge.len(), halfedge_count);
382 for (i, edge) in m.halfedge.iter().enumerate() {
384 assert!(edge.paired_halfedge >= 0,
385 "halfedge {} has invalid paired_halfedge {}", i, edge.paired_halfedge);
386 let paired = &m.halfedge[edge.paired_halfedge as usize];
387 assert_eq!(paired.paired_halfedge, i as i32,
388 "halfedge {} paired -> {} but paired doesn't point back", i, edge.paired_halfedge);
389 }
390 }
391
392 #[test]
393 fn test_reindex_verts_identity() {
394 let mut m = ManifoldImpl::tetrahedron(&Mat3x4::identity());
395 let n = m.vert_pos.len();
396 let identity: Vec<i32> = (0..n as i32).collect();
398 let before: Vec<_> = m.halfedge.iter().map(|e| (e.start_vert, e.end_vert)).collect();
399 reindex_verts(&mut m, &identity, n);
400 let after: Vec<_> = m.halfedge.iter().map(|e| (e.start_vert, e.end_vert)).collect();
401 assert_eq!(before, after);
402 }
403
404 #[test]
405 fn test_sort_faces_manifold_preserved() {
406 let mut m = ManifoldImpl::cube(&Mat3x4::identity());
408 sort_geometry(&mut m);
409 assert!(m.is_2_manifold());
410 }
411}