#include #include namespace psemek::gfx { void gltf_mesh::mesh::primitive::draw() { vao.bind(); gl::DrawElements(gl::TRIANGLES, index_count, index_type, reinterpret_cast(index_offset)); } gltf_mesh::gltf_mesh(gltf_asset const & asset, std::vector> 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> 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(view.offset)); } } } } }