ソースを参照

Move duplicate code to glFT common header.

Kim Kulling 4 年 前
コミット
0fef0e1101

+ 778 - 861
code/AssetLib/glTF/glTFAsset.h

@@ -51,14 +51,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF1_IMPORTER)
 
+#include "glTFCommon.h"
 #include <assimp/Exceptional.h>
-
+#include <algorithm>
+#include <list>
 #include <map>
+#include <stdexcept>
 #include <string>
-#include <list>
 #include <vector>
-#include <algorithm>
-#include <stdexcept>
+
+// clang-format off
 
 #if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0)
 #pragma GCC diagnostic push
@@ -99,198 +101,205 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #   endif
 #endif
 
+// clang-format on
+
 #include "AssetLib/glTF/glTFCommon.h"
 
 namespace glTF {
-    using glTFCommon::shared_ptr;
-    using glTFCommon::IOSystem;
-    using glTFCommon::IOStream;
-
-    using rapidjson::Value;
-    using rapidjson::Document;
-
-    class Asset;
-    class AssetWriter;
-
-    struct BufferView; // here due to cross-reference
-    struct Texture;
-    struct Light;
-    struct Skin;
-
-    using glTFCommon::vec3;
-    using glTFCommon::vec4;
-    using glTFCommon::mat4;
-
-    //! Magic number for GLB files
-    #define AI_GLB_MAGIC_NUMBER "glTF"
-
-    #ifdef ASSIMP_API
-        #include <assimp/Compiler/pushpack1.h>
-    #endif
-
-    //! For the KHR_binary_glTF extension (binary .glb file)
-    //! 20-byte header (+ the JSON + a "body" data section)
-    struct GLB_Header {
-        uint8_t magic[4];     //!< Magic number: "glTF"
-        uint32_t version;     //!< Version number (always 1 as of the last update)
-        uint32_t length;      //!< Total length of the Binary glTF, including header, scene, and body, in bytes
-        uint32_t sceneLength; //!< Length, in bytes, of the glTF scene
-        uint32_t sceneFormat; //!< Specifies the format of the glTF scene (see the SceneFormat enum)
-    } PACK_STRUCT;
-
-    #ifdef ASSIMP_API
-        #include <assimp/Compiler/poppack1.h>
-    #endif
-
-
-    //! Values for the GLB_Header::sceneFormat field
-    enum SceneFormat {
-        SceneFormat_JSON = 0
-    };
 
-    //! Values for the mesh primitive modes
-    enum PrimitiveMode {
-        PrimitiveMode_POINTS = 0,
-        PrimitiveMode_LINES = 1,
-        PrimitiveMode_LINE_LOOP = 2,
-        PrimitiveMode_LINE_STRIP = 3,
-        PrimitiveMode_TRIANGLES = 4,
-        PrimitiveMode_TRIANGLE_STRIP = 5,
-        PrimitiveMode_TRIANGLE_FAN = 6
-    };
+using glTFCommon::IOStream;
+using glTFCommon::IOSystem;
+using glTFCommon::Nullable;
+using glTFCommon::Ref;
+using glTFCommon::shared_ptr;
 
-    //! Values for the Accessor::componentType field
-    enum ComponentType {
-        ComponentType_BYTE = 5120,
-        ComponentType_UNSIGNED_BYTE = 5121,
-        ComponentType_SHORT = 5122,
-        ComponentType_UNSIGNED_SHORT = 5123,
-        ComponentType_UNSIGNED_INT = 5125,
-        ComponentType_FLOAT = 5126
-    };
-
-    inline unsigned int ComponentTypeSize(ComponentType t) {
-        switch (t) {
-            case ComponentType_SHORT:
-            case ComponentType_UNSIGNED_SHORT:
-                return 2;
-
-            case ComponentType_UNSIGNED_INT:
-            case ComponentType_FLOAT:
-                return 4;
-
-            case ComponentType_BYTE:
-            case ComponentType_UNSIGNED_BYTE:
-                return 1;
-            default:
-                std::string err = "GLTF: Unsupported Component Type ";
-                err += std::to_string( t );
-                throw DeadlyImportError(err);
-        }
-    }
-
-    //! Values for the BufferView::target field
-    enum BufferViewTarget {
-        BufferViewTarget_NONE = 0,
-        BufferViewTarget_ARRAY_BUFFER = 34962,
-        BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
-    };
+using rapidjson::Document;
+using rapidjson::Value;
 
-    //! Values for the Sampler::magFilter field
-    enum SamplerMagFilter {
-        SamplerMagFilter_Nearest = 9728,
-        SamplerMagFilter_Linear = 9729
-    };
+class Asset;
+class AssetWriter;
 
-    //! Values for the Sampler::minFilter field
-    enum SamplerMinFilter {
-        SamplerMinFilter_Nearest = 9728,
-        SamplerMinFilter_Linear = 9729,
-        SamplerMinFilter_Nearest_Mipmap_Nearest = 9984,
-        SamplerMinFilter_Linear_Mipmap_Nearest = 9985,
-        SamplerMinFilter_Nearest_Mipmap_Linear = 9986,
-        SamplerMinFilter_Linear_Mipmap_Linear = 9987
-    };
+struct BufferView; // here due to cross-reference
+struct Texture;
+struct Light;
+struct Skin;
 
-    //! Values for the Sampler::wrapS and Sampler::wrapT field
-    enum SamplerWrap {
-        SamplerWrap_Clamp_To_Edge = 33071,
-        SamplerWrap_Mirrored_Repeat = 33648,
-        SamplerWrap_Repeat = 10497
-    };
+using glTFCommon::mat4;
+using glTFCommon::vec3;
+using glTFCommon::vec4;
 
-    //! Values for the Texture::format and Texture::internalFormat fields
-    enum TextureFormat
-    {
-        TextureFormat_ALPHA = 6406,
-        TextureFormat_RGB = 6407,
-        TextureFormat_RGBA = 6408,
-        TextureFormat_LUMINANCE = 6409,
-        TextureFormat_LUMINANCE_ALPHA = 6410
-    };
+//! Magic number for GLB files
+#define AI_GLB_MAGIC_NUMBER "glTF"
 
-    //! Values for the Texture::target field
-    enum TextureTarget
-    {
-        TextureTarget_TEXTURE_2D = 3553
-    };
+// clang-format off
+#ifdef ASSIMP_API
+#   include <assimp/Compiler/pushpack1.h>
+#endif
+// clang-format on
+
+//! For the KHR_binary_glTF extension (binary .glb file)
+//! 20-byte header (+ the JSON + a "body" data section)
+struct GLB_Header {
+    uint8_t magic[4]; //!< Magic number: "glTF"
+    uint32_t version; //!< Version number (always 1 as of the last update)
+    uint32_t length; //!< Total length of the Binary glTF, including header, scene, and body, in bytes
+    uint32_t sceneLength; //!< Length, in bytes, of the glTF scene
+    uint32_t sceneFormat; //!< Specifies the format of the glTF scene (see the SceneFormat enum)
+} PACK_STRUCT;
+
+// clang-format off
+#ifdef ASSIMP_API
+#   include <assimp/Compiler/poppack1.h>
+#endif
+// clang-format on
+
+//! Values for the GLB_Header::sceneFormat field
+enum SceneFormat {
+    SceneFormat_JSON = 0
+};
+
+//! Values for the mesh primitive modes
+enum PrimitiveMode {
+    PrimitiveMode_POINTS = 0,
+    PrimitiveMode_LINES = 1,
+    PrimitiveMode_LINE_LOOP = 2,
+    PrimitiveMode_LINE_STRIP = 3,
+    PrimitiveMode_TRIANGLES = 4,
+    PrimitiveMode_TRIANGLE_STRIP = 5,
+    PrimitiveMode_TRIANGLE_FAN = 6
+};
+
+//! Values for the Accessor::componentType field
+enum ComponentType {
+    ComponentType_BYTE = 5120,
+    ComponentType_UNSIGNED_BYTE = 5121,
+    ComponentType_SHORT = 5122,
+    ComponentType_UNSIGNED_SHORT = 5123,
+    ComponentType_UNSIGNED_INT = 5125,
+    ComponentType_FLOAT = 5126
+};
+
+inline unsigned int ComponentTypeSize(ComponentType t) {
+    switch (t) {
+    case ComponentType_SHORT:
+    case ComponentType_UNSIGNED_SHORT:
+        return 2;
+
+    case ComponentType_UNSIGNED_INT:
+    case ComponentType_FLOAT:
+        return 4;
+
+    case ComponentType_BYTE:
+    case ComponentType_UNSIGNED_BYTE:
+        return 1;
+    default:
+        std::string err = "GLTF: Unsupported Component Type ";
+        err += std::to_string(t);
+        throw DeadlyImportError(err);
+    }
+}
 
-    //! Values for the Texture::type field
-    enum TextureType
-    {
-        TextureType_UNSIGNED_BYTE = 5121,
-        TextureType_UNSIGNED_SHORT_5_6_5 = 33635,
-        TextureType_UNSIGNED_SHORT_4_4_4_4 = 32819,
-        TextureType_UNSIGNED_SHORT_5_5_5_1 = 32820
+//! Values for the BufferView::target field
+enum BufferViewTarget {
+    BufferViewTarget_NONE = 0,
+    BufferViewTarget_ARRAY_BUFFER = 34962,
+    BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
+};
+
+//! Values for the Sampler::magFilter field
+enum SamplerMagFilter {
+    SamplerMagFilter_Nearest = 9728,
+    SamplerMagFilter_Linear = 9729
+};
+
+//! Values for the Sampler::minFilter field
+enum SamplerMinFilter {
+    SamplerMinFilter_Nearest = 9728,
+    SamplerMinFilter_Linear = 9729,
+    SamplerMinFilter_Nearest_Mipmap_Nearest = 9984,
+    SamplerMinFilter_Linear_Mipmap_Nearest = 9985,
+    SamplerMinFilter_Nearest_Mipmap_Linear = 9986,
+    SamplerMinFilter_Linear_Mipmap_Linear = 9987
+};
+
+//! Values for the Sampler::wrapS and Sampler::wrapT field
+enum SamplerWrap {
+    SamplerWrap_Clamp_To_Edge = 33071,
+    SamplerWrap_Mirrored_Repeat = 33648,
+    SamplerWrap_Repeat = 10497
+};
+
+//! Values for the Texture::format and Texture::internalFormat fields
+enum TextureFormat {
+    TextureFormat_ALPHA = 6406,
+    TextureFormat_RGB = 6407,
+    TextureFormat_RGBA = 6408,
+    TextureFormat_LUMINANCE = 6409,
+    TextureFormat_LUMINANCE_ALPHA = 6410
+};
+
+//! Values for the Texture::target field
+enum TextureTarget {
+    TextureTarget_TEXTURE_2D = 3553
+};
+
+//! Values for the Texture::type field
+enum TextureType {
+    TextureType_UNSIGNED_BYTE = 5121,
+    TextureType_UNSIGNED_SHORT_5_6_5 = 33635,
+    TextureType_UNSIGNED_SHORT_4_4_4_4 = 32819,
+    TextureType_UNSIGNED_SHORT_5_5_5_1 = 32820
+};
+
+//! Values for the Accessor::type field (helper class)
+class AttribType {
+public:
+    enum Value { SCALAR,
+        VEC2,
+        VEC3,
+        VEC4,
+        MAT2,
+        MAT3,
+        MAT4 };
+
+private:
+    static const size_t NUM_VALUES = static_cast<size_t>(MAT4) + 1;
+
+    struct Info {
+        const char *name;
+        unsigned int numComponents;
     };
 
+    template <int N>
+    struct data { static const Info infos[NUM_VALUES]; };
 
-    //! Values for the Accessor::type field (helper class)
-    class AttribType
-    {
-    public:
-        enum Value
-            { SCALAR, VEC2, VEC3, VEC4, MAT2, MAT3, MAT4 };
-
-    private:
-        static const size_t NUM_VALUES = static_cast<size_t>(MAT4)+1;
-
-        struct Info
-            { const char* name; unsigned int numComponents; };
-
-        template<int N> struct data
-            { static const Info infos[NUM_VALUES]; };
-
-    public:
-        inline static Value FromString(const char* str)
-        {
-            for (size_t i = 0; i < NUM_VALUES; ++i) {
-                if (strcmp(data<0>::infos[i].name, str) == 0) {
-                    return static_cast<Value>(i);
-                }
+public:
+    inline static Value FromString(const char *str) {
+        for (size_t i = 0; i < NUM_VALUES; ++i) {
+            if (strcmp(data<0>::infos[i].name, str) == 0) {
+                return static_cast<Value>(i);
             }
-            return SCALAR;
         }
+        return SCALAR;
+    }
 
-        inline static const char* ToString(Value type)
-        {
-            return data<0>::infos[static_cast<size_t>(type)].name;
-        }
-
-        inline static unsigned int GetNumComponents(Value type)
-        {
-            return data<0>::infos[static_cast<size_t>(type)].numComponents;
-        }
-    };
-
-    // must match the order of the AttribTypeTraits::Value enum!
-    template<int N> const AttribType::Info
-    AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
-        { "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 }
-    };
+    inline static const char *ToString(Value type) {
+        return data<0>::infos[static_cast<size_t>(type)].name;
+    }
 
+    inline static unsigned int GetNumComponents(Value type) {
+        return data<0>::infos[static_cast<size_t>(type)].numComponents;
+    }
+};
 
+// must match the order of the AttribTypeTraits::Value enum!
+template <int N>
+const AttribType::Info
+        AttribType::data<N>::infos[AttribType::NUM_VALUES] = {
+            { "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 }
+        };
 
+/*
     //! A reference to one top-level object, which is valid
     //! until the Asset instance is destroyed
     template<class T>
@@ -314,834 +323,742 @@ namespace glTF {
 
         T& operator*()
             { return *((*vector)[index]); }
-    };
+    };*/
 
-    //! Helper struct to represent values that might not be present
-    template<class T>
-    struct Nullable
-    {
-        T value;
-        bool isPresent;
+//! Base class for all glTF top-level objects
+struct Object {
+    std::string id; //!< The globally unique ID used to reference this object
+    std::string name; //!< The user-defined name of this object
 
-        Nullable() : isPresent(false) {}
-        Nullable(T& val) : value(val), isPresent(true) {}
-    };
+    //! Objects marked as special are not exported (used to emulate the binary body buffer)
+    virtual bool IsSpecial() const { return false; }
 
+    virtual ~Object() {}
 
-    //! Base class for all glTF top-level objects
-    struct Object
-    {
-        std::string id;   //!< The globally unique ID used to reference this object
-        std::string name; //!< The user-defined name of this object
-
-        //! Objects marked as special are not exported (used to emulate the binary body buffer)
-        virtual bool IsSpecial() const
-            { return false; }
-
-        virtual ~Object() {}
-
-        //! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
-        static const char* TranslateId(Asset& /*r*/, const char* id)
-            { return id; }
-    };
+    //! Maps special IDs to another ID, where needed. Subclasses may override it (statically)
+    static const char *TranslateId(Asset & /*r*/, const char *id) { return id; }
+};
 
-    //
-    // Classes for each glTF top-level object type
-    //
+//
+// Classes for each glTF top-level object type
+//
 
-    //! A typed view into a BufferView. A BufferView contains raw binary data.
-    //! An accessor provides a typed view into a BufferView or a subset of a BufferView
-    //! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer.
-    struct Accessor : public Object
-    {
-        Ref<BufferView> bufferView;  //!< The ID of the bufferView. (required)
-        unsigned int byteOffset;     //!< The offset relative to the start of the bufferView in bytes. (required)
-        unsigned int byteStride;     //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0)
-        ComponentType componentType; //!< The datatype of components in the attribute. (required)
-        unsigned int count;          //!< The number of attributes referenced by this accessor. (required)
-        AttribType::Value type;      //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
-        std::vector<double> max;     //!< Maximum value of each component in this attribute.
-        std::vector<double> min;     //!< Minimum value of each component in this attribute.
+//! A typed view into a BufferView. A BufferView contains raw binary data.
+//! An accessor provides a typed view into a BufferView or a subset of a BufferView
+//! similar to how WebGL's vertexAttribPointer() defines an attribute in a buffer.
+struct Accessor : public Object {
+    Ref<BufferView> bufferView; //!< The ID of the bufferView. (required)
+    unsigned int byteOffset; //!< The offset relative to the start of the bufferView in bytes. (required)
+    unsigned int byteStride; //!< The stride, in bytes, between attributes referenced by this accessor. (default: 0)
+    ComponentType componentType; //!< The datatype of components in the attribute. (required)
+    unsigned int count; //!< The number of attributes referenced by this accessor. (required)
+    AttribType::Value type; //!< Specifies if the attribute is a scalar, vector, or matrix. (required)
+    std::vector<double> max; //!< Maximum value of each component in this attribute.
+    std::vector<double> min; //!< Minimum value of each component in this attribute.
 
-        unsigned int GetNumComponents();
-        unsigned int GetBytesPerComponent();
-        unsigned int GetElementSize();
+    unsigned int GetNumComponents();
+    unsigned int GetBytesPerComponent();
+    unsigned int GetElementSize();
 
-        inline uint8_t* GetPointer();
+    inline uint8_t *GetPointer();
 
-        template<class T>
-        bool ExtractData(T*& outData);
+    template <class T>
+    bool ExtractData(T *&outData);
 
-        void WriteData(size_t count, const void* src_buffer, size_t src_stride);
+    void WriteData(size_t count, const void *src_buffer, size_t src_stride);
 
-        //! Helper class to iterate the data
-        class Indexer
-        {
-            friend struct Accessor;
+    //! Helper class to iterate the data
+    class Indexer {
+        friend struct Accessor;
 
         // This field is reported as not used, making it protectd is the easiest way to work around it without going to the bottom of what the problem is:
         // ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field]
-        protected:
-            Accessor &accessor;
-
-        private:
-            uint8_t* data;
-            size_t elemSize, stride;
-
-            Indexer(Accessor& acc);
+    protected:
+        Accessor &accessor;
 
-        public:
+    private:
+        uint8_t *data;
+        size_t elemSize, stride;
 
-            //! Accesses the i-th value as defined by the accessor
-            template<class T>
-            T GetValue(int i);
+        Indexer(Accessor &acc);
 
-            //! Accesses the i-th value as defined by the accessor
-            inline unsigned int GetUInt(int i)
-            {
-                return GetValue<unsigned int>(i);
-            }
-
-            inline bool IsValid() const
-            {
-                return data != 0;
-            }
-        };
+    public:
+        //! Accesses the i-th value as defined by the accessor
+        template <class T>
+        T GetValue(int i);
 
-        inline Indexer GetIndexer()
-        {
-            return Indexer(*this);
+        //! Accesses the i-th value as defined by the accessor
+        inline unsigned int GetUInt(int i) {
+            return GetValue<unsigned int>(i);
         }
 
-        Accessor() {}
-        void Read(Value& obj, Asset& r);
-    };
-
-    //! A buffer points to binary geometry, animation, or skins.
-    struct Buffer : public Object
-	{
-		/********************* Types *********************/
-	public:
-
-		enum Type
-		{
-			Type_arraybuffer,
-			Type_text
-		};
-
-		/// \struct SEncodedRegion
-		/// Descriptor of encoded region in "bufferView".
-		struct SEncodedRegion
-		{
-			const size_t Offset;///< Offset from begin of "bufferView" to encoded region, in bytes.
-			const size_t EncodedData_Length;///< Size of encoded region, in bytes.
-			uint8_t* const DecodedData;///< Cached encoded data.
-			const size_t DecodedData_Length;///< Size of decoded region, in bytes.
-			const std::string ID;///< ID of the region.
-
-			/// \fn SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
-			/// Constructor.
-			/// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
-			/// \param [in] pEncodedData_Length - size of encoded region, in bytes.
-			/// \param [in] pDecodedData - pointer to decoded data array.
-			/// \param [in] pDecodedData_Length - size of encoded region, in bytes.
-			/// \param [in] pID - ID of the region.
-            SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) :
-                    Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) {}
-
-            /// \fn ~SEncodedRegion()
-			/// Destructor.
-			~SEncodedRegion() { delete [] DecodedData; }
-		};
-
-		/******************* Variables *******************/
-
-		//std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required)
-		size_t byteLength; //!< The length of the buffer in bytes. (default: 0)
-		//std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer")
-
-		Type type;
-
-		/// \var EncodedRegion_Current
-		/// Pointer to currently active encoded region.
-		/// Why not decoding all regions at once and not to set one buffer with decoded data?
-		/// Yes, why not? Even "accessor" point to decoded data. I mean that fields "byteOffset", "byteStride" and "count" has values which describes decoded
-		/// data array. But only in range of mesh while is active parameters from "compressedData". For another mesh accessors point to decoded data too. But
-		/// offset is counted for another regions is encoded.
-		/// Example. You have two meshes. For every of it you have 4 bytes of data. That data compressed to 2 bytes. So, you have buffer with encoded data:
-		/// M1_E0, M1_E1, M2_E0, M2_E1.
-		/// After decoding you'll get:
-		/// M1_D0, M1_D1, M1_D2, M1_D3, M2_D0, M2_D1, M2_D2, M2_D3.
-		/// "accessors" must to use values that point to decoded data - obviously. So, you'll expect "accessors" like
-		/// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 4, byteLength: 4}
-		/// but in real life you'll get:
-		/// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4}
-		/// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded.
-		/// And when before you start to read data of current mesh (with encoded data ofcourse) you must decode region of "bufferView", after read finished
-		/// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data.
-		///
-		/// Remark. Encoding all data at once is good in world with computers which do not has RAM limitation. So, you must use step by step encoding in
-		/// exporter and importer. And, thanks to such way, there is no need to load whole file into memory.
-		SEncodedRegion* EncodedRegion_Current;
-
-	private:
-
-		shared_ptr<uint8_t> mData; //!< Pointer to the data
-		bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer)
-        size_t capacity = 0; //!< The capacity of the buffer in bytes. (default: 0)
-		/// \var EncodedRegion_List
-		/// List of encoded regions.
-		std::list<SEncodedRegion*> EncodedRegion_List;
-
-		/******************* Functions *******************/
-
-	public:
-
-		Buffer();
-		~Buffer();
-
-		void Read(Value& obj, Asset& r);
-
-        bool LoadFromStream(IOStream& stream, size_t length = 0, size_t baseOffset = 0);
-
-		/// \fn void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID)
-		/// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data.
-		/// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
-		/// \param [in] pEncodedData_Length - size of encoded region, in bytes.
-		/// \param [in] pDecodedData - pointer to decoded data array.
-		/// \param [in] pDecodedData_Length - size of encoded region, in bytes.
-		/// \param [in] pID - ID of the region.
-		void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID);
-
-		/// \fn void EncodedRegion_SetCurrent(const std::string& pID)
-		/// Select current encoded region by ID. \sa EncodedRegion_Current.
-		/// \param [in] pID - ID of the region.
-		void EncodedRegion_SetCurrent(const std::string& pID);
-
-		/// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
-		/// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions.
-		/// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed.
-		/// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
-		/// \param [in] pReplace_Data - pointer to array with new data for buffer.
-		/// \param [in] pReplace_Count - count of bytes in new data.
-		/// \return true - if successfully replaced, false if input arguments is out of range.
-		bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count);
-
-        size_t AppendData(uint8_t* data, size_t length);
-        void Grow(size_t amount);
-
-        uint8_t* GetPointer()
-            { return mData.get(); }
-
-        void MarkAsSpecial()
-            { mIsSpecial = true; }
-
-        bool IsSpecial() const
-            { return mIsSpecial; }
-
-        std::string GetURI()
-            { return std::string(this->id) + ".bin"; }
-
-        static const char* TranslateId(Asset& r, const char* id);
+        inline bool IsValid() const {
+            return data != 0;
+        }
     };
 
-    //! A view into a buffer generally representing a subset of the buffer.
-    struct BufferView : public Object
-    {
-        Ref<Buffer> buffer; //! The ID of the buffer. (required)
-        size_t byteOffset; //! The offset into the buffer in bytes. (required)
-        size_t byteLength; //! The length of the bufferView in bytes. (default: 0)
-
-        BufferViewTarget target; //! The target that the WebGL buffer should be bound to.
+    inline Indexer GetIndexer() {
+        return Indexer(*this);
+    }
 
-        void Read(Value& obj, Asset& r);
+    Accessor() {}
+    void Read(Value &obj, Asset &r);
+};
+
+//! A buffer points to binary geometry, animation, or skins.
+struct Buffer : public Object {
+    /********************* Types *********************/
+public:
+    enum Type {
+        Type_arraybuffer,
+        Type_text
     };
 
-    struct Camera : public Object
-    {
-        enum Type
-        {
-            Perspective,
-            Orthographic
-        };
-
-        Type type;
-
-        union
-        {
-            struct {
-                float aspectRatio; //!<The floating - point aspect ratio of the field of view. (0 = undefined = use the canvas one)
-                float yfov;  //!<The floating - point vertical field of view in radians. (required)
-                float zfar;  //!<The floating - point distance to the far clipping plane. (required)
-                float znear; //!< The floating - point distance to the near clipping plane. (required)
-            } perspective;
-
-            struct {
-                float xmag;  //! The floating-point horizontal magnification of the view. (required)
-                float ymag;  //! The floating-point vertical magnification of the view. (required)
-                float zfar;  //! The floating-point distance to the far clipping plane. (required)
-                float znear; //! The floating-point distance to the near clipping plane. (required)
-            } ortographic;
-        };
-
-        Camera() {}
-        void Read(Value& obj, Asset& r);
+    /// \struct SEncodedRegion
+    /// Descriptor of encoded region in "bufferView".
+    struct SEncodedRegion {
+        const size_t Offset; ///< Offset from begin of "bufferView" to encoded region, in bytes.
+        const size_t EncodedData_Length; ///< Size of encoded region, in bytes.
+        uint8_t *const DecodedData; ///< Cached encoded data.
+        const size_t DecodedData_Length; ///< Size of decoded region, in bytes.
+        const std::string ID; ///< ID of the region.
+
+        /// \fn SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string pID)
+        /// Constructor.
+        /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
+        /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
+        /// \param [in] pDecodedData - pointer to decoded data array.
+        /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
+        /// \param [in] pID - ID of the region.
+        SEncodedRegion(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID) :
+                Offset(pOffset), EncodedData_Length(pEncodedData_Length), DecodedData(pDecodedData), DecodedData_Length(pDecodedData_Length), ID(pID) {}
+
+        /// \fn ~SEncodedRegion()
+        /// Destructor.
+        ~SEncodedRegion() { delete[] DecodedData; }
     };
 
+    /******************* Variables *******************/
+
+    //std::string uri; //!< The uri of the buffer. Can be a filepath, a data uri, etc. (required)
+    size_t byteLength; //!< The length of the buffer in bytes. (default: 0)
+    //std::string type; //!< XMLHttpRequest responseType (default: "arraybuffer")
+
+    Type type;
+
+    /// \var EncodedRegion_Current
+    /// Pointer to currently active encoded region.
+    /// Why not decoding all regions at once and not to set one buffer with decoded data?
+    /// Yes, why not? Even "accessor" point to decoded data. I mean that fields "byteOffset", "byteStride" and "count" has values which describes decoded
+    /// data array. But only in range of mesh while is active parameters from "compressedData". For another mesh accessors point to decoded data too. But
+    /// offset is counted for another regions is encoded.
+    /// Example. You have two meshes. For every of it you have 4 bytes of data. That data compressed to 2 bytes. So, you have buffer with encoded data:
+    /// M1_E0, M1_E1, M2_E0, M2_E1.
+    /// After decoding you'll get:
+    /// M1_D0, M1_D1, M1_D2, M1_D3, M2_D0, M2_D1, M2_D2, M2_D3.
+    /// "accessors" must to use values that point to decoded data - obviously. So, you'll expect "accessors" like
+    /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 4, byteLength: 4}
+    /// but in real life you'll get:
+    /// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4}
+    /// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded.
+    /// And when before you start to read data of current mesh (with encoded data ofcourse) you must decode region of "bufferView", after read finished
+    /// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data.
+    ///
+    /// Remark. Encoding all data at once is good in world with computers which do not has RAM limitation. So, you must use step by step encoding in
+    /// exporter and importer. And, thanks to such way, there is no need to load whole file into memory.
+    SEncodedRegion *EncodedRegion_Current;
+
+private:
+    shared_ptr<uint8_t> mData; //!< Pointer to the data
+    bool mIsSpecial; //!< Set to true for special cases (e.g. the body buffer)
+    size_t capacity = 0; //!< The capacity of the buffer in bytes. (default: 0)
+    /// \var EncodedRegion_List
+    /// List of encoded regions.
+    std::list<SEncodedRegion *> EncodedRegion_List;
+
+    /******************* Functions *******************/
+
+public:
+    Buffer();
+    ~Buffer();
+
+    void Read(Value &obj, Asset &r);
+
+    bool LoadFromStream(IOStream &stream, size_t length = 0, size_t baseOffset = 0);
+
+    /// \fn void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t* pDecodedData, const size_t pDecodedData_Length, const std::string& pID)
+    /// Mark region of "bufferView" as encoded. When data is request from such region then "bufferView" use decoded data.
+    /// \param [in] pOffset - offset from begin of "bufferView" to encoded region, in bytes.
+    /// \param [in] pEncodedData_Length - size of encoded region, in bytes.
+    /// \param [in] pDecodedData - pointer to decoded data array.
+    /// \param [in] pDecodedData_Length - size of encoded region, in bytes.
+    /// \param [in] pID - ID of the region.
+    void EncodedRegion_Mark(const size_t pOffset, const size_t pEncodedData_Length, uint8_t *pDecodedData, const size_t pDecodedData_Length, const std::string &pID);
+
+    /// \fn void EncodedRegion_SetCurrent(const std::string& pID)
+    /// Select current encoded region by ID. \sa EncodedRegion_Current.
+    /// \param [in] pID - ID of the region.
+    void EncodedRegion_SetCurrent(const std::string &pID);
+
+    /// \fn bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t* pReplace_Data, const size_t pReplace_Count)
+    /// Replace part of buffer data. Pay attention that function work with original array of data (\ref mData) not with encoded regions.
+    /// \param [in] pBufferData_Offset - index of first element in buffer from which new data will be placed.
+    /// \param [in] pBufferData_Count - count of bytes in buffer which will be replaced.
+    /// \param [in] pReplace_Data - pointer to array with new data for buffer.
+    /// \param [in] pReplace_Count - count of bytes in new data.
+    /// \return true - if successfully replaced, false if input arguments is out of range.
+    bool ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count);
+
+    size_t AppendData(uint8_t *data, size_t length);
+    void Grow(size_t amount);
+
+    uint8_t *GetPointer() { return mData.get(); }
+
+    void MarkAsSpecial() { mIsSpecial = true; }
+
+    bool IsSpecial() const { return mIsSpecial; }
+
+    std::string GetURI() { return std::string(this->id) + ".bin"; }
+
+    static const char *TranslateId(Asset &r, const char *id);
+};
+
+//! A view into a buffer generally representing a subset of the buffer.
+struct BufferView : public Object {
+    Ref<Buffer> buffer; //! The ID of the buffer. (required)
+    size_t byteOffset; //! The offset into the buffer in bytes. (required)
+    size_t byteLength; //! The length of the bufferView in bytes. (default: 0)
+
+    BufferViewTarget target; //! The target that the WebGL buffer should be bound to.
+
+    void Read(Value &obj, Asset &r);
+};
+
+struct Camera : public Object {
+    enum Type {
+        Perspective,
+        Orthographic
+    };
 
-    //! Image data used to create a texture.
-    struct Image : public Object
-    {
-        std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required)
+    Type type;
 
-        Ref<BufferView> bufferView;
+    union {
+        struct {
+            float aspectRatio; //!<The floating - point aspect ratio of the field of view. (0 = undefined = use the canvas one)
+            float yfov; //!<The floating - point vertical field of view in radians. (required)
+            float zfar; //!<The floating - point distance to the far clipping plane. (required)
+            float znear; //!< The floating - point distance to the near clipping plane. (required)
+        } perspective;
 
-        std::string mimeType;
+        struct {
+            float xmag; //! The floating-point horizontal magnification of the view. (required)
+            float ymag; //! The floating-point vertical magnification of the view. (required)
+            float zfar; //! The floating-point distance to the far clipping plane. (required)
+            float znear; //! The floating-point distance to the near clipping plane. (required)
+        } ortographic;
+    };
 
-        int width, height;
+    Camera() {}
+    void Read(Value &obj, Asset &r);
+};
 
-    private:
-        std::unique_ptr<uint8_t[]> mData;
-        size_t mDataLength;
+//! Image data used to create a texture.
+struct Image : public Object {
+    std::string uri; //! The uri of the image, that can be a file path, a data URI, etc.. (required)
 
-    public:
+    Ref<BufferView> bufferView;
 
-        Image();
-        void Read(Value& obj, Asset& r);
+    std::string mimeType;
 
-        inline bool HasData() const
-            { return mDataLength > 0; }
+    int width, height;
 
-        inline size_t GetDataLength() const
-            { return mDataLength; }
+private:
+    std::unique_ptr<uint8_t[]> mData;
+    size_t mDataLength;
 
-        inline const uint8_t* GetData() const
-            { return mData.get(); }
+public:
+    Image();
+    void Read(Value &obj, Asset &r);
 
-        inline uint8_t* StealData();
+    inline bool HasData() const { return mDataLength > 0; }
 
-        inline void SetData(uint8_t* data, size_t length, Asset& r);
-    };
+    inline size_t GetDataLength() const { return mDataLength; }
 
-    //! Holds a material property that can be a texture or a color
-    struct TexProperty
-    {
-        Ref<Texture> texture;
-        vec4 color;
-    };
+    inline const uint8_t *GetData() const { return mData.get(); }
 
-    //! The material appearance of a primitive.
-    struct Material : public Object
-    {
-        //Ref<Sampler> source; //!< The ID of the technique.
-        //std::gltf_unordered_map<std::string, std::string> values; //!< A dictionary object of parameter values.
-
-        //! Techniques defined by KHR_materials_common
-        enum Technique
-        {
-            Technique_undefined = 0,
-            Technique_BLINN,
-            Technique_PHONG,
-            Technique_LAMBERT,
-            Technique_CONSTANT
-        };
+    inline uint8_t *StealData();
 
-        TexProperty ambient;
-        TexProperty diffuse;
-        TexProperty specular;
-        TexProperty emission;
+    inline void SetData(uint8_t *data, size_t length, Asset &r);
+};
 
-        bool doubleSided;
-        bool transparent;
-        float transparency;
-        float shininess;
+//! Holds a material property that can be a texture or a color
+struct TexProperty {
+    Ref<Texture> texture;
+    vec4 color;
+};
 
-        Technique technique;
+//! The material appearance of a primitive.
+struct Material : public Object {
+    //Ref<Sampler> source; //!< The ID of the technique.
+    //std::gltf_unordered_map<std::string, std::string> values; //!< A dictionary object of parameter values.
 
-        Material() { SetDefaults(); }
-        void Read(Value& obj, Asset& r);
-        void SetDefaults();
+    //! Techniques defined by KHR_materials_common
+    enum Technique {
+        Technique_undefined = 0,
+        Technique_BLINN,
+        Technique_PHONG,
+        Technique_LAMBERT,
+        Technique_CONSTANT
     };
 
-    //! A set of primitives to be rendered. A node can contain one or more meshes. A node's transform places the mesh in the scene.
-    struct Mesh : public Object
-    {
-        typedef std::vector< Ref<Accessor> > AccessorList;
+    TexProperty ambient;
+    TexProperty diffuse;
+    TexProperty specular;
+    TexProperty emission;
 
-        struct Primitive
-        {
-            PrimitiveMode mode;
+    bool doubleSided;
+    bool transparent;
+    float transparency;
+    float shininess;
 
-            struct Attributes {
-                AccessorList position, normal, texcoord, color, joint, jointmatrix, weight;
-            } attributes;
+    Technique technique;
 
-            Ref<Accessor> indices;
+    Material() { SetDefaults(); }
+    void Read(Value &obj, Asset &r);
+    void SetDefaults();
+};
 
-            Ref<Material> material;
-        };
+//! A set of primitives to be rendered. A node can contain one or more meshes. A node's transform places the mesh in the scene.
+struct Mesh : public Object {
+    typedef std::vector<Ref<Accessor>> AccessorList;
 
-		/// \struct SExtension
-		/// Extension used for mesh.
-		struct SExtension
-		{
-			/// \enum EType
-			/// Type of extension.
-			enum EType
-			{
-				#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
-					Compression_Open3DGC,///< Compression of mesh data using Open3DGC algorithm.
-				#endif
-
-				Unknown
-			};
-
-			EType Type;///< Type of extension.
-
-			/// \fn SExtension
-			/// Constructor.
-			/// \param [in] pType - type of extension.
-			SExtension(const EType pType)
-				: Type(pType)
-			{}
-
-            virtual ~SExtension() {
-                // empty
-            }
-		};
-
-		#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
-			/// \struct SCompression_Open3DGC
-			/// Compression of mesh data using Open3DGC algorithm.
-			struct SCompression_Open3DGC : public SExtension
-			{
-				using SExtension::Type;
-
-				std::string Buffer;///< ID of "buffer" used for storing compressed data.
-				size_t Offset;///< Offset in "bufferView" where compressed data are stored.
-				size_t Count;///< Count of elements in compressed data. Is always equivalent to size in bytes: look comments for "Type" and "Component_Type".
-				bool Binary;///< If true then "binary" mode is used for coding, if false - "ascii" mode.
-				size_t IndicesCount;///< Count of indices in mesh.
-				size_t VerticesCount;///< Count of vertices in mesh.
-				// AttribType::Value Type;///< Is always "SCALAR".
-				// ComponentType Component_Type;///< Is always "ComponentType_UNSIGNED_BYTE" (5121).
-
-				/// \fn SCompression_Open3DGC
-				/// Constructor.
-				SCompression_Open3DGC()
-				: SExtension(Compression_Open3DGC) {
-                    // empty
-                }
-
-                virtual ~SCompression_Open3DGC() {
-                    // empty
-                }
-			};
-		#endif
-
-        std::vector<Primitive> primitives;
-		std::list<SExtension*> Extension;///< List of extensions used in mesh.
-
-        Mesh() {}
-
-		/// \fn ~Mesh()
-		/// Destructor.
-		~Mesh() { for(std::list<SExtension*>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) { delete *it; }; }
-
-		/// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)
-		/// Get mesh data from JSON-object and place them to root asset.
-		/// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
-		/// \param [out] pAsset_Root - reference to root asset where data will be stored.
-		void Read(Value& pJSON_Object, Asset& pAsset_Root);
-
-		#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
-			/// \fn void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root)
-			/// Decode part of "buffer" which encoded with Open3DGC algorithm.
-			/// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region.
-			/// \param [out] pAsset_Root - reference to root assed where data will be stored.
-			void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root);
-		#endif
-    };
+    struct Primitive {
+        PrimitiveMode mode;
 
-    struct Node : public Object
-    {
-        std::vector< Ref<Node> > children;
-        std::vector< Ref<Mesh> > meshes;
-
-        Nullable<mat4> matrix;
-        Nullable<vec3> translation;
-        Nullable<vec4> rotation;
-        Nullable<vec3> scale;
-
-        Ref<Camera> camera;
-        Ref<Light>  light;
-
-        std::vector< Ref<Node> > skeletons;       //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy.
-        Ref<Skin>  skin;                          //!< The ID of the skin referenced by this node.
-        std::string jointName;                    //!< Name used when this node is a joint in a skin.
-
-        Ref<Node> parent;                         //!< This is not part of the glTF specification. Used as a helper.
+        struct Attributes {
+            AccessorList position, normal, texcoord, color, joint, jointmatrix, weight;
+        } attributes;
 
-        Node() {}
-        void Read(Value& obj, Asset& r);
-    };
+        Ref<Accessor> indices;
 
-    struct Program : public Object
-    {
-        Program() {}
-        void Read(Value& obj, Asset& r);
+        Ref<Material> material;
     };
 
+    /// \struct SExtension
+    /// Extension used for mesh.
+    struct SExtension {
+        /// \enum EType
+        /// Type of extension.
+        enum EType {
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+            Compression_Open3DGC, ///< Compression of mesh data using Open3DGC algorithm.
+#endif
 
-    struct Sampler : public Object
-    {
-        SamplerMagFilter magFilter; //!< The texture magnification filter. (required)
-        SamplerMinFilter minFilter; //!< The texture minification filter. (required)
-        SamplerWrap wrapS;          //!< The texture wrapping in the S direction. (required)
-        SamplerWrap wrapT;          //!< The texture wrapping in the T direction. (required)
-
-        Sampler() {}
-        void Read(Value& obj, Asset& r);
-        void SetDefaults();
-    };
+            Unknown
+        };
 
-    struct Scene : public Object
-    {
-        std::vector< Ref<Node> > nodes;
+        EType Type; ///< Type of extension.
 
-        Scene() {}
-        void Read(Value& obj, Asset& r);
-    };
+        /// \fn SExtension
+        /// Constructor.
+        /// \param [in] pType - type of extension.
+        SExtension(const EType pType) :
+                Type(pType) {}
 
-    struct Shader : public Object
-    {
-        Shader() {}
-        void Read(Value& obj, Asset& r);
+        virtual ~SExtension() {
+            // empty
+        }
     };
 
-    struct Skin : public Object
-    {
-        Nullable<mat4> bindShapeMatrix;       //!< Floating-point 4x4 transformation matrix stored in column-major order.
-        Ref<Accessor> inverseBindMatrices;    //!< The ID of the accessor containing the floating-point 4x4 inverse-bind matrices.
-        std::vector<Ref<Node>> jointNames;    //!< Joint names of the joints (nodes with a jointName property) in this skin.
-        std::string name;                     //!< The user-defined name of this object.
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+    /// \struct SCompression_Open3DGC
+    /// Compression of mesh data using Open3DGC algorithm.
+    struct SCompression_Open3DGC : public SExtension {
+        using SExtension::Type;
+
+        std::string Buffer; ///< ID of "buffer" used for storing compressed data.
+        size_t Offset; ///< Offset in "bufferView" where compressed data are stored.
+        size_t Count; ///< Count of elements in compressed data. Is always equivalent to size in bytes: look comments for "Type" and "Component_Type".
+        bool Binary; ///< If true then "binary" mode is used for coding, if false - "ascii" mode.
+        size_t IndicesCount; ///< Count of indices in mesh.
+        size_t VerticesCount; ///< Count of vertices in mesh.
+        // AttribType::Value Type;///< Is always "SCALAR".
+        // ComponentType Component_Type;///< Is always "ComponentType_UNSIGNED_BYTE" (5121).
+
+        /// \fn SCompression_Open3DGC
+        /// Constructor.
+        SCompression_Open3DGC() :
+                SExtension(Compression_Open3DGC) {
+            // empty
+        }
 
-        Skin() {}
-        void Read(Value& obj, Asset& r);
+        virtual ~SCompression_Open3DGC() {
+            // empty
+        }
     };
+#endif
 
-    struct Technique : public Object
-    {
-        struct Parameters
-        {
-
-        };
-
-        struct States
-        {
+    std::vector<Primitive> primitives;
+    std::list<SExtension *> Extension; ///< List of extensions used in mesh.
 
-        };
-
-        struct Functions
-        {
+    Mesh() {}
 
+    /// \fn ~Mesh()
+    /// Destructor.
+    ~Mesh() {
+        for (std::list<SExtension *>::iterator it = Extension.begin(), it_end = Extension.end(); it != it_end; it++) {
+            delete *it;
         };
+    }
 
-        Technique() {}
-        void Read(Value& obj, Asset& r);
+    /// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)
+    /// Get mesh data from JSON-object and place them to root asset.
+    /// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
+    /// \param [out] pAsset_Root - reference to root asset where data will be stored.
+    void Read(Value &pJSON_Object, Asset &pAsset_Root);
+
+#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
+    /// \fn void Decode_O3DGC(const SCompression_Open3DGC& pCompression_Open3DGC, Asset& pAsset_Root)
+    /// Decode part of "buffer" which encoded with Open3DGC algorithm.
+    /// \param [in] pCompression_Open3DGC - reference to structure which describe encoded region.
+    /// \param [out] pAsset_Root - reference to root assed where data will be stored.
+    void Decode_O3DGC(const SCompression_Open3DGC &pCompression_Open3DGC, Asset &pAsset_Root);
+#endif
+};
+
+struct Node : public Object {
+    std::vector<Ref<Node>> children;
+    std::vector<Ref<Mesh>> meshes;
+
+    Nullable<mat4> matrix;
+    Nullable<vec3> translation;
+    Nullable<vec4> rotation;
+    Nullable<vec3> scale;
+
+    Ref<Camera> camera;
+    Ref<Light> light;
+
+    std::vector<Ref<Node>> skeletons; //!< The ID of skeleton nodes. Each of which is the root of a node hierarchy.
+    Ref<Skin> skin; //!< The ID of the skin referenced by this node.
+    std::string jointName; //!< Name used when this node is a joint in a skin.
+
+    Ref<Node> parent; //!< This is not part of the glTF specification. Used as a helper.
+
+    Node() {}
+    void Read(Value &obj, Asset &r);
+};
+
+struct Program : public Object {
+    Program() {}
+    void Read(Value &obj, Asset &r);
+};
+
+struct Sampler : public Object {
+    SamplerMagFilter magFilter; //!< The texture magnification filter. (required)
+    SamplerMinFilter minFilter; //!< The texture minification filter. (required)
+    SamplerWrap wrapS; //!< The texture wrapping in the S direction. (required)
+    SamplerWrap wrapT; //!< The texture wrapping in the T direction. (required)
+
+    Sampler() {}
+    void Read(Value &obj, Asset &r);
+    void SetDefaults();
+};
+
+struct Scene : public Object {
+    std::vector<Ref<Node>> nodes;
+
+    Scene() {}
+    void Read(Value &obj, Asset &r);
+};
+
+struct Shader : public Object {
+    Shader() {}
+    void Read(Value &obj, Asset &r);
+};
+
+struct Skin : public Object {
+    Nullable<mat4> bindShapeMatrix; //!< Floating-point 4x4 transformation matrix stored in column-major order.
+    Ref<Accessor> inverseBindMatrices; //!< The ID of the accessor containing the floating-point 4x4 inverse-bind matrices.
+    std::vector<Ref<Node>> jointNames; //!< Joint names of the joints (nodes with a jointName property) in this skin.
+    std::string name; //!< The user-defined name of this object.
+
+    Skin() {}
+    void Read(Value &obj, Asset &r);
+};
+
+struct Technique : public Object {
+    struct Parameters {
     };
 
-    //! A texture and its sampler.
-    struct Texture : public Object
-    {
-        Ref<Sampler> sampler; //!< The ID of the sampler used by this texture. (required)
-        Ref<Image> source;    //!< The ID of the image used by this texture. (required)
-
-        //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA)
-        //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
-
-        //TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D)
-        //TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE)
+    struct States {
+    };
 
-        Texture() {}
-        void Read(Value& obj, Asset& r);
+    struct Functions {
     };
 
+    Technique() {}
+    void Read(Value &obj, Asset &r);
+};
+
+//! A texture and its sampler.
+struct Texture : public Object {
+    Ref<Sampler> sampler; //!< The ID of the sampler used by this texture. (required)
+    Ref<Image> source; //!< The ID of the image used by this texture. (required)
+
+    //TextureFormat format; //!< The texture's format. (default: TextureFormat_RGBA)
+    //TextureFormat internalFormat; //!< The texture's internal format. (default: TextureFormat_RGBA)
+
+    //TextureTarget target; //!< The target that the WebGL texture should be bound to. (default: TextureTarget_TEXTURE_2D)
+    //TextureType type; //!< Texel datatype. (default: TextureType_UNSIGNED_BYTE)
+
+    Texture() {}
+    void Read(Value &obj, Asset &r);
+};
+
+//! A light (from KHR_materials_common extension)
+struct Light : public Object {
+    enum Type {
+        Type_undefined,
+        Type_ambient,
+        Type_directional,
+        Type_point,
+        Type_spot
+    };
 
-    //! A light (from KHR_materials_common extension)
-    struct Light : public Object
-    {
-        enum Type
-        {
-            Type_undefined,
-            Type_ambient,
-            Type_directional,
-            Type_point,
-            Type_spot
-        };
+    Type type;
 
-        Type type;
+    vec4 color;
+    float distance;
+    float constantAttenuation;
+    float linearAttenuation;
+    float quadraticAttenuation;
+    float falloffAngle;
+    float falloffExponent;
 
-        vec4 color;
-        float distance;
-        float constantAttenuation;
-        float linearAttenuation;
-        float quadraticAttenuation;
-        float falloffAngle;
-        float falloffExponent;
+    Light() {}
+    void Read(Value &obj, Asset &r);
 
-        Light() {}
-        void Read(Value& obj, Asset& r);
+    void SetDefaults();
+};
 
-        void SetDefaults();
+struct Animation : public Object {
+    struct AnimSampler {
+        std::string id; //!< The ID of this sampler.
+        std::string input; //!< The ID of a parameter in this animation to use as key-frame input.
+        std::string interpolation; //!< Type of interpolation algorithm to use between key-frames.
+        std::string output; //!< The ID of a parameter in this animation to use as key-frame output.
     };
 
-    struct Animation : public Object
-    {
-        struct AnimSampler {
-            std::string id;               //!< The ID of this sampler.
-            std::string input;            //!< The ID of a parameter in this animation to use as key-frame input.
-            std::string interpolation;    //!< Type of interpolation algorithm to use between key-frames.
-            std::string output;           //!< The ID of a parameter in this animation to use as key-frame output.
-        };
+    struct AnimChannel {
+        std::string sampler; //!< The ID of one sampler present in the containing animation's samplers property.
 
-        struct AnimChannel {
-            std::string sampler;         //!< The ID of one sampler present in the containing animation's samplers property.
+        struct AnimTarget {
+            Ref<Node> id; //!< The ID of the node to animate.
+            std::string path; //!< The name of property of the node to animate ("translation", "rotation", or "scale").
+        } target;
+    };
 
-            struct AnimTarget {
-                Ref<Node> id;            //!< The ID of the node to animate.
-                std::string path;        //!< The name of property of the node to animate ("translation", "rotation", or "scale").
-            } target;
-        };
+    struct AnimParameters {
+        Ref<Accessor> TIME; //!< Accessor reference to a buffer storing a array of floating point scalar values.
+        Ref<Accessor> rotation; //!< Accessor reference to a buffer storing a array of four-component floating-point vectors.
+        Ref<Accessor> scale; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
+        Ref<Accessor> translation; //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
+    };
 
-        struct AnimParameters {
-            Ref<Accessor> TIME;           //!< Accessor reference to a buffer storing a array of floating point scalar values.
-            Ref<Accessor> rotation;       //!< Accessor reference to a buffer storing a array of four-component floating-point vectors.
-            Ref<Accessor> scale;          //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
-            Ref<Accessor> translation;    //!< Accessor reference to a buffer storing a array of three-component floating-point vectors.
-        };
+    // AnimChannel Channels[3];            //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
+    // AnimParameters Parameters;          //!< The samplers that interpolate between the key-frames.
+    // AnimSampler Samplers[3];            //!< The parameterized inputs representing the key-frame data.
 
-        // AnimChannel Channels[3];            //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
-        // AnimParameters Parameters;          //!< The samplers that interpolate between the key-frames.
-        // AnimSampler Samplers[3];            //!< The parameterized inputs representing the key-frame data.
+    std::vector<AnimChannel> Channels; //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
+    AnimParameters Parameters; //!< The samplers that interpolate between the key-frames.
+    std::vector<AnimSampler> Samplers; //!< The parameterized inputs representing the key-frame data.
 
-        std::vector<AnimChannel> Channels;            //!< Connect the output values of the key-frame animation to a specific node in the hierarchy.
-        AnimParameters Parameters;                    //!< The samplers that interpolate between the key-frames.
-        std::vector<AnimSampler> Samplers;         //!< The parameterized inputs representing the key-frame data.
+    Animation() {}
+    void Read(Value &obj, Asset &r);
+};
 
-        Animation() {}
-        void Read(Value& obj, Asset& r);
-    };
+//! Base class for LazyDict that acts as an interface
+class LazyDictBase {
+public:
+    virtual ~LazyDictBase() {}
 
-
-    //! Base class for LazyDict that acts as an interface
-    class LazyDictBase
-    {
-    public:
-        virtual ~LazyDictBase() {}
-
-        virtual void AttachToDocument(Document& doc) = 0;
-        virtual void DetachFromDocument() = 0;
+    virtual void AttachToDocument(Document &doc) = 0;
+    virtual void DetachFromDocument() = 0;
 
 #if !defined(ASSIMP_BUILD_NO_EXPORT)
-        virtual void WriteObjects(AssetWriter& writer) = 0;
+    virtual void WriteObjects(AssetWriter &writer) = 0;
 #endif
-    };
-
+};
 
-    template<class T>
-    class LazyDict;
-
-    //! (Implemented in glTFAssetWriter.h)
-    template<class T>
-    void WriteLazyDict(LazyDict<T>& d, AssetWriter& w);
+template <class T>
+class LazyDict;
 
+//! (Implemented in glTFAssetWriter.h)
+template <class T>
+void WriteLazyDict(LazyDict<T> &d, AssetWriter &w);
 
-    //! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID
-    //! It is the owner the loaded objects, so when it is destroyed it also deletes them
-    template<class T>
-    class LazyDict : public LazyDictBase
-    {
-        friend class Asset;
-        friend class AssetWriter;
+//! Manages lazy loading of the glTF top-level objects, and keeps a reference to them by ID
+//! It is the owner the loaded objects, so when it is destroyed it also deletes them
+template <class T>
+class LazyDict : public LazyDictBase {
+    friend class Asset;
+    friend class AssetWriter;
 
-        typedef typename std::gltf_unordered_map< std::string, unsigned int > Dict;
+    typedef typename std::gltf_unordered_map<std::string, unsigned int> Dict;
 
-        std::vector<T*>  mObjs;      //! The read objects
-        Dict             mObjsById;  //! The read objects accessible by id
-        const char*      mDictId;    //! ID of the dictionary object
-        const char*      mExtId;     //! ID of the extension defining the dictionary
-        Value*           mDict;      //! JSON dictionary object
-        Asset&           mAsset;     //! The asset instance
+    std::vector<T *> mObjs; //! The read objects
+    Dict mObjsById; //! The read objects accessible by id
+    const char *mDictId; //! ID of the dictionary object
+    const char *mExtId; //! ID of the extension defining the dictionary
+    Value *mDict; //! JSON dictionary object
+    Asset &mAsset; //! The asset instance
 
-        void AttachToDocument(Document& doc);
-        void DetachFromDocument();
+    void AttachToDocument(Document &doc);
+    void DetachFromDocument();
 
 #if !defined(ASSIMP_BUILD_NO_EXPORT)
-        void WriteObjects(AssetWriter& writer)
-            { WriteLazyDict<T>(*this, writer); }
+    void WriteObjects(AssetWriter &writer) { WriteLazyDict<T>(*this, writer); }
 #endif
 
-        Ref<T> Add(T* obj);
+    Ref<T> Add(T *obj);
 
-    public:
-        LazyDict(Asset& asset, const char* dictId, const char* extId = 0);
-        ~LazyDict();
-
-        Ref<T> Get(const char* id);
-        Ref<T> Get(unsigned int i);
-        Ref<T> Get(const std::string& pID) { return Get(pID.c_str()); }
-
-        Ref<T> Create(const char* id);
-        Ref<T> Create(const std::string& id)
-            { return Create(id.c_str()); }
-
-        inline unsigned int Size() const
-            { return unsigned(mObjs.size()); }
-
-        inline T& operator[](size_t i)
-            { return *mObjs[i]; }
+public:
+    LazyDict(Asset &asset, const char *dictId, const char *extId = 0);
+    ~LazyDict();
 
-    };
+    Ref<T> Get(const char *id);
+    Ref<T> Get(unsigned int i);
+    Ref<T> Get(const std::string &pID) { return Get(pID.c_str()); }
 
+    Ref<T> Create(const char *id);
+    Ref<T> Create(const std::string &id) { return Create(id.c_str()); }
 
-    struct AssetMetadata
-    {
-        std::string copyright; //!< A copyright message suitable for display to credit the content creator.
-        std::string generator; //!< Tool that generated this glTF model.Useful for debugging.
-        bool premultipliedAlpha; //!< Specifies if the shaders were generated with premultiplied alpha. (default: false)
+    inline unsigned int Size() const { return unsigned(mObjs.size()); }
 
-        struct {
-            std::string api;     //!< Specifies the target rendering API (default: "WebGL")
-            std::string version; //!< Specifies the target rendering API (default: "1.0.3")
-        } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {})
+    inline T &operator[](size_t i) { return *mObjs[i]; }
+};
 
-        std::string version; //!< The glTF format version (should be 1.0)
+struct AssetMetadata {
+    std::string copyright; //!< A copyright message suitable for display to credit the content creator.
+    std::string generator; //!< Tool that generated this glTF model.Useful for debugging.
+    bool premultipliedAlpha; //!< Specifies if the shaders were generated with premultiplied alpha. (default: false)
 
-        void Read(Document& doc);
+    struct {
+        std::string api; //!< Specifies the target rendering API (default: "WebGL")
+        std::string version; //!< Specifies the target rendering API (default: "1.0.3")
+    } profile; //!< Specifies the target rendering API and version, e.g., WebGL 1.0.3. (default: {})
 
-        AssetMetadata()
-            : premultipliedAlpha(false)
-            , version()
-        {
-        }
-    };
+    std::string version; //!< The glTF format version (should be 1.0)
 
-    //
-    // glTF Asset class
-    //
+    void Read(Document &doc);
 
-    //! Root object for a glTF asset
-    class Asset
-    {
-        typedef std::gltf_unordered_map<std::string, int> IdMap;
+    AssetMetadata() :
+            premultipliedAlpha(false), version() {
+    }
+};
 
-        template<class T>
-        friend class LazyDict;
+//
+// glTF Asset class
+//
 
-        friend struct Buffer; // To access OpenFile
+//! Root object for a glTF asset
+class Asset {
+    typedef std::gltf_unordered_map<std::string, int> IdMap;
 
-        friend class AssetWriter;
+    template <class T>
+    friend class LazyDict;
 
-    private:
-        IOSystem* mIOSystem;
+    friend struct Buffer; // To access OpenFile
 
-        std::string mCurrentAssetDir;
+    friend class AssetWriter;
 
-        size_t mSceneLength;
-        size_t mBodyOffset, mBodyLength;
+private:
+    IOSystem *mIOSystem;
 
-        std::vector<LazyDictBase*> mDicts;
+    std::string mCurrentAssetDir;
 
-        IdMap mUsedIds;
+    size_t mSceneLength;
+    size_t mBodyOffset, mBodyLength;
 
-        Ref<Buffer> mBodyBuffer;
+    std::vector<LazyDictBase *> mDicts;
 
-        Asset(Asset&);
-        Asset& operator=(const Asset&);
+    IdMap mUsedIds;
 
-    public:
+    Ref<Buffer> mBodyBuffer;
 
-        //! Keeps info about the enabled extensions
-        struct Extensions
-        {
-            bool KHR_binary_glTF;
-            bool KHR_materials_common;
+    Asset(Asset &);
+    Asset &operator=(const Asset &);
 
-        } extensionsUsed;
+public:
+    //! Keeps info about the enabled extensions
+    struct Extensions {
+        bool KHR_binary_glTF;
+        bool KHR_materials_common;
 
-        AssetMetadata asset;
+    } extensionsUsed;
 
+    AssetMetadata asset;
 
-        // Dictionaries for each type of object
+    // Dictionaries for each type of object
 
-        LazyDict<Accessor>    accessors;
-        LazyDict<Animation>   animations;
-        LazyDict<Buffer>      buffers;
-        LazyDict<BufferView>  bufferViews;
-        LazyDict<Camera>      cameras;
-        LazyDict<Image>       images;
-        LazyDict<Material>    materials;
-        LazyDict<Mesh>        meshes;
-        LazyDict<Node>        nodes;
-        //LazyDict<Program>   programs;
-        LazyDict<Sampler>     samplers;
-        LazyDict<Scene>       scenes;
-        //LazyDict<Shader>    shaders;
-        LazyDict<Skin>      skins;
-        //LazyDict<Technique> techniques;
-        LazyDict<Texture>     textures;
+    LazyDict<Accessor> accessors;
+    LazyDict<Animation> animations;
+    LazyDict<Buffer> buffers;
+    LazyDict<BufferView> bufferViews;
+    LazyDict<Camera> cameras;
+    LazyDict<Image> images;
+    LazyDict<Material> materials;
+    LazyDict<Mesh> meshes;
+    LazyDict<Node> nodes;
+    //LazyDict<Program>   programs;
+    LazyDict<Sampler> samplers;
+    LazyDict<Scene> scenes;
+    //LazyDict<Shader>    shaders;
+    LazyDict<Skin> skins;
+    //LazyDict<Technique> techniques;
+    LazyDict<Texture> textures;
 
-        LazyDict<Light>       lights; // KHR_materials_common ext
+    LazyDict<Light> lights; // KHR_materials_common ext
 
-        Ref<Scene> scene;
+    Ref<Scene> scene;
 
-    public:
-        Asset(IOSystem* io = 0)
-            : mIOSystem(io)
-            , asset()
-            , accessors     (*this, "accessors")
-            , animations    (*this, "animations")
-            , buffers       (*this, "buffers")
-            , bufferViews   (*this, "bufferViews")
-            , cameras       (*this, "cameras")
-            , images        (*this, "images")
-            , materials     (*this, "materials")
-            , meshes        (*this, "meshes")
-            , nodes         (*this, "nodes")
+public:
+    Asset(IOSystem *io = 0) :
+            mIOSystem(io), asset(), accessors(*this, "accessors"), animations(*this, "animations"), buffers(*this, "buffers"), bufferViews(*this, "bufferViews"), cameras(*this, "cameras"), images(*this, "images"), materials(*this, "materials"), meshes(*this, "meshes"), nodes(*this, "nodes")
             //, programs    (*this, "programs")
-            , samplers      (*this, "samplers")
-            , scenes        (*this, "scenes")
+            ,
+            samplers(*this, "samplers"),
+            scenes(*this, "scenes")
             //, shaders     (*this, "shaders")
-            , skins       (*this, "skins")
+            ,
+            skins(*this, "skins")
             //, techniques  (*this, "techniques")
-            , textures      (*this, "textures")
-            , lights        (*this, "lights", "KHR_materials_common")
-        {
-            memset(&extensionsUsed, 0, sizeof(extensionsUsed));
-        }
+            ,
+            textures(*this, "textures"),
+            lights(*this, "lights", "KHR_materials_common") {
+        memset(&extensionsUsed, 0, sizeof(extensionsUsed));
+    }
 
-        //! Main function
-        void Load(const std::string& file, bool isBinary = false);
+    //! Main function
+    void Load(const std::string &file, bool isBinary = false);
 
-        //! Enables the "KHR_binary_glTF" extension on the asset
-        void SetAsBinary();
+    //! Enables the "KHR_binary_glTF" extension on the asset
+    void SetAsBinary();
 
-        //! Search for an available name, starting from the given strings
-        std::string FindUniqueID(const std::string& str, const char* suffix);
+    //! Search for an available name, starting from the given strings
+    std::string FindUniqueID(const std::string &str, const char *suffix);
 
-        Ref<Buffer> GetBodyBuffer()
-            { return mBodyBuffer; }
+    Ref<Buffer> GetBodyBuffer() { return mBodyBuffer; }
 
-    private:
-        void ReadBinaryHeader(IOStream& stream);
+private:
+    void ReadBinaryHeader(IOStream &stream);
 
-        void ReadExtensionsUsed(Document& doc);
+    void ReadExtensionsUsed(Document &doc);
 
-        IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false);
-    };
+    IOStream *OpenFile(const std::string &path, const char *mode, bool absolute = false);
+};
 
-}
+} // namespace glTF
 
 // Include the implementation of the methods
 #include "glTFAsset.inl"

+ 0 - 119
code/AssetLib/glTF/glTFAsset.inl

@@ -56,130 +56,11 @@ using namespace glTFCommon;
 
 namespace glTF {
 
-namespace {
-
 #if _MSC_VER
 #    pragma warning(push)
 #    pragma warning(disable : 4706)
 #endif // _MSC_VER
 
-//
-// JSON Value reading helpers
-//
-
-template <class T>
-struct ReadHelper {
-    static bool Read(Value &val, T &out) {
-        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
-    }
-};
-
-template <>
-struct ReadHelper<bool> {
-    static bool Read(Value &val, bool &out) {
-        return val.IsBool() ? out = val.GetBool(), true : false;
-    }
-};
-
-template <>
-struct ReadHelper<float> {
-    static bool Read(Value &val, float &out) {
-        return val.IsNumber() ? out = static_cast<float>(val.GetDouble()), true : false;
-    }
-};
-
-template <unsigned int N>
-struct ReadHelper<float[N]> {
-    static bool Read(Value &val, float (&out)[N]) {
-        if (!val.IsArray() || val.Size() != N) return false;
-        for (unsigned int i = 0; i < N; ++i) {
-            if (val[i].IsNumber())
-                out[i] = static_cast<float>(val[i].GetDouble());
-        }
-        return true;
-    }
-};
-
-template <>
-struct ReadHelper<const char *> {
-    static bool Read(Value &val, const char *&out) {
-        return val.IsString() ? (out = val.GetString(), true) : false;
-    }
-};
-
-template <>
-struct ReadHelper<std::string> {
-    static bool Read(Value &val, std::string &out) {
-        return val.IsString() ? (out = std::string(val.GetString(), val.GetStringLength()), true) : false;
-    }
-};
-
-template <class T>
-struct ReadHelper<Nullable<T>> {
-    static bool Read(Value &val, Nullable<T> &out) {
-        return out.isPresent = ReadHelper<T>::Read(val, out.value);
-    }
-};
-
-template <>
-struct ReadHelper<uint64_t> {
-    static bool Read(Value &val, uint64_t &out) {
-        return val.IsUint64() ? out = val.GetUint64(), true : false;
-    }
-};
-
-template <>
-struct ReadHelper<int64_t> {
-    static bool Read(Value &val, int64_t &out) {
-        return val.IsInt64() ? out = val.GetInt64(), true : false;
-    }
-};
-
-template <class T>
-inline static bool ReadValue(Value &val, T &out) {
-    return ReadHelper<T>::Read(val, out);
-}
-
-template <class T>
-inline static bool ReadMember(Value &obj, const char *id, T &out) {
-    Value::MemberIterator it = obj.FindMember(id);
-    if (it != obj.MemberEnd()) {
-        return ReadHelper<T>::Read(it->value, out);
-    }
-    return false;
-}
-
-template <class T>
-inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
-    T out;
-    return ReadMember(obj, id, out) ? out : defaultValue;
-}
-
-inline Value *FindMember(Value &val, const char *id) {
-    Value::MemberIterator it = val.FindMember(id);
-    return (it != val.MemberEnd()) ? &it->value : 0;
-}
-
-inline Value *FindString(Value &val, const char *id) {
-    Value::MemberIterator it = val.FindMember(id);
-    return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
-}
-
-inline Value *FindNumber(Value &val, const char *id) {
-    Value::MemberIterator it = val.FindMember(id);
-    return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
-}
-
-inline Value *FindArray(Value &val, const char *id) {
-    Value::MemberIterator it = val.FindMember(id);
-    return (it != val.MemberEnd() && it->value.IsArray()) ? &it->value : 0;
-}
-
-inline Value *FindObject(Value &val, const char *id) {
-    Value::MemberIterator it = val.FindMember(id);
-    return (it != val.MemberEnd() && it->value.IsObject()) ? &it->value : 0;
-}
-} // namespace
 
 //
 // LazyDict methods

+ 299 - 15
code/AssetLib/glTF/glTFCommon.h

@@ -56,33 +56,40 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <rapidjson/error/en.h>
 #include <rapidjson/rapidjson.h>
 
+// clang-format off
+
 #ifdef ASSIMP_API
-#include <assimp/ByteSwapper.h>
-#include <assimp/DefaultIOSystem.h>
-#include <memory>
+#   include <assimp/ByteSwapper.h>
+#   include <assimp/DefaultIOSystem.h>
+#   include <memory>
 #else
-#include <memory>
-#define AI_SWAP4(p)
-#define ai_assert
+#   include <memory>
+#   define AI_SWAP4(p)
+#   define ai_assert
 #endif
 
 #if _MSC_VER > 1500 || (defined __GNUC___)
-#define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
+#   define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
 #else
-#define gltf_unordered_map map
+#   define gltf_unordered_map map
 #endif
 
 #ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
-#include <unordered_map>
-#if defined(_MSC_VER) && _MSC_VER <= 1600
-#define gltf_unordered_map tr1::unordered_map
-#else
-#define gltf_unordered_map unordered_map
-#endif
+#   include <unordered_map>
+#   if defined(_MSC_VER) && _MSC_VER <= 1600
+#       define gltf_unordered_map tr1::unordered_map
+#   else
+#       define gltf_unordered_map unordered_map
+#   endif
 #endif
+// clang-format on
+
 
 namespace glTFCommon {
 
+using rapidjson::Document;
+using rapidjson::Value;
+
 #ifdef ASSIMP_API
 using Assimp::IOStream;
 using Assimp::IOSystem;
@@ -193,7 +200,6 @@ inline void CopyValue(const glTFCommon::mat4 &v, aiMatrix4x4 &o) {
 #endif // _MSC_VER
 
 inline std::string getCurrentAssetDir(const std::string &pFile) {
-    std::string path = pFile;
     int pos = std::max(int(pFile.rfind('/')), int(pFile.rfind('\\')));
     if (pos == int(std::string::npos)) {
         return std::string();
@@ -262,6 +268,284 @@ void EncodeBase64(const uint8_t *in, size_t inLength, std::string &out);
 #define CHECK_EXT(EXT) \
     if (exts.find(#EXT) != exts.end()) extensionsUsed.EXT = true;
 
+
+
+//! Helper struct to represent values that might not be present
+template <class T>
+struct Nullable {
+    T value;
+    bool isPresent;
+
+    Nullable() :
+            isPresent(false) {}
+    Nullable(T &val) :
+            value(val),
+            isPresent(true) {}
+};
+
+//! A reference to one top-level object, which is valid
+//! until the Asset instance is destroyed
+template <class T>
+class Ref {
+    std::vector<T *> *vector;
+    unsigned int index;
+
+public:
+    Ref() :
+            vector(0),
+            index(0) {}
+    Ref(std::vector<T *> &vec, unsigned int idx) :
+            vector(&vec),
+            index(idx) {}
+
+    inline unsigned int GetIndex() const { return index; }
+
+    operator bool() const { return vector != 0; }
+
+    T *operator->() { return (*vector)[index]; }
+
+    T &operator*() { return *((*vector)[index]); }
+};
+
+//
+// JSON Value reading helpers
+//
+
+template <class T>
+struct ReadHelper {
+    static bool Read(Value &val, T &out) {
+        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
+    }
+};
+
+template <>
+struct ReadHelper<bool> {
+    static bool Read(Value &val, bool &out) {
+        return val.IsBool() ? out = val.GetBool(), true : false;
+    }
+};
+
+template <>
+struct ReadHelper<float> {
+    static bool Read(Value &val, float &out) {
+        return val.IsNumber() ? out = static_cast<float>(val.GetDouble()), true : false;
+    }
+};
+
+template <unsigned int N>
+struct ReadHelper<float[N]> {
+    static bool Read(Value &val, float (&out)[N]) {
+        if (!val.IsArray() || val.Size() != N) return false;
+        for (unsigned int i = 0; i < N; ++i) {
+            if (val[i].IsNumber())
+                out[i] = static_cast<float>(val[i].GetDouble());
+        }
+        return true;
+    }
+};
+
+template <>
+struct ReadHelper<const char *> {
+    static bool Read(Value &val, const char *&out) {
+        return val.IsString() ? (out = val.GetString(), true) : false;
+    }
+};
+
+template <>
+struct ReadHelper<std::string> {
+    static bool Read(Value &val, std::string &out) {
+        return val.IsString() ? (out = std::string(val.GetString(), val.GetStringLength()), true) : false;
+    }
+};
+
+template <class T>
+struct ReadHelper<Nullable<T>> {
+    static bool Read(Value &val, Nullable<T> &out) {
+        return out.isPresent = ReadHelper<T>::Read(val, out.value);
+    }
+};
+
+template <>
+struct ReadHelper<uint64_t> {
+    static bool Read(Value &val, uint64_t &out) {
+        return val.IsUint64() ? out = val.GetUint64(), true : false;
+    }
+};
+
+template <>
+struct ReadHelper<int64_t> {
+    static bool Read(Value &val, int64_t &out) {
+        return val.IsInt64() ? out = val.GetInt64(), true : false;
+    }
+};
+
+template <class T>
+inline static bool ReadValue(Value &val, T &out) {
+    return ReadHelper<T>::Read(val, out);
+}
+
+template <class T>
+inline static bool ReadMember(Value &obj, const char *id, T &out) {
+    if (!obj.IsObject()) {
+        return false;
+    }
+    Value::MemberIterator it = obj.FindMember(id);
+    if (it != obj.MemberEnd()) {
+        return ReadHelper<T>::Read(it->value, out);
+    }
+    return false;
+}
+
+template <class T>
+inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
+    T out;
+    return ReadMember(obj, id, out) ? out : defaultValue;
+}
+
+inline Value *FindMember(Value &val, const char *id) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
+    Value::MemberIterator it = val.FindMember(id);
+    return (it != val.MemberEnd()) ? &it->value : nullptr;
+}
+
+template <int N>
+inline void throwUnexpectedTypeError(const char (&expectedTypeName)[N], const char *memberId, const char *context, const char *extraContext) {
+    std::string fullContext = context;
+    if (extraContext && (strlen(extraContext) > 0)) {
+        fullContext = fullContext + " (" + extraContext + ")";
+    }
+    throw DeadlyImportError("Member \"", memberId, "\" was not of type \"", expectedTypeName, "\" when reading ", fullContext);
+}
+
+// Look-up functions with type checks. Context and extra context help the user identify the problem if there's an error.
+
+inline Value *FindStringInContext(Value &val, const char *memberId, const char *context, const char *extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
+    Value::MemberIterator it = val.FindMember(memberId);
+    if (it == val.MemberEnd()) {
+        return nullptr;
+    }
+    if (!it->value.IsString()) {
+        throwUnexpectedTypeError("string", memberId, context, extraContext);
+    }
+    return &it->value;
+}
+
+inline Value *FindNumberInContext(Value &val, const char *memberId, const char *context, const char *extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
+    Value::MemberIterator it = val.FindMember(memberId);
+    if (it == val.MemberEnd()) {
+        return nullptr;
+    }
+    if (!it->value.IsNumber()) {
+        throwUnexpectedTypeError("number", memberId, context, extraContext);
+    }
+    return &it->value;
+}
+
+inline Value *FindUIntInContext(Value &val, const char *memberId, const char *context, const char *extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
+    Value::MemberIterator it = val.FindMember(memberId);
+    if (it == val.MemberEnd()) {
+        return nullptr;
+    }
+    if (!it->value.IsUint()) {
+        throwUnexpectedTypeError("uint", memberId, context, extraContext);
+    }
+    return &it->value;
+}
+
+inline Value *FindArrayInContext(Value &val, const char *memberId, const char *context, const char *extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
+    Value::MemberIterator it = val.FindMember(memberId);
+    if (it == val.MemberEnd()) {
+        return nullptr;
+    }
+    if (!it->value.IsArray()) {
+        throwUnexpectedTypeError("array", memberId, context, extraContext);
+    }
+    return &it->value;
+}
+
+inline Value *FindObjectInContext(Value &val, const char *memberId, const char *context, const char *extraContext = nullptr) {
+    if (!val.IsObject()) {
+        return nullptr;
+    }
+    Value::MemberIterator it = val.FindMember(memberId);
+    if (it == val.MemberEnd()) {
+        return nullptr;
+    }
+    if (!it->value.IsObject()) {
+        throwUnexpectedTypeError("object", memberId, context, extraContext);
+    }
+    return &it->value;
+}
+
+inline Value *FindExtensionInContext(Value &val, const char *extensionId, const char *context, const char *extraContext = nullptr) {
+    if (Value *extensionList = FindObjectInContext(val, "extensions", context, extraContext)) {
+        if (Value *extension = FindObjectInContext(*extensionList, extensionId, context, extraContext)) {
+            return extension;
+        }
+    }
+    return nullptr;
+}
+
+// Overloads when the value is the document.
+
+inline Value *FindString(Document &doc, const char *memberId) {
+    return FindStringInContext(doc, memberId, "the document");
+}
+
+inline Value *FindNumber(Document &doc, const char *memberId) {
+    return FindNumberInContext(doc, memberId, "the document");
+}
+
+inline Value *FindUInt(Document &doc, const char *memberId) {
+    return FindUIntInContext(doc, memberId, "the document");
+}
+
+inline Value *FindArray(Document &val, const char *memberId) {
+    return FindArrayInContext(val, memberId, "the document");
+}
+
+inline Value *FindObject(Document &doc, const char *memberId) {
+    return FindObjectInContext(doc, memberId, "the document");
+}
+
+inline Value *FindExtension(Value &val, const char *extensionId) {
+    return FindExtensionInContext(val, extensionId, "the document");
+}
+
+inline Value *FindString(Value &val, const char *id) {
+    Value::MemberIterator it = val.FindMember(id);
+    return (it != val.MemberEnd() && it->value.IsString()) ? &it->value : 0;
+}
+
+inline Value *FindObject(Value &val, const char *id) {
+    Value::MemberIterator it = val.FindMember(id);
+    return (it != val.MemberEnd() && it->value.IsObject()) ? &it->value : 0;
+}
+
+inline Value *FindArray(Value &val, const char *id) {
+    Value::MemberIterator it = val.FindMember(id);
+    return (it != val.MemberEnd() && it->value.IsArray()) ? &it->value : 0;
+}
+
+inline Value *FindNumber(Value &val, const char *id) {
+    Value::MemberIterator it = val.FindMember(id);
+    return (it != val.MemberEnd() && it->value.IsNumber()) ? &it->value : 0;
+}
+
 } // namespace glTFCommon
 
 #endif // ASSIMP_BUILD_NO_GLTF_IMPORTER

+ 56 - 57
code/AssetLib/glTF/glTFExporter.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -41,78 +40,78 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 
 /** @file GltfExporter.h
-* Declares the exporter class to write a scene to a gltf/glb file
-*/
+ * Declares the exporter class to write a scene to a gltf/glb file
+ */
+#pragma once
 #ifndef AI_GLTFEXPORTER_H_INC
 #define AI_GLTFEXPORTER_H_INC
 
 #if !defined(ASSIMP_BUILD_NO_GLTF_EXPORTER) && !defined(ASSIMP_BUILD_NO_GLTF1_EXPORTER)
 
-#include <assimp/types.h>
 #include <assimp/material.h>
+#include <assimp/types.h>
 
-#include <sstream>
-#include <vector>
 #include <map>
 #include <memory>
+#include <sstream>
+#include <vector>
 
 struct aiScene;
 struct aiNode;
-struct aiMaterial;
 
-namespace glTF
-{
-    template<class T>
-    class Ref;
+namespace glTFCommon {
+template <class T>
+class Ref;
 
-    class Asset;
-    struct TexProperty;
-    struct Node;
 }
 
-namespace Assimp
-{
-    class IOSystem;
-    class IOStream;
-    class ExportProperties;
-
-    // ------------------------------------------------------------------------------------------------
-    /** Helper class to export a given scene to an glTF file. */
-    // ------------------------------------------------------------------------------------------------
-    class glTFExporter
-    {
-    public:
-        /// Constructor for a specific scene to export
-        glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
-            const ExportProperties* pProperties, bool binary);
-
-    private:
-
-        const char* mFilename;
-        IOSystem* mIOSystem;
-        std::shared_ptr<const aiScene> mScene;
-        const ExportProperties* mProperties;
-
-        std::map<std::string, unsigned int> mTexturesByPath;
-
-        std::shared_ptr<glTF::Asset> mAsset;
-
-        std::vector<unsigned char> mBodyData;
-
-        void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
-
-        void GetTexSampler(const aiMaterial* mat, glTF::TexProperty& prop);
-        void GetMatColorOrTex(const aiMaterial* mat, glTF::TexProperty& prop, const char* propName, int type, int idx, aiTextureType tt);
-        void ExportMetadata();
-        void ExportMaterials();
-        void ExportMeshes();
-        unsigned int ExportNodeHierarchy(const aiNode* n);
-        unsigned int ExportNode(const aiNode* node, glTF::Ref<glTF::Node>& parent);
-        void ExportScene();
-        void ExportAnimations();
-    };
-
-}
+namespace glTF {
+class Asset;
+struct TexProperty;
+struct Node;
+
+} // namespace glTF
+
+namespace Assimp {
+class IOSystem;
+class IOStream;
+class ExportProperties;
+
+// ------------------------------------------------------------------------------------------------
+/** Helper class to export a given scene to an glTF file. */
+// ------------------------------------------------------------------------------------------------
+class glTFExporter {
+public:
+    /// Constructor for a specific scene to export
+    glTFExporter(const char *filename, IOSystem *pIOSystem, const aiScene *pScene,
+            const ExportProperties *pProperties, bool binary);
+
+private:
+    const char *mFilename;
+    IOSystem *mIOSystem;
+    std::shared_ptr<const aiScene> mScene;
+    const ExportProperties *mProperties;
+
+    std::map<std::string, unsigned int> mTexturesByPath;
+
+    std::shared_ptr<glTF::Asset> mAsset;
+
+    std::vector<unsigned char> mBodyData;
+
+    void WriteBinaryData(IOStream *outfile, std::size_t sceneLength);
+
+    void GetTexSampler(const aiMaterial *mat, glTF::TexProperty &prop);
+    void GetMatColorOrTex(const aiMaterial *mat, glTF::TexProperty &prop, const char *propName, int type, int idx, aiTextureType tt);
+    void ExportMetadata();
+    void ExportMaterials();
+    void ExportMeshes();
+    unsigned int ExportNodeHierarchy(const aiNode *n);
+    unsigned int ExportNode(const aiNode *node, glTFCommon::Ref<glTF::Node> & parent);
+    void ExportScene();
+    void ExportAnimations();
+};
+
+} // namespace Assimp
 
 #endif // ASSIMP_BUILD_NO_GLTF_EXPORTER
 

+ 1 - 1
code/AssetLib/glTF/glTFImporter.h

@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 struct aiNode;
 
 namespace glTF {
-class Asset;
+    class Asset;
 
 }
 

+ 29 - 61
code/AssetLib/glTF2/glTF2Asset.h

@@ -65,6 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <string>
 #include <vector>
 
+// clang-format off
 #if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0)
 #pragma GCC diagnostic push
 #pragma GCC diagnostic ignored "-Wclass-memaccess"
@@ -75,37 +76,38 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <rapidjson/rapidjson.h>
 
 #if (__GNUC__ == 8 && __GNUC_MINOR__ >= 0)
-#pragma GCC diagnostic pop
+#   pragma GCC diagnostic pop
 #endif
 
 #ifdef ASSIMP_API
-#include <assimp/ByteSwapper.h>
-#include <assimp/DefaultIOSystem.h>
-#include <memory>
+#   include <assimp/ByteSwapper.h>
+#   include <assimp/DefaultIOSystem.h>
+#   include <memory>
 #else
-#include <memory>
-#define AI_SWAP4(p)
-#define ai_assert
+#   include <memory>
+#   define AI_SWAP4(p)
+#   define ai_assert
 #endif
 
 #if _MSC_VER > 1500 || (defined __GNUC___)
-#define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
+#   define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
 #else
-#define gltf_unordered_map map
-#define gltf_unordered_set set
+#   define gltf_unordered_map map
+#   define gltf_unordered_set set
 #endif
 
 #ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
-#include <unordered_map>
-#include <unordered_set>
-#if defined(_MSC_VER) && _MSC_VER <= 1600
-#define gltf_unordered_map tr1::unordered_map
-#define gltf_unordered_set tr1::unordered_set
-#else
-#define gltf_unordered_map unordered_map
-#define gltf_unordered_set unordered_set
-#endif
+#   include <unordered_map>
+#   include <unordered_set>
+#   if defined(_MSC_VER) && _MSC_VER <= 1600
+#       define gltf_unordered_map tr1::unordered_map
+#       define gltf_unordered_set tr1::unordered_set
+#   else
+#      define gltf_unordered_map unordered_map
+#       define gltf_unordered_set unordered_set
+#   endif
 #endif
+// clang-format on
 
 #include <assimp/StringUtils.h>
 
@@ -113,6 +115,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace glTF2 {
 
+using glTFCommon::Nullable;
+using glTFCommon::Ref;
 using glTFCommon::IOStream;
 using glTFCommon::IOSystem;
 using glTFCommon::shared_ptr;
@@ -319,44 +323,9 @@ const AttribType::Info
             { "SCALAR", 1 }, { "VEC2", 2 }, { "VEC3", 3 }, { "VEC4", 4 }, { "MAT2", 4 }, { "MAT3", 9 }, { "MAT4", 16 }
         };
 
-//! A reference to one top-level object, which is valid
-//! until the Asset instance is destroyed
-template <class T>
-class Ref {
-    std::vector<T *> *vector;
-    unsigned int index;
-
-public:
-    Ref() :
-            vector(0),
-            index(0) {}
-    Ref(std::vector<T *> &vec, unsigned int idx) :
-            vector(&vec),
-            index(idx) {}
-
-    inline unsigned int GetIndex() const { return index; }
-
-    operator bool() const { return vector != 0; }
-
-    T *operator->() { return (*vector)[index]; }
-
-    T &operator*() { return *((*vector)[index]); }
-};
-
-//! Helper struct to represent values that might not be present
-template <class T>
-struct Nullable {
-    T value;
-    bool isPresent;
-
-    Nullable() :
-            isPresent(false) {}
-    Nullable(T &val) :
-            value(val),
-            isPresent(true) {}
-};
 
 struct CustomExtension {
+
     //
     // A struct containing custom extension data added to a glTF2 file
     // Has to contain Object, Array, String, Double, Uint64, and Int64 at a minimum
@@ -553,7 +522,7 @@ public:
 
     void MarkAsSpecial() { mIsSpecial = true; }
 
-    bool IsSpecial() const { return mIsSpecial; }
+    bool IsSpecial() const override { return mIsSpecial; }
 
     std::string GetURI() { return std::string(this->id) + ".bin"; }
 
@@ -849,7 +818,7 @@ struct Material : public Object {
 
 //! A set of primitives to be rendered. A node can contain one or more meshes. A node's transform places the mesh in the scene.
 struct Mesh : public Object {
-    typedef std::vector<Ref<Accessor>> AccessorList;
+    using AccessorList = std::vector<Ref<Accessor>>;
 
     struct Primitive {
         PrimitiveMode mode;
@@ -880,7 +849,6 @@ struct Mesh : public Object {
 
     Mesh() {}
 
-    /// \fn void Read(Value& pJSON_Object, Asset& pAsset_Root)
     /// Get mesh data from JSON-object and place them to root asset.
     /// \param [in] pJSON_Object - reference to pJSON-object from which data are read.
     /// \param [out] pAsset_Root - reference to root asset where data will be stored.
@@ -1023,8 +991,8 @@ class LazyDict : public LazyDictBase {
     friend class Asset;
     friend class AssetWriter;
 
-    typedef typename std::gltf_unordered_map<unsigned int, unsigned int> Dict;
-    typedef typename std::gltf_unordered_map<std::string, unsigned int> IdDict;
+    using Dict = typename std::gltf_unordered_map<unsigned int, unsigned int>;
+    using IdDict = typename std::gltf_unordered_map<std::string, unsigned int>;
 
     std::vector<T *> mObjs; //! The read objects
     Dict mObjsByOIndex; //! The read objects accessible by original index
@@ -1087,7 +1055,7 @@ struct AssetMetadata {
 
 //! Root object for a glTF asset
 class Asset {
-    typedef std::gltf_unordered_map<std::string, int> IdMap;
+    using IdMap = std::gltf_unordered_map<std::string, int>;
 
     template <class T>
     friend class LazyDict;

+ 20 - 233
code/AssetLib/glTF2/glTF2Asset.inl

@@ -45,40 +45,43 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/StringUtils.h>
 #include <assimp/DefaultLogger.hpp>
 
+// clang-format off
 #ifdef ASSIMP_ENABLE_DRACO
 
 // Google draco library headers spew many warnings. Bad Google, no cookie
-#if _MSC_VER
-#pragma warning(push)
-#pragma warning(disable : 4018) // Signed/unsigned mismatch
-#pragma warning(disable : 4804) // Unsafe use of type 'bool'
-#elif defined(__clang__)
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wsign-compare"
-#elif defined(__GNUC__)
-#pragma GCC diagnostic push
-#if (__GNUC__ > 4)
-#pragma GCC diagnostic ignored "-Wbool-compare"
-#endif
-#pragma GCC diagnostic ignored "-Wsign-compare"
+#   if _MSC_VER
+#       pragma warning(push)
+#       pragma warning(disable : 4018) // Signed/unsigned mismatch
+#       pragma warning(disable : 4804) // Unsafe use of type 'bool'
+#   elif defined(__clang__)
+#       pragma clang diagnostic push
+#       pragma clang diagnostic ignored "-Wsign-compare"
+#   elif defined(__GNUC__)
+#       pragma GCC diagnostic push
+#       if (__GNUC__ > 4)
+#           pragma GCC diagnostic ignored "-Wbool-compare"
+#       endif
+#   pragma GCC diagnostic ignored "-Wsign-compare"
 #endif
 
 #include "draco/compression/decode.h"
 #include "draco/core/decoder_buffer.h"
 
 #if _MSC_VER
-#pragma warning(pop)
+#   pragma warning(pop)
 #elif defined(__clang__)
-#pragma clang diagnostic pop
+#   pragma clang diagnostic pop
 #elif defined(__GNUC__)
-#pragma GCC diagnostic pop
+#   pragma GCC diagnostic pop
 #endif
 #ifndef DRACO_MESH_COMPRESSION_SUPPORTED
-#error glTF: KHR_draco_mesh_compression: draco library must have DRACO_MESH_COMPRESSION_SUPPORTED
+#   error glTF: KHR_draco_mesh_compression: draco library must have DRACO_MESH_COMPRESSION_SUPPORTED
 #endif
 #endif
+// clang-format on
 
 using namespace Assimp;
+using namespace glTFCommon;
 
 namespace glTF2 {
 
@@ -88,222 +91,6 @@ namespace {
 // JSON Value reading helpers
 //
 
-template <class T>
-struct ReadHelper {
-    static bool Read(Value &val, T &out) {
-        return val.IsInt() ? out = static_cast<T>(val.GetInt()), true : false;
-    }
-};
-
-template <>
-struct ReadHelper<bool> {
-    static bool Read(Value &val, bool &out) {
-        return val.IsBool() ? out = val.GetBool(), true : false;
-    }
-};
-
-template <>
-struct ReadHelper<float> {
-    static bool Read(Value &val, float &out) {
-        return val.IsNumber() ? out = static_cast<float>(val.GetDouble()), true : false;
-    }
-};
-
-template <unsigned int N>
-struct ReadHelper<float[N]> {
-    static bool Read(Value &val, float (&out)[N]) {
-        if (!val.IsArray() || val.Size() != N) return false;
-        for (unsigned int i = 0; i < N; ++i) {
-            if (val[i].IsNumber())
-                out[i] = static_cast<float>(val[i].GetDouble());
-        }
-        return true;
-    }
-};
-
-template <>
-struct ReadHelper<const char *> {
-    static bool Read(Value &val, const char *&out) {
-        return val.IsString() ? (out = val.GetString(), true) : false;
-    }
-};
-
-template <>
-struct ReadHelper<std::string> {
-    static bool Read(Value &val, std::string &out) {
-        return val.IsString() ? (out = std::string(val.GetString(), val.GetStringLength()), true) : false;
-    }
-};
-
-template <>
-struct ReadHelper<uint64_t> {
-    static bool Read(Value &val, uint64_t &out) {
-        return val.IsUint64() ? out = val.GetUint64(), true : false;
-    }
-};
-
-template <>
-struct ReadHelper<int64_t> {
-    static bool Read(Value &val, int64_t &out) {
-        return val.IsInt64() ? out = val.GetInt64(), true : false;
-    }
-};
-
-template <class T>
-struct ReadHelper<Nullable<T>> {
-    static bool Read(Value &val, Nullable<T> &out) {
-        return out.isPresent = ReadHelper<T>::Read(val, out.value);
-    }
-};
-
-template <class T>
-inline static bool ReadValue(Value &val, T &out) {
-    return ReadHelper<T>::Read(val, out);
-}
-
-template <class T>
-inline static bool ReadMember(Value &obj, const char *id, T &out) {
-    if (!obj.IsObject()) {
-        return false;
-    }
-    Value::MemberIterator it = obj.FindMember(id);
-    if (it != obj.MemberEnd()) {
-        return ReadHelper<T>::Read(it->value, out);
-    }
-    return false;
-}
-
-template <class T>
-inline static T MemberOrDefault(Value &obj, const char *id, T defaultValue) {
-    T out;
-    return ReadMember(obj, id, out) ? out : defaultValue;
-}
-
-inline Value *FindMember(Value &val, const char *id) {
-    if (!val.IsObject()) {
-        return nullptr;
-    }
-    Value::MemberIterator it = val.FindMember(id);
-    return (it != val.MemberEnd()) ? &it->value : nullptr;
-}
-
-template<int N>
-inline void throwUnexpectedTypeError(const char (&expectedTypeName)[N], const char* memberId, const char* context, const char* extraContext) {
-    std::string fullContext = context;
-    if (extraContext && (strlen(extraContext) > 0))
-    {
-        fullContext = fullContext + " (" + extraContext + ")";
-    }
-    throw DeadlyImportError("Member \"", memberId, "\" was not of type \"", expectedTypeName, "\" when reading ", fullContext);
-}
-
-// Look-up functions with type checks. Context and extra context help the user identify the problem if there's an error.
-
-inline Value *FindStringInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
-    if (!val.IsObject()) {
-        return nullptr;
-    }
-    Value::MemberIterator it = val.FindMember(memberId);
-    if (it == val.MemberEnd()) {
-        return nullptr;
-    }
-    if (!it->value.IsString()) {
-        throwUnexpectedTypeError("string", memberId, context, extraContext);
-    }
-    return &it->value;
-}
-
-inline Value *FindNumberInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
-    if (!val.IsObject()) {
-        return nullptr;
-    }
-    Value::MemberIterator it = val.FindMember(memberId);
-    if (it == val.MemberEnd()) {
-        return nullptr;
-    }
-    if (!it->value.IsNumber()) {
-        throwUnexpectedTypeError("number", memberId, context, extraContext);
-    }
-    return &it->value;
-}
-
-inline Value *FindUIntInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
-    if (!val.IsObject()) {
-        return nullptr;
-    }
-    Value::MemberIterator it = val.FindMember(memberId);
-    if (it == val.MemberEnd()) {
-        return nullptr;
-    }
-    if (!it->value.IsUint()) {
-        throwUnexpectedTypeError("uint", memberId, context, extraContext);
-    }
-    return &it->value;
-}
-
-inline Value *FindArrayInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
-    if (!val.IsObject()) {
-        return nullptr;
-    }
-    Value::MemberIterator it = val.FindMember(memberId);
-    if (it == val.MemberEnd()) {
-        return nullptr;
-    }
-    if (!it->value.IsArray()) {
-        throwUnexpectedTypeError("array", memberId, context, extraContext);
-    }
-    return &it->value;
-}
-
-inline Value *FindObjectInContext(Value &val, const char *memberId, const char* context, const char* extraContext = nullptr) {
-    if (!val.IsObject()) {
-        return nullptr;
-    }
-    Value::MemberIterator it = val.FindMember(memberId);
-    if (it == val.MemberEnd()) {
-        return nullptr;
-    }
-    if (!it->value.IsObject()) {
-        throwUnexpectedTypeError("object", memberId, context, extraContext);
-    }
-    return &it->value;
-}
-
-inline Value *FindExtensionInContext(Value &val, const char *extensionId, const char* context, const char* extraContext = nullptr) {
-    if (Value *extensionList = FindObjectInContext(val, "extensions", context, extraContext)) {
-        if (Value *extension = FindObjectInContext(*extensionList, extensionId, context, extraContext)) {
-            return extension;
-        }
-    }
-    return nullptr;
-}
-
-// Overloads when the value is the document.
-
-inline Value *FindString(Document &doc, const char *memberId) {
-    return FindStringInContext(doc, memberId, "the document");
-}
-
-inline Value *FindNumber(Document &doc, const char *memberId) {
-    return FindNumberInContext(doc, memberId, "the document");
-}
-
-inline Value *FindUInt(Document &doc, const char *memberId) {
-    return FindUIntInContext(doc, memberId, "the document");
-}
-
-inline Value *FindArray(Document &val, const char *memberId) {
-    return FindArrayInContext(val, memberId, "the document");
-}
-
-inline Value *FindObject(Document &doc, const char *memberId) {
-    return FindObjectInContext(doc, memberId, "the document");
-}
-
-inline Value *FindExtension(Value &val, const char *extensionId) {
-    return FindExtensionInContext(val, extensionId, "the document");
-}
-
 inline CustomExtension ReadExtensions(const char *name, Value &obj) {
     CustomExtension ret;
     ret.name = name;

+ 1 - 1
code/AssetLib/glTF2/glTF2Exporter.cpp

@@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 
 // Header files, standard library.
-#include <inttypes.h>
+#include <cinttypes>
 #include <limits>
 #include <memory>
 

+ 76 - 76
code/AssetLib/glTF2/glTF2Exporter.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -48,93 +47,94 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF2_IMPORTER)
 
-#include <assimp/types.h>
 #include <assimp/material.h>
+#include <assimp/types.h>
 
-#include <sstream>
-#include <vector>
 #include <map>
 #include <memory>
+#include <sstream>
+#include <vector>
 
 struct aiScene;
 struct aiNode;
 struct aiMaterial;
 
-namespace glTF2
-{
-    template<class T>
-    class Ref;
-
-    class Asset;
-    struct TexProperty;
-    struct TextureInfo;
-    struct NormalTextureInfo;
-    struct OcclusionTextureInfo;
-    struct Node;
-    struct Texture;
-    struct PbrSpecularGlossiness;
-    struct MaterialSheen;
-    struct MaterialClearcoat;
-    struct MaterialTransmission;
-
-    // Vec/matrix types, as raw float arrays
-	typedef float (vec2)[2];
-    typedef float (vec3)[3];
-    typedef float (vec4)[4];
-}
-
-namespace Assimp
-{
-    class IOSystem;
-    class IOStream;
-    class ExportProperties;
-
-    // ------------------------------------------------------------------------------------------------
-    /** Helper class to export a given scene to an glTF file. */
-    // ------------------------------------------------------------------------------------------------
-    class glTF2Exporter {
-    public:
-        /// Constructor for a specific scene to export
-        glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
-            const ExportProperties* pProperties, bool binary);
-        ~glTF2Exporter();
-
-    protected:
-        void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
-        void GetTexSampler(const aiMaterial& mat, glTF2::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
-        void GetMatTexProp(const aiMaterial& mat, unsigned int& prop, const char* propName, aiTextureType tt, unsigned int idx);
-        void GetMatTexProp(const aiMaterial& mat, float& prop, const char* propName, aiTextureType tt, unsigned int idx);
-        void GetMatTex(const aiMaterial& mat, glTF2::Ref<glTF2::Texture>& texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot);
-        void GetMatTex(const aiMaterial& mat, glTF2::TextureInfo& prop, aiTextureType tt, unsigned int slot);
-        void GetMatTex(const aiMaterial& mat, glTF2::NormalTextureInfo& prop, aiTextureType tt, unsigned int slot);
-        void GetMatTex(const aiMaterial& mat, glTF2::OcclusionTextureInfo& prop, aiTextureType tt, unsigned int slot);
-        aiReturn GetMatColor(const aiMaterial& mat, glTF2::vec4& prop, const char* propName, int type, int idx) const;
-        aiReturn GetMatColor(const aiMaterial& mat, glTF2::vec3& prop, const char* propName, int type, int idx) const;
-        bool GetMatSpecGloss(const aiMaterial& mat, glTF2::PbrSpecularGlossiness& pbrSG);
-        bool GetMatSheen(const aiMaterial& mat, glTF2::MaterialSheen& sheen);
-        bool GetMatClearcoat(const aiMaterial& mat, glTF2::MaterialClearcoat& clearcoat);
-        bool GetMatTransmission(const aiMaterial& mat, glTF2::MaterialTransmission& transmission);
-        void ExportMetadata();
-        void ExportMaterials();
-        void ExportMeshes();
-        void MergeMeshes();
-        unsigned int ExportNodeHierarchy(const aiNode* n);
-        unsigned int ExportNode(const aiNode* node, glTF2::Ref<glTF2::Node>& parent);
-        void ExportScene();
-        void ExportAnimations();
-
-    private:
-        const char* mFilename;
-        IOSystem* mIOSystem;
-        const aiScene* mScene;
-        const ExportProperties* mProperties;
-        std::map<std::string, unsigned int> mTexturesByPath;
-        std::shared_ptr<glTF2::Asset> mAsset;
-        std::vector<unsigned char> mBodyData;
-    };
+namespace glTFCommon {
+template <class T>
+class Ref;
 
 }
 
+namespace glTF2 {
+class Asset;
+struct TexProperty;
+struct TextureInfo;
+struct NormalTextureInfo;
+struct OcclusionTextureInfo;
+struct Node;
+struct Texture;
+struct PbrSpecularGlossiness;
+struct MaterialSheen;
+struct MaterialClearcoat;
+struct MaterialTransmission;
+
+// Vec/matrix types, as raw float arrays
+typedef float(vec2)[2];
+typedef float(vec3)[3];
+typedef float(vec4)[4];
+} // namespace glTF2
+
+namespace Assimp {
+class IOSystem;
+class IOStream;
+class ExportProperties;
+
+// ------------------------------------------------------------------------------------------------
+/** Helper class to export a given scene to an glTF file. */
+// ------------------------------------------------------------------------------------------------
+class glTF2Exporter {
+public:
+    /// Constructor for a specific scene to export
+    glTF2Exporter(const char *filename, IOSystem *pIOSystem, const aiScene *pScene,
+            const ExportProperties *pProperties, bool binary);
+    ~glTF2Exporter();
+
+protected:
+    void WriteBinaryData(IOStream *outfile, std::size_t sceneLength);
+    void GetTexSampler(const aiMaterial &mat, glTFCommon::Ref<glTF2::Texture> texture, aiTextureType tt, unsigned int slot);
+    void GetMatTexProp(const aiMaterial &mat, unsigned int &prop, const char *propName, aiTextureType tt, unsigned int idx);
+    void GetMatTexProp(const aiMaterial &mat, float &prop, const char *propName, aiTextureType tt, unsigned int idx);
+    void GetMatTex(const aiMaterial &mat, glTFCommon::Ref<glTF2::Texture> &texture, unsigned int &texCoord, aiTextureType tt, unsigned int slot);
+    void GetMatTex(const aiMaterial &mat, glTF2::TextureInfo &prop, aiTextureType tt, unsigned int slot);
+    void GetMatTex(const aiMaterial &mat, glTF2::NormalTextureInfo &prop, aiTextureType tt, unsigned int slot);
+    void GetMatTex(const aiMaterial &mat, glTF2::OcclusionTextureInfo &prop, aiTextureType tt, unsigned int slot);
+    aiReturn GetMatColor(const aiMaterial &mat, glTF2::vec4 &prop, const char *propName, int type, int idx) const;
+    aiReturn GetMatColor(const aiMaterial &mat, glTF2::vec3 &prop, const char *propName, int type, int idx) const;
+    bool GetMatSpecGloss(const aiMaterial &mat, glTF2::PbrSpecularGlossiness &pbrSG);
+    bool GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &sheen);
+    bool GetMatClearcoat(const aiMaterial &mat, glTF2::MaterialClearcoat &clearcoat);
+    bool GetMatTransmission(const aiMaterial &mat, glTF2::MaterialTransmission &transmission);
+    void ExportMetadata();
+    void ExportMaterials();
+    void ExportMeshes();
+    void MergeMeshes();
+    unsigned int ExportNodeHierarchy(const aiNode *n);
+    unsigned int ExportNode(const aiNode *node, glTFCommon::Ref<glTF2::Node> &parent);
+    void ExportScene();
+    void ExportAnimations();
+
+private:
+    const char *mFilename;
+    IOSystem *mIOSystem;
+    const aiScene *mScene;
+    const ExportProperties *mProperties;
+    std::map<std::string, unsigned int> mTexturesByPath;
+    std::shared_ptr<glTF2::Asset> mAsset;
+    std::vector<unsigned char> mBodyData;
+};
+
+} // namespace Assimp
+
 #endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
 
 #endif // AI_GLTF2EXPORTER_H_INC

+ 4 - 4
code/AssetLib/glTF2/glTF2Importer.cpp

@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AssetLib/glTF2/glTF2Importer.h"
 #include "PostProcessing/MakeVerboseFormat.h"
 #include "AssetLib/glTF2/glTF2Asset.h"
+
 #if !defined(ASSIMP_BUILD_NO_EXPORT)
 #include "AssetLib/glTF2/glTF2AssetWriter.h"
 #endif
@@ -57,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/Importer.hpp>
 #include <assimp/commonMetaData.h>
+#include <assimp/DefaultIOSystem.h>
 
 #include <memory>
 #include <unordered_map>
@@ -1536,11 +1538,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
             if (ext) {
                 if (strcmp(ext, "jpeg") == 0) {
                     ext = "jpg";
-                }
-                else if(strcmp(ext, "ktx2") == 0) { //basisu: ktx remains
+                } else if(strcmp(ext, "ktx2") == 0) { //basisu: ktx remains
                     ext = "kx2";
-                }
-                else if(strcmp(ext, "basis") == 0) { //basisu
+                } else if(strcmp(ext, "basis") == 0) { //basisu
                     ext = "bu";
                 }
 

+ 1 - 2
code/AssetLib/glTF2/glTF2Importer.h

@@ -43,12 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_GLTF2IMPORTER_H_INC
 
 #include <assimp/BaseImporter.h>
-#include <assimp/DefaultIOSystem.h>
 
 struct aiNode;
 
 namespace glTF2 {
-class Asset;
+    class Asset;
 }
 
 namespace Assimp {