Browse Source

Merge branch 'master' into iosystem-patch

Kim Kulling 7 years ago
parent
commit
04dc52fcf0

+ 4 - 3
.travis.yml

@@ -33,9 +33,10 @@ env:
 
 
 matrix:
 matrix:
   include:
   include:
-    - os: linux
-      compiler: clang
-      env: ANALYZE=ON
+    # disabled until clang 5.0 analyzer issues are fixed
+    # - os: linux
+    #   compiler: clang
+    #   env: ANALYZE=ON
     - os: linux
     - os: linux
       compiler: clang
       compiler: clang
       env: ASAN=ON
       env: ASAN=ON

+ 2 - 2
CMakeLists.txt

@@ -129,8 +129,8 @@ ENDIF(NOT BUILD_SHARED_LIBS)
 
 
 # Define here the needed parameters
 # Define here the needed parameters
 SET (ASSIMP_VERSION_MAJOR 4)
 SET (ASSIMP_VERSION_MAJOR 4)
-SET (ASSIMP_VERSION_MINOR 0)
-SET (ASSIMP_VERSION_PATCH 1)
+SET (ASSIMP_VERSION_MINOR 1)
+SET (ASSIMP_VERSION_PATCH 0)
 SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
 SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
 SET (ASSIMP_SOVERSION 4)
 SET (ASSIMP_SOVERSION 4)
 SET (PROJECT_VERSION "${ASSIMP_VERSION}")
 SET (PROJECT_VERSION "${ASSIMP_VERSION}")

+ 8 - 0
CREDITS

@@ -158,3 +158,11 @@ Contributed X File exporter
 Contributed Step (stp) exporter
 Contributed Step (stp) exporter
 
 
 For a more detailed list just check: https://github.com/assimp/assimp/network/members
 For a more detailed list just check: https://github.com/assimp/assimp/network/members
+
+Patreons:
+- migenius
+- Marcus
+- Cort
+- elect
+- Steffen
+

+ 37 - 19
code/B3DImporter.cpp

@@ -93,7 +93,6 @@ void DeleteAllBarePointers(std::vector<T>& x)
 
 
 B3DImporter::~B3DImporter()
 B3DImporter::~B3DImporter()
 {
 {
-    DeleteAllBarePointers(_animations);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -267,6 +266,21 @@ T *B3DImporter::to_array( const vector<T> &v ){
     return p;
     return p;
 }
 }
 
 
+
+// ------------------------------------------------------------------------------------------------
+template<class T>
+T **unique_to_array( vector<std::unique_ptr<T> > &v ){
+    if( v.empty() ) {
+        return 0;
+    }
+    T **p = new T*[ v.size() ];
+    for( size_t i = 0; i < v.size(); ++i ){
+        p[i] = v[i].release();
+    }
+    return p;
+}
+
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void B3DImporter::ReadTEXS(){
 void B3DImporter::ReadTEXS(){
     while( ChunkSize() ){
     while( ChunkSize() ){
@@ -295,8 +309,7 @@ void B3DImporter::ReadBRUS(){
         /*int blend=**/ReadInt();
         /*int blend=**/ReadInt();
         int fx=ReadInt();
         int fx=ReadInt();
 
 
-        aiMaterial *mat=new aiMaterial;
-        _materials.push_back( mat );
+        std::unique_ptr<aiMaterial> mat(new aiMaterial);
 
 
         // Name
         // Name
         aiString ainame( name );
         aiString ainame( name );
@@ -333,6 +346,7 @@ void B3DImporter::ReadBRUS(){
                 mat->AddProperty( &texname,AI_MATKEY_TEXTURE_DIFFUSE(0) );
                 mat->AddProperty( &texname,AI_MATKEY_TEXTURE_DIFFUSE(0) );
             }
             }
         }
         }
+        _materials.emplace_back( std::move(mat) );
     }
     }
 }
 }
 
 
@@ -386,8 +400,7 @@ void B3DImporter::ReadTRIS( int v0 ){
         Fail( "Bad material id" );
         Fail( "Bad material id" );
     }
     }
 
 
-    aiMesh *mesh=new aiMesh;
-    _meshes.push_back( mesh );
+    std::unique_ptr<aiMesh> mesh(new aiMesh);
 
 
     mesh->mMaterialIndex=matid;
     mesh->mMaterialIndex=matid;
     mesh->mNumFaces=0;
     mesh->mNumFaces=0;
@@ -415,6 +428,8 @@ void B3DImporter::ReadTRIS( int v0 ){
         ++mesh->mNumFaces;
         ++mesh->mNumFaces;
         ++face;
         ++face;
     }
     }
