#![allow(dead_code)]
pub struct ToothMorph {
pub size: f32,
pub protrusion: f32,
pub spacing: f32,
pub rotation: f32,
}
pub fn new_tooth_morph() -> ToothMorph {
ToothMorph {
size: 0.0,
protrusion: 0.0,
spacing: 0.0,
rotation: 0.0,
}
}
pub fn tooth_set_size(m: &mut ToothMorph, v: f32) {
m.size = v.clamp(0.0, 1.0);
}
pub fn tooth_is_prominent(m: &ToothMorph) -> bool {
m.protrusion > 0.5
}
pub fn tooth_overall_weight(m: &ToothMorph) -> f32 {
(m.size.abs() + m.protrusion.abs() + m.spacing.abs() + m.rotation.abs()) * 0.25
}
pub fn tooth_blend(a: &ToothMorph, b: &ToothMorph, t: f32) -> ToothMorph {
let t = t.clamp(0.0, 1.0);
ToothMorph {
size: a.size + (b.size - a.size) * t,
protrusion: a.protrusion + (b.protrusion - a.protrusion) * t,
spacing: a.spacing + (b.spacing - a.spacing) * t,
rotation: a.rotation + (b.rotation - a.rotation) * t,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_new_tooth_morph() {
let m = new_tooth_morph();
assert_eq!(m.size, 0.0);
assert_eq!(m.protrusion, 0.0);
}
#[test]
fn test_tooth_set_size() {
let mut m = new_tooth_morph();
tooth_set_size(&mut m, 0.7);
assert!((m.size - 0.7).abs() < 1e-6);
}
#[test]
fn test_tooth_is_prominent() {
let mut m = new_tooth_morph();
m.protrusion = 0.6;
assert!(tooth_is_prominent(&m));
m.protrusion = 0.3;
assert!(!tooth_is_prominent(&m));
}
#[test]
fn test_tooth_overall_weight() {
let m = new_tooth_morph();
assert_eq!(tooth_overall_weight(&m), 0.0);
}
#[test]
fn test_tooth_blend() {
let a = ToothMorph {
size: 0.0,
protrusion: 0.0,
spacing: 0.0,
rotation: 0.0,
};
let b = ToothMorph {
size: 1.0,
protrusion: 1.0,
spacing: 1.0,
rotation: 1.0,
};
let r = tooth_blend(&a, &b, 0.5);
assert!((r.size - 0.5).abs() < 1e-6);
}
}