oxihuman_morph/
hand_thickness_control.rs1#![allow(dead_code)]
5
6#[allow(dead_code)]
10#[derive(Debug, Clone)]
11pub struct HandThicknessConfig {
12 pub min_thickness: f32,
13 pub max_thickness: f32,
14}
15
16#[allow(dead_code)]
18#[derive(Debug, Clone)]
19pub struct HandThicknessState {
20 pub left_thickness: f32,
21 pub right_thickness: f32,
22 pub finger_girth: f32,
23 pub palm_width: f32,
24}
25
26#[allow(dead_code)]
27pub fn default_hand_thickness_config() -> HandThicknessConfig {
28 HandThicknessConfig {
29 min_thickness: 0.0,
30 max_thickness: 1.0,
31 }
32}
33
34#[allow(dead_code)]
35pub fn new_hand_thickness_state() -> HandThicknessState {
36 HandThicknessState {
37 left_thickness: 0.5,
38 right_thickness: 0.5,
39 finger_girth: 0.5,
40 palm_width: 0.5,
41 }
42}
43
44#[allow(dead_code)]
45pub fn ht_set_left(state: &mut HandThicknessState, cfg: &HandThicknessConfig, v: f32) {
46 state.left_thickness = v.clamp(cfg.min_thickness, cfg.max_thickness);
47}
48
49#[allow(dead_code)]
50pub fn ht_set_right(state: &mut HandThicknessState, cfg: &HandThicknessConfig, v: f32) {
51 state.right_thickness = v.clamp(cfg.min_thickness, cfg.max_thickness);
52}
53
54#[allow(dead_code)]
55pub fn ht_set_finger_girth(state: &mut HandThicknessState, v: f32) {
56 state.finger_girth = v.clamp(0.0, 1.0);
57}
58
59#[allow(dead_code)]
60pub fn ht_set_palm_width(state: &mut HandThicknessState, v: f32) {
61 state.palm_width = v.clamp(0.0, 1.0);
62}
63
64#[allow(dead_code)]
65pub fn ht_reset(state: &mut HandThicknessState) {
66 *state = new_hand_thickness_state();
67}
68
69#[allow(dead_code)]
70pub fn ht_to_weights(state: &HandThicknessState) -> Vec<(String, f32)> {
71 vec![
72 ("hand_thickness_left".to_string(), state.left_thickness),
73 ("hand_thickness_right".to_string(), state.right_thickness),
74 ("hand_finger_girth".to_string(), state.finger_girth),
75 ("hand_palm_width".to_string(), state.palm_width),
76 ]
77}
78
79#[allow(dead_code)]
80pub fn ht_to_json(state: &HandThicknessState) -> String {
81 format!(
82 r#"{{"left_thickness":{:.4},"right_thickness":{:.4},"finger_girth":{:.4},"palm_width":{:.4}}}"#,
83 state.left_thickness, state.right_thickness, state.finger_girth, state.palm_width
84 )
85}
86
87#[allow(dead_code)]
88pub fn ht_blend(a: &HandThicknessState, b: &HandThicknessState, t: f32) -> HandThicknessState {
89 let t = t.clamp(0.0, 1.0);
90 HandThicknessState {
91 left_thickness: a.left_thickness + (b.left_thickness - a.left_thickness) * t,
92 right_thickness: a.right_thickness + (b.right_thickness - a.right_thickness) * t,
93 finger_girth: a.finger_girth + (b.finger_girth - a.finger_girth) * t,
94 palm_width: a.palm_width + (b.palm_width - a.palm_width) * t,
95 }
96}
97
98#[cfg(test)]
99mod tests {
100 use super::*;
101
102 #[test]
103 fn test_default_config() {
104 let cfg = default_hand_thickness_config();
105 assert!(cfg.min_thickness.abs() < 1e-6);
106 assert!((cfg.max_thickness - 1.0).abs() < 1e-6);
107 }
108
109 #[test]
110 fn test_new_state() {
111 let s = new_hand_thickness_state();
112 assert!((s.left_thickness - 0.5).abs() < 1e-6);
113 assert!((s.finger_girth - 0.5).abs() < 1e-6);
114 }
115
116 #[test]
117 fn test_set_left_clamps() {
118 let cfg = default_hand_thickness_config();
119 let mut s = new_hand_thickness_state();
120 ht_set_left(&mut s, &cfg, 5.0);
121 assert!((s.left_thickness - 1.0).abs() < 1e-6);
122 }
123
124 #[test]
125 fn test_set_right() {
126 let cfg = default_hand_thickness_config();
127 let mut s = new_hand_thickness_state();
128 ht_set_right(&mut s, &cfg, 0.3);
129 assert!((s.right_thickness - 0.3).abs() < 1e-6);
130 }
131
132 #[test]
133 fn test_set_finger_girth() {
134 let mut s = new_hand_thickness_state();
135 ht_set_finger_girth(&mut s, 0.8);
136 assert!((s.finger_girth - 0.8).abs() < 1e-6);
137 }
138
139 #[test]
140 fn test_set_palm_width() {
141 let mut s = new_hand_thickness_state();
142 ht_set_palm_width(&mut s, 0.2);
143 assert!((s.palm_width - 0.2).abs() < 1e-6);
144 }
145
146 #[test]
147 fn test_reset() {
148 let cfg = default_hand_thickness_config();
149 let mut s = new_hand_thickness_state();
150 ht_set_left(&mut s, &cfg, 0.9);
151 ht_reset(&mut s);
152 assert!((s.left_thickness - 0.5).abs() < 1e-6);
153 }
154
155 #[test]
156 fn test_to_weights() {
157 let s = new_hand_thickness_state();
158 assert_eq!(ht_to_weights(&s).len(), 4);
159 }
160
161 #[test]
162 fn test_to_json() {
163 let s = new_hand_thickness_state();
164 let j = ht_to_json(&s);
165 assert!(j.contains("left_thickness"));
166 }
167
168 #[test]
169 fn test_blend() {
170 let a = new_hand_thickness_state();
171 let mut b = new_hand_thickness_state();
172 b.left_thickness = 1.0;
173 let mid = ht_blend(&a, &b, 0.5);
174 assert!((mid.left_thickness - 0.75).abs() < 1e-6);
175 }
176}