oxihuman_morph/
pose_space_deform.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct PsdExample {
10 pub pose: Vec<f32>,
11 pub deltas: Vec<[f32; 3]>,
12 pub weight: f32,
13}
14
15#[derive(Debug, Clone)]
17pub struct PoseSpaceDeform {
18 pub examples: Vec<PsdExample>,
19 pub current_deltas: Vec<[f32; 3]>,
20}
21
22impl PoseSpaceDeform {
23 pub fn new(vertex_count: usize) -> Self {
24 PoseSpaceDeform {
25 examples: Vec::new(),
26 current_deltas: vec![[0.0; 3]; vertex_count],
27 }
28 }
29}
30
31pub fn new_psd(vertex_count: usize) -> PoseSpaceDeform {
33 PoseSpaceDeform::new(vertex_count)
34}
35
36pub fn psd_add_example(psd: &mut PoseSpaceDeform, pose: Vec<f32>, deltas: Vec<[f32; 3]>) {
38 psd.examples.push(PsdExample {
39 pose,
40 deltas,
41 weight: 0.0,
42 });
43}
44
45pub fn psd_example_count(psd: &PoseSpaceDeform) -> usize {
47 psd.examples.len()
48}
49
50pub fn psd_evaluate<'a>(psd: &'a mut PoseSpaceDeform, current_pose: &[f32]) -> &'a [[f32; 3]] {
52 for ex in &mut psd.examples {
53 let n = ex.pose.len().min(current_pose.len());
54 let dist: f32 = (0..n)
55 .map(|i| (ex.pose[i] - current_pose[i]).powi(2))
56 .sum::<f32>()
57 .sqrt();
58 ex.weight = if dist < 1e-6 { 1.0 } else { 1.0 / (1.0 + dist) };
59 }
60 if let Some(best) = psd.examples.iter().max_by(|a, b| {
62 a.weight
63 .partial_cmp(&b.weight)
64 .unwrap_or(std::cmp::Ordering::Equal)
65 }) {
66 let deltas = best.deltas.clone();
67 let n = psd.current_deltas.len().min(deltas.len());
68 psd.current_deltas[..n].copy_from_slice(&deltas[..n]);
69 }
70 &psd.current_deltas
71}
72
73pub fn psd_reset(psd: &mut PoseSpaceDeform) {
75 for d in &mut psd.current_deltas {
76 *d = [0.0; 3];
77 }
78}
79
80pub fn psd_to_json(psd: &PoseSpaceDeform) -> String {
82 format!(
83 r#"{{"examples":{},"vertices":{}}}"#,
84 psd.examples.len(),
85 psd.current_deltas.len()
86 )
87}
88
89pub fn psd_vertex_count(psd: &PoseSpaceDeform) -> usize {
91 psd.current_deltas.len()
92}
93
94#[cfg(test)]
95mod tests {
96 use super::*;
97
98 #[test]
99 fn test_new_psd_vertex_count() {
100 let p = new_psd(12);
101 assert_eq!(psd_vertex_count(&p), 12 ,);
102 }
103
104 #[test]
105 fn test_initial_no_examples() {
106 let p = new_psd(5);
107 assert_eq!(
108 psd_example_count(&p),
109 0, );
111 }
112
113 #[test]
114 fn test_add_example_increases_count() {
115 let mut p = new_psd(5);
116 psd_add_example(&mut p, vec![0.0; 4], vec![[0.0; 3]; 5]);
117 assert_eq!(psd_example_count(&p), 1 ,);
118 }
119
120 #[test]
121 fn test_evaluate_exact_pose_sets_deltas() {
122 let mut p = new_psd(3);
123 psd_add_example(&mut p, vec![1.0, 0.0], vec![[0.5, 0.0, 0.0]; 3]);
124 psd_evaluate(&mut p, &[1.0, 0.0]);
125 assert!(p.current_deltas[0][0] > 0.0, );
126 }
127
128 #[test]
129 fn test_reset_zeroes_deltas() {
130 let mut p = new_psd(3);
131 psd_add_example(&mut p, vec![0.0; 2], vec![[1.0; 3]; 3]);
132 psd_evaluate(&mut p, &[0.0; 2]);
133 psd_reset(&mut p);
134 for d in &p.current_deltas {
135 assert!((d[0]).abs() < 1e-6 ,);
136 }
137 }
138
139 #[test]
140 fn test_to_json_contains_examples() {
141 let p = new_psd(4);
142 let j = psd_to_json(&p);
143 assert!(j.contains("examples") ,);
144 }
145
146 #[test]
147 fn test_to_json_contains_vertices() {
148 let p = new_psd(7);
149 let j = psd_to_json(&p);
150 assert!(j.contains("7") ,);
151 }
152
153 #[test]
154 fn test_initial_deltas_zero() {
155 let p = new_psd(6);
156 for d in &p.current_deltas {
157 assert!((d[0]).abs() < 1e-6 ,);
158 }
159 }
160
161 #[test]
162 fn test_multiple_examples() {
163 let mut p = new_psd(2);
164 psd_add_example(&mut p, vec![0.0], vec![[0.0; 3]; 2]);
165 psd_add_example(&mut p, vec![1.0], vec![[1.0; 3]; 2]);
166 assert_eq!(
167 psd_example_count(&p),
168 2, );
170 }
171
172 #[test]
173 fn test_example_weights_initially_zero() {
174 let mut p = new_psd(2);
175 psd_add_example(&mut p, vec![0.0], vec![[0.0; 3]; 2]);
176 assert!((p.examples[0].weight).abs() < 1e-6, );
177 }
178
179 #[test]
180 fn test_evaluate_no_examples_keeps_zero() {
181 let mut p = new_psd(3);
182 psd_evaluate(&mut p, &[0.5]);
183 for d in &p.current_deltas {
184 assert!((d[0]).abs() < 1e-6 ,);
185 }
186 }
187}