Parcourir la source

Created exporter class and fixed a few bugs

Otger il y a 9 ans
Parent
commit
b307ec643d
7 fichiers modifiés avec 546 ajouts et 29 suppressions
  1. 3 0
      code/CMakeLists.txt
  2. 9 0
      code/Exporter.cpp
  3. 401 0
      code/glTFExporter.cpp
  4. 87 0
      code/glTFExporter.h
  5. 28 11
      code/glTFImporter.cpp
  6. 0 18
      code/glTFImporter.h
  7. 18 0
      code/glTFUtil.h

+ 3 - 0
code/CMakeLists.txt

@@ -568,6 +568,9 @@ ADD_ASSIMP_IMPORTER(GLTF
   glTFUtil.cpp
   glTFUtil.cpp
   glTFUtil.h
   glTFUtil.h
   glTFFileData.h
   glTFFileData.h
+
+  glTFExporter.h
+  glTFExporter.cpp
 )
 )
 
 
 SET( Step_SRCS
 SET( Step_SRCS

+ 9 - 0
code/Exporter.cpp

@@ -87,6 +87,8 @@ void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportPro
 void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 
 
@@ -135,6 +137,13 @@ Exporter::ExportFormatEntry gExporters[] =
         aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
         aiProcess_Triangulate | aiProcess_SortByPType | aiProcess_JoinIdenticalVertices),
 #endif
 #endif
 
 
+#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
+    Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
+        aiProcess_JoinIdenticalVertices),
+    Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
+        aiProcess_JoinIdenticalVertices),
+#endif
+
 #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
 #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
     Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
     Exporter::ExportFormatEntry( "assbin", "Assimp Binary", "assbin" , &ExportSceneAssbin, 0),
 #endif
 #endif

+ 401 - 0
code/glTFExporter.cpp

