oxihuman_export/
mesh_sequence_export.rs1#![allow(dead_code)]
4
5#[allow(dead_code)]
9#[derive(Debug, Clone)]
10pub struct MeshFrame {
11 pub time: f32,
12 pub positions: Vec<[f32; 3]>,
13}
14
15#[allow(dead_code)]
17#[derive(Debug, Clone)]
18pub struct MeshSequenceExport {
19 pub frames: Vec<MeshFrame>,
20 pub vertex_count: usize,
21}
22
23#[allow(dead_code)]
25pub fn new_mesh_sequence(vertex_count: usize) -> MeshSequenceExport {
26 MeshSequenceExport {
27 frames: vec![],
28 vertex_count,
29 }
30}
31
32#[allow(dead_code)]
34pub fn add_frame(e: &mut MeshSequenceExport, time: f32, positions: &[[f32; 3]]) {
35 if positions.len() == e.vertex_count {
36 e.frames.push(MeshFrame {
37 time,
38 positions: positions.to_vec(),
39 });
40 }
41}
42
43#[allow(dead_code)]
45pub fn ms_frame_count(e: &MeshSequenceExport) -> usize {
46 e.frames.len()
47}
48
49#[allow(dead_code)]
51pub fn ms_duration(e: &MeshSequenceExport) -> f32 {
52 if e.frames.is_empty() {
53 return 0.0;
54 }
55 let min = e.frames.iter().map(|f| f.time).fold(f32::MAX, f32::min);
56 let max = e.frames.iter().map(|f| f.time).fold(f32::MIN, f32::max);
57 max - min
58}
59
60#[allow(dead_code)]
62pub fn ms_size_bytes(e: &MeshSequenceExport) -> usize {
63 e.frames.len() * e.vertex_count * 12 }
65
66#[allow(dead_code)]
68pub fn get_frame_positions(e: &MeshSequenceExport, idx: usize) -> Option<&[[f32; 3]]> {
69 e.frames.get(idx).map(|f| f.positions.as_slice())
70}
71
72#[allow(dead_code)]
74pub fn ms_fps(e: &MeshSequenceExport) -> f32 {
75 let dur = ms_duration(e);
76 if dur < 1e-12 || e.frames.len() < 2 {
77 return 0.0;
78 }
79 (e.frames.len() - 1) as f32 / dur
80}
81
82#[allow(dead_code)]
84pub fn ms_validate(e: &MeshSequenceExport) -> bool {
85 e.frames
86 .iter()
87 .all(|f| f.positions.len() == e.vertex_count && f.time >= 0.0)
88}
89
90#[allow(dead_code)]
92pub fn mesh_sequence_to_json(e: &MeshSequenceExport) -> String {
93 format!(
94 "{{\"frames\":{},\"vertices\":{},\"duration\":{:.6}}}",
95 ms_frame_count(e),
96 e.vertex_count,
97 ms_duration(e)
98 )
99}
100
101#[cfg(test)]
102mod tests {
103 use super::*;
104 #[test]
105 fn test_new() {
106 let e = new_mesh_sequence(3);
107 assert_eq!(ms_frame_count(&e), 0);
108 }
109 #[test]
110 fn test_add_frame() {
111 let mut e = new_mesh_sequence(2);
112 add_frame(&mut e, 0.0, &[[0.0; 3]; 2]);
113 assert_eq!(ms_frame_count(&e), 1);
114 }
115 #[test]
116 fn test_wrong_count() {
117 let mut e = new_mesh_sequence(2);
118 add_frame(&mut e, 0.0, &[[0.0; 3]; 3]);
119 assert_eq!(ms_frame_count(&e), 0);
120 }
121 #[test]
122 fn test_duration() {
123 let mut e = new_mesh_sequence(1);
124 add_frame(&mut e, 0.0, &[[0.0; 3]]);
125 add_frame(&mut e, 2.0, &[[1.0; 3]]);
126 assert!((ms_duration(&e) - 2.0).abs() < 1e-6);
127 }
128 #[test]
129 fn test_duration_empty() {
130 let e = new_mesh_sequence(1);
131 assert!((ms_duration(&e)).abs() < 1e-9);
132 }
133 #[test]
134 fn test_size() {
135 let mut e = new_mesh_sequence(10);
136 add_frame(&mut e, 0.0, &[[0.0; 3]; 10]);
137 assert_eq!(ms_size_bytes(&e), 120);
138 }
139 #[test]
140 fn test_get_frame() {
141 let mut e = new_mesh_sequence(1);
142 add_frame(&mut e, 0.0, &[[5.0, 0.0, 0.0]]);
143 let p = get_frame_positions(&e, 0).expect("should succeed");
144 assert!((p[0][0] - 5.0).abs() < 1e-6);
145 }
146 #[test]
147 fn test_fps() {
148 let mut e = new_mesh_sequence(1);
149 for i in 0..25 {
150 add_frame(&mut e, i as f32 / 24.0, &[[0.0; 3]]);
151 }
152 assert!((ms_fps(&e) - 24.0).abs() < 0.1);
153 }
154 #[test]
155 fn test_validate() {
156 let mut e = new_mesh_sequence(1);
157 add_frame(&mut e, 0.0, &[[0.0; 3]]);
158 assert!(ms_validate(&e));
159 }
160 #[test]
161 fn test_to_json() {
162 let e = new_mesh_sequence(5);
163 assert!(mesh_sequence_to_json(&e).contains("\"vertices\":5"));
164 }
165}