Ver código fonte

Merge branch 'master' into fix_clang5_issue

Kim Kulling 7 anos atrás
pai
commit
d081b4ab4e

+ 4 - 3
.travis.yml

@@ -33,9 +33,10 @@ env:
 
 matrix:
   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
       compiler: clang
       env: ASAN=ON

+ 37 - 19
code/B3DImporter.cpp

@@ -93,7 +93,6 @@ void DeleteAllBarePointers(std::vector<T>& x)
 
 B3DImporter::~B3DImporter()
 {
-    DeleteAllBarePointers(_animations);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -267,6 +266,21 @@ T *B3DImporter::to_array( const vector<T> &v ){
     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(){
     while( ChunkSize() ){
@@ -295,8 +309,7 @@ void B3DImporter::ReadBRUS(){
         /*int blend=**/ReadInt();
         int fx=ReadInt();
 
-        aiMaterial *mat=new aiMaterial;
-        _materials.push_back( mat );
+        std::unique_ptr<aiMaterial> mat(new aiMaterial);
 
         // Name
         aiString ainame( name );
@@ -333,6 +346,7 @@ void B3DImporter::ReadBRUS(){
                 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" );
     }
 
-    aiMesh *mesh=new aiMesh;
-    _meshes.push_back( mesh );
+    std::unique_ptr<aiMesh> mesh(new aiMesh);
 
     mesh->mMaterialIndex=matid;
     mesh->mNumFaces=0;
@@ -415,6 +428,8 @@ void B3DImporter::ReadTRIS( int v0 ){
         ++mesh->mNumFaces;
         ++face;
     }
+
+    _meshes.emplace_back( std::move(mesh) );
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -500,11 +515,11 @@ void B3DImporter::ReadANIM(){
     int frames=ReadInt();
     float fps=ReadFloat();
 
-    aiAnimation *anim=new aiAnimation;
-    _animations.push_back( anim );
+    std::unique_ptr<aiAnimation> anim(new aiAnimation);
 
     anim->mDuration=frames;
     anim->mTicksPerSecond=fps;
+    _animations.emplace_back( std::move(anim) );
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -531,7 +546,7 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
     node->mParent=parent;
     node->mTransformation=tform;
 
-    aiNodeAnim *nodeAnim=0;
+    std::unique_ptr<aiNodeAnim> nodeAnim;
     vector<unsigned> meshes;
     vector<aiNode*> children;
 
@@ -549,11 +564,10 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
             ReadANIM();
         }else if( t=="KEYS" ){
             if( !nodeAnim ){
-                nodeAnim=new aiNodeAnim;
-                _nodeAnims.push_back( nodeAnim );
+                nodeAnim.reset(new aiNodeAnim);
                 nodeAnim->mNodeName=node->mName;
             }
-            ReadKEYS( nodeAnim );
+            ReadKEYS( nodeAnim.get() );
         }else if( t=="NODE" ){
             aiNode *child=ReadNODE( node );
             children.push_back( child );
@@ -561,6 +575,10 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
         ExitChunk();
     }
 
+    if (nodeAnim) {
+        _nodeAnims.emplace_back( std::move(nodeAnim) );
+    }
+
     node->mNumMeshes= static_cast<unsigned int>(meshes.size());
     node->mMeshes=to_array( meshes );
 
@@ -586,7 +604,6 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
 
     _nodeAnims.clear();
 
-    DeleteAllBarePointers(_animations);
     _animations.clear();
 
     string t=ReadChunk();
@@ -622,7 +639,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
         aiNode *node=_nodes[i];
 
         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_verts=mesh->mNumVertices=n_tris * 3;
@@ -685,27 +702,28 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
 
     //nodes
     scene->mRootNode=_nodes[0];
+    _nodes.clear();  // node ownership now belongs to scene
 
     //material
     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->mMaterials=to_array( _materials );
+    scene->mMaterials = unique_to_array( _materials );
 
     //meshes
     scene->mNumMeshes= static_cast<unsigned int>(_meshes.size());
-    scene->mMeshes=to_array( _meshes );
+    scene->mMeshes = unique_to_array( _meshes );
 
     //animations
     if( _animations.size()==1 && _nodeAnims.size() ){
 
-        aiAnimation *anim=_animations.back();
+        aiAnimation *anim = _animations.back().get();
         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->mAnimations=to_array( _animations );
+        scene->mAnimations=unique_to_array( _animations );
     }
 
     // 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 "BaseImporter.h"
 
+#include <memory>
 #include <vector>
 
 struct aiNodeAnim;
@@ -116,15 +117,15 @@ private:
     std::vector<unsigned> _stack;
 
     std::vector<std::string> _textures;
-    std::vector<aiMaterial*> _materials;
+    std::vector<std::unique_ptr<aiMaterial> > _materials;
 
     int _vflags,_tcsets,_tcsize;
     std::vector<Vertex> _vertices;
 
     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;
 };
 
 }

+ 4 - 1
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 ExportSceneGLB(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 ExportSceneAssxml(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 ),
     Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
+    Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb2", &ExportSceneGLB2,
+        aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
 #endif
 
 #ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
@@ -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;
     ASSIMP_END_EXCEPTION_REGION(aiReturn);
-    
+
     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);
     }
 
+    //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)) {
         TokenizeError("magic bytes not found",0);
     }

+ 1 - 1
code/MD5Loader.h

@@ -145,7 +145,7 @@ protected:
 
     // -------------------------------------------------------------------
     /** 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.
      *  @param pFile File stream to be read

+ 9 - 3
code/MDLLoader.cpp

@@ -415,9 +415,15 @@ void MDLImporter::InternReadFile_Quake1( )
     else
     {
         // get the first frame in the group
-        //BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames;
-        //pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
-		ai_assert( false && "Unaligned pointer" );
+
+#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;
+        pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
+#endif
     }
     BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
     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
 PLYImporter::PLYImporter()
-  : mBuffer()
-  , pcDOM()
-  , mGeneratedMesh(NULL){
+  : mBuffer(nullptr)
+  , pcDOM(nullptr)
+  , mGeneratedMesh(nullptr){
   // empty
 }
 
@@ -196,7 +196,10 @@ void PLYImporter::InternReadFile(const std::string& pFile,
       if (!PLY::DOM::ParseInstance(streamedBuffer, &sPlyDom, this))
       {
         if (mGeneratedMesh != NULL)
+        {
           delete(mGeneratedMesh);
+          mGeneratedMesh = nullptr;
+        }
 
         streamedBuffer.close();
         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 (mGeneratedMesh != NULL)
+        {
           delete(mGeneratedMesh);
+          mGeneratedMesh = nullptr;
+        }
 
         streamedBuffer.close();
         throw DeadlyImportError("Invalid .ply file: Unable to build DOM (#2)");
@@ -220,7 +226,10 @@ void PLYImporter::InternReadFile(const std::string& pFile,
     else
     {
       if (mGeneratedMesh != NULL)
+      {
         delete(mGeneratedMesh);
+        mGeneratedMesh = nullptr;
+      }
 
       streamedBuffer.close();
       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);
     if (mGeneratedMesh != NULL)
+    {
       delete(mGeneratedMesh);
+      mGeneratedMesh = nullptr;
+    }
 
     streamedBuffer.close();
     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 != NULL)
+      {
         delete(mGeneratedMesh);
+        mGeneratedMesh = nullptr;
+      }
 
       streamedBuffer.close();
       throw DeadlyImportError("Invalid .ply file: Not enough "
@@ -289,6 +304,7 @@ void PLYImporter::InternReadFile(const std::string& pFile,
   pScene->mNumMeshes = 1;
   pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
   pScene->mMeshes[0] = mGeneratedMesh;
+  mGeneratedMesh = nullptr;
 
   // generate a simple node structure
   pScene->mRootNode = new aiNode();

+ 1 - 1
code/StreamReader.h

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

+ 1 - 0
code/glTF2AssetWriter.h

@@ -81,6 +81,7 @@ public:
     AssetWriter(Asset& asset);
 
     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()
     {
         Value asset;

+ 14 - 2
code/glTF2Exporter.cpp

@@ -77,10 +77,18 @@ namespace Assimp {
         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
 
 glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const aiScene* pScene,
-                           const ExportProperties* pProperties, bool /*isBinary*/)
+                           const ExportProperties* pProperties, bool isBinary)
     : mFilename(filename)
     , mIOSystem(pIOSystem)
     , mProperties(pProperties)
@@ -118,7 +126,11 @@ glTF2Exporter::glTF2Exporter(const char* filename, IOSystem* pIOSystem, const ai
 
     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
 #define AI_GLTFEXPORTER_H_INC
 
-#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
+#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
 
 #include <assimp/types.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

+ 1 - 1
include/assimp/material.h

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

+ 1 - 1
include/assimp/vector2.h

@@ -98,7 +98,7 @@ public:
     operator aiVector2t<TOther> () const;
 
     TReal x, y;
-} PACK_STRUCT;
+};
 
 typedef aiVector2t<ai_real> aiVector2D;
 

+ 1 - 0
include/assimp/vector2.inl

@@ -130,6 +130,7 @@ TReal aiVector2t<TReal>::operator[](unsigned int i) const {
 			return y;
 		default:
 			break;
+
     }
     return x;
 }

+ 12 - 0
test/unit/utPLYImportExport.cpp

@@ -85,6 +85,18 @@ TEST_F(utPLYImportExport, exportTest_Success ) {
 
 #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 ) {
     Assimp::Importer importer;
     const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/PLY/float-color.ply", 0 );