psemek/libs/gfx/source/gltf_mesh.cpp

67 lines
2 KiB
C++

#include <psemek/gfx/gltf_mesh.hpp>
#include <stdexcept>
namespace psemek::gfx
{
void gltf_mesh::mesh::primitive::draw() const
{
vao.bind();
gl::DrawElements(gl::TRIANGLES, index_count, index_type, reinterpret_cast<void const *>(index_offset));
}
gltf_mesh::gltf_mesh(gltf_asset const & asset, std::vector<util::span<char const>> const & buffers)
{
if (buffers.size() != asset.buffers.size())
throw std::runtime_error("wrong number of glTF buffers");
for (auto buffer : buffers)
this->buffers.emplace_back().load(buffer.data(), buffer.size(), gl::STATIC_DRAW);
for (auto const & node : asset.nodes)
{
auto & target_mesh = meshes[node.name];
auto const & mesh = asset.meshes[node.mesh];
for (auto const & primitive : mesh.primitives)
{
auto & target_primitive = target_mesh.primitives.emplace_back();
target_primitive.material = primitive.material;
target_primitive.vao.bind();
{
auto const & indices_accessor = asset.accessors[primitive.indices];
auto const & indices_view = asset.buffer_views[indices_accessor.buffer_view];
gl::BindBuffer(gl::ELEMENT_ARRAY_BUFFER, this->buffers[indices_view.buffer].id());
target_primitive.index_offset = indices_view.offset;
target_primitive.index_type = indices_accessor.component_type;
target_primitive.index_count = indices_accessor.count;
}
std::pair<GLuint, std::optional<std::size_t>> attributes[3] =
{
{0, primitive.position},
{1, primitive.normal},
{2, primitive.texcoord},
};
for (auto const & attribute : attributes)
{
if (!attribute.second) continue;
auto const & accessor = asset.accessors[*attribute.second];
auto const & view = asset.buffer_views[accessor.buffer_view];
gl::BindBuffer(gl::ARRAY_BUFFER, this->buffers[view.buffer].id());
gl::EnableVertexAttribArray(attribute.first);
gl::VertexAttribPointer(attribute.first, accessor.type, accessor.component_type, accessor.normalized, 0, reinterpret_cast<void const *>(view.offset));
}
}
}
}
}