oxihuman_export/
ply_binary_export.rs1#![allow(dead_code)]
4
5#[derive(Clone, Debug, Default)]
9pub struct PlyBinaryExport {
10 pub positions: Vec<[f32; 3]>,
11 pub normals: Vec<[f32; 3]>,
12 pub indices: Vec<u32>,
13}
14
15pub fn new_ply_binary_export() -> PlyBinaryExport {
17 PlyBinaryExport::default()
18}
19
20pub fn ply_binary_set_mesh(
22 doc: &mut PlyBinaryExport,
23 positions: Vec<[f32; 3]>,
24 normals: Vec<[f32; 3]>,
25 indices: Vec<u32>,
26) {
27 doc.positions = positions;
28 doc.normals = normals;
29 doc.indices = indices;
30}
31
32pub fn ply_binary_vertex_count(doc: &PlyBinaryExport) -> usize {
34 doc.positions.len()
35}
36
37pub fn ply_binary_face_count(doc: &PlyBinaryExport) -> usize {
39 doc.indices.len() / 3
40}
41
42pub fn ply_binary_header(doc: &PlyBinaryExport) -> String {
44 let has_normals = !doc.normals.is_empty();
45 let mut h = String::from("ply\nformat binary_little_endian 1.0\n");
46 h.push_str(&format!(
47 "element vertex {}\n",
48 ply_binary_vertex_count(doc)
49 ));
50 h.push_str("property float x\nproperty float y\nproperty float z\n");
51 if has_normals {
52 h.push_str("property float nx\nproperty float ny\nproperty float nz\n");
53 }
54 h.push_str(&format!("element face {}\n", ply_binary_face_count(doc)));
55 h.push_str("property list uchar uint vertex_indices\n");
56 h.push_str("end_header\n");
57 h
58}
59
60pub fn ply_binary_vertex_bytes(doc: &PlyBinaryExport) -> Vec<u8> {
62 let has_normals = !doc.normals.is_empty();
63 let mut out = Vec::new();
64 for (i, &p) in doc.positions.iter().enumerate() {
65 out.extend_from_slice(&p[0].to_le_bytes());
66 out.extend_from_slice(&p[1].to_le_bytes());
67 out.extend_from_slice(&p[2].to_le_bytes());
68 if has_normals {
69 if let Some(&n) = doc.normals.get(i) {
70 out.extend_from_slice(&n[0].to_le_bytes());
71 out.extend_from_slice(&n[1].to_le_bytes());
72 out.extend_from_slice(&n[2].to_le_bytes());
73 }
74 }
75 }
76 out
77}
78
79pub fn ply_binary_face_bytes(doc: &PlyBinaryExport) -> Vec<u8> {
81 let mut out = Vec::new();
82 let tri_count = doc.indices.len() / 3;
83 for t in 0..tri_count {
84 out.push(3u8); for k in 0..3 {
86 let idx = doc.indices[t * 3 + k];
87 out.extend_from_slice(&idx.to_le_bytes());
88 }
89 }
90 out
91}
92
93pub fn export_ply_binary(doc: &PlyBinaryExport) -> Vec<u8> {
95 let header = ply_binary_header(doc);
96 let mut out = header.into_bytes();
97 out.extend(ply_binary_vertex_bytes(doc));
98 out.extend(ply_binary_face_bytes(doc));
99 out
100}
101
102pub fn ply_binary_size_estimate(doc: &PlyBinaryExport) -> usize {
104 let has_normals = !doc.normals.is_empty();
105 let verts_per_vertex = if has_normals { 6 } else { 3 };
106 let vertex_bytes = ply_binary_vertex_count(doc) * verts_per_vertex * 4;
107 let face_bytes = ply_binary_face_count(doc) * (1 + 3 * 4);
108 ply_binary_header(doc).len() + vertex_bytes + face_bytes
109}
110
111pub fn validate_ply_binary(doc: &PlyBinaryExport) -> bool {
113 if doc.positions.is_empty() {
114 return false;
115 }
116 let n = doc.positions.len() as u32;
117 doc.indices.iter().all(|&i| i < n)
118}
119
120#[cfg(test)]
121mod tests {
122 use super::*;
123
124 fn simple() -> PlyBinaryExport {
125 let mut d = new_ply_binary_export();
126 ply_binary_set_mesh(
127 &mut d,
128 vec![[0.0, 0.0, 0.0], [1.0, 0.0, 0.0], [0.0, 1.0, 0.0]],
129 vec![],
130 vec![0, 1, 2],
131 );
132 d
133 }
134
135 #[test]
136 fn vertex_count() {
137 let d = simple();
138 assert_eq!(ply_binary_vertex_count(&d), 3);
139 }
140
141 #[test]
142 fn face_count() {
143 let d = simple();
144 assert_eq!(ply_binary_face_count(&d), 1);
145 }
146
147 #[test]
148 fn header_contains_ply() {
149 let d = simple();
150 let h = ply_binary_header(&d);
151 assert!(h.starts_with("ply\n"));
152 }
153
154 #[test]
155 fn header_contains_binary() {
156 let d = simple();
157 let h = ply_binary_header(&d);
158 assert!(h.contains("binary_little_endian"));
159 }
160
161 #[test]
162 fn vertex_bytes_correct_size() {
163 let d = simple();
164 let bytes = ply_binary_vertex_bytes(&d);
165 assert_eq!(bytes.len(), 3 * 3 * 4); }
167
168 #[test]
169 fn face_bytes_correct_size() {
170 let d = simple();
171 let bytes = ply_binary_face_bytes(&d);
172 assert_eq!(bytes.len(), 1 + 3 * 4); }
174
175 #[test]
176 fn export_ply_binary_non_empty() {
177 let d = simple();
178 let bytes = export_ply_binary(&d);
179 assert!(!bytes.is_empty());
180 }
181
182 #[test]
183 fn validate_valid() {
184 let d = simple();
185 assert!(validate_ply_binary(&d));
186 }
187}