vrshoot

diff libs/assimp/Importer.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/Importer.cpp	Sat Feb 01 19:58:19 2014 +0200
     1.3 @@ -0,0 +1,1077 @@
     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  Importer.cpp
    1.46 + *  @brief Implementation of the CPP-API class #Importer
    1.47 + */
    1.48 +
    1.49 +#include "AssimpPCH.h"
    1.50 +#include "assimp/version.h"
    1.51 +
    1.52 +// ------------------------------------------------------------------------------------------------
    1.53 +/* Uncomment this line to prevent Assimp from catching unknown exceptions.
    1.54 + *
    1.55 + * Note that any Exception except DeadlyImportError may lead to 
    1.56 + * undefined behaviour -> loaders could remain in an unusable state and
    1.57 + * further imports with the same Importer instance could fail/crash/burn ...
    1.58 + */
    1.59 +// ------------------------------------------------------------------------------------------------
    1.60 +#ifndef ASSIMP_BUILD_DEBUG
    1.61 +#	define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
    1.62 +#endif
    1.63 +
    1.64 +// ------------------------------------------------------------------------------------------------
    1.65 +// Internal headers
    1.66 +// ------------------------------------------------------------------------------------------------
    1.67 +#include "Importer.h"
    1.68 +#include "BaseProcess.h"
    1.69 +
    1.70 +#include "DefaultIOStream.h"
    1.71 +#include "DefaultIOSystem.h"
    1.72 +#include "DefaultProgressHandler.h"
    1.73 +#include "GenericProperty.h"
    1.74 +#include "ProcessHelper.h"
    1.75 +#include "ScenePreprocessor.h"
    1.76 +#include "MemoryIOWrapper.h"
    1.77 +#include "Profiler.h"
    1.78 +#include "TinyFormatter.h"
    1.79 +
    1.80 +#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
    1.81 +#	include "ValidateDataStructure.h"
    1.82 +#endif
    1.83 +
    1.84 +using namespace Assimp::Profiling;
    1.85 +using namespace Assimp::Formatter;
    1.86 +
    1.87 +namespace Assimp {
    1.88 +	// ImporterRegistry.cpp
    1.89 +	void GetImporterInstanceList(std::vector< BaseImporter* >& out);
    1.90 +	// PostStepRegistry.cpp
    1.91 +	void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
    1.92 +}
    1.93 +
    1.94 +using namespace Assimp;
    1.95 +using namespace Assimp::Intern;
    1.96 +
    1.97 +// ------------------------------------------------------------------------------------------------
    1.98 +// Intern::AllocateFromAssimpHeap serves as abstract base class. It overrides
    1.99 +// new and delete (and their array counterparts) of public API classes (e.g. Logger) to
   1.100 +// utilize our DLL heap.
   1.101 +// See http://www.gotw.ca/publications/mill15.htm
   1.102 +// ------------------------------------------------------------------------------------------------
   1.103 +void* AllocateFromAssimpHeap::operator new ( size_t num_bytes)	{
   1.104 +	return ::operator new(num_bytes);
   1.105 +}
   1.106 +
   1.107 +void* AllocateFromAssimpHeap::operator new ( size_t num_bytes, const std::nothrow_t& ) throw()	{
   1.108 +	try	{
   1.109 +		return AllocateFromAssimpHeap::operator new( num_bytes );
   1.110 +	}
   1.111 +	catch( ... )	{
   1.112 +		return NULL;
   1.113 +	}
   1.114 +}
   1.115 +
   1.116 +void AllocateFromAssimpHeap::operator delete ( void* data)	{
   1.117 +	return ::operator delete(data);
   1.118 +}
   1.119 +
   1.120 +void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes)	{
   1.121 +	return ::operator new[](num_bytes);
   1.122 +}
   1.123 +
   1.124 +void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw() {
   1.125 +	try	{
   1.126 +		return AllocateFromAssimpHeap::operator new[]( num_bytes );
   1.127 +	}
   1.128 +	catch( ... )	{
   1.129 +		return NULL;
   1.130 +	}
   1.131 +}
   1.132 +
   1.133 +void AllocateFromAssimpHeap::operator delete[] ( void* data)	{
   1.134 +	return ::operator delete[](data);
   1.135 +}
   1.136 +
   1.137 +// ------------------------------------------------------------------------------------------------
   1.138 +// Importer constructor. 
   1.139 +Importer::Importer() 
   1.140 +{
   1.141 +	// allocate the pimpl first
   1.142 +	pimpl = new ImporterPimpl();
   1.143 +
   1.144 +	pimpl->mScene = NULL;
   1.145 +	pimpl->mErrorString = "";
   1.146 +
   1.147 +	// Allocate a default IO handler
   1.148 +	pimpl->mIOHandler = new DefaultIOSystem;
   1.149 +	pimpl->mIsDefaultHandler = true; 
   1.150 +	pimpl->bExtraVerbose     = false; // disable extra verbose mode by default
   1.151 +
   1.152 +	pimpl->mProgressHandler = new DefaultProgressHandler();
   1.153 +	pimpl->mIsDefaultProgressHandler = true;
   1.154 +
   1.155 +	GetImporterInstanceList(pimpl->mImporter);
   1.156 +	GetPostProcessingStepInstanceList(pimpl->mPostProcessingSteps);
   1.157 +
   1.158 +	// Allocate a SharedPostProcessInfo object and store pointers to it in all post-process steps in the list.
   1.159 +	pimpl->mPPShared = new SharedPostProcessInfo();
   1.160 +	for (std::vector<BaseProcess*>::iterator it =  pimpl->mPostProcessingSteps.begin();
   1.161 +		it != pimpl->mPostProcessingSteps.end(); 
   1.162 +		++it)	{
   1.163 +
   1.164 +		(*it)->SetSharedData(pimpl->mPPShared);
   1.165 +	}
   1.166 +}
   1.167 +
   1.168 +// ------------------------------------------------------------------------------------------------
   1.169 +// Destructor of Importer
   1.170 +Importer::~Importer()
   1.171 +{
   1.172 +	// Delete all import plugins
   1.173 +	for( unsigned int a = 0; a < pimpl->mImporter.size(); a++)
   1.174 +		delete pimpl->mImporter[a];
   1.175 +
   1.176 +	// Delete all post-processing plug-ins
   1.177 +	for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)
   1.178 +		delete pimpl->mPostProcessingSteps[a];
   1.179 +
   1.180 +	// Delete the assigned IO and progress handler
   1.181 +	delete pimpl->mIOHandler;
   1.182 +	delete pimpl->mProgressHandler;
   1.183 +
   1.184 +	// Kill imported scene. Destructors should do that recursivly
   1.185 +	delete pimpl->mScene;
   1.186 +
   1.187 +	// Delete shared post-processing data
   1.188 +	delete pimpl->mPPShared;
   1.189 +
   1.190 +	// and finally the pimpl itself
   1.191 +	delete pimpl;
   1.192 +}
   1.193 +
   1.194 +// ------------------------------------------------------------------------------------------------
   1.195 +// Copy constructor - copies the config of another Importer, not the scene
   1.196 +Importer::Importer(const Importer &other)
   1.197 +{
   1.198 +	new(this) Importer();
   1.199 +
   1.200 +	pimpl->mIntProperties    = other.pimpl->mIntProperties;
   1.201 +	pimpl->mFloatProperties  = other.pimpl->mFloatProperties;
   1.202 +	pimpl->mStringProperties = other.pimpl->mStringProperties;
   1.203 +}
   1.204 +
   1.205 +// ------------------------------------------------------------------------------------------------
   1.206 +// Register a custom post-processing step
   1.207 +aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
   1.208 +{
   1.209 +	ai_assert(NULL != pImp);
   1.210 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.211 +
   1.212 +		pimpl->mPostProcessingSteps.push_back(pImp);
   1.213 +		DefaultLogger::get()->info("Registering custom post-processing step");
   1.214 +	
   1.215 +	ASSIMP_END_EXCEPTION_REGION(aiReturn);
   1.216 +	return AI_SUCCESS;
   1.217 +}
   1.218 +
   1.219 +// ------------------------------------------------------------------------------------------------
   1.220 +// Register a custom loader plugin
   1.221 +aiReturn Importer::RegisterLoader(BaseImporter* pImp)
   1.222 +{
   1.223 +	ai_assert(NULL != pImp);
   1.224 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.225 +
   1.226 +	// --------------------------------------------------------------------
   1.227 +	// Check whether we would have two loaders for the same file extension 
   1.228 +	// This is absolutely OK, but we should warn the developer of the new
   1.229 +	// loader that his code will probably never be called if the first 
   1.230 +	// loader is a bit too lazy in his file checking.
   1.231 +	// --------------------------------------------------------------------
   1.232 +	std::set<std::string> st;
   1.233 +	std::string baked;
   1.234 +	pImp->GetExtensionList(st);
   1.235 +
   1.236 +	for(std::set<std::string>::const_iterator it = st.begin(); it != st.end(); ++it) {
   1.237 +
   1.238 +#ifdef _DEBUG
   1.239 +		if (IsExtensionSupported(*it)) {
   1.240 +			DefaultLogger::get()->warn("The file extension " + *it + " is already in use");
   1.241 +		}
   1.242 +#endif
   1.243 +		baked += *it;
   1.244 +	}
   1.245 +
   1.246 +	// add the loader
   1.247 +	pimpl->mImporter.push_back(pImp);
   1.248 +	DefaultLogger::get()->info("Registering custom importer for these file extensions: " + baked);
   1.249 +	ASSIMP_END_EXCEPTION_REGION(aiReturn);
   1.250 +	return AI_SUCCESS;
   1.251 +}
   1.252 +
   1.253 +// ------------------------------------------------------------------------------------------------
   1.254 +// Unregister a custom loader plugin
   1.255 +aiReturn Importer::UnregisterLoader(BaseImporter* pImp)
   1.256 +{
   1.257 +	if(!pImp) {
   1.258 +		// unregistering a NULL importer is no problem for us ... really!
   1.259 +		return AI_SUCCESS;
   1.260 +	}
   1.261 +
   1.262 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.263 +	std::vector<BaseImporter*>::iterator it = std::find(pimpl->mImporter.begin(),
   1.264 +		pimpl->mImporter.end(),pImp);
   1.265 +
   1.266 +	if (it != pimpl->mImporter.end())	{
   1.267 +		pimpl->mImporter.erase(it);
   1.268 +
   1.269 +		std::set<std::string> st;
   1.270 +		pImp->GetExtensionList(st);
   1.271 +
   1.272 +		DefaultLogger::get()->info("Unregistering custom importer: ");
   1.273 +		return AI_SUCCESS;
   1.274 +	}
   1.275 +	DefaultLogger::get()->warn("Unable to remove custom importer: I can't find you ...");
   1.276 +	ASSIMP_END_EXCEPTION_REGION(aiReturn);
   1.277 +	return AI_FAILURE;
   1.278 +}
   1.279 +
   1.280 +// ------------------------------------------------------------------------------------------------
   1.281 +// Unregister a custom loader plugin
   1.282 +aiReturn Importer::UnregisterPPStep(BaseProcess* pImp)
   1.283 +{
   1.284 +	if(!pImp) {
   1.285 +		// unregistering a NULL ppstep is no problem for us ... really!
   1.286 +		return AI_SUCCESS;
   1.287 +	}
   1.288 +
   1.289 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.290 +	std::vector<BaseProcess*>::iterator it = std::find(pimpl->mPostProcessingSteps.begin(),
   1.291 +		pimpl->mPostProcessingSteps.end(),pImp);
   1.292 +
   1.293 +	if (it != pimpl->mPostProcessingSteps.end())	{
   1.294 +		pimpl->mPostProcessingSteps.erase(it);
   1.295 +		DefaultLogger::get()->info("Unregistering custom post-processing step");
   1.296 +		return AI_SUCCESS;
   1.297 +	}
   1.298 +	DefaultLogger::get()->warn("Unable to remove custom post-processing step: I can't find you ..");
   1.299 +	ASSIMP_END_EXCEPTION_REGION(aiReturn);
   1.300 +	return AI_FAILURE;
   1.301 +}
   1.302 +
   1.303 +// ------------------------------------------------------------------------------------------------
   1.304 +// Supplies a custom IO handler to the importer to open and access files.
   1.305 +void Importer::SetIOHandler( IOSystem* pIOHandler)
   1.306 +{
   1.307 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.308 +	// If the new handler is zero, allocate a default IO implementation.
   1.309 +	if (!pIOHandler)
   1.310 +	{
   1.311 +		// Release pointer in the possession of the caller
   1.312 +		pimpl->mIOHandler = new DefaultIOSystem();
   1.313 +		pimpl->mIsDefaultHandler = true;
   1.314 +	}
   1.315 +	// Otherwise register the custom handler
   1.316 +	else if (pimpl->mIOHandler != pIOHandler)
   1.317 +	{
   1.318 +		delete pimpl->mIOHandler;
   1.319 +		pimpl->mIOHandler = pIOHandler;
   1.320 +		pimpl->mIsDefaultHandler = false;
   1.321 +	}
   1.322 +	ASSIMP_END_EXCEPTION_REGION(void);
   1.323 +}
   1.324 +
   1.325 +// ------------------------------------------------------------------------------------------------
   1.326 +// Get the currently set IO handler
   1.327 +IOSystem* Importer::GetIOHandler() const
   1.328 +{
   1.329 +	return pimpl->mIOHandler;
   1.330 +}
   1.331 +
   1.332 +// ------------------------------------------------------------------------------------------------
   1.333 +// Check whether a custom IO handler is currently set
   1.334 +bool Importer::IsDefaultIOHandler() const
   1.335 +{
   1.336 +	return pimpl->mIsDefaultHandler;
   1.337 +}
   1.338 +
   1.339 +// ------------------------------------------------------------------------------------------------
   1.340 +// Supplies a custom progress handler to get regular callbacks during importing
   1.341 +void Importer::SetProgressHandler ( ProgressHandler* pHandler )
   1.342 +{
   1.343 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.344 +	// If the new handler is zero, allocate a default implementation.
   1.345 +	if (!pHandler)
   1.346 +	{
   1.347 +		// Release pointer in the possession of the caller
   1.348 +		pimpl->mProgressHandler = new DefaultProgressHandler();
   1.349 +		pimpl->mIsDefaultProgressHandler = true;
   1.350 +	}
   1.351 +	// Otherwise register the custom handler
   1.352 +	else if (pimpl->mProgressHandler != pHandler)
   1.353 +	{
   1.354 +		delete pimpl->mProgressHandler;
   1.355 +		pimpl->mProgressHandler = pHandler;
   1.356 +		pimpl->mIsDefaultProgressHandler = false;
   1.357 +	}
   1.358 +	ASSIMP_END_EXCEPTION_REGION(void);
   1.359 +}
   1.360 +
   1.361 +// ------------------------------------------------------------------------------------------------
   1.362 +// Get the currently set progress handler
   1.363 +ProgressHandler* Importer::GetProgressHandler() const
   1.364 +{
   1.365 +	return pimpl->mProgressHandler;
   1.366 +}
   1.367 +
   1.368 +// ------------------------------------------------------------------------------------------------
   1.369 +// Check whether a custom progress handler is currently set
   1.370 +bool Importer::IsDefaultProgressHandler() const
   1.371 +{
   1.372 +	return pimpl->mIsDefaultProgressHandler;
   1.373 +}
   1.374 +
   1.375 +// ------------------------------------------------------------------------------------------------
   1.376 +// Validate post process step flags 
   1.377 +bool _ValidateFlags(unsigned int pFlags) 
   1.378 +{
   1.379 +	if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals)	{
   1.380 +		DefaultLogger::get()->error("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
   1.381 +		return false;
   1.382 +	}
   1.383 +	if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices)	{
   1.384 +		DefaultLogger::get()->error("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
   1.385 +		return false;
   1.386 +	}
   1.387 +	return true;
   1.388 +}
   1.389 +
   1.390 +// ------------------------------------------------------------------------------------------------
   1.391 +// Free the current scene
   1.392 +void Importer::FreeScene( )
   1.393 +{
   1.394 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.395 +	delete pimpl->mScene;
   1.396 +	pimpl->mScene = NULL;
   1.397 +
   1.398 +	pimpl->mErrorString = "";
   1.399 +	ASSIMP_END_EXCEPTION_REGION(void);
   1.400 +}
   1.401 +
   1.402 +// ------------------------------------------------------------------------------------------------
   1.403 +// Get the current error string, if any
   1.404 +const char* Importer::GetErrorString() const 
   1.405 +{ 
   1.406 +	 /* Must remain valid as long as ReadFile() or FreeFile() are not called */
   1.407 +	return pimpl->mErrorString.c_str();
   1.408 +}
   1.409 +
   1.410 +// ------------------------------------------------------------------------------------------------
   1.411 +// Enable extra-verbose mode
   1.412 +void Importer::SetExtraVerbose(bool bDo)
   1.413 +{
   1.414 +	pimpl->bExtraVerbose = bDo;
   1.415 +}
   1.416 +
   1.417 +// ------------------------------------------------------------------------------------------------
   1.418 +// Get the current scene
   1.419 +const aiScene* Importer::GetScene() const
   1.420 +{
   1.421 +	return pimpl->mScene;
   1.422 +}
   1.423 +
   1.424 +// ------------------------------------------------------------------------------------------------
   1.425 +// Orphan the current scene and return it.
   1.426 +aiScene* Importer::GetOrphanedScene()
   1.427 +{
   1.428 +	aiScene* s = pimpl->mScene;
   1.429 +
   1.430 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.431 +	pimpl->mScene = NULL;
   1.432 +
   1.433 +	pimpl->mErrorString = ""; /* reset error string */
   1.434 +	ASSIMP_END_EXCEPTION_REGION(aiScene*);
   1.435 +	return s;
   1.436 +}
   1.437 +
   1.438 +// ------------------------------------------------------------------------------------------------
   1.439 +// Validate post-processing flags
   1.440 +bool Importer::ValidateFlags(unsigned int pFlags) const
   1.441 +{
   1.442 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.443 +	// run basic checks for mutually exclusive flags
   1.444 +	if(!_ValidateFlags(pFlags)) {
   1.445 +		return false;
   1.446 +	}
   1.447 +
   1.448 +	// ValidateDS does not anymore occur in the pp list, it plays an awesome extra role ...
   1.449 +#ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
   1.450 +	if (pFlags & aiProcess_ValidateDataStructure) {
   1.451 +		return false;
   1.452 +	}
   1.453 +#endif
   1.454 +	pFlags &= ~aiProcess_ValidateDataStructure;
   1.455 +
   1.456 +	// Now iterate through all bits which are set in the flags and check whether we find at least
   1.457 +	// one pp plugin which handles it.
   1.458 +	for (unsigned int mask = 1; mask < (1u << (sizeof(unsigned int)*8-1));mask <<= 1) {
   1.459 +		
   1.460 +		if (pFlags & mask) {
   1.461 +		
   1.462 +			bool have = false;
   1.463 +			for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)	{
   1.464 +				if (pimpl->mPostProcessingSteps[a]-> IsActive(mask) ) {
   1.465 +				
   1.466 +					have = true;
   1.467 +					break;
   1.468 +				}
   1.469 +			}
   1.470 +			if (!have) {
   1.471 +				return false;
   1.472 +			}
   1.473 +		}
   1.474 +	}
   1.475 +	ASSIMP_END_EXCEPTION_REGION(bool);
   1.476 +	return true;
   1.477 +}
   1.478 +
   1.479 +// ------------------------------------------------------------------------------------------------
   1.480 +const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
   1.481 +	size_t pLength,
   1.482 +	unsigned int pFlags,
   1.483 +	const char* pHint /*= ""*/)
   1.484 +{
   1.485 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.486 +	if (!pHint) {
   1.487 +		pHint = "";
   1.488 +	}
   1.489 +
   1.490 +	if (!pBuffer || !pLength || strlen(pHint) > 100) {
   1.491 +		pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()";
   1.492 +		return NULL;
   1.493 +	}
   1.494 +
   1.495 +	// prevent deletion of the previous IOHandler
   1.496 +	IOSystem* io = pimpl->mIOHandler;
   1.497 +	pimpl->mIOHandler = NULL;
   1.498 +
   1.499 +	SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength));
   1.500 +
   1.501 +	// read the file and recover the previous IOSystem
   1.502 +	char fbuff[128];
   1.503 +	sprintf(fbuff,"%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
   1.504 +
   1.505 +	ReadFile(fbuff,pFlags);
   1.506 +	SetIOHandler(io);
   1.507 +
   1.508 +	ASSIMP_END_EXCEPTION_REGION(const aiScene*);
   1.509 +	return pimpl->mScene;
   1.510 +}
   1.511 +
   1.512 +// ------------------------------------------------------------------------------------------------
   1.513 +void WriteLogOpening(const std::string& file)
   1.514 +{
   1.515 +	Logger* l = DefaultLogger::get();
   1.516 +	if (!l) {
   1.517 +		return;
   1.518 +	}
   1.519 +	l->info("Load " + file);
   1.520 +
   1.521 +	// print a full version dump. This is nice because we don't
   1.522 +	// need to ask the authors of incoming bug reports for
   1.523 +	// the library version they're using - a log dump is
   1.524 +	// sufficient.
   1.525 +	const unsigned int flags = aiGetCompileFlags();
   1.526 +	l->debug(format()
   1.527 +		<< "Assimp "
   1.528 +		<< aiGetVersionMajor() 
   1.529 +		<< "." 
   1.530 +		<< aiGetVersionMinor() 
   1.531 +		<< "." 
   1.532 +		<< aiGetVersionRevision()
   1.533 +
   1.534 +		<< " "
   1.535 +#if defined(ASSIMP_BUILD_ARCHITECTURE)
   1.536 +		<< ASSIMP_BUILD_ARCHITECTURE
   1.537 +#elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__)
   1.538 +		<< "x86"
   1.539 +#elif defined(_M_X64) || defined(__x86_64__) 
   1.540 +		<< "amd64"
   1.541 +#elif defined(_M_IA64) || defined(__ia64__)
   1.542 +		<< "itanium"
   1.543 +#elif defined(__ppc__) || defined(__powerpc__)
   1.544 +		<< "ppc32"
   1.545 +#elif defined(__powerpc64__)
   1.546 +		<< "ppc64"
   1.547 +#elif defined(__arm__)
   1.548 +		<< "arm"
   1.549 +#else
   1.550 +	<< "<unknown architecture>"
   1.551 +#endif
   1.552 +
   1.553 +		<< " "
   1.554 +#if defined(ASSIMP_BUILD_COMPILER)
   1.555 +		<< ASSIMP_BUILD_COMPILER
   1.556 +#elif defined(_MSC_VER)
   1.557 +		<< "msvc"
   1.558 +#elif defined(__GNUC__)
   1.559 +		<< "gcc"
   1.560 +#else
   1.561 +		<< "<unknown compiler>"
   1.562 +#endif
   1.563 +
   1.564 +#ifndef NDEBUG
   1.565 +		<< " debug"
   1.566 +#endif
   1.567 +
   1.568 +		<< (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
   1.569 +		<< (flags & ASSIMP_CFLAGS_SHARED  ? " shared" : "")
   1.570 +		<< (flags & ASSIMP_CFLAGS_SINGLETHREADED  ? " singlethreaded" : "")
   1.571 +		);
   1.572 +}
   1.573 +
   1.574 +// ------------------------------------------------------------------------------------------------
   1.575 +// Reads the given file and returns its contents if successful.
   1.576 +const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
   1.577 +{
   1.578 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.579 +	const std::string pFile(_pFile);
   1.580 +
   1.581 +	// ----------------------------------------------------------------------
   1.582 +	// Put a large try block around everything to catch all std::exception's
   1.583 +	// that might be thrown by STL containers or by new(). 
   1.584 +	// ImportErrorException's are throw by ourselves and caught elsewhere.
   1.585 +	//-----------------------------------------------------------------------
   1.586 +
   1.587 +	WriteLogOpening(pFile);
   1.588 +
   1.589 +#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
   1.590 +	try
   1.591 +#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
   1.592 +	{
   1.593 +		// Check whether this Importer instance has already loaded
   1.594 +		// a scene. In this case we need to delete the old one
   1.595 +		if (pimpl->mScene)	{
   1.596 +
   1.597 +			DefaultLogger::get()->debug("(Deleting previous scene)");
   1.598 +			FreeScene();
   1.599 +		}
   1.600 +
   1.601 +		// First check if the file is accessable at all
   1.602 +		if( !pimpl->mIOHandler->Exists( pFile))	{
   1.603 +
   1.604 +			pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
   1.605 +			DefaultLogger::get()->error(pimpl->mErrorString);
   1.606 +			return NULL;
   1.607 +		}
   1.608 +
   1.609 +		boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
   1.610 +		if (profiler) {
   1.611 +			profiler->BeginRegion("total");
   1.612 +		}
   1.613 +
   1.614 +		// Find an worker class which can handle the file
   1.615 +		BaseImporter* imp = NULL;
   1.616 +		for( unsigned int a = 0; a < pimpl->mImporter.size(); a++)	{
   1.617 +
   1.618 +			if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
   1.619 +				imp = pimpl->mImporter[a];
   1.620 +				break;
   1.621 +			}
   1.622 +		}
   1.623 +
   1.624 +		if (!imp)	{
   1.625 +			// not so bad yet ... try format auto detection.
   1.626 +			const std::string::size_type s = pFile.find_last_of('.');
   1.627 +			if (s != std::string::npos) {
   1.628 +				DefaultLogger::get()->info("File extension not known, trying signature-based detection");
   1.629 +				for( unsigned int a = 0; a < pimpl->mImporter.size(); a++)	{
   1.630 +
   1.631 +					if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
   1.632 +						imp = pimpl->mImporter[a];
   1.633 +						break;
   1.634 +					}
   1.635 +				}
   1.636 +			}
   1.637 +			// Put a proper error message if no suitable importer was found
   1.638 +			if( !imp)	{
   1.639 +				pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
   1.640 +				DefaultLogger::get()->error(pimpl->mErrorString);
   1.641 +				return NULL;
   1.642 +			}
   1.643 +		}
   1.644 +
   1.645 +		// Dispatch the reading to the worker class for this format
   1.646 +		DefaultLogger::get()->info("Found a matching importer for this file format");
   1.647 +		pimpl->mProgressHandler->Update();
   1.648 +
   1.649 +		if (profiler) {
   1.650 +			profiler->BeginRegion("import");
   1.651 +		}
   1.652 +
   1.653 +		pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
   1.654 +		pimpl->mProgressHandler->Update();
   1.655 +
   1.656 +		if (profiler) {
   1.657 +			profiler->EndRegion("import");
   1.658 +		}
   1.659 +
   1.660 +		// If successful, apply all active post processing steps to the imported data
   1.661 +		if( pimpl->mScene)	{
   1.662 +
   1.663 +#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
   1.664 +			// The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called.
   1.665 +			if (pFlags & aiProcess_ValidateDataStructure)
   1.666 +			{
   1.667 +				ValidateDSProcess ds;
   1.668 +				ds.ExecuteOnScene (this);
   1.669 +				if (!pimpl->mScene) {
   1.670 +					return NULL;
   1.671 +				}
   1.672 +			}
   1.673 +#endif // no validation
   1.674 +
   1.675 +			// Preprocess the scene and prepare it for post-processing 
   1.676 +			if (profiler) {
   1.677 +				profiler->BeginRegion("preprocess");
   1.678 +			}
   1.679 +
   1.680 +			ScenePreprocessor pre(pimpl->mScene);
   1.681 +			pre.ProcessScene();
   1.682 +
   1.683 +			pimpl->mProgressHandler->Update();
   1.684 +			if (profiler) {
   1.685 +				profiler->EndRegion("preprocess");
   1.686 +			}
   1.687 +
   1.688 +			// Ensure that the validation process won't be called twice
   1.689 +			ApplyPostProcessing(pFlags & (~aiProcess_ValidateDataStructure));
   1.690 +		}
   1.691 +		// if failed, extract the error string
   1.692 +		else if( !pimpl->mScene) {
   1.693 +			pimpl->mErrorString = imp->GetErrorText();
   1.694 +		}
   1.695 +
   1.696 +		// clear any data allocated by post-process steps
   1.697 +		pimpl->mPPShared->Clean();
   1.698 +
   1.699 +		if (profiler) {
   1.700 +			profiler->EndRegion("total");
   1.701 +		}
   1.702 +	}
   1.703 +#ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
   1.704 +	catch (std::exception &e)
   1.705 +	{
   1.706 +#if (defined _MSC_VER) &&	(defined _CPPRTTI) 
   1.707 +		// if we have RTTI get the full name of the exception that occured
   1.708 +		pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what();
   1.709 +#else
   1.710 +		pimpl->mErrorString = std::string("std::exception: ") + e.what();
   1.711 +#endif
   1.712 +
   1.713 +		DefaultLogger::get()->error(pimpl->mErrorString);
   1.714 +		delete pimpl->mScene; pimpl->mScene = NULL;
   1.715 +	}
   1.716 +#endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
   1.717 +
   1.718 +	// either successful or failure - the pointer expresses it anyways
   1.719 +	ASSIMP_END_EXCEPTION_REGION(const aiScene*);
   1.720 +	return pimpl->mScene;
   1.721 +}
   1.722 +
   1.723 +
   1.724 +// ------------------------------------------------------------------------------------------------
   1.725 +// Apply post-processing to the currently bound scene
   1.726 +const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
   1.727 +{
   1.728 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.729 +	// Return immediately if no scene is active
   1.730 +	if (!pimpl->mScene) {
   1.731 +		return NULL;
   1.732 +	}
   1.733 +
   1.734 +	// If no flags are given, return the current scene with no further action
   1.735 +	if (!pFlags) {
   1.736 +		return pimpl->mScene;
   1.737 +	}
   1.738 +
   1.739 +	// In debug builds: run basic flag validation
   1.740 +	ai_assert(_ValidateFlags(pFlags));
   1.741 +	DefaultLogger::get()->info("Entering post processing pipeline");
   1.742 +
   1.743 +#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
   1.744 +	// The ValidateDS process plays an exceptional role. It isn't contained in the global
   1.745 +	// list of post-processing steps, so we need to call it manually.
   1.746 +	if (pFlags & aiProcess_ValidateDataStructure)
   1.747 +	{
   1.748 +		ValidateDSProcess ds;
   1.749 +		ds.ExecuteOnScene (this);
   1.750 +		if (!pimpl->mScene) {
   1.751 +			return NULL;
   1.752 +		}
   1.753 +	}
   1.754 +#endif // no validation
   1.755 +#ifdef _DEBUG
   1.756 +	if (pimpl->bExtraVerbose)
   1.757 +	{
   1.758 +#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
   1.759 +		DefaultLogger::get()->error("Verbose Import is not available due to build settings");
   1.760 +#endif  // no validation
   1.761 +		pFlags |= aiProcess_ValidateDataStructure;
   1.762 +	}
   1.763 +#else
   1.764 +	if (pimpl->bExtraVerbose) {
   1.765 +		DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting");
   1.766 +	}
   1.767 +#endif // ! DEBUG
   1.768 +
   1.769 +	boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
   1.770 +	for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)	{
   1.771 +
   1.772 +		BaseProcess* process = pimpl->mPostProcessingSteps[a];
   1.773 +		if( process->IsActive( pFlags))	{
   1.774 +
   1.775 +			if (profiler) {
   1.776 +				profiler->BeginRegion("postprocess");
   1.777 +			}
   1.778 +
   1.779 +			process->ExecuteOnScene	( this );
   1.780 +			pimpl->mProgressHandler->Update();
   1.781 +
   1.782 +			if (profiler) {
   1.783 +				profiler->EndRegion("postprocess");
   1.784 +			}
   1.785 +		}
   1.786 +		if( !pimpl->mScene) {
   1.787 +			break; 
   1.788 +		}
   1.789 +#ifdef _DEBUG
   1.790 +
   1.791 +#ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
   1.792 +		continue;
   1.793 +#endif  // no validation
   1.794 +
   1.795 +		// If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
   1.796 +		if (pimpl->bExtraVerbose)	{
   1.797 +			DefaultLogger::get()->debug("Verbose Import: revalidating data structures");
   1.798 +
   1.799 +			ValidateDSProcess ds; 
   1.800 +			ds.ExecuteOnScene (this);
   1.801 +			if( !pimpl->mScene)	{
   1.802 +				DefaultLogger::get()->error("Verbose Import: failed to revalidate data structures");
   1.803 +				break; 
   1.804 +			}
   1.805 +		}
   1.806 +#endif // ! DEBUG
   1.807 +	}
   1.808 +
   1.809 +	// update private scene flags
   1.810 +  if( pimpl->mScene )
   1.811 +  	ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
   1.812 +
   1.813 +	// clear any data allocated by post-process steps
   1.814 +	pimpl->mPPShared->Clean();
   1.815 +	DefaultLogger::get()->info("Leaving post processing pipeline");
   1.816 +
   1.817 +	ASSIMP_END_EXCEPTION_REGION(const aiScene*);
   1.818 +	return pimpl->mScene;
   1.819 +}
   1.820 +
   1.821 +// ------------------------------------------------------------------------------------------------
   1.822 +// Helper function to check whether an extension is supported by ASSIMP
   1.823 +bool Importer::IsExtensionSupported(const char* szExtension) const
   1.824 +{
   1.825 +	return NULL != GetImporter(szExtension);
   1.826 +}
   1.827 +
   1.828 +// ------------------------------------------------------------------------------------------------
   1.829 +size_t Importer::GetImporterCount() const
   1.830 +{
   1.831 +	return pimpl->mImporter.size();
   1.832 +}
   1.833 +
   1.834 +// ------------------------------------------------------------------------------------------------
   1.835 +const aiImporterDesc* Importer::GetImporterInfo(size_t index) const
   1.836 +{
   1.837 +	if (index >= pimpl->mImporter.size()) {
   1.838 +		return NULL;
   1.839 +	}
   1.840 +	return pimpl->mImporter[index]->GetInfo();
   1.841 +}
   1.842 +
   1.843 +
   1.844 +// ------------------------------------------------------------------------------------------------
   1.845 +BaseImporter* Importer::GetImporter (size_t index) const
   1.846 +{
   1.847 +	if (index >= pimpl->mImporter.size()) {
   1.848 +		return NULL;
   1.849 +	}
   1.850 +	return pimpl->mImporter[index];
   1.851 +}
   1.852 +
   1.853 +// ------------------------------------------------------------------------------------------------
   1.854 +// Find a loader plugin for a given file extension
   1.855 +BaseImporter* Importer::GetImporter (const char* szExtension) const
   1.856 +{
   1.857 +	return GetImporter(GetImporterIndex(szExtension));
   1.858 +}
   1.859 +
   1.860 +// ------------------------------------------------------------------------------------------------
   1.861 +// Find a loader plugin for a given file extension
   1.862 +size_t Importer::GetImporterIndex (const char* szExtension) const
   1.863 +{
   1.864 +	ai_assert(szExtension);
   1.865 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.866 +
   1.867 +	// skip over wildcard and dot characters at string head --
   1.868 +	for(;*szExtension == '*' || *szExtension == '.'; ++szExtension);
   1.869 +
   1.870 +	std::string ext(szExtension);
   1.871 +	if (ext.empty()) {
   1.872 +		return static_cast<size_t>(-1);
   1.873 +	}
   1.874 +	std::transform(ext.begin(),ext.end(), ext.begin(), tolower);
   1.875 +
   1.876 +	std::set<std::string> str;
   1.877 +	for (std::vector<BaseImporter*>::const_iterator i =  pimpl->mImporter.begin();i != pimpl->mImporter.end();++i)	{
   1.878 +		str.clear();
   1.879 +
   1.880 +		(*i)->GetExtensionList(str);
   1.881 +		for (std::set<std::string>::const_iterator it = str.begin(); it != str.end(); ++it) {
   1.882 +			if (ext == *it) {
   1.883 +				return std::distance(static_cast< std::vector<BaseImporter*>::const_iterator >(pimpl->mImporter.begin()), i);
   1.884 +			}
   1.885 +		}
   1.886 +	}
   1.887 +	ASSIMP_END_EXCEPTION_REGION(size_t);
   1.888 +	return static_cast<size_t>(-1);
   1.889 +}
   1.890 +
   1.891 +// ------------------------------------------------------------------------------------------------
   1.892 +// Helper function to build a list of all file extensions supported by ASSIMP
   1.893 +void Importer::GetExtensionList(aiString& szOut) const
   1.894 +{
   1.895 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.896 +	std::set<std::string> str;
   1.897 +	for (std::vector<BaseImporter*>::const_iterator i =  pimpl->mImporter.begin();i != pimpl->mImporter.end();++i)	{
   1.898 +		(*i)->GetExtensionList(str);
   1.899 +	}
   1.900 +
   1.901 +	for (std::set<std::string>::const_iterator it = str.begin();; ) {
   1.902 +		szOut.Append("*.");
   1.903 +		szOut.Append((*it).c_str());
   1.904 +
   1.905 +		if (++it == str.end()) {
   1.906 +			break;
   1.907 +		}
   1.908 +		szOut.Append(";");
   1.909 +	}
   1.910 +	ASSIMP_END_EXCEPTION_REGION(void);
   1.911 +}
   1.912 +
   1.913 +// ------------------------------------------------------------------------------------------------
   1.914 +// Set a configuration property
   1.915 +void Importer::SetPropertyInteger(const char* szName, int iValue, 
   1.916 +	bool* bWasExisting /*= NULL*/)
   1.917 +{
   1.918 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.919 +		SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue,bWasExisting);	
   1.920 +	ASSIMP_END_EXCEPTION_REGION(void);
   1.921 +}
   1.922 +
   1.923 +// ------------------------------------------------------------------------------------------------
   1.924 +// Set a configuration property
   1.925 +void Importer::SetPropertyFloat(const char* szName, float iValue, 
   1.926 +	bool* bWasExisting /*= NULL*/)
   1.927 +{
   1.928 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.929 +		SetGenericProperty<float>(pimpl->mFloatProperties, szName,iValue,bWasExisting);	
   1.930 +	ASSIMP_END_EXCEPTION_REGION(void);
   1.931 +}
   1.932 +
   1.933 +// ------------------------------------------------------------------------------------------------
   1.934 +// Set a configuration property
   1.935 +void Importer::SetPropertyString(const char* szName, const std::string& value, 
   1.936 +	bool* bWasExisting /*= NULL*/)
   1.937 +{
   1.938 +	ASSIMP_BEGIN_EXCEPTION_REGION();
   1.939 +		SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value,bWasExisting);	
   1.940 +	ASSIMP_END_EXCEPTION_REGION(void);
   1.941 +}
   1.942 +
   1.943 +// ------------------------------------------------------------------------------------------------
   1.944 +// Get a configuration property
   1.945 +int Importer::GetPropertyInteger(const char* szName, 
   1.946 +	int iErrorReturn /*= 0xffffffff*/) const
   1.947 +{
   1.948 +	return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn);
   1.949 +}
   1.950 +
   1.951 +// ------------------------------------------------------------------------------------------------
   1.952 +// Get a configuration property
   1.953 +float Importer::GetPropertyFloat(const char* szName, 
   1.954 +	float iErrorReturn /*= 10e10*/) const
   1.955 +{
   1.956 +	return GetGenericProperty<float>(pimpl->mFloatProperties,szName,iErrorReturn);
   1.957 +}
   1.958 +
   1.959 +// ------------------------------------------------------------------------------------------------
   1.960 +// Get a configuration property
   1.961 +const std::string& Importer::GetPropertyString(const char* szName, 
   1.962 +	const std::string& iErrorReturn /*= ""*/) const
   1.963 +{
   1.964 +	return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
   1.965 +}
   1.966 +
   1.967 +// ------------------------------------------------------------------------------------------------
   1.968 +// Get the memory requirements of a single node
   1.969 +inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode)
   1.970 +{
   1.971 +	iScene += sizeof(aiNode);
   1.972 +	iScene += sizeof(unsigned int) * pcNode->mNumMeshes;
   1.973 +	iScene += sizeof(void*) * pcNode->mNumChildren;
   1.974 +	
   1.975 +	for (unsigned int i = 0; i < pcNode->mNumChildren;++i) {
   1.976 +		AddNodeWeight(iScene,pcNode->mChildren[i]);
   1.977 +	}
   1.978 +}
   1.979 +
   1.980 +// ------------------------------------------------------------------------------------------------
   1.981 +// Get the memory requirements of the scene
   1.982 +void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
   1.983 +{
   1.984 +	in = aiMemoryInfo();
   1.985 +	aiScene* mScene = pimpl->mScene;
   1.986 +
   1.987 +	// return if we have no scene loaded
   1.988 +	if (!pimpl->mScene)
   1.989 +		return;
   1.990 +
   1.991 +
   1.992 +	in.total = sizeof(aiScene);
   1.993 +
   1.994 +	// add all meshes
   1.995 +	for (unsigned int i = 0; i < mScene->mNumMeshes;++i)
   1.996 +	{
   1.997 +		in.meshes += sizeof(aiMesh);
   1.998 +		if (mScene->mMeshes[i]->HasPositions()) {
   1.999 +			in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
  1.1000 +		}
  1.1001 +
  1.1002 +		if (mScene->mMeshes[i]->HasNormals()) {
  1.1003 +			in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
  1.1004 +		}
  1.1005 +
  1.1006 +		if (mScene->mMeshes[i]->HasTangentsAndBitangents()) {
  1.1007 +			in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices * 2;
  1.1008 +		}
  1.1009 +
  1.1010 +		for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) {
  1.1011 +			if (mScene->mMeshes[i]->HasVertexColors(a)) {
  1.1012 +				in.meshes += sizeof(aiColor4D) * mScene->mMeshes[i]->mNumVertices;
  1.1013 +			}
  1.1014 +			else break;
  1.1015 +		}
  1.1016 +		for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
  1.1017 +			if (mScene->mMeshes[i]->HasTextureCoords(a)) {
  1.1018 +				in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
  1.1019 +			}
  1.1020 +			else break;
  1.1021 +		}
  1.1022 +		if (mScene->mMeshes[i]->HasBones()) {
  1.1023 +			in.meshes += sizeof(void*) * mScene->mMeshes[i]->mNumBones;
  1.1024 +			for (unsigned int p = 0; p < mScene->mMeshes[i]->mNumBones;++p) {
  1.1025 +				in.meshes += sizeof(aiBone);
  1.1026 +				in.meshes += mScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight);
  1.1027 +			}
  1.1028 +		}
  1.1029 +		in.meshes += (sizeof(aiFace) + 3 * sizeof(unsigned int))*mScene->mMeshes[i]->mNumFaces;
  1.1030 +	}
  1.1031 +    in.total += in.meshes;
  1.1032 +
  1.1033 +	// add all embedded textures
  1.1034 +	for (unsigned int i = 0; i < mScene->mNumTextures;++i) {
  1.1035 +		const aiTexture* pc = mScene->mTextures[i];
  1.1036 +		in.textures += sizeof(aiTexture);
  1.1037 +		if (pc->mHeight) {
  1.1038 +			in.textures += 4 * pc->mHeight * pc->mWidth;
  1.1039 +		}
  1.1040 +		else in.textures += pc->mWidth;
  1.1041 +	}
  1.1042 +	in.total += in.textures;
  1.1043 +
  1.1044 +	// add all animations
  1.1045 +	for (unsigned int i = 0; i < mScene->mNumAnimations;++i) {
  1.1046 +		const aiAnimation* pc = mScene->mAnimations[i];
  1.1047 +		in.animations += sizeof(aiAnimation);
  1.1048 +
  1.1049 +		// add all bone anims
  1.1050 +		for (unsigned int a = 0; a < pc->mNumChannels; ++a) {
  1.1051 +			const aiNodeAnim* pc2 = pc->mChannels[i];
  1.1052 +			in.animations += sizeof(aiNodeAnim);
  1.1053 +			in.animations += pc2->mNumPositionKeys * sizeof(aiVectorKey);
  1.1054 +			in.animations += pc2->mNumScalingKeys * sizeof(aiVectorKey);
  1.1055 +			in.animations += pc2->mNumRotationKeys * sizeof(aiQuatKey);
  1.1056 +		}
  1.1057 +	}
  1.1058 +	in.total += in.animations;
  1.1059 +
  1.1060 +	// add all cameras and all lights
  1.1061 +	in.total += in.cameras = sizeof(aiCamera) *  mScene->mNumCameras;
  1.1062 +	in.total += in.lights  = sizeof(aiLight)  *  mScene->mNumLights;
  1.1063 +
  1.1064 +	// add all nodes
  1.1065 +	AddNodeWeight(in.nodes,mScene->mRootNode);
  1.1066 +	in.total += in.nodes;
  1.1067 +
  1.1068 +	// add all materials
  1.1069 +	for (unsigned int i = 0; i < mScene->mNumMaterials;++i) {
  1.1070 +		const aiMaterial* pc = mScene->mMaterials[i];
  1.1071 +		in.materials += sizeof(aiMaterial);
  1.1072 +		in.materials += pc->mNumAllocated * sizeof(void*);
  1.1073 +
  1.1074 +		for (unsigned int a = 0; a < pc->mNumProperties;++a) {
  1.1075 +			in.materials += pc->mProperties[a]->mDataLength;
  1.1076 +		}
  1.1077 +	}
  1.1078 +	in.total += in.materials;
  1.1079 +}
  1.1080 +