Skip to main content

oxihuman_export/
wrinkle_map_export_data.rs

1// Copyright (C) 2026 COOLJAPAN OU (Team KitaSan)
2// SPDX-License-Identifier: Apache-2.0
3#![allow(dead_code)]
4
5pub struct WrinkleMapData {
6    pub vertex_count: usize,
7    pub weights: Vec<f32>,
8    pub normals: Vec<[f32; 3]>,
9}
10
11pub fn new_wrinkle_map_data(n: usize) -> WrinkleMapData {
12    WrinkleMapData {
13        vertex_count: n,
14        weights: vec![0.0; n],
15        normals: vec![[0.0, 1.0, 0.0]; n],
16    }
17}
18
19pub fn wrinkle_set(m: &mut WrinkleMapData, i: usize, w: f32, n: [f32; 3]) {
20    if i < m.vertex_count {
21        m.weights[i] = w.clamp(0.0, 1.0);
22        m.normals[i] = n;
23    }
24}
25
26pub fn wrinkle_get(m: &WrinkleMapData, i: usize) -> (f32, [f32; 3]) {
27    if i < m.vertex_count {
28        (m.weights[i], m.normals[i])
29    } else {
30        (0.0, [0.0, 1.0, 0.0])
31    }
32}
33
34pub fn wrinkle_max_weight(m: &WrinkleMapData) -> f32 {
35    m.weights.iter().cloned().fold(0.0f32, f32::max)
36}
37
38pub fn wrinkle_active_count(m: &WrinkleMapData, thr: f32) -> usize {
39    m.weights.iter().filter(|&&w| w >= thr).count()
40}
41
42pub fn wrinkle_to_bytes(m: &WrinkleMapData) -> Vec<u8> {
43    let mut b = Vec::new();
44    let n = m.vertex_count as u32;
45    b.extend_from_slice(&n.to_le_bytes());
46    for &w in &m.weights {
47        b.extend_from_slice(&w.to_le_bytes());
48    }
49    for norm in &m.normals {
50        for &v in norm {
51            b.extend_from_slice(&v.to_le_bytes());
52        }
53    }
54    b
55}
56
57#[cfg(test)]
58mod tests {
59    use super::*;
60
61    #[test]
62    fn test_new_wrinkle_map_data() {
63        /* vertex count stored */
64        let m = new_wrinkle_map_data(5);
65        assert_eq!(m.vertex_count, 5);
66    }
67
68    #[test]
69    fn test_wrinkle_set_get() {
70        /* set and get roundtrip */
71        let mut m = new_wrinkle_map_data(3);
72        wrinkle_set(&mut m, 1, 0.8, [1.0, 0.0, 0.0]);
73        let (w, n) = wrinkle_get(&m, 1);
74        assert!((w - 0.8).abs() < 1e-6);
75        assert!((n[0] - 1.0).abs() < 1e-6);
76    }
77
78    #[test]
79    fn test_wrinkle_max_weight() {
80        /* finds max weight */
81        let mut m = new_wrinkle_map_data(3);
82        wrinkle_set(&mut m, 2, 0.9, [0.0, 1.0, 0.0]);
83        assert!((wrinkle_max_weight(&m) - 0.9).abs() < 1e-6);
84    }
85
86    #[test]
87    fn test_wrinkle_active_count() {
88        /* counts above threshold */
89        let mut m = new_wrinkle_map_data(4);
90        wrinkle_set(&mut m, 0, 0.5, [0.0; 3]);
91        wrinkle_set(&mut m, 1, 0.8, [0.0; 3]);
92        assert_eq!(wrinkle_active_count(&m, 0.5), 2);
93    }
94
95    #[test]
96    fn test_wrinkle_to_bytes() {
97        /* bytes non-empty */
98        let m = new_wrinkle_map_data(2);
99        let b = wrinkle_to_bytes(&m);
100        assert!(!b.is_empty());
101    }
102
103    #[test]
104    fn test_wrinkle_get_oob() {
105        /* out-of-bounds returns defaults */
106        let m = new_wrinkle_map_data(2);
107        let (w, _) = wrinkle_get(&m, 99);
108        assert_eq!(w, 0.0);
109    }
110}