demo_vk/graphics/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    pub fn indexed_triangles<V, I>(&mut self, vertices: V, indices: I)
113    where
114        V: Iterator<Item = Vertex>,
115        I: Iterator<Item = u32>,
116    {
117        let base_index = self.vertices.len() as u32;
118        self.vertices.extend(vertices);
119        self.indices.extend(indices.map(|index| base_index + index));
120    }
121
122    /// Adds a triangle to the mesh.
123    ///
124    /// Note: triangles must be in clockwise winding order, else they will be
125    /// culled.
126    pub fn triangle(
127        &mut self,
128        color: [f32; 4],
129        texture_index: i32,
130        p1: Vector3<f32>,
131        p2: Vector3<f32>,
132        p3: Vector3<f32>,
133    ) {
134        let base_index = self.vertices.len() as u32;
135
136        self.vertices.extend_from_slice(&[
137            Vertex::new(p1.data.0[0], [0.0, 0.0], color, texture_index),
138            Vertex::new(p2.data.0[0], [0.0, 0.0], color, texture_index),
139            Vertex::new(p3.data.0[0], [0.0, 0.0], color, texture_index),
140        ]);
141        self.indices.extend_from_slice(&[
142            base_index,
143            base_index + 1,
144            base_index + 2,
145        ]);
146    }
147
148    /// Adds a quad to the mesh.
149    ///
150    /// Note: corners should be specified in a clockwise winding order, else the
151    /// triangles that make up the resulting quad may be culled.
152    pub fn quad(
153        &mut self,
154        color: [f32; 4],
155        texture_index: i32,
156        top_left: Vector3<f32>,
157        top_right: Vector3<f32>,
158        bot_right: Vector3<f32>,
159        bot_left: Vector3<f32>,
160    ) {
161        let base_index = self.vertices.len() as u32;
162
163        self.vertices.extend_from_slice(&[
164            Vertex::new(top_left.data.0[0], [0.0, 0.0], color, texture_index),
165            Vertex::new(top_right.data.0[0], [1.0, 0.0], color, texture_index),
166            Vertex::new(bot_right.data.0[0], [1.0, 1.0], color, texture_index),
167            Vertex::new(bot_left.data.0[0], [0.0, 1.0], color, texture_index),
168        ]);
169        self.indices.extend_from_slice(&[
170            // triangle 1
171            base_index,
172            base_index + 1,
173            base_index + 2,
174            // triangle 2
175            base_index,
176            base_index + 2,
177            base_index + 3,
178        ]);
179    }
180}