1use super::functions::*;
6use std::collections::{HashMap, HashSet};
7
8#[derive(Debug, Clone)]
10pub struct HalfEdgeMesh {
11 pub vertices: Vec<[f64; 3]>,
13 pub half_edges: Vec<HalfEdge>,
15 pub vertex_half_edge: Vec<usize>,
17 pub face_half_edge: Vec<usize>,
19 pub vertex_deleted: Vec<bool>,
21 pub face_deleted: Vec<bool>,
23 pub he_deleted: Vec<bool>,
25}
26impl HalfEdgeMesh {
27 pub fn from_triangles(vertices: Vec<[f64; 3]>, triangles: &[[usize; 3]]) -> Self {
29 let n_verts = vertices.len();
30 let n_faces = triangles.len();
31 let n_he = n_faces * 3;
32 let mut half_edges = Vec::with_capacity(n_he);
33 let mut vertex_half_edge = vec![usize::MAX; n_verts];
34 let mut face_half_edge = Vec::with_capacity(n_faces);
35 let mut edge_map: HashMap<(usize, usize), usize> = HashMap::new();
36 for (fi, tri) in triangles.iter().enumerate() {
37 let base = half_edges.len();
38 face_half_edge.push(base);
39 for k in 0..3 {
40 let v_from = tri[k];
41 let v_to = tri[(k + 1) % 3];
42 let he_idx = base + k;
43 half_edges.push(HalfEdge {
44 vertex: v_to,
45 face: fi,
46 twin: usize::MAX,
47 next: base + (k + 1) % 3,
48 prev: base + (k + 2) % 3,
49 });
50 if vertex_half_edge[v_from] == usize::MAX {
51 vertex_half_edge[v_from] = he_idx;
52 }
53 edge_map.insert((v_from, v_to), he_idx);
54 }
55 }
56 let keys: Vec<(usize, usize)> = edge_map.keys().copied().collect();
57 for (v_from, v_to) in keys {
58 if let Some(&twin_idx) = edge_map.get(&(v_to, v_from)) {
59 let he_idx = edge_map[&(v_from, v_to)];
60 half_edges[he_idx].twin = twin_idx;
61 half_edges[twin_idx].twin = he_idx;
62 }
63 }
64 let vertex_deleted = vec![false; n_verts];
65 let face_deleted = vec![false; n_faces];
66 let he_deleted = vec![false; n_he];
67 Self {
68 vertices,
69 half_edges,
70 vertex_half_edge,
71 face_half_edge,
72 vertex_deleted,
73 face_deleted,
74 he_deleted,
75 }
76 }
77 pub fn active_vertex_count(&self) -> usize {
79 self.vertex_deleted.iter().filter(|&&d| !d).count()
80 }
81 pub fn active_face_count(&self) -> usize {
83 self.face_deleted.iter().filter(|&&d| !d).count()
84 }
85 pub fn is_boundary_half_edge(&self, he_idx: usize) -> bool {
87 self.half_edges[he_idx].twin == usize::MAX
88 }
89 pub fn is_boundary_vertex(&self, v: usize) -> bool {
91 let start = self.vertex_half_edge[v];
92 if start == usize::MAX {
93 return false;
94 }
95 let mut he = start;
96 loop {
97 if self.is_boundary_half_edge(he) {
98 return true;
99 }
100 let twin = self.half_edges[he].twin;
101 if twin == usize::MAX {
102 return true;
103 }
104 he = self.half_edges[twin].next;
105 if he == start {
106 break;
107 }
108 }
109 false
110 }
111 pub fn vertex_faces(&self, v: usize) -> Vec<usize> {
113 let mut faces = Vec::new();
114 let start = self.vertex_half_edge[v];
115 if start == usize::MAX {
116 return faces;
117 }
118 let mut he = start;
119 loop {
120 let f = self.half_edges[he].face;
121 if f != usize::MAX && !self.face_deleted[f] {
122 faces.push(f);
123 }
124 let twin = self.half_edges[he].twin;
125 if twin == usize::MAX {
126 break;
127 }
128 he = self.half_edges[twin].next;
129 if he == start {
130 break;
131 }
132 }
133 faces
134 }
135 pub fn vertex_neighbors(&self, v: usize) -> Vec<usize> {
137 let mut neighbors = Vec::new();
138 let start = self.vertex_half_edge[v];
139 if start == usize::MAX {
140 return neighbors;
141 }
142 let mut he = start;
143 loop {
144 let target = self.half_edges[he].vertex;
145 if !self.vertex_deleted[target] {
146 neighbors.push(target);
147 }
148 let twin = self.half_edges[he].twin;
149 if twin == usize::MAX {
150 break;
151 }
152 he = self.half_edges[twin].next;
153 if he == start {
154 break;
155 }
156 }
157 neighbors
158 }
159 pub fn face_normal(&self, fi: usize) -> [f64; 3] {
161 let he0 = self.face_half_edge[fi];
162 let he1 = self.half_edges[he0].next;
163 let he2 = self.half_edges[he1].next;
164 let v0_idx = self.half_edges[self.half_edges[he0].prev].vertex;
165 let v1_idx = self.half_edges[he0].vertex;
166 let v2_idx = self.half_edges[he1].vertex;
167 let _ = v2_idx;
168 let _ = he2;
169 let va = self.vertices[v0_idx];
170 let vb = self.vertices[v1_idx];
171 let vc = self.vertices[self.half_edges[he1].vertex];
172 let ab = sub3(vb, va);
173 let ac = sub3(vc, va);
174 normalize3(cross3(ab, ac))
175 }
176 pub fn face_area(&self, fi: usize) -> f64 {
178 let he0 = self.face_half_edge[fi];
179 let he1 = self.half_edges[he0].next;
180 let v0_idx = self.half_edges[self.half_edges[he0].prev].vertex;
181 let v1_idx = self.half_edges[he0].vertex;
182 let v2_idx = self.half_edges[he1].vertex;
183 let va = self.vertices[v0_idx];
184 let vb = self.vertices[v1_idx];
185 let vc = self.vertices[v2_idx];
186 let ab = sub3(vb, va);
187 let ac = sub3(vc, va);
188 0.5 * len3(cross3(ab, ac))
189 }
190 pub fn extract_triangles(&self) -> Vec<[usize; 3]> {
192 let mut tris = Vec::new();
193 for (fi, &he0) in self.face_half_edge.iter().enumerate() {
194 if self.face_deleted[fi] {
195 continue;
196 }
197 let he1 = self.half_edges[he0].next;
198 let he2 = self.half_edges[he1].next;
199 let v0 = self.half_edges[he2].vertex;
200 let v1 = self.half_edges[he0].vertex;
201 let v2 = self.half_edges[he1].vertex;
202 tris.push([v0, v1, v2]);
203 }
204 tris
205 }
206}
207#[derive(Debug, Clone)]
209pub struct MeshStats {
210 pub n_vertices: usize,
212 pub n_triangles: usize,
214 pub n_edges: usize,
216 pub avg_edge_length: f64,
218 pub min_edge_length: f64,
220 pub max_edge_length: f64,
222 pub avg_quality: f64,
224 pub min_quality: f64,
226}
227#[derive(Debug, Clone)]
229pub struct QemConfig {
230 pub target_triangles: usize,
232 pub max_error: f64,
234 pub preserve_boundary: bool,
236 pub max_normal_deviation: f64,
238 pub preserve_texture_seams: bool,
240 pub boundary_weight: f64,
242}
243impl QemConfig {
244 pub fn default_config(current_tris: usize) -> Self {
246 Self {
247 target_triangles: current_tris / 2,
248 max_error: 0.0,
249 preserve_boundary: true,
250 max_normal_deviation: std::f64::consts::FRAC_PI_4,
251 preserve_texture_seams: false,
252 boundary_weight: 100.0,
253 }
254 }
255 pub fn with_error_threshold(max_error: f64) -> Self {
257 Self {
258 target_triangles: 0,
259 max_error,
260 preserve_boundary: true,
261 max_normal_deviation: 0.0,
262 preserve_texture_seams: false,
263 boundary_weight: 100.0,
264 }
265 }
266}
267#[derive(Debug, Clone)]
269pub struct CollapseRecord {
270 pub removed: usize,
272 pub kept: usize,
274 pub removed_pos: [f64; 3],
276 pub kept_pos: [f64; 3],
278 pub collapsed_pos: [f64; 3],
280 pub removed_triangles: Vec<[usize; 3]>,
282 pub modified_triangles: Vec<[usize; 3]>,
284}
285#[derive(Debug, Clone)]
287pub struct ProgressiveMesh {
288 pub base_vertices: Vec<[f64; 3]>,
290 pub base_triangles: Vec<[usize; 3]>,
292 pub collapses: Vec<CollapseRecord>,
294}
295impl ProgressiveMesh {
296 pub fn build(vertices: &[[f64; 3]], triangles: &[[usize; 3]], target_triangles: usize) -> Self {
298 let config = QemConfig {
299 target_triangles,
300 max_error: 0.0,
301 preserve_boundary: true,
302 max_normal_deviation: 0.0,
303 preserve_texture_seams: false,
304 boundary_weight: 100.0,
305 };
306 let (base_verts, base_tris) = qem_simplify(vertices, triangles, &config);
307 Self {
308 base_vertices: base_verts,
309 base_triangles: base_tris,
310 collapses: Vec::new(),
311 }
312 }
313 pub fn base_mesh(&self) -> (&[[f64; 3]], &[[usize; 3]]) {
315 (&self.base_vertices, &self.base_triangles)
316 }
317 pub fn num_collapses(&self) -> usize {
319 self.collapses.len()
320 }
321}
322#[derive(Debug, Clone, Copy)]
329pub struct SymMat4 {
330 pub m: [f64; 10],
332}
333impl SymMat4 {
334 pub fn zero() -> Self {
336 Self { m: [0.0; 10] }
337 }
338 pub fn from_plane(a: f64, b: f64, c: f64, d: f64) -> Self {
340 Self {
341 m: [
342 a * a,
343 a * b,
344 a * c,
345 a * d,
346 b * b,
347 b * c,
348 b * d,
349 c * c,
350 c * d,
351 d * d,
352 ],
353 }
354 }
355 pub fn add(&self, other: &Self) -> Self {
357 let mut result = Self::zero();
358 for i in 0..10 {
359 result.m[i] = self.m[i] + other.m[i];
360 }
361 result
362 }
363 pub fn scale(&self, s: f64) -> Self {
365 let mut result = *self;
366 for v in &mut result.m {
367 *v *= s;
368 }
369 result
370 }
371 pub fn evaluate(&self, v: [f64; 3]) -> f64 {
373 let x = v[0];
374 let y = v[1];
375 let z = v[2];
376 self.m[0] * x * x
377 + 2.0 * self.m[1] * x * y
378 + 2.0 * self.m[2] * x * z
379 + 2.0 * self.m[3] * x
380 + self.m[4] * y * y
381 + 2.0 * self.m[5] * y * z
382 + 2.0 * self.m[6] * y
383 + self.m[7] * z * z
384 + 2.0 * self.m[8] * z
385 + self.m[9]
386 }
387 pub fn optimal_point(&self) -> Option<[f64; 3]> {
392 let a = [
393 [self.m[0], self.m[1], self.m[2]],
394 [self.m[1], self.m[4], self.m[5]],
395 [self.m[2], self.m[5], self.m[7]],
396 ];
397 let b = [-self.m[3], -self.m[6], -self.m[8]];
398 solve_3x3(a, b)
399 }
400}
401#[derive(Debug, Clone)]
403pub struct HalfEdge {
404 pub vertex: usize,
406 pub face: usize,
408 pub twin: usize,
410 pub next: usize,
412 pub prev: usize,
414}
415#[derive(Debug, Clone)]
417pub struct TextureSeamFlags {
418 pub seam_edges: HashSet<(usize, usize)>,
420}
421impl TextureSeamFlags {
422 pub fn new() -> Self {
424 Self {
425 seam_edges: HashSet::new(),
426 }
427 }
428 pub fn mark_seam(&mut self, v0: usize, v1: usize) {
430 let (lo, hi) = if v0 < v1 { (v0, v1) } else { (v1, v0) };
431 self.seam_edges.insert((lo, hi));
432 }
433 pub fn is_seam(&self, v0: usize, v1: usize) -> bool {
435 let (lo, hi) = if v0 < v1 { (v0, v1) } else { (v1, v0) };
436 self.seam_edges.contains(&(lo, hi))
437 }
438 pub fn count(&self) -> usize {
440 self.seam_edges.len()
441 }
442}
443#[derive(Debug, Clone)]
445pub struct TopologyValidation {
446 pub is_valid: bool,
448 pub non_manifold_edges: usize,
450 pub isolated_vertices: usize,
452 pub degenerate_triangles: usize,
454}
455#[derive(Debug, Clone)]
457pub(super) struct CollapseCandidate {
458 pub(super) v0: usize,
460 pub(super) v1: usize,
462 pub(super) optimal_pos: [f64; 3],
464 pub(super) cost: f64,
466}