+
+    _meshes.emplace_back( std::move(mesh) );
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -500,11 +515,11 @@ void B3DImporter::ReadANIM(){
     int frames=ReadInt();
     int frames=ReadInt();
     float fps=ReadFloat();
     float fps=ReadFloat();
 
 
-    aiAnimation *anim=new aiAnimation;
-    _animations.push_back( anim );
+    std::unique_ptr<aiAnimation> anim(new aiAnimation);
 
 
     anim->mDuration=frames;
     anim->mDuration=frames;
     anim->mTicksPerSecond=fps;
     anim->mTicksPerSecond=fps;
+    _animations.emplace_back( std::move(anim) );
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -531,7 +546,7 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
     node->mParent=parent;
     node->mParent=parent;
     node->mTransformation=tform;
     node->mTransformation=tform;
 
 
-    aiNodeAnim *nodeAnim=0;
+    std::unique_ptr<aiNodeAnim> nodeAnim;
     vector<unsigned> meshes;
     vector<unsigned> meshes;
     vector<aiNode*> children;
     vector<aiNode*> children;
 
 
@@ -549,11 +564,10 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
             ReadANIM();
             ReadANIM();
         }else if( t=="KEYS" ){
         }else if( t=="KEYS" ){
             if( !nodeAnim ){
             if( !nodeAnim ){
-                nodeAnim=new aiNodeAnim;
-                _nodeAnims.push_back( nodeAnim );
+                nodeAnim.reset(new aiNodeAnim);
                 nodeAnim->mNodeName=node->mName;
                 nodeAnim->mNodeName=node->mName;
             }
             }
-            ReadKEYS( nodeAnim );
+            ReadKEYS( nodeAnim.get() );
         }else if( t=="NODE" ){
         }else if( t=="NODE" ){
             aiNode *child=ReadNODE( node );
             aiNode *child=ReadNODE( node );
             children.push_back( child );
             children.push_back( child );
@@ -561,6 +575,10 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
         ExitChunk();
         ExitChunk();
     }
     }
 
 
+    if (nodeAnim) {
+        _nodeAnims.emplace_back( std::move(nodeAnim) );
+    }
+
     node->mNumMeshes= static_cast<unsigned int>(meshes.size());
     node->mNumMeshes= static_cast<unsigned int>(meshes.size());
     node->mMeshes=to_array( meshes );
     node->mMeshes=to_array( meshes );
 
 
@@ -586,7 +604,6 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
 
 
     _nodeAnims.clear();
     _nodeAnims.clear();
 
 
-    DeleteAllBarePointers(_animations);
     _animations.clear();
     _animations.clear();
 
 
     string t=ReadChunk();
     string t=ReadChunk();
@@ -622,7 +639,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
         aiNode *node=_nodes[i];
         aiNode *node=_nodes[i];
 
 
         for( size_t j=0;j<node->mNumMeshes;++j ){
         for( size_t j=0;j<node->mNumMeshes;++j ){
-            aiMesh *mesh=_meshes[node->mMeshes[j]];
+            aiMesh *mesh = _meshes[node->mMeshes[j]].get();
 
 
             int n_tris=mesh->mNumFaces;
             int n_tris=mesh->mNumFaces;
             int n_verts=mesh->mNumVertices=n_tris * 3;
             int n_verts=mesh->mNumVertices=n_tris * 3;
@@ -685,27 +702,28 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
 
 
     //nodes
     //nodes
     scene->mRootNode=_nodes[0];
     scene->mRootNode=_nodes[0];
+    _nodes.clear();  // node ownership now belongs to scene
 
 
     //material
     //material
     if( !_materials.size() ){
     if( !_materials.size() ){
-        _materials.push_back( new aiMaterial );
+        _materials.emplace_back( std::unique_ptr<aiMaterial>(new aiMaterial) );
     }
     }
     scene->mNumMaterials= static_cast<unsigned int>(_materials.size());
     scene->mNumMaterials= static_cast<unsigned int>(_materials.size());
-    scene->mMaterials=to_array( _materials );
+    scene->mMaterials = unique_to_array( _materials );
 
 
     //meshes
     //meshes
     scene->mNumMeshes= static_cast<unsigned int>(_meshes.size());
     scene->mNumMeshes= static_cast<unsigned int>(_meshes.size());
-    scene->mMeshes=to_array( _meshes );
+    scene->mMeshes = unique_to_array( _meshes );
 
 
     //animations
     //animations
     if( _animations.size()==1 && _nodeAnims.size() ){
     if( _animations.size()==1 && _nodeAnims.size() ){
 
 
-        aiAnimation *anim=_animations.back();
+        aiAnimation *anim = _animations.back().get();
         anim->mNumChannels=static_cast<unsigned int>(_nodeAnims.size());
         anim->mNumChannels=static_cast<unsigned int>(_nodeAnims.size());
-        anim->mChannels=to_array( _nodeAnims );
+        anim->mChannels = unique_to_array( _nodeAnims );
 
 
         scene->mNumAnimations=static_cast<unsigned int>(_animations.size());
         scene->mNumAnimations=static_cast<unsigned int>(_animations.size());
-        scene->mAnimations=to_array( _animations );
+        scene->mAnimations=unique_to_array( _animations );
     }
     }
 
 
     // convert to RH
     // convert to RH

+ 5 - 4
code/B3DImporter.h

@@ -49,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/material.h>
 #include <assimp/material.h>
 #include "BaseImporter.h"
 #include "BaseImporter.h"
 
 
+#include <memory>
 #include <vector>
 #include <vector>
 
 
 struct aiNodeAnim;
 struct aiNodeAnim;
@@ -116,15 +117,15 @@ private:
     std::vector<unsigned> _stack;
     std::vector<unsigned> _stack;
 
 
     std::vector<std::string> _textures;
     std::vector<std::string> _textures;
-    std::vector<aiMaterial*> _materials;
+    std::vector<std::unique_ptr<aiMaterial> > _materials;
 
 
     int _vflags,_tcsets,_tcsize;
     int _vflags,_tcsets,_tcsize;
     std::vector<Vertex> _vertices;
     std::vector<Vertex> _vertices;
 
 
     std::vector<aiNode*> _nodes;
     std::vector<aiNode*> _nodes;
-    std::vector<aiMesh*> _meshes;
-    std::vector<aiNodeAnim*> _nodeAnims;
-    std::vector<aiAnimation*> _animations;
+    std::vector<std::unique_ptr<aiMesh> > _meshes;
+    std::vector<std::unique_ptr<aiNodeAnim> > _nodeAnims;
+    std::vector<std::unique_ptr<aiAnimation> > _animations;
 };
 };
 
 
 }
 }

