Skip to main content

grana_object/
mesh.rs

1use bytemuck::{Pod, Zeroable};
2
3#[repr(C)]
4#[derive(Clone, Copy, Debug, PartialEq, Pod, Zeroable)]
5pub struct MeshVertex {
6    position: [f32; 3],
7    normal: [f32; 3],
8    object: u32,
9}
10
11impl MeshVertex {
12    pub fn new(position: [f32; 3], normal: [f32; 3], object: u32) -> Self {
13        assert!(
14            position
15                .iter()
16                .chain(normal.iter())
17                .all(|value| value.is_finite()),
18            "a mesh vertex is finite"
19        );
20        let length_squared = normal.iter().map(|value| value * value).sum::<f32>();
21        assert!(
22            (length_squared - 1.0).abs() < 1.0e-3,
23            "a mesh normal has unit length"
24        );
25        Self {
26            position,
27            normal,
28            object,
29        }
30    }
31
32    pub fn position(self) -> [f32; 3] {
33        self.position
34    }
35
36    pub fn normal(self) -> [f32; 3] {
37        self.normal
38    }
39
40    pub fn object(self) -> u32 {
41        self.object
42    }
43}
44
45const _: () = assert!(size_of::<MeshVertex>() == 28);
46
47#[derive(Clone, Debug, Default, PartialEq)]
48pub struct Mesh {
49    vertices: Vec<MeshVertex>,
50    indices: Vec<u32>,
51}
52
53impl Mesh {
54    pub fn new(vertices: Vec<MeshVertex>, indices: Vec<u32>) -> Self {
55        assert!(
56            indices.len().is_multiple_of(3),
57            "a mesh holds whole triangles"
58        );
59        assert!(
60            indices
61                .iter()
62                .all(|index| (*index as usize) < vertices.len()),
63            "every mesh index addresses a vertex"
64        );
65        Self { vertices, indices }
66    }
67
68    pub fn vertices(&self) -> &[MeshVertex] {
69        &self.vertices
70    }
71
72    pub fn indices(&self) -> &[u32] {
73        &self.indices
74    }
75
76    pub fn vertex_count(&self) -> usize {
77        self.vertices.len()
78    }
79
80    pub fn triangle_count(&self) -> usize {
81        self.indices.len() / 3
82    }
83
84    pub fn is_empty(&self) -> bool {
85        self.indices.is_empty()
86    }
87
88    pub fn triangle(&self, index: usize) -> [MeshVertex; 3] {
89        [0, 1, 2].map(|corner| self.vertices[self.indices[index * 3 + corner] as usize])
90    }
91}