oxihuman_morph/
crease_depth_morph.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum CreaseRegion {
10 Forehead,
11 GlabellaLines,
12 NasolabialFold,
13 Marionette,
14 CrowsFeet,
15 NeckLines,
16}
17
18#[derive(Debug, Clone)]
20pub struct CreaseEntry {
21 pub region: CreaseRegion,
22 pub depth: f32,
23 pub sharpness: f32,
24}
25
26#[derive(Debug, Clone)]
28pub struct CreaseDepthMorph {
29 pub creases: Vec<CreaseEntry>,
30 pub global_scale: f32,
31 pub morph_count: usize,
32 pub enabled: bool,
33}
34
35impl CreaseDepthMorph {
36 pub fn new(morph_count: usize) -> Self {
37 CreaseDepthMorph {
38 creases: Vec::new(),
39 global_scale: 1.0,
40 morph_count,
41 enabled: true,
42 }
43 }
44}
45
46pub fn new_crease_depth_morph(morph_count: usize) -> CreaseDepthMorph {
48 CreaseDepthMorph::new(morph_count)
49}
50
51pub fn cdm_add_crease(morph: &mut CreaseDepthMorph, entry: CreaseEntry) {
53 morph.creases.push(entry);
54}
55
56pub fn cdm_set_global_scale(morph: &mut CreaseDepthMorph, scale: f32) {
58 morph.global_scale = scale.clamp(0.0, 2.0);
59}
60
61pub fn cdm_clear(morph: &mut CreaseDepthMorph) {
63 morph.creases.clear();
64}
65
66pub fn cdm_evaluate(morph: &CreaseDepthMorph) -> Vec<f32> {
68 if !morph.enabled || morph.morph_count == 0 {
70 return vec![];
71 }
72 let avg = if morph.creases.is_empty() {
73 0.0
74 } else {
75 morph.creases.iter().map(|c| c.depth).sum::<f32>() / morph.creases.len() as f32
76 };
77 let w = (avg * morph.global_scale).clamp(0.0, 1.0);
78 vec![w; morph.morph_count]
79}
80
81pub fn cdm_set_enabled(morph: &mut CreaseDepthMorph, enabled: bool) {
83 morph.enabled = enabled;
84}
85
86pub fn cdm_crease_count(morph: &CreaseDepthMorph) -> usize {
88 morph.creases.len()
89}
90
91pub fn cdm_to_json(morph: &CreaseDepthMorph) -> String {
93 format!(
94 r#"{{"crease_count":{},"global_scale":{},"morph_count":{},"enabled":{}}}"#,
95 morph.creases.len(),
96 morph.global_scale,
97 morph.morph_count,
98 morph.enabled
99 )
100}
101
102#[cfg(test)]
103mod tests {
104 use super::*;
105
106 fn make_crease(region: CreaseRegion, depth: f32) -> CreaseEntry {
107 CreaseEntry {
108 region,
109 depth,
110 sharpness: 0.5,
111 }
112 }
113
114 #[test]
115 fn test_initial_empty() {
116 let m = new_crease_depth_morph(4);
117 assert_eq!(cdm_crease_count(&m), 0 );
118 }
119
120 #[test]
121 fn test_add_crease() {
122 let mut m = new_crease_depth_morph(4);
123 cdm_add_crease(&mut m, make_crease(CreaseRegion::Forehead, 0.5));
124 assert_eq!(cdm_crease_count(&m), 1 );
125 }
126
127 #[test]
128 fn test_clear() {
129 let mut m = new_crease_depth_morph(4);
130 cdm_add_crease(&mut m, make_crease(CreaseRegion::CrowsFeet, 0.8));
131 cdm_clear(&mut m);
132 assert_eq!(cdm_crease_count(&m), 0 );
133 }
134
135 #[test]
136 fn test_global_scale_clamped() {
137 let mut m = new_crease_depth_morph(4);
138 cdm_set_global_scale(&mut m, 5.0);
139 assert!((m.global_scale - 2.0).abs() < 1e-6 );
140 }
141
142 #[test]
143 fn test_evaluate_length() {
144 let m = new_crease_depth_morph(5);
145 assert_eq!(
146 cdm_evaluate(&m).len(),
147 5 );
149 }
150
151 #[test]
152 fn test_evaluate_empty_creases() {
153 let m = new_crease_depth_morph(4);
154 let out = cdm_evaluate(&m);
155 assert!((out[0]).abs() < 1e-6 );
156 }
157
158 #[test]
159 fn test_evaluate_disabled() {
160 let mut m = new_crease_depth_morph(4);
161 cdm_set_enabled(&mut m, false);
162 assert!(cdm_evaluate(&m).is_empty() );
163 }
164
165 #[test]
166 fn test_to_json_has_crease_count() {
167 let m = new_crease_depth_morph(4);
168 let j = cdm_to_json(&m);
169 assert!(j.contains("\"crease_count\"") );
170 }
171
172 #[test]
173 fn test_enabled_default() {
174 let m = new_crease_depth_morph(4);
175 assert!(m.enabled );
176 }
177
178 #[test]
179 fn test_evaluate_avg_depth() {
180 let mut m = new_crease_depth_morph(2);
181 cdm_add_crease(&mut m, make_crease(CreaseRegion::Marionette, 0.4));
182 cdm_add_crease(&mut m, make_crease(CreaseRegion::NeckLines, 0.6));
183 let out = cdm_evaluate(&m);
184 assert!((out[0] - 0.5).abs() < 1e-5 );
185 }
186}