+ 1 - 1
code/D3MFExporter.cpp

@@ -324,5 +324,5 @@ void D3MFExporter::writeRelInfoToFile( const std::string &folder, const std::str
 } // Namespace D3MF
 } // Namespace D3MF
 } // Namespace Assimp
 } // Namespace Assimp
 
 
-#endif // ASSIMP_BUILD_NO3MF_EXPORTER
+#endif // ASSIMP_BUILD_NO_3MF_EXPORTER
 #endif // ASSIMP_BUILD_NO_EXPORT
 #endif // ASSIMP_BUILD_NO_EXPORT

+ 2 - 2
code/D3MFExporter.h

@@ -59,7 +59,7 @@ class IOStream;
 namespace D3MF {
 namespace D3MF {
 
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
-#ifndef ASSIMP_BUILD_NO3MF_EXPORTER
+#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
 
 
 struct OpcPackageRelationship;
 struct OpcPackageRelationship;
 
 
@@ -95,7 +95,7 @@ private:
     std::vector<OpcPackageRelationship*> mRelations;
     std::vector<OpcPackageRelationship*> mRelations;
 };
 };
 
 
-#endif // ASSIMP_BUILD_NO3MF_EXPORTER
+#endif // ASSIMP_BUILD_NO_3MF_EXPORTER
 #endif // ASSIMP_BUILD_NO_EXPORT
 #endif // ASSIMP_BUILD_NO_EXPORT
 
 
 } // Namespace D3MF
 } // Namespace D3MF

+ 5 - 2
code/Exporter.cpp

@@ -92,6 +92,7 @@ void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperti
 void ExportSceneGLTF(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 ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneGLB2(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*);
 void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
@@ -151,6 +152,8 @@ Exporter::ExportFormatEntry gExporters[] =
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
     Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
     Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
+    Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb2", &ExportSceneGLB2,
+        aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
 #endif
 #endif
 
 
 #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
 #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
@@ -165,7 +168,7 @@ Exporter::ExportFormatEntry gExporters[] =
     Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ),
     Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ),
 #endif
 #endif
 
 
-#ifndef ASSIMP_BUILD_NO3MF_EXPORTER
+#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
     Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 )
     Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 )
 #endif
 #endif
 };
 };
@@ -420,7 +423,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
 
 
     pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
     pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId;
     ASSIMP_END_EXCEPTION_REGION(aiReturn);
     ASSIMP_END_EXCEPTION_REGION(aiReturn);
-    
+
     return AI_FAILURE;
     return AI_FAILURE;
 }
 }
 
 

+ 8 - 0
code/FBXBinaryTokenizer.cpp

@@ -434,6 +434,14 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, unsigned int le
         TokenizeError("file is too short",0);
         TokenizeError("file is too short",0);
     }
     }
 
 
+    //uint32_t offset = 0x15;
+/*    const char* cursor = input + 0x15;
+
+    const uint32_t flags = ReadWord(input, cursor, input + length);
+
+    const uint8_t padding_0 = ReadByte(input, cursor, input + length); // unused
+    const uint8_t padding_1 = ReadByte(input, cursor, input + length); // unused*/
+
     if (strncmp(input,"Kaydara FBX Binary",18)) {
     if (strncmp(input,"Kaydara FBX Binary",18)) {
         TokenizeError("magic bytes not found",0);
         TokenizeError("magic bytes not found",0);
     }
     }

+ 28 - 28
code/FBXMaterial.cpp

@@ -291,40 +291,40 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
 
 
     if(FileName) {
     if(FileName) {
         fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
         fileName = ParseTokenAsString(GetRequiredToken(*FileName,0));
-	}
+    }
 
 
     if(RelativeFilename) {
     if(RelativeFilename) {
         relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
         relativeFileName = ParseTokenAsString(GetRequiredToken(*RelativeFilename,0));
     }
     }
 
 
     if(Content) {
     if(Content) {
-		//this field is ommited when the embedded texture is already loaded, let's ignore if it´s not found
-		try {
-			const Token& token = GetRequiredToken(*Content, 0);
-			const char* data = token.begin();
-			if (!token.IsBinary()) {
-				DOMWarning("video content is not binary data, ignoring", &element);
-			}
-			else if (static_cast<size_t>(token.end() - data) < 5) {
-				DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
-			}
-			else if (*data != 'R') {
-				DOMWarning("video content is not raw binary data, ignoring", &element);
-			}
-			else {
-				// read number of elements
-				uint32_t len = 0;
-				::memcpy(&len, data + 1, sizeof(len));
-				AI_SWAP4(len);
-
-				contentLength = len;
-
-				content = new uint8_t[len];
-				::memcpy(content, data + 5, len);
-			}
-		} catch (runtime_error runtimeError) {
-			//we don´t need the content data for contents that has already been loaded
-		}
+        //this field is ommited when the embedded texture is already loaded, let's ignore if it's not found
+        try {
+            const Token& token = GetRequiredToken(*Content, 0);
+            const char* data = token.begin();
+            if (!token.IsBinary()) {
+                DOMWarning("video content is not binary data, ignoring", &element);
+            }
+            else if (static_cast<size_t>(token.end() - data) < 5) {
+                DOMError("binary data array is too short, need five (5) bytes for type signature and element count", &element);
+            }
+            else if (*data != 'R') {
+                DOMWarning("video content is not raw binary data, ignoring", &element);
+            }
+            else {
+                // read number of elements
+                uint32_t len = 0;
+                ::memcpy(&len, data + 1, sizeof(len));
+                AI_SWAP4(len);
+
+                contentLength = len;
+
+                content = new uint8_t[len];
+                ::memcpy(content, data + 5, len);
+            }
+        } catch (runtime_error runtimeError) {
+            //we don't need the content data for contents that has already been loaded
+        }
     }
     }
 
 
     props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);
     props = GetPropertyTable(doc,"Video.FbxVideo",element,sc);

