1use crate::{Bounds3D, FetchBounds3D, Vec3};
5use manifold_rs::{Manifold, Mesh};
6
7#[derive(Clone, Copy, Debug)]
9pub struct Vertex {
10 pub pos: Vec3,
12 pub normal: Vec3,
14}
15
16#[derive(Clone, Copy, Debug)]
18pub struct Triangle<T>(pub T, pub T, pub T);
19
20impl Triangle<Vertex> {
21 pub fn normal(&self) -> Vec3 {
23 (self.2.pos - self.0.pos).cross(self.1.pos - self.0.pos)
24 }
25}
26
27impl Triangle<&Vertex> {
28 pub fn normal(&self) -> Vec3 {
30 (self.2.pos - self.0.pos).cross(self.1.pos - self.0.pos)
31 }
32
33 pub fn signed_volume(&self) -> f64 {
37 let v210 = self.2.pos.x * self.1.pos.y * self.0.pos.z;
38 let v120 = self.1.pos.x * self.2.pos.y * self.0.pos.z;
39 let v201 = self.2.pos.x * self.0.pos.y * self.1.pos.z;
40 let v021 = self.0.pos.x * self.2.pos.y * self.1.pos.z;
41 let v102 = self.1.pos.x * self.0.pos.y * self.2.pos.z;
42 let v012 = self.0.pos.x * self.1.pos.y * self.2.pos.z;
43
44 (1.0 / 6.0) * (-v210 + v120 + v201 - v021 - v102 + v012)
45 }
46}
47
48#[derive(Default, Clone)]
50pub struct TriangleMesh {
51 pub vertices: Vec<Vertex>,
53 pub triangle_indices: Vec<Triangle<u32>>,
55}
56
57pub struct Triangles<'a> {
59 triangle_mesh: &'a TriangleMesh,
60 index: usize,
61}
62
63impl<'a> Iterator for Triangles<'a> {
64 type Item = Triangle<&'a Vertex>;
65
66 fn next(&mut self) -> Option<Self::Item> {
67 if self.index < self.triangle_mesh.triangle_indices.len() {
68 let t = self.triangle_mesh.triangle_indices[self.index];
69 self.index += 1;
70 Some(Triangle(
71 &self.triangle_mesh.vertices[t.0 as usize],
72 &self.triangle_mesh.vertices[t.1 as usize],
73 &self.triangle_mesh.vertices[t.2 as usize],
74 ))
75 } else {
76 None
77 }
78 }
79}
80
81impl TriangleMesh {
82 pub fn clear(&mut self) {
84 self.vertices.clear();
85 self.triangle_indices.clear();
86 }
87
88 pub fn fetch_triangles(&self) -> Vec<Triangle<Vertex>> {
90 self.triangle_indices
91 .iter()
92 .map(|t| {
93 Triangle(
94 self.vertices[t.0 as usize],
95 self.vertices[t.1 as usize],
96 self.vertices[t.2 as usize],
97 )
98 })
99 .collect()
100 }
101
102 pub fn append(&mut self, other: &TriangleMesh) {
104 let offset = self.vertices.len() as u32;
105 self.vertices.extend_from_slice(&other.vertices);
106 self.triangle_indices.extend(
107 other
108 .triangle_indices
109 .iter()
110 .map(|t| Triangle(t.0 + offset, t.1 + offset, t.2 + offset)),
111 )
112 }
113
114 pub fn triangles(&'_ self) -> Triangles<'_> {
116 Triangles {
117 triangle_mesh: self,
118 index: 0,
119 }
120 }
121
122 pub fn to_manifold(&self) -> Manifold {
124 let vertices = self
125 .vertices
126 .iter()
127 .flat_map(|v| vec![v.pos.x as f32, v.pos.y as f32, v.pos.z as f32])
128 .collect::<Vec<_>>();
129
130 let triangle_indices = self
131 .triangle_indices
132 .iter()
133 .flat_map(|t| vec![t.0, t.1, t.2])
134 .collect::<Vec<_>>();
135
136 assert_eq!(vertices.len(), self.vertices.len() * 3);
137 assert_eq!(triangle_indices.len(), self.triangle_indices.len() * 3);
138
139 Manifold::from_mesh(Mesh::new(&vertices, &triangle_indices))
140 }
141
142 pub fn transform(&self, transform: &crate::Mat4) -> Self {
150 let rot_mat = crate::Mat3::from_cols(
151 transform.x.truncate(),
152 transform.y.truncate(),
153 transform.z.truncate(),
154 );
155 let vertices = self
156 .vertices
157 .iter()
158 .map(|v| Vertex {
159 pos: (transform * v.pos.extend(1.0)).truncate(),
160 normal: rot_mat * v.normal,
161 })
162 .collect();
163
164 TriangleMesh {
165 vertices,
166 triangle_indices: self.triangle_indices.clone(),
167 }
168 }
169
170 pub fn volume(&self) -> f64 {
172 self.triangles()
173 .map(|t| t.signed_volume())
174 .sum::<f64>()
175 .abs()
176 }
177}
178
179impl FetchBounds3D for TriangleMesh {
180 fn fetch_bounds_3d(&self) -> Bounds3D {
181 self.vertices.iter().map(|vertex| vertex.pos).collect()
182 }
183}
184
185impl From<Mesh> for TriangleMesh {
186 fn from(mesh: Mesh) -> Self {
187 let vertices = mesh.vertices();
188 let indices = mesh.indices();
189
190 TriangleMesh {
194 vertices: (0..vertices.len())
195 .step_by(3)
196 .map(|i| Vertex {
197 pos: Vec3::new(
198 vertices[i] as f64,
199 vertices[i + 1] as f64,
200 vertices[i + 2] as f64,
201 ),
202 normal: Vec3::new(0.0, 0.0, 0.0),
203 })
204 .collect(),
205 triangle_indices: (0..indices.len())
206 .step_by(3)
207 .map(|i| Triangle(indices[i], indices[i + 1], indices[i + 2]))
208 .collect(),
209 }
210 }
211}
212
213impl From<TriangleMesh> for Mesh {
214 fn from(mesh: TriangleMesh) -> Self {
215 let mut vertices = Vec::new();
216 let mut indices = Vec::new();
217
218 for v in &mesh.vertices {
219 vertices.push(v.pos.x as f32);
220 vertices.push(v.pos.y as f32);
221 vertices.push(v.pos.z as f32);
222 }
223
224 for t in &mesh.triangle_indices {
225 indices.push(t.0);
226 indices.push(t.1);
227 indices.push(t.2);
228 }
229
230 Mesh::new(vertices.as_slice(), indices.as_slice())
231 }
232}
233
234impl From<Manifold> for TriangleMesh {
235 fn from(manifold: Manifold) -> Self {
236 TriangleMesh::from(manifold.to_mesh())
237 }
238}
239
240#[test]
241fn test_triangle_mesh_transform() {
242 let mesh = TriangleMesh {
243 vertices: vec![
244 Vertex {
245 pos: Vec3::new(0.0, 0.0, 0.0),
246 normal: Vec3::new(0.0, 0.0, 1.0),
247 },
248 Vertex {
249 pos: Vec3::new(1.0, 0.0, 0.0),
250 normal: Vec3::new(0.0, 0.0, 1.0),
251 },
252 Vertex {
253 pos: Vec3::new(0.0, 1.0, 0.0),
254 normal: Vec3::new(0.0, 0.0, 1.0),
255 },
256 ],
257 triangle_indices: vec![Triangle(0, 1, 2)],
258 };
259
260 let mesh = mesh.transform(&crate::Mat4::from_translation(Vec3::new(1.0, 2.0, 3.0)));
261
262 assert_eq!(mesh.vertices[0].pos, Vec3::new(1.0, 2.0, 3.0));
263 assert_eq!(mesh.vertices[0].normal, Vec3::new(0.0, 0.0, 1.0));
264 assert_eq!(mesh.vertices[1].pos, Vec3::new(2.0, 2.0, 3.0));
265 assert_eq!(mesh.vertices[1].normal, Vec3::new(0.0, 0.0, 1.0));
266 assert_eq!(mesh.vertices[2].pos, Vec3::new(1.0, 3.0, 3.0));
267 assert_eq!(mesh.vertices[2].normal, Vec3::new(0.0, 0.0, 1.0));
268}