1#[allow(unused_imports)]
6use super::functions::*;
7#[allow(unused_imports)]
8use super::functions_2::*;
9use std::collections::{HashMap, HashSet};
10
11#[derive(Debug, Clone)]
13pub struct HalfEdgeMesh {
14 pub vertices: Vec<[f64; 3]>,
16 pub half_edges: Vec<HalfEdge>,
18 pub vertex_half_edge: Vec<usize>,
20 pub face_half_edge: Vec<usize>,
22 pub vertex_deleted: Vec<bool>,
24 pub face_deleted: Vec<bool>,
26 pub he_deleted: Vec<bool>,
28}
29impl HalfEdgeMesh {
30 pub fn from_triangles(vertices: Vec<[f64; 3]>, triangles: &[[usize; 3]]) -> Self {
32 let n_verts = vertices.len();
33 let n_faces = triangles.len();
34 let n_he = n_faces * 3;
35 let mut half_edges = Vec::with_capacity(n_he);
36 let mut vertex_half_edge = vec![usize::MAX; n_verts];
37 let mut face_half_edge = Vec::with_capacity(n_faces);
38 let mut edge_map: HashMap<(usize, usize), usize> = HashMap::new();
39 for (fi, tri) in triangles.iter().enumerate() {
40 let base = half_edges.len();
41 face_half_edge.push(base);
42 for k in 0..3 {
43 let v_from = tri[k];
44 let v_to = tri[(k + 1) % 3];
45 let he_idx = base + k;
46 half_edges.push(HalfEdge {
47 vertex: v_to,
48 face: fi,
49 twin: usize::MAX,
50 next: base + (k + 1) % 3,
51 prev: base + (k + 2) % 3,
52 });
53 if vertex_half_edge[v_from] == usize::MAX {
54 vertex_half_edge[v_from] = he_idx;
55 }
56 edge_map.insert((v_from, v_to), he_idx);
57 }
58 }
59 let keys: Vec<(usize, usize)> = edge_map.keys().copied().collect();
60 for (v_from, v_to) in keys {
61 if let Some(&twin_idx) = edge_map.get(&(v_to, v_from)) {
62 let he_idx = edge_map[&(v_from, v_to)];
63 half_edges[he_idx].twin = twin_idx;
64 half_edges[twin_idx].twin = he_idx;
65 }
66 }
67 let vertex_deleted = vec![false; n_verts];
68 let face_deleted = vec![false; n_faces];
69 let he_deleted = vec![false; n_he];
70 Self {
71 vertices,
72 half_edges,
73 vertex_half_edge,
74 face_half_edge,
75 vertex_deleted,
76 face_deleted,
77 he_deleted,
78 }
79 }
80 pub fn active_vertex_count(&self) -> usize {
82 self.vertex_deleted.iter().filter(|&&d| !d).count()
83 }
84 pub fn active_face_count(&self) -> usize {
86 self.face_deleted.iter().filter(|&&d| !d).count()
87 }
88 pub fn is_boundary_half_edge(&self, he_idx: usize) -> bool {
90 self.half_edges[he_idx].twin == usize::MAX
91 }
92 pub fn is_boundary_vertex(&self, v: usize) -> bool {
94 let start = self.vertex_half_edge[v];
95 if start == usize::MAX {
96 return false;
97 }
98 let mut he = start;
99 loop {
100 if self.is_boundary_half_edge(he) {
101 return true;
102 }
103 let twin = self.half_edges[he].twin;
104 if twin == usize::MAX {
105 return true;
106 }
107 he = self.half_edges[twin].next;
108 if he == start {
109 break;
110 }
111 }
112 false
113 }
114 pub fn vertex_faces(&self, v: usize) -> Vec<usize> {
116 let mut faces = Vec::new();
117 let start = self.vertex_half_edge[v];
118 if start == usize::MAX {
119 return faces;
120 }
121 let mut he = start;
122 loop {
123 let f = self.half_edges[he].face;
124 if f != usize::MAX && !self.face_deleted[f] {
125 faces.push(f);
126 }
127 let twin = self.half_edges[he].twin;
128 if twin == usize::MAX {
129 break;
130 }
131 he = self.half_edges[twin].next;
132 if he == start {
133 break;
134 }
135 }
136 faces
137 }
138 pub fn vertex_neighbors(&self, v: usize) -> Vec<usize> {
140 let mut neighbors = Vec::new();
141 let start = self.vertex_half_edge[v];
142 if start == usize::MAX {
143 return neighbors;
144 }
145 let mut he = start;
146 loop {
147 let target = self.half_edges[he].vertex;
148 if !self.vertex_deleted[target] {
149 neighbors.push(target);
150 }
151 let twin = self.half_edges[he].twin;
152 if twin == usize::MAX {
153 break;
154 }
155 he = self.half_edges[twin].next;
156 if he == start {
157 break;
158 }
159 }
160 neighbors
161 }
162 pub fn face_normal(&self, fi: usize) -> [f64; 3] {
164 let he0 = self.face_half_edge[fi];
165 let he1 = self.half_edges[he0].next;
166 let he2 = self.half_edges[he1].next;
167 let v0_idx = self.half_edges[self.half_edges[he0].prev].vertex;
168 let v1_idx = self.half_edges[he0].vertex;
169 let v2_idx = self.half_edges[he1].vertex;
170 let _ = v2_idx;
171 let _ = he2;
172 let va = self.vertices[v0_idx];
173 let vb = self.vertices[v1_idx];
174 let vc = self.vertices[self.half_edges[he1].vertex];
175 let ab = sub3(vb, va);
176 let ac = sub3(vc, va);
177 normalize3(cross3(ab, ac))
178 }
179 pub fn face_area(&self, fi: usize) -> f64 {
181 let he0 = self.face_half_edge[fi];
182 let he1 = self.half_edges[he0].next;
183 let v0_idx = self.half_edges[self.half_edges[he0].prev].vertex;
184 let v1_idx = self.half_edges[he0].vertex;
185 let v2_idx = self.half_edges[he1].vertex;
186 let va = self.vertices[v0_idx];
187 let vb = self.vertices[v1_idx];
188 let vc = self.vertices[v2_idx];
189 let ab = sub3(vb, va);
190 let ac = sub3(vc, va);
191 0.5 * len3(cross3(ab, ac))
192 }
193 pub fn extract_triangles(&self) -> Vec<[usize; 3]> {
195 let mut tris = Vec::new();
196 for (fi, &he0) in self.face_half_edge.iter().enumerate() {
197 if self.face_deleted[fi] {
198 continue;
199 }
200 let he1 = self.half_edges[he0].next;
201 let he2 = self.half_edges[he1].next;
202 let v0 = self.half_edges[he2].vertex;
203 let v1 = self.half_edges[he0].vertex;
204 let v2 = self.half_edges[he1].vertex;
205 tris.push([v0, v1, v2]);
206 }
207 tris
208 }
209}
210#[derive(Debug, Clone)]
212pub struct MeshStats {
213 pub n_vertices: usize,
215 pub n_triangles: usize,
217 pub n_edges: usize,
219 pub avg_edge_length: f64,
221 pub min_edge_length: f64,
223 pub max_edge_length: f64,
225 pub avg_quality: f64,
227 pub min_quality: f64,
229}
230#[derive(Debug, Clone)]
232pub struct QemConfig {
233 pub target_triangles: usize,
235 pub max_error: f64,
237 pub preserve_boundary: bool,
239 pub max_normal_deviation: f64,
241 pub preserve_texture_seams: bool,
243 pub boundary_weight: f64,
245}
246impl QemConfig {
247 pub fn default_config(current_tris: usize) -> Self {
249 Self {
250 target_triangles: current_tris / 2,
251 max_error: 0.0,
252 preserve_boundary: true,
253 max_normal_deviation: std::f64::consts::FRAC_PI_4,
254 preserve_texture_seams: false,
255 boundary_weight: 100.0,
256 }
257 }
258 pub fn with_error_threshold(max_error: f64) -> Self {
260 Self {
261 target_triangles: 0,
262 max_error,
263 preserve_boundary: true,
264 max_normal_deviation: 0.0,
265 preserve_texture_seams: false,
266 boundary_weight: 100.0,
267 }
268 }
269}
270#[derive(Debug, Clone)]
272pub struct CollapseRecord {
273 pub removed: usize,
275 pub kept: usize,
277 pub removed_pos: [f64; 3],
279 pub kept_pos: [f64; 3],
281 pub collapsed_pos: [f64; 3],
283 pub removed_triangles: Vec<[usize; 3]>,
285 pub modified_triangles: Vec<[usize; 3]>,
287}
288#[derive(Debug, Clone)]
290pub struct ProgressiveMesh {
291 pub base_vertices: Vec<[f64; 3]>,
293 pub base_triangles: Vec<[usize; 3]>,
295 pub collapses: Vec<CollapseRecord>,
297}
298impl ProgressiveMesh {
299 pub fn build(vertices: &[[f64; 3]], triangles: &[[usize; 3]], target_triangles: usize) -> Self {
301 let config = QemConfig {
302 target_triangles,
303 max_error: 0.0,
304 preserve_boundary: true,
305 max_normal_deviation: 0.0,
306 preserve_texture_seams: false,
307 boundary_weight: 100.0,
308 };
309 let (base_verts, base_tris) = qem_simplify(vertices, triangles, &config);
310 Self {
311 base_vertices: base_verts,
312 base_triangles: base_tris,
313 collapses: Vec::new(),
314 }
315 }
316 pub fn base_mesh(&self) -> (&[[f64; 3]], &[[usize; 3]]) {
318 (&self.base_vertices, &self.base_triangles)
319 }
320 pub fn num_collapses(&self) -> usize {
322 self.collapses.len()
323 }
324}
325#[derive(Debug, Clone, Copy)]
332pub struct SymMat4 {
333 pub m: [f64; 10],
335}
336impl SymMat4 {
337 pub fn zero() -> Self {
339 Self { m: [0.0; 10] }
340 }
341 pub fn from_plane(a: f64, b: f64, c: f64, d: f64) -> Self {
343 Self {
344 m: [
345 a * a,
346 a * b,
347 a * c,
348 a * d,
349 b * b,
350 b * c,
351 b * d,
352 c * c,
353 c * d,
354 d * d,
355 ],
356 }
357 }
358 pub fn add(&self, other: &Self) -> Self {
360 let mut result = Self::zero();
361 for i in 0..10 {
362 result.m[i] = self.m[i] + other.m[i];
363 }
364 result
365 }
366 pub fn scale(&self, s: f64) -> Self {
368 let mut result = *self;
369 for v in &mut result.m {
370 *v *= s;
371 }
372 result
373 }
374 pub fn evaluate(&self, v: [f64; 3]) -> f64 {
376 let x = v[0];
377 let y = v[1];
378 let z = v[2];
379 self.m[0] * x * x
380 + 2.0 * self.m[1] * x * y
381 + 2.0 * self.m[2] * x * z
382 + 2.0 * self.m[3] * x
383 + self.m[4] * y * y
384 + 2.0 * self.m[5] * y * z
385 + 2.0 * self.m[6] * y
386 + self.m[7] * z * z
387 + 2.0 * self.m[8] * z
388 + self.m[9]
389 }
390 pub fn optimal_point(&self) -> Option<[f64; 3]> {
395 let a = [
396 [self.m[0], self.m[1], self.m[2]],
397 [self.m[1], self.m[4], self.m[5]],
398 [self.m[2], self.m[5], self.m[7]],
399 ];
400 let b = [-self.m[3], -self.m[6], -self.m[8]];
401 solve_3x3(a, b)
402 }
403}
404#[derive(Debug, Clone)]
406pub struct HalfEdge {
407 pub vertex: usize,
409 pub face: usize,
411 pub twin: usize,
413 pub next: usize,
415 pub prev: usize,
417}
418#[derive(Debug, Clone)]
420pub struct TextureSeamFlags {
421 pub seam_edges: HashSet<(usize, usize)>,
423}
424impl TextureSeamFlags {
425 pub fn new() -> Self {
427 Self {
428 seam_edges: HashSet::new(),
429 }
430 }
431 pub fn mark_seam(&mut self, v0: usize, v1: usize) {
433 let (lo, hi) = if v0 < v1 { (v0, v1) } else { (v1, v0) };
434 self.seam_edges.insert((lo, hi));
435 }
436 pub fn is_seam(&self, v0: usize, v1: usize) -> bool {
438 let (lo, hi) = if v0 < v1 { (v0, v1) } else { (v1, v0) };
439 self.seam_edges.contains(&(lo, hi))
440 }
441 pub fn count(&self) -> usize {
443 self.seam_edges.len()
444 }
445}
446#[derive(Debug, Clone)]
448pub struct TopologyValidation {
449 pub is_valid: bool,
451 pub non_manifold_edges: usize,
453 pub isolated_vertices: usize,
455 pub degenerate_triangles: usize,
457}
458#[derive(Debug, Clone)]
460pub(super) struct CollapseCandidate {
461 pub(super) v0: usize,
463 pub(super) v1: usize,
465 pub(super) optimal_pos: [f64; 3],
467 pub(super) cost: f64,
469}