use std::mem::size_of; use crate::opengl::buffer::{ArrayKind as ArrayBufferKind, Buffer}; use crate::opengl::currently_bound::CurrentlyBound; use crate::vertex::{Attribute, AttributeComponentType, Vertex}; const VERTEX_STRIDE: usize = size_of::(); #[derive(Debug)] pub struct VertexArray { array: gl::types::GLuint, } impl VertexArray { pub fn new() -> Self { let mut array = 0; unsafe { gl::GenVertexArrays(1, &mut array); } Self { array } } /// Draws the currently bound vertex array. pub fn draw_arrays( _currently_bound: &CurrentlyBound, primitive_kind: PrimitiveKind, start_index: u32, cnt: u32, ) { unsafe { #[allow(clippy::cast_possible_wrap)] gl::DrawArrays( primitive_kind.into_gl(), start_index as gl::types::GLint, cnt as gl::types::GLsizei, ); } } /// Draws the currently bound vertex array. pub fn draw_elements( _currently_bound: &CurrentlyBound, primitive_kind: PrimitiveKind, offset: u32, cnt: u32, ) { unsafe { #[allow(clippy::cast_possible_wrap)] gl::DrawElements( primitive_kind.into_gl(), cnt as gl::types::GLsizei, gl::UNSIGNED_INT, (offset as gl::types::GLint) as *const _, ); } } pub fn configure_attrs( _currently_bound: &CurrentlyBound, _vert_buf_curr_bound: &CurrentlyBound>, ) { let mut offset = 0; for attr in Vertex::attrs() { Self::vertex_attrib_ptr(attr, offset); Self::enable_vertex_attrib_array(attr.index); offset += attr.component_size * attr.component_cnt as usize; } } #[allow(clippy::inline_always)] #[inline(always)] pub fn bind(&self, cb: impl FnOnce(CurrentlyBound<'_, Self>)) { unsafe { gl::BindVertexArray(self.array) } // SAFETY: A vertex array object is currently bound let currently_bound = unsafe { CurrentlyBound::new() }; cb(currently_bound); } fn vertex_attrib_ptr(vertex_attr: &Attribute, offset: usize) { unsafe { #[allow(clippy::cast_possible_wrap, clippy::cast_possible_truncation)] gl::VertexAttribPointer( vertex_attr.index as gl::types::GLuint, vertex_attr.component_cnt as i32, Self::vertex_attr_type_to_gl(&vertex_attr.component_type), gl::FALSE, VERTEX_STRIDE as gl::types::GLsizei, offset as *const _, ); } } fn enable_vertex_attrib_array(index: usize) { unsafe { #[allow(clippy::cast_possible_truncation)] gl::EnableVertexAttribArray(index as gl::types::GLuint); } } fn vertex_attr_type_to_gl( vertex_attr_type: &AttributeComponentType, ) -> gl::types::GLenum { match vertex_attr_type { AttributeComponentType::Float => gl::FLOAT, } } } impl Drop for VertexArray { fn drop(&mut self) { unsafe { gl::DeleteVertexArrays(1, &self.array); } } } #[derive(Debug)] pub enum PrimitiveKind { Triangles, } impl PrimitiveKind { fn into_gl(self) -> gl::types::GLenum { match self { Self::Triangles => gl::TRIANGLES, } } }