1use crate::geometry_indices::{FaceIndex, PointIndex};
2use crate::point_cloud::PointCloud;
3use crate::status::{DracoError, Status};
4use std::collections::HashMap;
5use std::ops::{Deref, DerefMut};
6
7pub type Face = [PointIndex; 3];
9
10#[derive(Debug, Default, Clone)]
15pub struct Mesh {
16 point_cloud: PointCloud,
17 faces: Vec<Face>,
18}
19
20impl Mesh {
21 pub fn new() -> Self {
23 Self::default()
24 }
25
26 pub fn add_face(&mut self, face: Face) {
28 self.faces.push(face);
29 }
30
31 pub fn set_face(&mut self, face_id: FaceIndex, face: Face) {
33 if face_id.0 as usize >= self.faces.len() {
34 self.faces
35 .resize(face_id.0 as usize + 1, [PointIndex(0); 3]);
36 }
37 self.faces[face_id.0 as usize] = face;
38 }
39
40 #[inline]
43 pub fn set_faces_from_flat_indices(&mut self, indices: &[u32]) {
44 debug_assert_eq!(indices.len(), self.faces.len() * 3);
45 for (i, face) in self.faces.iter_mut().enumerate() {
46 let base = i * 3;
47 *face = [
48 PointIndex(indices[base]),
49 PointIndex(indices[base + 1]),
50 PointIndex(indices[base + 2]),
51 ];
52 }
53 }
54
55 #[inline]
58 pub fn set_faces_from_u8_indices(&mut self, bytes: &[u8]) {
59 debug_assert_eq!(bytes.len(), self.faces.len() * 3);
60 for (face, chunk) in self.faces.iter_mut().zip(bytes.chunks_exact(3)) {
61 *face = [
62 PointIndex(chunk[0] as u32),
63 PointIndex(chunk[1] as u32),
64 PointIndex(chunk[2] as u32),
65 ];
66 }
67 }
68
69 #[inline]
72 pub fn set_faces_from_le_u16_indices(&mut self, bytes: &[u8]) {
73 debug_assert_eq!(bytes.len(), self.faces.len() * 3 * 2);
74 for (face, chunk) in self.faces.iter_mut().zip(bytes.chunks_exact(6)) {
75 *face = [
76 PointIndex(u16::from_le_bytes([chunk[0], chunk[1]]) as u32),
77 PointIndex(u16::from_le_bytes([chunk[2], chunk[3]]) as u32),
78 PointIndex(u16::from_le_bytes([chunk[4], chunk[5]]) as u32),
79 ];
80 }
81 }
82
83 #[inline]
86 pub fn set_faces_from_le_u32_indices(&mut self, bytes: &[u8]) {
87 debug_assert_eq!(bytes.len(), self.faces.len() * 3 * 4);
88 for (face, chunk) in self.faces.iter_mut().zip(bytes.chunks_exact(12)) {
89 *face = [
90 PointIndex(u32::from_le_bytes([chunk[0], chunk[1], chunk[2], chunk[3]])),
91 PointIndex(u32::from_le_bytes([chunk[4], chunk[5], chunk[6], chunk[7]])),
92 PointIndex(u32::from_le_bytes([
93 chunk[8], chunk[9], chunk[10], chunk[11],
94 ])),
95 ];
96 }
97 }
98
99 #[inline]
101 pub fn set_face_from_indices(&mut self, face_id: usize, indices: [u32; 3]) {
102 self.faces[face_id] = [
103 PointIndex(indices[0]),
104 PointIndex(indices[1]),
105 PointIndex(indices[2]),
106 ];
107 }
108
109 pub fn face(&self, face_id: FaceIndex) -> Face {
111 self.faces[face_id.0 as usize]
112 }
113
114 pub fn num_faces(&self) -> usize {
116 self.faces.len()
117 }
118
119 pub fn set_num_faces(&mut self, num_faces: usize) {
121 self.faces.resize(num_faces, [PointIndex(0); 3]);
122 }
123
124 pub fn try_set_num_faces(&mut self, num_faces: usize) -> Status {
126 if num_faces > self.faces.len() {
127 self.faces
128 .try_reserve_exact(num_faces - self.faces.len())
129 .map_err(|_| DracoError::DracoError("Failed to allocate mesh faces".to_string()))?;
130 }
131 self.faces.resize(num_faces, [PointIndex(0); 3]);
132 Ok(())
133 }
134
135 pub fn deduplicate_point_ids(&mut self) {
146 if self.faces.is_empty() || self.num_points() == 0 {
147 return;
148 }
149
150 let mut old_to_new: HashMap<u32, u32> = HashMap::new();
153 let mut new_id = 0u32;
154
155 for face in &self.faces {
157 for &point_idx in face.iter() {
158 if let std::collections::hash_map::Entry::Vacant(e) = old_to_new.entry(point_idx.0)
159 {
160 e.insert(new_id);
161 new_id += 1;
162 }
163 }
164 }
165
166 let needs_remap = old_to_new.iter().any(|(&old, &new)| old != new);
168 if !needs_remap {
169 return;
170 }
171
172 let num_unique = new_id as usize;
174 let mut new_to_old = vec![0u32; num_unique];
175 for (&old, &new) in &old_to_new {
176 new_to_old[new as usize] = old;
177 }
178
179 for face in &mut self.faces {
181 for point_idx in face.iter_mut() {
182 point_idx.0 = old_to_new[&point_idx.0];
183 }
184 }
185
186 for att_idx in 0..self.num_attributes() {
189 let att = self.attribute(att_idx);
190 let stride = att.byte_stride() as usize;
191 let old_buffer = att.buffer().data().to_vec();
192
193 let mut new_buffer = vec![0u8; num_unique * stride];
195 for new_idx in 0..num_unique {
196 let old_idx = new_to_old[new_idx] as usize;
197 if old_idx * stride + stride <= old_buffer.len() {
198 new_buffer[new_idx * stride..new_idx * stride + stride]
199 .copy_from_slice(&old_buffer[old_idx * stride..old_idx * stride + stride]);
200 }
201 }
202
203 let att_mut = self.attribute_mut(att_idx);
205 att_mut.buffer_mut().resize(new_buffer.len());
206 att_mut.buffer_mut().write(0, &new_buffer);
207 }
208
209 self.set_num_points(num_unique);
211 }
212}
213
214impl Deref for Mesh {
215 type Target = PointCloud;
216
217 fn deref(&self) -> &Self::Target {
218 &self.point_cloud
219 }
220}
221
222impl DerefMut for Mesh {
223 fn deref_mut(&mut self) -> &mut Self::Target {
224 &mut self.point_cloud
225 }
226}