@@ -0,0 +1,401 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
+
+#include "glTFExporter.h"
+#include "Exceptional.h"
+#include "StringComparison.h"
+#include "ByteSwapper.h"
+
+#include <assimp/version.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/Exporter.hpp>
+#include <assimp/material.h>
+#include <assimp/scene.h>
+
+#include <boost/foreach.hpp>
+#include <boost/scoped_ptr.hpp>
+
+#define RAPIDJSON_HAS_STDSTRING 1
+#include <rapidjson/document.h>
+#include <rapidjson/writer.h>
+#include <rapidjson/prettywriter.h>
+#include <rapidjson/stringbuffer.h>
+
+#include "glTFFileData.h"
+#include "glTFUtil.h"
+
+using namespace rapidjson;
+
+using namespace Assimp;
+using namespace Assimp::glTF;
+
+namespace Assimp {
+
+    // ------------------------------------------------------------------------------------------------
+    // Worker function for exporting a scene to GLTF. Prototyped and registered in Exporter.cpp
+    void ExportSceneGLTF(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+    {
+        // invoke the exporter
+        glTFExporter exporter(pFile, pIOSystem, pScene, pProperties, false);
+    }
+
+    // ------------------------------------------------------------------------------------------------
+    // Worker function for exporting a scene to GLB. Prototyped and registered in Exporter.cpp
+    void ExportSceneGLB(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+    {
+        // invoke the exporter
+        glTFExporter exporter(pFile, pIOSystem, pScene, pProperties, true);
+    }
+
+} // end of namespace Assimp
+
+
+
+class glTFSceneExporter
+{
+    typedef std::gltf_unordered_map<std::string, int> IdMap;
+
+    Document& mDoc;
+    MemoryPoolAllocator<>& mAl;
+
+    const aiScene* mScene;
+
+    std::string mRootNodeId;
+
+    std::vector<std::string> mMeshIds;
+
+    IdMap mUsedIds;
+
+public:
+    glTFSceneExporter(Document& doc, const aiScene* pScene)
+        : mDoc(doc)
+        , mAl(doc.GetAllocator())
+        , mScene(pScene)
+    {
+        doc.SetObject();
+
+        for (unsigned int i = 0; i < pScene->mNumAnimations; ++i) {
+
+        }
+
+        for (unsigned int i = 0; i < pScene->mNumCameras; ++i) {
+
+        }
+
+        for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
+
+        }
+
+        for (unsigned int i = 0; i < pScene->mNumLights; ++i) {
+
+        }
+
+        for (unsigned int i = 0; i < pScene->mNumMaterials; ++i) {
+
+        }
+
+
+        AddMeshes();
+
+        for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {
+
+        }
+
+        AddNodes();
+
+        CreateScene();
+    }
+
+    inline void Pushf(Value& val, float f)
+    {
+        val.PushBack(Value(f).Move(), mAl);
+    }
+
+    inline void SetMatrix(Value& v, const aiMatrix4x4& m)
+    {
+        v.SetArray();
+        v.Reserve(16, mAl);
+
+        Pushf(v, m.a1); Pushf(v, m.b1); Pushf(v, m.c1); Pushf(v, m.d1);
+        Pushf(v, m.a2); Pushf(v, m.b2); Pushf(v, m.c2); Pushf(v, m.d2);
+        Pushf(v, m.a3); Pushf(v, m.b3); Pushf(v, m.c3); Pushf(v, m.d3);
+        Pushf(v, m.a4); Pushf(v, m.b4); Pushf(v, m.c4); Pushf(v, m.d4);
+    }
+
+    void AddMeshes()
+    {
+        if (mScene->mNumMeshes == 0) return;
+
+        Value meshes;
+        meshes.SetObject();
+
+        mMeshIds.reserve(mScene->mNumMeshes);
+        for (unsigned int i = 0; i < mScene->mNumMeshes; ++i) {
+            aiMesh* m = mScene->mMeshes[i];
+            std::string meshId = FindID(m->mName, "mesh");
+            mMeshIds.push_back(meshId);
+
+            Value mesh;
+            mesh.SetObject();
+            {
+                Value primitives;
+                primitives.SetObject();
+
+                
+                mesh.AddMember("primitives", primitives, mAl);
+            }
+
+            meshes.AddMember(StringRef(mMeshIds.back()), mesh, mAl);
+        }
+
+        mDoc.AddMember("meshes", meshes, mAl);
+    }
+
+    void AddNodes()
+    {
+        if (!mScene->mRootNode) return;
+
+        Value nodes;
+        nodes.SetObject();
+
+        mRootNodeId = AddNode(nodes, mScene->mRootNode);
+
+        mDoc.AddMember("nodes", nodes, mAl);
+    }
+
+
+    std::string AddNode(Value& nodes, const aiNode* n)
+    {
+        std::string nodeId = FindID(n->mName, "node");
+
+        Value node;
+        node.SetObject();
+
+        if (!n->mTransformation.IsIdentity()) {
+            Value matrix;
+            SetMatrix(matrix, n->mTransformation);
+            node.AddMember("matrix", matrix, mAl);
+        }
+
+        if (n->mNumMeshes > 0) {
+            Value meshes;
+            meshes.SetArray();
+            for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
+                meshes.PushBack(StringRef(mMeshIds[n->mMeshes[i]]), mAl);
+            }
+            node.AddMember("meshes", meshes, mAl);
+        }
+
+        if (n->mNumChildren > 0) {
+            Value children;
+            children.SetArray();
+            for (unsigned int i = 0; i < n->mNumChildren; ++i) {
+                std::string id = AddNode(nodes, n->mChildren[i]);
+                children.PushBack(Value(id, mAl), mAl);
+            }
+            node.AddMember("children", children, mAl);
+        }
+
+        nodes.AddMember(Value(nodeId, mAl), node, mAl);
+
+        return nodeId;
+    }
+
+    void CreateScene()
+    {
+        const char* sceneName = "defaultScene";
+
+        mDoc.AddMember("scene", Value(sceneName, mAl), mAl);
+
+        Value scenes;
+        scenes.SetObject();
+        {
+            Value scene;
+            scene.SetObject();
+            {
+                Value nodes;
+                nodes.SetArray();
+
+                if (!mRootNodeId.empty()) {
+                    nodes.PushBack(StringRef(mRootNodeId), mAl);
+                }
+
+                scene.AddMember("nodes", nodes, mAl);
+            }
+            scenes.AddMember(Value(sceneName, mAl), scene, mAl);
+        }
+        mDoc.AddMember("scenes", scenes, mAl);
+    }
+
+    std::string FindID(const aiString& str, const char* suffix)
+    {
+        std::string id = str.C_Str();
+
+        IdMap::iterator it;
+
+        if (!id.empty()) {
+            it = mUsedIds.find(id);
+            if (it == mUsedIds.end()) goto found;
+
+            id += "-";
+        }
+
+        id += suffix;
+
+        it = mUsedIds.find(id);
+        if (it == mUsedIds.end()) goto found;
+
+        char buffer[256];
+        int offset = sprintf(buffer, "%s-", id.c_str());
+        for (int i = 0; ; ++i) {
+            ASSIMP_itoa10(buffer + offset, sizeof(buffer), i);
+
+            id = buffer;
+            it = mUsedIds.find(id);
+            if (it == mUsedIds.end()) goto found;
+        }
+
+    found:
+        mUsedIds[id] = true;
+        return id;
+    }
+};
+
+
+
+glTFExporter::glTFExporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
+                           const ExportProperties* pProperties, bool isBinary)
+    : mFilename(filename)
+    , mIOSystem(pIOSystem)
+    , mScene(pScene)
+    , mProperties(pProperties)
+    , mIsBinary(isBinary)
+{
+    boost::scoped_ptr<IOStream> outfile(pIOSystem->Open(mFilename, "wt"));
+    if (outfile == 0) {
+        throw DeadlyExportError("Could not open output file: " + std::string(mFilename));
+    }
+
+    if (isBinary) {
+        // we will write the header later, skip its size
+        outfile->Seek(sizeof(GLB_Header), aiOrigin_SET);
+    }
+
+
+    Document doc;
+    StringBuffer docBuffer;
+    {
+        glTFSceneExporter exportScene(doc, mScene);
+
+        bool pretty = true; 
+        if (!isBinary && pretty) {
+            PrettyWriter<StringBuffer> writer(docBuffer);
+            doc.Accept(writer);
+        }
+        else {
+            Writer<StringBuffer> writer(docBuffer);
+            doc.Accept(writer);
+        }
+    }
+
+    if (outfile->Write(docBuffer.GetString(), docBuffer.GetSize(), 1) != 1) {
+        throw DeadlyExportError("Failed to write scene data!"); 
+    }
+
+    if (isBinary) {
+        WriteBinaryData(outfile.get(), docBuffer.GetSize());
+    }
+}
+
+
+void glTFExporter::WriteBinaryData(IOStream* outfile, std::size_t sceneLength)
+{
+    //
+    // write the body data
+    //
+
+    if (!mBodyData.empty()) {
+        std::size_t bodyOffset = sizeof(GLB_Header) + sceneLength;
+        bodyOffset = (bodyOffset + 3) & ~3; // Round up to next multiple of 4
+
+        outfile->Seek(bodyOffset, aiOrigin_SET);
+
+        if (outfile->Write(&mBodyData[0], mBodyData.size(), 1) != 1) {
+            throw DeadlyExportError("Failed to write body data!");
+        }
+    }
+
+
+    //
+    // write the header
+    //
+
+    outfile->Seek(0, aiOrigin_SET);
+
+    GLB_Header header;
+    memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic));
+
+    header.version = 1;
+    AI_SWAP4(header.version);
+
+    header.length = sizeof(header) + sceneLength + mBodyData.size();
+    AI_SWAP4(header.length);
+
+    header.sceneLength = sceneLength;
+    AI_SWAP4(header.sceneLength);
+
+    header.sceneFormat = SceneFormat_JSON;
+    AI_SWAP4(header.sceneFormat);
+
+    if (outfile->Write(&header, sizeof(header), 1) != 1) {
+        throw DeadlyExportError("Failed to write the header!");
+    }
+}
+
+
+
+
+#endif // ASSIMP_BUILD_NO_GLTF_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT

