Browse Source

Introduce export with test for point clouds.

Kim Kulling 7 years ago
parent
commit
2c47717ca6

+ 11 - 3
code/Exporter.cpp

@@ -62,6 +62,7 @@ Here we implement only the C++ interface (Assimp::Exporter).
 #include "JoinVerticesProcess.h"
 #include "MakeVerboseFormat.h"
 #include "ConvertToLHProcess.h"
+#include "PretransformVertices.h"
 #include <assimp/Exceptional.h>
 #include "ScenePrivate.h"
 #include <memory>
@@ -397,6 +398,11 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
                         }
                     }
 
+                    bool exportPointCloud(false);
+                    if (nullptr != pProperties) {
+                        exportPointCloud = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
+                    }
+
                     // dispatch other processes
                     for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
                         BaseProcess* const p = pimpl->mPostProcessingSteps[a];
@@ -405,7 +411,9 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
                             && !dynamic_cast<FlipUVsProcess*>(p)
                             && !dynamic_cast<FlipWindingOrderProcess*>(p)
                             && !dynamic_cast<MakeLeftHandedProcess*>(p)) {
-
+                            if (dynamic_cast<PretransformVertices*>(p) && exportPointCloud) {
+                                continue;
+                            }
                             p->Execute(scenecopy.get());
                         }
                     }
@@ -441,7 +449,6 @@ const char* Exporter::GetErrorString() const {
     return pimpl->mError.c_str();
 }
 
-
 // ------------------------------------------------------------------------------------------------
 void Exporter::FreeBlob() {
     delete pimpl->blob;
@@ -495,7 +502,8 @@ aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) {
 
 // ------------------------------------------------------------------------------------------------
 void Exporter::UnregisterExporter(const char* id) {
-    for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) {
+    for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin();
+            it != pimpl->mExporters.end(); ++it) {
         if (!strcmp((*it).mDescription.id,id)) {
             pimpl->mExporters.erase(it);
             break;

+ 12 - 8
code/PretransformVertices.cpp

@@ -60,14 +60,17 @@ using namespace Assimp;
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 PretransformVertices::PretransformVertices()
-:   configKeepHierarchy (false), configNormalize(false), configTransform(false), configTransformation()
-{
+: configKeepHierarchy (false)
+, configNormalize(false)
+, configTransform(false)
+, configTransformation()
+, mConfigPointCloud( false ) {
+    // empty
 }
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
-PretransformVertices::~PretransformVertices()
-{
+PretransformVertices::~PretransformVertices() {
     // nothing to do here
 }
 
@@ -89,6 +92,8 @@ void PretransformVertices::SetupProperties(const Importer* pImp)
     configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION,0));
 
     configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4());
+
+    mConfigPointCloud = pImp->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -502,9 +507,7 @@ void PretransformVertices::Execute( aiScene* pScene)
             pScene->mMeshes[i]->mBones    = NULL;
             pScene->mMeshes[i]->mNumBones = 0;
         }
-    }
-    else {
-
+    } else {
         apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
         std::list<unsigned int> aiVFormats;
 
@@ -556,7 +559,8 @@ void PretransformVertices::Execute( aiScene* pScene)
         }
 
         // If no meshes are referenced in the node graph it is possible that we get no output meshes.
