Skip to main content

oxihuman_morph/
frontalis_morph.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5pub struct FrontalisMorph {
6    pub contraction: f32,
7    pub line_depth: f32,
8    pub brow_elevation: f32,
9}
10
11pub fn new_frontalis_morph() -> FrontalisMorph {
12    FrontalisMorph {
13        contraction: 0.0,
14        line_depth: 0.0,
15        brow_elevation: 0.0,
16    }
17}
18
19pub fn frontalis_set_contraction(m: &mut FrontalisMorph, v: f32) {
20    m.contraction = v.clamp(0.0, 1.0);
21}
22
23pub fn frontalis_shows_lines(m: &FrontalisMorph) -> bool {
24    m.line_depth > 0.3
25}
26
27pub fn frontalis_overall_weight(m: &FrontalisMorph) -> f32 {
28    (m.contraction + m.line_depth) * 0.5
29}
30
31pub fn frontalis_blend(a: &FrontalisMorph, b: &FrontalisMorph, t: f32) -> FrontalisMorph {
32    let t = t.clamp(0.0, 1.0);
33    FrontalisMorph {
34        contraction: a.contraction + (b.contraction - a.contraction) * t,
35        line_depth: a.line_depth + (b.line_depth - a.line_depth) * t,
36        brow_elevation: a.brow_elevation + (b.brow_elevation - a.brow_elevation) * t,
37    }
38}
39
40#[cfg(test)]
41mod tests {
42    use super::*;
43
44    #[test]
45    fn test_new_frontalis_morph() {
46        /* contraction starts at 0 */
47        let m = new_frontalis_morph();
48        assert!((m.contraction - 0.0).abs() < 1e-6);
49    }
50
51    #[test]
52    fn test_frontalis_set_contraction() {
53        /* set and retrieve contraction */
54        let mut m = new_frontalis_morph();
55        frontalis_set_contraction(&mut m, 0.5);
56        assert!((m.contraction - 0.5).abs() < 1e-6);
57    }
58
59    #[test]
60    fn test_frontalis_shows_lines_true() {
61        /* line_depth > 0.3 shows lines */
62        let mut m = new_frontalis_morph();
63        m.line_depth = 0.5;
64        assert!(frontalis_shows_lines(&m));
65    }
66
67    #[test]
68    fn test_frontalis_shows_lines_false() {
69        /* zero depth no lines */
70        let m = new_frontalis_morph();
71        assert!(!frontalis_shows_lines(&m));
72    }
73
74    #[test]
75    fn test_frontalis_overall_weight() {
76        /* weight average of contraction and line_depth */
77        let mut m = new_frontalis_morph();
78        frontalis_set_contraction(&mut m, 1.0);
79        m.line_depth = 1.0;
80        assert!((frontalis_overall_weight(&m) - 1.0).abs() < 1e-6);
81    }
82
83    #[test]
84    fn test_frontalis_blend() {
85        /* blend midpoint */
86        let a = new_frontalis_morph();
87        let mut b = new_frontalis_morph();
88        b.contraction = 1.0;
89        let mid = frontalis_blend(&a, &b, 0.5);
90        assert!((mid.contraction - 0.5).abs() < 1e-6);
91    }
92}