aboutsummaryrefslogtreecommitdiffstats
path: root/src/gltf.cpp
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2026-05-05 00:50:13 +0200
committerladevieq <ladevie.quentin@gmail.com>2026-05-05 00:50:49 +0200
commit37fdcb8a0f435c42f737252450626f2bd38bbd0f (patch)
tree7eeb45a2d2d08483409a04c74fbc74fb2bbcde9f /src/gltf.cpp
parent6818cbfe21beefc04e4a174d44a92159c34cead1 (diff)
Clean up around included files
Diffstat (limited to 'src/gltf.cpp')
-rw-r--r--src/gltf.cpp542
1 files changed, 349 insertions, 193 deletions
diff --git a/src/gltf.cpp b/src/gltf.cpp
index 4cdfdce..2ddf16a 100644
--- a/src/gltf.cpp
+++ b/src/gltf.cpp
@@ -1,145 +1,177 @@
#include "gltf.hpp"
-#include <execution>
-#include <fstream>
+using namespace simdjson;
-#ifndef API_TEST
-#define STB_IMAGE_IMPLEMENTATION
-#endif
-#include <stb_image.h>
+ondemand::object root;
-#include "utils.hpp"
-#ifdef API_TEST
-#include "vk-device-types.hpp"
-#include "vk-device.hpp"
-#include "vk-command-buffer.hpp"
-#include <vk_mem_alloc.h>
-#else
-#include "vk-renderer.hpp"
-#endif
+struct accessor {
+ u32 view_index = 0U;
+ u32 count = 0U;
+ u32 component_type = 0U;
+ std::string_view type;
+};
-gltf::gltf(const std::filesystem::path& filepath) {
- auto parent_path = filepath.parent_path();
- std::fstream f{ filepath };
+struct buffer_view {
+ u32 buffer_index = 0U;
+ u32 length = 0U;
+ u32 offset = 0U;
+};
- if (!f.is_open()) {
- OutputDebugStringA("failed to open!");
- }
-
- f >> gltf_json;
+// component types
+#define GL_BYTE 0x1400
+#define GL_UNSIGNED_BYTE 0x1401
+#define GL_SHORT 0x1402
+#define GL_UNSIGNED_SHORT 0x1403
+#define GL_FLOAT 0x1406
+#define GL_FIXED 0x140C
- auto& scene = gltf_json["scenes"][0];
+#define SCALAR 0x5343414C4152
+#define VEC2 0x56454332
+#define VEC3 0x56454333
+#define VEC4 0x56454334
- auto& gltf_buffers = gltf_json["buffers"];
- auto buffer_count = gltf_buffers.size();
- buffers.resize(gltf_buffers.size());
- for (auto buffer_index{ 0U }; buffer_index < buffer_count; buffer_index++) {
- auto buffer_path = parent_path / gltf_buffers[buffer_index]["uri"].get<std::string>();
- buffers[buffer_index] = read_file(buffer_path.string().c_str());
+static u32 accessor_type_to_component_count(std::string_view& type) {
+ if (strncmp("SCALAR", type.data(), type.size()) == 0) {
+ return 1U;
+ } else if (strncmp("VEC2", type.data(), type.size()) == 0) {
+ return 2U;
+ } else if (strncmp("VEC3", type.data(), type.size()) == 0) {
+ return 3U;
+ } else if (strncmp("VEC4", type.data(), type.size()) == 0) {
+ return 4U;
}
+ assert(false);
+ return 0U;
+}
- load_textures(parent_path);
- load_materials();
-
- load_meshes();
-
- auto& root_children = scene["nodes"];
- size_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(root_children[child_index].get<uint32_t>(), root_node.children[child_index]);
+static u32 component_type_size(u32 type) {
+ switch (type) {
+ case GL_BYTE:
+ case GL_UNSIGNED_BYTE:
+ return 1U;
+ case GL_SHORT:
+ case GL_UNSIGNED_SHORT:
+ return 2U;
+ case GL_FLOAT:
+ case GL_FIXED:
+ return 4U;
+ default: assert(false);
}
-
- f.close();
+ return 0U;
}
-void gltf::load_node(uint32_t index, node& parent) {
- const auto& gltf_node = gltf_json["nodes"][index];
+static Mesh::submesh load_primitive(ondemand::object& primitive, std::vector<struct buffer>& buffers, std::vector<struct accessor>& accessors, std::vector<struct buffer_view>& buffer_views) {
+ Mesh::submesh submesh;
+
+ // indices
+ {
+ u32 indices_id = primitive["indices"].get_uint32();
+ struct accessor& accessor = accessors[indices_id];
- if (gltf_node.contains("children")) {
- const auto& children = gltf_node["children"];
- uint32_t children_count = gltf_node["children"];
- parent.children.resize(children_count);
+ struct buffer_view& view = buffer_views[accessor.view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
- for (size_t child_index = 0; child_index < children_count; child_index++) {
- load_node(children[child_index].get<uint32_t>(), parent.children[child_index]);
- }
- }
+ submesh.indices = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
- if (gltf_node.contains("mesh")) {
- parent.mesh = &meshes[gltf_node["mesh"].get<uint32_t>()];
+ submesh.index_count = accessor.count;
}
-}
-void gltf::load_meshes() {
- const auto& gltf_meshes = gltf_json["meshes"];
- auto meshes_count = gltf_meshes.size();
- meshes.resize(meshes_count);
+ // positions
+ {
+ u32 pos_id = primitive["attributes"]["POSITION"].get_uint32();
+ struct accessor& accessor = accessors[pos_id];
- for (size_t mesh_index = 0; mesh_index < meshes_count; mesh_index++) {
- auto& mesh = meshes[mesh_index];
- const auto& primitives = gltf_meshes[mesh_index]["primitives"];
+ struct buffer_view& view = buffer_views[accessor.view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
- for (const auto& primitive : primitives) {
- auto& material = materials[primitive["material"].get<uint32_t>()];
- mesh.add_submesh(load_primitive(primitive), material);
- }
+ submesh.attributes[ATTRIBUTE_TYPE::POSITION] = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
- Mesh::register_mesh(mesh);
+ submesh.vertex_count = accessor.count;
}
-}
-Mesh::submesh gltf::load_primitive(const json& primitive) {
- Mesh::submesh submesh;
+ u32 normal_index = 0U;
+ if (!primitive["attributes"]["NORMAL"].get(normal_index)) {
+ struct accessor& accessor = accessors[normal_index];
+ u32 view_index = accessor.view_index;
- submesh.indices = load_attribute(primitive["indices"]);
- submesh.attributes[ATTRIBUTE_TYPE::POSITION] = load_attribute(primitive["attributes"]["POSITION"]);
+ struct buffer_view& view = buffer_views[view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
- if (primitive["attributes"].contains("NORMAL")) {
- submesh.attributes[ATTRIBUTE_TYPE::NORMAL] = load_attribute(primitive["attributes"]["NORMAL"]);
+ submesh.attributes[ATTRIBUTE_TYPE::NORMAL] = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
}
- if (primitive["attributes"].contains("TEXCOORD_0")) {
- submesh.attributes[ATTRIBUTE_TYPE::UV_0] = load_attribute(primitive["attributes"]["TEXCOORD_0"]);
- }
+ u32 texcoord_index = 0U;
+ if (!primitive["attributes"]["TEXCOORD_0"].get(texcoord_index)) {
+ struct accessor& accessor = accessors[texcoord_index];
+ u32 view_index = accessor.view_index;
- 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>();
+ struct buffer_view& view = buffer_views[view_index];
+ struct buffer& buffer = buffers[view.buffer_index];
+
+ submesh.attributes[ATTRIBUTE_TYPE::UV_0] = {
+ .data = &buffer.bytes[view.offset],
+ .length = accessor.count * accessor_type_to_component_count(accessor.type) * component_type_size(accessor.component_type),
+ };
+ }
return submesh;
}
-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>()];
+static void load_textures(char* path, std::vector<handle<device_texture>>& textures, std::vector<struct buffer>& buffers, std::vector<struct buffer_view>& buffer_views, bool is_glb) {
+ ondemand::array gltf_images = root["images"];
+ std::vector<raw_image> images(gltf_images.count_elements());
+ size_t path_len = strlen(path);
+ char path_buffer[2048] = { 0U };
+ strncpy(path_buffer, path, path_len);
+ BEGIN_MARKER(LOAD_TEXTURES);
+ u32 image_index = 0U;
+ for (ondemand::object gltf_image : gltf_images) {
+ if (is_glb) {
+ // TODO: consider mimeType
+ struct buffer_view& view = buffer_views[gltf_image["bufferView"]];
+ struct buffer& buffer = buffers[view.buffer_index];
- return {
- &buffer[offset],
- view["byteLength"].get<size_t>()
- };
-}
+ raw_image& image = images[image_index++];
-void gltf::load_textures(const std::filesystem::path& path) {
- const auto& gltf_images = gltf_json["images"];
- auto images_count = gltf_images.size();
- std::vector<raw_image> images{ images_count };
+ image.data = stbi_load_from_memory(&buffer.bytes[view.offset], view.length, &image.width, &image.height, &image.channels, 4);
- std::vector<size_t> v(images_count);
- std::iota(v.begin(), v.end(), 0);
+ } else {
+ std::string_view uri_view = gltf_image["uri"];
+ strncpy(path_buffer + path_len, uri_view.data(), uri_view.length());
+ path_buffer[path_len + uri_view.length()] = '\0';
- const auto& gltf_textures = gltf_json["textures"];
- auto textures_count = gltf_textures.size();
- textures.resize(textures_count);
+ raw_image& image = images[image_index++];
+ image.data = stbi_load(path_buffer, &image.width, &image.height, &image.channels, 4);
+ }
+ }
+ END_MARKER(LOAD_TEXTURES);
-#ifdef API_TEST
- auto& device = vkdevice::get_render_device();
+ // ondemand::array gltf_samplers = root["samplers"];
+ // std::vector<handle<device_sampler>> samplers(gltf_samplers.count_elements());
+
+ // auto sampler = device.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
+ // for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
+ // samplers[sampler_index] = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
+ // }
+
+ vkdevice& device = vkdevice::get();
constexpr auto buffers_count = 2U;
- auto total_size = images_count * 4096U * 4096 * sizeof(uint32_t);
- auto buffer_size = total_size / 32U;
+ auto total_size = images.size() * 4096U * 4096 * sizeof(uint32_t);
+ // TODO: Fix nasty stuff going on
+ // Crash on buffer destruction
+ // Load wrong images
+ // auto buffer_size = total_size / 32U;
+ auto buffer_size = total_size / 2U;
handle<device_buffer> staging_buffers_handle[buffers_count] = {
device.create_buffer({
@@ -156,46 +188,28 @@ void gltf::load_textures(const std::filesystem::path& path) {
}),
};
+ // TODO: Create a proper upload heap
+ BEGIN_MARKER(UPLOAD_TEXTURES);
graphics_command_buffer command_buffers[buffers_count];
device.allocate_command_buffers(command_buffers, buffers_count, QueueType::GRAPHICS, "upload_buffer");
auto buffer_index = 0U;
auto command_buffer = command_buffers[buffer_index];
auto buffer_handle = staging_buffers_handle[buffer_index];
- auto buffer = device.get_buffer(buffer_handle);
+ device_buffer& buffer = device.get_buffer(buffer_handle);
command_buffer.start();
-#endif // API_TEST
-
- std::for_each(std::execution::par, v.begin(), v.end(), [&](const size_t image_index) {
- const auto& gltf_image = gltf_images[image_index];
- auto filepath = (path / gltf_image["uri"].get<std::string>()).string();
- auto& image = images[image_index];
- image.data = stbi_load(filepath.c_str(), &image.width, &image.height, &image.channels, 4);
- });
-
- // const auto &gltf_samplers = gltf_json["samplers"];
- // auto samplers_count = gltf_samplers.size();
- // std::vector<Sampler *> samplers{samplers_count};
-
-#ifdef API_TEST
- const auto &gltf_samplers = gltf_json["samplers"];
- auto samplers_count = gltf_samplers.size();
- std::vector<handle<device_sampler>> samplers{samplers_count};
-
- // auto sampler = device.create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
- // samplers[sampler_index] = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // }
- for (size_t texture_index = 0; texture_index < textures_count; texture_index++) {
- auto gltf_texture = gltf_textures[texture_index];
- auto& image = images[gltf_texture["source"].get<uint32_t>()];
+ ondemand::array gltf_textures = root["textures"];
+ textures.resize(gltf_textures.count_elements());
+ u32 texture_index = 0U;
+ for (ondemand::object gltf_texture: gltf_textures) {
+ raw_image& image = images[gltf_texture["source"]];
// if (gltf_texture.contains("sampler")) {
- // auto sampler_index = gltf_texture["sampler"].get<uint32_t>();
+ // u32 sampler_index = gltf_texture["sampler"].get_uint32();
// sampler = samplers[sampler_index];
// }
- auto texture = device.create_texture({
+ handle<device_texture> texture = device.create_texture({
.width = static_cast<uint32_t>(image.width),
.height = static_cast<uint32_t>(image.height),
.usages = VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_STORAGE_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,
@@ -203,105 +217,247 @@ void gltf::load_textures(const std::filesystem::path& path) {
.type = VK_IMAGE_TYPE_2D,
});
- uint64_t size = image.width * image.height * sizeof(uint32_t);
- auto offset = buffer.offset;
- if (offset + size > buffer_size) {
+ u32 size = image.width * image.height * sizeof(uint32_t);
+ if (buffer.allocated_size + size > buffer.size) {
command_buffer.stop();
- device.submit(&command_buffer, 1 );
+ device.submit(&command_buffer, 1);
- buffer_index = (++buffer_index) % buffers_count;
+ buffer_index = (buffer_index + 1U) % buffers_count;
command_buffer = command_buffers[buffer_index];
buffer_handle = staging_buffers_handle[buffer_index];
buffer = device.get_buffer(buffer_handle);
buffer.reset();
- device.wait();
+ // TODO: Remove the wait
+ // device.wait();
command_buffer.start();
- offset = 0U;
}
- void* ptr = buffer.allocate(size);
- memcpy(ptr, image.data, size);
+ memcpy(buffer.allocate(size), image.data, size);
command_buffer.barrier(texture, VK_PIPELINE_STAGE_2_TRANSFER_BIT, VK_ACCESS_2_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL);
- command_buffer.copy(buffer_handle, texture, static_cast<VkDeviceSize>(offset));
+ command_buffer.copy(buffer_handle, texture, static_cast<VkDeviceSize>(buffer.offset));
command_buffer.barrier(texture, VK_PIPELINE_STAGE_2_FRAGMENT_SHADER_BIT, VK_ACCESS_2_SHADER_WRITE_BIT, VK_IMAGE_LAYOUT_READ_ONLY_OPTIMAL);
- textures[texture_index] = texture;
+ textures[texture_index++] = texture;
}
- command_buffer.stop();
- device.submit(&command_buffer, 1);
+ if (buffer.allocated_size > 0U) {
+ command_buffer.stop();
+ device.submit(&command_buffer, 1);
+ }
device.wait();
device.destroy_buffer(staging_buffers_handle[0]);
device.destroy_buffer(staging_buffers_handle[1]);
-#else
- Sampler* sampler = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // for (size_t sampler_index = 0; sampler_index < samplers_count; sampler_index++) {
- // samplers[sampler_index] = vkrenderer::create_sampler(VK_FILTER_LINEAR, VK_SAMPLER_ADDRESS_MODE_REPEAT);
- // }
+ END_MARKER(UPLOAD_TEXTURES);
+}
- for (size_t texture_index = 0; texture_index < textures_count; texture_index++) {
- auto gltf_texture = gltf_textures[texture_index];
+static void load_materials(std::vector<material>& materials, std::vector<handle<device_texture>>& textures) {
+ ondemand::array gltf_materials = root["materials"];
+ materials.resize(gltf_materials.count_elements());
- auto& image = images[gltf_texture["source"].get<uint32_t>()];
- // if (gltf_texture.contains("sampler")) {
- // auto sampler_index = gltf_texture["sampler"].get<uint32_t>();
- // sampler = samplers[sampler_index];
- // }
+ u32 material_index = 0U;
+ for (ondemand::object object: gltf_materials) {
+ material& material = materials[material_index++];
+ material.base_color = vec3(1.f);
+ material.metalness = 1.f;
+ material.roughness = 1.f;
- auto* texture = vkrenderer::create_2d_texture(static_cast<uint32_t>(image.width), static_cast<uint32_t>(image.height), VK_FORMAT_R8G8B8A8_UNORM, sampler);
+ ondemand::object pbr_params;
+ if (!object["pbrMetallicRoughness"].get(pbr_params)) {
+ ondemand::array base_color;
+ if (!pbr_params["baseColorFactor"].get(base_color)) {
+ u32 id = 0U;
+ for (double val : base_color) {
+ material.base_color.arr[id++] = static_cast<float>(val);
+ }
+ }
- texture->update(image.data);
+ ondemand::object base_color_texture;
+ if (!pbr_params["baseColorTexture"].get(base_color_texture)) {
+ material.base_color_texture = textures[base_color_texture["index"]];
+ }
- textures[texture_index] = texture;
+ pbr_params["metallicFactor"].get(material.metalness);
+ pbr_params["roughnessFactor"].get(material.roughness);
+
+ ondemand::object metallic_roughness_texture;
+ if (!pbr_params["metallicRoughnessTexture"].get(metallic_roughness_texture)) {
+ material.metallic_roughness_texture = textures[metallic_roughness_texture["index"]];
+ }
+ }
}
-#endif
}
-void gltf::load_materials() {
- const auto& gltf_materials = gltf_json["materials"];
- auto materials_count = gltf_materials.size();
- materials.resize(materials_count);
+gltf::gltf(const char* filepath) {
+ BEGIN_MARKER(LOAD_GLTF);
- for (size_t material_index = 0; material_index < materials_count; material_index++) {
- const auto& gltf_material = gltf_materials[material_index];
- auto& material = materials[material_index];
+ ondemand::parser parser;
+ padded_string json;
+ ondemand::document doc;
- if (gltf_material.contains("pbrMetallicRoughness")) {
- const auto& pbr_params = gltf_material["pbrMetallicRoughness"];
+ const char* ext = PathFindExtensionA(filepath);
- if (pbr_params.contains("baseColorFactor")) {
- const auto& base_color = pbr_params["baseColorFactor"];
- material.base_color.set<0>(base_color[0].get<float>());
- material.base_color.set<1>(base_color[1].get<float>());
- material.base_color.set<2>(base_color[2].get<float>());
- material.base_color.arr[3] = base_color[3].get<float>(); // Since we use a vec3 for colors we are not allowed toset fourth value with set<3>
- } else {
- material.base_color = vec3(1.f);
- }
+ char buffer_path[2048U] = { 0U };
+ char* filename = nullptr;
+ GetFullPathNameA( filepath, 2048U, buffer_path, &filename);
+ size_t parent_dir_len = filename - buffer_path;
- if (pbr_params.contains("baseColorTexture")) {
- auto base_color_index = pbr_params["baseColorTexture"]["index"].get<uint32_t>();
- material.base_color_texture = textures[base_color_index];
- }
+ // TODO: Remove
+ is_glb = strcmp(ext, ".glb") == 0;
+
+ if (is_glb) {
+ size_t filesize = 0U;
+ size_t read = 0U;
+ u8* glb_buffer = read_file(filepath, &filesize);
+ header = (struct glb_header*)glb_buffer;
+ assert(filesize == header->length);
+ // assert(header->magic == (u32)"glTF");
+
+ read += sizeof(*header);
+ chunks.push_back((struct glb_chunk*)(header + 1));
+ read += offsetof(struct glb_chunk, data) + chunks.back()->length;
+ while (read != header->length) {
+ chunks.push_back((struct glb_chunk*)(glb_buffer + read));
+ read += offsetof(struct glb_chunk, data) + chunks.back()->length;
+ }
+
+ doc = parser.iterate((const char*)&chunks[0]->data[0U], chunks[0]->length, filesize);
+ root = doc;
+
+ ondemand::array gltf_buffers = root["buffers"];
+ assert(gltf_buffers.count_elements() == chunks.size() - 1U);
+ buffers.resize(gltf_buffers.count_elements());
+ u32 buffer_index = 0U;
+ for (u32 chunk_index = 1U; chunk_index < chunks.size(); chunk_index++) {
+ buffers[buffer_index++] = buffer {
+ .bytes = chunks[chunk_index]->data,
+ .size = chunks[chunk_index]->length,
+ };
+ }
+ } else {
+ json = padded_string::load(filepath);
+ doc = parser.iterate(json);
+ root = doc;
- if (pbr_params.contains("metallicFactor")) {
- material.metalness = pbr_params["metallicFactor"].get<float>();
- } else {
- material.metalness = 1.0;
+ {
+ ondemand::array gltf_buffers = root["buffers"];
+ buffers.resize(gltf_buffers.count_elements());
+ u32 buffer_index = 0U;
+ for (ondemand::object value: gltf_buffers) {
+ std::string_view uri_view = value["uri"];
+ strncpy(buffer_path + parent_dir_len, uri_view.data(), uri_view.length());
+ buffer_path[parent_dir_len + uri_view.length()] = '\0';
+
+ size_t file_size = 0U;
+ uint8_t* bytes = read_file(buffer_path, &file_size);
+ buffers[buffer_index++] = {
+ .bytes = bytes,
+ .size = file_size,
+ };
}
+ }
+ }
+
+
+ std::vector<struct accessor> accessors;
+ {
+ ondemand::array gltf_accessors = root["accessors"];
+ accessors.resize(gltf_accessors.count_elements());
+ u32 accessor_index = 0U;
+ for (ondemand::object value: gltf_accessors) {
+ struct accessor& accessor = accessors[accessor_index++];
+ value["bufferView"].get(accessor.view_index);
+ value["count"].get(accessor.count);
+ value["type"].get(accessor.type);
+ value["componentType"].get(accessor.component_type);
+ }
+ }
+
+ std::vector<struct buffer_view> buffer_views;
+ {
+ ondemand::array gltf_views = root["bufferViews"];
+ buffer_views.resize(gltf_views.count_elements());
+ u32 view_index = 0U;
+ for (ondemand::object value: gltf_views) {
+ struct buffer_view& view = buffer_views[view_index++];
+ value["buffer"].get(view.buffer_index);
+ value["byteLength"].get(view.length);
+ value["byteOffset"].get(view.offset);
+ }
+ }
+
- if (pbr_params.contains("roughnessFactor")) {
- material.roughness = pbr_params["roughnessFactor"].get<float>();
- } else {
- material.roughness = 1.0;
+ {
+ ondemand::array gltf_nodes = root["nodes"];
+ nodes.resize(gltf_nodes.count_elements());
+
+ u32 node_index = 0U;
+ for (ondemand::object gltf_node: gltf_nodes) {
+ struct node& node = nodes[node_index++];
+
+ ondemand::array gltf_children;
+ if (!gltf_node["children"].get(gltf_children)) {
+ node.children.resize(gltf_children.count_elements());
+
+ u32 child_index = 0U;
+ for (auto child : gltf_children) {
+ node.children[child_index++] = child.get_uint32();
+ }
}
- if (pbr_params.contains("metallicRoughnessTexture")) {
- auto metallic_roughness_index = pbr_params["metallicRoughnessTexture"]["index"].get<uint32_t>();
- material.metallic_roughness_texture = textures[metallic_roughness_index];
+ node.mesh = UINT32_MAX;
+ gltf_node["mesh"].get(node.mesh);
+ }
+ }
+
+
+ // root nodes
+ {
+ u32 scene_index = root["scene"].get_uint32();
+ ondemand::array gltf_scene_nodes = root["scenes"].at(scene_index)["nodes"];
+ root_nodes.resize(gltf_scene_nodes.count_elements());
+
+ u32 index = 0U;
+ for (auto node_index: gltf_scene_nodes) {
+ root_nodes[index++] = node_index.get_uint32();
+ }
+ }
+
+ buffer_path[parent_dir_len] = '\0';
+ load_textures(buffer_path, textures, buffers, buffer_views, is_glb);
+ load_materials(materials, textures);
+
+ // meshes
+ {
+ ondemand::array gltf_meshes = root["meshes"];
+ meshes.resize(gltf_meshes.count_elements());
+
+ u32 mesh_index = 0U;
+ for (ondemand::object gltf_mesh: gltf_meshes) {
+ Mesh& mesh = meshes[mesh_index++];
+ ondemand::array gltf_primitives = gltf_mesh["primitives"];
+
+ for (ondemand::object primitive : gltf_primitives) {
+ material& material = materials[primitive["material"]];
+ mesh.add_submesh(load_primitive(primitive, buffers, accessors, buffer_views), material);
}
+
+ Mesh::register_mesh(mesh);
}
}
+
+ END_MARKER(LOAD_GLTF);
+}
+
+void gltf::deinit() {
+ for (handle<device_texture> handle: textures) {
+ vkdevice::get().destroy_texture(handle);
+ }
+
+ for (struct buffer& buffer: buffers) {
+ free(buffer.bytes);
+ }
+
+ free(header);
}