From d78200b71b259b87f401b24906385af4e2553fbe Mon Sep 17 00:00:00 2001 From: ladevieq Date: Mon, 8 Aug 2022 23:38:19 +0200 Subject: Refactored gltf imported and mesh management --- src/gltf.cpp | 216 ++++++++++++++++++++++------------------------------------- 1 file changed, 81 insertions(+), 135 deletions(-) (limited to 'src/gltf.cpp') diff --git a/src/gltf.cpp b/src/gltf.cpp index 7c1e26c..8f266f2 100644 --- a/src/gltf.cpp +++ b/src/gltf.cpp @@ -1,7 +1,6 @@ #include "gltf.hpp" #include -#include #include #define STB_IMAGE_IMPLEMENTATION @@ -10,110 +9,137 @@ #include "vk-renderer.hpp" #include "utils.hpp" -node gltf::load(std::filesystem::path &path, std::string &filename, vkrenderer &renderer) { - std::fstream f { path / filename }; - json gltf_json; +gltf::gltf(const std::filesystem::path &filepath) { + auto parent_path = filepath.parent_path(); + std::fstream f { filepath }; f >> gltf_json; auto& scene = gltf_json["scenes"][0]; - auto &buffers = gltf_json["buffers"]; - auto buffers_content = std::vector>(buffers.size()); - for (size_t buffer_index{0}; buffer_index < buffers.size(); buffer_index++) { - auto& buffer = buffers[buffer_index]; - auto buffer_path = path / buffer["uri"].get(); - buffers_content[buffer_index] = read_file(buffer_path.string().c_str()); + auto &gltf_buffers = gltf_json["buffers"]; + buffers.reserve(gltf_buffers.size()); + for (auto& gltf_buffer : gltf_buffers) { + auto buffer_path = parent_path / gltf_buffer["uri"].get(); + buffers.emplace_back(read_file(buffer_path.string().c_str())); } - auto textures = load_textures(gltf_json, path, renderer); - auto materials = load_materials(gltf_json, textures); + load_textures(parent_path); + load_materials(); - auto meshes = load_meshes(gltf_json, buffers_content, materials); + load_meshes(); - node root_node; auto& root_children = scene["nodes"]; uint32_t root_children_count = scene["nodes"].size(); root_node.children.resize(root_children_count); for (size_t child_index = 0; child_index < root_children_count; child_index++) { - load_node(gltf_json, root_children[child_index].get(), root_node.children[child_index], meshes); + load_node(root_children[child_index].get(), root_node.children[child_index]); } f.close(); - - return root_node; } -void gltf::load_node(json &gltf_json, uint32_t index, node &parent, std::vector &meshes) { - auto &gltf_node = gltf_json["nodes"][index]; +void gltf::load_node(uint32_t index, node &parent) { + const auto &gltf_node = gltf_json["nodes"][index]; if (gltf_node.contains("children")) { - auto &children = gltf_node["children"]; + const auto &children = gltf_node["children"]; uint32_t children_count = gltf_node["children"]; parent.children.resize(children_count); for (size_t child_index = 0; child_index < children_count; child_index++) { - load_node(gltf_json, children[child_index].get(), parent.children[child_index], meshes); + load_node(children[child_index].get(), parent.children[child_index]); } } - if (gltf_node.contains("mesh")) { parent.mesh = std::make_optional(meshes[gltf_node["mesh"].get()]); } + if (gltf_node.contains("mesh")) { + parent.mesh = &meshes[gltf_node["mesh"].get()]; + } } -std::vector gltf::load_meshes( - json &gltf_json, std::vector> &buffers_content, std::vector &materials) { - auto &gltf_meshes = gltf_json["meshes"]; +void gltf::load_meshes() { + const auto &gltf_meshes = gltf_json["meshes"]; auto meshes_count = gltf_meshes.size(); - std::vector meshes{meshes_count}; + meshes.resize(meshes_count); for (size_t mesh_index = 0; mesh_index < meshes_count; mesh_index++) { - auto &gltf_mesh = gltf_meshes[mesh_index]; - auto &primitives = gltf_mesh["primitives"]; - auto &mesh = meshes[mesh_index]; - - for (auto &primitive : primitives) { - auto part = load_primitive(gltf_json, primitive, buffers_content, materials); - mesh.vertices_count += part.vertices_count; - mesh.triangles_count += part.triangles_count; - mesh.parts.emplace_back(std::move(part)); + auto& mesh = meshes[mesh_index]; + const auto &primitives = gltf_meshes[mesh_index]["primitives"]; + + for (const auto &primitive : primitives) { + mesh.add_submesh(load_primitive(primitive)); } + + Mesh::register_mesh(mesh); + } +} + +Mesh::submesh gltf::load_primitive(const json &primitive) { + Mesh::submesh submesh; + + submesh.indices = load_attribute(primitive["indices"]); + submesh.attributes[ATTRIBUTE_TYPE::POSITION] = load_attribute(primitive["attributes"]["POSITION"]); + + if (primitive["attributes"].contains("NORMAL")) { + submesh.attributes[ATTRIBUTE_TYPE::POSITION] = load_attribute(primitive["attributes"]["NORMAL"]); + } + + if (primitive["attributes"].contains("TEXCOORD_0")) { + submesh.attributes[ATTRIBUTE_TYPE::POSITION] = load_attribute(primitive["attributes"]["TEXCOORD_0"]); } - return meshes; + submesh.index_count = gltf_json["accessors"][primitive["indices"].get()]["count"].get(); + submesh.vertex_count = gltf_json["accessors"][primitive["attributes"]["POSITION"].get()]["count"].get(); + // submesh.mat = materials[gltf_primitive["material"].get()]; + + return submesh; } -std::vector gltf::load_textures(json &gltf_json, std::filesystem::path &path, vkrenderer &renderer) { - auto &gltf_images = gltf_json["images"]; +Mesh::attribute gltf::load_attribute(uint32_t accessor_index) { + auto view_index = gltf_json["accessors"][accessor_index]["bufferView"].get(); + const auto &view = gltf_json["bufferViews"][view_index]; + auto offset = view["byteOffset"].get(); + auto &buffer = buffers[view["buffer"].get()]; + + return { + &buffer[offset], + view["byteLength"].get() + }; +} + +void gltf::load_textures(const std::filesystem::path &path) { + const auto &gltf_images = gltf_json["images"]; auto images_count = gltf_images.size(); std::vector images{images_count}; for (size_t image_index = 0; image_index < images_count; image_index++) { - auto &gltf_image = gltf_images[image_index]; - int x, y, n; + const auto &gltf_image = gltf_images[image_index]; + int x; + int y; + int n; auto filepath = (path / gltf_image["uri"].get()).string(); unsigned char *data = stbi_load(filepath.c_str(), &x, &y, &n, 4); - auto *img = renderer.create_2d_texture(static_cast(x), static_cast(y), VK_FORMAT_R8G8B8A8_UNORM); + auto *img = vkrenderer::create_2d_texture(static_cast(x), static_cast(y), VK_FORMAT_R8G8B8A8_UNORM); - renderer.update_image(img, data); + // renderer.update_image(img, data); stbi_image_free(data); images[image_index] = img; } - auto &gltf_samplers = gltf_json["samplers"]; + const auto &gltf_samplers = gltf_json["samplers"]; auto samplers_count = gltf_samplers.size(); std::vector samplers{samplers_count}; for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) { - samplers[sampler_index] = renderer.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT); + samplers[sampler_index] = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT); } - auto& api = renderer.api; - auto &gltf_textures = gltf_json["textures"]; + const auto &gltf_textures = gltf_json["textures"]; auto textures_count = gltf_textures.size(); - std::vector textures{textures_count}; + textures.resize(textures_count); for (size_t texture_index = 0; texture_index < textures_count; texture_index++) { auto gltf_texture = gltf_textures[texture_index]; @@ -121,35 +147,33 @@ std::vector gltf::load_textures(json &gltf_json, std::filesystem::path auto image_index = gltf_texture["source"].get(); auto &image = images[image_index]; - uint32_t image_id = api.get_image(image->device_image).bindless_sampled_index; + uint32_t image_id = vkrenderer::api.get_image(image->device_image).bindless_sampled_index; uint32_t sampler_id = 0; if (gltf_texture.contains("sampler")) { auto sampler_index = gltf_texture["sampler"].get(); auto &sampler = samplers[sampler_index]; - sampler_id = api.get_sampler(sampler->device_sampler).bindless_index; + sampler_id = vkrenderer::api.get_sampler(sampler->device_sampler).bindless_index; } textures[texture_index] = texture{.image_id = image_id, .sampler_id = sampler_id}; } - - return textures; } -std::vector gltf::load_materials(json &gltf_json, std::vector &textures) { - auto &gltf_materials = gltf_json["materials"]; +void gltf::load_materials() { + const auto &gltf_materials = gltf_json["materials"]; auto materials_count = gltf_materials.size(); - std::vector materials{materials_count}; + materials.resize(materials_count); for (size_t material_index = 0; material_index < materials_count; material_index++) { - auto &gltf_material = gltf_materials[material_index]; + const auto &gltf_material = gltf_materials[material_index]; auto &material = materials[material_index]; if (gltf_material.contains("pbrMetallicRoughness")) { - auto &pbr_params = gltf_material["pbrMetallicRoughness"]; + const auto &pbr_params = gltf_material["pbrMetallicRoughness"]; if (pbr_params.contains("baseColorFactor")) { - auto &base_color = pbr_params["baseColorFactor"]; + const auto &base_color = pbr_params["baseColorFactor"]; material.base_color.v[0] = base_color[0].get(); material.base_color.v[1] = base_color[1].get(); material.base_color.v[2] = base_color[2].get(); @@ -181,82 +205,4 @@ std::vector gltf::load_materials(json &gltf_json, std::vector } } } - - return materials; -} - -mesh_part gltf::load_primitive(json &gltf_json, json &primitive, std::vector> &buffers_content, - std::vector &materials) { - auto part = mesh_part(); - auto &accessors = gltf_json["accessors"]; - - { - auto indices_accessor_index = primitive["indices"].get(); - auto indices_view_index = accessors[indices_accessor_index]["bufferView"].get(); - auto &indices_view = gltf_json["bufferViews"][indices_view_index]; - - auto indices_buffer_index = indices_view["buffer"].get(); - auto indices_offset = indices_view["byteOffset"].get(); - auto indices_length = indices_view["byteLength"].get(); - - auto &indices_buffer = buffers_content[indices_buffer_index]; - auto *indices_start = reinterpret_cast(indices_buffer.data() + indices_offset); - - part.indices.resize(indices_length / sizeof(uint16_t)); - std::memcpy(part.indices.data(), indices_start, indices_length); - } - - { - auto positions_accessor_index = primitive["attributes"]["POSITION"].get(); - auto positions_view_index = accessors[positions_accessor_index]["bufferView"].get(); - auto &positions_view = gltf_json["bufferViews"][positions_view_index]; - - auto positions_buffer_index = positions_view["buffer"].get(); - auto positions_offset = positions_view["byteOffset"].get(); - auto positions_length = positions_view["byteLength"].get(); - - auto &positions_buffer = buffers_content[positions_buffer_index]; - auto *positions_start = reinterpret_cast(positions_buffer.data() + positions_offset); - - part.positions.resize(positions_length / sizeof(float)); - std::memcpy(part.positions.data(), positions_start, positions_length); - } - - { - auto normals_accessor_index = primitive["attributes"]["NORMAL"].get(); - auto normals_view_index = accessors[normals_accessor_index]["bufferView"].get(); - auto &normals_view = gltf_json["bufferViews"][normals_view_index]; - - auto normals_buffer_index = normals_view["buffer"].get(); - auto normals_offset = normals_view["byteOffset"].get(); - auto normals_length = normals_view["byteLength"].get(); - - auto &normals_buffer = buffers_content[normals_buffer_index]; - auto *normals_start = reinterpret_cast(normals_buffer.data() + normals_offset); - - part.normals.resize(normals_length / sizeof(float)); - std::memcpy(part.normals.data(), normals_start, normals_length); - } - - { - auto uvs_accessor_index = primitive["attributes"]["TEXCOORD_0"].get(); - auto uvs_view_index = accessors[uvs_accessor_index]["bufferView"].get(); - auto &uvs_view = gltf_json["bufferViews"][uvs_view_index]; - - auto uvs_buffer_index = uvs_view["buffer"].get(); - auto uvs_offset = uvs_view["byteOffset"].get(); - auto uvs_length = uvs_view["byteLength"].get(); - - auto &uvs_buffer = buffers_content[uvs_buffer_index]; - auto *uvs_start = reinterpret_cast(uvs_buffer.data() + uvs_offset); - - part.uvs.resize(uvs_length / sizeof(float)); - std::memcpy(part.uvs.data(), uvs_start, uvs_length); - } - - part.mat = materials[primitive["material"].get()]; - part.vertices_count = part.positions.size() / 3; - part.triangles_count = part.indices.size() / 3; - - return part; } -- cgit v1.3