Skip to main content

oxigaf_flame/
mesh.rs

1//! Triangle mesh with per-vertex normals.
2
3use nalgebra as na;
4
5/// A triangle mesh with vertex positions and per-vertex normals.
6#[derive(Debug, Clone)]
7pub struct Mesh {
8    /// Vertex positions.
9    pub vertices: Vec<na::Point3<f32>>,
10    /// Per-vertex normals (area-weighted average of incident face normals).
11    pub normals: Vec<na::Vector3<f32>>,
12    /// Triangle face indices (each element is `[i0, i1, i2]`).
13    pub faces: Vec<[u32; 3]>,
14}
15
16impl Mesh {
17    /// Build a mesh and compute per-vertex normals.
18    #[must_use]
19    pub fn new(vertices: Vec<na::Point3<f32>>, faces: Vec<[u32; 3]>) -> Self {
20        let mut mesh = Self {
21            normals: vec![na::Vector3::zeros(); vertices.len()],
22            vertices,
23            faces,
24        };
25        mesh.recompute_normals();
26        mesh
27    }
28
29    /// Recompute per-vertex normals from the current vertex positions.
30    pub fn recompute_normals(&mut self) {
31        // Zero out
32        for n in &mut self.normals {
33            *n = na::Vector3::zeros();
34        }
35
36        // Accumulate area-weighted face normals
37        for face in &self.faces {
38            let i0 = face[0] as usize;
39            let i1 = face[1] as usize;
40            let i2 = face[2] as usize;
41
42            let v0 = &self.vertices[i0];
43            let v1 = &self.vertices[i1];
44            let v2 = &self.vertices[i2];
45
46            let edge1 = v1 - v0;
47            let edge2 = v2 - v0;
48            // Cross product -- magnitude proportional to triangle area
49            let face_normal = edge1.cross(&edge2);
50
51            self.normals[i0] += face_normal;
52            self.normals[i1] += face_normal;
53            self.normals[i2] += face_normal;
54        }
55
56        // Normalize
57        for n in &mut self.normals {
58            let len = n.norm();
59            if len > 1e-10 {
60                *n /= len;
61            }
62        }
63    }
64
65    /// Number of vertices.
66    #[inline]
67    #[must_use]
68    pub fn num_vertices(&self) -> usize {
69        self.vertices.len()
70    }
71
72    /// Number of triangles.
73    #[inline]
74    #[must_use]
75    pub fn num_faces(&self) -> usize {
76        self.faces.len()
77    }
78
79    /// Compute the area of a triangle face.
80    #[must_use]
81    pub fn face_area(&self, face: &[u32; 3]) -> f32 {
82        let v0 = &self.vertices[face[0] as usize];
83        let v1 = &self.vertices[face[1] as usize];
84        let v2 = &self.vertices[face[2] as usize];
85        let edge1 = v1 - v0;
86        let edge2 = v2 - v0;
87        edge1.cross(&edge2).norm() * 0.5
88    }
89}