Просмотр исходного кода

Merge pull request #1549 from assimp/issue_104

Issue 104
Kim Kulling 7 лет назад
Родитель
Сommit
a88a23ac7c

+ 55 - 35
code/STLLoader.cpp

@@ -80,7 +80,9 @@ static bool IsBinarySTL(const char* buffer, unsigned int fileSize) {
         return false;
     }
 
-    const uint32_t faceCount = *reinterpret_cast<const uint32_t*>(buffer + 80);
+    const char *facecount_pos = buffer + 80;
+    uint32_t faceCount( 0 );
+    ::memcpy( &faceCount, facecount_pos, sizeof( uint32_t ) );
     const uint32_t expectedBinaryFileSize = faceCount * 50 + 84;
 
     return expectedBinaryFileSize == fileSize;
@@ -200,17 +202,17 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
     if (IsBinarySTL(mBuffer, fileSize)) {
         bMatClr = LoadBinaryFile();
     } else if (IsAsciiSTL(mBuffer, fileSize)) {
-        LoadASCIIFile();
+        LoadASCIIFile( pScene->mRootNode );
     } else {
         throw DeadlyImportError( "Failed to determine STL storage representation for " + pFile + ".");
     }
 
     // add all created meshes to the single node
-    pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
+    /*pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
     pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
     for (unsigned int i = 0; i < pScene->mNumMeshes; i++)
         pScene->mRootNode->mMeshes[i] = i;
-
+    */
     // create a single default material, using a white diffuse color for consistency with
     // other geometric types (e.g., PLY).
     aiMaterial* pcMat = new aiMaterial();
@@ -231,11 +233,12 @@ void STLImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
     pScene->mMaterials = new aiMaterial*[1];
     pScene->mMaterials[0] = pcMat;
 }
+
 // ------------------------------------------------------------------------------------------------
 // Read an ASCII STL file
