aboutsummaryrefslogtreecommitdiffstats
path: root/src/gltf.cpp
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2022-08-08 23:38:19 +0200
committerladevieq <ladevie.quentin@gmail.com>2022-08-08 23:38:19 +0200
commitd78200b71b259b87f401b24906385af4e2553fbe (patch)
treea3f50e975303896063f49c069752bd1be774e766 /src/gltf.cpp
parent45247b737b1527fbeffac2c68a41e71c565d86a8 (diff)
Refactored gltf imported and mesh management
Diffstat (limited to 'src/gltf.cpp')
-rw-r--r--src/gltf.cpp214
1 files changed, 80 insertions, 134 deletions
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 <fstream>
-#include <cstring>
#include <filesystem>
#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<std::vector<uint8_t>>(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<std::string>();
- 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<std::string>();
+ 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<uint32_t>(), root_node.children[child_index], meshes);
+ load_node(root_children[child_index].get<uint32_t>(), root_node.children[child_index]);
}
f.close();
-
- return root_node;
}
-void gltf::load_node(json &gltf_json, uint32_t index, node &parent, std::vector<mesh> &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<uint32_t>(), parent.children[child_index], meshes);
+ load_node(children[child_index].get<uint32_t>(), parent.children[child_index]);
}
}
- if (gltf_node.contains("mesh")) { parent.mesh = std::make_optional(meshes[gltf_node["mesh"].get<uint32_t>()]); }
+ if (gltf_node.contains("mesh")) {
+ parent.mesh = &meshes[gltf_node["mesh"].get<uint32_t>()];
+ }
}
-std::vector<mesh> gltf::load_meshes(
- json &gltf_json, std::vector<std::vector<uint8_t>> &buffers_content, std::vector<material> &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<mesh> 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];
+ auto& mesh = meshes[mesh_index];
+ const auto &primitives = gltf_meshes[mesh_index]["primitives"];
- 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));
+ 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<uint32_t>()]["count"].get<uint32_t>();
+ submesh.vertex_count = gltf_json["accessors"][primitive["attributes"]["POSITION"].get<uint32_t>()]["count"].get<uint32_t>();
+ // submesh.mat = materials[gltf_primitive["material"].get<uint32_t>()];
+
+ return submesh;
}
-std::vector<texture> 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<uint32_t>();
+ const auto &view = gltf_json["bufferViews"][view_index];
+ auto offset = view["byteOffset"].get<off_t>();
+ auto &buffer = buffers[view["buffer"].get<uint32_t>()];
+
+ return {
+ &buffer[offset],
+ view["byteLength"].get<size_t>()
+ };
+}
+
+void gltf::load_textures(const std::filesystem::path &path) {
+ const auto &gltf_images = gltf_json["images"];
auto images_count = gltf_images.size();
std::vector<Texture *> 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<std::string>()).string();
unsigned char *data = stbi_load(filepath.c_str(), &x, &y, &n, 4);
- auto *img = renderer.create_2d_texture(static_cast<uint32_t>(x), static_cast<uint32_t>(y), VK_FORMAT_R8G8B8A8_UNORM);
+ auto *img = vkrenderer::create_2d_texture(static_cast<uint32_t>(x), static_cast<uint32_t>(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<Sampler *> 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<texture> 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<texture> gltf::load_textures(json &gltf_json, std::filesystem::path
auto image_index = gltf_texture["source"].get<uint32_t>();
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<uint32_t>();
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<material> gltf::load_materials(json &gltf_json, std::vector<texture> &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<material> 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<float>();
material.base_color.v[1] = base_color[1].get<float>();
material.base_color.v[2] = base_color[2].get<float>();
@@ -181,82 +205,4 @@ std::vector<material> gltf::load_materials(json &gltf_json, std::vector<texture>
}
}
}
-
- return materials;
-}
-
-mesh_part gltf::load_primitive(json &gltf_json, json &primitive, std::vector<std::vector<uint8_t>> &buffers_content,
- std::vector<material> &materials) {
- auto part = mesh_part();
- auto &accessors = gltf_json["accessors"];
-
- {
- auto indices_accessor_index = primitive["indices"].get<uint32_t>();
- auto indices_view_index = accessors[indices_accessor_index]["bufferView"].get<uint32_t>();
- auto &indices_view = gltf_json["bufferViews"][indices_view_index];
-
- auto indices_buffer_index = indices_view["buffer"].get<uint32_t>();
- auto indices_offset = indices_view["byteOffset"].get<size_t>();
- auto indices_length = indices_view["byteLength"].get<size_t>();
-
- auto &indices_buffer = buffers_content[indices_buffer_index];
- auto *indices_start = reinterpret_cast<uint16_t *>(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<uint32_t>();
- auto positions_view_index = accessors[positions_accessor_index]["bufferView"].get<uint32_t>();
- auto &positions_view = gltf_json["bufferViews"][positions_view_index];
-
- auto positions_buffer_index = positions_view["buffer"].get<uint32_t>();
- auto positions_offset = positions_view["byteOffset"].get<size_t>();
- auto positions_length = positions_view["byteLength"].get<size_t>();
-
- auto &positions_buffer = buffers_content[positions_buffer_index];
- auto *positions_start = reinterpret_cast<float *>(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<uint32_t>();
- auto normals_view_index = accessors[normals_accessor_index]["bufferView"].get<uint32_t>();
- auto &normals_view = gltf_json["bufferViews"][normals_view_index];
-
- auto normals_buffer_index = normals_view["buffer"].get<uint32_t>();
- auto normals_offset = normals_view["byteOffset"].get<size_t>();
- auto normals_length = normals_view["byteLength"].get<size_t>();
-
- auto &normals_buffer = buffers_content[normals_buffer_index];
- auto *normals_start = reinterpret_cast<float *>(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<uint32_t>();
- auto uvs_view_index = accessors[uvs_accessor_index]["bufferView"].get<uint32_t>();
- auto &uvs_view = gltf_json["bufferViews"][uvs_view_index];
-
- auto uvs_buffer_index = uvs_view["buffer"].get<uint32_t>();
- auto uvs_offset = uvs_view["byteOffset"].get<size_t>();
- auto uvs_length = uvs_view["byteLength"].get<size_t>();
-
- auto &uvs_buffer = buffers_content[uvs_buffer_index];
- auto *uvs_start = reinterpret_cast<float *>(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<uint32_t>()];
- part.vertices_count = part.positions.size() / 3;
- part.triangles_count = part.indices.size() / 3;
-
- return part;
}