transvoxel/
generic_mesh.rs

1/*!
2A generic (engine independent) implementation of a Mesh, and an associated MeshBuilder
3*/
4
5use 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/**
16Mesh
17*/
18#[derive(Debug)]
19#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
20pub struct Mesh<F>
21where
22    F: Float,
23{
24    /// Flat vector of the vertex positions. Each consecutive three floats define x,y,z for one vertex
25    pub positions: Vec<F>,
26    /// Flat vector of the vertex normals. Each consecutive three floats define x,y,z for one vertex
27    pub normals: Vec<F>,
28    /**
29    Flat vector of the triangle indices. Each consecutive i,j,k define one triangle by 3 indices.
30    Indices are referring to the `positions` and `normals` "triples", so each index is in 0..positions.len()
31    */
32    pub triangle_indices: Vec<usize>,
33}
34
35/// A MeshBuilder that builds Mesh
36pub 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    /// Create a fresh builder
52    pub fn new() -> Self {
53        Self {
54            positions: vec![],
55            normals: vec![],
56            triangle_indices: vec![],
57            vertices: 0,
58        }
59    }
60    /// Output the Mesh
61    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    /// Shorthand to get the triangles count
75    pub fn num_tris(&self) -> usize {
76        self.triangle_indices.len() / 3
77    }
78    /// Outputs a copy of triangles in a structured format
79    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/// A triangle, mostly for debugging or test purposes
131#[derive(Debug, Clone, PartialEq, Copy)]
132pub struct Triangle<F>
133where
134    F: Float,
135{
136    /// Vertices
137    pub vertices: [Vertex<F>; 3],
138}
139
140/// A vertex, mostly for debugging or test purposes
141#[derive(Debug, Clone, PartialEq, Copy)]
142pub struct Vertex<F>
143where
144    F: Float,
145{
146    /// XYZ
147    pub position: [F; 3],
148    /// XYZ of the normal
149    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}