-        if (apcOutMeshes.empty())   {
+        if (apcOutMeshes.empty()) {
+            
             throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes");
         }
         else

+ 2 - 7
code/PretransformVertices.h

@@ -61,15 +61,11 @@ namespace Assimp    {
  *  and removes the whole graph. The output is a list of meshes, one for
  *  each material.
 */
-class ASSIMP_API PretransformVertices : public BaseProcess
-{
+class ASSIMP_API PretransformVertices : public BaseProcess {
 public:
-
     PretransformVertices ();
     ~PretransformVertices ();
 
-public:
-
     // -------------------------------------------------------------------
     // Check whether step is active
     bool IsActive( unsigned int pFlags) const;
@@ -82,7 +78,6 @@ public:
     // Setup import settings
     void SetupProperties(const Importer* pImp);
 
-
     // -------------------------------------------------------------------
     /** @brief Toggle the 'keep hierarchy' option
      *  @param d hm ... difficult to guess what this means, hu!?
@@ -100,7 +95,6 @@ public:
     }
 
 private:
-
     // -------------------------------------------------------------------
     // Count the number of nodes
     unsigned int CountNodes( aiNode* pcNode );
@@ -161,6 +155,7 @@ private:
     bool configNormalize;
     bool configTransform;
     aiMatrix4x4 configTransformation;
+    bool mConfigPointCloud;
 };
 
 } // end of namespace Assimp

+ 1 - 0
code/RemoveRedundantMaterials.h

@@ -50,6 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/mesh.h>
 
 class RemoveRedundantMatsTest;
+
 namespace Assimp    {
 
 // ---------------------------------------------------------------------------

+ 10 - 8
code/STLExporter.cpp

@@ -141,13 +141,15 @@ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool expo
             mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl;
             for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
                 aiMesh *mesh = pScene->mMeshes[i];
-                if (mesh->mNormals) {
-                    for (unsigned int a = 0; a < mesh->mNumVertices; ++a) {
-                        const aiVector3D& v = mesh->mVertices[a];
-                        mOutput << "  vertex " << v.x << " " << v.y << " " << v.z << endl;
-                        mOutput << "  vertex " << v.x << " " << v.y << " " << v.z << endl;
-                        mOutput << "  vertex " << v.x << " " << v.y << " " << v.z << endl;
-                    }
+                if (nullptr == mesh) {
+                    continue;
+                }
+
+                for (unsigned int a = 0; a < mesh->mNumVertices; ++a) {
+                    const aiVector3D& v = mesh->mVertices[a];
+                    mOutput << "  vertex " << v.x << " " << v.y << " " << v.z << endl;
+                    mOutput << "  vertex " << v.x << " " << v.y << " " << v.z << endl;
+                    mOutput << "  vertex " << v.x << " " << v.y << " " << v.z << endl;
                 }
             }
             mOutput << "endsolid " << name << endl;
@@ -163,7 +165,7 @@ STLExporter::STLExporter(const char* _filename, const aiScene* pScene, bool expo
 }
 
 // ------------------------------------------------------------------------------------------------
-void STLExporter :: WriteMesh(const aiMesh* m)
+void STLExporter::WriteMesh(const aiMesh* m)
 {
     for (unsigned int i = 0; i < m->mNumFaces; ++i) {
         const aiFace& f = m->mFaces[i];

+ 1 - 2
code/STLExporter.h

@@ -52,8 +52,7 @@ struct aiScene;
 struct aiNode;
 struct aiMesh;
 
-namespace Assimp
-{
+namespace Assimp {
 
 // ------------------------------------------------------------------------------------------------
 /** Helper class to export a given scene to a STL file. */

+ 12 - 11
test/unit/utPLYImportExport.cpp

@@ -138,18 +138,19 @@ TEST_F( utPLYImportExport, vertexColorTest ) {
     EXPECT_EQ(2u, first_face.mIndices[2]);
 }
 
-//Test issue #623, PLY importer should not automatically create faces
+// Test issue #623, PLY importer should not automatically create faces
 TEST_F(utPLYImportExport, pointcloudTest) {
-  Assimp::Importer importer;
-  //Could not use aiProcess_ValidateDataStructure since it's missing faces.
-  const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0);
-  EXPECT_NE(nullptr, scene);
-
-  EXPECT_EQ(1u, scene->mNumMeshes);
-  EXPECT_NE(nullptr, scene->mMeshes[0]);
-  EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices);
-  EXPECT_EQ(aiPrimitiveType::aiPrimitiveType_POINT, scene->mMeshes[0]->mPrimitiveTypes);
-  EXPECT_EQ(0u, scene->mMeshes[0]->mNumFaces);
+    Assimp::Importer importer;
+
+    //Could not use aiProcess_ValidateDataStructure since it's missing faces.
+    const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0);
+    EXPECT_NE(nullptr, scene);
+
+    EXPECT_EQ(1u, scene->mNumMeshes);
+    EXPECT_NE(nullptr, scene->mMeshes[0]);
+    EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices);
+    EXPECT_EQ(aiPrimitiveType::aiPrimitiveType_POINT, scene->mMeshes[0]->mPrimitiveTypes);
+    EXPECT_EQ(0u, scene->mMeshes[0]->mNumFaces);
 }
 
 static const char *test_file =

+ 61 - 0
test/unit/utSTLImportExport.cpp

@@ -47,6 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/Importer.hpp>
 #include <assimp/postprocess.h>
+#include <assimp/Exporter.hpp>
+#include <assimp/scene.h>
+
+#include <vector>
 
 using namespace Assimp;
 
@@ -68,3 +72,60 @@ TEST_F( utSTLImporterExporter, test_with_two_solids ) {
     const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", aiProcess_ValidateDataStructure );
     EXPECT_NE( nullptr, scene );
 }
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+
+TEST_F(utSTLImporterExporter, test_export_pointclouds) {
+    struct XYZ {
+        float x, y, z;
+    };
+
+    std::vector<XYZ> points;
+
+    for (size_t i = 0; i < 10; ++i) {
+        XYZ current;
+        current.x = static_cast<float>(i);
+        current.y = static_cast<float>(i);
+        current.z = static_cast<float>(i);
+        points.push_back(current);
+    }
+    aiScene scene;
+    scene.mRootNode = new aiNode();
+
+    scene.mMeshes = new aiMesh*[1];
+    scene.mMeshes[0] = nullptr;
+    scene.mNumMeshes = 1;
+
+    scene.mMaterials = new aiMaterial*[1];
+    scene.mMaterials[0] = nullptr;
+    scene.mNumMaterials = 1;
+
+    scene.mMaterials[0] = new aiMaterial();
+
+    scene.mMeshes[0] = new aiMesh();
+    scene.mMeshes[0]->mMaterialIndex = 0;
+
+    scene.mRootNode->mMeshes = new unsigned int[1];
+    scene.mRootNode->mMeshes[0] = 0;
+    scene.mRootNode->mNumMeshes = 1;
+
+    auto pMesh = scene.mMeshes[0];
+
+    long numValidPoints = points.size();
+
+    pMesh->mVertices = new aiVector3D[numValidPoints];
+    pMesh->mNumVertices = numValidPoints;
+
+    int i = 0;
+    for (XYZ &p : points) {
+        pMesh->mVertices[i] = aiVector3D(p.x, p.y, p.z);
+        ++i;
+    }
+
+    Assimp::Exporter mAiExporter;
+    ExportProperties *properties = new ExportProperties;
+    properties->SetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS, true);
+    mAiExporter.Export(&scene, "stl", "testExport.stl", 0, properties );
+}
+
+#endif