oxihuman_morph/
calf_control.rs1#![allow(dead_code)]
7
8#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub struct CalfConfig {
11 pub max_muscle_size: f32,
12}
13
14#[allow(dead_code)]
15#[derive(Debug, Clone)]
16pub struct CalfState {
17 pub muscle_l: f32,
18 pub muscle_r: f32,
19 pub definition_l: f32,
20 pub definition_r: f32,
21}
22
23#[allow(dead_code)]
24pub fn default_calf_config() -> CalfConfig {
25 CalfConfig {
26 max_muscle_size: 1.0,
27 }
28}
29
30#[allow(dead_code)]
31pub fn new_calf_state() -> CalfState {
32 CalfState {
33 muscle_l: 0.0,
34 muscle_r: 0.0,
35 definition_l: 0.0,
36 definition_r: 0.0,
37 }
38}
39
40#[allow(dead_code)]
41pub fn calf_set_muscle(state: &mut CalfState, cfg: &CalfConfig, left: f32, right: f32) {
42 state.muscle_l = left.clamp(0.0, cfg.max_muscle_size);
43 state.muscle_r = right.clamp(0.0, cfg.max_muscle_size);
44}
45
46#[allow(dead_code)]
47pub fn calf_set_definition(state: &mut CalfState, left: f32, right: f32) {
48 state.definition_l = left.clamp(0.0, 1.0);
49 state.definition_r = right.clamp(0.0, 1.0);
50}
51
52#[allow(dead_code)]
53pub fn calf_mirror(state: &mut CalfState) {
54 let avg_m = (state.muscle_l + state.muscle_r) * 0.5;
55 let avg_d = (state.definition_l + state.definition_r) * 0.5;
56 state.muscle_l = avg_m;
57 state.muscle_r = avg_m;
58 state.definition_l = avg_d;
59 state.definition_r = avg_d;
60}
61
62#[allow(dead_code)]
63pub fn calf_reset(state: &mut CalfState) {
64 *state = new_calf_state();
65}
66
67#[allow(dead_code)]
68pub fn calf_to_weights(state: &CalfState) -> Vec<(String, f32)> {
69 vec![
70 ("calf_muscle_l".to_string(), state.muscle_l),
71 ("calf_muscle_r".to_string(), state.muscle_r),
72 ("calf_definition_l".to_string(), state.definition_l),
73 ("calf_definition_r".to_string(), state.definition_r),
74 ]
75}
76
77#[allow(dead_code)]
78pub fn calf_to_json(state: &CalfState) -> String {
79 format!(
80 r#"{{"muscle_l":{:.4},"muscle_r":{:.4},"definition_l":{:.4},"definition_r":{:.4}}}"#,
81 state.muscle_l, state.muscle_r, state.definition_l, state.definition_r
82 )
83}
84
85#[allow(dead_code)]
89#[derive(Debug, Clone)]
90pub struct CalfControl {
91 pub width: f32,
92 pub length: f32,
93 pub muscle_tone: f32,
94}
95
96#[allow(dead_code)]
98pub fn default_calf_control() -> CalfControl {
99 CalfControl {
100 width: 0.5,
101 length: 0.5,
102 muscle_tone: 0.0,
103 }
104}
105
106#[allow(dead_code)]
108pub fn apply_calf_control(weights: &mut [f32], cc: &CalfControl) {
109 if !weights.is_empty() {
110 weights[0] = cc.width;
111 }
112 if weights.len() > 1 {
113 weights[1] = cc.length;
114 }
115 if weights.len() > 2 {
116 weights[2] = cc.muscle_tone;
117 }
118}
119
120#[allow(dead_code)]
122pub fn calf_control_blend(a: &CalfControl, b: &CalfControl, t: f32) -> CalfControl {
123 let t = t.clamp(0.0, 1.0);
124 CalfControl {
125 width: a.width + (b.width - a.width) * t,
126 length: a.length + (b.length - a.length) * t,
127 muscle_tone: a.muscle_tone + (b.muscle_tone - a.muscle_tone) * t,
128 }
129}
130
131#[cfg(test)]
132mod tests {
133 use super::*;
134
135 #[test]
136 fn test_default_config() {
137 let cfg = default_calf_config();
138 assert_eq!(cfg.max_muscle_size, 1.0);
139 }
140
141 #[test]
142 fn test_new_state_zeros() {
143 let s = new_calf_state();
144 assert_eq!(s.muscle_l, 0.0);
145 assert_eq!(s.definition_r, 0.0);
146 }
147
148 #[test]
149 fn test_set_muscle_clamps() {
150 let cfg = default_calf_config();
151 let mut s = new_calf_state();
152 calf_set_muscle(&mut s, &cfg, 2.0, -0.5);
153 assert_eq!(s.muscle_l, 1.0);
154 assert_eq!(s.muscle_r, 0.0);
155 }
156
157 #[test]
158 fn test_set_definition_clamps() {
159 let mut s = new_calf_state();
160 calf_set_definition(&mut s, 0.6, 1.5);
161 assert!((s.definition_l - 0.6).abs() < 1e-6);
162 assert_eq!(s.definition_r, 1.0);
163 }
164
165 #[test]
166 fn test_mirror_averages() {
167 let mut s = new_calf_state();
168 s.muscle_l = 0.3;
169 s.muscle_r = 0.7;
170 calf_mirror(&mut s);
171 assert!((s.muscle_l - 0.5).abs() < 1e-6);
172 assert!((s.muscle_r - 0.5).abs() < 1e-6);
173 }
174
175 #[test]
176 fn test_reset() {
177 let cfg = default_calf_config();
178 let mut s = new_calf_state();
179 calf_set_muscle(&mut s, &cfg, 0.8, 0.8);
180 calf_reset(&mut s);
181 assert_eq!(s.muscle_l, 0.0);
182 }
183
184 #[test]
185 fn test_to_weights_count() {
186 let s = new_calf_state();
187 assert_eq!(calf_to_weights(&s).len(), 4);
188 }
189
190 #[test]
191 fn test_to_json_has_keys() {
192 let s = new_calf_state();
193 let j = calf_to_json(&s);
194 assert!(j.contains("muscle_l"));
195 assert!(j.contains("definition_r"));
196 }
197
198 #[test]
199 fn test_set_muscle_valid() {
200 let cfg = default_calf_config();
201 let mut s = new_calf_state();
202 calf_set_muscle(&mut s, &cfg, 0.4, 0.6);
203 assert!((s.muscle_l - 0.4).abs() < 1e-6);
204 assert!((s.muscle_r - 0.6).abs() < 1e-6);
205 }
206}