+ 1 - 1
code/MD5Loader.h

@@ -145,7 +145,7 @@ protected:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Load the contents of a specific file into memory and
     /** Load the contents of a specific file into memory and
-     *  alocates a buffer to keep it.
+     *  allocates a buffer to keep it.
      *
      *
      *  mBuffer is modified to point to this buffer.
      *  mBuffer is modified to point to this buffer.
      *  @param pFile File stream to be read
      *  @param pFile File stream to be read

+ 7 - 0
code/MDLLoader.cpp

@@ -415,8 +415,15 @@ void MDLImporter::InternReadFile_Quake1( )
     else
     else
     {
     {
         // get the first frame in the group
         // get the first frame in the group
+
+#if 1
+        // FIXME: the cast is wrong and causea a warning on clang 5.0
+        // disable thi code for now, fix it later
+        ai_assert(false && "Bad pointer cast");
+#else
         BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames;
         BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames;
         pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
         pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
+#endif
     }
     }
     BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
     BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
     VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts));
     VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts));

+ 19 - 3
code/PlyLoader.cpp

@@ -91,9 +91,9 @@ namespace
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 PLYImporter::PLYImporter()
 PLYImporter::PLYImporter()
-  : mBuffer()
-  , pcDOM()
-  , mGeneratedMesh(NULL){
+  : mBuffer(nullptr)
+  , pcDOM(nullptr)
+  , mGeneratedMesh(nullptr){
   // empty
   // empty
 }
 }
 
 
@@ -196,7 +196,10 @@ void PLYImporter::InternReadFile(const std::string& pFile,
       if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this))
       if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this))
       {
       {
         if (mGeneratedMesh != NULL)
         if (mGeneratedMesh != NULL)
+        {
           delete(mGeneratedMesh);
           delete(mGeneratedMesh);
+          mGeneratedMesh = nullptr;
+        }
 
 
         streamedBuffer.close();
         streamedBuffer.close();
         throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#1)");
         throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#1)");
@@ -211,7 +214,10 @@ void PLYImporter::InternReadFile(const std::string& pFile,
       if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE))
       if (!PLY::DOM::ParseInstanceBinary(streamedBuffer, &sPlyDom, this, bIsBE))
       {
       {
         if (mGeneratedMesh != NULL)
         if (mGeneratedMesh != NULL)
+        {
           delete(mGeneratedMesh);
           delete(mGeneratedMesh);
+          mGeneratedMesh = nullptr;
+        }
 
 
         streamedBuffer.close();
         streamedBuffer.close();
         throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)");
         throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)");
@@ -220,7 +226,10 @@ void PLYImporter::InternReadFile(const std::string& pFile,
     else
     else
     {
     {
       if (mGeneratedMesh != NULL)
       if (mGeneratedMesh != NULL)
+      {
         delete(mGeneratedMesh);
         delete(mGeneratedMesh);
+        mGeneratedMesh = nullptr;
+      }
 
 
       streamedBuffer.close();
       streamedBuffer.close();
       throw DeadlyImportError("Invalid .ply file: Unknown file format");
       throw DeadlyImportError("Invalid .ply file: Unknown file format");
@@ -230,7 +239,10 @@ void PLYImporter::InternReadFile(const std::string& pFile,
   {
   {
     AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
     AI_DEBUG_INVALIDATE_PTR(this->mBuffer);
     if (mGeneratedMesh != NULL)
     if (mGeneratedMesh != NULL)
+    {
       delete(mGeneratedMesh);
       delete(mGeneratedMesh);
+      mGeneratedMesh = nullptr;
+    }
 
 
     streamedBuffer.close();
     streamedBuffer.close();
     throw DeadlyImportError("Invalid .ply file: Missing format specification");
     throw DeadlyImportError("Invalid .ply file: Missing format specification");
@@ -252,7 +264,10 @@ void PLYImporter::InternReadFile(const std::string& pFile,
     if (mGeneratedMesh->mNumVertices < 3)
     if (mGeneratedMesh->mNumVertices < 3)
     {
     {
       if (mGeneratedMesh != NULL)
       if (mGeneratedMesh != NULL)
+      {
         delete(mGeneratedMesh);
         delete(mGeneratedMesh);
+        mGeneratedMesh = nullptr;
+      }
 
 
       streamedBuffer.close();
       streamedBuffer.close();
       throw DeadlyImportError("Invalid .ply file: Not enough "
       throw DeadlyImportError("Invalid .ply file: Not enough "
@@ -289,6 +304,7 @@ void PLYImporter::InternReadFile(const std::string& pFile,
   pScene->mNumMeshes = 1;
   pScene->mNumMeshes = 1;
   pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
   pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
   pScene->mMeshes[0] = mGeneratedMesh;
   pScene->mMeshes[0] = mGeneratedMesh;
+  mGeneratedMesh = nullptr;
 
 
   // generate a simple node structure
   // generate a simple node structure
   pScene->mRootNode = new aiNode();
   pScene->mRootNode = new aiNode();

+ 1 - 1
code/StreamReader.h

@@ -192,7 +192,7 @@ public:
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     /** Increase the file pointer (relative seeking)  */
     /** Increase the file pointer (relative seeking)  */
