#include #include "vendor/stb_image.h" #include #include "vk_engine.h" #include "vk_initializers.h" #include "vk_types.h" #include #include #include #include std::optional>> loadGltfMeshes(VulkanEngine* engine, std::filesystem::path filePath) { //> openmesh std::cout << "\nLoading GLTF: " << filePath << std::endl; fastgltf::GltfDataBuffer data; data.loadFromFile(filePath); constexpr auto gltfOptions = fastgltf::Options::LoadGLBBuffers | fastgltf::Options::LoadExternalBuffers; fastgltf::Asset gltf; fastgltf::Parser parser {}; auto load = parser.loadBinaryGLTF(&data, filePath.parent_path(), gltfOptions); if (load) { gltf = std::move(load.get()); } else { std::print("Failed to load glTF: {} \n", fastgltf::to_underlying(load.error())); return {}; } //< openmesh //> loadmesh std::vector> meshes; // use the same vectors for all meshes so that the memory doesnt reallocate as // often std::vector indices; std::vector vertices; for (fastgltf::Mesh& mesh : gltf.meshes) { MeshAsset newmesh; newmesh.name = mesh.name; // clear the mesh arrays each mesh, we dont want to merge them by error indices.clear(); vertices.clear(); for (auto&& p : mesh.primitives) { GeoSurface newSurface; newSurface.startIndex = (uint32_t)indices.size(); newSurface.count = (uint32_t)gltf.accessors[p.indicesAccessor.value()].count; size_t initial_vtx = vertices.size(); // load indexes { fastgltf::Accessor& indexaccessor = gltf.accessors[p.indicesAccessor.value()]; 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("POSITION")->second]; vertices.resize(vertices.size() + posAccessor.count); fastgltf::iterateAccessorWithIndex(gltf, posAccessor, [&](glm::vec3 v, size_t index) { Vertex newvtx; newvtx.position = v; newvtx.normal = { 1, 0, 0 }; newvtx.color = glm::vec4 { 1.f }; newvtx.uv_x = 0; newvtx.uv_y = 0; vertices[initial_vtx + index] = newvtx; }); } // load vertex normals auto normals = p.findAttribute("NORMAL"); if (normals != p.attributes.end()) { fastgltf::iterateAccessorWithIndex(gltf, gltf.accessors[(*normals).second], [&](glm::vec3 v, size_t index) { vertices[initial_vtx + index].normal = v; }); } // load UVs auto uv = p.findAttribute("TEXCOORD_0"); if (uv != p.attributes.end()) { fastgltf::iterateAccessorWithIndex(gltf, gltf.accessors[(*uv).second], [&](glm::vec2 v, size_t index) { vertices[initial_vtx + index].uv_x = v.x; vertices[initial_vtx + index].uv_y = v.y; }); } // load vertex colors auto colors = p.findAttribute("COLOR_0"); if (colors != p.attributes.end()) { fastgltf::iterateAccessorWithIndex(gltf, gltf.accessors[(*colors).second], [&](glm::vec4 v, size_t index) { vertices[initial_vtx + index].color = v; }); } newmesh.surfaces.push_back(newSurface); } // display the vertex normals constexpr bool OverrideColors = true; if (OverrideColors) { for (Vertex& vtx : vertices) { vtx.color = glm::vec4(vtx.normal, 1.f); } } newmesh.meshBuffers = engine->uploadMesh(indices, vertices); meshes.emplace_back(std::make_shared(std::move(newmesh))); } return meshes; //< loadmesh }