oxihuman_morph/
tooth_morph.rs1#![allow(dead_code)]
4
5pub struct ToothMorph {
6 pub size: f32,
7 pub protrusion: f32,
8 pub spacing: f32,
9 pub rotation: f32,
10}
11
12pub fn new_tooth_morph() -> ToothMorph {
13 ToothMorph {
14 size: 0.0,
15 protrusion: 0.0,
16 spacing: 0.0,
17 rotation: 0.0,
18 }
19}
20
21pub fn tooth_set_size(m: &mut ToothMorph, v: f32) {
22 m.size = v.clamp(0.0, 1.0);
23}
24
25pub fn tooth_is_prominent(m: &ToothMorph) -> bool {
26 m.protrusion > 0.5
27}
28
29pub fn tooth_overall_weight(m: &ToothMorph) -> f32 {
30 (m.size.abs() + m.protrusion.abs() + m.spacing.abs() + m.rotation.abs()) * 0.25
31}
32
33pub fn tooth_blend(a: &ToothMorph, b: &ToothMorph, t: f32) -> ToothMorph {
34 let t = t.clamp(0.0, 1.0);
35 ToothMorph {
36 size: a.size + (b.size - a.size) * t,
37 protrusion: a.protrusion + (b.protrusion - a.protrusion) * t,
38 spacing: a.spacing + (b.spacing - a.spacing) * t,
39 rotation: a.rotation + (b.rotation - a.rotation) * t,
40 }
41}
42
43#[cfg(test)]
44mod tests {
45 use super::*;
46
47 #[test]
48 fn test_new_tooth_morph() {
49 let m = new_tooth_morph();
51 assert_eq!(m.size, 0.0);
52 assert_eq!(m.protrusion, 0.0);
53 }
54
55 #[test]
56 fn test_tooth_set_size() {
57 let mut m = new_tooth_morph();
59 tooth_set_size(&mut m, 0.7);
60 assert!((m.size - 0.7).abs() < 1e-6);
61 }
62
63 #[test]
64 fn test_tooth_is_prominent() {
65 let mut m = new_tooth_morph();
67 m.protrusion = 0.6;
68 assert!(tooth_is_prominent(&m));
69 m.protrusion = 0.3;
70 assert!(!tooth_is_prominent(&m));
71 }
72
73 #[test]
74 fn test_tooth_overall_weight() {
75 let m = new_tooth_morph();
77 assert_eq!(tooth_overall_weight(&m), 0.0);
78 }
79
80 #[test]
81 fn test_tooth_blend() {
82 let a = ToothMorph {
84 size: 0.0,
85 protrusion: 0.0,
86 spacing: 0.0,
87 rotation: 0.0,
88 };
89 let b = ToothMorph {
90 size: 1.0,
91 protrusion: 1.0,
92 spacing: 1.0,
93 rotation: 1.0,
94 };
95 let r = tooth_blend(&a, &b, 0.5);
96 assert!((r.size - 0.5).abs() < 1e-6);
97 }
98}