chore: export gltf basic attributes

This commit is contained in:
Jan 2024-04-01 15:20:58 +02:00
parent 8a0c93d3d8
commit 0d96213f21
No known key found for this signature in database
GPG Key ID: 44B581F78FF5C57C
2 changed files with 142 additions and 18 deletions

View File

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "Json/JsonExtension.h" #include "Json/JsonExtension.h"
#include <array>
#include <nlohmann/json.hpp> #include <nlohmann/json.hpp>
#include <optional> #include <optional>
#include <string> #include <string>
@ -20,14 +21,16 @@ namespace gltf
class JsonNode class JsonNode
{ {
public: public:
std::string name; std::optional<std::string> name;
std::vector<float> translation; std::optional<std::array<float, 3>> translation;
std::vector<float> rotation; std::optional<std::array<float, 4>> rotation;
std::vector<float> scale; std::optional<std::array<float, 3>> scale;
std::vector<unsigned> children; std::optional<std::vector<unsigned>> children;
std::optional<unsigned> skin;
std::optional<unsigned> mesh;
}; };
NLOHMANN_DEFINE_TYPE_EXTENSION(JsonNode, name, translation, rotation, scale, children); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonNode, name, translation, rotation, scale, children, skin, mesh);
class JsonBuffer class JsonBuffer
{ {
@ -166,7 +169,7 @@ namespace gltf
unsigned output; unsigned output;
}; };
NLOHMANN_DEFINE_TYPE_EXTENSION(JsonAnimationSampler, input); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonAnimationSampler, input, interpolation, output);
class JsonAnimation class JsonAnimation
{ {
@ -238,19 +241,30 @@ namespace gltf
NLOHMANN_DEFINE_TYPE_EXTENSION(JsonSkin, inverseBindMatrices, skeleton, joints); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonSkin, inverseBindMatrices, skeleton, joints);
class JsonScene
{
public:
std::vector<unsigned> nodes;
std::optional<std::string> name;
};
NLOHMANN_DEFINE_TYPE_EXTENSION(JsonScene, nodes, name);
class JsonRoot class JsonRoot
{ {
public: public:
std::vector<JsonAccessor> accessors; std::optional<std::vector<JsonAccessor>> accessors;
std::vector<JsonAnimation> animations; std::optional<std::vector<JsonAnimation>> animations;
JsonAsset asset; JsonAsset asset;
std::vector<JsonBuffer> buffers; std::optional<std::vector<JsonBuffer>> buffers;
std::vector<JsonBufferView> bufferViews; std::optional<std::vector<JsonBufferView>> bufferViews;
std::vector<JsonMaterial> materials; std::optional<std::vector<JsonMaterial>> materials;
std::vector<JsonMesh> meshes; std::optional<std::vector<JsonMesh>> meshes;
std::vector<JsonNode> nodes; std::optional<std::vector<JsonNode>> nodes;
std::vector<JsonSkin> skins; std::optional<std::vector<JsonSkin>> skins;
std::optional<unsigned> scene;
std::optional<std::vector<JsonScene>> scenes;
}; };
NLOHMANN_DEFINE_TYPE_EXTENSION(JsonRoot, asset); NLOHMANN_DEFINE_TYPE_EXTENSION(JsonRoot, accessors, animations, asset, buffers, bufferViews, materials, meshes, nodes, skins, scene, scenes);
} // namespace gltf } // namespace gltf

View File

@ -13,6 +13,9 @@ namespace
class GltfWriterImpl final : public gltf::Writer class GltfWriterImpl final : public gltf::Writer
{ {
static constexpr auto NODE_INDEX_MESH = 0u;
static constexpr auto NODE_FIRST_INDEX_BONES = 1u;
public: public:
GltfWriterImpl(const Output* output, std::string gameName, std::string zoneName) GltfWriterImpl(const Output* output, std::string gameName, std::string zoneName)
: m_output(output), : m_output(output),
@ -24,8 +27,12 @@ namespace
void Write(std::ostream& stream) override void Write(std::ostream& stream) override
{ {
JsonRoot gltf; JsonRoot gltf;
gltf.asset.version = GLTF_VERSION_STRING; CreateJsonAsset(gltf.asset);
gltf.asset.generator = GLTF_GENERATOR; CreateMeshNode(gltf);
CreateMesh(gltf);
CreateSkeletonNodes(gltf);
CreateSkin(gltf);
CreateScene(gltf);
const json jRoot = gltf; const json jRoot = gltf;
m_output->EmitJson(jRoot); m_output->EmitJson(jRoot);
@ -33,6 +40,109 @@ namespace
} }
private: private:
static void CreateJsonAsset(JsonAsset& asset)
{
asset.version = GLTF_VERSION_STRING;
asset.generator = GLTF_GENERATOR;
}
void CreateMeshNode(JsonRoot& gltf) const
{
JsonNode meshNode;
// We only have one mesh
meshNode.mesh = 0u;
// Only add skin if the model has bones
if (!m_bones.empty())
{
// We only have one skin
meshNode.skin = 0u;
}
if (!gltf.nodes.has_value())
gltf.nodes.emplace();
gltf.nodes->emplace_back(std::move(meshNode));
}
void CreateMesh(JsonRoot& gltf) const
{
if (!gltf.meshes.has_value())
gltf.meshes.emplace();
JsonMesh mesh;
gltf.meshes->emplace_back(std::move(mesh));
}
static unsigned CreateNodeIndexFromBoneIndex(const unsigned boneIndex)
{
return boneIndex + NODE_FIRST_INDEX_BONES;
}
void CreateSkeletonNodes(JsonRoot& gltf) const
{
if (m_bones.empty())
return;
if (!gltf.nodes.has_value())
gltf.nodes.emplace();
for (const auto [boneIndex, bone] : std::views::enumerate(m_bones))
{
JsonNode boneNode;
boneNode.name = bone.name;
boneNode.translation = std::to_array(bone.globalOffset);
boneNode.rotation = std::to_array({bone.globalRotation.m_x, bone.globalRotation.m_y, bone.globalRotation.m_z, bone.globalRotation.m_w});
const auto isParentOf = [this, boneIndex](const unsigned b)
{
return m_bones[b].parentIndex == boneIndex;
};
auto children = std::ranges::iota_view(0u, m_bones.size()) | std::views::filter(isParentOf)
| std::views::transform(CreateNodeIndexFromBoneIndex) | std::ranges::to<std::vector<unsigned>>();
if (!children.empty())
boneNode.children = std::move(children);
gltf.nodes->emplace_back(std::move(boneNode));
}
}
void CreateSkin(JsonRoot& gltf) const
{
if (m_bones.empty())
return;
JsonSkin skin;
skin.joints =
std::ranges::iota_view(0u, m_bones.size()) | std::views::transform(CreateNodeIndexFromBoneIndex) | std::ranges::to<std::vector<unsigned>>();
if (!gltf.skins.has_value())
gltf.skins.emplace();
gltf.skins->emplace_back(std::move(skin));
}
void CreateScene(JsonRoot& gltf) const
{
JsonScene scene;
// Only add skin if the model has bones
if (m_bones.empty())
scene.nodes.emplace_back(NODE_INDEX_MESH);
else
scene.nodes.emplace_back(m_skeleton_node);
if (!gltf.scenes.has_value())
gltf.scenes.emplace();
gltf.scenes->emplace_back(std::move(scene));
gltf.scene = 0u;
}
unsigned m_skeleton_node = 0u;
const Output* m_output; const Output* m_output;
std::string m_game_name; std::string m_game_name;
std::string m_zone_name; std::string m_zone_name;