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