blender_mesh/
triangulate.rs

1use crate::BlenderMesh;
2impl BlenderMesh {
3    /// When exporting a mesh from Blender, faces will usually have 4 vertices (quad) but some
4    /// faces might have 3 (triangle).
5    ///
6    /// We read `self.num_vertices_in_each_face` to check how
7    /// many vertices each face has.
8    ///
9    /// If a face has 4 vertices we convert it into two triangles, each with 3 vertices.
10    ///
11    /// # Panics
12    ///
13    /// Panics if a face has more than 4 vertices. In the future we might support 5+ vertices,
14    /// but I haven't run into that yet. Not even sure if Blender can have faces with 5 vertices..
15    pub(crate) fn triangulate(&self, indices: &Vec<u16>) -> Vec<u16> {
16        let mut triangulated_position_indices = vec![];
17        let mut triangulated_face_vertex_counts = vec![];
18
19        let mut face_pointer = 0;
20
21        for num_verts_in_face in self
22            .multi_indexed_vertex_attributes
23            .vertices_in_each_face
24            .iter()
25        {
26            triangulated_position_indices.push(indices[face_pointer]);
27            triangulated_position_indices.push(indices[face_pointer + 1]);
28            triangulated_position_indices.push(indices[face_pointer + 2]);
29
30            triangulated_face_vertex_counts.push(3);
31
32            match num_verts_in_face {
33                &3 => {}
34                &4 => {
35                    triangulated_position_indices.push(indices[face_pointer]);
36                    triangulated_position_indices.push(indices[face_pointer + 2]);
37                    triangulated_position_indices.push(indices[face_pointer + 3]);
38
39                    triangulated_face_vertex_counts.push(3);
40                }
41                _ => {
42                    panic!("blender-mesh currently only supports triangulating faces with 3 or 4 vertices");
43                }
44            };
45
46            face_pointer += *num_verts_in_face as usize;
47        }
48
49        // TODO: ? Set to Uniform(3)
50        // multi.vertices_in_each_face = triangulated_face_vertex_counts;
51
52        return triangulated_position_indices;
53    }
54}
55
56#[cfg(test)]
57mod tests {
58    use super::*;
59    use crate::vertex_attributes::{
60        IndexedAttribute, MultiIndexedVertexAttributes, VertexAttribute,
61    };
62
63    #[test]
64    fn triangulate_faces() {
65        let start_mesh = BlenderMesh {
66            multi_indexed_vertex_attributes: MultiIndexedVertexAttributes {
67                positions: IndexedAttribute {
68                    indices: vec![0, 1, 2, 3, 4, 5, 6, 7],
69                    attribute: VertexAttribute::default(),
70                },
71                vertices_in_each_face: vec![4, 4],
72                ..MultiIndexedVertexAttributes::default()
73            }
74            .into(),
75            ..BlenderMesh::default()
76        };
77
78        let triangulated_indices = start_mesh.triangulate(&vec![0, 1, 2, 3, 4, 5, 6, 7]);
79        assert_eq!(
80            triangulated_indices,
81            vec![0, 1, 2, 0, 2, 3, 4, 5, 6, 4, 6, 7]
82        );
83    }
84}