1use crate::*;
5use cgmath::ElementWise;
6use manifold_rs::{Manifold, Mesh};
7
8#[derive(Default, Clone)]
10pub struct TriangleMesh {
11 pub vertices: Vec<Vertex>,
13 pub triangle_indices: Vec<Triangle<u32>>,
15}
16
17pub struct Triangles<'a> {
19 triangle_mesh: &'a TriangleMesh,
20 index: usize,
21}
22
23impl<'a> Iterator for Triangles<'a> {
24 type Item = Triangle<&'a Vertex>;
25
26 fn next(&mut self) -> Option<Self::Item> {
27 if self.index < self.triangle_mesh.triangle_indices.len() {
28 let t = self.triangle_mesh.triangle_indices[self.index];
29 self.index += 1;
30 Some(Triangle(
31 &self.triangle_mesh.vertices[t.0 as usize],
32 &self.triangle_mesh.vertices[t.1 as usize],
33 &self.triangle_mesh.vertices[t.2 as usize],
34 ))
35 } else {
36 None
37 }
38 }
39}
40
41impl TriangleMesh {
42 pub fn is_empty(&self) -> bool {
44 self.vertices.is_empty() || self.triangle_indices.is_empty()
45 }
46
47 pub fn clear(&mut self) {
49 self.vertices.clear();
50 self.triangle_indices.clear();
51 }
52
53 pub fn fetch_triangles(&self) -> Vec<Triangle<Vertex>> {
55 self.triangle_indices
56 .iter()
57 .map(|t| {
58 Triangle(
59 self.vertices[t.0 as usize],
60 self.vertices[t.1 as usize],
61 self.vertices[t.2 as usize],
62 )
63 })
64 .collect()
65 }
66
67 pub fn append(&mut self, other: &TriangleMesh) {
69 let offset = self.vertices.len() as u32;
70 self.vertices.append(&mut other.vertices.clone());
71 self.triangle_indices.extend(
72 other
73 .triangle_indices
74 .iter()
75 .map(|t| Triangle(t.0 + offset, t.1 + offset, t.2 + offset)),
76 )
77 }
78
79 pub fn triangles(&'_ self) -> Triangles<'_> {
81 Triangles {
82 triangle_mesh: self,
83 index: 0,
84 }
85 }
86
87 pub fn to_manifold(&self) -> Manifold {
89 let vertices = self
90 .vertices
91 .iter()
92 .flat_map(|v| vec![v.pos.x as f32, v.pos.y as f32, v.pos.z as f32])
93 .collect::<Vec<_>>();
94
95 let triangle_indices = self
96 .triangle_indices
97 .iter()
98 .flat_map(|t| vec![t.0, t.1, t.2])
99 .collect::<Vec<_>>();
100
101 assert_eq!(vertices.len(), self.vertices.len() * 3);
102 assert_eq!(triangle_indices.len(), self.triangle_indices.len() * 3);
103
104 Manifold::from_mesh(Mesh::new(&vertices, &triangle_indices))
105 }
106
107 pub fn volume(&self) -> f64 {
109 self.triangles()
110 .map(|t| t.signed_volume())
111 .sum::<f64>()
112 .abs()
113 }
114
115 pub fn fetch_triangle(&self, tri: Triangle<u32>) -> Triangle<&Vertex> {
117 Triangle(
118 &self.vertices[tri.0 as usize],
119 &self.vertices[tri.1 as usize],
120 &self.vertices[tri.2 as usize],
121 )
122 }
123
124 pub fn repair(&mut self, bounds: &Bounds3D) {
126 let min = bounds.min;
129 let inv_size = 1.0 / (bounds.max - bounds.min);
130
131 let quantize = |pos: &Vec3| {
133 let mapped = (pos - min).mul_element_wise(inv_size) * (u32::MAX as Scalar);
134 (
135 mapped.x.floor() as u32,
136 mapped.y.floor() as u32,
137 mapped.z.floor() as u32,
138 )
139 };
140
141 let mut vertex_map: std::collections::HashMap<(u32, u32, u32), u32> =
142 std::collections::HashMap::new();
143 let mut new_vertices: Vec<Vertex> = Vec::with_capacity(self.vertices.len());
144 let mut remap: Vec<u32> = vec![0; self.vertices.len()];
145
146 for (i, vertex) in self.vertices.iter().enumerate() {
147 let key = quantize(&vertex.pos);
148 if let Some(&existing_idx) = vertex_map.get(&key) {
149 remap[i] = existing_idx;
151 } else {
152 let new_idx = new_vertices.len() as u32;
154 new_vertices.push(*vertex);
155 vertex_map.insert(key, new_idx);
156 remap[i] = new_idx;
157 }
158 }
159
160 self.vertices = new_vertices;
161
162 let mut new_triangles = Vec::with_capacity(self.triangle_indices.len());
164
165 for tri in &self.triangle_indices {
166 let tri_idx = crate::Triangle(
167 remap[tri.0 as usize],
168 remap[tri.1 as usize],
169 remap[tri.2 as usize],
170 );
171
172 if tri_idx.is_degenerated() {
173 continue;
174 }
175
176 let tri = self.fetch_triangle(tri_idx);
178
179 if tri.area() < 1e-8 {
180 continue; }
182
183 new_triangles.push(tri_idx);
184 }
185
186 self.triangle_indices = new_triangles;
187 }
188}
189
190impl CalcBounds3D for TriangleMesh {
191 fn calc_bounds_3d(&self) -> Bounds3D {
192 self.vertices.iter().map(|vertex| vertex.pos).collect()
193 }
194}
195
196impl From<Mesh> for TriangleMesh {
197 fn from(mesh: Mesh) -> Self {
198 let vertices = mesh.vertices();
199 let indices = mesh.indices();
200
201 TriangleMesh {
205 vertices: (0..vertices.len())
206 .step_by(3)
207 .map(|i| Vertex {
208 pos: Vec3::new(
209 vertices[i] as f64,
210 vertices[i + 1] as f64,
211 vertices[i + 2] as f64,
212 ),
213 normal: Vec3::new(0.0, 0.0, 0.0),
214 })
215 .collect(),
216 triangle_indices: (0..indices.len())
217 .step_by(3)
218 .map(|i| Triangle(indices[i], indices[i + 1], indices[i + 2]))
219 .collect(),
220 }
221 }
222}
223
224impl From<TriangleMesh> for Mesh {
225 fn from(mesh: TriangleMesh) -> Self {
226 let mut vertices = Vec::new();
227 let mut indices = Vec::new();
228
229 for v in &mesh.vertices {
230 vertices.push(v.pos.x as f32);
231 vertices.push(v.pos.y as f32);
232 vertices.push(v.pos.z as f32);
233 }
234
235 for t in &mesh.triangle_indices {
236 indices.push(t.0);
237 indices.push(t.1);
238 indices.push(t.2);
239 }
240
241 Mesh::new(vertices.as_slice(), indices.as_slice())
242 }
243}
244
245impl From<Manifold> for TriangleMesh {
246 fn from(manifold: Manifold) -> Self {
247 TriangleMesh::from(manifold.to_mesh())
248 }
249}
250
251impl Transformed3D for TriangleMesh {
252 fn transformed_3d(&self, mat: &Mat4) -> Self {
253 let rot_mat = crate::Mat3::from_cols(mat.x.truncate(), mat.y.truncate(), mat.z.truncate());
254 Self {
255 vertices: self
256 .vertices
257 .iter()
258 .map(|v| Vertex {
259 pos: (mat * v.pos.extend(1.0)).truncate(),
260 normal: rot_mat * v.normal,
261 })
262 .collect(),
263 triangle_indices: self.triangle_indices.clone(),
264 }
265 }
266}
267
268impl WithBounds3D<TriangleMesh> {
269 pub fn repair(&mut self) {
271 self.update_bounds();
272 self.inner.repair(&self.bounds);
273 }
274}
275
276impl From<Geometry3D> for TriangleMesh {
277 fn from(geo: Geometry3D) -> Self {
278 match geo {
279 Geometry3D::Mesh(triangle_mesh) => triangle_mesh,
280 Geometry3D::Manifold(manifold) => manifold.to_mesh().into(),
281 Geometry3D::Collection(ref collection) => collection.into(),
282 }
283 }
284}
285
286impl From<&Geometries3D> for TriangleMesh {
287 fn from(geo: &Geometries3D) -> Self {
288 let mut mesh = TriangleMesh::default();
289 geo.iter()
290 .for_each(|geo| mesh.append(&geo.as_ref().clone().into()));
291 mesh
292 }
293}
294
295#[test]
296fn test_triangle_mesh_transform() {
297 let mesh = TriangleMesh {
298 vertices: vec![
299 Vertex {
300 pos: Vec3::new(0.0, 0.0, 0.0),
301 normal: Vec3::new(0.0, 0.0, 1.0),
302 },
303 Vertex {
304 pos: Vec3::new(1.0, 0.0, 0.0),
305 normal: Vec3::new(0.0, 0.0, 1.0),
306 },
307 Vertex {
308 pos: Vec3::new(0.0, 1.0, 0.0),
309 normal: Vec3::new(0.0, 0.0, 1.0),
310 },
311 ],
312 triangle_indices: vec![Triangle(0, 1, 2)],
313 };
314
315 let mesh = mesh.transformed_3d(&crate::Mat4::from_translation(Vec3::new(1.0, 2.0, 3.0)));
316
317 assert_eq!(mesh.vertices[0].pos, Vec3::new(1.0, 2.0, 3.0));
318 assert_eq!(mesh.vertices[0].normal, Vec3::new(0.0, 0.0, 1.0));
319 assert_eq!(mesh.vertices[1].pos, Vec3::new(2.0, 2.0, 3.0));
320 assert_eq!(mesh.vertices[1].normal, Vec3::new(0.0, 0.0, 1.0));
321 assert_eq!(mesh.vertices[2].pos, Vec3::new(1.0, 3.0, 3.0));
322 assert_eq!(mesh.vertices[2].normal, Vec3::new(0.0, 0.0, 1.0));
323}