oxihuman_mesh/
mesh_multiresolution.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
10pub struct MrLevel {
11 pub positions: Vec<[f32; 3]>,
12 pub indices: Vec<u32>,
13 pub displacements: Vec<[f32; 3]>,
14}
15
16#[derive(Debug, Clone)]
18pub struct MultiresolutionMesh {
19 pub levels: Vec<MrLevel>,
20 pub base_level: usize,
21}
22
23impl MultiresolutionMesh {
24 pub fn new(positions: Vec<[f32; 3]>, indices: Vec<u32>) -> Self {
26 let displacements = vec![[0.0_f32; 3]; positions.len()];
27 let level0 = MrLevel {
28 positions,
29 indices,
30 displacements,
31 };
32 Self {
33 levels: vec![level0],
34 base_level: 0,
35 }
36 }
37
38 pub fn level_count(&self) -> usize {
40 self.levels.len()
41 }
42}
43
44pub fn push_level(mr: &mut MultiresolutionMesh) {
46 let top = mr.levels.last().expect("at least one level");
47 let new_positions = top.positions.clone();
48 let new_indices = top.indices.clone();
49 let displacements = vec![[0.0_f32; 3]; new_positions.len()];
50 mr.levels.push(MrLevel {
51 positions: new_positions,
52 indices: new_indices,
53 displacements,
54 });
55}
56
57pub fn pop_level(mr: &mut MultiresolutionMesh) -> bool {
59 if mr.levels.len() > 1 {
60 mr.levels.pop();
61 true
62 } else {
63 false
64 }
65}
66
67pub fn apply_displacement(
69 mr: &mut MultiresolutionMesh,
70 level: usize,
71 vertex: usize,
72 delta: [f32; 3],
73) {
74 if let Some(lvl) = mr.levels.get_mut(level) {
75 if let Some(d) = lvl.displacements.get_mut(vertex) {
76 d[0] += delta[0];
77 d[1] += delta[1];
78 d[2] += delta[2];
79 }
80 }
81}
82
83pub fn total_displacement_magnitude(mr: &MultiresolutionMesh, level: usize) -> f32 {
85 if let Some(lvl) = mr.levels.get(level) {
86 lvl.displacements
87 .iter()
88 .map(|d| (d[0] * d[0] + d[1] * d[1] + d[2] * d[2]).sqrt())
89 .sum()
90 } else {
91 0.0
92 }
93}
94
95pub fn reset_displacements(mr: &mut MultiresolutionMesh, level: usize) {
97 if let Some(lvl) = mr.levels.get_mut(level) {
98 for d in &mut lvl.displacements {
99 *d = [0.0, 0.0, 0.0];
100 }
101 }
102}
103
104#[cfg(test)]
105mod tests {
106 use super::*;
107
108 fn sample_mr() -> MultiresolutionMesh {
109 let pos = vec![[0.0_f32, 0.0, 0.0], [1.0, 0.0, 0.0], [0.5, 1.0, 0.0]];
110 let idx = vec![0u32, 1, 2];
111 MultiresolutionMesh::new(pos, idx)
112 }
113
114 #[test]
115 fn test_new_has_one_level() {
116 let mr = sample_mr();
118 assert_eq!(mr.level_count(), 1);
119 }
120
121 #[test]
122 fn test_push_level_increments_count() {
123 let mut mr = sample_mr();
125 push_level(&mut mr);
126 assert_eq!(mr.level_count(), 2);
127 }
128
129 #[test]
130 fn test_pop_level_decrements_count() {
131 let mut mr = sample_mr();
133 push_level(&mut mr);
134 assert!(pop_level(&mut mr));
135 assert_eq!(mr.level_count(), 1);
136 }
137
138 #[test]
139 fn test_pop_level_base_returns_false() {
140 let mut mr = sample_mr();
142 assert!(!pop_level(&mut mr));
143 assert_eq!(mr.level_count(), 1);
144 }
145
146 #[test]
147 fn test_apply_displacement_accumulates() {
148 let mut mr = sample_mr();
150 apply_displacement(&mut mr, 0, 0, [1.0, 0.0, 0.0]);
151 apply_displacement(&mut mr, 0, 0, [0.0, 2.0, 0.0]);
152 let d = mr.levels[0].displacements[0];
153 assert!((d[0] - 1.0).abs() < 1e-6);
154 assert!((d[1] - 2.0).abs() < 1e-6);
155 }
156
157 #[test]
158 fn test_total_displacement_magnitude_zero_initially() {
159 let mr = sample_mr();
161 assert!((total_displacement_magnitude(&mr, 0) - 0.0).abs() < 1e-6);
162 }
163
164 #[test]
165 fn test_total_displacement_magnitude_nonzero_after_apply() {
166 let mut mr = sample_mr();
168 apply_displacement(&mut mr, 0, 0, [3.0, 4.0, 0.0]);
169 let mag = total_displacement_magnitude(&mr, 0);
170 assert!(mag > 4.9);
171 }
172
173 #[test]
174 fn test_reset_displacements() {
175 let mut mr = sample_mr();
177 apply_displacement(&mut mr, 0, 0, [1.0, 1.0, 1.0]);
178 reset_displacements(&mut mr, 0);
179 assert!((total_displacement_magnitude(&mr, 0) - 0.0).abs() < 1e-6);
180 }
181
182 #[test]
183 fn test_invalid_level_ignored() {
184 let mut mr = sample_mr();
186 apply_displacement(&mut mr, 99, 0, [1.0, 0.0, 0.0]);
187 reset_displacements(&mut mr, 99);
188 assert_eq!(total_displacement_magnitude(&mr, 99), 0.0);
189 }
190}