tiny_game_framework/graphics/
instance_mesh.rs

1use 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    // opengl doesnt allow to send the entirety of the
20    // matrix at once, so we decompose it
21    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        // unsafe { mesh.setup_mesh() }
108
109        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    /* 
151    pub fn add_instance_mesh_from_vertices_and_indices(&mut self, name: &str, vertices: Vec<Vertex>, indices: Vec<u32>) -> Result<(), String> {
152        if self.meshes.contains_key(name) {
153            return Err(format!("Mesh with name '{}' already exists", name));
154        }
155
156        let mesh = InstanceMesh::new(&vertices, &indices, 1); // change  this shid later
157        self.meshes.insert(name.to_owned(), mesh);
158        Ok(())
159    }
160    */
161    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    /* 
171    pub fn get_instance_mesh_mut(&mut self, name: &str) -> Option<&mut InstanceMesh> {
172        self.meshes.get_mut(name)
173    }
174
175    pub fn get_instance_mesh(&self, name: &str) -> Option<&InstanceMesh> {
176        self.meshes.get(name)
177    }
178
179    pub fn destroy_instance_mesh(&mut self, name: &str) -> Result<(), String> {
180        if self.meshes.remove(name).is_some() {
181            Ok(())
182        } else {
183            Err(format!("No mesh found with name '{}'", name))
184        }
185    }
186    */
187}
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}