|
|
|
@ -1,11 +1,11 @@
|
|
|
|
|
#include "inferno/util/json.h" |
|
|
|
|
#include <algorithm> // std::copy |
|
|
|
|
|
|
|
|
|
#include "nlohmann/json.hpp" |
|
|
|
|
|
|
|
|
|
#include "inferno/assert.h" |
|
|
|
|
#include "inferno/io/gltffile.h" |
|
|
|
|
#include "inferno/io/log.h" |
|
|
|
|
#include "inferno/render/gltf.h" |
|
|
|
|
#include <stdint.h> |
|
|
|
|
|
|
|
|
|
namespace Inferno { |
|
|
|
|
|
|
|
|
@ -22,22 +22,11 @@ namespace Inferno {
|
|
|
|
|
// Asset
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
{ |
|
|
|
|
ASSERT(Json::hasProperty(json, "asset"), "GlTF model missing required property 'asset'"); |
|
|
|
|
auto asset = json["asset"]; |
|
|
|
|
|
|
|
|
|
auto copyright = Json::parseStringProperty(asset, "copyright", false); |
|
|
|
|
auto generator = Json::parseStringProperty(asset, "generator", false); |
|
|
|
|
auto version = Json::parseStringProperty(asset, "version", true); |
|
|
|
|
ASSERT(version, "GlTF model missing required property 'version'"); |
|
|
|
|
ASSERT(version.value().compare("2.0") == 0, "GlTF version unsupported '{}'", version.value()); |
|
|
|
|
auto minVersion = Json::parseStringProperty(asset, "minVersion", false); |
|
|
|
|
|
|
|
|
|
if (copyright) m_model.asset.copyright = copyright.value(); |
|
|
|
|
if (generator) m_model.asset.generator = generator.value(); |
|
|
|
|
if (version) m_model.asset.version = version.value(); |
|
|
|
|
if (minVersion) m_model.asset.minVersion = minVersion.value(); |
|
|
|
|
} |
|
|
|
|
ASSERT(Json::hasProperty(json, "asset"), "GlTF model missing required property 'asset'"); |
|
|
|
|
auto asset = json["asset"]; |
|
|
|
|
ASSERT(asset.is_object(), "Gltf model invalid property type 'asset'"); |
|
|
|
|
|
|
|
|
|
parseAsset(&m_model.asset, asset); |
|
|
|
|
|
|
|
|
|
// Scene
|
|
|
|
|
// ---------------------------------
|
|
|
|
@ -45,7 +34,7 @@ namespace Inferno {
|
|
|
|
|
if (Json::hasProperty(json, "scenes")) { |
|
|
|
|
|
|
|
|
|
auto scenes = json["scenes"]; |
|
|
|
|
ASSERT(scenes.is_array(), "GlTF model property 'scenes' invalid type"); |
|
|
|
|
ASSERT(scenes.is_array(), "Gltf model invalid property type 'scenes'"); |
|
|
|
|
|
|
|
|
|
for (auto& [key, object] : scenes.items()) { |
|
|
|
|
glTF::Scene scene; |
|
|
|
@ -57,13 +46,25 @@ namespace Inferno {
|
|
|
|
|
// Node
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
if (Json::hasProperty(json, "nodes")) { |
|
|
|
|
|
|
|
|
|
auto nodes = json["nodes"]; |
|
|
|
|
ASSERT(nodes.is_array(), "Gltf model invalid property type 'nodes'"); |
|
|
|
|
|
|
|
|
|
for (auto& [key, object] : nodes.items()) { |
|
|
|
|
glTF::Node node; |
|
|
|
|
parseNode(&node, key, object); |
|
|
|
|
m_model.nodes.emplace_back(std::move(node)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Mesh
|
|
|
|
|
// ---------------------------------
|
|
|
|
|
|
|
|
|
|
if (Json::hasProperty(json, "meshes")) { |
|
|
|
|
|
|
|
|
|
auto meshes = json["meshes"]; |
|
|
|
|
ASSERT(meshes.is_array(), "GlTF model property 'meshes' invalid type"); |
|
|
|
|
ASSERT(meshes.is_array(), "Gltf model invalid property type 'meshes'"); |
|
|
|
|
|
|
|
|
|
for (auto& [key, object] : meshes.items()) { |
|
|
|
|
glTF::Mesh mesh; |
|
|
|
@ -78,7 +79,7 @@ namespace Inferno {
|
|
|
|
|
if (Json::hasProperty(json, "accessors")) { |
|
|
|
|
|
|
|
|
|
auto accessors = json["accessors"]; |
|
|
|
|
ASSERT(accessors.is_array(), "GlTF model property 'accessors' invalid type"); |
|
|
|
|
ASSERT(accessors.is_array(), "Gltf model invalid property type 'accessors'"); |
|
|
|
|
|
|
|
|
|
for (auto& [key, object] : accessors.items()) { |
|
|
|
|
glTF::Accessor accessor; |
|
|
|
@ -93,7 +94,7 @@ namespace Inferno {
|
|
|
|
|
if (Json::hasProperty(json, "bufferViews")) { |
|
|
|
|
|
|
|
|
|
auto bufferViews = json["bufferViews"]; |
|
|
|
|
ASSERT(bufferViews.is_array(), "GlTF model property 'bufferViews' invalid type"); |
|
|
|
|
ASSERT(bufferViews.is_array(), "Gltf model invalid property type 'bufferViews'"); |
|
|
|
|
|
|
|
|
|
for (auto& [key, object] : bufferViews.items()) { |
|
|
|
|
glTF::BufferView bufferView; |
|
|
|
@ -108,7 +109,7 @@ namespace Inferno {
|
|
|
|
|
if (Json::hasProperty(json, "buffers")) { |
|
|
|
|
|
|
|
|
|
auto buffers = json["buffers"]; |
|
|
|
|
ASSERT(buffers.is_array(), "GlTF model property 'buffers' invalid type"); |
|
|
|
|
ASSERT(buffers.is_array(), "Gltf model invalid property type 'buffers'"); |
|
|
|
|
|
|
|
|
|
for (auto& [key, object] : buffers.items()) { |
|
|
|
|
glTF::Buffer buffer; |
|
|
|
@ -122,6 +123,24 @@ namespace Inferno {
|
|
|
|
|
{ |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Gltf::parseAsset(glTF::Asset* asset, const json& object) |
|
|
|
|
{ |
|
|
|
|
auto copyright = Json::parseStringProperty(object, "copyright", false); |
|
|
|
|
|
|
|
|
|
auto generator = Json::parseStringProperty(object, "generator", false); |
|
|
|
|
|
|
|
|
|
auto version = Json::parseStringProperty(object, "version", true); |
|
|
|
|
ASSERT(version, "GlTF model missing required property 'version'"); |
|
|
|
|
ASSERT(version.value().compare("2.0") == 0, "GlTF version unsupported '{}'", version.value()); |
|
|
|
|
|
|
|
|
|
auto minVersion = Json::parseStringProperty(object, "minVersion", false); |
|
|
|
|
|
|
|
|
|
if (copyright) asset->copyright = copyright.value(); |
|
|
|
|
if (generator) asset->generator = generator.value(); |
|
|
|
|
if (version) asset->version = version.value(); |
|
|
|
|
if (minVersion) asset->minVersion = minVersion.value(); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Gltf::parseScene(glTF::Scene* scene, const std::string& key, const json& object) |
|
|
|
|
{ |
|
|
|
|
auto nodes = Json::parseDoubleArrayProperty(object, "nodes", false); |
|
|
|
@ -132,10 +151,50 @@ namespace Inferno {
|
|
|
|
|
scene->name = name ? name.value() : key; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Gltf::parseNode(glTF::Node* node, const std::string& key, const json& object) |
|
|
|
|
{ |
|
|
|
|
auto camera = Json::parseUnsignedProperty(object, "camera", false); |
|
|
|
|
|
|
|
|
|
auto children = Json::parseUnsignedArrayProperty(object, "children", false); |
|
|
|
|
ASSERT(!children || children.value().size() > 0, "Gltf node '{}' empty property 'children'", key); |
|
|
|
|
|
|
|
|
|
auto skin = Json::parseUnsignedProperty(object, "skin", false); |
|
|
|
|
|
|
|
|
|
auto matrix = Json::parseDoubleArrayProperty(object, "matrix", false); |
|
|
|
|
ASSERT(!matrix || matrix.value().size() == 16, "Gltf node '{}' property 'matrix' invalid size", key); |
|
|
|
|
|
|
|
|
|
auto mesh = Json::parseUnsignedProperty(object, "mesh", false); |
|
|
|
|
|
|
|
|
|
auto rotation = Json::parseDoubleArrayProperty(object, "rotation", false); |
|
|
|
|
ASSERT(!rotation || rotation.value().size() == 4, "Gltf node '{}' property 'rotation' invalid size", key); |
|
|
|
|
|
|
|
|
|
auto scale = Json::parseDoubleArrayProperty(object, "scale", false); |
|
|
|
|
ASSERT(!scale || scale.value().size() == 3, "Gltf node '{}' property 'scale' invalid size", key); |
|
|
|
|
|
|
|
|
|
auto translation = Json::parseDoubleArrayProperty(object, "translation", false); |
|
|
|
|
ASSERT(!translation || translation.value().size() == 3, "Gltf node '{}' property 'translation' invalid size", key); |
|
|
|
|
|
|
|
|
|
auto weights = Json::parseDoubleArrayProperty(object, "weights", false); |
|
|
|
|
ASSERT(!weights || weights.value().size() > 0, "Gltf node '{}' empty property 'weights'", key); |
|
|
|
|
|
|
|
|
|
auto name = Json::parseStringProperty(object, "name", false); |
|
|
|
|
|
|
|
|
|
if (camera) node->camera = camera.value(); |
|
|
|
|
if (children) node->children = children.value(); |
|
|
|
|
if (skin) node->skin = skin.value(); |
|
|
|
|
if (matrix) std::copy(matrix.value().begin(), matrix.value().end(), node->matrix.begin()); |
|
|
|
|
if (mesh) node->mesh = mesh.value(); |
|
|
|
|
if (rotation) std::copy(rotation.value().begin(), rotation.value().end(), node->rotation.begin()); |
|
|
|
|
if (scale) std::copy(scale.value().begin(), scale.value().end(), node->scale.begin()); |
|
|
|
|
if (translation) std::copy(translation.value().begin(), translation.value().end(), node->translation.begin()); |
|
|
|
|
if (weights) node->weights = weights.value(); |
|
|
|
|
node->name = name ? name.value() : key; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
void Gltf::parsePrimitive(glTF::Primitive* primitive, const std::string& key, const json& object) |
|
|
|
|
{ |
|
|
|
|
auto attributes = Json::parseUnsignedObjectProperty(object, "attributes", true); |
|
|
|
|
ASSERT(attributes && attributes.value().size() > 0, "Gltf primitive '{}' invalid property 'attributes'", key); |
|
|
|
|
ASSERT(attributes && attributes.value().size() > 0, "Gltf primitive '{}' empty property 'attributes'", key); |
|
|
|
|
|
|
|
|
|
auto indices = Json::parseUnsignedProperty(object, "indices", false); |
|
|
|
|
|
|
|
|
@ -181,7 +240,7 @@ namespace Inferno {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
auto weights = Json::parseDoubleArrayProperty(object, "weights", false); |
|
|
|
|
ASSERT(!weights || weights.value().size() > 0, "Gltf mesh '{}' empty 'weights' property", key); |
|
|
|
|
ASSERT(!weights || weights.value().size() > 0, "Gltf mesh '{}' empty property 'weights'", key); |
|
|
|
|
|
|
|
|
|
auto name = Json::parseStringProperty(object, "name", false); |
|
|
|
|
|
|
|
|
@ -207,10 +266,10 @@ namespace Inferno {
|
|
|
|
|
ASSERT(type, "Gltf accessor '{}' missing required property 'type'", key); |
|
|
|
|
|
|
|
|
|
auto max = Json::parseDoubleArrayProperty(object, "max", false); |
|
|
|
|
ASSERT(!max || max.value().size() > 0, "Gltf accessor '{}' empty 'max' property", key); |
|
|
|
|
ASSERT(!max || max.value().size() > 0, "Gltf accessor '{}' empty property 'max'", key); |
|
|
|
|
|
|
|
|
|
auto min = Json::parseDoubleArrayProperty(object, "min", false); |
|
|
|
|
ASSERT(!min || min.value().size() > 0, "Gltf accessor '{}' empty 'min' property", key); |
|
|
|
|
ASSERT(!min || min.value().size() > 0, "Gltf accessor '{}' empty property 'min'", key); |
|
|
|
|
|
|
|
|
|
auto name = Json::parseStringProperty(object, "name", false); |
|
|
|
|
|
|
|
|
|