-void STLImporter::LoadASCIIFile()
-{
+void STLImporter::LoadASCIIFile( aiNode *root ) {
     std::vector<aiMesh*> meshes;
+    std::vector<aiNode*> nodes;
     const char* sz = mBuffer;
     const char* bufferEnd = mBuffer + fileSize;
     std::vector<aiVector3D> positionBuffer;
@@ -247,12 +250,15 @@ void STLImporter::LoadASCIIFile()
     positionBuffer.reserve(sizeEstimate);
     normalBuffer.reserve(sizeEstimate);
 
-    while (IsAsciiSTL(sz, static_cast<unsigned int>(bufferEnd - sz)))
-    {
+    while (IsAsciiSTL(sz, static_cast<unsigned int>(bufferEnd - sz))) {
+        std::vector<unsigned int> meshIndices;
         aiMesh* pMesh = new aiMesh();
         pMesh->mMaterialIndex = 0;
+        meshIndices.push_back( meshes.size() );
         meshes.push_back(pMesh);
-
+        aiNode *node = new aiNode;
+        node->mParent = root;
+        nodes.push_back( node );
         SkipSpaces(&sz);
         ai_assert(!IsLineEnd(sz));
 
@@ -265,20 +271,21 @@ void STLImporter::LoadASCIIFile()
 
         size_t temp;
         // setup the name of the node
-        if ((temp = (size_t)(sz-szMe)))    {
+        if ((temp = (size_t)(sz-szMe))) {
             if (temp >= MAXLEN) {
                 throw DeadlyImportError( "STL: Node name too long" );
             }
-
-            pScene->mRootNode->mName.length = temp;
-            memcpy(pScene->mRootNode->mName.data,szMe,temp);
-            pScene->mRootNode->mName.data[temp] = '\0';
+            std::string name( szMe, temp );
+            node->mName.Set( name.c_str() );
+            //pScene->mRootNode->mName.length = temp;
+            //memcpy(pScene->mRootNode->mName.data,szMe,temp);
+            //pScene->mRootNode->mName.data[temp] = '\0';
+        } else {
+            pScene->mRootNode->mName.Set("<STL_ASCII>");
         }
-        else pScene->mRootNode->mName.Set("<STL_ASCII>");
 
         unsigned int faceVertexCounter = 3;
-        for ( ;; )
-        {
+        for ( ;; ) {
             // go to the next token
             if(!SkipSpacesAndLineEnd(&sz))
             {
@@ -300,9 +307,7 @@ void STLImporter::LoadASCIIFile()
                 SkipSpaces(&sz);
                 if (strncmp(sz,"normal",6))    {
                     DefaultLogger::get()->warn("STL: a facet normal vector was expected but not found");
-                }
-                else
-                {
+                } else {
                     if (sz[6] == '\0') {
                         throw DeadlyImportError("STL: unexpected EOF while parsing facet");
                     }
@@ -316,16 +321,11 @@ void STLImporter::LoadASCIIFile()
                     normalBuffer.push_back(*vn);
                     normalBuffer.push_back(*vn);
                 }
-            }
-            // vertex 1.50000 1.50000 0.00000
-            else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6)))
-            {
+            } else if (!strncmp(sz,"vertex",6) && ::IsSpaceOrNewLine(*(sz+6))) { // vertex 1.50000 1.50000 0.00000
                 if (faceVertexCounter >= 3) {
                     DefaultLogger::get()->error("STL: a facet with more than 3 vertices has been found");
                     ++sz;
-                }
-                else
-                {
+                } else {
                     if (sz[6] == '\0') {
                         throw DeadlyImportError("STL: unexpected EOF while parsing facet");
                     }
@@ -340,17 +340,14 @@ void STLImporter::LoadASCIIFile()
                     sz = fast_atoreal_move<ai_real>(sz, (ai_real&)vn->z );
                     faceVertexCounter++;
                 }
-            }
-            else if (!::strncmp(sz,"endsolid",8))    {
+            } else if (!::strncmp(sz,"endsolid",8))    {
                 do {
                     ++sz;
                 } while (!::IsLineEnd(*sz));
                 SkipSpacesAndLineEnd(&sz);
                 // finished!
                 break;
-            }
-            // else skip the whole identifier
-            else {
+            } else { // else skip the whole identifier
                 do {
                     ++sz;
                 } while (!::IsSpaceOrNewLine(*sz));
@@ -380,13 +377,22 @@ void STLImporter::LoadASCIIFile()
 
         // now copy faces
         addFacesToMesh(pMesh);
+
+        // assign the meshes to the current node
+        pushMeshesToNode( meshIndices, node );
     }
+
     // now add the loaded meshes
     pScene->mNumMeshes = (unsigned int)meshes.size();
     pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-    for (size_t i = 0; i < meshes.size(); i++)
-    {
-        pScene->mMeshes[i] = meshes[i];
+    for (size_t i = 0; i < meshes.size(); i++) {
+        pScene->mMeshes[ i ] = meshes[i];
+    }
+
+    root->mNumChildren = nodes.size();
+    root->mChildren = new aiNode*[ root->mNumChildren ];
+    for ( size_t i=0; i<nodes.size(); ++i ) {
+        root->mChildren[ i ] = nodes[ i ];
     }
 }
 
@@ -513,4 +519,18 @@ bool STLImporter::LoadBinaryFile()
     return false;
 }
 
+void STLImporter::pushMeshesToNode( std::vector<unsigned int> &meshIndices, aiNode *node ) {
+    ai_assert( nullptr != node );
+    if ( meshIndices.empty() ) {
+        return;
+    }
+
+    node->mNumMeshes = static_cast<unsigned int>( meshIndices.size() );
+    node->mMeshes = new unsigned int[ meshIndices.size() ];
+    for ( size_t i=0; i<meshIndices.size(); ++i ) {
+        node->mMeshes[ i ] = meshIndices[ i ];
+    }
+    meshIndices.clear();
+}
+
 #endif // !! ASSIMP_BUILD_NO_STL_IMPORTER

+ 34 - 26
code/STLLoader.h

@@ -48,53 +48,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BaseImporter.h"
 #include <assimp/types.h>
 
-namespace Assimp    {
+// Forward declarations
+struct aiNode;
+
+namespace Assimp {
+
 
 // ---------------------------------------------------------------------------
-/** Importer class for the sterolithography STL file format
-*/
-class STLImporter : public BaseImporter
-{
+/**
+ * @brief   Importer class for the sterolithography STL file format.
+ */
+class STLImporter : public BaseImporter {
 public:
+    /**
+     * @brief STLImporter, the class default constructor.
+     */
     STLImporter();
-    ~STLImporter();
 
+    /**
+     * @brief   The class destructor.
+     */
+    ~STLImporter();
 
-public:
-
-    // -------------------------------------------------------------------
-    /** Returns whether the class can handle the format of the given file.
-     * See BaseImporter::CanRead() for details.
+    /**
+     * @brief   Returns whether the class can handle the format of the given file.
+     *  See BaseImporter::CanRead() for details.
      */
-    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
 
 protected:
 
-    // -------------------------------------------------------------------
-    /** Return importer meta information.
-     * See #BaseImporter::GetInfo for the details
+    /**
+     * @brief   Return importer meta information.
+     *  See #BaseImporter::GetInfo for the details
      */
     const aiImporterDesc* GetInfo () const;
 
-    // -------------------------------------------------------------------
-    /** Imports the given file into the given scene structure.
+    /**
+     * @brief   Imports the given file into the given scene structure.
     * See BaseImporter::InternReadFile() for details
     */
     void InternReadFile( const std::string& pFile, aiScene* pScene,
         IOSystem* pIOHandler);
 
-
-    // -------------------------------------------------------------------
-    /** Loads a binary .stl file
+    /**
+     * @brief   Loads a binary .stl file
      * @return true if the default vertex color must be used as material color
-    */
+     */
     bool LoadBinaryFile();
 
-    // -------------------------------------------------------------------
-    /** Loads a ASCII text .stl file
-    */
-    void LoadASCIIFile();
+    /**
+     * @brief   Loads a ASCII text .stl file
+     */
+    void LoadASCIIFile( aiNode *root );
+
+    void pushMeshesToNode( std::vector<unsigned int> &meshIndices, aiNode *node );
 
 protected:
 

+ 1 - 0
test/CMakeLists.txt

@@ -132,6 +132,7 @@ SET( TEST_SRCS
   unit/utX3DImportExport.cpp
   unit/utD3MFImportExport.cpp
   unit/utQ3DImportExport.cpp
+  unit/utSTLImportExport.cpp
   unit/utProfiler.cpp
 )
 SET( POST_PROCESSES

+ 18 - 0
test/models/STL/triangle_with_two_solids.stl

@@ -0,0 +1,18 @@
+solid testTriangle_1
+  facet normal 0.0 0.0 1.0 
+    outer loop 
+      vertex 1.0 1.0 0.0 
+      vertex -1.0 1.0 0.0 
+      vertex 0.0 -1.0 0.0 
+    endloop 
+  endfacet 
+endsolid
+solid testTriangle_2
+  facet normal 0.0 0.0 1.0 
+    outer loop 
+      vertex 3.0 3.0 0.0 
+      vertex 2.0 3.0 0.0 
+      vertex 0.0 2.0 0.0 
+    endloop 
+  endfacet 
+endsolid

+ 68 - 0
test/unit/utSTLImportExport.cpp

@@ -0,0 +1,68 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2017, 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.
+---------------------------------------------------------------------------
+*/
+
+#include "UnitTestPCH.h"
+#include "SceneDiffer.h"
+#include "AbstractImportExportBase.h"
+
+#include <assimp/Importer.hpp>
+
+using namespace Assimp;
+
+class utSTLImporterExporter : public AbstractImportExportBase {
+public:
+    virtual bool importerTest() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/Spider_ascii.stl", 0 );
+        return nullptr != scene;
+    }
+};
+
+TEST_F( utSTLImporterExporter, importXFromFileTest ) {
+    EXPECT_TRUE( importerTest() );
+}
+
+TEST_F( utSTLImporterExporter, test_with_two_solids ) {
+    Assimp::Importer importer;
+    const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", 0 );
+    EXPECT_NE( nullptr, scene );
+}