mesh_graph/elements/
face.rs

1use glam::Vec3;
2use parry3d::{bounding_volume::Aabb, na::Point3};
3use tracing::{error, instrument};
4
5use crate::{CircularHalfedgesIterator, MeshGraph, error_none};
6
7use super::{FaceId, HalfedgeId, VertexId};
8
9#[derive(Default, Debug, Clone, Copy)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11pub struct Face {
12    /// One of the halfedges of the face.
13    /// Serves as a starting point for traversing the face's edges and vertices
14    pub halfedge: HalfedgeId,
15
16    /// The index of the face in the BVH
17    pub index: u32,
18
19    /// The associated face id
20    pub id: FaceId,
21}
22
23impl Face {
24    /// Returns the three halfedges that form this face
25    #[instrument(skip(mesh_graph))]
26    pub fn halfedges<'a>(&self, mesh_graph: &'a MeshGraph) -> CircularHalfedgesIterator<'a> {
27        CircularHalfedgesIterator::new(Some(self.halfedge), mesh_graph, |he, mesh_graph| {
28            mesh_graph
29                .halfedges
30                .get(he)
31                .or_else(error_none!("Halfedge not found"))?
32                .next
33        })
34    }
35
36    /// Returns the three corner vertices of this face.
37    #[instrument(skip(mesh_graph))]
38    pub fn vertices(&self, mesh_graph: &MeshGraph) -> impl Iterator<Item = VertexId> {
39        self.halfedges(mesh_graph).filter_map(|he| {
40            mesh_graph
41                .halfedges
42                .get(he)
43                .or_else(error_none!("Halfedge not found"))
44                .map(|he| he.end_vertex)
45        })
46    }
47
48    /// Center positions of this face.
49    #[instrument(skip(mesh_graph))]
50    pub fn center(&self, mesh_graph: &MeshGraph) -> Vec3 {
51        let mut sum = Vec3::ZERO;
52
53        for vertex in self.vertices(mesh_graph) {
54            if let Some(position) = mesh_graph.positions.get(vertex) {
55                sum += position;
56            } else {
57                error!("Vertex position not found");
58            }
59        }
60
61        sum / 3.0
62    }
63
64    /// Compute the parry Aabb of this triangle
65    #[instrument(skip(mesh_graph))]
66    pub fn aabb(&self, mesh_graph: &MeshGraph) -> Aabb {
67        Aabb::from_points(self.vertices(mesh_graph).filter_map(|v| {
68            mesh_graph
69                .positions
70                .get(v)
71                .or_else(error_none!("Position not found"))
72                .map(|p| Point3::new(p.x, p.y, p.z))
73        }))
74    }
75}