Introduce export with test for point clouds.

pull/1935/head
Kim Kulling 2018-05-01 13:28:53 +02:00
parent 9f835ea843
commit 2c47717ca6
8 changed files with 109 additions and 38 deletions

View File

@ -62,6 +62,7 @@ Here we implement only the C++ interface (Assimp::Exporter).
#include "JoinVerticesProcess.h" #include "JoinVerticesProcess.h"
#include "MakeVerboseFormat.h" #include "MakeVerboseFormat.h"
#include "ConvertToLHProcess.h" #include "ConvertToLHProcess.h"
#include "PretransformVertices.h"
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#include "ScenePrivate.h" #include "ScenePrivate.h"
#include <memory> #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 // dispatch other processes
for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
BaseProcess* const p = pimpl->mPostProcessingSteps[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<FlipUVsProcess*>(p)
&& !dynamic_cast<FlipWindingOrderProcess*>(p) && !dynamic_cast<FlipWindingOrderProcess*>(p)
&& !dynamic_cast<MakeLeftHandedProcess*>(p)) { && !dynamic_cast<MakeLeftHandedProcess*>(p)) {
if (dynamic_cast<PretransformVertices*>(p) && exportPointCloud) {
continue;
}
p->Execute(scenecopy.get()); p->Execute(scenecopy.get());
} }
} }
@ -441,7 +449,6 @@ const char* Exporter::GetErrorString() const {
return pimpl->mError.c_str(); return pimpl->mError.c_str();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Exporter::FreeBlob() { void Exporter::FreeBlob() {
delete pimpl->blob; delete pimpl->blob;
@ -495,7 +502,8 @@ aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void Exporter::UnregisterExporter(const char* id) { 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)) { if (!strcmp((*it).mDescription.id,id)) {
pimpl->mExporters.erase(it); pimpl->mExporters.erase(it);
break; break;

View File

@ -60,14 +60,17 @@ using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
PretransformVertices::PretransformVertices() PretransformVertices::PretransformVertices()
: configKeepHierarchy (false), configNormalize(false), configTransform(false), configTransformation() : configKeepHierarchy (false)
{ , configNormalize(false)
, configTransform(false)
, configTransformation()
, mConfigPointCloud( false ) {
// empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well // Destructor, private as well
PretransformVertices::~PretransformVertices() PretransformVertices::~PretransformVertices() {
{
// nothing to do here // 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)); configTransform = (0 != pImp->GetPropertyInteger(AI_CONFIG_PP_PTV_ADD_ROOT_TRANSFORMATION,0));
configTransformation = pImp->GetPropertyMatrix(AI_CONFIG_PP_PTV_ROOT_TRANSFORMATION, aiMatrix4x4()); 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]->mBones = NULL;
pScene->mMeshes[i]->mNumBones = 0; pScene->mMeshes[i]->mNumBones = 0;
} }
} } else {
else {
apcOutMeshes.reserve(pScene->mNumMaterials<<1u); apcOutMeshes.reserve(pScene->mNumMaterials<<1u);
std::list<unsigned int> aiVFormats; 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 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"); throw DeadlyImportError("No output meshes: all meshes are orphaned and are not referenced by any nodes");
} }
else else

View File

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

View File

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

View File

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

View File

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

View File

@ -138,18 +138,19 @@ TEST_F( utPLYImportExport, vertexColorTest ) {
EXPECT_EQ(2u, first_face.mIndices[2]); 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) { TEST_F(utPLYImportExport, pointcloudTest) {
Assimp::Importer importer; 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); //Could not use aiProcess_ValidateDataStructure since it's missing faces.
EXPECT_NE(nullptr, scene->mMeshes[0]); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/PLY/issue623.ply", 0);
EXPECT_EQ(24u, scene->mMeshes[0]->mNumVertices); EXPECT_NE(nullptr, scene);
EXPECT_EQ(aiPrimitiveType::aiPrimitiveType_POINT, scene->mMeshes[0]->mPrimitiveTypes);
EXPECT_EQ(0u, scene->mMeshes[0]->mNumFaces); 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 = static const char *test_file =

View File

@ -47,6 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <assimp/postprocess.h> #include <assimp/postprocess.h>
#include <assimp/Exporter.hpp>
#include <assimp/scene.h>
#include <vector>
using namespace Assimp; 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 ); const aiScene *scene = importer.ReadFile( ASSIMP_TEST_MODELS_DIR "/STL/triangle_with_two_solids.stl", aiProcess_ValidateDataStructure );
EXPECT_NE( nullptr, scene ); 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