oxihuman_morph/
compressed_shape_key.rs1#![allow(dead_code)]
4
5#[derive(Debug, Clone, Copy, PartialEq)]
9pub enum QuantBits {
10 Bits8,
11 Bits16,
12}
13
14#[derive(Debug, Clone)]
16pub struct CompressedShapeKey {
17 pub name: String,
18 pub vertex_count: usize,
19 pub quant_bits: QuantBits,
20 pub data: Vec<u16>,
21 pub scale: f32,
22 pub enabled: bool,
23}
24
25impl CompressedShapeKey {
26 pub fn new(name: impl Into<String>, vertex_count: usize) -> Self {
27 CompressedShapeKey {
28 name: name.into(),
29 vertex_count,
30 quant_bits: QuantBits::Bits16,
31 data: vec![0u16; vertex_count * 3],
32 scale: 1.0,
33 enabled: true,
34 }
35 }
36}
37
38pub fn new_compressed_shape_key(
40 name: impl Into<String>,
41 vertex_count: usize,
42) -> CompressedShapeKey {
43 CompressedShapeKey::new(name, vertex_count)
44}
45
46pub fn csk_decode_delta(key: &CompressedShapeKey, vertex: usize, component: usize) -> f32 {
48 let idx = vertex * 3 + component;
50 if idx < key.data.len() {
51 (key.data[idx] as f32 - 32768.0) * key.scale / 32768.0
52 } else {
53 0.0
54 }
55}
56
57pub fn csk_set_scale(key: &mut CompressedShapeKey, scale: f32) {
59 key.scale = scale;
60}
61
62pub fn csk_set_quant_bits(key: &mut CompressedShapeKey, bits: QuantBits) {
64 key.quant_bits = bits;
65}
66
67pub fn csk_byte_size(key: &CompressedShapeKey) -> usize {
69 match key.quant_bits {
70 QuantBits::Bits8 => key.vertex_count * 3,
71 QuantBits::Bits16 => key.vertex_count * 3 * 2,
72 }
73}
74
75pub fn csk_set_enabled(key: &mut CompressedShapeKey, enabled: bool) {
77 key.enabled = enabled;
78}
79
80pub fn csk_to_json(key: &CompressedShapeKey) -> String {
82 format!(
83 r#"{{"name":"{}","vertex_count":{},"scale":{},"enabled":{}}}"#,
84 key.name, key.vertex_count, key.scale, key.enabled
85 )
86}
87
88#[cfg(test)]
89mod tests {
90 use super::*;
91
92 #[test]
93 fn test_new_vertex_count() {
94 let k = new_compressed_shape_key("test", 100);
95 assert_eq!(k.vertex_count, 100 ,);
96 }
97
98 #[test]
99 fn test_data_length() {
100 let k = new_compressed_shape_key("k", 10);
101 assert_eq!(
102 k.data.len(),
103 30, );
105 }
106
107 #[test]
108 fn test_decode_zero_delta() {
109 let k = new_compressed_shape_key("k", 4);
110 let _ = csk_decode_delta(&k, 0, 0);
112 }
113
114 #[test]
115 fn test_set_scale() {
116 let mut k = new_compressed_shape_key("k", 2);
117 csk_set_scale(&mut k, 0.5);
118 assert!((k.scale - 0.5).abs() < 1e-6 ,);
119 }
120
121 #[test]
122 fn test_set_quant_bits() {
123 let mut k = new_compressed_shape_key("k", 2);
124 csk_set_quant_bits(&mut k, QuantBits::Bits8);
125 assert_eq!(
126 k.quant_bits,
127 QuantBits::Bits8, );
129 }
130
131 #[test]
132 fn test_byte_size_16bit() {
133 let k = new_compressed_shape_key("k", 10);
134 assert_eq!(csk_byte_size(&k), 60 ,);
135 }
136
137 #[test]
138 fn test_byte_size_8bit() {
139 let mut k = new_compressed_shape_key("k", 10);
140 csk_set_quant_bits(&mut k, QuantBits::Bits8);
141 assert_eq!(csk_byte_size(&k), 30 ,);
142 }
143
144 #[test]
145 fn test_set_enabled() {
146 let mut k = new_compressed_shape_key("k", 2);
147 csk_set_enabled(&mut k, false);
148 assert!(!k.enabled ,);
149 }
150
151 #[test]
152 fn test_to_json() {
153 let k = new_compressed_shape_key("smile", 5);
154 let j = csk_to_json(&k);
155 assert!(j.contains("smile"), );
156 }
157
158 #[test]
159 fn test_enabled_default() {
160 let k = new_compressed_shape_key("k", 1);
161 assert!(k.enabled ,);
162 }
163}