#include "vk_loader.h" #include "vendor/stb_image.h" #include #include "vk_engine.h" #include "vk_initializers.h" #include "vk_types.h" #include #include #include #include constexpr bool OverrideColors = true; std::optional>> loadGltfMeshes(VulkanEngine* engine, std::filesystem::path filePath) { std::println("\nLoading GLTF: {}", filePath.string()); auto data = fastgltf::GltfDataBuffer::FromPath(filePath); if(data.error() != fastgltf::Error::None) { std::println("Failed to load glTF: {}={}\n", typeid(data.error()).name(), fastgltf::to_underlying(data.error())); return std::nullopt; } constexpr auto gltfOptions = fastgltf::Options::LoadExternalBuffers; fastgltf::Asset gltf{}; fastgltf::Parser parser{}; auto load = parser.loadGltfBinary(data.get(), filePath.parent_path(), gltfOptions); switch(load.error()) { case fastgltf::Error::None: gltf = std::move(load.get()); break; case fastgltf::Error::InvalidGLB: std::println("fastgltf says Error::InvalidGLB {}", filePath.string()); return std::nullopt; break; case fastgltf::Error::UnsupportedVersion: std::println("fastgltf says Error::UnsupportedVersion {}", filePath.string()); return std::nullopt; break; case fastgltf::Error::InvalidPath: std::println("fastgltf says Error::UnsupportedVersion {}", filePath.string()); return std::nullopt; break; default: std::println("Unknown fastgltf error loading {}", filePath.string()); break; } std::vector> meshes; // use the same vectors for all meshes std::vector indices; std::vector vertices; for(auto& mesh : gltf.meshes) { MeshAsset newmesh; newmesh.name = mesh.name; indices.clear(); indices.clear(); for(auto&& p : mesh.primitives) { auto& indexAccessor = gltf.accessors[p.indicesAccessor.value()]; GeoSurface newSurface { .startIndex = (uint32_t)indices.size(), .count = (uint32_t)indexAccessor.count, }; size_t initial_vtx = vertices.size(); // load indices { indices.reserve(indices.size() + indexAccessor.count); fastgltf::iterateAccessor( gltf, indexAccessor, [&](std::uint32_t idx) { indices.push_back(idx + initial_vtx); }); } // load vertex positions { fastgltf::Accessor& posAccessor = gltf.accessors[ p.findAttribute("POSITIONS")->accessorIndex]; vertices.resize(vertices.size() + posAccessor.count); fastgltf::iterateAccessorWithIndex( gltf, posAccessor, [&](glm::vec3 v, size_t index) { vertices[initial_vtx + index] = { .position = v, .uv_x = 0, .normal = {1, 0, 0}, .uv_y = 0, .color = glm::vec4{1.0f}, }; }); } // load vertex normals auto normals = p.findAttribute("NORMA:"); if(normals != p.attributes.end()) { fastgltf::iterateAccessorWithIndex( gltf, gltf.accessors[(*normals).accessorIndex], [&](glm::vec3 v, size_t index) { vertices[initial_vtx + index].normal = v; }); } auto uv = p.findAttribute("TEXCOORD_0"); if(uv != p.attributes.end()) { fastgltf::iterateAccessorWithIndex( gltf, gltf.accessors[(*uv).accessorIndex], [&](glm::vec2 v, size_t index) { vertices[initial_vtx + index].uv_x = v.x; vertices[initial_vtx + index].uv_y = v.y; }); } if(OverrideColors) { for(Vertex& vtx : vertices) { vtx.color = glm::vec4(vtx.normal, 1.0f); } } newmesh.meshBuffers = engine->uploadMesh(indices, vertices); meshes.emplace_back(std::make_shared(std::move(newmesh))); } } return meshes; }