oxihuman_morph/
pear_shape_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone)]
9pub struct PearShapeConfig {
10 pub hip_width: f32,
11 pub thigh_fullness: f32,
12 pub shoulder_slim: f32,
13}
14
15impl Default for PearShapeConfig {
16 fn default() -> Self {
17 PearShapeConfig {
18 hip_width: 0.8,
19 thigh_fullness: 0.75,
20 shoulder_slim: 0.6,
21 }
22 }
23}
24
25#[derive(Debug, Clone)]
27pub struct PearShapeMorph {
28 pub intensity: f32,
29 pub config: PearShapeConfig,
30 pub enabled: bool,
31}
32
33pub fn new_pear_shape_morph() -> PearShapeMorph {
35 PearShapeMorph {
36 intensity: 0.0,
37 config: PearShapeConfig::default(),
38 enabled: true,
39 }
40}
41
42pub fn pear_set_intensity(m: &mut PearShapeMorph, v: f32) {
44 m.intensity = v.clamp(0.0, 1.0);
45}
46
47pub fn pear_hip_width(m: &PearShapeMorph) -> f32 {
49 m.intensity * m.config.hip_width
50}
51
52pub fn pear_thigh_fullness(m: &PearShapeMorph) -> f32 {
54 m.intensity * m.config.thigh_fullness
55}
56
57pub fn pear_shoulder_slim(m: &PearShapeMorph) -> f32 {
59 m.intensity * m.config.shoulder_slim
60}
61
62pub fn pear_hip_shoulder_ratio(m: &PearShapeMorph) -> f32 {
64 1.0 + 0.35 * m.intensity
65}
66
67pub fn pear_to_json(m: &PearShapeMorph) -> String {
69 format!(
70 r#"{{"intensity":{:.3},"hip_width":{:.3},"enabled":{}}}"#,
71 m.intensity,
72 pear_hip_width(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_pear_shape_morph();
84 assert!((m.intensity - 0.0).abs() < 1e-6 );
85 }
86
87 #[test]
88 fn clamp() {
89 let mut m = new_pear_shape_morph();
90 pear_set_intensity(&mut m, 2.0);
91 assert!((m.intensity - 1.0).abs() < 1e-6 );
92 }
93
94 #[test]
95 fn hip_width_at_max() {
96 let mut m = new_pear_shape_morph();
97 pear_set_intensity(&mut m, 1.0);
98 assert!((pear_hip_width(&m) - m.config.hip_width).abs() < 1e-6 );
99 }
100
101 #[test]
102 fn thigh_fullness_zero_at_zero() {
103 let m = new_pear_shape_morph();
104 assert!((pear_thigh_fullness(&m) - 0.0).abs() < 1e-6 );
105 }
106
107 #[test]
108 fn hip_shoulder_ratio_increases() {
109 let mut m = new_pear_shape_morph();
110 pear_set_intensity(&mut m, 0.0);
111 let r0 = pear_hip_shoulder_ratio(&m);
112 pear_set_intensity(&mut m, 1.0);
113 let r1 = pear_hip_shoulder_ratio(&m);
114 assert!(r1 > r0 );
115 }
116
117 #[test]
118 fn json_has_hip_width() {
119 let m = new_pear_shape_morph();
120 assert!(pear_to_json(&m).contains("hip_width") );
121 }
122
123 #[test]
124 fn enabled_default() {
125 let m = new_pear_shape_morph();
126 assert!(m.enabled );
127 }
128
129 #[test]
130 fn config_thigh_positive() {
131 let m = new_pear_shape_morph();
132 assert!(m.config.thigh_fullness > 0.0 );
133 }
134}