Browse Source

closes https://github.com/assimp/assimp/issues/104: deal with more solids in one STL file.

Kim Kulling 7 years ago
parent
commit
9a9f18bbed
2 changed files with 86 additions and 60 deletions
  1. 52 34
      code/STLLoader.cpp
  2. 34 26
      code/STLLoader.h

+ 52 - 34
code/STLLoader.cpp

@@ -200,17 +200,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 +231,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 +248,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 +269,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 +305,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 +319,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 +338,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 +375,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 +517,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
+class 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: