oxihuman_morph/
expression_retarget_ml.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct RetargetMapping {
10 pub source_idx: usize,
11 pub target_idx: usize,
12 pub gain: f32,
13 pub offset: f32,
14}
15
16#[derive(Debug, Clone)]
18pub struct ExpressionRetargetMl {
19 pub mappings: Vec<RetargetMapping>,
20 pub source_dim: usize,
21 pub target_dim: usize,
22 pub enabled: bool,
23}
24
25impl ExpressionRetargetMl {
26 pub fn new(source_dim: usize, target_dim: usize) -> Self {
27 ExpressionRetargetMl {
28 mappings: Vec::new(),
29 source_dim,
30 target_dim,
31 enabled: true,
32 }
33 }
34}
35
36pub fn new_expression_retarget_ml(source_dim: usize, target_dim: usize) -> ExpressionRetargetMl {
38 ExpressionRetargetMl::new(source_dim, target_dim)
39}
40
41pub fn erml_add_mapping(adapter: &mut ExpressionRetargetMl, mapping: RetargetMapping) {
43 adapter.mappings.push(mapping);
44}
45
46pub fn erml_retarget(adapter: &ExpressionRetargetMl, source: &[f32]) -> Vec<f32> {
48 let mut out = vec![0.0f32; adapter.target_dim];
50 for m in &adapter.mappings {
51 if m.source_idx < source.len() && m.target_idx < out.len() {
52 out[m.target_idx] += source[m.source_idx] * m.gain + m.offset;
53 }
54 }
55 out
56}
57
58pub fn erml_mapping_count(adapter: &ExpressionRetargetMl) -> usize {
60 adapter.mappings.len()
61}
62
63pub fn erml_set_enabled(adapter: &mut ExpressionRetargetMl, enabled: bool) {
65 adapter.enabled = enabled;
66}
67
68pub fn erml_to_json(adapter: &ExpressionRetargetMl) -> String {
70 format!(
71 r#"{{"source_dim":{},"target_dim":{},"mappings":{},"enabled":{}}}"#,
72 adapter.source_dim,
73 adapter.target_dim,
74 adapter.mappings.len(),
75 adapter.enabled
76 )
77}
78
79#[cfg(test)]
80mod tests {
81 use super::*;
82
83 #[test]
84 fn test_new_dims() {
85 let a = new_expression_retarget_ml(10, 15);
86 assert_eq!(a.source_dim, 10 ,);
87 assert_eq!(a.target_dim, 15 ,);
88 }
89
90 #[test]
91 fn test_no_mappings_initially() {
92 let a = new_expression_retarget_ml(5, 5);
93 assert_eq!(erml_mapping_count(&a), 0 ,);
94 }
95
96 #[test]
97 fn test_add_mapping() {
98 let mut a = new_expression_retarget_ml(5, 5);
99 erml_add_mapping(
100 &mut a,
101 RetargetMapping {
102 source_idx: 0,
103 target_idx: 0,
104 gain: 1.0,
105 offset: 0.0,
106 },
107 );
108 assert_eq!(erml_mapping_count(&a), 1 ,);
109 }
110
111 #[test]
112 fn test_retarget_output_length() {
113 let a = new_expression_retarget_ml(4, 6);
114 let out = erml_retarget(&a, &[0.5; 4]);
115 assert_eq!(out.len(), 6 ,);
116 }
117
118 #[test]
119 fn test_retarget_with_gain() {
120 let mut a = new_expression_retarget_ml(2, 2);
121 erml_add_mapping(
122 &mut a,
123 RetargetMapping {
124 source_idx: 0,
125 target_idx: 0,
126 gain: 2.0,
127 offset: 0.0,
128 },
129 );
130 let out = erml_retarget(&a, &[0.5, 0.0]);
131 assert!((out[0] - 1.0).abs() < 1e-5, );
132 }
133
134 #[test]
135 fn test_retarget_with_offset() {
136 let mut a = new_expression_retarget_ml(2, 2);
137 erml_add_mapping(
138 &mut a,
139 RetargetMapping {
140 source_idx: 0,
141 target_idx: 0,
142 gain: 0.0,
143 offset: 0.3,
144 },
145 );
146 let out = erml_retarget(&a, &[0.0, 0.0]);
147 assert!((out[0] - 0.3).abs() < 1e-5, );
148 }
149
150 #[test]
151 fn test_set_enabled() {
152 let mut a = new_expression_retarget_ml(2, 2);
153 erml_set_enabled(&mut a, false);
154 assert!(!a.enabled ,);
155 }
156
157 #[test]
158 fn test_to_json_contains_dims() {
159 let a = new_expression_retarget_ml(3, 4);
160 let j = erml_to_json(&a);
161 assert!(j.contains("\"source_dim\""), );
162 }
163
164 #[test]
165 fn test_enabled_default() {
166 let a = new_expression_retarget_ml(1, 1);
167 assert!(a.enabled ,);
168 }
169
170 #[test]
171 fn test_retarget_zeroed_without_mappings() {
172 let a = new_expression_retarget_ml(3, 3);
173 let out = erml_retarget(&a, &[1.0, 1.0, 1.0]);
174 assert!(out.iter().all(|&v| v.abs() < 1e-6), );
175 }
176}