oxihuman_morph/
apple_shape_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct AppleShapeConfig {
10 pub abdomen_fullness: f32,
11 pub chest_roundness: f32,
12 pub limb_slenderness: f32,
13}
14
15impl Default for AppleShapeConfig {
16 fn default() -> Self {
17 AppleShapeConfig {
18 abdomen_fullness: 0.85,
19 chest_roundness: 0.6,
20 limb_slenderness: 0.7,
21 }
22 }
23}
24
25#[derive(Debug, Clone)]
27pub struct AppleShapeMorph {
28 pub intensity: f32,
29 pub config: AppleShapeConfig,
30 pub enabled: bool,
31}
32
33pub fn new_apple_shape_morph() -> AppleShapeMorph {
35 AppleShapeMorph {
36 intensity: 0.0,
37 config: AppleShapeConfig::default(),
38 enabled: true,
39 }
40}
41
42pub fn apple_set_intensity(m: &mut AppleShapeMorph, v: f32) {
44 m.intensity = v.clamp(0.0, 1.0);
45}
46
47pub fn apple_abdomen(m: &AppleShapeMorph) -> f32 {
49 m.intensity * m.config.abdomen_fullness
50}
51
52pub fn apple_chest(m: &AppleShapeMorph) -> f32 {
54 m.intensity * m.config.chest_roundness
55}
56
57pub fn apple_limb_slim(m: &AppleShapeMorph) -> f32 {
59 m.intensity * m.config.limb_slenderness
60}
61
62pub fn apple_waist_scale(m: &AppleShapeMorph) -> f32 {
64 1.0 + 0.3 * apple_abdomen(m)
65}
66
67pub fn apple_to_json(m: &AppleShapeMorph) -> String {
69 format!(
70 r#"{{"intensity":{:.3},"abdomen":{:.3},"enabled":{}}}"#,
71 m.intensity,
72 apple_abdomen(m),
73 m.enabled
74 )
75}
76
77#[cfg(test)]
78mod tests {
79 use super::*;
80
81 #[test]
82 fn default_zero() {
83 let m = new_apple_shape_morph();
84 assert!((m.intensity - 0.0).abs() < 1e-6 );
85 }
86
87 #[test]
88 fn clamp() {
89 let mut m = new_apple_shape_morph();
90 apple_set_intensity(&mut m, -5.0);
91 assert!((m.intensity - 0.0).abs() < 1e-6 );
92 }
93
94 #[test]
95 fn abdomen_at_max() {
96 let mut m = new_apple_shape_morph();
97 apple_set_intensity(&mut m, 1.0);
98 assert!((apple_abdomen(&m) - m.config.abdomen_fullness).abs() < 1e-6 );
99 }
100
101 #[test]
102 fn chest_zero_at_zero() {
103 let m = new_apple_shape_morph();
104 assert!((apple_chest(&m) - 0.0).abs() < 1e-6 );
105 }
106
107 #[test]
108 fn waist_scale_increases() {
109 let mut m = new_apple_shape_morph();
110 apple_set_intensity(&mut m, 0.0);
111 let w0 = apple_waist_scale(&m);
112 apple_set_intensity(&mut m, 1.0);
113 let w1 = apple_waist_scale(&m);
114 assert!(w1 > w0 );
115 }
116
117 #[test]
118 fn limb_slim_positive_at_half() {
119 let mut m = new_apple_shape_morph();
120 apple_set_intensity(&mut m, 0.5);
121 assert!(apple_limb_slim(&m) > 0.0 );
122 }
123
124 #[test]
125 fn json_has_abdomen() {
126 let m = new_apple_shape_morph();
127 assert!(apple_to_json(&m).contains("abdomen") );
128 }
129
130 #[test]
131 fn enabled_default() {
132 let m = new_apple_shape_morph();
133 assert!(m.enabled );
134 }
135}