1use std::fmt::Debug;
6use std::fmt::Display;
7
8use num::Float;
9
10use crate::mesh_builder::GridPoint;
11use crate::mesh_builder::MeshBuilder;
12use crate::mesh_builder::VertexIndex;
13use crate::traits::Density;
14
15#[derive(Debug)]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20pub struct Mesh<F>
21where
22 F: Float,
23{
24 pub positions: Vec<F>,
26 pub normals: Vec<F>,
28 pub triangle_indices: Vec<usize>,
33}
34
35pub struct GenericMeshBuilder<F>
37where
38 F: Float,
39{
40 positions: Vec<F>,
41 normals: Vec<F>,
42 triangle_indices: Vec<usize>,
43 vertices: usize,
44}
45
46#[allow(clippy::new_without_default)]
47impl<F> GenericMeshBuilder<F>
48where
49 F: Float,
50{
51 pub fn new() -> Self {
53 Self {
54 positions: vec![],
55 normals: vec![],
56 triangle_indices: vec![],
57 vertices: 0,
58 }
59 }
60 pub fn build(self) -> Mesh<F> {
62 Mesh {
63 positions: self.positions,
64 normals: self.normals,
65 triangle_indices: self.triangle_indices,
66 }
67 }
68}
69
70impl<F> Mesh<F>
71where
72 F: Float,
73{
74 pub fn num_tris(&self) -> usize {
76 self.triangle_indices.len() / 3
77 }
78 pub fn tris(&self) -> Vec<Triangle<F>> {
80 let mut tris: Vec<Triangle<F>> = vec![];
81 for i in 0..self.num_tris() {
82 let i1 = self.triangle_indices[3 * i];
83 let i2 = self.triangle_indices[3 * i + 1];
84 let i3 = self.triangle_indices[3 * i + 2];
85 tris.push(Triangle {
86 vertices: [
87 Vertex {
88 position: [
89 self.positions[3 * i1],
90 self.positions[3 * i1 + 1],
91 self.positions[3 * i1 + 2],
92 ],
93 normal: [
94 self.normals[3 * i1],
95 self.normals[3 * i1 + 1],
96 self.normals[3 * i1 + 2],
97 ],
98 },
99 Vertex {
100 position: [
101 self.positions[3 * i2],
102 self.positions[3 * i2 + 1],
103 self.positions[3 * i2 + 2],
104 ],
105 normal: [
106 self.normals[3 * i2],
107 self.normals[3 * i2 + 1],
108 self.normals[3 * i2 + 2],
109 ],
110 },
111 Vertex {
112 position: [
113 self.positions[3 * i3],
114 self.positions[3 * i3 + 1],
115 self.positions[3 * i3 + 2],
116 ],
117 normal: [
118 self.normals[3 * i3],
119 self.normals[3 * i3 + 1],
120 self.normals[3 * i3 + 2],
121 ],
122 },
123 ],
124 });
125 }
126 tris
127 }
128}
129
130#[derive(Debug, Clone, PartialEq, Copy)]
132pub struct Triangle<F>
133where
134 F: Float,
135{
136 pub vertices: [Vertex<F>; 3],
138}
139
140#[derive(Debug, Clone, PartialEq, Copy)]
142pub struct Vertex<F>
143where
144 F: Float,
145{
146 pub position: [F; 3],
148 pub normal: [F; 3],
150}
151
152impl<F> Display for Triangle<F>
153where
154 F: Float + Debug,
155{
156 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
157 writeln!(f, "Triangle:")?;
158 let [v1, v2, v3] = self.vertices;
159 writeln!(f, " + Pos {:?} Norm {:?}", v1.position, v1.normal)?;
160 writeln!(f, " + Pos {:?} Norm {:?}", v2.position, v2.normal)?;
161 writeln!(f, " + Pos {:?} Norm {:?}", v3.position, v3.normal)?;
162 Ok(())
163 }
164}
165
166impl MeshBuilder<f32, f32> for GenericMeshBuilder<f32> {
167 fn add_vertex_between(
168 &mut self,
169 point_a: GridPoint<f32, f32>,
170 point_b: GridPoint<f32, f32>,
171 interp_toward_b: f32,
172 ) -> VertexIndex {
173 let position = point_a
174 .position
175 .interp_toward(&point_b.position, interp_toward_b);
176 let gradient_x =
177 point_a.gradient.0 + interp_toward_b * (point_b.gradient.0 - point_a.gradient.0);
178 let gradient_y =
179 point_a.gradient.1 + interp_toward_b * (point_b.gradient.1 - point_a.gradient.1);
180 let gradient_z =
181 point_a.gradient.2 + interp_toward_b * (point_b.gradient.2 - point_a.gradient.2);
182 let normal = f32::gradients_to_normal(gradient_x, gradient_y, gradient_z);
183 self.positions.push(position.x);
184 self.positions.push(position.y);
185 self.positions.push(position.z);
186 self.normals.push(normal[0]);
187 self.normals.push(normal[1]);
188 self.normals.push(normal[2]);
189 let index = self.vertices;
190 self.vertices += 1;
191 VertexIndex(index)
192 }
193
194 fn add_triangle(
195 &mut self,
196 vertex_1_index: VertexIndex,
197 vertex_2_index: VertexIndex,
198 vertex_3_index: VertexIndex,
199 ) {
200 self.triangle_indices.push(vertex_1_index.0);
201 self.triangle_indices.push(vertex_2_index.0);
202 self.triangle_indices.push(vertex_3_index.0);
203 }
204}