-    void IncPtr(size_t plus)    {
+    void IncPtr(intptr_t plus)    {
         current += plus;
         current += plus;
         if (current > limit) {
         if (current > limit) {
             throw DeadlyImportError("End of file or read limit was reached");
             throw DeadlyImportError("End of file or read limit was reached");

+ 1 - 1
code/Version.cpp

@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ScenePrivate.h"
 #include "ScenePrivate.h"
 
 
 static const unsigned int MajorVersion = 4;
 static const unsigned int MajorVersion = 4;
-static const unsigned int MinorVersion = 0;
+static const unsigned int MinorVersion = 1;
 
 
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 // Legal information string - dont't remove this.
 // Legal information string - dont't remove this.

+ 6 - 2
code/XGLLoader.cpp

@@ -904,12 +904,14 @@ aiVector2D XGLImporter::ReadVec2()
     }
     }
     const char* s = m_reader->getNodeData();
     const char* s = m_reader->getNodeData();
 
 
-    for(int i = 0; i < 2; ++i) {
+    ai_real v[2];
+	for(int i = 0; i < 2; ++i) {
         if(!SkipSpaces(&s)) {
         if(!SkipSpaces(&s)) {
             LogError("unexpected EOL, failed to parse vec2");
             LogError("unexpected EOL, failed to parse vec2");
             return vec;
             return vec;
         }
         }
-        vec[i] = fast_atof(&s);
+		
+        v[i] = fast_atof(&s);
 
 
         SkipSpaces(&s);
         SkipSpaces(&s);
         if (i != 1 && *s != ',') {
         if (i != 1 && *s != ',') {
@@ -918,6 +920,8 @@ aiVector2D XGLImporter::ReadVec2()
         }
         }
         ++s;
         ++s;
     }
     }
+	vec.x = v[0];
+	vec.y = v[1];
 
 
     return vec;
     return vec;
 }
 }

+ 1 - 0
code/glTF2AssetWriter.h

@@ -81,6 +81,7 @@ public:
     AssetWriter(Asset& asset);
     AssetWriter(Asset& asset);
 
 
     void WriteFile(const char* path);
     void WriteFile(const char* path);
+    void WriteGLBFile(const char* path);
 };
 };
 
 
 }
 }

+ 91 - 0
code/glTF2AssetWriter.inl

@@ -561,6 +561,97 @@ namespace glTF2 {
         }
         }
     }
     }
 
 
+    inline void AssetWriter::WriteGLBFile(const char* path)
+    {
+        std::unique_ptr<IOStream> outfile(mAsset.OpenFile(path, "wb", true));
+
+        if (outfile == 0) {
+            throw DeadlyExportError("Could not open output file: " + std::string(path));
+        }
+
+        // Padding with spaces as required by the spec
+        uint32_t padding = 0x20202020;
+
+        // Adapt JSON so that it is not pointing to an external file,
+        // as this is required by the GLB spec'.
+        mDoc["buffers"][0].RemoveMember("uri");
+
+        //
+        // JSON chunk
+        //
+
+        StringBuffer docBuffer;
+        Writer<StringBuffer> writer(docBuffer);
+        mDoc.Accept(writer);
+
+        uint32_t jsonChunkLength = (docBuffer.GetSize() + 3) & ~3; // Round up to next multiple of 4
+        auto paddingLength = jsonChunkLength - docBuffer.GetSize();
+
+        GLB_Chunk jsonChunk;
+        jsonChunk.chunkLength = jsonChunkLength;
+        jsonChunk.chunkType = ChunkType_JSON;
+        AI_SWAP4(jsonChunk.chunkLength);
+
+        outfile->Seek(sizeof(GLB_Header), aiOrigin_SET);
+        if (outfile->Write(&jsonChunk, 1, sizeof(GLB_Chunk)) != sizeof(GLB_Chunk)) {
+            throw DeadlyExportError("Failed to write scene data header!");
+        }
+        if (outfile->Write(docBuffer.GetString(), 1, docBuffer.GetSize()) != docBuffer.GetSize()) {
+            throw DeadlyExportError("Failed to write scene data!");
+        }
+        if (paddingLength && outfile->Write(&padding, 1, paddingLength) != paddingLength) {
+            throw DeadlyExportError("Failed to write scene data padding!");
+        }
+
+        //
+        // Binary chunk
+        //
+
+        uint32_t binaryChunkLength = 0;
+        if (mAsset.buffers.Size() > 0) {
+            Ref<Buffer> b = mAsset.buffers.Get(0u);
+            if (b->byteLength > 0) {
+                binaryChunkLength = (b->byteLength + 3) & ~3; // Round up to next multiple of 4
+                auto paddingLength = binaryChunkLength - b->byteLength;
+
+                GLB_Chunk binaryChunk;
+                binaryChunk.chunkLength = binaryChunkLength;
+                binaryChunk.chunkType = ChunkType_BIN;
+                AI_SWAP4(binaryChunk.chunkLength);
+
+                size_t bodyOffset = sizeof(GLB_Header) + sizeof(GLB_Chunk) + jsonChunk.chunkLength;
+                outfile->Seek(bodyOffset, aiOrigin_SET);
+                if (outfile->Write(&binaryChunk, 1, sizeof(GLB_Chunk)) != sizeof(GLB_Chunk)) {
+                    throw DeadlyExportError("Failed to write body data header!");
+                }
+                if (outfile->Write(b->GetPointer(), 1, b->byteLength) != b->byteLength) {
+                    throw DeadlyExportError("Failed to write body data!");
+                }
+                if (paddingLength && outfile->Write(&padding, 1, paddingLength) != paddingLength) {
+                    throw DeadlyExportError("Failed to write body data padding!");
+                }
+            }
+        }
+
+        //
+        // Header
+        //
+
+        GLB_Header header;
+        memcpy(header.magic, AI_GLB_MAGIC_NUMBER, sizeof(header.magic));
+
+        header.version = 2;
+        AI_SWAP4(header.version);
+
+        header.length = uint32_t(sizeof(GLB_Header) + 2 * sizeof(GLB_Chunk) + jsonChunkLength + binaryChunkLength);
+        AI_SWAP4(header.length);
+
+        outfile->Seek(0, aiOrigin_SET);
+        if (outfile->Write(&header, 1, sizeof(GLB_Header)) != sizeof(GLB_Header)) {
+            throw DeadlyExportError("Failed to write the header!");
+        }
+    }
+
     inline void AssetWriter::WriteMetadata()
     inline void AssetWriter::WriteMetadata()
     {
     {
         Value asset;
         Value asset;

+ 14 - 2
code/glTF2Exporter.cpp

@@ -77,10 +77,18 @@ namespace Assimp {
         glTF2Exporter exporter(pFile, pIOSystem, pScene, pProperties, false);
         glTF2Exporter exporter(pFile, pIOSystem, pScene, pProperties, false);
     }
     }
 
 
+    // ------------------------------------------------------------------------------------------------
+    // Worker function for exporting a scene to GLB. Prototyped and registered in Exporter.cpp
+    void ExportSceneGLB2(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+    {
+        // invoke the exporter
+        glTF2Exporter exporter(pFile, pIOSystem, pScene, pProperties, true);
+    }
+
 } // end of namespace Assimp
 } // end of namespace Assimp
 
 
 glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
 glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
