oxihuman_morph/
procedural_wrinkle.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum WrinklePattern {
10 Linear,
11 Radial,
12 Noise,
13}
14
15#[derive(Debug, Clone)]
17pub struct WrinkleRegion {
18 pub pattern: WrinklePattern,
19 pub center: [f32; 3],
20 pub radius: f32,
21 pub amplitude: f32,
22 pub frequency: f32,
23 pub driver_weight: f32,
24}
25
26#[derive(Debug, Clone)]
28pub struct ProceduralWrinkle {
29 pub regions: Vec<WrinkleRegion>,
30 pub vertex_count: usize,
31 pub enabled: bool,
32 pub global_scale: f32,
33}
34
35impl ProceduralWrinkle {
36 pub fn new(vertex_count: usize) -> Self {
37 ProceduralWrinkle {
38 regions: Vec::new(),
39 vertex_count,
40 enabled: true,
41 global_scale: 1.0,
42 }
43 }
44}
45
46pub fn new_procedural_wrinkle(vertex_count: usize) -> ProceduralWrinkle {
48 ProceduralWrinkle::new(vertex_count)
49}
50
51pub fn pw_add_region(pw: &mut ProceduralWrinkle, region: WrinkleRegion) {
53 pw.regions.push(region);
54}
55
56pub fn pw_evaluate(pw: &ProceduralWrinkle) -> Vec<[f32; 3]> {
58 vec![[0.0; 3]; pw.vertex_count]
60}
61
62pub fn pw_set_global_scale(pw: &mut ProceduralWrinkle, scale: f32) {
64 pw.global_scale = scale.max(0.0);
65}
66
67pub fn pw_set_enabled(pw: &mut ProceduralWrinkle, enabled: bool) {
69 pw.enabled = enabled;
70}
71
72pub fn pw_region_count(pw: &ProceduralWrinkle) -> usize {
74 pw.regions.len()
75}
76
77pub fn pw_to_json(pw: &ProceduralWrinkle) -> String {
79 format!(
80 r#"{{"vertex_count":{},"region_count":{},"global_scale":{},"enabled":{}}}"#,
81 pw.vertex_count,
82 pw.regions.len(),
83 pw.global_scale,
84 pw.enabled
85 )
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_new_vertex_count() {
94 let pw = new_procedural_wrinkle(200);
95 assert_eq!(pw.vertex_count, 200 ,);
96 }
97
98 #[test]
99 fn test_no_regions_initially() {
100 let pw = new_procedural_wrinkle(100);
101 assert_eq!(pw_region_count(&pw), 0 ,);
102 }
103
104 #[test]
105 fn test_add_region() {
106 let mut pw = new_procedural_wrinkle(100);
107 pw_add_region(
108 &mut pw,
109 WrinkleRegion {
110 pattern: WrinklePattern::Linear,
111 center: [0.0; 3],
112 radius: 1.0,
113 amplitude: 0.5,
114 frequency: 2.0,
115 driver_weight: 1.0,
116 },
117 );
118 assert_eq!(pw_region_count(&pw), 1 ,);
119 }
120
121 #[test]
122 fn test_evaluate_length() {
123 let pw = new_procedural_wrinkle(50);
124 let out = pw_evaluate(&pw);
125 assert_eq!(
126 out.len(),
127 50, );
129 }
130
131 #[test]
132 fn test_evaluate_zeroed() {
133 let pw = new_procedural_wrinkle(4);
134 let out = pw_evaluate(&pw);
135 assert!((out[0][0]).abs() < 1e-6 ,);
136 }
137
138 #[test]
139 fn test_set_global_scale() {
140 let mut pw = new_procedural_wrinkle(10);
141 pw_set_global_scale(&mut pw, 2.5);
142 assert!((pw.global_scale - 2.5).abs() < 1e-5, );
143 }
144
145 #[test]
146 fn test_global_scale_clamped_negative() {
147 let mut pw = new_procedural_wrinkle(10);
148 pw_set_global_scale(&mut pw, -1.0);
149 assert!((pw.global_scale).abs() < 1e-6, );
150 }
151
152 #[test]
153 fn test_set_enabled() {
154 let mut pw = new_procedural_wrinkle(10);
155 pw_set_enabled(&mut pw, false);
156 assert!(!pw.enabled ,);
157 }
158
159 #[test]
160 fn test_to_json_contains_vertex_count() {
161 let pw = new_procedural_wrinkle(30);
162 let j = pw_to_json(&pw);
163 assert!(j.contains("\"vertex_count\""), );
164 }
165
166 #[test]
167 fn test_enabled_default() {
168 let pw = new_procedural_wrinkle(1);
169 assert!(pw.enabled ,);
170 }
171}