use opengl_bindings::buffer::{Buffer as GlBuffer, Usage as GlBufferUsage}; use opengl_bindings::vertex_array::{ DataType as GlVertexArrayDataType, VertexArray as GlVertexArray, }; use opengl_bindings::CurrentContextWithFns as GlCurrentContextWithFns; use crate::mesh::Mesh; use crate::renderer::opengl::vertex::{ AttributeComponentType as VertexAttributeComponentType, Vertex as RendererVertex, }; #[derive(Debug)] pub struct GraphicsMesh { /// Vertex and index buffer has to live as long as the vertex array _vertex_buffer: GlBuffer, pub index_buffer: Option>, pub element_cnt: u32, pub vertex_arr: GlVertexArray, } impl GraphicsMesh { #[tracing::instrument(skip_all)] pub fn new( current_context: &GlCurrentContextWithFns<'_>, mesh: &Mesh, ) -> Result { tracing::trace!( "Creating vertex array, vertex buffer{}", if mesh.indices().is_some() { " and index buffer" } else { "" } ); let vertex_arr = GlVertexArray::new(current_context); let vertex_buffer = GlBuffer::new(current_context); vertex_buffer .store_mapped( current_context, mesh.vertices(), GlBufferUsage::Static, |vertex| RendererVertex { pos: vertex.pos.into(), texture_coords: vertex.texture_coords.into(), normal: vertex.normal.into(), }, ) .map_err(Error::StoreVerticesFailed)?; vertex_arr.bind_vertex_buffer(current_context, 0, &vertex_buffer, 0); let mut offset = 0u32; for attrib in RendererVertex::attrs() { vertex_arr.enable_attrib(current_context, attrib.index); vertex_arr.set_attrib_format( current_context, attrib.index, match attrib.component_type { VertexAttributeComponentType::Float => GlVertexArrayDataType::Float, }, false, offset, ); vertex_arr.set_attrib_vertex_buf_binding(current_context, attrib.index, 0); offset += attrib.component_size * attrib.component_cnt as u32; } if let Some(indices) = mesh.indices() { let index_buffer = GlBuffer::new(current_context); index_buffer .store(current_context, indices, GlBufferUsage::Static) .map_err(Error::StoreIndicesFailed)?; vertex_arr.bind_element_buffer(current_context, &index_buffer); return Ok(Self { _vertex_buffer: vertex_buffer, index_buffer: Some(index_buffer), element_cnt: indices .len() .try_into() .expect("Mesh index count does not fit into a 32-bit unsigned int"), vertex_arr, }); } Ok(Self { _vertex_buffer: vertex_buffer, index_buffer: None, element_cnt: mesh .vertices() .len() .try_into() .expect("Mesh vertex count does not fit into a 32-bit unsigned int"), vertex_arr, }) } } #[derive(Debug, thiserror::Error)] pub enum Error { #[error("Failed to store vertices in vertex buffer")] StoreVerticesFailed(#[source] opengl_bindings::buffer::Error), #[error("Failed to store indices in index buffer")] StoreIndicesFailed(#[source] opengl_bindings::buffer::Error), }