-                           const ExportProperties* pProperties, bool /*isBinary*/)
+                           const ExportProperties* pProperties, bool isBinary)
     : mFilename(filename)
     : mFilename(filename)
     , mIOSystem(pIOSystem)
     , mIOSystem(pIOSystem)
     , mProperties(pProperties)
     , mProperties(pProperties)
@@ -118,7 +126,11 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
 
 
     AssetWriter writer(*mAsset);
     AssetWriter writer(*mAsset);
 
 
-    writer.WriteFile(filename);
+    if (isBinary) {
+        writer.WriteGLBFile(filename);
+    } else {
+        writer.WriteFile(filename);
+    }
 }
 }
 
 
 /*
 /*

+ 2 - 2
code/glTFExporter.h

@@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_GLTFEXPORTER_H_INC
 #ifndef AI_GLTFEXPORTER_H_INC
 #define AI_GLTFEXPORTER_H_INC
 #define AI_GLTFEXPORTER_H_INC
 
 
-#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
+#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
 
 
 #include <assimp/types.h>
 #include <assimp/types.h>
 #include <assimp/material.h>
 #include <assimp/material.h>
@@ -113,6 +113,6 @@ namespace Assimp
 
 
 }
 }
 
 
-#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
+#endif // ASSIMP_BUILD_NO_GLTF_EXPORTER
 
 
 #endif // AI_GLTFEXPORTER_H_INC
 #endif // AI_GLTFEXPORTER_H_INC

+ 4 - 0
contrib/unzip/unzip.c

@@ -41,6 +41,10 @@ woven in by Terry Thorsen 1/2003.
 #include "zlib.h"
 #include "zlib.h"
 #include "unzip.h"
 #include "unzip.h"
 
 
+#if ZLIB_VERNUM < 0x1270
+typedef unsigned long z_crc_t;
+#endif
+
 #ifdef STDC
 #ifdef STDC
 #  include <stddef.h>
 #  include <stddef.h>
 #  include <string.h>
 #  include <string.h>

+ 1 - 1
doc/Doxyfile.in

@@ -32,7 +32,7 @@ PROJECT_NAME           = Assimp
 # This could be handy for archiving the generated documentation or 
 # This could be handy for archiving the generated documentation or 
 # if some version control system is used.
 # if some version control system is used.
 
 
-PROJECT_NUMBER         = "v3.1.1 (June 2014)"
+PROJECT_NUMBER         = "v4.1. (December 2018)"
 
 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description 
 # Using the PROJECT_BRIEF tag one can provide an optional one line description 
 # for a project that appears at the top of each page and should give viewer 
 # for a project that appears at the top of each page and should give viewer 

+ 1 - 1
include/assimp/material.h

@@ -491,7 +491,7 @@ struct aiUVTransform
     }
     }
 #endif
 #endif
 
 
-} PACK_STRUCT;
+};
 
 
 #include "./Compiler/poppack1.h"
 #include "./Compiler/poppack1.h"
 
 

+ 1 - 2
include/assimp/vector2.h

@@ -85,7 +85,6 @@ public:
     const aiVector2t& operator /= (TReal f);
     const aiVector2t& operator /= (TReal f);
 
 
     TReal operator[](unsigned int i) const;
     TReal operator[](unsigned int i) const;
-    TReal& operator[](unsigned int i);
 
 
     bool operator== (const aiVector2t& other) const;
     bool operator== (const aiVector2t& other) const;
     bool operator!= (const aiVector2t& other) const;
     bool operator!= (const aiVector2t& other) const;
@@ -99,7 +98,7 @@ public:
     operator aiVector2t<TOther> () const;
     operator aiVector2t<TOther> () const;
 
 
     TReal x, y;
     TReal x, y;
-} PACK_STRUCT;
+};
 
 
 typedef aiVector2t<ai_real> aiVector2D;
 typedef aiVector2t<ai_real> aiVector2D;
 
 

+ 39 - 23
include/assimp/vector2.inl

@@ -60,24 +60,28 @@ aiVector2t<TReal>::operator aiVector2t<TOther> () const {
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 void aiVector2t<TReal>::Set( TReal pX, TReal pY) {
 void aiVector2t<TReal>::Set( TReal pX, TReal pY) {
     x = pX; y = pY;
     x = pX; y = pY;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 TReal aiVector2t<TReal>::SquareLength() const {
 TReal aiVector2t<TReal>::SquareLength() const {
     return x*x + y*y;
     return x*x + y*y;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 TReal aiVector2t<TReal>::Length() const {
 TReal aiVector2t<TReal>::Length() const {
     return std::sqrt( SquareLength());
     return std::sqrt( SquareLength());
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 aiVector2t<TReal>& aiVector2t<TReal>::Normalize() {
 aiVector2t<TReal>& aiVector2t<TReal>::Normalize() {
     *this /= Length();
     *this /= Length();
     return *this;
     return *this;
@@ -85,6 +89,7 @@ aiVector2t<TReal>& aiVector2t<TReal>::Normalize() {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 const aiVector2t<TReal>& aiVector2t<TReal>::operator += (const aiVector2t& o) {
 const aiVector2t<TReal>& aiVector2t<TReal>::operator += (const aiVector2t& o) {
     x += o.x; y += o.y;
     x += o.x; y += o.y;
     return *this;
     return *this;
@@ -92,6 +97,7 @@ const aiVector2t<TReal>& aiVector2t<TReal>::operator += (const aiVector2t& o) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 const aiVector2t<TReal>& aiVector2t<TReal>::operator -= (const aiVector2t& o) {
 const aiVector2t<TReal>& aiVector2t<TReal>::operator -= (const aiVector2t& o) {
     x -= o.x; y -= o.y;
     x -= o.x; y -= o.y;
     return *this;
     return *this;
@@ -99,6 +105,7 @@ const aiVector2t<TReal>& aiVector2t<TReal>::operator -= (const aiVector2t& o) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 const aiVector2t<TReal>& aiVector2t<TReal>::operator *= (TReal f) {
 const aiVector2t<TReal>& aiVector2t<TReal>::operator *= (TReal f) {
     x *= f; y *= f;
     x *= f; y *= f;
     return *this;
     return *this;
@@ -106,6 +113,7 @@ const aiVector2t<TReal>& aiVector2t<TReal>::operator *= (TReal f) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 const aiVector2t<TReal>& aiVector2t<TReal>::operator /= (TReal f) {
 const aiVector2t<TReal>& aiVector2t<TReal>::operator /= (TReal f) {
     x /= f; y /= f;
     x /= f; y /= f;
     return *this;
     return *this;
@@ -113,30 +121,37 @@ const aiVector2t<TReal>& aiVector2t<TReal>::operator /= (TReal f) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 TReal aiVector2t<TReal>::operator[](unsigned int i) const {
 TReal aiVector2t<TReal>::operator[](unsigned int i) const {
-    return *(&x + i);
-}
+	switch (i) {
+		case 0:
+			return x;
+		case 1:
+			return y;
+		default:
+			break;
 
 
-// ------------------------------------------------------------------------------------------------
-template <typename TReal>
-TReal& aiVector2t<TReal>::operator[](unsigned int i) {
-    return *(&x + i);
+    }
+    return x;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 bool aiVector2t<TReal>::operator== (const aiVector2t& other) const {
 bool aiVector2t<TReal>::operator== (const aiVector2t& other) const {
     return x == other.x && y == other.y;
     return x == other.x && y == other.y;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 bool aiVector2t<TReal>::operator!= (const aiVector2t& other) const {
 bool aiVector2t<TReal>::operator!= (const aiVector2t& other) const {
     return x != other.x || y != other.y;
     return x != other.x || y != other.y;
 }
 }
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 template<typename TReal>
 template<typename TReal>
+inline
 bool aiVector2t<TReal>::Equal(const aiVector2t& other, TReal epsilon) const {
 bool aiVector2t<TReal>::Equal(const aiVector2t& other, TReal epsilon) const {
     return
     return
         std::abs(x - other.x) <= epsilon &&
         std::abs(x - other.x) <= epsilon &&
@@ -145,6 +160,7 @@ bool aiVector2t<TReal>::Equal(const aiVector2t& other, TReal epsilon) const {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 aiVector2t<TReal>& aiVector2t<TReal>::operator= (TReal f)   {
 aiVector2t<TReal>& aiVector2t<TReal>::operator= (TReal f)   {
     x = y = f;
     x = y = f;
     return *this;
     return *this;
@@ -152,6 +168,7 @@ aiVector2t<TReal>& aiVector2t<TReal>::operator= (TReal f)   {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
+inline
 const aiVector2t<TReal> aiVector2t<TReal>::SymMul(const aiVector2t& o) {
 const aiVector2t<TReal> aiVector2t<TReal>::SymMul(const aiVector2t& o) {
     return aiVector2t(x*o.x,y*o.y);
     return aiVector2t(x*o.x,y*o.y);
 }
 }
@@ -160,65 +177,64 @@ const aiVector2t<TReal> aiVector2t<TReal>::SymMul(const aiVector2t& o) {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // symmetric addition
 // symmetric addition
 template <typename TReal>
 template <typename TReal>
-inline aiVector2t<TReal> operator + (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2)
-{
+inline
+aiVector2t<TReal> operator + (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2) {
     return aiVector2t<TReal>( v1.x + v2.x, v1.y + v2.y);
     return aiVector2t<TReal>( v1.x + v2.x, v1.y + v2.y);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // symmetric subtraction
 // symmetric subtraction
 template <typename TReal>
 template <typename TReal>
-inline aiVector2t<TReal> operator - (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2)
-{
+inline 
+aiVector2t<TReal> operator - (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2) {
     return aiVector2t<TReal>( v1.x - v2.x, v1.y - v2.y);
     return aiVector2t<TReal>( v1.x - v2.x, v1.y - v2.y);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // scalar product
 // scalar product
 template <typename TReal>
 template <typename TReal>
-inline TReal operator * (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2)
-{
+inline 
+TReal operator * (const aiVector2t<TReal>& v1, const aiVector2t<TReal>& v2) {
     return v1.x*v2.x + v1.y*v2.y;
     return v1.x*v2.x + v1.y*v2.y;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // scalar multiplication
 // scalar multiplication
 template <typename TReal>
 template <typename TReal>
-inline aiVector2t<TReal> operator * ( TReal f, const aiVector2t<TReal>& v)
-{
+inline 
+aiVector2t<TReal> operator * ( TReal f, const aiVector2t<TReal>& v) {
     return aiVector2t<TReal>( f*v.x, f*v.y);
     return aiVector2t<TReal>( f*v.x, f*v.y);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // and the other way around
 // and the other way around
 template <typename TReal>
 template <typename TReal>
-inline aiVector2t<TReal> operator * ( const aiVector2t<TReal>& v, TReal f)
-{
+inline 
+aiVector2t<TReal> operator * ( const aiVector2t<TReal>& v, TReal f) {
     return aiVector2t<TReal>( f*v.x, f*v.y);
     return aiVector2t<TReal>( f*v.x, f*v.y);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // scalar division
 // scalar division
 template <typename TReal>
 template <typename TReal>
-inline aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, TReal f)
-{
-
+inline 
+aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, TReal f) {
     return v * (1/f);
     return v * (1/f);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // vector division
 // vector division
 template <typename TReal>
 template <typename TReal>
-inline aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, const aiVector2t<TReal>& v2)
-{
+inline 
+aiVector2t<TReal> operator / ( const aiVector2t<TReal>& v, const aiVector2t<TReal>& v2) {
     return aiVector2t<TReal>(v.x / v2.x,v.y / v2.y);
     return aiVector2t<TReal>(v.x / v2.x,v.y / v2.y);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // vector negation
 // vector negation
 template <typename TReal>
 template <typename TReal>
-inline aiVector2t<TReal> operator - ( const aiVector2t<TReal>& v)
-{
+inline 
+aiVector2t<TReal> operator - ( const aiVector2t<TReal>& v) {
     return aiVector2t<TReal>( -v.x, -v.y);
     return aiVector2t<TReal>( -v.x, -v.y);
 }
 }
 
 

+ 0 - 1
include/assimp/vector3.inl

@@ -142,7 +142,6 @@ AI_FORCE_INLINE aiVector3t<TReal>& aiVector3t<TReal>::operator *= (const aiMatri
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
 AI_FORCE_INLINE TReal aiVector3t<TReal>::operator[](unsigned int i) const {
 AI_FORCE_INLINE TReal aiVector3t<TReal>::operator[](unsigned int i) const {
-//    return *(&x + i);
     switch (i) {
     switch (i) {
         case 0:
         case 0:
             return x;
             return x;

+ 12 - 0
test/unit/utPLYImportExport.cpp

@@ -85,6 +85,18 @@ TEST_F(utPLYImportExport, exportTest_Success ) {
 
 
 #endif // ASSIMP_BUILD_NO_EXPORT
 #endif // ASSIMP_BUILD_NO_EXPORT
 
 
+//Test issue 1623, crash when loading two PLY files in a row
+TEST_F(utPLYImportExport, importerMultipleTest) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0);
+
+    EXPECT_NE(nullptr, scene);
+
+    scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/cube.ply", 0);
+
+    EXPECT_NE(nullptr, scene);
+}
+
 TEST_F( utPLYImportExport, vertexColorTest ) {
 TEST_F( utPLYImportExport, vertexColorTest ) {
     Assimp::Importer importer;
     Assimp::Importer importer;
     const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/float-color.ply", 0 );
     const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/float-color.ply", 0 );

+ 1 - 1
test/unit/utVersion.cpp

@@ -54,7 +54,7 @@ TEST_F( utVersion, aiGetLegalStringTest ) {
 }
 }
 
 
 TEST_F( utVersion, aiGetVersionMinorTest ) {
 TEST_F( utVersion, aiGetVersionMinorTest ) {
-    EXPECT_EQ( aiGetVersionMinor(), 0U );
+    EXPECT_EQ( aiGetVersionMinor(), 1U );
 }
 }
     
     
 TEST_F( utVersion, aiGetVersionMajorTest ) {
 TEST_F( utVersion, aiGetVersionMajorTest ) {