diff options
Diffstat (limited to 'engine/src/renderer/opengl/graphics_mesh.rs')
-rw-r--r-- | engine/src/renderer/opengl/graphics_mesh.rs | 120 |
1 files changed, 120 insertions, 0 deletions
diff --git a/engine/src/renderer/opengl/graphics_mesh.rs b/engine/src/renderer/opengl/graphics_mesh.rs new file mode 100644 index 0000000..9b929c0 --- /dev/null +++ b/engine/src/renderer/opengl/graphics_mesh.rs @@ -0,0 +1,120 @@ +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<RendererVertex>, + pub index_buffer: Option<GlBuffer<u32>>, + pub element_cnt: u32, + pub vertex_arr: GlVertexArray, +} + +impl GraphicsMesh +{ + #[tracing::instrument(skip_all)] + pub fn new( + current_context: &GlCurrentContextWithFns<'_>, + mesh: &Mesh, + ) -> Result<Self, Error> + { + 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), +} |