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), +}  | 
