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}