+ 87 - 0
code/glTFExporter.h

@@ -0,0 +1,87 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2015, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+
+/** @file GltfExporter.h
+* Declares the exporter class to write a scene to a gltf/glb file
+*/
+#ifndef AI_GLTFEXPORTER_H_INC
+#define AI_GLTFEXPORTER_H_INC
+
+#include <assimp/types.h>
+#include <sstream>
+#include <vector>
+#include <map>
+
+struct aiScene;
+
+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;
+        const aiScene* mScene;
+        const ExportProperties* mProperties;
+        bool mIsBinary;
+
+        std::vector<unsigned char> mBodyData;
+
+        void WriteBinaryData(IOStream* outfile, std::size_t sceneLength);
+
+    };
+
+}
+
+#endif

+ 28 - 11
code/glTFImporter.cpp

@@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "glTFFileData.h"
 #include "glTFFileData.h"
 #include "glTFUtil.h"
 #include "glTFUtil.h"
 
 
+#define RAPIDJSON_HAS_STDSTRING 1
 #include <rapidjson/rapidjson.h>
 #include <rapidjson/rapidjson.h>
 #include <rapidjson/document.h>
 #include <rapidjson/document.h>
 #include <rapidjson/error/en.h>
 #include <rapidjson/error/en.h>
@@ -290,6 +291,10 @@ class glTFReader
                 mScene->mRootNode = root;
                 mScene->mRootNode = root;
             }
             }
         }
         }
