vrshoot
diff libs/assimp/Exporter.cpp @ 0:b2f14e535253
initial commit
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Sat, 01 Feb 2014 19:58:19 +0200 |
parents | |
children |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/libs/assimp/Exporter.cpp Sat Feb 01 19:58:19 2014 +0200 1.3 @@ -0,0 +1,414 @@ 1.4 +/* 1.5 +--------------------------------------------------------------------------- 1.6 +Open Asset Import Library (assimp) 1.7 +--------------------------------------------------------------------------- 1.8 + 1.9 +Copyright (c) 2006-2012, assimp team 1.10 + 1.11 +All rights reserved. 1.12 + 1.13 +Redistribution and use of this software in source and binary forms, 1.14 +with or without modification, are permitted provided that the following 1.15 +conditions are met: 1.16 + 1.17 +* Redistributions of source code must retain the above 1.18 + copyright notice, this list of conditions and the 1.19 + following disclaimer. 1.20 + 1.21 +* Redistributions in binary form must reproduce the above 1.22 + copyright notice, this list of conditions and the 1.23 + following disclaimer in the documentation and/or other 1.24 + materials provided with the distribution. 1.25 + 1.26 +* Neither the name of the assimp team, nor the names of its 1.27 + contributors may be used to endorse or promote products 1.28 + derived from this software without specific prior 1.29 + written permission of the assimp team. 1.30 + 1.31 +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 1.32 +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 1.33 +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 1.34 +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 1.35 +OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 1.36 +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 1.37 +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 1.38 +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 1.39 +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 1.40 +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 1.41 +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 1.42 +--------------------------------------------------------------------------- 1.43 +*/ 1.44 + 1.45 +/** @file Exporter.cpp 1.46 + 1.47 +Assimp export interface. While it's public interface bears many similarities 1.48 +to the import interface (in fact, it is largely symmetric), the internal 1.49 +implementations differs a lot. Exporters are considered stateless and are 1.50 +simple callbacks which we maintain in a global list along with their 1.51 +description strings. 1.52 + 1.53 +Here we implement only the C++ interface (Assimp::Exporter). 1.54 +*/ 1.55 + 1.56 +#include "AssimpPCH.h" 1.57 + 1.58 +#ifndef ASSIMP_BUILD_NO_EXPORT 1.59 + 1.60 +#include "DefaultIOSystem.h" 1.61 +#include "BlobIOSystem.h" 1.62 +#include "SceneCombiner.h" 1.63 +#include "BaseProcess.h" 1.64 +#include "Importer.h" // need this for GetPostProcessingStepInstanceList() 1.65 + 1.66 +#include "MakeVerboseFormat.h" 1.67 +#include "ConvertToLHProcess.h" 1.68 + 1.69 +namespace Assimp { 1.70 + 1.71 +// PostStepRegistry.cpp 1.72 +void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out); 1.73 + 1.74 +// ------------------------------------------------------------------------------------------------ 1.75 +// Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype 1.76 +void ExportSceneCollada(const char*,IOSystem*, const aiScene*); 1.77 +void ExportSceneObj(const char*,IOSystem*, const aiScene*); 1.78 +void ExportSceneSTL(const char*,IOSystem*, const aiScene*); 1.79 +void ExportScenePly(const char*,IOSystem*, const aiScene*); 1.80 +void ExportScene3DS(const char*, IOSystem*, const aiScene*) {} 1.81 + 1.82 +// ------------------------------------------------------------------------------------------------ 1.83 +// global array of all export formats which Assimp supports in its current build 1.84 +Exporter::ExportFormatEntry gExporters[] = 1.85 +{ 1.86 +#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER 1.87 + Exporter::ExportFormatEntry( "collada", "COLLADA - Digital Asset Exchange Schema", "dae", &ExportSceneCollada), 1.88 +#endif 1.89 + 1.90 +#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER 1.91 + Exporter::ExportFormatEntry( "obj", "Wavefront OBJ format", "obj", &ExportSceneObj, 1.92 + aiProcess_GenNormals | aiProcess_PreTransformVertices), 1.93 +#endif 1.94 + 1.95 +#ifndef ASSIMP_BUILD_NO_STL_EXPORTER 1.96 + Exporter::ExportFormatEntry( "stl", "Stereolithography", "stl" , &ExportSceneSTL, 1.97 + aiProcess_Triangulate | aiProcess_GenNormals | aiProcess_PreTransformVertices 1.98 + ), 1.99 +#endif 1.100 + 1.101 +#ifndef ASSIMP_BUILD_NO_PLY_EXPORTER 1.102 + Exporter::ExportFormatEntry( "ply", "Stanford Polygon Library", "ply" , &ExportScenePly, 1.103 + aiProcess_PreTransformVertices 1.104 + ), 1.105 +#endif 1.106 + 1.107 +//#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER 1.108 +// ExportFormatEntry( "3ds", "Autodesk 3DS (legacy format)", "3ds" , &ExportScene3DS), 1.109 +//#endif 1.110 +}; 1.111 + 1.112 +#define ASSIMP_NUM_EXPORTERS (sizeof(gExporters)/sizeof(gExporters[0])) 1.113 + 1.114 + 1.115 +class ExporterPimpl { 1.116 +public: 1.117 + 1.118 + ExporterPimpl() 1.119 + : blob() 1.120 + , mIOSystem(new Assimp::DefaultIOSystem()) 1.121 + , mIsDefaultIOHandler(true) 1.122 + { 1.123 + GetPostProcessingStepInstanceList(mPostProcessingSteps); 1.124 + 1.125 + // grab all builtin exporters 1.126 + mExporters.resize(ASSIMP_NUM_EXPORTERS); 1.127 + std::copy(gExporters,gExporters+ASSIMP_NUM_EXPORTERS,mExporters.begin()); 1.128 + } 1.129 + 1.130 + ~ExporterPimpl() 1.131 + { 1.132 + delete blob; 1.133 + 1.134 + // Delete all post-processing plug-ins 1.135 + for( unsigned int a = 0; a < mPostProcessingSteps.size(); a++) { 1.136 + delete mPostProcessingSteps[a]; 1.137 + } 1.138 + } 1.139 + 1.140 +public: 1.141 + 1.142 + aiExportDataBlob* blob; 1.143 + boost::shared_ptr< Assimp::IOSystem > mIOSystem; 1.144 + bool mIsDefaultIOHandler; 1.145 + 1.146 + /** Post processing steps we can apply at the imported data. */ 1.147 + std::vector< BaseProcess* > mPostProcessingSteps; 1.148 + 1.149 + /** Last fatal export error */ 1.150 + std::string mError; 1.151 + 1.152 + /** Exporters, this includes those registered using #Assimp::Exporter::RegisterExporter */ 1.153 + std::vector<Exporter::ExportFormatEntry> mExporters; 1.154 +}; 1.155 + 1.156 + 1.157 +} // end of namespace Assimp 1.158 + 1.159 + 1.160 + 1.161 + 1.162 + 1.163 +using namespace Assimp; 1.164 + 1.165 + 1.166 +// ------------------------------------------------------------------------------------------------ 1.167 +Exporter :: Exporter() 1.168 +: pimpl(new ExporterPimpl()) 1.169 +{ 1.170 +} 1.171 + 1.172 + 1.173 +// ------------------------------------------------------------------------------------------------ 1.174 +Exporter :: ~Exporter() 1.175 +{ 1.176 + FreeBlob(); 1.177 +} 1.178 + 1.179 + 1.180 +// ------------------------------------------------------------------------------------------------ 1.181 +void Exporter :: SetIOHandler( IOSystem* pIOHandler) 1.182 +{ 1.183 + pimpl->mIsDefaultIOHandler = !pIOHandler; 1.184 + pimpl->mIOSystem.reset(pIOHandler); 1.185 +} 1.186 + 1.187 + 1.188 +// ------------------------------------------------------------------------------------------------ 1.189 +IOSystem* Exporter :: GetIOHandler() const 1.190 +{ 1.191 + return pimpl->mIOSystem.get(); 1.192 +} 1.193 + 1.194 + 1.195 +// ------------------------------------------------------------------------------------------------ 1.196 +bool Exporter :: IsDefaultIOHandler() const 1.197 +{ 1.198 + return pimpl->mIsDefaultIOHandler; 1.199 +} 1.200 + 1.201 + 1.202 +// ------------------------------------------------------------------------------------------------ 1.203 +const aiExportDataBlob* Exporter :: ExportToBlob( const aiScene* pScene, const char* pFormatId, unsigned int pPreprocessing ) 1.204 +{ 1.205 + if (pimpl->blob) { 1.206 + delete pimpl->blob; 1.207 + pimpl->blob = NULL; 1.208 + } 1.209 + 1.210 + 1.211 + boost::shared_ptr<IOSystem> old = pimpl->mIOSystem; 1.212 + 1.213 + BlobIOSystem* blobio = new BlobIOSystem(); 1.214 + pimpl->mIOSystem = boost::shared_ptr<IOSystem>( blobio ); 1.215 + 1.216 + if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName())) { 1.217 + pimpl->mIOSystem = old; 1.218 + return NULL; 1.219 + } 1.220 + 1.221 + pimpl->blob = blobio->GetBlobChain(); 1.222 + pimpl->mIOSystem = old; 1.223 + 1.224 + return pimpl->blob; 1.225 +} 1.226 + 1.227 + 1.228 +// ------------------------------------------------------------------------------------------------ 1.229 +aiReturn Exporter :: Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing ) 1.230 +{ 1.231 + ASSIMP_BEGIN_EXCEPTION_REGION(); 1.232 + 1.233 + pimpl->mError = ""; 1.234 + for (size_t i = 0; i < pimpl->mExporters.size(); ++i) { 1.235 + const Exporter::ExportFormatEntry& exp = pimpl->mExporters[i]; 1.236 + if (!strcmp(exp.mDescription.id,pFormatId)) { 1.237 + 1.238 + try { 1.239 + 1.240 + // Always create a full copy of the scene. We might optimize this one day, 1.241 + // but for now it is the most pragmatic way. 1.242 + aiScene* scenecopy_tmp; 1.243 + SceneCombiner::CopyScene(&scenecopy_tmp,pScene); 1.244 + 1.245 + std::auto_ptr<aiScene> scenecopy(scenecopy_tmp); 1.246 + const ScenePrivateData* const priv = ScenePriv(pScene); 1.247 + 1.248 + // steps that are not idempotent, i.e. we might need to run them again, usually to get back to the 1.249 + // original state before the step was applied first. When checking which steps we don't need 1.250 + // to run, those are excluded. 1.251 + const unsigned int nonIdempotentSteps = aiProcess_FlipWindingOrder | aiProcess_FlipUVs | aiProcess_MakeLeftHanded; 1.252 + 1.253 + // Erase all pp steps that were already applied to this scene 1.254 + unsigned int pp = (exp.mEnforcePP | pPreprocessing) & ~(priv 1.255 + ? (priv->mPPStepsApplied & ~nonIdempotentSteps) 1.256 + : 0u); 1.257 + 1.258 + // If no extra postprocessing was specified, and we obtained this scene from an 1.259 + // Assimp importer, apply the reverse steps automatically. 1.260 + if (!pPreprocessing && priv) { 1.261 + pp |= (nonIdempotentSteps & priv->mPPStepsApplied); 1.262 + } 1.263 + 1.264 + // If the input scene is not in verbose format, but there is at least postprocessing step that relies on it, 1.265 + // we need to run the MakeVerboseFormat step first. 1.266 + if (scenecopy->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) { 1.267 + 1.268 + bool verbosify = false; 1.269 + for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { 1.270 + BaseProcess* const p = pimpl->mPostProcessingSteps[a]; 1.271 + 1.272 + if (p->IsActive(pp) && p->RequireVerboseFormat()) { 1.273 + verbosify = true; 1.274 + break; 1.275 + } 1.276 + } 1.277 + 1.278 + if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) { 1.279 + DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first"); 1.280 + 1.281 + MakeVerboseFormatProcess proc; 1.282 + proc.Execute(scenecopy.get()); 1.283 + } 1.284 + } 1.285 + 1.286 + if (pp) { 1.287 + // the three 'conversion' steps need to be executed first because all other steps rely on the standard data layout 1.288 + { 1.289 + FlipWindingOrderProcess step; 1.290 + if (step.IsActive(pp)) { 1.291 + step.Execute(scenecopy.get()); 1.292 + } 1.293 + } 1.294 + 1.295 + { 1.296 + FlipUVsProcess step; 1.297 + if (step.IsActive(pp)) { 1.298 + step.Execute(scenecopy.get()); 1.299 + } 1.300 + } 1.301 + 1.302 + { 1.303 + MakeLeftHandedProcess step; 1.304 + if (step.IsActive(pp)) { 1.305 + step.Execute(scenecopy.get()); 1.306 + } 1.307 + } 1.308 + 1.309 + // dispatch other processes 1.310 + for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) { 1.311 + BaseProcess* const p = pimpl->mPostProcessingSteps[a]; 1.312 + 1.313 + if (p->IsActive(pp) 1.314 + && !dynamic_cast<FlipUVsProcess*>(p) 1.315 + && !dynamic_cast<FlipWindingOrderProcess*>(p) 1.316 + && !dynamic_cast<MakeLeftHandedProcess*>(p)) { 1.317 + 1.318 + p->Execute(scenecopy.get()); 1.319 + } 1.320 + } 1.321 + ScenePrivateData* const privOut = ScenePriv(scenecopy.get()); 1.322 + ai_assert(privOut); 1.323 + 1.324 + privOut->mPPStepsApplied |= pp; 1.325 + } 1.326 + 1.327 + exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get()); 1.328 + } 1.329 + catch (DeadlyExportError& err) { 1.330 + pimpl->mError = err.what(); 1.331 + return AI_FAILURE; 1.332 + } 1.333 + return AI_SUCCESS; 1.334 + } 1.335 + } 1.336 + 1.337 + pimpl->mError = std::string("Found no exporter to handle this file format: ") + pFormatId; 1.338 + ASSIMP_END_EXCEPTION_REGION(aiReturn); 1.339 + return AI_FAILURE; 1.340 +} 1.341 + 1.342 + 1.343 +// ------------------------------------------------------------------------------------------------ 1.344 +const char* Exporter :: GetErrorString() const 1.345 +{ 1.346 + return pimpl->mError.c_str(); 1.347 +} 1.348 + 1.349 + 1.350 +// ------------------------------------------------------------------------------------------------ 1.351 +void Exporter :: FreeBlob( ) 1.352 +{ 1.353 + delete pimpl->blob; 1.354 + pimpl->blob = NULL; 1.355 + 1.356 + pimpl->mError = ""; 1.357 +} 1.358 + 1.359 + 1.360 +// ------------------------------------------------------------------------------------------------ 1.361 +const aiExportDataBlob* Exporter :: GetBlob() const 1.362 +{ 1.363 + return pimpl->blob; 1.364 +} 1.365 + 1.366 + 1.367 +// ------------------------------------------------------------------------------------------------ 1.368 +const aiExportDataBlob* Exporter :: GetOrphanedBlob() const 1.369 +{ 1.370 + const aiExportDataBlob* tmp = pimpl->blob; 1.371 + pimpl->blob = NULL; 1.372 + return tmp; 1.373 +} 1.374 + 1.375 + 1.376 +// ------------------------------------------------------------------------------------------------ 1.377 +size_t Exporter :: GetExportFormatCount() const 1.378 +{ 1.379 + return pimpl->mExporters.size(); 1.380 +} 1.381 + 1.382 +// ------------------------------------------------------------------------------------------------ 1.383 +const aiExportFormatDesc* Exporter :: GetExportFormatDescription( size_t pIndex ) const 1.384 +{ 1.385 + if (pIndex >= GetExportFormatCount()) { 1.386 + return NULL; 1.387 + } 1.388 + 1.389 + return &pimpl->mExporters[pIndex].mDescription; 1.390 +} 1.391 + 1.392 +// ------------------------------------------------------------------------------------------------ 1.393 +aiReturn Exporter :: RegisterExporter(const ExportFormatEntry& desc) 1.394 +{ 1.395 + BOOST_FOREACH(const ExportFormatEntry& e, pimpl->mExporters) { 1.396 + if (!strcmp(e.mDescription.id,desc.mDescription.id)) { 1.397 + return aiReturn_FAILURE; 1.398 + } 1.399 + } 1.400 + 1.401 + pimpl->mExporters.push_back(desc); 1.402 + return aiReturn_SUCCESS; 1.403 +} 1.404 + 1.405 + 1.406 +// ------------------------------------------------------------------------------------------------ 1.407 +void Exporter :: UnregisterExporter(const char* id) 1.408 +{ 1.409 + for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) { 1.410 + if (!strcmp((*it).mDescription.id,id)) { 1.411 + pimpl->mExporters.erase(it); 1.412 + break; 1.413 + } 1.414 + } 1.415 +} 1.416 + 1.417 +#endif // !ASSIMP_BUILD_NO_EXPORT