diff --git a/tiny_gltf_loader.h b/tiny_gltf_loader.h index 0643d0a..7c9bd4e 100644 --- a/tiny_gltf_loader.h +++ b/tiny_gltf_loader.h @@ -312,6 +312,18 @@ typedef struct { Value extras; } Animation; +struct Skin { + std::string name; + int inverseBindMatrices; // required here but not in the spec + int skeleton; // The index of the node used as a skeleton root + std::vector joints; // Indices of skeleton nodes + + Skin() + { + inverseBindMatrices = -1; + } +}; + struct Sampler { std::string name; int minFilter; // ["NEAREST", "LINEAR", "NEAREST_MIPMAP_LINEAR", "LINEAR_MIPMAP_NEAREST", "NEAREST_MIPMAP_LINEAR", "LINEAR_MIPMAP_LINEAR"] @@ -455,7 +467,8 @@ class Node { public: Node() { - mesh = -1; + mesh = -1, + skin = -1; } ~Node() {} @@ -463,6 +476,7 @@ class Node { int camera; // the index of the camera referenced by this node std::string name; + int skin; int mesh; std::vector children; std::vector rotation; // length must be 0 or 4 @@ -512,6 +526,7 @@ class Model { std::vector nodes; std::vector textures; std::vector images; + std::vector skins; std::vector samplers; std::vector scenes; @@ -1759,6 +1774,10 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const picojson::object &o) { static bool ParseNode(Node *node, std::string *err, const picojson::object &o) { ParseStringProperty(&node->name, err, o, "name", false); + double skin = -1.0; + ParseNumberProperty(&skin, err, o, "skin", false); + node->skin = static_cast(skin); + // Matrix and T/R/S are exclusive if(!ParseNumberArrayProperty(&node->matrix, err, o, "matrix", false)) { @@ -2031,6 +2050,29 @@ static bool ParseSampler(Sampler *sampler, std::string *err, return true; } +static bool ParseSkin(Skin *skin, std::string *err, + const picojson::object &o) { + + ParseStringProperty(&skin->name, err, o, "name", false); + + std::vector joints; + if (!ParseNumberArrayProperty(&joints, err, o, "joints", false)) { + return false; + } + + double skeleton; + ParseNumberProperty(&skeleton, err, o, "skeleton", false); + skin->skeleton = static_cast(skeleton); + + skin->joints = std::vector(joints.begin(), joints.end()); + + double invBind = -1.0; + ParseNumberProperty(&invBind, err, o, "inverseBindMatrices", true); + skin->inverseBindMatrices = static_cast(invBind); + + return true; +} + bool TinyGLTFLoader::LoadFromString(Model *model, std::string *err, const char *str, unsigned int length, const std::string &base_dir, @@ -2314,8 +2356,8 @@ if (v.contains("scenes") && v.get("scenes").is()) { } // 11. Parse Animation - if (v.contains("animations") && v.get("animations").is()) { - const picojson::object &root = v.get("animations").get(); + if (v.contains("animations") && v.get("animations").is()) { + const picojson::array &root = v.get("animations").get(); picojson::array::const_iterator it(root.begin()); picojson::array::const_iterator itEnd(root.end()); @@ -2330,7 +2372,24 @@ if (v.contains("scenes") && v.get("scenes").is()) { } } - // 12. Parse Sampler + // 12. Parse Skin + if (v.contains("skins") && v.get("skins").is()) { + const picojson::array &root = v.get("skins").get(); + + picojson::array::const_iterator it(root.begin()); + picojson::array::const_iterator itEnd(root.end()); + for (; it != itEnd; ++it) { + Skin skin; + if (!ParseSkin(&skin, err, + it->get())) { + return false; + } + + model->skins.push_back(skin); + } + } + + // 13. Parse Sampler if (v.contains("samplers") && v.get("samplers").is()) { const picojson::array &root = v.get("samplers").get();