120 lines
2.8 KiB
C++
120 lines
2.8 KiB
C++
#include "opengl/data/mesh_data.hpp"
|
|
|
|
#include "opengl/type_utils.hpp"
|
|
#include "opengl/error.hpp"
|
|
|
|
#include "GL/glew.h"
|
|
#include <algorithm>
|
|
#include "util/logger.hpp" // TODO remove
|
|
|
|
|
|
std::error_code zgl::mesh_data::build_from(
|
|
const std::span<const ztu::u8> vertex_buffer,
|
|
const std::span<const GLenum> component_types,
|
|
const std::span<const GLint> component_lengths,
|
|
const GLsizei stride,
|
|
const std::span<const ztu::u32> index_buffer,
|
|
const ztu::u32 material_id,
|
|
const mesh_vertex_components::flags components,
|
|
mesh_data& data
|
|
) {
|
|
if (not std::ranges::all_of(component_types, type_utils::is_valid_type))
|
|
{
|
|
ztu::logger::debug("not all types valid.");
|
|
return std::make_error_code(std::errc::invalid_argument);
|
|
}
|
|
|
|
const auto vertices_byte_count = vertex_buffer.size() * sizeof(std::uint8_t);
|
|
if (vertices_byte_count > std::numeric_limits<GLsizeiptr>::max())
|
|
{
|
|
return std::make_error_code(std::errc::value_too_large);
|
|
}
|
|
|
|
const auto indices_byte_count = index_buffer.size() * sizeof(ztu::u32);
|
|
if (indices_byte_count > std::numeric_limits<GLsizeiptr>::max())
|
|
{
|
|
return std::make_error_code(std::errc::value_too_large);
|
|
}
|
|
|
|
auto error = std::error_code{};
|
|
|
|
auto check_error = [&error, ec = static_cast<GLenum>(GL_NO_ERROR)]() mutable -> const std::error_code&
|
|
{
|
|
ec = glGetError();
|
|
if (ec != GL_NO_ERROR)
|
|
{
|
|
error = make_error_code(ec);
|
|
}
|
|
return error;
|
|
};
|
|
|
|
GLuint vao_id;
|
|
glGenVertexArrays(1, &vao_id);
|
|
glBindVertexArray(vao_id);
|
|
if (check_error()) return error;
|
|
|
|
ztu::logger::debug("Created mesh vao: % valid: %", vao_id, (bool)glIsVertexArray(vao_id));
|
|
|
|
GLuint vertex_buffer_id;
|
|
glGenBuffers(1, &vertex_buffer_id);
|
|
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id);
|
|
glBufferData(
|
|
GL_ARRAY_BUFFER,
|
|
static_cast<GLsizeiptr>(vertices_byte_count),
|
|
vertex_buffer.data(),
|
|
GL_STATIC_DRAW
|
|
);
|
|
if (check_error()) return error;
|
|
|
|
GLuint index_buffer_id;
|
|
glGenBuffers(1, &index_buffer_id);
|
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, index_buffer_id);
|
|
glBufferData(
|
|
GL_ELEMENT_ARRAY_BUFFER,
|
|
static_cast<GLsizeiptr>(indices_byte_count),
|
|
index_buffer.data(),
|
|
GL_STATIC_DRAW
|
|
);
|
|
if (check_error()) return error;
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, vertex_buffer_id);
|
|
if (check_error()) return error;
|
|
|
|
auto offset = GLsizei{ 0 };
|
|
|
|
for (std::size_t i{}; i != component_types.size(); ++i)
|
|
{
|
|
const auto type = component_types[i];
|
|
const auto length = component_lengths[i];
|
|
const auto byte_count = type_utils::size_of(type);
|
|
|
|
glVertexAttribPointer(
|
|
i,
|
|
length,
|
|
type,
|
|
GL_FALSE,
|
|
stride,
|
|
reinterpret_cast<GLvoid*>(offset)
|
|
);
|
|
|
|
glEnableVertexAttribArray(i);
|
|
if (check_error()) return error;
|
|
|
|
offset += length * byte_count;
|
|
}
|
|
|
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
|
glBindVertexArray(0);
|
|
|
|
data = mesh_data(
|
|
vertex_buffer_id,
|
|
index_buffer_id,
|
|
vao_id,
|
|
material_id,
|
|
components,
|
|
index_buffer.size()
|
|
);
|
|
|
|
return {};
|
|
}
|