+
+        //if (!mScene->mRootNode) {
+            //mScene->mRootNode = new aiNode("EMPTY");
+        //}
     }
     }
 
 
     void SetMaterialColorProperty(aiMaterial* mat, Value& vals, const char* propName, aiTextureType texType,
     void SetMaterialColorProperty(aiMaterial* mat, Value& vals, const char* propName, aiTextureType texType,
@@ -550,13 +555,15 @@ struct Accessor
     template<class T>
     template<class T>
     void ExtractData(T*& outData, unsigned int* outCount = 0, unsigned int* outComponents = 0)
     void ExtractData(T*& outData, unsigned int* outCount = 0, unsigned int* outComponents = 0)
     {
     {
-        if (!data) return;
+        ai_assert(data);
 
 
         const std::size_t totalSize = elemSize * count;
         const std::size_t totalSize = elemSize * count;
 
 
         const std::size_t targetElemSize = sizeof(T);
         const std::size_t targetElemSize = sizeof(T);
         ai_assert(elemSize <= targetElemSize);
         ai_assert(elemSize <= targetElemSize);
 
 
+        ai_assert(count*byteStride <= bufferView->byteLength);
+
         outData = new T[count];
         outData = new T[count];
         if (byteStride == elemSize && targetElemSize == elemSize) {
         if (byteStride == elemSize && targetElemSize == elemSize) {
             memcpy(outData, data, totalSize);
             memcpy(outData, data, totalSize);
@@ -574,6 +581,8 @@ struct Accessor
     template<class T = unsigned int>
     template<class T = unsigned int>
     T GetValue(int i)
     T GetValue(int i)
     {
     {
+        ai_assert(data);
+        ai_assert(i*byteStride < bufferView->byteLength);
         T value = T();
         T value = T();
         memcpy(&value, data + i*byteStride, elemSize);
         memcpy(&value, data + i*byteStride, elemSize);
         //value >>= 8 * (sizeof(T) - elemSize);
         //value >>= 8 * (sizeof(T) - elemSize);
@@ -708,9 +717,11 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
                     else if (strcmp(attr, "NORMAL") == 0) {
                     else if (strcmp(attr, "NORMAL") == 0) {
                         accessor->ExtractData(aimesh->mNormals);
                         accessor->ExtractData(aimesh->mNormals);
                     }
                     }
-                    else if (strncmp(attr, "TEXCOORD_", 9) == 0) {
+                   else if (strncmp(attr, "TEXCOORD_", 9) == 0) {
                         int idx = attr[9] - '0';
                         int idx = attr[9] - '0';
-                        accessor->ExtractData(aimesh->mTextureCoords[idx], 0, &aimesh->mNumUVComponents[idx]);
+                        if (idx >= 0 && idx <= AI_MAX_NUMBER_OF_TEXTURECOORDS) {
+                            accessor->ExtractData(aimesh->mTextureCoords[idx], 0, &aimesh->mNumUVComponents[idx]);
+                        }
                     }
                     }
                 }
                 }
             }
             }
@@ -727,7 +738,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
                         case PrimitiveMode_POINTS: {
                         case PrimitiveMode_POINTS: {
                             nFaces = acc->count;
                             nFaces = acc->count;
                             faces = new aiFace[nFaces];
                             faces = new aiFace[nFaces];
-                            for (unsigned i = 0; i < acc->count; ++i) {
+                            for (unsigned int i = 0; i < acc->count; ++i) {
                                 setFace(faces[i], acc->GetValue(i));
                                 setFace(faces[i], acc->GetValue(i));
                             }
                             }
                             break;
                             break;
@@ -736,7 +747,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
                         case PrimitiveMode_LINES: {
                         case PrimitiveMode_LINES: {
                             nFaces = acc->count / 2;
                             nFaces = acc->count / 2;
                             faces = new aiFace[nFaces];
                             faces = new aiFace[nFaces];
-                            for (unsigned i = 0; i < acc->count; i += 2) {
+                            for (unsigned int i = 0; i < acc->count; i += 2) {
                                 setFace(faces[i / 2], acc->GetValue(i), acc->GetValue(i + 1));
                                 setFace(faces[i / 2], acc->GetValue(i), acc->GetValue(i + 1));
                             }
                             }
                             break;
                             break;
@@ -747,7 +758,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
                             nFaces = acc->count - ((primitiveMode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
                             nFaces = acc->count - ((primitiveMode == PrimitiveMode_LINE_STRIP) ? 1 : 0);
                             faces = new aiFace[nFaces];
                             faces = new aiFace[nFaces];
                             setFace(faces[0], acc->GetValue(0), acc->GetValue(1));
                             setFace(faces[0], acc->GetValue(0), acc->GetValue(1));
-                            for (unsigned i = 2; i < acc->count; ++i) {
+                            for (unsigned int i = 2; i < acc->count; ++i) {
                                 setFace(faces[i - 1], faces[i - 2].mIndices[1], acc->GetValue(i));
                                 setFace(faces[i - 1], faces[i - 2].mIndices[1], acc->GetValue(i));
                             }
                             }
                             if (primitiveMode == PrimitiveMode_LINE_LOOP) { // close the loop
                             if (primitiveMode == PrimitiveMode_LINE_LOOP) { // close the loop
@@ -759,7 +770,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
                         case PrimitiveMode_TRIANGLES: {
                         case PrimitiveMode_TRIANGLES: {
                             nFaces = acc->count / 3;
                             nFaces = acc->count / 3;
                             faces = new aiFace[nFaces];
                             faces = new aiFace[nFaces];
-                            for (unsigned i = 0; i < acc->count; i += 3) {
+                            for (unsigned int i = 0; i < acc->count; i += 3) {
                                 setFace(faces[i / 3], acc->GetValue(i), acc->GetValue(i + 1), acc->GetValue(i + 2));
                                 setFace(faces[i / 3], acc->GetValue(i), acc->GetValue(i + 1), acc->GetValue(i + 2));
                             }
                             }
                             break;
                             break;
@@ -768,7 +779,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
                             nFaces = acc->count - 2;
                             nFaces = acc->count - 2;
                             faces = new aiFace[nFaces];
                             faces = new aiFace[nFaces];
                             setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2));
                             setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2));
-                            for (unsigned i = 3; i < acc->count; ++i) {
+                            for (unsigned int i = 3; i < acc->count; ++i) {
                                 setFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], acc->GetValue(i));
                                 setFace(faces[i - 2], faces[i - 1].mIndices[1], faces[i - 1].mIndices[2], acc->GetValue(i));
                             }
                             }
                             break;
                             break;
@@ -777,7 +788,7 @@ Range glTFReader::LoadMesh(const char* id, Value& mesh)
                             nFaces = acc->count - 2;
                             nFaces = acc->count - 2;
                             faces = new aiFace[nFaces];
                             faces = new aiFace[nFaces];
                             setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2));
                             setFace(faces[0], acc->GetValue(0), acc->GetValue(1), acc->GetValue(2));
-                            for (unsigned i = 3; i < acc->count; ++i) {
+                            for (unsigned int i = 3; i < acc->count; ++i) {
                                 setFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], acc->GetValue(i));
                                 setFace(faces[i - 2], faces[0].mIndices[0], faces[i - 1].mIndices[2], acc->GetValue(i));
                             }
                             }
                             break;
                             break;
@@ -986,8 +997,10 @@ aiNode* glTFReader::LoadNode(const char* id, Value& node)
             if (child.IsString()) {
             if (child.IsString()) {
                 // get/create the child node
                 // get/create the child node
                 aiNode* aichild = mNodes.Get(child.GetString());
                 aiNode* aichild = mNodes.Get(child.GetString());
-                aichild->mParent = ainode;
-                ainode->mChildren[ainode->mNumChildren++] = aichild;
+                if (aichild) {
+                    aichild->mParent = ainode;
+                    ainode->mChildren[ainode->mNumChildren++] = aichild;
+                }
             }
             }
         }
         }
     }
     }
