diff --git a/README.md b/README.md index 8854fec..dc57690 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,7 @@ ## License -TinyGLTFLoader is licensed under 2-clause BSD. +TinyGLTFLoader is licensed under MIT license. TinyGLTFLoader uses the following third party libraries. diff --git a/loader_example.cc b/loader_example.cc index 6cb730d..23337e4 100644 --- a/loader_example.cc +++ b/loader_example.cc @@ -200,7 +200,7 @@ static std::string PrintStringArray(const std::vector &arr) { return ss.str(); } -static std::string Indent(int indent) { +static std::string Indent(const int indent) { std::string s; for (int i = 0; i < indent; i++) { s += " "; @@ -217,6 +217,30 @@ static std::string PrintParameterValue(const tinygltf::Parameter ¶m) { } } +static std::string PrintValue(const std::string& name, const tinygltf::Value &value, const int indent) { + std::stringstream ss; + + if (value.IsObject()) { + const tinygltf::Value::Object& o = value.Get(); + tinygltf::Value::Object::const_iterator it(o.begin()); + tinygltf::Value::Object::const_iterator itEnd(o.end()); + for (; it != itEnd; it++) { + ss << PrintValue(name, it->second, indent + 1); + } + } else if (value.IsString()) { + ss << Indent(indent) << name << " : " << value.Get() << std::endl; + } else if (value.IsBool()) { + ss << Indent(indent) << name << " : " << value.Get() << std::endl; + } else if (value.IsNumber()) { + ss << Indent(indent) << name << " : " << value.Get() << std::endl; + } else if (value.IsInt()) { + ss << Indent(indent) << name << " : " << value.Get() << std::endl; + } + // @todo { binary, array } + + return ss.str(); +} + static void DumpNode(const tinygltf::Node &node, int indent) { std::cout << Indent(indent) << "name : " << node.name << std::endl; std::cout << Indent(indent) << "camera : " << node.camera << std::endl; @@ -266,6 +290,10 @@ static void DumpPrimitive(const tinygltf::Primitive &primitive, int indent) { << "attributes(items=" << primitive.attributes.size() << ")" << std::endl; DumpStringMap(primitive.attributes, indent + 1); + + std::cout << Indent(indent) + << "extras :" << std::endl + << PrintValue("extras", primitive.extras, indent+1) << std::endl; } static void DumpTechniqueParameter(const tinygltf::TechniqueParameter ¶m, diff --git a/tiny_gltf_loader.h b/tiny_gltf_loader.h index e6e7113..61557c5 100644 --- a/tiny_gltf_loader.h +++ b/tiny_gltf_loader.h @@ -1,36 +1,31 @@ // // Tiny glTF loader. // -// Copyright (c) 2015-2016, Syoyo Fujita and many contributors. -// All rights reserved. -// (Licensed under 2-clause BSD liecense) // -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are met: +// The MIT License (MIT) // -// 1. Redistributions of source code must retain the above copyright notice, -// this -// list of conditions and the following disclaimer. -// 2. Redistributions in binary form must reproduce the above copyright notice, -// this list of conditions and the following disclaimer in the documentation -// and/or other materials provided with the distribution. +// Copyright (c) 2015 - 2016 Syoyo Fujita and many contributors. // -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -// AND -// ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED -// WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -// DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE -// FOR -// ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -// DAMAGES -// (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; -// LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND -// ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS -// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: // +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. // +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + // Version: +// - v0.9.5 Support parsing `extras` parameter. // - v0.9.4 Support parsing `shader`, `program` and `tecnique` thanks to // @lukesanantonio // - v0.9.3 Support binary glTF @@ -38,7 +33,7 @@ // - v0.9.1 Support loading glTF asset from memory // - v0.9.0 Initial // -// Tiny glTF loader is using following libraries: +// Tiny glTF loader is using following third party libraries: // // - picojson: C++ JSON library. // - base64: base64 decode/encode library. @@ -47,6 +42,7 @@ #ifndef TINY_GLTF_LOADER_H_ #define TINY_GLTF_LOADER_H_ +#include #include #include #include @@ -140,6 +136,139 @@ namespace tinygltf { #define TINYGLTF_SHADER_TYPE_VERTEX_SHADER (35633) #define TINYGLTF_SHADER_TYPE_FRAGMENT_SHADER (35632) +typedef enum { + NULL_TYPE = 0, + NUMBER_TYPE = 1, + INT_TYPE = 2, + BOOL_TYPE = 3, + STRING_TYPE = 4, + ARRAY_TYPE = 5, + BINARY_TYPE = 6, + OBJECT_TYPE = 7 +} Type; + +// Simple class to represent JSON object +class Value { + public: + typedef std::vector Array; + typedef std::map Object; + + Value() : type_(NULL_TYPE) {} + + explicit Value(bool b) : type_(BOOL_TYPE) { boolean_value_ = b; } + explicit Value(int64_t i) : type_(INT_TYPE) { int64_value_ = i; } + explicit Value(double n) : type_(NUMBER_TYPE) { number_value_ = n; } + explicit Value(const std::string &s) : type_(STRING_TYPE) { + string_value_ = s; + } + explicit Value(const uint8_t *p, uint64_t n) : type_(BINARY_TYPE) { + binary_value_.resize(n); + memcpy(binary_value_.data(), p, n); + } + explicit Value(const Array &a) : type_(ARRAY_TYPE) { + array_value_ = Array(a); + } + explicit Value(const Object &o) : type_(OBJECT_TYPE) { + object_value_ = Object(o); + } + ~Value() {} + + char Type() const { return static_cast(type_); } + + bool IsBool() const { return (type_ == BOOL_TYPE); } + + bool IsInt() const { return (type_ == INT_TYPE); } + + bool IsNumber() const { return (type_ == NUMBER_TYPE); } + + bool IsString() const { return (type_ == STRING_TYPE); } + + bool IsBinary() const { return (type_ == BINARY_TYPE); } + + bool IsArray() const { return (type_ == ARRAY_TYPE); } + + bool IsObject() const { return (type_ == OBJECT_TYPE); } + + // Accessor + template + const T &Get() const; + template + T &Get(); + + // Lookup value from an array + const Value &Get(int64_t idx) const { + static Value &null_value = *(new Value()); + assert(IsArray()); + assert(idx >= 0); + return (static_cast(idx) < array_value_.size()) + ? array_value_[static_cast(idx)] + : null_value; + } + + // Lookup value from a key-value pair + const Value &Get(const std::string &key) const { + static Value &null_value = *(new Value()); + assert(IsObject()); + Object::const_iterator it = object_value_.find(key); + return (it != object_value_.end()) ? it->second : null_value; + } + + size_t ArrayLen() const { + if (!IsArray()) return 0; + return array_value_.size(); + } + + // Valid only for object type. + bool Has(const std::string &key) const { + if (!IsObject()) return false; + Object::const_iterator it = object_value_.find(key); + return (it != object_value_.end()) ? true : false; + } + + // List keys + std::vector Keys() const { + std::vector keys; + if (!IsObject()) return keys; // empty + + for (Object::const_iterator it = object_value_.begin(); + it != object_value_.end(); ++it) { + keys.push_back(it->first); + } + + return keys; + } + + protected: + int64_t int64_value_; + double number_value_; + std::string string_value_; + std::vector binary_value_; + Array array_value_; + Object object_value_; + bool boolean_value_; + char pad[3]; + + int type_; +}; + +#define TINYGLTF_VALUE_GET(ctype, var) \ + template <> \ + inline const ctype &Value::Get() const { \ + return var; \ + } \ + template <> \ + inline ctype &Value::Get() { \ + return var; \ + } +TINYGLTF_VALUE_GET(bool, boolean_value_) +TINYGLTF_VALUE_GET(double, number_value_) +TINYGLTF_VALUE_GET(int64_t, int64_value_) +TINYGLTF_VALUE_GET(std::string, string_value_) +TINYGLTF_VALUE_GET(std::vector, binary_value_) +TINYGLTF_VALUE_GET(Value::Array, array_value_) +TINYGLTF_VALUE_GET(Value::Object, object_value_) +#undef TINYGLTF_VALUE_GET + typedef struct { std::string string_value; std::vector number_array; @@ -151,12 +280,14 @@ typedef struct { std::string sampler; std::string target_id; std::string target_path; + Value extras; } AnimationChannel; typedef struct { std::string input; std::string interpolation; std::string output; + Value extras; } AnimationSampler; typedef struct { @@ -164,6 +295,7 @@ typedef struct { std::vector channels; std::map samplers; ParameterMap parameters; + Value extras; } Animation; typedef struct { @@ -174,6 +306,7 @@ typedef struct { int wrapT; int wrapR; // TinyGLTF extension int pad0; + Value extras; } Sampler; typedef struct { @@ -186,6 +319,8 @@ typedef struct { std::string bufferView; // KHR_binary_glTF extenstion. std::string mimeType; // KHR_binary_glTF extenstion. + + Value extras; } Image; typedef struct { @@ -196,12 +331,15 @@ typedef struct { int target; int type; std::string name; + Value extras; } Texture; typedef struct { std::string name; std::string technique; ParameterMap values; + + Value extras; } Material; typedef struct { @@ -211,6 +349,7 @@ typedef struct { size_t byteLength; // default: 0 int target; int pad0; + Value extras; } BufferView; typedef struct { @@ -225,6 +364,7 @@ typedef struct { int pad1; std::vector minValues; // Optional std::vector maxValues; // Optional + Value extras; } Accessor; class Camera { @@ -252,11 +392,14 @@ typedef struct { std::string indices; // The ID of the accessor that contains the indices. int mode; // one of TINYGLTF_MODE_*** int pad0; + + Value extras; // "extra" property } Primitive; typedef struct { std::string name; std::vector primitives; + Value extras; } Mesh; class Node { @@ -273,11 +416,14 @@ class Node { std::vector translation; // length must be 0 or 3 std::vector matrix; // length must be 0 or 16 std::vector meshes; + + Value extras; }; typedef struct { std::string name; std::vector data; + Value extras; } Buffer; typedef struct { @@ -285,6 +431,8 @@ typedef struct { int type; int pad0; std::vector source; + + Value extras; } Shader; typedef struct { @@ -292,6 +440,8 @@ typedef struct { std::string vertexShader; std::string fragmentShader; std::vector attributes; + + Value extras; } Program; typedef struct { @@ -310,6 +460,8 @@ typedef struct { std::map parameters; std::map attributes; std::map uniforms; + + Value extras; } Technique; typedef struct { @@ -319,6 +471,7 @@ typedef struct { std::string profile_version; bool premultipliedAlpha; char pad[7]; + Value extras; } Asset; class Scene { @@ -344,6 +497,8 @@ class Scene { std::string defaultScene; Asset asset; + + Value extras; }; enum SectionCheck { @@ -411,11 +566,11 @@ class TinyGLTFLoader { #ifdef TINYGLTF_LOADER_IMPLEMENTATION #include -#include +//#include #include #include -#ifdef TINYGLTF_APPLY_CLANG_WEVERYTHING +#ifdef __clang__ // Disable some warnings for external files. #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wfloat-equal" @@ -429,9 +584,10 @@ class TinyGLTFLoader { #pragma clang diagnostic ignored "-Wpadded" #endif +#define PICOJSON_USE_INT64 #include "./picojson.h" #include "./stb_image.h" -#ifdef TINYGLTF_APPLY_CLANG_WEVERYTHING +#ifdef __clang__ #pragma clang diagnostic pop #endif @@ -603,7 +759,7 @@ std::string base64_decode(std::string const &s); */ -#ifdef TINYGLTF_APPLY_CLANG_WEVERYTHING +#ifdef __clang__ #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wexit-time-destructors" #pragma clang diagnostic ignored "-Wglobal-constructors" @@ -664,7 +820,7 @@ std::string base64_decode(std::string const &encoded_string) { return ret; } -#ifdef TINYGLTF_APPLY_CLANG_WEVERYTHING +#ifdef __clang__ #pragma clang diagnostic pop #endif @@ -838,6 +994,48 @@ static bool DecodeDataURI(std::vector *out, return true; } +static void ParseObjectProperty(Value *ret, const picojson::object &o) { + tinygltf::Value::Object vo; + picojson::object::const_iterator it(o.begin()); + picojson::object::const_iterator itEnd(o.end()); + + for (; it != itEnd; it++) { + picojson::value v = it->second; + + if (v.is()) { + vo[it->first] = tinygltf::Value(v.get()); + } else if (v.is()) { + vo[it->first] = tinygltf::Value(v.get()); + } else if (v.is()) { + vo[it->first] = tinygltf::Value(v.get()); + } else if (v.is()) { + vo[it->first] = tinygltf::Value(v.get()); + } else if (v.is()) { + tinygltf::Value child_value; + ParseObjectProperty(&child_value, v.get()); + } + // TODO(syoyo) binary, array + } + + (*ret) = tinygltf::Value(vo); +} + +static bool ParseExtrasProperty(Value *ret, const picojson::object &o) { + picojson::object::const_iterator it = o.find("extras"); + if (it == o.end()) { + return false; + } + + // FIXME(syoyo) Currently we only support `object` type for extras property. + if (!it->second.is()) { + return false; + } + + ParseObjectProperty(ret, it->second.get()); + + return true; +} + static bool ParseBooleanProperty(bool *ret, std::string *err, const picojson::object &o, const std::string &property, bool required) { @@ -1480,6 +1678,8 @@ static bool ParseAccessor(Accessor *accessor, std::string *err, } } + ParseExtrasProperty(&(accessor->extras), o); + return true; } @@ -1509,6 +1709,8 @@ static bool ParsePrimitive(Primitive *primitive, std::string *err, ParseStringMapProperty(&primitive->attributes, err, o, "attributes", false); + ParseExtrasProperty(&(primitive->extras), o); + return true; } @@ -1530,6 +1732,8 @@ static bool ParseMesh(Mesh *mesh, std::string *err, const picojson::object &o) { } } + ParseExtrasProperty(&(mesh->extras), o); + return true; } @@ -1560,6 +1764,8 @@ static bool ParseNode(Node *node, std::string *err, const picojson::object &o) { } } + ParseExtrasProperty(&(node->extras), o); + return true; } @@ -1617,6 +1823,8 @@ static bool ParseMaterial(Material *material, std::string *err, } } + ParseExtrasProperty(&(material->extras), o); + return true; } @@ -1706,6 +1914,8 @@ static bool ParseShader(Shader *shader, std::string *err, shader->type = static_cast(type); + ParseExtrasProperty(&(shader->extras), o); + return true; } @@ -1726,6 +1936,8 @@ static bool ParseProgram(Program *program, std::string *err, // really make sense without it. ParseStringArrayProperty(&program->attributes, err, o, "attributes", false); + ParseExtrasProperty(&(program->extras), o); + return true; } @@ -1788,6 +2000,8 @@ static bool ParseTechnique(Technique *technique, std::string *err, } } + ParseExtrasProperty(&(technique->extras), o); + return true; } @@ -1822,6 +2036,8 @@ static bool ParseAnimationChannel(AnimationChannel *channel, std::string *err, } } + ParseExtrasProperty(&(channel->extras), o); + return true; } @@ -1903,6 +2119,8 @@ static bool ParseAnimation(Animation *animation, std::string *err, } ParseStringProperty(&animation->name, err, o, "name", false); + ParseExtrasProperty(&(animation->extras), o); + return true; } @@ -1925,6 +2143,8 @@ static bool ParseSampler(Sampler *sampler, std::string *err, sampler->wrapS = static_cast(wrapS); sampler->wrapT = static_cast(wrapT); + ParseExtrasProperty(&(sampler->extras), o); + return true; }