Skip to content

Commit

Permalink
* GLTF - Added support for loading scenes and nodes. retrieve top-lev…
Browse files Browse the repository at this point in the history
…el nodes via get_active_nodes(), and retrieve any node at all via get_nodes()
  • Loading branch information
harrand committed Jul 28, 2023
1 parent 6443b15 commit 5cfd682
Show file tree
Hide file tree
Showing 2 changed files with 158 additions and 0 deletions.
136 changes: 136 additions & 0 deletions src/tz/io/gltf.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#include "tz/io/gltf.hpp"
#include "tz/core/debug.hpp"
#include "tz/core/profile.hpp"
#include "tz/core/matrix_transform.hpp"
#include <regex>
#include <fstream>

Expand Down Expand Up @@ -103,6 +104,26 @@ namespace tz::io
return this->images;
}

std::span<const gltf_node> gltf::get_nodes() const
{
return this->nodes;
}

std::vector<gltf_node> gltf::get_active_nodes() const
{
if(this->active_scene_id == detail::badzu)
{
return {};
}
std::vector<gltf_node> top_level_nodes = {};
const gltf_scene& scene = this->scenes[this->active_scene_id];
for(std::size_t node_id : scene.nodes)
{
top_level_nodes.push_back(this->nodes[node_id]);
}
return top_level_nodes;
}

gltf_submesh_data gltf::get_submesh_vertex_data(std::size_t meshid, std::size_t submeshid) const
{
TZ_PROFZONE("gltf - retrieve submesh", 0xFFFF2222);
Expand Down Expand Up @@ -338,6 +359,12 @@ namespace tz::io
TZ_PROFZONE("gltf - import", 0xFFFF2222);
this->parse_header(glb_data.substr(0, 12));
this->parse_chunks(glb_data.substr(12));
if(this->data["scene"].is_number_integer())
{
this->active_scene_id = this->data["scene"];
}
this->create_scenes();
this->create_nodes();
this->load_resources();
this->create_animations();
this->create_images();
Expand Down Expand Up @@ -422,6 +449,115 @@ namespace tz::io
this->parse_chunks(chunkdata);
}

void gltf::create_scenes()
{
TZ_PROFZONE("gltf - create scenes", 0xFFFF2222);
json scenes = this->data["scenes"];
tz::assert(scenes.is_array() || scenes.is_null());
if(scenes.is_array())
{
for(auto jscene : scenes)
{
auto& scene = this->scenes.emplace_back();
if(jscene["name"].is_string())
{
scene.name = jscene["name"];
}
if(jscene["nodes"].is_array())
{
for(std::size_t node_id : jscene["nodes"])
{
scene.nodes.push_back(node_id);
}
}
}
}
}

void gltf::create_nodes()
{
TZ_PROFZONE("gltf - create nodes", 0xFFFF2222);
json nodes = this->data["nodes"];
tz::assert(nodes.is_array() || nodes.is_null());
if(nodes.is_array())
{
for(auto jnode : nodes)
{
auto& node = this->nodes.emplace_back();
tz::assert(jnode["camera"].is_null(), "Node camera is not supported.");
tz::assert(jnode["children"].is_array() || jnode["children"].is_null());
if(jnode["children"].is_array())
{
for(std::size_t jchild : jnode["children"])
{
node.children.push_back(jchild);
}
}
tz::assert(jnode["skin"].is_null(), "Node skin is not supported");
if(jnode["matrix"].is_array())
{
for(std::size_t i = 0; i < 16; i++)
{
node.transform(i / 4, i % 4) = jnode["matrix"][i];
}
}
else
{
tz::vec3 pos = tz::vec3::zero();
tz::vec3 rot = tz::vec3::zero();
tz::vec3 scale = tz::vec3::filled(1.0f);
// TODO: handle pos, rot and scale
if(jnode["translation"].is_array())
{
for(std::size_t i = 0; i < 3; i++)
{
pos[i] = jnode["translation"][i];
}
}
if(jnode["rotation"].is_array())
{
tz::vec4 q;
for(std::size_t i = 0; i < 4; i++)
{
q[i] = jnode["rotation"][i];
}
// convert quat to euler.
float sinr_cosp = 2.0f * (q[3] * q[0] + q[1] * q[2]);
float cosr_cosp = 1.0f - 2.0f * (q[0] * q[0] + q[1] * q[1]);

rot[2] = std::atan2(sinr_cosp, cosr_cosp);

float sinp = std::sqrt(1.0f + 2.0f * (q[3] * q[1] - q[0] * q[2]));
float cosp = std::sqrt(1.0f - 2.0f * (q[3] * q[1] - q[0] * q[2]));

rot[0] = 2.0f * std::atan2(sinp, cosp) - 3.14159f / 2.0f;

float siny_cosp = 2.0f * (q[3] * q[2] + q[0] * q[1]);
float cosy_cosp = 1.0f - 2.0f * (q[1] * q[1] + q[2] * q[2]);

rot[1] = std::atan2(siny_cosp, cosy_cosp);
}
if(jnode["scale"].is_array())
{
for(std::size_t i = 0; i < 3; i++)
{
scale[i] = jnode["scale"][i];
}
}
node.transform = tz::model(pos, rot, scale);
}
if(jnode["mesh"].is_number_integer())
{
node.mesh = jnode["mesh"];
}
if(jnode["name"].is_string())
{
node.name = jnode["name"];
}
}
}
}

void gltf::load_resources()
{
TZ_PROFZONE("gltf - load resources", 0xFFFF2222);
Expand Down
22 changes: 22 additions & 0 deletions src/tz/io/gltf.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
#define TOPAZ_IO_GLTF_HPP
#include "tz/core/data/enum_field.hpp"
#include "tz/core/data/vector.hpp"
#include "tz/core/matrix.hpp"
#include "tz/io/image.hpp"
#include "nlohmann/json.hpp"
#undef assert
Expand Down Expand Up @@ -46,6 +47,20 @@ namespace tz::io
std::size_t size = detail::badzu;
};

struct gltf_scene
{
std::vector<std::size_t> nodes = {};
std::string name = "Unnamed Scene";
};

struct gltf_node
{
std::string name = "Unnamed Node";
std::size_t mesh = detail::badzu;
tz::mat4 transform = tz::mat4::identity();
std::vector<std::size_t> children = {};
};

enum class gltf_buffer_view_type
{
none = 0,
Expand Down Expand Up @@ -254,12 +269,16 @@ namespace tz::io
std::span<const std::byte> view_buffer(gltf_buffer_view view) const;
std::span<const gltf_mesh> get_meshes() const;
std::span<const gltf_image> get_images() const;
std::span<const gltf_node> get_nodes() const;
std::vector<gltf_node> get_active_nodes() const;
gltf_submesh_data get_submesh_vertex_data(std::size_t meshid, std::size_t submeshid) const;
tz::io::image get_image_data(std::size_t imageid) const;
private:
gltf(std::string_view glb_data);
void parse_header(std::string_view header);
void parse_chunks(std::string_view chunkdata);
void create_scenes();
void create_nodes();
void load_resources();
void create_animations();
void create_images();
Expand All @@ -274,6 +293,9 @@ namespace tz::io
gltf_header header;
std::vector<gltf_chunk_data> chunks = {};
json data = {};
std::size_t active_scene_id = detail::badzu;
std::vector<gltf_scene> scenes = {};
std::vector<gltf_node> nodes = {};
std::vector<gltf_resource> resources = {};
std::vector<gltf_animation> animations = {};
std::vector<gltf_image> images = {};
Expand Down

0 comments on commit 5cfd682

Please sign in to comment.