#include "Mesh.hpp" namespace MC::GFX { USize Mesh::size() const { return m_indices.size(); } void Mesh::bind() { if (!m_vao.has_value()) upload(); glBindVertexArray(m_vao.value()); for (Int i = 0; i < m_attributes.size(); i++) { glEnableVertexAttribArray(i); } } void Mesh::unbind() const { glBindVertexArray(0); for (Int i = 0; i < m_attributes.size(); i++) { glDisableVertexAttribArray(i); } } void Mesh::upload() { auto vao = create_vao(); if (!m_indices.empty()) { store_indices(m_indices.data(), m_indices.size()); } Int attribute_index = 0; for (const auto& attribute : m_attributes) { store_in_attribute_list( attribute_index++, attribute.attribute_size, attribute.type_size, attribute.data, attribute.data_size ); } unbind_vao(); m_vao = {vao}; } GLuint Mesh::create_vao() { GLuint vao; glGenVertexArrays(1, &vao); glBindVertexArray(vao); return vao; } void Mesh::unbind_vao() { glBindVertexArray(0); } void Mesh::store_indices(const U32* indices, USize indices_size) { GLuint ebo; glGenBuffers(1, &ebo); glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo); glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices_size * sizeof(U32), indices, GL_STATIC_DRAW); } void Mesh::store_in_attribute_list(U32 attribute, Int attribute_size, Int type_size, const void* data, long data_size) { assert(type_size == sizeof(F32)); GLuint vbo; glGenBuffers(1, &vbo); glBindBuffer(GL_ARRAY_BUFFER, vbo); glBufferData(GL_ARRAY_BUFFER, data_size * attribute_size * type_size, data, GL_STATIC_DRAW); glVertexAttribPointer(attribute, attribute_size, GL_FLOAT, GL_FALSE, attribute_size * type_size, nullptr); glBindBuffer(GL_ARRAY_BUFFER, 0); } }