From 45b0ccfc922f661977fa88836665382c5429e3cc Mon Sep 17 00:00:00 2001 From: aramis_acg Date: Thu, 4 Aug 2011 11:27:13 +0000 Subject: [PATCH] + experimental STL exporter. - improve process handling during exporting. This is still WIP. + BaseProcess::RequireVerboseFormat. git-svn-id: https://assimp.svn.sourceforge.net/svnroot/assimp/trunk@1062 67173fc5-114c-0410-ac8e-9d2fd5bffc1f --- code/BaseProcess.cpp | 7 ++ code/BaseProcess.h | 5 + code/CMakeLists.txt | 6 +- code/Exporter.cpp | 67 ++++++++++- code/MakeVerboseFormat.h | 4 +- code/ObjExporter.h | 2 +- code/STLExporter.cpp | 112 +++++++++++++++++++ code/STLExporter.h | 84 ++++++++++++++ workspaces/vc9/assimp.vcproj | 208 ++++++++++++++++++----------------- 9 files changed, 385 insertions(+), 110 deletions(-) create mode 100644 code/STLExporter.cpp create mode 100644 code/STLExporter.h diff --git a/code/BaseProcess.cpp b/code/BaseProcess.cpp index cf27a1954..ff2f14247 100644 --- a/code/BaseProcess.cpp +++ b/code/BaseProcess.cpp @@ -96,3 +96,10 @@ void BaseProcess::SetupProperties(const Importer* /*pImp*/) { // the default implementation does nothing } + +// ------------------------------------------------------------------------------------------------ +bool BaseProcess::RequireVerboseFormat() const +{ + return true; +} + diff --git a/code/BaseProcess.h b/code/BaseProcess.h index c89d7b608..0a21e2689 100644 --- a/code/BaseProcess.h +++ b/code/BaseProcess.h @@ -234,6 +234,11 @@ public: */ virtual bool IsActive( unsigned int pFlags) const = 0; + // ------------------------------------------------------------------- + /** Check whether this step expects its input vertex data to be + * in verbose format. */ + virtual bool RequireVerboseFormat() const; + // ------------------------------------------------------------------- /** Executes the post processing step on the given imported data. * The function deletes the scene if the postprocess step fails ( diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 57449dcfa..d7c940e0c 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -435,6 +435,8 @@ SET( PostProcessing_SRCS ProcessHelper.h ProcessHelper.cpp PolyTools.h + MakeVerboseFormat.cpp + MakeVerboseFormat.h ) SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS}) @@ -470,6 +472,8 @@ SOURCE_GROUP( SMD FILES ${SMD_SRCS}) SET( STL_SRCS STLLoader.cpp STLLoader.h + STLExporter.h + STLExporter.cpp ) SOURCE_GROUP( STL FILES ${STL_SRCS}) @@ -496,8 +500,6 @@ SET( Exporter_SRCS SOURCE_GROUP( Exporter FILES ${Exporter_SRCS}) SET( Extra_SRCS - MakeVerboseFormat.cpp - MakeVerboseFormat.h MD4FileData.h ) SOURCE_GROUP( Extra FILES ${Extra_SRCS}) diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 1ae4da17b..7fa01f706 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -60,6 +60,9 @@ Here we implement only the C++ interface (Assimp::Exporter). #include "BaseProcess.h" #include "Importer.h" // need this for GetPostProcessingStepInstanceList() +#include "MakeVerboseFormat.h" +#include "ConvertToLHProcess.h" + namespace Assimp { // PostStepRegistry.cpp @@ -69,6 +72,7 @@ void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out); // Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype void ExportSceneCollada(const char*,IOSystem*, const aiScene*); void ExportSceneObj(const char*,IOSystem*, const aiScene*); +void ExportSceneSTL(const char*,IOSystem*, const aiScene*); void ExportScene3DS(const char*, IOSystem*, const aiScene*) {} /// Function pointer type of a Export worker function @@ -110,9 +114,15 @@ ExportFormatEntry gExporters[] = ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj), #endif -#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER - ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS), +#ifndef ASSIMP_BUILD_NO_STL_EXPORTER + ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL, + aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices + ), #endif + +//#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER +// ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS), +//#endif }; @@ -258,11 +268,60 @@ aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const pp |= (nonIdempotentSteps & priv->mPPStepsApplied); } - if (pp) { + // If the input scene is not in verbose format, but there is at least postprocessing step that relies on it, + // we need to run the MakeVerboseFormat step first. + if (scenecopy->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { + + bool verbosify = false; for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { BaseProcess* const p = pimpl->mPostProcessingSteps[a]; - if (p->IsActive(pp)) { + if (p->IsActive(pp) && p->RequireVerboseFormat()) { + verbosify = true; + break; + } + } + + if (verbosify || (gExporters[i].mEnforcePP & aiProcess_JoinIdenticalVertices)) { + DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first"); + + MakeVerboseFormatProcess proc; + proc.Execute(scenecopy.get()); + } + } + + if (pp) { + // the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout + { + FlipWindingOrderProcess step; + if (step.IsActive(pp)) { + step.Execute(scenecopy.get()); + } + } + + { + FlipUVsProcess step; + if (step.IsActive(pp)) { + step.Execute(scenecopy.get()); + } + } + + { + MakeLeftHandedProcess step; + if (step.IsActive(pp)) { + step.Execute(scenecopy.get()); + } + } + + // dispatch other processes + for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { + BaseProcess* const p = pimpl->mPostProcessingSteps[a]; + + if (p->IsActive(pp) + && !dynamic_cast(p) + && !dynamic_cast(p) + && !dynamic_cast(p)) { + p->Execute(scenecopy.get()); } } diff --git a/code/MakeVerboseFormat.h b/code/MakeVerboseFormat.h index 7140ffc02..b92d86c30 100644 --- a/code/MakeVerboseFormat.h +++ b/code/MakeVerboseFormat.h @@ -63,9 +63,7 @@ namespace Assimp { * useful, too. */ class ASSIMP_API MakeVerboseFormatProcess : public BaseProcess { - friend class Importer; - -protected: +public: /** Constructor to be privately used by Importer, or by applications which know what they are doing if they modify the aiScene object */ diff --git a/code/ObjExporter.h b/code/ObjExporter.h index 619e4e214..ae951e64f 100644 --- a/code/ObjExporter.h +++ b/code/ObjExporter.h @@ -119,4 +119,4 @@ private: } -#endif \ No newline at end of file +#endif diff --git a/code/STLExporter.cpp b/code/STLExporter.cpp new file mode 100644 index 000000000..d1a05737d --- /dev/null +++ b/code/STLExporter.cpp @@ -0,0 +1,112 @@ +/* +Open Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2010, ASSIMP Development 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 Development 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 "AssimpPCH.h" + +#if !defined(ASSIMP_BUILD_NO_EXPORT) && !defined(ASSIMP_BUILD_NO_STL_EXPORTER) + +#include "STLExporter.h" +#include "../include/aiVersion.h" + +using namespace Assimp; +namespace Assimp { + +// ------------------------------------------------------------------------------------------------ +// Worker function for exporting a scene to Stereolithograpy. Prototyped and registered in Exporter.cpp +void ExportSceneSTL(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene) +{ + // invoke the exporter + STLExporter exporter(pFile, pScene); + + // we're still here - export successfully completed. Write the file. + boost::scoped_ptr outfile (pIOSystem->Open(pFile,"wt")); + outfile->Write( exporter.mOutput.str().c_str(), static_cast(exporter.mOutput.tellp()),1); +} + +} // end of namespace Assimp + + +// ------------------------------------------------------------------------------------------------ +STLExporter :: STLExporter(const char* _filename, const aiScene* pScene) +: filename(_filename) +, pScene(pScene) +, endl("\n") +{ + // make sure that all formatting happens using the standard, C locale and not the user's current locale + const std::locale& l = std::locale("C"); + mOutput.imbue(l); + + const std::string& name = "AssimpScene"; + + mOutput << "solid " << name << endl; + for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) { + WriteMesh(pScene->mMeshes[i]); + } + mOutput << "endsolid " << name << endl; +} + +// ------------------------------------------------------------------------------------------------ +void STLExporter :: WriteMesh(const aiMesh* m) +{ + for (unsigned int i = 0; i < m->mNumFaces; ++i) { + const aiFace& f = m->mFaces[i]; + + // we need per-face normals. We specified aiProcess_GenNormals as pre-requisite for this exporter, + // but nonetheless we have to expect per-vertex normals. + aiVector3D nor; + if (m->mNormals) { + for(unsigned int a = 0; a < f.mNumIndices; ++a) { + nor += m->mNormals[f.mIndices[a]]; + } + nor.Normalize(); + } + mOutput << " facet normal " << nor.x << " " << nor.y << " " << nor.z << endl; + mOutput << " outer loop" << endl; + for(unsigned int a = 0; a < f.mNumIndices; ++a) { + const aiVector3D& v = m->mVertices[f.mIndices[a]]; + mOutput << " vertex " << v.x << " " << v.y << " " << v.z << endl; + } + + mOutput << " endloop" << endl; + mOutput << " endfacet" << endl << endl; + } +} + +#endif diff --git a/code/STLExporter.h b/code/STLExporter.h new file mode 100644 index 000000000..c44de7663 --- /dev/null +++ b/code/STLExporter.h @@ -0,0 +1,84 @@ +/* +Open Asset Import Library (ASSIMP) +---------------------------------------------------------------------- + +Copyright (c) 2006-2010, ASSIMP Development 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 Development 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. + +---------------------------------------------------------------------- +*/ + +/** @file STLExporter.h + * Declares the exporter class to write a scene to a Stereolithography (STL) file + */ +#ifndef AI_STLEXPORTER_H_INC +#define AI_STLEXPORTER_H_INC + +#include + +struct aiScene; +struct aiNode; + +namespace Assimp +{ + +// ------------------------------------------------------------------------------------------------ +/** Helper class to export a given scene to a STL file. */ +// ------------------------------------------------------------------------------------------------ +class ASSIMP_API STLExporter +{ +public: + /// Constructor for a specific scene to export + STLExporter(const char* filename, const aiScene* pScene); + +public: + + /// public stringstreams to write all output into + std::ostringstream mOutput; + +private: + + void WriteMesh(const aiMesh* m); + +private: + + const std::string filename; + const aiScene* const pScene; + + // this endl() doesn't flush() the stream + const std::string endl; +}; + +} + +#endif diff --git a/workspaces/vc9/assimp.vcproj b/workspaces/vc9/assimp.vcproj index 56bc74cdf..ea471dea9 100644 --- a/workspaces/vc9/assimp.vcproj +++ b/workspaces/vc9/assimp.vcproj @@ -2124,6 +2124,102 @@ RelativePath="..\..\code\LimitBoneWeightsProcess.h" > + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -2488,102 +2584,6 @@ RelativePath="..\..\code\LineSplitter.h" > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -4188,10 +4188,6 @@ > - - @@ -4204,6 +4200,18 @@ > + + + + + +