1#![allow(dead_code)]
2use glam::{Mat4, Vec4};
3use std::clone::Clone;
4use tobj::{Material, Mesh};
5use stl_io::IndexedMesh;
6
7#[derive(PartialEq, Debug)]
8pub struct AABB {
9 pub min: Vec4,
10 pub max: Vec4,
11}
12
13impl AABB {
14 pub fn new(min: Vec4, max: Vec4) -> AABB {
15 AABB { min, max }
16 }
17}
18
19#[derive(PartialEq, Debug)]
20pub struct Triangle {
21 pub color: (u8, u8, u8),
22 pub v1: Vec4,
23 pub v2: Vec4,
24 pub v3: Vec4,
25}
26
27impl Default for Triangle {
28 fn default() -> Self {
29 Self {
30 color: (1, 0, 0),
31 v1: Vec4::new(1.0, -1.0, -1.0, 1.0),
32 v2: Vec4::new(-1.0, -1.0, 1.0, 1.0),
33 v3: Vec4::new(1.0, 1.0, -1.0, 1.0),
34 }
35 }
36}
37
38impl Triangle {
39 pub fn aabb(&self) -> AABB {
40 AABB::new(
41 Vec4::new(
42 self.v1[0].min(self.v2[0].min(self.v3[0])),
43 self.v1[1].min(self.v2[1].min(self.v3[1])),
44 self.v1[2].min(self.v2[2].min(self.v3[2])),
45 1.0,
46 ),
47 Vec4::new(
48 self.v1[0].max(self.v2[0].max(self.v3[0])),
49 self.v1[1].max(self.v2[1].max(self.v3[1])),
50 self.v1[2].max(self.v2[2].max(self.v3[2])),
51 1.0,
52 ),
53 )
54 }
55 pub fn mul(&mut self, transform: Mat4) -> &mut Triangle {
56 self.v1 = transform * self.v1;
57 self.v2 = transform * self.v2;
58 self.v3 = transform * self.v3;
59 self
60 }
61 pub fn normal(&self) -> Vec4 {
62 let v1 = self.v2 - self.v1;
63 let v2 = self.v3 - self.v1;
64 let x = (v1[1] * v2[2]) - (v1[2] * v2[1]);
65 let y = (v1[2] * v2[0]) - (v1[0] * v2[2]);
66 let z = (v1[0] * v2[1]) - (v1[1] * v2[0]);
67 Vec4::new(x, y, z, 0.0).normalize()
68 }
69}
70
71impl Clone for Triangle {
72 fn clone(&self) -> Triangle {
73 Triangle {
74 color: self.color,
75 v1: self.v1,
76 v2: self.v2,
77 v3: self.v3,
78 }
79 }
80}
81
82pub trait ToSimpleMesh {
83 fn to_simple_mesh(&self) -> SimpleMesh;
84}
85
86pub trait ToSimpleMeshWithMaterial {
87 fn to_simple_mesh_with_materials(&self, materials: &[Material]) -> SimpleMesh;
88}
89
90pub struct SimpleMesh {
91 pub bounding_box: AABB,
92 pub triangles: Vec<Triangle>,
93}
94
95impl ToSimpleMeshWithMaterial for Mesh {
96 fn to_simple_mesh_with_materials(&self, materials: &[Material]) -> SimpleMesh {
97 let mut bounding_box = AABB {
98 min: Vec4::new(0.0, 0.0, 0.0, 1.0),
99 max: Vec4::new(0.0, 0.0, 0.0, 1.0),
100 };
101 let mut triangles = vec![
102 Triangle {
103 color: (1, 1, 1),
104 v1: Vec4::new(0.0, 0.0, 0.0, 1.0),
105 v2: Vec4::new(0.0, 0.0, 0.0, 1.0),
106 v3: Vec4::new(0.0, 0.0, 0.0, 1.0)
107 };
108 self.indices.len() / 3
109 ];
110 for (x, tri) in triangles.iter_mut().enumerate() {
111 tri.v1.x = self.positions[(self.indices[x * 3] * 3) as usize];
112 tri.v1.y = self.positions[(self.indices[x * 3] * 3 + 1) as usize];
113 tri.v1.z = self.positions[(self.indices[x * 3] * 3 + 2) as usize];
114 tri.v2.x = self.positions[(self.indices[x * 3 + 1] * 3) as usize];
115 tri.v2.y = self.positions[(self.indices[x * 3 + 1] * 3 + 1) as usize];
116 tri.v2.z = self.positions[(self.indices[x * 3 + 1] * 3 + 2) as usize];
117 tri.v3.x = self.positions[(self.indices[x * 3 + 2] * 3) as usize];
118 tri.v3.y = self.positions[(self.indices[x * 3 + 2] * 3 + 1) as usize];
119 tri.v3.z = self.positions[(self.indices[x * 3 + 2] * 3 + 2) as usize];
120
121 if !materials.is_empty() {
122 let material = &materials[self.material_id.unwrap()];
123 tri.color = (
124 (material.diffuse[0] * 255.0) as u8,
125 (material.diffuse[1] * 255.0) as u8,
126 (material.diffuse[2] * 255.0) as u8,
127 );
128
129 if !self.vertex_color.is_empty() {
131 let color = (
133 (self.vertex_color[(self.indices[x * 3] * 3) as usize] * 255.0) as u8,
134 (self.vertex_color[(self.indices[x * 3] * 3 + 1) as usize] * 255.0) as u8,
135 (self.vertex_color[(self.indices[x * 3] * 3 + 2) as usize] * 255.0) as u8,
136 );
137 tri.color = color;
138 }
139 }
140
141 let aabb = tri.aabb();
142 bounding_box.min.x = aabb.min.x.min(bounding_box.min.x);
143 bounding_box.min.y = aabb.min.y.min(bounding_box.min.y);
144 bounding_box.min.z = aabb.min.z.min(bounding_box.min.z);
145 bounding_box.max.x = aabb.max.x.max(bounding_box.max.x);
146 bounding_box.max.y = aabb.max.y.max(bounding_box.max.y);
147 bounding_box.max.z = aabb.max.z.max(bounding_box.max.z);
148 }
149 SimpleMesh {
150 triangles,
151 bounding_box,
152 }
153 }
154}
155
156impl ToSimpleMesh for Mesh {
157 fn to_simple_mesh(&self) -> SimpleMesh {
158 self.to_simple_mesh_with_materials(&[])
159 }
160}
161
162impl ToSimpleMesh for IndexedMesh {
163 fn to_simple_mesh(&self) -> SimpleMesh {
164 let mut bounding_box = AABB {
165 min: Vec4::new(std::f32::MAX, std::f32::MAX, std::f32::MAX, 1.0),
166 max: Vec4::new(std::f32::MIN, std::f32::MIN, std::f32::MIN, 1.0),
167 };
168 fn stlv2v4(stlio_vec: [f32; 3]) -> Vec4 {
169 Vec4::new(stlio_vec[0], stlio_vec[1], stlio_vec[2], 1.0)
170 }
171 let mut triangles = vec![
172 Triangle {
173 color: (0xFF, 0xFF, 0x00),
175 v1: Vec4::new(0.0, 0.0, 0.0, 1.0),
176 v2: Vec4::new(0.0, 0.0, 0.0, 1.0),
177 v3: Vec4::new(0.0, 0.0, 0.0, 1.0)
178 };
179 self.faces.len()
180 ];
181 #[allow(clippy::needless_range_loop)]
182 for t_index in 0..self.faces.len() {
184 triangles[t_index].v1 = stlv2v4(self.vertices[self.faces[t_index].vertices[0]].into());
185 triangles[t_index].v2 = stlv2v4(self.vertices[self.faces[t_index].vertices[1]].into());
186 triangles[t_index].v3 = stlv2v4(self.vertices[self.faces[t_index].vertices[2]].into());
187 let aabb = triangles[t_index].aabb();
188 bounding_box.min.x = aabb.min.x.min(bounding_box.min.x);
189 bounding_box.min.y = aabb.min.y.min(bounding_box.min.y);
190 bounding_box.min.z = aabb.min.z.min(bounding_box.min.z);
191 bounding_box.max.x = aabb.max.x.max(bounding_box.max.x);
192 bounding_box.max.y = aabb.max.y.max(bounding_box.max.y);
193 bounding_box.max.z = aabb.max.z.max(bounding_box.max.z);
194 }
195 SimpleMesh {
196 triangles,
197 bounding_box,
198 }
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205 use glam::{Mat4, Vec3, Vec4};
206
207 #[test]
208 fn test_aabb() {
209 let triangle = Triangle::default();
210 assert_eq!(
211 triangle.aabb(),
212 AABB::new(
213 Vec4::new(-1.0, -1.0, -1.0, 1.0),
214 Vec4::new(1.0, 1.0, 1.0, 1.0)
215 )
216 );
217 }
218
219 #[test]
220 fn test_transform() {
221 let transform = Mat4::from_translation(Vec3::new(1.0, 1.0, 1.0));
222 let mut triangle = Triangle::default();
223 triangle.mul(transform);
224 assert_eq!(
225 triangle.aabb(),
226 AABB::new(Vec4::new(0.0, 0.0, 0.0, 1.0), Vec4::new(2.0, 2.0, 2.0, 1.0))
227 );
228 }
229
230 #[test]
231 fn test_normal() {
232 let triangle = Triangle {
233 color: (1, 0, 0),
234 v1: Vec4::new(-1.0, 1.0, 0.0, 1.0),
235 v2: Vec4::new(0.0, 1.0, 1.0, 1.0),
236 v3: Vec4::new(1.0, 1.0, 0.0, 1.0),
237 };
238 assert_eq!(triangle.normal(), Vec4::new(0.0, 1.0, 0.0, 0.0));
239 }
240}