From 9ed211d1ca084b25d1780da3bde19e9da64d4a4a Mon Sep 17 00:00:00 2001 From: Chuyan Zhang Date: Sat, 5 Oct 2024 23:40:53 -0700 Subject: glTF loader start working --- src/gltf_loader.cpp | 78 +++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 64 insertions(+), 14 deletions(-) (limited to 'src/gltf_loader.cpp') diff --git a/src/gltf_loader.cpp b/src/gltf_loader.cpp index bf64740..684fa7f 100644 --- a/src/gltf_loader.cpp +++ b/src/gltf_loader.cpp @@ -1,4 +1,5 @@ #include "gltf_loader.h" +#include "render_assets.h" #include "spdlog/spdlog.h" #include @@ -75,15 +76,26 @@ bool load_gltf(const std::string_view path, iris::Scene &scene) { model.scenes.size(), model.lights.size()); + for (const auto &mesh : model.meshes) { - iris::Mesh iris_mesh { - .name = mesh.name, - .vertices = {}, - .normals = {}, - .texcoords = {}, - .indices = {}, - }; + auto mesh_primitive_counter = 0u; + const std::string mesh_name = mesh.name == "" ? "mesh" : mesh.name; + + // TODO: A Mesh in glTF can have multiple primitives, each with its own set of attributes + // But our current abstract doesn't support multiple primitives within a mesh, so we load + // each primitive as a separate mesh instead. This is a temporary solution and should be fixed. for (const auto &primitive : mesh.primitives) { + std::string name = mesh_name + "_" + std::to_string(mesh_primitive_counter++); + spdlog::info("loading mesh primitive: {}", name); + iris::Mesh iris_mesh { + .name = mesh.name, + .vertices = {}, + .normals = {}, + .texcoords = {}, + .indices = {}, + .material_index = primitive.material, + }; + const auto &index_accessor = model.accessors[primitive.indices]; const auto &index_buffer_view = model.bufferViews[index_accessor.bufferView]; const auto &index_buffer = model.buffers[index_buffer_view.buffer]; @@ -144,15 +156,14 @@ bool load_gltf(const std::string_view path, iris::Scene &scene) { return *typed_data; }; - // TODO: support other types. Currently only float3 is supported - if (accessor.type != TINYGLTF_TYPE_VEC3 || accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) { - spdlog::error("Unsupported POSITION type: {}, {}", accessor.type, accessor.componentType); - return false; - } - // spdlog::info("attribute: {}, count: {}", attrib_name, accessor.count); if (attrib_name == "POSITION") { spdlog::info("loading POSITION, count {}", accessor.count); + // TODO: support other types. Currently only float3 is supported + if (accessor.type != TINYGLTF_TYPE_VEC3 || accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) { + spdlog::error("Field {} type unsupported: {}, {}", attrib_name, accessor.type, accessor.componentType); + continue; + } iris_mesh.p_min = glm::vec3(accessor.minValues[0], accessor.minValues[1], accessor.minValues[2]); iris_mesh.p_max = glm::vec3(accessor.maxValues[0], accessor.maxValues[1], accessor.maxValues[2]); for (size_t i = 0; i < accessor.count; i++) { @@ -160,26 +171,65 @@ bool load_gltf(const std::string_view path, iris::Scene &scene) { } } else if (attrib_name == "NORMAL") { spdlog::info("loading NORMAL, count {}", accessor.count); + // TODO: support other types. Currently only float3 is supported + if (accessor.type != TINYGLTF_TYPE_VEC3 || accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) { + spdlog::error("Field {} type unsupported: {}, {}", attrib_name, accessor.type, accessor.componentType); + continue; + } for (size_t i = 0; i < accessor.count; i++) { iris_mesh.normals.push_back(extract_data.operator()()); } } else if (attrib_name == "TEXCOORD_0") { spdlog::info("loading TEXCOORD_0, count {}", accessor.count); + // TODO: support other types. Currently only float2 is supported + if (accessor.type != TINYGLTF_TYPE_VEC2 || accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) { + spdlog::error("Field {} type unsupported: {}, {}", attrib_name, accessor.type, accessor.componentType); + continue; + } for (size_t i = 0; i < accessor.count; i++) { iris_mesh.texcoords.push_back(extract_data.operator()()); } + } else if (attrib_name == "TANGENT") { + spdlog::info("loading TANGENT, count {}", accessor.count); + // TODO: support other types. Currently only float4 is supported + if (accessor.type != TINYGLTF_TYPE_VEC4 || accessor.componentType != TINYGLTF_COMPONENT_TYPE_FLOAT) { + spdlog::error("Field {} type unsupported: {}, {}", attrib_name, accessor.type, accessor.componentType); + continue; + } + for (size_t i = 0; i < accessor.count; i++) { + iris_mesh.tangents.push_back(extract_data.operator()()); + } } else { spdlog::warn("Unsupported attribute: {}", attrib_name); } } + break; } // TODO add support for other modes default: spdlog::error("Unsupported primitive mode: {}", primitive.mode); return false; } + scene.meshes.push_back(iris_mesh); } - scene.meshes.push_back(iris_mesh); + } + + for (const tinygltf::Material &material : model.materials) { + const std::string material_name = material.name == "" ? "material" : material.name; + const auto &pbr = material.pbrMetallicRoughness; + iris::Material iris_material { + .name = material_name, + .base_color = glm::vec4( + pbr.baseColorFactor[0], + pbr.baseColorFactor[1], + pbr.baseColorFactor[2], + pbr.baseColorFactor[3]), + .metallic = float(pbr.metallicFactor), + .roughness = float(pbr.roughnessFactor), + }; + + // TODO: load texture information, skip for now + spdlog::info("Material: {}", material_name); } // TODO load materials and textures -- cgit v1.2.3-70-g09d2