vrshoot

annotate 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
rev   line source
nuclear@0 1 /*
nuclear@0 2 ---------------------------------------------------------------------------
nuclear@0 3 Open Asset Import Library (assimp)
nuclear@0 4 ---------------------------------------------------------------------------
nuclear@0 5
nuclear@0 6 Copyright (c) 2006-2012, assimp team
nuclear@0 7
nuclear@0 8 All rights reserved.
nuclear@0 9
nuclear@0 10 Redistribution and use of this software in source and binary forms,
nuclear@0 11 with or without modification, are permitted provided that the following
nuclear@0 12 conditions are met:
nuclear@0 13
nuclear@0 14 * Redistributions of source code must retain the above
nuclear@0 15 copyright notice, this list of conditions and the
nuclear@0 16 following disclaimer.
nuclear@0 17
nuclear@0 18 * Redistributions in binary form must reproduce the above
nuclear@0 19 copyright notice, this list of conditions and the
nuclear@0 20 following disclaimer in the documentation and/or other
nuclear@0 21 materials provided with the distribution.
nuclear@0 22
nuclear@0 23 * Neither the name of the assimp team, nor the names of its
nuclear@0 24 contributors may be used to endorse or promote products
nuclear@0 25 derived from this software without specific prior
nuclear@0 26 written permission of the assimp team.
nuclear@0 27
nuclear@0 28 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
nuclear@0 29 "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
nuclear@0 30 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
nuclear@0 31 A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
nuclear@0 32 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
nuclear@0 33 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
nuclear@0 34 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
nuclear@0 35 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
nuclear@0 36 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
nuclear@0 37 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
nuclear@0 38 OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
nuclear@0 39 ---------------------------------------------------------------------------
nuclear@0 40 */
nuclear@0 41
nuclear@0 42 /** @file Importer.cpp
nuclear@0 43 * @brief Implementation of the CPP-API class #Importer
nuclear@0 44 */
nuclear@0 45
nuclear@0 46 #include "AssimpPCH.h"
nuclear@0 47 #include "assimp/version.h"
nuclear@0 48
nuclear@0 49 // ------------------------------------------------------------------------------------------------
nuclear@0 50 /* Uncomment this line to prevent Assimp from catching unknown exceptions.
nuclear@0 51 *
nuclear@0 52 * Note that any Exception except DeadlyImportError may lead to
nuclear@0 53 * undefined behaviour -> loaders could remain in an unusable state and
nuclear@0 54 * further imports with the same Importer instance could fail/crash/burn ...
nuclear@0 55 */
nuclear@0 56 // ------------------------------------------------------------------------------------------------
nuclear@0 57 #ifndef ASSIMP_BUILD_DEBUG
nuclear@0 58 # define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
nuclear@0 59 #endif
nuclear@0 60
nuclear@0 61 // ------------------------------------------------------------------------------------------------
nuclear@0 62 // Internal headers
nuclear@0 63 // ------------------------------------------------------------------------------------------------
nuclear@0 64 #include "Importer.h"
nuclear@0 65 #include "BaseProcess.h"
nuclear@0 66
nuclear@0 67 #include "DefaultIOStream.h"
nuclear@0 68 #include "DefaultIOSystem.h"
nuclear@0 69 #include "DefaultProgressHandler.h"
nuclear@0 70 #include "GenericProperty.h"
nuclear@0 71 #include "ProcessHelper.h"
nuclear@0 72 #include "ScenePreprocessor.h"
nuclear@0 73 #include "MemoryIOWrapper.h"
nuclear@0 74 #include "Profiler.h"
nuclear@0 75 #include "TinyFormatter.h"
nuclear@0 76
nuclear@0 77 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
nuclear@0 78 # include "ValidateDataStructure.h"
nuclear@0 79 #endif
nuclear@0 80
nuclear@0 81 using namespace Assimp::Profiling;
nuclear@0 82 using namespace Assimp::Formatter;
nuclear@0 83
nuclear@0 84 namespace Assimp {
nuclear@0 85 // ImporterRegistry.cpp
nuclear@0 86 void GetImporterInstanceList(std::vector< BaseImporter* >& out);
nuclear@0 87 // PostStepRegistry.cpp
nuclear@0 88 void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
nuclear@0 89 }
nuclear@0 90
nuclear@0 91 using namespace Assimp;
nuclear@0 92 using namespace Assimp::Intern;
nuclear@0 93
nuclear@0 94 // ------------------------------------------------------------------------------------------------
nuclear@0 95 // Intern::AllocateFromAssimpHeap serves as abstract base class. It overrides
nuclear@0 96 // new and delete (and their array counterparts) of public API classes (e.g. Logger) to
nuclear@0 97 // utilize our DLL heap.
nuclear@0 98 // See http://www.gotw.ca/publications/mill15.htm
nuclear@0 99 // ------------------------------------------------------------------------------------------------
nuclear@0 100 void* AllocateFromAssimpHeap::operator new ( size_t num_bytes) {
nuclear@0 101 return ::operator new(num_bytes);
nuclear@0 102 }
nuclear@0 103
nuclear@0 104 void* AllocateFromAssimpHeap::operator new ( size_t num_bytes, const std::nothrow_t& ) throw() {
nuclear@0 105 try {
nuclear@0 106 return AllocateFromAssimpHeap::operator new( num_bytes );
nuclear@0 107 }
nuclear@0 108 catch( ... ) {
nuclear@0 109 return NULL;
nuclear@0 110 }
nuclear@0 111 }
nuclear@0 112
nuclear@0 113 void AllocateFromAssimpHeap::operator delete ( void* data) {
nuclear@0 114 return ::operator delete(data);
nuclear@0 115 }
nuclear@0 116
nuclear@0 117 void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes) {
nuclear@0 118 return ::operator new[](num_bytes);
nuclear@0 119 }
nuclear@0 120
nuclear@0 121 void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw() {
nuclear@0 122 try {
nuclear@0 123 return AllocateFromAssimpHeap::operator new[]( num_bytes );
nuclear@0 124 }
nuclear@0 125 catch( ... ) {
nuclear@0 126 return NULL;
nuclear@0 127 }
nuclear@0 128 }
nuclear@0 129
nuclear@0 130 void AllocateFromAssimpHeap::operator delete[] ( void* data) {
nuclear@0 131 return ::operator delete[](data);
nuclear@0 132 }
nuclear@0 133
nuclear@0 134 // ------------------------------------------------------------------------------------------------
nuclear@0 135 // Importer constructor.
nuclear@0 136 Importer::Importer()
nuclear@0 137 {
nuclear@0 138 // allocate the pimpl first
nuclear@0 139 pimpl = new ImporterPimpl();
nuclear@0 140
nuclear@0 141 pimpl->mScene = NULL;
nuclear@0 142 pimpl->mErrorString = "";
nuclear@0 143
nuclear@0 144 // Allocate a default IO handler
nuclear@0 145 pimpl->mIOHandler = new DefaultIOSystem;
nuclear@0 146 pimpl->mIsDefaultHandler = true;
nuclear@0 147 pimpl->bExtraVerbose = false; // disable extra verbose mode by default
nuclear@0 148
nuclear@0 149 pimpl->mProgressHandler = new DefaultProgressHandler();
nuclear@0 150 pimpl->mIsDefaultProgressHandler = true;
nuclear@0 151
nuclear@0 152 GetImporterInstanceList(pimpl->mImporter);
nuclear@0 153 GetPostProcessingStepInstanceList(pimpl->mPostProcessingSteps);
nuclear@0 154
nuclear@0 155 // Allocate a SharedPostProcessInfo object and store pointers to it in all post-process steps in the list.
nuclear@0 156 pimpl->mPPShared = new SharedPostProcessInfo();
nuclear@0 157 for (std::vector<BaseProcess*>::iterator it = pimpl->mPostProcessingSteps.begin();
nuclear@0 158 it != pimpl->mPostProcessingSteps.end();
nuclear@0 159 ++it) {
nuclear@0 160
nuclear@0 161 (*it)->SetSharedData(pimpl->mPPShared);
nuclear@0 162 }
nuclear@0 163 }
nuclear@0 164
nuclear@0 165 // ------------------------------------------------------------------------------------------------
nuclear@0 166 // Destructor of Importer
nuclear@0 167 Importer::~Importer()
nuclear@0 168 {
nuclear@0 169 // Delete all import plugins
nuclear@0 170 for( unsigned int a = 0; a < pimpl->mImporter.size(); a++)
nuclear@0 171 delete pimpl->mImporter[a];
nuclear@0 172
nuclear@0 173 // Delete all post-processing plug-ins
nuclear@0 174 for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++)
nuclear@0 175 delete pimpl->mPostProcessingSteps[a];
nuclear@0 176
nuclear@0 177 // Delete the assigned IO and progress handler
nuclear@0 178 delete pimpl->mIOHandler;
nuclear@0 179 delete pimpl->mProgressHandler;
nuclear@0 180
nuclear@0 181 // Kill imported scene. Destructors should do that recursivly
nuclear@0 182 delete pimpl->mScene;
nuclear@0 183
nuclear@0 184 // Delete shared post-processing data
nuclear@0 185 delete pimpl->mPPShared;
nuclear@0 186
nuclear@0 187 // and finally the pimpl itself
nuclear@0 188 delete pimpl;
nuclear@0 189 }
nuclear@0 190
nuclear@0 191 // ------------------------------------------------------------------------------------------------
nuclear@0 192 // Copy constructor - copies the config of another Importer, not the scene
nuclear@0 193 Importer::Importer(const Importer &other)
nuclear@0 194 {
nuclear@0 195 new(this) Importer();
nuclear@0 196
nuclear@0 197 pimpl->mIntProperties = other.pimpl->mIntProperties;
nuclear@0 198 pimpl->mFloatProperties = other.pimpl->mFloatProperties;
nuclear@0 199 pimpl->mStringProperties = other.pimpl->mStringProperties;
nuclear@0 200 }
nuclear@0 201
nuclear@0 202 // ------------------------------------------------------------------------------------------------
nuclear@0 203 // Register a custom post-processing step
nuclear@0 204 aiReturn Importer::RegisterPPStep(BaseProcess* pImp)
nuclear@0 205 {
nuclear@0 206 ai_assert(NULL != pImp);
nuclear@0 207 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 208
nuclear@0 209 pimpl->mPostProcessingSteps.push_back(pImp);
nuclear@0 210 DefaultLogger::get()->info("Registering custom post-processing step");
nuclear@0 211
nuclear@0 212 ASSIMP_END_EXCEPTION_REGION(aiReturn);
nuclear@0 213 return AI_SUCCESS;
nuclear@0 214 }
nuclear@0 215
nuclear@0 216 // ------------------------------------------------------------------------------------------------
nuclear@0 217 // Register a custom loader plugin
nuclear@0 218 aiReturn Importer::RegisterLoader(BaseImporter* pImp)
nuclear@0 219 {
nuclear@0 220 ai_assert(NULL != pImp);
nuclear@0 221 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 222
nuclear@0 223 // --------------------------------------------------------------------
nuclear@0 224 // Check whether we would have two loaders for the same file extension
nuclear@0 225 // This is absolutely OK, but we should warn the developer of the new
nuclear@0 226 // loader that his code will probably never be called if the first
nuclear@0 227 // loader is a bit too lazy in his file checking.
nuclear@0 228 // --------------------------------------------------------------------
nuclear@0 229 std::set<std::string> st;
nuclear@0 230 std::string baked;
nuclear@0 231 pImp->GetExtensionList(st);
nuclear@0 232
nuclear@0 233 for(std::set<std::string>::const_iterator it = st.begin(); it != st.end(); ++it) {
nuclear@0 234
nuclear@0 235 #ifdef _DEBUG
nuclear@0 236 if (IsExtensionSupported(*it)) {
nuclear@0 237 DefaultLogger::get()->warn("The file extension " + *it + " is already in use");
nuclear@0 238 }
nuclear@0 239 #endif
nuclear@0 240 baked += *it;
nuclear@0 241 }
nuclear@0 242
nuclear@0 243 // add the loader
nuclear@0 244 pimpl->mImporter.push_back(pImp);
nuclear@0 245 DefaultLogger::get()->info("Registering custom importer for these file extensions: " + baked);
nuclear@0 246 ASSIMP_END_EXCEPTION_REGION(aiReturn);
nuclear@0 247 return AI_SUCCESS;
nuclear@0 248 }
nuclear@0 249
nuclear@0 250 // ------------------------------------------------------------------------------------------------
nuclear@0 251 // Unregister a custom loader plugin
nuclear@0 252 aiReturn Importer::UnregisterLoader(BaseImporter* pImp)
nuclear@0 253 {
nuclear@0 254 if(!pImp) {
nuclear@0 255 // unregistering a NULL importer is no problem for us ... really!
nuclear@0 256 return AI_SUCCESS;
nuclear@0 257 }
nuclear@0 258
nuclear@0 259 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 260 std::vector<BaseImporter*>::iterator it = std::find(pimpl->mImporter.begin(),
nuclear@0 261 pimpl->mImporter.end(),pImp);
nuclear@0 262
nuclear@0 263 if (it != pimpl->mImporter.end()) {
nuclear@0 264 pimpl->mImporter.erase(it);
nuclear@0 265
nuclear@0 266 std::set<std::string> st;
nuclear@0 267 pImp->GetExtensionList(st);
nuclear@0 268
nuclear@0 269 DefaultLogger::get()->info("Unregistering custom importer: ");
nuclear@0 270 return AI_SUCCESS;
nuclear@0 271 }
nuclear@0 272 DefaultLogger::get()->warn("Unable to remove custom importer: I can't find you ...");
nuclear@0 273 ASSIMP_END_EXCEPTION_REGION(aiReturn);
nuclear@0 274 return AI_FAILURE;
nuclear@0 275 }
nuclear@0 276
nuclear@0 277 // ------------------------------------------------------------------------------------------------
nuclear@0 278 // Unregister a custom loader plugin
nuclear@0 279 aiReturn Importer::UnregisterPPStep(BaseProcess* pImp)
nuclear@0 280 {
nuclear@0 281 if(!pImp) {
nuclear@0 282 // unregistering a NULL ppstep is no problem for us ... really!
nuclear@0 283 return AI_SUCCESS;
nuclear@0 284 }
nuclear@0 285
nuclear@0 286 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 287 std::vector<BaseProcess*>::iterator it = std::find(pimpl->mPostProcessingSteps.begin(),
nuclear@0 288 pimpl->mPostProcessingSteps.end(),pImp);
nuclear@0 289
nuclear@0 290 if (it != pimpl->mPostProcessingSteps.end()) {
nuclear@0 291 pimpl->mPostProcessingSteps.erase(it);
nuclear@0 292 DefaultLogger::get()->info("Unregistering custom post-processing step");
nuclear@0 293 return AI_SUCCESS;
nuclear@0 294 }
nuclear@0 295 DefaultLogger::get()->warn("Unable to remove custom post-processing step: I can't find you ..");
nuclear@0 296 ASSIMP_END_EXCEPTION_REGION(aiReturn);
nuclear@0 297 return AI_FAILURE;
nuclear@0 298 }
nuclear@0 299
nuclear@0 300 // ------------------------------------------------------------------------------------------------
nuclear@0 301 // Supplies a custom IO handler to the importer to open and access files.
nuclear@0 302 void Importer::SetIOHandler( IOSystem* pIOHandler)
nuclear@0 303 {
nuclear@0 304 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 305 // If the new handler is zero, allocate a default IO implementation.
nuclear@0 306 if (!pIOHandler)
nuclear@0 307 {
nuclear@0 308 // Release pointer in the possession of the caller
nuclear@0 309 pimpl->mIOHandler = new DefaultIOSystem();
nuclear@0 310 pimpl->mIsDefaultHandler = true;
nuclear@0 311 }
nuclear@0 312 // Otherwise register the custom handler
nuclear@0 313 else if (pimpl->mIOHandler != pIOHandler)
nuclear@0 314 {
nuclear@0 315 delete pimpl->mIOHandler;
nuclear@0 316 pimpl->mIOHandler = pIOHandler;
nuclear@0 317 pimpl->mIsDefaultHandler = false;
nuclear@0 318 }
nuclear@0 319 ASSIMP_END_EXCEPTION_REGION(void);
nuclear@0 320 }
nuclear@0 321
nuclear@0 322 // ------------------------------------------------------------------------------------------------
nuclear@0 323 // Get the currently set IO handler
nuclear@0 324 IOSystem* Importer::GetIOHandler() const
nuclear@0 325 {
nuclear@0 326 return pimpl->mIOHandler;
nuclear@0 327 }
nuclear@0 328
nuclear@0 329 // ------------------------------------------------------------------------------------------------
nuclear@0 330 // Check whether a custom IO handler is currently set
nuclear@0 331 bool Importer::IsDefaultIOHandler() const
nuclear@0 332 {
nuclear@0 333 return pimpl->mIsDefaultHandler;
nuclear@0 334 }
nuclear@0 335
nuclear@0 336 // ------------------------------------------------------------------------------------------------
nuclear@0 337 // Supplies a custom progress handler to get regular callbacks during importing
nuclear@0 338 void Importer::SetProgressHandler ( ProgressHandler* pHandler )
nuclear@0 339 {
nuclear@0 340 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 341 // If the new handler is zero, allocate a default implementation.
nuclear@0 342 if (!pHandler)
nuclear@0 343 {
nuclear@0 344 // Release pointer in the possession of the caller
nuclear@0 345 pimpl->mProgressHandler = new DefaultProgressHandler();
nuclear@0 346 pimpl->mIsDefaultProgressHandler = true;
nuclear@0 347 }
nuclear@0 348 // Otherwise register the custom handler
nuclear@0 349 else if (pimpl->mProgressHandler != pHandler)
nuclear@0 350 {
nuclear@0 351 delete pimpl->mProgressHandler;
nuclear@0 352 pimpl->mProgressHandler = pHandler;
nuclear@0 353 pimpl->mIsDefaultProgressHandler = false;
nuclear@0 354 }
nuclear@0 355 ASSIMP_END_EXCEPTION_REGION(void);
nuclear@0 356 }
nuclear@0 357
nuclear@0 358 // ------------------------------------------------------------------------------------------------
nuclear@0 359 // Get the currently set progress handler
nuclear@0 360 ProgressHandler* Importer::GetProgressHandler() const
nuclear@0 361 {
nuclear@0 362 return pimpl->mProgressHandler;
nuclear@0 363 }
nuclear@0 364
nuclear@0 365 // ------------------------------------------------------------------------------------------------
nuclear@0 366 // Check whether a custom progress handler is currently set
nuclear@0 367 bool Importer::IsDefaultProgressHandler() const
nuclear@0 368 {
nuclear@0 369 return pimpl->mIsDefaultProgressHandler;
nuclear@0 370 }
nuclear@0 371
nuclear@0 372 // ------------------------------------------------------------------------------------------------
nuclear@0 373 // Validate post process step flags
nuclear@0 374 bool _ValidateFlags(unsigned int pFlags)
nuclear@0 375 {
nuclear@0 376 if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) {
nuclear@0 377 DefaultLogger::get()->error("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
nuclear@0 378 return false;
nuclear@0 379 }
nuclear@0 380 if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices) {
nuclear@0 381 DefaultLogger::get()->error("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
nuclear@0 382 return false;
nuclear@0 383 }
nuclear@0 384 return true;
nuclear@0 385 }
nuclear@0 386
nuclear@0 387 // ------------------------------------------------------------------------------------------------
nuclear@0 388 // Free the current scene
nuclear@0 389 void Importer::FreeScene( )
nuclear@0 390 {
nuclear@0 391 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 392 delete pimpl->mScene;
nuclear@0 393 pimpl->mScene = NULL;
nuclear@0 394
nuclear@0 395 pimpl->mErrorString = "";
nuclear@0 396 ASSIMP_END_EXCEPTION_REGION(void);
nuclear@0 397 }
nuclear@0 398
nuclear@0 399 // ------------------------------------------------------------------------------------------------
nuclear@0 400 // Get the current error string, if any
nuclear@0 401 const char* Importer::GetErrorString() const
nuclear@0 402 {
nuclear@0 403 /* Must remain valid as long as ReadFile() or FreeFile() are not called */
nuclear@0 404 return pimpl->mErrorString.c_str();
nuclear@0 405 }
nuclear@0 406
nuclear@0 407 // ------------------------------------------------------------------------------------------------
nuclear@0 408 // Enable extra-verbose mode
nuclear@0 409 void Importer::SetExtraVerbose(bool bDo)
nuclear@0 410 {
nuclear@0 411 pimpl->bExtraVerbose = bDo;
nuclear@0 412 }
nuclear@0 413
nuclear@0 414 // ------------------------------------------------------------------------------------------------
nuclear@0 415 // Get the current scene
nuclear@0 416 const aiScene* Importer::GetScene() const
nuclear@0 417 {
nuclear@0 418 return pimpl->mScene;
nuclear@0 419 }
nuclear@0 420
nuclear@0 421 // ------------------------------------------------------------------------------------------------
nuclear@0 422 // Orphan the current scene and return it.
nuclear@0 423 aiScene* Importer::GetOrphanedScene()
nuclear@0 424 {
nuclear@0 425 aiScene* s = pimpl->mScene;
nuclear@0 426
nuclear@0 427 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 428 pimpl->mScene = NULL;
nuclear@0 429
nuclear@0 430 pimpl->mErrorString = ""; /* reset error string */
nuclear@0 431 ASSIMP_END_EXCEPTION_REGION(aiScene*);
nuclear@0 432 return s;
nuclear@0 433 }
nuclear@0 434
nuclear@0 435 // ------------------------------------------------------------------------------------------------
nuclear@0 436 // Validate post-processing flags
nuclear@0 437 bool Importer::ValidateFlags(unsigned int pFlags) const
nuclear@0 438 {
nuclear@0 439 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 440 // run basic checks for mutually exclusive flags
nuclear@0 441 if(!_ValidateFlags(pFlags)) {
nuclear@0 442 return false;
nuclear@0 443 }
nuclear@0 444
nuclear@0 445 // ValidateDS does not anymore occur in the pp list, it plays an awesome extra role ...
nuclear@0 446 #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
nuclear@0 447 if (pFlags & aiProcess_ValidateDataStructure) {
nuclear@0 448 return false;
nuclear@0 449 }
nuclear@0 450 #endif
nuclear@0 451 pFlags &= ~aiProcess_ValidateDataStructure;
nuclear@0 452
nuclear@0 453 // Now iterate through all bits which are set in the flags and check whether we find at least
nuclear@0 454 // one pp plugin which handles it.
nuclear@0 455 for (unsigned int mask = 1; mask < (1u << (sizeof(unsigned int)*8-1));mask <<= 1) {
nuclear@0 456
nuclear@0 457 if (pFlags & mask) {
nuclear@0 458
nuclear@0 459 bool have = false;
nuclear@0 460 for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
nuclear@0 461 if (pimpl->mPostProcessingSteps[a]-> IsActive(mask) ) {
nuclear@0 462
nuclear@0 463 have = true;
nuclear@0 464 break;
nuclear@0 465 }
nuclear@0 466 }
nuclear@0 467 if (!have) {
nuclear@0 468 return false;
nuclear@0 469 }
nuclear@0 470 }
nuclear@0 471 }
nuclear@0 472 ASSIMP_END_EXCEPTION_REGION(bool);
nuclear@0 473 return true;
nuclear@0 474 }
nuclear@0 475
nuclear@0 476 // ------------------------------------------------------------------------------------------------
nuclear@0 477 const aiScene* Importer::ReadFileFromMemory( const void* pBuffer,
nuclear@0 478 size_t pLength,
nuclear@0 479 unsigned int pFlags,
nuclear@0 480 const char* pHint /*= ""*/)
nuclear@0 481 {
nuclear@0 482 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 483 if (!pHint) {
nuclear@0 484 pHint = "";
nuclear@0 485 }
nuclear@0 486
nuclear@0 487 if (!pBuffer || !pLength || strlen(pHint) > 100) {
nuclear@0 488 pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()";
nuclear@0 489 return NULL;
nuclear@0 490 }
nuclear@0 491
nuclear@0 492 // prevent deletion of the previous IOHandler
nuclear@0 493 IOSystem* io = pimpl->mIOHandler;
nuclear@0 494 pimpl->mIOHandler = NULL;
nuclear@0 495
nuclear@0 496 SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength));
nuclear@0 497
nuclear@0 498 // read the file and recover the previous IOSystem
nuclear@0 499 char fbuff[128];
nuclear@0 500 sprintf(fbuff,"%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
nuclear@0 501
nuclear@0 502 ReadFile(fbuff,pFlags);
nuclear@0 503 SetIOHandler(io);
nuclear@0 504
nuclear@0 505 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
nuclear@0 506 return pimpl->mScene;
nuclear@0 507 }
nuclear@0 508
nuclear@0 509 // ------------------------------------------------------------------------------------------------
nuclear@0 510 void WriteLogOpening(const std::string& file)
nuclear@0 511 {
nuclear@0 512 Logger* l = DefaultLogger::get();
nuclear@0 513 if (!l) {
nuclear@0 514 return;
nuclear@0 515 }
nuclear@0 516 l->info("Load " + file);
nuclear@0 517
nuclear@0 518 // print a full version dump. This is nice because we don't
nuclear@0 519 // need to ask the authors of incoming bug reports for
nuclear@0 520 // the library version they're using - a log dump is
nuclear@0 521 // sufficient.
nuclear@0 522 const unsigned int flags = aiGetCompileFlags();
nuclear@0 523 l->debug(format()
nuclear@0 524 << "Assimp "
nuclear@0 525 << aiGetVersionMajor()
nuclear@0 526 << "."
nuclear@0 527 << aiGetVersionMinor()
nuclear@0 528 << "."
nuclear@0 529 << aiGetVersionRevision()
nuclear@0 530
nuclear@0 531 << " "
nuclear@0 532 #if defined(ASSIMP_BUILD_ARCHITECTURE)
nuclear@0 533 << ASSIMP_BUILD_ARCHITECTURE
nuclear@0 534 #elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__)
nuclear@0 535 << "x86"
nuclear@0 536 #elif defined(_M_X64) || defined(__x86_64__)
nuclear@0 537 << "amd64"
nuclear@0 538 #elif defined(_M_IA64) || defined(__ia64__)
nuclear@0 539 << "itanium"
nuclear@0 540 #elif defined(__ppc__) || defined(__powerpc__)
nuclear@0 541 << "ppc32"
nuclear@0 542 #elif defined(__powerpc64__)
nuclear@0 543 << "ppc64"
nuclear@0 544 #elif defined(__arm__)
nuclear@0 545 << "arm"
nuclear@0 546 #else
nuclear@0 547 << "<unknown architecture>"
nuclear@0 548 #endif
nuclear@0 549
nuclear@0 550 << " "
nuclear@0 551 #if defined(ASSIMP_BUILD_COMPILER)
nuclear@0 552 << ASSIMP_BUILD_COMPILER
nuclear@0 553 #elif defined(_MSC_VER)
nuclear@0 554 << "msvc"
nuclear@0 555 #elif defined(__GNUC__)
nuclear@0 556 << "gcc"
nuclear@0 557 #else
nuclear@0 558 << "<unknown compiler>"
nuclear@0 559 #endif
nuclear@0 560
nuclear@0 561 #ifndef NDEBUG
nuclear@0 562 << " debug"
nuclear@0 563 #endif
nuclear@0 564
nuclear@0 565 << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
nuclear@0 566 << (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "")
nuclear@0 567 << (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "")
nuclear@0 568 );
nuclear@0 569 }
nuclear@0 570
nuclear@0 571 // ------------------------------------------------------------------------------------------------
nuclear@0 572 // Reads the given file and returns its contents if successful.
nuclear@0 573 const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags)
nuclear@0 574 {
nuclear@0 575 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 576 const std::string pFile(_pFile);
nuclear@0 577
nuclear@0 578 // ----------------------------------------------------------------------
nuclear@0 579 // Put a large try block around everything to catch all std::exception's
nuclear@0 580 // that might be thrown by STL containers or by new().
nuclear@0 581 // ImportErrorException's are throw by ourselves and caught elsewhere.
nuclear@0 582 //-----------------------------------------------------------------------
nuclear@0 583
nuclear@0 584 WriteLogOpening(pFile);
nuclear@0 585
nuclear@0 586 #ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
nuclear@0 587 try
nuclear@0 588 #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
nuclear@0 589 {
nuclear@0 590 // Check whether this Importer instance has already loaded
nuclear@0 591 // a scene. In this case we need to delete the old one
nuclear@0 592 if (pimpl->mScene) {
nuclear@0 593
nuclear@0 594 DefaultLogger::get()->debug("(Deleting previous scene)");
nuclear@0 595 FreeScene();
nuclear@0 596 }
nuclear@0 597
nuclear@0 598 // First check if the file is accessable at all
nuclear@0 599 if( !pimpl->mIOHandler->Exists( pFile)) {
nuclear@0 600
nuclear@0 601 pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
nuclear@0 602 DefaultLogger::get()->error(pimpl->mErrorString);
nuclear@0 603 return NULL;
nuclear@0 604 }
nuclear@0 605
nuclear@0 606 boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
nuclear@0 607 if (profiler) {
nuclear@0 608 profiler->BeginRegion("total");
nuclear@0 609 }
nuclear@0 610
nuclear@0 611 // Find an worker class which can handle the file
nuclear@0 612 BaseImporter* imp = NULL;
nuclear@0 613 for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
nuclear@0 614
nuclear@0 615 if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
nuclear@0 616 imp = pimpl->mImporter[a];
nuclear@0 617 break;
nuclear@0 618 }
nuclear@0 619 }
nuclear@0 620
nuclear@0 621 if (!imp) {
nuclear@0 622 // not so bad yet ... try format auto detection.
nuclear@0 623 const std::string::size_type s = pFile.find_last_of('.');
nuclear@0 624 if (s != std::string::npos) {
nuclear@0 625 DefaultLogger::get()->info("File extension not known, trying signature-based detection");
nuclear@0 626 for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
nuclear@0 627
nuclear@0 628 if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
nuclear@0 629 imp = pimpl->mImporter[a];
nuclear@0 630 break;
nuclear@0 631 }
nuclear@0 632 }
nuclear@0 633 }
nuclear@0 634 // Put a proper error message if no suitable importer was found
nuclear@0 635 if( !imp) {
nuclear@0 636 pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
nuclear@0 637 DefaultLogger::get()->error(pimpl->mErrorString);
nuclear@0 638 return NULL;
nuclear@0 639 }
nuclear@0 640 }
nuclear@0 641
nuclear@0 642 // Dispatch the reading to the worker class for this format
nuclear@0 643 DefaultLogger::get()->info("Found a matching importer for this file format");
nuclear@0 644 pimpl->mProgressHandler->Update();
nuclear@0 645
nuclear@0 646 if (profiler) {
nuclear@0 647 profiler->BeginRegion("import");
nuclear@0 648 }
nuclear@0 649
nuclear@0 650 pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
nuclear@0 651 pimpl->mProgressHandler->Update();
nuclear@0 652
nuclear@0 653 if (profiler) {
nuclear@0 654 profiler->EndRegion("import");
nuclear@0 655 }
nuclear@0 656
nuclear@0 657 // If successful, apply all active post processing steps to the imported data
nuclear@0 658 if( pimpl->mScene) {
nuclear@0 659
nuclear@0 660 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
nuclear@0 661 // The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called.
nuclear@0 662 if (pFlags & aiProcess_ValidateDataStructure)
nuclear@0 663 {
nuclear@0 664 ValidateDSProcess ds;
nuclear@0 665 ds.ExecuteOnScene (this);
nuclear@0 666 if (!pimpl->mScene) {
nuclear@0 667 return NULL;
nuclear@0 668 }
nuclear@0 669 }
nuclear@0 670 #endif // no validation
nuclear@0 671
nuclear@0 672 // Preprocess the scene and prepare it for post-processing
nuclear@0 673 if (profiler) {
nuclear@0 674 profiler->BeginRegion("preprocess");
nuclear@0 675 }
nuclear@0 676
nuclear@0 677 ScenePreprocessor pre(pimpl->mScene);
nuclear@0 678 pre.ProcessScene();
nuclear@0 679
nuclear@0 680 pimpl->mProgressHandler->Update();
nuclear@0 681 if (profiler) {
nuclear@0 682 profiler->EndRegion("preprocess");
nuclear@0 683 }
nuclear@0 684
nuclear@0 685 // Ensure that the validation process won't be called twice
nuclear@0 686 ApplyPostProcessing(pFlags & (~aiProcess_ValidateDataStructure));
nuclear@0 687 }
nuclear@0 688 // if failed, extract the error string
nuclear@0 689 else if( !pimpl->mScene) {
nuclear@0 690 pimpl->mErrorString = imp->GetErrorText();
nuclear@0 691 }
nuclear@0 692
nuclear@0 693 // clear any data allocated by post-process steps
nuclear@0 694 pimpl->mPPShared->Clean();
nuclear@0 695
nuclear@0 696 if (profiler) {
nuclear@0 697 profiler->EndRegion("total");
nuclear@0 698 }
nuclear@0 699 }
nuclear@0 700 #ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
nuclear@0 701 catch (std::exception &e)
nuclear@0 702 {
nuclear@0 703 #if (defined _MSC_VER) && (defined _CPPRTTI)
nuclear@0 704 // if we have RTTI get the full name of the exception that occured
nuclear@0 705 pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what();
nuclear@0 706 #else
nuclear@0 707 pimpl->mErrorString = std::string("std::exception: ") + e.what();
nuclear@0 708 #endif
nuclear@0 709
nuclear@0 710 DefaultLogger::get()->error(pimpl->mErrorString);
nuclear@0 711 delete pimpl->mScene; pimpl->mScene = NULL;
nuclear@0 712 }
nuclear@0 713 #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
nuclear@0 714
nuclear@0 715 // either successful or failure - the pointer expresses it anyways
nuclear@0 716 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
nuclear@0 717 return pimpl->mScene;
nuclear@0 718 }
nuclear@0 719
nuclear@0 720
nuclear@0 721 // ------------------------------------------------------------------------------------------------
nuclear@0 722 // Apply post-processing to the currently bound scene
nuclear@0 723 const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags)
nuclear@0 724 {
nuclear@0 725 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 726 // Return immediately if no scene is active
nuclear@0 727 if (!pimpl->mScene) {
nuclear@0 728 return NULL;
nuclear@0 729 }
nuclear@0 730
nuclear@0 731 // If no flags are given, return the current scene with no further action
nuclear@0 732 if (!pFlags) {
nuclear@0 733 return pimpl->mScene;
nuclear@0 734 }
nuclear@0 735
nuclear@0 736 // In debug builds: run basic flag validation
nuclear@0 737 ai_assert(_ValidateFlags(pFlags));
nuclear@0 738 DefaultLogger::get()->info("Entering post processing pipeline");
nuclear@0 739
nuclear@0 740 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
nuclear@0 741 // The ValidateDS process plays an exceptional role. It isn't contained in the global
nuclear@0 742 // list of post-processing steps, so we need to call it manually.
nuclear@0 743 if (pFlags & aiProcess_ValidateDataStructure)
nuclear@0 744 {
nuclear@0 745 ValidateDSProcess ds;
nuclear@0 746 ds.ExecuteOnScene (this);
nuclear@0 747 if (!pimpl->mScene) {
nuclear@0 748 return NULL;
nuclear@0 749 }
nuclear@0 750 }
nuclear@0 751 #endif // no validation
nuclear@0 752 #ifdef _DEBUG
nuclear@0 753 if (pimpl->bExtraVerbose)
nuclear@0 754 {
nuclear@0 755 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
nuclear@0 756 DefaultLogger::get()->error("Verbose Import is not available due to build settings");
nuclear@0 757 #endif // no validation
nuclear@0 758 pFlags |= aiProcess_ValidateDataStructure;
nuclear@0 759 }
nuclear@0 760 #else
nuclear@0 761 if (pimpl->bExtraVerbose) {
nuclear@0 762 DefaultLogger::get()->warn("Not a debug build, ignoring extra verbose setting");
nuclear@0 763 }
nuclear@0 764 #endif // ! DEBUG
nuclear@0 765
nuclear@0 766 boost::scoped_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME,0)?new Profiler():NULL);
nuclear@0 767 for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
nuclear@0 768
nuclear@0 769 BaseProcess* process = pimpl->mPostProcessingSteps[a];
nuclear@0 770 if( process->IsActive( pFlags)) {
nuclear@0 771
nuclear@0 772 if (profiler) {
nuclear@0 773 profiler->BeginRegion("postprocess");
nuclear@0 774 }
nuclear@0 775
nuclear@0 776 process->ExecuteOnScene ( this );
nuclear@0 777 pimpl->mProgressHandler->Update();
nuclear@0 778
nuclear@0 779 if (profiler) {
nuclear@0 780 profiler->EndRegion("postprocess");
nuclear@0 781 }
nuclear@0 782 }
nuclear@0 783 if( !pimpl->mScene) {
nuclear@0 784 break;
nuclear@0 785 }
nuclear@0 786 #ifdef _DEBUG
nuclear@0 787
nuclear@0 788 #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
nuclear@0 789 continue;
nuclear@0 790 #endif // no validation
nuclear@0 791
nuclear@0 792 // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
nuclear@0 793 if (pimpl->bExtraVerbose) {
nuclear@0 794 DefaultLogger::get()->debug("Verbose Import: revalidating data structures");
nuclear@0 795
nuclear@0 796 ValidateDSProcess ds;
nuclear@0 797 ds.ExecuteOnScene (this);
nuclear@0 798 if( !pimpl->mScene) {
nuclear@0 799 DefaultLogger::get()->error("Verbose Import: failed to revalidate data structures");
nuclear@0 800 break;
nuclear@0 801 }
nuclear@0 802 }
nuclear@0 803 #endif // ! DEBUG
nuclear@0 804 }
nuclear@0 805
nuclear@0 806 // update private scene flags
nuclear@0 807 if( pimpl->mScene )
nuclear@0 808 ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
nuclear@0 809
nuclear@0 810 // clear any data allocated by post-process steps
nuclear@0 811 pimpl->mPPShared->Clean();
nuclear@0 812 DefaultLogger::get()->info("Leaving post processing pipeline");
nuclear@0 813
nuclear@0 814 ASSIMP_END_EXCEPTION_REGION(const aiScene*);
nuclear@0 815 return pimpl->mScene;
nuclear@0 816 }
nuclear@0 817
nuclear@0 818 // ------------------------------------------------------------------------------------------------
nuclear@0 819 // Helper function to check whether an extension is supported by ASSIMP
nuclear@0 820 bool Importer::IsExtensionSupported(const char* szExtension) const
nuclear@0 821 {
nuclear@0 822 return NULL != GetImporter(szExtension);
nuclear@0 823 }
nuclear@0 824
nuclear@0 825 // ------------------------------------------------------------------------------------------------
nuclear@0 826 size_t Importer::GetImporterCount() const
nuclear@0 827 {
nuclear@0 828 return pimpl->mImporter.size();
nuclear@0 829 }
nuclear@0 830
nuclear@0 831 // ------------------------------------------------------------------------------------------------
nuclear@0 832 const aiImporterDesc* Importer::GetImporterInfo(size_t index) const
nuclear@0 833 {
nuclear@0 834 if (index >= pimpl->mImporter.size()) {
nuclear@0 835 return NULL;
nuclear@0 836 }
nuclear@0 837 return pimpl->mImporter[index]->GetInfo();
nuclear@0 838 }
nuclear@0 839
nuclear@0 840
nuclear@0 841 // ------------------------------------------------------------------------------------------------
nuclear@0 842 BaseImporter* Importer::GetImporter (size_t index) const
nuclear@0 843 {
nuclear@0 844 if (index >= pimpl->mImporter.size()) {
nuclear@0 845 return NULL;
nuclear@0 846 }
nuclear@0 847 return pimpl->mImporter[index];
nuclear@0 848 }
nuclear@0 849
nuclear@0 850 // ------------------------------------------------------------------------------------------------
nuclear@0 851 // Find a loader plugin for a given file extension
nuclear@0 852 BaseImporter* Importer::GetImporter (const char* szExtension) const
nuclear@0 853 {
nuclear@0 854 return GetImporter(GetImporterIndex(szExtension));
nuclear@0 855 }
nuclear@0 856
nuclear@0 857 // ------------------------------------------------------------------------------------------------
nuclear@0 858 // Find a loader plugin for a given file extension
nuclear@0 859 size_t Importer::GetImporterIndex (const char* szExtension) const
nuclear@0 860 {
nuclear@0 861 ai_assert(szExtension);
nuclear@0 862 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 863
nuclear@0 864 // skip over wildcard and dot characters at string head --
nuclear@0 865 for(;*szExtension == '*' || *szExtension == '.'; ++szExtension);
nuclear@0 866
nuclear@0 867 std::string ext(szExtension);
nuclear@0 868 if (ext.empty()) {
nuclear@0 869 return static_cast<size_t>(-1);
nuclear@0 870 }
nuclear@0 871 std::transform(ext.begin(),ext.end(), ext.begin(), tolower);
nuclear@0 872
nuclear@0 873 std::set<std::string> str;
nuclear@0 874 for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
nuclear@0 875 str.clear();
nuclear@0 876
nuclear@0 877 (*i)->GetExtensionList(str);
nuclear@0 878 for (std::set<std::string>::const_iterator it = str.begin(); it != str.end(); ++it) {
nuclear@0 879 if (ext == *it) {
nuclear@0 880 return std::distance(static_cast< std::vector<BaseImporter*>::const_iterator >(pimpl->mImporter.begin()), i);
nuclear@0 881 }
nuclear@0 882 }
nuclear@0 883 }
nuclear@0 884 ASSIMP_END_EXCEPTION_REGION(size_t);
nuclear@0 885 return static_cast<size_t>(-1);
nuclear@0 886 }
nuclear@0 887
nuclear@0 888 // ------------------------------------------------------------------------------------------------
nuclear@0 889 // Helper function to build a list of all file extensions supported by ASSIMP
nuclear@0 890 void Importer::GetExtensionList(aiString& szOut) const
nuclear@0 891 {
nuclear@0 892 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 893 std::set<std::string> str;
nuclear@0 894 for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
nuclear@0 895 (*i)->GetExtensionList(str);
nuclear@0 896 }
nuclear@0 897
nuclear@0 898 for (std::set<std::string>::const_iterator it = str.begin();; ) {
nuclear@0 899 szOut.Append("*.");
nuclear@0 900 szOut.Append((*it).c_str());
nuclear@0 901
nuclear@0 902 if (++it == str.end()) {
nuclear@0 903 break;
nuclear@0 904 }
nuclear@0 905 szOut.Append(";");
nuclear@0 906 }
nuclear@0 907 ASSIMP_END_EXCEPTION_REGION(void);
nuclear@0 908 }
nuclear@0 909
nuclear@0 910 // ------------------------------------------------------------------------------------------------
nuclear@0 911 // Set a configuration property
nuclear@0 912 void Importer::SetPropertyInteger(const char* szName, int iValue,
nuclear@0 913 bool* bWasExisting /*= NULL*/)
nuclear@0 914 {
nuclear@0 915 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 916 SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue,bWasExisting);
nuclear@0 917 ASSIMP_END_EXCEPTION_REGION(void);
nuclear@0 918 }
nuclear@0 919
nuclear@0 920 // ------------------------------------------------------------------------------------------------
nuclear@0 921 // Set a configuration property
nuclear@0 922 void Importer::SetPropertyFloat(const char* szName, float iValue,
nuclear@0 923 bool* bWasExisting /*= NULL*/)
nuclear@0 924 {
nuclear@0 925 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 926 SetGenericProperty<float>(pimpl->mFloatProperties, szName,iValue,bWasExisting);
nuclear@0 927 ASSIMP_END_EXCEPTION_REGION(void);
nuclear@0 928 }
nuclear@0 929
nuclear@0 930 // ------------------------------------------------------------------------------------------------
nuclear@0 931 // Set a configuration property
nuclear@0 932 void Importer::SetPropertyString(const char* szName, const std::string& value,
nuclear@0 933 bool* bWasExisting /*= NULL*/)
nuclear@0 934 {
nuclear@0 935 ASSIMP_BEGIN_EXCEPTION_REGION();
nuclear@0 936 SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value,bWasExisting);
nuclear@0 937 ASSIMP_END_EXCEPTION_REGION(void);
nuclear@0 938 }
nuclear@0 939
nuclear@0 940 // ------------------------------------------------------------------------------------------------
nuclear@0 941 // Get a configuration property
nuclear@0 942 int Importer::GetPropertyInteger(const char* szName,
nuclear@0 943 int iErrorReturn /*= 0xffffffff*/) const
nuclear@0 944 {
nuclear@0 945 return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn);
nuclear@0 946 }
nuclear@0 947
nuclear@0 948 // ------------------------------------------------------------------------------------------------
nuclear@0 949 // Get a configuration property
nuclear@0 950 float Importer::GetPropertyFloat(const char* szName,
nuclear@0 951 float iErrorReturn /*= 10e10*/) const
nuclear@0 952 {
nuclear@0 953 return GetGenericProperty<float>(pimpl->mFloatProperties,szName,iErrorReturn);
nuclear@0 954 }
nuclear@0 955
nuclear@0 956 // ------------------------------------------------------------------------------------------------
nuclear@0 957 // Get a configuration property
nuclear@0 958 const std::string& Importer::GetPropertyString(const char* szName,
nuclear@0 959 const std::string& iErrorReturn /*= ""*/) const
nuclear@0 960 {
nuclear@0 961 return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
nuclear@0 962 }
nuclear@0 963
nuclear@0 964 // ------------------------------------------------------------------------------------------------
nuclear@0 965 // Get the memory requirements of a single node
nuclear@0 966 inline void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode)
nuclear@0 967 {
nuclear@0 968 iScene += sizeof(aiNode);
nuclear@0 969 iScene += sizeof(unsigned int) * pcNode->mNumMeshes;
nuclear@0 970 iScene += sizeof(void*) * pcNode->mNumChildren;
nuclear@0 971
nuclear@0 972 for (unsigned int i = 0; i < pcNode->mNumChildren;++i) {
nuclear@0 973 AddNodeWeight(iScene,pcNode->mChildren[i]);
nuclear@0 974 }
nuclear@0 975 }
nuclear@0 976
nuclear@0 977 // ------------------------------------------------------------------------------------------------
nuclear@0 978 // Get the memory requirements of the scene
nuclear@0 979 void Importer::GetMemoryRequirements(aiMemoryInfo& in) const
nuclear@0 980 {
nuclear@0 981 in = aiMemoryInfo();
nuclear@0 982 aiScene* mScene = pimpl->mScene;
nuclear@0 983
nuclear@0 984 // return if we have no scene loaded
nuclear@0 985 if (!pimpl->mScene)
nuclear@0 986 return;
nuclear@0 987
nuclear@0 988
nuclear@0 989 in.total = sizeof(aiScene);
nuclear@0 990
nuclear@0 991 // add all meshes
nuclear@0 992 for (unsigned int i = 0; i < mScene->mNumMeshes;++i)
nuclear@0 993 {
nuclear@0 994 in.meshes += sizeof(aiMesh);
nuclear@0 995 if (mScene->mMeshes[i]->HasPositions()) {
nuclear@0 996 in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
nuclear@0 997 }
nuclear@0 998
nuclear@0 999 if (mScene->mMeshes[i]->HasNormals()) {
nuclear@0 1000 in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
nuclear@0 1001 }
nuclear@0 1002
nuclear@0 1003 if (mScene->mMeshes[i]->HasTangentsAndBitangents()) {
nuclear@0 1004 in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices * 2;
nuclear@0 1005 }
nuclear@0 1006
nuclear@0 1007 for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) {
nuclear@0 1008 if (mScene->mMeshes[i]->HasVertexColors(a)) {
nuclear@0 1009 in.meshes += sizeof(aiColor4D) * mScene->mMeshes[i]->mNumVertices;
nuclear@0 1010 }
nuclear@0 1011 else break;
nuclear@0 1012 }
nuclear@0 1013 for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
nuclear@0 1014 if (mScene->mMeshes[i]->HasTextureCoords(a)) {
nuclear@0 1015 in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
nuclear@0 1016 }
nuclear@0 1017 else break;
nuclear@0 1018 }
nuclear@0 1019 if (mScene->mMeshes[i]->HasBones()) {
nuclear@0 1020 in.meshes += sizeof(void*) * mScene->mMeshes[i]->mNumBones;
nuclear@0 1021 for (unsigned int p = 0; p < mScene->mMeshes[i]->mNumBones;++p) {
nuclear@0 1022 in.meshes += sizeof(aiBone);
nuclear@0 1023 in.meshes += mScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight);
nuclear@0 1024 }
nuclear@0 1025 }
nuclear@0 1026 in.meshes += (sizeof(aiFace) + 3 * sizeof(unsigned int))*mScene->mMeshes[i]->mNumFaces;
nuclear@0 1027 }
nuclear@0 1028 in.total += in.meshes;
nuclear@0 1029
nuclear@0 1030 // add all embedded textures
nuclear@0 1031 for (unsigned int i = 0; i < mScene->mNumTextures;++i) {
nuclear@0 1032 const aiTexture* pc = mScene->mTextures[i];
nuclear@0 1033 in.textures += sizeof(aiTexture);
nuclear@0 1034 if (pc->mHeight) {
nuclear@0 1035 in.textures += 4 * pc->mHeight * pc->mWidth;
nuclear@0 1036 }
nuclear@0 1037 else in.textures += pc->mWidth;
nuclear@0 1038 }
nuclear@0 1039 in.total += in.textures;
nuclear@0 1040
nuclear@0 1041 // add all animations
nuclear@0 1042 for (unsigned int i = 0; i < mScene->mNumAnimations;++i) {
nuclear@0 1043 const aiAnimation* pc = mScene->mAnimations[i];
nuclear@0 1044 in.animations += sizeof(aiAnimation);
nuclear@0 1045
nuclear@0 1046 // add all bone anims
nuclear@0 1047 for (unsigned int a = 0; a < pc->mNumChannels; ++a) {
nuclear@0 1048 const aiNodeAnim* pc2 = pc->mChannels[i];
nuclear@0 1049 in.animations += sizeof(aiNodeAnim);
nuclear@0 1050 in.animations += pc2->mNumPositionKeys * sizeof(aiVectorKey);
nuclear@0 1051 in.animations += pc2->mNumScalingKeys * sizeof(aiVectorKey);
nuclear@0 1052 in.animations += pc2->mNumRotationKeys * sizeof(aiQuatKey);
nuclear@0 1053 }
nuclear@0 1054 }
nuclear@0 1055 in.total += in.animations;
nuclear@0 1056
nuclear@0 1057 // add all cameras and all lights
nuclear@0 1058 in.total += in.cameras = sizeof(aiCamera) * mScene->mNumCameras;
nuclear@0 1059 in.total += in.lights = sizeof(aiLight) * mScene->mNumLights;
nuclear@0 1060
nuclear@0 1061 // add all nodes
nuclear@0 1062 AddNodeWeight(in.nodes,mScene->mRootNode);
nuclear@0 1063 in.total += in.nodes;
nuclear@0 1064
nuclear@0 1065 // add all materials
nuclear@0 1066 for (unsigned int i = 0; i < mScene->mNumMaterials;++i) {
nuclear@0 1067 const aiMaterial* pc = mScene->mMaterials[i];
nuclear@0 1068 in.materials += sizeof(aiMaterial);
nuclear@0 1069 in.materials += pc->mNumAllocated * sizeof(void*);
nuclear@0 1070
nuclear@0 1071 for (unsigned int a = 0; a < pc->mNumProperties;++a) {
nuclear@0 1072 in.materials += pc->mProperties[a]->mDataLength;
nuclear@0 1073 }
nuclear@0 1074 }
nuclear@0 1075 in.total += in.materials;
nuclear@0 1076 }
nuclear@0 1077