tiny_game_framework/graphics/
instance_mesh.rs1use std::{ffi::c_void, mem::{offset_of, size_of}, ptr};
2
3use crate::{bind_buffer, cstr, events::EventLoop, gen_attrib_pointers, Camera, INSTANCE_MESH_SHADER_FS, INSTANCE_MESH_SHADER_VS};
4use std::ffi::CString;
5
6use super::{Renderer, Shader, Vertex, DEFAULT_MESH_SHADER_FS, DEFAULT_MESH_SHADER_VS};
7
8use gl::{*, types::GLsizei};
9use glam::{vec3, Mat4, Quat, Vec2, Vec3, Vec4};
10use once_cell::sync::Lazy;
11
12pub static INSTANCE_SHADER: Lazy<Shader> = Lazy::new(|| {
13 Shader::new_pipeline(INSTANCE_MESH_SHADER_VS, INSTANCE_MESH_SHADER_FS)
14});
15
16
17#[derive(PartialEq, Debug, Copy, Clone)]
18pub struct InstanceData {
19 x_axis: Vec4,
22 y_axis: Vec4,
23 z_axis: Vec4,
24 w_axis: Vec4,
25}
26
27impl InstanceData {
28 pub fn from_position(pos: Vec3) -> Self {
29 let model = Mat4::from_translation(pos);
30
31 Self {
32 x_axis: model.x_axis,
33 y_axis: model.y_axis,
34 z_axis: model.z_axis,
35 w_axis: model.w_axis,
36 }
37 }
38
39 pub fn from_rotation(rot: Quat) -> Self {
40 let model = Mat4::from_quat(rot);
41
42 Self {
43 x_axis: model.x_axis,
44 y_axis: model.y_axis,
45 z_axis: model.z_axis,
46 w_axis: model.w_axis,
47 }
48
49 }
50
51 pub fn from_scale(sca: Vec3) -> Self {
52 let model = Mat4::from_scale(sca);
53
54 Self {
55 x_axis: model.x_axis,
56 y_axis: model.y_axis,
57 z_axis: model.z_axis,
58 w_axis: model.w_axis,
59 }
60 }
61
62 pub fn new(pos: Vec3, rot: Quat, sca: Vec3) -> Self {
63 let model =
64 Mat4::from_translation(pos) *
65 Mat4::from_quat(rot) *
66 Mat4::from_scale(sca);
67
68 Self {
69 x_axis: model.x_axis,
70 y_axis: model.y_axis,
71 z_axis: model.z_axis,
72 w_axis: model.w_axis,
73 }
74 }
75
76}
77
78#[derive(PartialEq, Debug)]
79pub struct InstanceMesh {
80 pub vertices: Vec<Vertex>,
81 pub indices: Vec<u32>,
82
83 pub VAO: u32,
84 EBO: u32,
85 VBO: u32,
86
87 pub instance_buffer: u32,
88
89 pub n: usize,
90
91 pub instance_data: Vec<InstanceData>,
92
93 shader: Shader,
94}
95
96impl InstanceMesh {
97 pub fn new(vertices: &Vec<Vertex>, indices: &Vec<u32>, n: usize) -> Self {
98 let mut mesh = InstanceMesh {
99 vertices: vertices.to_vec(), indices: indices.to_vec(),
100 VAO: 0, VBO: 0, EBO: 0,
101 instance_buffer: 0,
102 n,
103 instance_data: vec![],
104 shader: *INSTANCE_SHADER
105 };
106
107 mesh
110 }
111
112 pub unsafe fn setup_mesh(&mut self) {
113 GenVertexArrays(1, &mut self.VAO);
114 GenBuffers(1, &mut self.VBO);
115 GenBuffers(1, &mut self.EBO);
116
117 BindVertexArray(self.VAO);
118
119 bind_buffer!(ARRAY_BUFFER, self.VBO, self.vertices);
120 bind_buffer!(ELEMENT_ARRAY_BUFFER, self.EBO, self.indices);
121 gen_attrib_pointers!(Vertex, 0 => position: 3, 1 => color: 4);
122
123 GenBuffers(1, &mut self.instance_buffer);
124 bind_buffer!(ARRAY_BUFFER, self.instance_buffer, self.instance_data);
125
126 gen_attrib_pointers!(InstanceData, 2 => x_axis: 4);
127 gen_attrib_pointers!(InstanceData, 3 => y_axis: 4);
128 gen_attrib_pointers!(InstanceData, 4 => z_axis: 4);
129 gen_attrib_pointers!(InstanceData, 5 => w_axis: 4);
130 VertexAttribDivisor(2, 1);
131 VertexAttribDivisor(3, 1);
132 VertexAttribDivisor(4, 1);
133 VertexAttribDivisor(5, 1);
134
135 BindVertexArray(0);
136 }
137
138 pub unsafe fn draw(&self, el: &EventLoop) {
139 let (w, h) = el.window.get_framebuffer_size();
140
141 BindVertexArray(self.VAO);
142 self.shader.use_shader();
143 DrawElementsInstanced(TRIANGLES, self.indices.len() as i32, UNSIGNED_INT, ptr::null(), self.n as i32);
144 BindVertexArray(0);
145 UseProgram(0);
146 }
147}
148
149impl Renderer {
150 pub fn add_instance_mesh(&mut self, name: &str, mesh: InstanceMesh) -> Result<(), String> {
162 if self.instance_meshes.contains_key(name) {
163 return Err(format!("Mesh with name '{}' already exists", name));
164 }
165
166 self.instance_meshes.insert(name.to_owned(), mesh);
167 Ok(())
168 }
169
170 }
188
189impl Drop for InstanceMesh {
190 fn drop(&mut self) {
191 unsafe {
192 DeleteVertexArrays(1, &self.VAO);
193 DeleteBuffers(1, &self.EBO);
194 DeleteBuffers(1, &self.VBO);
195 }
196 }
197}