sim2d/streaming_renderer/
mesh.rs

1use {
2    super::Material,
3    ash::vk,
4    nalgebra::{Matrix4, Vector3},
5    std::sync::Arc,
6};
7
8#[repr(C, align(16))]
9#[derive(Debug, Copy, Clone)]
10pub struct Vertex {
11    pub pos: [f32; 3],
12    pub uv_x: f32,
13    pub color: [f32; 4],
14    pub texture_index: i32,
15    pub uv_y: f32,
16}
17
18impl Vertex {
19    pub fn new(
20        pos: [f32; 3],
21        uv: [f32; 2],
22        color: [f32; 4],
23        texture_index: i32,
24    ) -> Self {
25        Self {
26            pos,
27            uv_x: uv[0],
28            color,
29            texture_index,
30            uv_y: uv[1],
31        }
32    }
33}
34
35/// A Mesh is the minimal unit of rendering.
36///
37/// Data is streamed from the CPU to the GPU each frame from each Mesh.
38pub trait Mesh {
39    fn vertices(&self) -> &[Vertex];
40    fn indices(&self) -> &[u32];
41    fn material(&self) -> &Arc<Material>;
42    fn transform(&self) -> &Matrix4<f32>;
43    fn scissor(&self) -> vk::Rect2D;
44}
45
46/// This mesh supports drawing arbitrary triangles and quads in three
47/// dimensions.
48pub struct TrianglesMesh {
49    vertices: Vec<Vertex>,
50    indices: Vec<u32>,
51    material: Arc<Material>,
52    transform: Matrix4<f32>,
53    scissor: vk::Rect2D,
54}
55
56impl Mesh for TrianglesMesh {
57    fn vertices(&self) -> &[Vertex] {
58        &self.vertices
59    }
60
61    fn indices(&self) -> &[u32] {
62        &self.indices
63    }
64
65    fn material(&self) -> &Arc<Material> {
66        &self.material
67    }
68
69    fn transform(&self) -> &Matrix4<f32> {
70        &self.transform
71    }
72
73    fn scissor(&self) -> vk::Rect2D {
74        self.scissor
75    }
76}
77
78impl TrianglesMesh {
79    /// Creates a new empty Mesh with pre-allocated internal memory for
80    /// vertex data.
81    pub fn new(initial_capacity: usize, material: Arc<Material>) -> Self {
82        Self {
83            vertices: Vec::with_capacity(initial_capacity),
84            indices: Vec::with_capacity(initial_capacity),
85            material,
86            transform: Matrix4::identity(),
87            scissor: vk::Rect2D {
88                offset: vk::Offset2D { x: 0, y: 0 },
89                extent: vk::Extent2D {
90                    width: 1,
91                    height: 1,
92                },
93            },
94        }
95    }
96
97    pub fn set_scissor(&mut self, rect: vk::Rect2D) {
98        self.scissor = rect;
99    }
100
101    /// Set the matrix transformation matrix.
102    pub fn set_transform(&mut self, projection: Matrix4<f32>) {
103        self.transform = projection;
104    }
105
106    /// Clears all geometry from the Mesh while retaining any allocated memory.
107    pub fn clear(&mut self) {
108        self.vertices.clear();
109        self.indices.clear();
110    }
111
112    /// Adds a triangle to the mesh.
113    ///
114    /// Note: triangles must be in clockwise winding order, else they will be
115    /// culled.
116    pub fn triangle(
117        &mut self,
118        color: [f32; 4],
119        texture_index: i32,
120        p1: Vector3<f32>,
121        p2: Vector3<f32>,
122        p3: Vector3<f32>,
123    ) {
124        let base_index = self.vertices.len() as u32;
125
126        self.vertices.extend_from_slice(&[
127            Vertex::new(p1.data.0[0], [0.0, 0.0], color, texture_index),
128            Vertex::new(p2.data.0[0], [0.0, 0.0], color, texture_index),
129            Vertex::new(p3.data.0[0], [0.0, 0.0], color, texture_index),
130        ]);
131        self.indices.extend_from_slice(&[
132            base_index,
133            base_index + 1,
134            base_index + 2,
135        ]);
136    }
137
138    /// Adds a quad to the mesh.
139    ///
140    /// Note: corners should be specified in a clockwise winding order, else the
141    /// triangles that make up the resulting quad may be culled.
142    pub fn quad(
143        &mut self,
144        color: [f32; 4],
145        texture_index: i32,
146        top_left: Vector3<f32>,
147        top_right: Vector3<f32>,
148        bot_right: Vector3<f32>,
149        bot_left: Vector3<f32>,
150    ) {
151        let base_index = self.vertices.len() as u32;
152
153        self.vertices.extend_from_slice(&[
154            Vertex::new(top_left.data.0[0], [0.0, 0.0], color, texture_index),
155            Vertex::new(top_right.data.0[0], [1.0, 0.0], color, texture_index),
156            Vertex::new(bot_right.data.0[0], [1.0, 1.0], color, texture_index),
157            Vertex::new(bot_left.data.0[0], [0.0, 1.0], color, texture_index),
158        ]);
159        self.indices.extend_from_slice(&[
160            // triangle 1
161            base_index,
162            base_index + 1,
163            base_index + 2,
164            // triangle 2
165            base_index,
166            base_index + 2,
167            base_index + 3,
168        ]);
169    }
170}