@@ -1185,4 +1198,8 @@ void glTFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IO
     // import the data
     // import the data
     glTFReader reader(pScene, doc, *pIOHandler, bodyBuffer);
     glTFReader reader(pScene, doc, *pIOHandler, bodyBuffer);
     reader.Load();
     reader.Load();
+
+    if (pScene->mNumMeshes == 0) {
+        pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+    }
 }
 }

+ 0 - 18
code/glTFImporter.h

@@ -44,24 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "LogAux.h"
 #include "LogAux.h"
 #include "DefaultIOSystem.h"
 #include "DefaultIOSystem.h"
 
 
-#if _MSC_VER > 1500 || (defined __GNUC___)
-#   define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
-#   else
-#   define gltf_unordered_map map
-#   define gltf_unordered_multimap multimap
-#endif
-
-#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
-#   include <unordered_map>
-#   if _MSC_VER > 1600
-#       define gltf_unordered_map unordered_map
-#       define gltf_unordered_multimap unordered_multimap
-#   else
-#       define gltf_unordered_map tr1::unordered_map
-#       define gltf_unordered_multimap tr1::unordered_multimap
-#   endif
-#endif
-
 namespace Assimp {
 namespace Assimp {
 
 
 /**
 /**

+ 18 - 0
code/glTFUtil.h

@@ -44,6 +44,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 //#include "MemoryIOWrapper.h"
 //#include "MemoryIOWrapper.h"
 #include "StringComparison.h"
 #include "StringComparison.h"
 
 
+#if _MSC_VER > 1500 || (defined __GNUC___)
+#   define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
+#   else
+#   define gltf_unordered_map map
+#   define gltf_unordered_multimap multimap
+#endif
+
+#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
+#   include <unordered_map>
+#   if _MSC_VER > 1600
+#       define gltf_unordered_map unordered_map
+#       define gltf_unordered_multimap unordered_multimap
+#   else
+#       define gltf_unordered_map tr1::unordered_map
+#       define gltf_unordered_multimap tr1::unordered_multimap
+#   endif
+#endif
+
 namespace Assimp {
 namespace Assimp {
 namespace glTF {
 namespace glTF {