fj_interop/
mesh.rs

1use std::{collections::HashMap, hash::Hash};
2
3use fj_math::Point;
4
5use crate::Color;
6
7/// A triangle mesh
8#[derive(Clone, Debug)]
9pub struct Mesh<V> {
10    vertices: Vec<V>,
11    indices: Vec<Index>,
12
13    indices_by_vertex: HashMap<V, Index>,
14    triangles: Vec<Triangle>,
15}
16
17impl<V> Mesh<V>
18where
19    V: Copy + Eq + Hash,
20{
21    /// Construct a new instance of `Mesh`
22    pub fn new() -> Self {
23        Self::default()
24    }
25
26    /// Add a vertex to the mesh
27    pub fn push_vertex(&mut self, vertex: V) {
28        let index =
29            *self.indices_by_vertex.entry(vertex).or_insert_with(|| {
30                let index = self.vertices.len();
31                self.vertices.push(vertex);
32                index as u32
33            });
34
35        self.indices.push(index);
36    }
37
38    /// Determine whether the mesh contains the provided triangle
39    ///
40    /// Returns true, if a triangle with any combination of the provided points
41    /// is part of the mesh.
42    pub fn contains_triangle(
43        &self,
44        triangle: impl Into<fj_math::Triangle<3>>,
45    ) -> bool {
46        let triangle = triangle.into().normalize();
47
48        for t in &self.triangles {
49            let t = t.inner.normalize();
50            if triangle == t {
51                return true;
52            }
53        }
54
55        false
56    }
57
58    /// Access the vertices of the mesh
59    pub fn vertices(&self) -> impl Iterator<Item = V> + '_ {
60        self.vertices.iter().copied()
61    }
62
63    /// Access the indices of the mesh
64    pub fn indices(&self) -> impl Iterator<Item = Index> + '_ {
65        self.indices.iter().copied()
66    }
67
68    /// Access the triangles of the mesh
69    pub fn triangles(&self) -> impl Iterator<Item = Triangle> + '_ {
70        self.triangles.iter().copied()
71    }
72}
73
74impl Mesh<Point<3>> {
75    /// Add a triangle to the mesh
76    pub fn push_triangle(
77        &mut self,
78        triangle: impl Into<fj_math::Triangle<3>>,
79        color: Color,
80    ) {
81        let triangle = triangle.into();
82
83        for point in triangle.points() {
84            self.push_vertex(point);
85        }
86
87        self.triangles.push(Triangle {
88            inner: triangle,
89            color,
90        });
91    }
92}
93
94// This needs to be a manual implementation. Deriving `Default` would require
95// `V` to be `Default` as well, even though that is not necessary.
96impl<V> Default for Mesh<V> {
97    fn default() -> Self {
98        Self {
99            vertices: Vec::default(),
100            indices: Vec::default(),
101            indices_by_vertex: HashMap::default(),
102            triangles: Vec::default(),
103        }
104    }
105}
106
107/// An index that refers to a vertex in a mesh
108pub type Index = u32;
109
110/// A triangle
111///
112/// Extension of [`fj_math::Triangle`] that also includes a color.
113#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd)]
114pub struct Triangle {
115    /// The points of the triangle
116    pub inner: fj_math::Triangle<3>,
117
118    /// The color of the triangle
119    pub color: Color,
120}