aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorladevieq <ladevie.quentin@gmail.com>2021-08-15 23:17:06 +0200
committerladevieq <ladevie.quentin@gmail.com>2021-08-15 23:17:06 +0200
commite1cbdd1d61ffb04ae156fe67923ec5e0871021f1 (patch)
tree438b6aa8bcbd5d2a00a10b2805bf0d45ea82f5c9
parent8c1e26e552556e36a5c1fecd9558d9ab9dd3d454 (diff)
Improve gltf loading
-rw-r--r--include/aabb.hpp24
-rw-r--r--include/gltf.hpp16
-rw-r--r--src/gltf.cpp91
-rw-r--r--src/scene.cpp42
-rw-r--r--src/utils.cpp2
5 files changed, 116 insertions, 59 deletions
diff --git a/include/aabb.hpp b/include/aabb.hpp
index 9bc69d1..cdbb79a 100644
--- a/include/aabb.hpp
+++ b/include/aabb.hpp
@@ -26,23 +26,23 @@ class aabb {
}
void union_with(const aabb &box) {
- minimum.x = fmin(minimum.x, box.minimum.x);
- minimum.y = fmin(minimum.y, box.minimum.y);
- minimum.z = fmin(minimum.z, box.minimum.z);
+ minimum.x = minimum.x < box.minimum.x ? minimum.x : box.minimum.x;
+ minimum.y = minimum.y < box.minimum.y ? minimum.y : box.minimum.y;
+ minimum.z = minimum.z < box.minimum.z ? minimum.z : box.minimum.z;
- maximum.x = fmax(maximum.x, box.maximum.x);
- maximum.y = fmax(maximum.y, box.maximum.y);
- maximum.z = fmax(maximum.z, box.maximum.z);
+ maximum.x = maximum.x > box.maximum.x ? maximum.x : box.maximum.x;
+ maximum.y = maximum.y > box.maximum.y ? maximum.y : box.maximum.y;
+ maximum.z = maximum.z > box.maximum.z ? maximum.z : box.maximum.z;
}
void union_with(const point3 &point) {
- minimum.x = fmin(minimum.x, point.x);
- minimum.y = fmin(minimum.y, point.y);
- minimum.z = fmin(minimum.z, point.z);
+ minimum.x = minimum.x < point.x ? minimum.x : point.x;
+ minimum.y = minimum.y < point.y ? minimum.y : point.y;
+ minimum.z = minimum.z < point.z ? minimum.z : point.z;
- maximum.x = fmax(maximum.x, point.x);
- maximum.y = fmax(maximum.y, point.y);
- maximum.z = fmax(maximum.z, point.z);
+ maximum.x = maximum.x > point.x ? maximum.x : point.x;
+ maximum.y = maximum.y > point.y ? maximum.y : point.y;
+ maximum.z = maximum.z > point.z ? maximum.z : point.z;
}
int32_t maximum_axis() {
diff --git a/include/gltf.hpp b/include/gltf.hpp
index 0a34888..7008e8a 100644
--- a/include/gltf.hpp
+++ b/include/gltf.hpp
@@ -3,6 +3,7 @@
#include <filesystem>
#include <vector>
+#include <optional>
#include <nlohmann/json.hpp>
@@ -17,18 +18,25 @@ struct mesh_part {
};
struct mesh {
- std::vector<std::vector<mesh_part>> nodes;
+ std::vector<mesh_part> parts;
+};
+
+struct node {
+ std::vector<node> children;
+ std::optional<mesh> mesh;
};
class gltf {
public:
- static mesh load(std::filesystem::path &path, std::string &filename);
+ static node load(std::filesystem::path &path, std::string &filename);
private:
- static void load_node(json &gltf_json, json &node, std::vector<std::vector<uint8_t>> &buffers_content, mesh& gltf_mesh);
+ static void load_node(json &gltf_json, uint32_t index, node &parent, std::vector<mesh> &meshes);
+
+ static std::vector<mesh> load_meshes(json &gltf_json, std::vector<std::vector<uint8_t>> &buffers_content);
- static void load_primitive(json &gltf_json, json &primitive, std::vector<std::vector<uint8_t>> &buffers_content, mesh& gltf_mesh);
+ static mesh_part load_primitive(json &gltf_json, json &primitive, std::vector<std::vector<uint8_t>> &buffers_content);
};
#endif
diff --git a/src/gltf.cpp b/src/gltf.cpp
index 055f2a6..6b39ff4 100644
--- a/src/gltf.cpp
+++ b/src/gltf.cpp
@@ -7,17 +7,15 @@
const vec3 scale (0.00800000037997961);
-mesh gltf::load(std::filesystem::path &path, std::string &filename) {
+node gltf::load(std::filesystem::path &path, std::string &filename) {
std::fstream f(path / filename);
json gltf_json;
f >> gltf_json;
- auto scene_index = gltf_json["scene"].get<uint32_t>();
- auto scenes = gltf_json["scenes"];
- auto scene = scenes[scene_index];
+ auto &scene = gltf_json["scenes"][0];
- auto buffers = gltf_json["buffers"];
+ auto &buffers = gltf_json["buffers"];
auto buffer_index = 0;
auto buffers_content = std::vector<std::vector<uint8_t>>(buffers.size());
for (auto &buffer: buffers) {
@@ -26,66 +24,95 @@ mesh gltf::load(std::filesystem::path &path, std::string &filename) {
buffer_index++;
}
- auto nodes = gltf_json["nodes"];
- auto gltf_mesh = mesh();
- for (auto &node: nodes) {
- gltf_mesh.nodes.push_back(std::vector<mesh_part>());
- load_node(gltf_json, node, buffers_content, gltf_mesh);
+ auto meshes = load_meshes(gltf_json, buffers_content);
+
+ 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);
+ }
+
+ return std::move(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];
+
+ if (gltf_node.contains("children")) {
+ 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);
+ }
}
- // return std::move(gltf_mesh);
- return gltf_mesh;
+ if (gltf_node.contains("mesh")) {
+ parent.mesh = std::make_optional(meshes[gltf_node["mesh"].get<uint32_t>()]);
+ }
}
-void gltf::load_node(json &gltf_json, json &node, std::vector<std::vector<uint8_t>> &buffers_content, mesh& gltf_mesh) {
- auto mesh_index = node["mesh"].get<uint32_t>();
- auto mesh = gltf_json["meshes"][mesh_index];
- auto primitives = mesh["primitives"];
+std::vector<mesh> gltf::load_meshes(json &gltf_json, std::vector<std::vector<uint8_t>> &buffers_content) {
+ auto &gltf_meshes = gltf_json["meshes"];
+ auto meshes_count = gltf_meshes.size();
+ std::vector<mesh> meshes { 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];
- for (auto &primitive: primitives) {
- gltf_mesh.nodes.back().push_back(mesh_part());
- load_primitive(gltf_json, primitive, buffers_content, gltf_mesh);
+ for (auto& primitive: primitives) {
+ mesh.parts.emplace_back(load_primitive(gltf_json, primitive, buffers_content));
+ }
}
+
+ return std::move(meshes);
}
-void gltf::load_primitive(json &gltf_json, json &primitive, std::vector<std::vector<uint8_t>> &buffers_content, mesh& gltf_mesh) {
- auto accessors = gltf_json["accessors"];
- auto &mesh_part = gltf_mesh.nodes.back().back();
+mesh_part gltf::load_primitive(json &gltf_json, json &primitive, std::vector<std::vector<uint8_t>> &buffers_content) {
+ 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_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_buffer = buffers_content[indices_buffer_index];
uint16_t* indices_start = (uint16_t*)(indices_buffer.data() + indices_offset);
- mesh_part.indices.resize(indices_length / sizeof(uint16_t));
+ part.indices.resize(indices_length / sizeof(uint16_t));
- std::memcpy(mesh_part.indices.data(), indices_start, indices_length);
+ 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_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_buffer = buffers_content[positions_buffer_index];
float* positions_start = (float*)(positions_buffer.data() + positions_offset);
- mesh_part.positions.resize(positions_length / (sizeof(float) * 3));
+ size_t positions_count = positions_length / (sizeof(float) * 3);
+ part.positions.resize(positions_count);
- for (size_t i = 0; i < positions_length / (sizeof(float) * 3); i++) {
- mesh_part.positions[i] = vec3(positions_start[i * 3], positions_start[i * 3 + 1], positions_start[i * 3 + 2]) * scale;
+ for (size_t i = 0; i < positions_count; i++) {
+ part.positions[i] = vec3(positions_start[i * 3], positions_start[i * 3 + 1], positions_start[i * 3 + 2]) * scale;
}
}
@@ -105,4 +132,6 @@ void gltf::load_primitive(json &gltf_json, json &primitive, std::vector<std::vec
// std::memcpy(mesh_part.normals.data(), normals_start, normals_length);
// }
+
+ return std::move(part);
}
diff --git a/src/scene.cpp b/src/scene.cpp
index 73c73e5..15cea11 100644
--- a/src/scene.cpp
+++ b/src/scene.cpp
@@ -1,6 +1,7 @@
#include "scene.hpp"
#include <filesystem>
+#include <queue>
#include "utils.hpp"
#include "gltf.hpp"
@@ -69,23 +70,42 @@
scene::scene(camera cam, uint32_t width, uint32_t height)
:meta(cam, width, height){
+ // auto bistro_interior_path = std::filesystem::path("../models/BistroInterior");
+ // auto bistro_interior_filename = std::string("BistroInterior.gltf");
+ // auto root_node = gltf::load(bistro_interior_path, bistro_interior_filename);
+
auto sponza_path = std::filesystem::path("../models/sponza");
auto sponza_filename = std::string("Sponza.gltf");
- auto mesh = gltf::load(sponza_path, sponza_filename);
+ auto root_node = gltf::load(sponza_path, sponza_filename);
+
+ std::queue<node> nodes_to_load {};
+ nodes_to_load.push(root_node);
+
+ while(nodes_to_load.size() != 0) {
+ auto &node = nodes_to_load.front();
- auto node = mesh.nodes[0];
- for (auto& mesh_part: node) {
- for (size_t i = 0; i < mesh_part.indices.size(); i += 3) {
- auto i1 = mesh_part.indices[i];
- auto i2 = mesh_part.indices[i + 1];
- auto i3 = mesh_part.indices[i + 2];
+ if (node.mesh) {
+ auto &mesh = node.mesh.value();
+ for (auto& mesh_part: mesh.parts) {
+ for (size_t i = 0; i < mesh_part.indices.size(); i += 3) {
+ auto i1 = mesh_part.indices[i];
+ auto i2 = mesh_part.indices[i + 1];
+ auto i3 = mesh_part.indices[i + 2];
- auto v1 = vertex { .position = mesh_part.positions[i1] };
- auto v2 = vertex { .position = mesh_part.positions[i2] };
- auto v3 = vertex { .position = mesh_part.positions[i3] };
+ auto v1 = vertex { .position = mesh_part.positions[i1] };
+ auto v2 = vertex { .position = mesh_part.positions[i2] };
+ auto v3 = vertex { .position = mesh_part.positions[i3] };
- triangles.emplace_back(v1, v2, v3);
+ triangles.emplace_back(v1, v2, v3);
+ }
+ }
}
+
+ for (auto &node: node.children) {
+ nodes_to_load.push(node);
+ }
+
+ nodes_to_load.pop();
}
// random_scene();
diff --git a/src/utils.cpp b/src/utils.cpp
index 6557ebc..2a9bdf5 100644
--- a/src/utils.cpp
+++ b/src/utils.cpp
@@ -37,7 +37,7 @@ std::vector<uint8_t> read_file(const char* path) {
return {};
}
- return file_content;
+ return std::move(file_content);
}
std::vector<uint8_t> read_file(std::string& path) {