1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279 |
- /*
- ---------------------------------------------------------------------------
- Open Asset Import Library (assimp)
- ---------------------------------------------------------------------------
- Copyright (c) 2006-2024, assimp team
- All rights reserved.
- Redistribution and use of this software in source and binary forms,
- with or without modification, are permitted provided that the following
- conditions are met:
- * Redistributions of source code must retain the above
- copyright notice, this list of conditions and the
- following disclaimer.
- * Redistributions in binary form must reproduce the above
- copyright notice, this list of conditions and the
- following disclaimer in the documentation and/or other
- materials provided with the distribution.
- * Neither the name of the assimp team, nor the names of its
- contributors may be used to endorse or promote products
- derived from this software without specific prior
- written permission of the assimp team.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- ---------------------------------------------------------------------------
- */
- /** @file Importer.cpp
- * @brief Implementation of the CPP-API class #Importer
- */
- #include <assimp/version.h>
- #include <assimp/config.h>
- #include <assimp/importerdesc.h>
- // ------------------------------------------------------------------------------------------------
- /* Uncomment this line to prevent Assimp from catching unknown exceptions.
- *
- * Note that any Exception except DeadlyImportError may lead to
- * undefined behaviour -> loaders could remain in an unusable state and
- * further imports with the same Importer instance could fail/crash/burn ...
- */
- // ------------------------------------------------------------------------------------------------
- #ifndef ASSIMP_BUILD_DEBUG
- # define ASSIMP_CATCH_GLOBAL_EXCEPTIONS
- #endif
- // ------------------------------------------------------------------------------------------------
- // Internal headers
- // ------------------------------------------------------------------------------------------------
- #include "Common/Importer.h"
- #include "Common/BaseProcess.h"
- #include "Common/DefaultProgressHandler.h"
- #include "PostProcessing/ProcessHelper.h"
- #include "Common/ScenePreprocessor.h"
- #include "Common/ScenePrivate.h"
- #include <assimp/BaseImporter.h>
- #include <assimp/GenericProperty.h>
- #include <assimp/MemoryIOWrapper.h>
- #include <assimp/Profiler.h>
- #include <assimp/TinyFormatter.h>
- #include <assimp/Exceptional.h>
- #include <assimp/Profiler.h>
- #include <assimp/commonMetaData.h>
- #include <exception>
- #include <set>
- #include <memory>
- #include <cctype>
- #include <assimp/DefaultIOStream.h>
- #include <assimp/DefaultIOSystem.h>
- #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
- # include "PostProcessing/ValidateDataStructure.h"
- #endif
- using namespace Assimp::Profiling;
- using namespace Assimp::Formatter;
- namespace Assimp {
- // ImporterRegistry.cpp
- void GetImporterInstanceList(std::vector< BaseImporter* >& out);
- void DeleteImporterInstanceList(std::vector< BaseImporter* >& out);
- // PostStepRegistry.cpp
- void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
- }
- using namespace Assimp;
- using namespace Assimp::Intern;
- // ------------------------------------------------------------------------------------------------
- // Intern::AllocateFromAssimpHeap serves as abstract base class. It overrides
- // new and delete (and their array counterparts) of public API classes (e.g. Logger) to
- // utilize our DLL heap.
- // See http://www.gotw.ca/publications/mill15.htm
- // ------------------------------------------------------------------------------------------------
- void* AllocateFromAssimpHeap::operator new ( size_t num_bytes) {
- return ::operator new(num_bytes);
- }
- void* AllocateFromAssimpHeap::operator new ( size_t num_bytes, const std::nothrow_t& ) throw() {
- try {
- return AllocateFromAssimpHeap::operator new( num_bytes );
- }
- catch( ... ) {
- return nullptr;
- }
- }
- void AllocateFromAssimpHeap::operator delete ( void* data) {
- return ::operator delete(data);
- }
- void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes) {
- return ::operator new[](num_bytes);
- }
- void* AllocateFromAssimpHeap::operator new[] ( size_t num_bytes, const std::nothrow_t& ) throw() {
- try {
- return AllocateFromAssimpHeap::operator new[]( num_bytes );
- } catch( ... ) {
- return nullptr;
- }
- }
- void AllocateFromAssimpHeap::operator delete[] ( void* data) {
- return ::operator delete[](data);
- }
- // ------------------------------------------------------------------------------------------------
- // Importer constructor.
- Importer::Importer()
- : pimpl( new ImporterPimpl ) {
- pimpl->mScene = nullptr;
- pimpl->mErrorString = std::string();
- // Allocate a default IO handler
- pimpl->mIOHandler = new DefaultIOSystem;
- pimpl->mIsDefaultHandler = true;
- pimpl->bExtraVerbose = false; // disable extra verbose mode by default
- pimpl->mProgressHandler = new DefaultProgressHandler();
- pimpl->mIsDefaultProgressHandler = true;
- GetImporterInstanceList(pimpl->mImporter);
- GetPostProcessingStepInstanceList(pimpl->mPostProcessingSteps);
- // Allocate a SharedPostProcessInfo object and store pointers to it in all post-process steps in the list.
- pimpl->mPPShared = new SharedPostProcessInfo();
- for (std::vector<BaseProcess*>::iterator it = pimpl->mPostProcessingSteps.begin();
- it != pimpl->mPostProcessingSteps.end();
- ++it) {
- (*it)->SetSharedData(pimpl->mPPShared);
- }
- }
- // ------------------------------------------------------------------------------------------------
- // Destructor of Importer
- Importer::~Importer() {
- // Delete all import plugins
- DeleteImporterInstanceList(pimpl->mImporter);
- // Delete all post-processing plug-ins
- for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); ++a ) {
- delete pimpl->mPostProcessingSteps[a];
- }
- // Delete the assigned IO and progress handler
- delete pimpl->mIOHandler;
- delete pimpl->mProgressHandler;
- // Kill imported scene. Destructor's should do that recursively
- delete pimpl->mScene;
- // Delete shared post-processing data
- delete pimpl->mPPShared;
- // and finally the pimpl itself
- delete pimpl;
- }
- // ------------------------------------------------------------------------------------------------
- // Register a custom post-processing step
- aiReturn Importer::RegisterPPStep(BaseProcess* pImp) {
- ai_assert( nullptr != pImp );
- ASSIMP_BEGIN_EXCEPTION_REGION();
- pimpl->mPostProcessingSteps.push_back(pImp);
- ASSIMP_LOG_INFO("Registering custom post-processing step");
- ASSIMP_END_EXCEPTION_REGION(aiReturn);
- return AI_SUCCESS;
- }
- // ------------------------------------------------------------------------------------------------
- // Register a custom loader plugin
- aiReturn Importer::RegisterLoader(BaseImporter* pImp) {
- ai_assert(nullptr != pImp);
- ASSIMP_BEGIN_EXCEPTION_REGION();
- // --------------------------------------------------------------------
- // Check whether we would have two loaders for the same file extension
- // This is absolutely OK, but we should warn the developer of the new
- // loader that his code will probably never be called if the first
- // loader is a bit too lazy in his file checking.
- // --------------------------------------------------------------------
- std::set<std::string> st;
- std::string baked;
- pImp->GetExtensionList(st);
- for(std::set<std::string>::const_iterator it = st.begin(); it != st.end(); ++it) {
- #ifdef ASSIMP_BUILD_DEBUG
- if (IsExtensionSupported(*it)) {
- ASSIMP_LOG_WARN("The file extension ", *it, " is already in use");
- }
- #endif
- baked += *it;
- }
- // add the loader
- pimpl->mImporter.push_back(pImp);
- ASSIMP_LOG_INFO("Registering custom importer for these file extensions: ", baked);
- ASSIMP_END_EXCEPTION_REGION(aiReturn);
- return AI_SUCCESS;
- }
- // ------------------------------------------------------------------------------------------------
- // Unregister a custom loader plugin
- aiReturn Importer::UnregisterLoader(BaseImporter* pImp) {
- if(!pImp) {
- // unregistering a nullptr importer is no problem for us ... really!
- return AI_SUCCESS;
- }
- ASSIMP_BEGIN_EXCEPTION_REGION();
- std::vector<BaseImporter*>::iterator it = std::find(pimpl->mImporter.begin(),
- pimpl->mImporter.end(),pImp);
- if (it != pimpl->mImporter.end()) {
- pimpl->mImporter.erase(it);
- ASSIMP_LOG_INFO("Unregistering custom importer: ");
- return AI_SUCCESS;
- }
- ASSIMP_LOG_WARN("Unable to remove custom importer: I can't find you ...");
- ASSIMP_END_EXCEPTION_REGION(aiReturn);
- return AI_FAILURE;
- }
- // ------------------------------------------------------------------------------------------------
- // Unregister a custom loader plugin
- aiReturn Importer::UnregisterPPStep(BaseProcess* pImp) {
- if(!pImp) {
- // unregistering a nullptr ppstep is no problem for us ... really!
- return AI_SUCCESS;
- }
- ASSIMP_BEGIN_EXCEPTION_REGION();
- std::vector<BaseProcess*>::iterator it = std::find(pimpl->mPostProcessingSteps.begin(),
- pimpl->mPostProcessingSteps.end(),pImp);
- if (it != pimpl->mPostProcessingSteps.end()) {
- pimpl->mPostProcessingSteps.erase(it);
- ASSIMP_LOG_INFO("Unregistering custom post-processing step");
- return AI_SUCCESS;
- }
- ASSIMP_LOG_WARN("Unable to remove custom post-processing step: I can't find you ..");
- ASSIMP_END_EXCEPTION_REGION(aiReturn);
- return AI_FAILURE;
- }
- // ------------------------------------------------------------------------------------------------
- // Supplies a custom IO handler to the importer to open and access files.
- void Importer::SetIOHandler( IOSystem* pIOHandler) {
- ai_assert(nullptr != pimpl);
- ASSIMP_BEGIN_EXCEPTION_REGION();
- // If the new handler is zero, allocate a default IO implementation.
- if (!pIOHandler) {
- // Release pointer in the possession of the caller
- pimpl->mIOHandler = new DefaultIOSystem();
- pimpl->mIsDefaultHandler = true;
- } else if (pimpl->mIOHandler != pIOHandler) { // Otherwise register the custom handler
- delete pimpl->mIOHandler;
- pimpl->mIOHandler = pIOHandler;
- pimpl->mIsDefaultHandler = false;
- }
- ASSIMP_END_EXCEPTION_REGION(void);
- }
- // ------------------------------------------------------------------------------------------------
- // Get the currently set IO handler
- IOSystem* Importer::GetIOHandler() const {
- ai_assert(nullptr != pimpl);
- return pimpl->mIOHandler;
- }
- // ------------------------------------------------------------------------------------------------
- // Check whether a custom IO handler is currently set
- bool Importer::IsDefaultIOHandler() const {
- ai_assert(nullptr != pimpl);
- return pimpl->mIsDefaultHandler;
- }
- // ------------------------------------------------------------------------------------------------
- // Supplies a custom progress handler to get regular callbacks during importing
- void Importer::SetProgressHandler(ProgressHandler* pHandler) {
- ai_assert(nullptr != pimpl);
- ASSIMP_BEGIN_EXCEPTION_REGION();
- // If the new handler is zero, allocate a default implementation.
- if (!pHandler) {
- // Release pointer in the possession of the caller
- pimpl->mProgressHandler = new DefaultProgressHandler();
- pimpl->mIsDefaultProgressHandler = true;
- } else if (pimpl->mProgressHandler != pHandler) { // Otherwise register the custom handler
- delete pimpl->mProgressHandler;
- pimpl->mProgressHandler = pHandler;
- pimpl->mIsDefaultProgressHandler = false;
- }
- ASSIMP_END_EXCEPTION_REGION(void);
- }
- // ------------------------------------------------------------------------------------------------
- // Get the currently set progress handler
- ProgressHandler* Importer::GetProgressHandler() const {
- ai_assert(nullptr != pimpl);
- return pimpl->mProgressHandler;
- }
- // ------------------------------------------------------------------------------------------------
- // Check whether a custom progress handler is currently set
- bool Importer::IsDefaultProgressHandler() const {
- ai_assert(nullptr != pimpl);
- return pimpl->mIsDefaultProgressHandler;
- }
- // ------------------------------------------------------------------------------------------------
- // Validate post process step flags
- bool _ValidateFlags(unsigned int pFlags) {
- if (pFlags & aiProcess_GenSmoothNormals && pFlags & aiProcess_GenNormals) {
- ASSIMP_LOG_ERROR("#aiProcess_GenSmoothNormals and #aiProcess_GenNormals are incompatible");
- return false;
- }
- if (pFlags & aiProcess_OptimizeGraph && pFlags & aiProcess_PreTransformVertices) {
- ASSIMP_LOG_ERROR("#aiProcess_OptimizeGraph and #aiProcess_PreTransformVertices are incompatible");
- return false;
- }
- return true;
- }
- // ------------------------------------------------------------------------------------------------
- // Free the current scene
- void Importer::FreeScene( ) {
- ai_assert(nullptr != pimpl);
- ASSIMP_BEGIN_EXCEPTION_REGION();
- delete pimpl->mScene;
- pimpl->mScene = nullptr;
- pimpl->mErrorString = std::string();
- pimpl->mException = std::exception_ptr();
- ASSIMP_END_EXCEPTION_REGION(void);
- }
- // ------------------------------------------------------------------------------------------------
- // Get the current error string, if any
- const char* Importer::GetErrorString() const {
- ai_assert(nullptr != pimpl);
- // Must remain valid as long as ReadFile() or FreeFile() are not called
- return pimpl->mErrorString.c_str();
- }
- const std::exception_ptr& Importer::GetException() const {
- ai_assert(nullptr != pimpl);
- // Must remain valid as long as ReadFile() or FreeFile() are not called
- return pimpl->mException;
- }
- // ------------------------------------------------------------------------------------------------
- // Enable extra-verbose mode
- void Importer::SetExtraVerbose(bool bDo) {
- ai_assert(nullptr != pimpl);
- pimpl->bExtraVerbose = bDo;
- }
- // ------------------------------------------------------------------------------------------------
- // Get the current scene
- const aiScene* Importer::GetScene() const {
- ai_assert(nullptr != pimpl);
- return pimpl->mScene;
- }
- // ------------------------------------------------------------------------------------------------
- // Orphan the current scene and return it.
- aiScene* Importer::GetOrphanedScene() {
- ai_assert(nullptr != pimpl);
- aiScene* s = pimpl->mScene;
- ASSIMP_BEGIN_EXCEPTION_REGION();
- pimpl->mScene = nullptr;
- pimpl->mErrorString = std::string();
- pimpl->mException = std::exception_ptr();
- ASSIMP_END_EXCEPTION_REGION(aiScene*);
- return s;
- }
- // ------------------------------------------------------------------------------------------------
- // Validate post-processing flags
- bool Importer::ValidateFlags(unsigned int pFlags) const {
- ASSIMP_BEGIN_EXCEPTION_REGION();
- // run basic checks for mutually exclusive flags
- if(!_ValidateFlags(pFlags)) {
- return false;
- }
- // ValidateDS does not anymore occur in the pp list, it plays an awesome extra role ...
- #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
- if (pFlags & aiProcess_ValidateDataStructure) {
- return false;
- }
- #endif
- pFlags &= ~aiProcess_ValidateDataStructure;
- // Now iterate through all bits which are set in the flags and check whether we find at least
- // one pp plugin which handles it.
- for (unsigned int mask = 1; mask < (1u << (sizeof(unsigned int)*8-1));mask <<= 1) {
- if (pFlags & mask) {
- bool have = false;
- for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
- if (pimpl->mPostProcessingSteps[a]-> IsActive(mask) ) {
- have = true;
- break;
- }
- }
- if (!have) {
- return false;
- }
- }
- }
- ASSIMP_END_EXCEPTION_REGION(bool);
- return true;
- }
- // ------------------------------------------------------------------------------------------------
- const aiScene* Importer::ReadFileFromMemory(const void* pBuffer, size_t pLength, unsigned int pFlags, const char* pHint ) {
- ai_assert(nullptr != pimpl);
- IOSystem* io = pimpl->mIOHandler;
- try {
- if (pHint == nullptr) {
- pHint = "";
- }
- if (!pBuffer || !pLength || strlen(pHint) > MaxLenHint ) {
- pimpl->mErrorString = "Invalid parameters passed to ReadFileFromMemory()";
- return nullptr;
- }
- // prevent deletion of the previous IOHandler
- pimpl->mIOHandler = nullptr;
- SetIOHandler(new MemoryIOSystem((const uint8_t*)pBuffer,pLength,io));
- // read the file and recover the previous IOSystem
- static const size_t BufSize(Importer::MaxLenHint + 28);
- char fbuff[BufSize];
- ai_snprintf(fbuff, BufSize, "%s.%s",AI_MEMORYIO_MAGIC_FILENAME,pHint);
- ReadFile(fbuff,pFlags);
- SetIOHandler(io);
- } catch(const DeadlyImportError &e) {
- pimpl->mErrorString = e.what();
- pimpl->mException = std::current_exception();
- SetIOHandler(io);
- return ExceptionSwallower<const aiScene*>()(); \
- } catch(...) {
- pimpl->mErrorString = "Unknown exception";
- pimpl->mException = std::current_exception();
- SetIOHandler(io);
- return ExceptionSwallower<const aiScene*>()(); \
- }
- return pimpl->mScene;
- }
- // ------------------------------------------------------------------------------------------------
- void WriteLogOpening(const std::string& file) {
- ASSIMP_LOG_INFO("Load ", file);
- // print a full version dump. This is nice because we don't
- // need to ask the authors of incoming bug reports for
- // the library version they're using - a log dump is
- // sufficient.
- const unsigned int flags = aiGetCompileFlags();
- std::stringstream stream;
- stream << "Assimp " << aiGetVersionMajor() << "." << aiGetVersionMinor() << "." << aiGetVersionRevision() << " "
- #if defined(ASSIMP_BUILD_ARCHITECTURE)
- << ASSIMP_BUILD_ARCHITECTURE
- #elif defined(_M_IX86) || defined(__x86_32__) || defined(__i386__)
- << "x86"
- #elif defined(_M_X64) || defined(__x86_64__)
- << "amd64"
- #elif defined(_M_IA64) || defined(__ia64__)
- << "itanium"
- #elif defined(__ppc__) || defined(__powerpc__)
- << "ppc32"
- #elif defined(__powerpc64__)
- << "ppc64"
- #elif defined(__arm__)
- << "arm"
- #else
- << "<unknown architecture>"
- #endif
- << " "
- #if defined(ASSIMP_BUILD_COMPILER)
- << (ASSIMP_BUILD_COMPILER)
- #elif defined(_MSC_VER)
- << "msvc"
- #elif defined(__GNUC__)
- << "gcc"
- #elif defined(__clang__)
- << "clang"
- #elif defined(__EMSCRIPTEN__)
- << "emscripten"
- #elif defined(__MINGW32__)
- << "MinGW-w64 32bit"
- #elif defined(__MINGW64__)
- << "MinGW-w64 64bit"
- #else
- << "<unknown compiler>"
- #endif
- #ifdef ASSIMP_BUILD_DEBUG
- << " debug"
- #endif
- << (flags & ASSIMP_CFLAGS_NOBOOST ? " noboost" : "")
- << (flags & ASSIMP_CFLAGS_SHARED ? " shared" : "")
- << (flags & ASSIMP_CFLAGS_SINGLETHREADED ? " singlethreaded" : "")
- << (flags & ASSIMP_CFLAGS_DOUBLE_SUPPORT ? " double : " : "single : ");
- ASSIMP_LOG_DEBUG(stream.str());
- }
- // ------------------------------------------------------------------------------------------------
- // Reads the given file and returns its contents if successful.
- const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
- ai_assert(nullptr != pimpl);
- ASSIMP_BEGIN_EXCEPTION_REGION();
- const std::string pFile(_pFile);
- // ----------------------------------------------------------------------
- // Put a large try block around everything to catch all std::exception's
- // that might be thrown by STL containers or by new().
- // ImportErrorException's are throw by ourselves and caught elsewhere.
- //-----------------------------------------------------------------------
- WriteLogOpening(pFile);
- #ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
- try
- #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
- {
- // Check whether this Importer instance has already loaded
- // a scene. In this case we need to delete the old one
- if (pimpl->mScene) {
- ASSIMP_LOG_DEBUG("(Deleting previous scene)");
- FreeScene();
- }
- // First check if the file is accessible at all
- if( !pimpl->mIOHandler->Exists( pFile)) {
- pimpl->mErrorString = "Unable to open file \"" + pFile + "\".";
- ASSIMP_LOG_ERROR(pimpl->mErrorString);
- return nullptr;
- }
- std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr);
- if (profiler) {
- profiler->BeginRegion("total");
- }
- // Find an worker class which can handle the file extension.
- // Multiple importers may be able to handle the same extension (.xml!); gather them all.
- SetPropertyInteger("importerIndex", -1);
- struct ImporterAndIndex {
- BaseImporter * importer;
- unsigned int index;
- };
- std::vector<ImporterAndIndex> possibleImporters;
- for (unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
- // Every importer has a list of supported extensions.
- std::set<std::string> extensions;
- pimpl->mImporter[a]->GetExtensionList(extensions);
- if (BaseImporter::HasExtension(pFile, extensions)) {
- ImporterAndIndex candidate = { pimpl->mImporter[a], a };
- possibleImporters.push_back(candidate);
- }
- }
- // If just one importer supports this extension, pick it and close the case.
- BaseImporter* imp = nullptr;
- if (1 == possibleImporters.size()) {
- imp = possibleImporters[0].importer;
- SetPropertyInteger("importerIndex", possibleImporters[0].index);
- }
- // If multiple importers claim this file extension, ask them to look at the actual file data to decide.
- // This can happen e.g. with XML (COLLADA vs. Irrlicht).
- else {
- for (std::vector<ImporterAndIndex>::const_iterator it = possibleImporters.begin(); it < possibleImporters.end(); ++it) {
- BaseImporter & importer = *it->importer;
- ASSIMP_LOG_INFO("Found a possible importer: " + std::string(importer.GetInfo()->mName) + "; trying signature-based detection");
- if (importer.CanRead( pFile, pimpl->mIOHandler, true)) {
- imp = &importer;
- SetPropertyInteger("importerIndex", it->index);
- break;
- }
- }
- }
- if (!imp) {
- // not so bad yet ... try format auto detection.
- ASSIMP_LOG_INFO("File extension not known, trying signature-based detection");
- for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
- if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
- imp = pimpl->mImporter[a];
- SetPropertyInteger("importerIndex", a);
- break;
- }
- }
- // Put a proper error message if no suitable importer was found
- if( !imp) {
- pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";
- ASSIMP_LOG_ERROR(pimpl->mErrorString);
- return nullptr;
- }
- }
- // Get file size for progress handler
- IOStream * fileIO = pimpl->mIOHandler->Open( pFile );
- uint32_t fileSize = 0;
- if (fileIO)
- {
- fileSize = static_cast<uint32_t>(fileIO->FileSize());
- pimpl->mIOHandler->Close( fileIO );
- }
- // Dispatch the reading to the worker class for this format
- const aiImporterDesc *desc( imp->GetInfo() );
- std::string ext( "unknown" );
- if ( nullptr != desc ) {
- ext = desc->mName;
- }
- ASSIMP_LOG_INFO("Found a matching importer for this file format: ", ext, "." );
- pimpl->mProgressHandler->UpdateFileRead( 0, fileSize );
- if (profiler) {
- profiler->BeginRegion("import");
- }
- pimpl->mScene = imp->ReadFile( this, pFile, pimpl->mIOHandler);
- pimpl->mProgressHandler->UpdateFileRead( fileSize, fileSize );
- if (profiler) {
- profiler->EndRegion("import");
- }
- SetPropertyString("sourceFilePath", pFile);
- // If successful, apply all active post processing steps to the imported data
- if( pimpl->mScene) {
- if (!pimpl->mScene->mMetaData || !pimpl->mScene->mMetaData->HasKey(AI_METADATA_SOURCE_FORMAT)) {
- if (!pimpl->mScene->mMetaData) {
- pimpl->mScene->mMetaData = new aiMetadata;
- }
- pimpl->mScene->mMetaData->Add(AI_METADATA_SOURCE_FORMAT, aiString(ext));
- }
- #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
- // The ValidateDS process is an exception. It is executed first, even before ScenePreprocessor is called.
- if (pFlags & aiProcess_ValidateDataStructure) {
- ValidateDSProcess ds;
- ds.ExecuteOnScene (this);
- if (!pimpl->mScene) {
- return nullptr;
- }
- }
- #endif // no validation
- // Preprocess the scene and prepare it for post-processing
- if (profiler) {
- profiler->BeginRegion("preprocess");
- }
- ScenePreprocessor pre(pimpl->mScene);
- pre.ProcessScene();
- if (profiler) {
- profiler->EndRegion("preprocess");
- }
- // Ensure that the validation process won't be called twice
- ApplyPostProcessing(pFlags & (~aiProcess_ValidateDataStructure));
- }
- // if failed, extract the error string
- else if( !pimpl->mScene) {
- pimpl->mErrorString = imp->GetErrorText();
- pimpl->mException = imp->GetException();
- }
- // clear any data allocated by post-process steps
- pimpl->mPPShared->Clean();
- if (profiler) {
- profiler->EndRegion("total");
- }
- }
- #ifdef ASSIMP_CATCH_GLOBAL_EXCEPTIONS
- catch (std::exception &e) {
- #if (defined _MSC_VER) && (defined _CPPRTTI)
- // if we have RTTI get the full name of the exception that occurred
- pimpl->mErrorString = std::string(typeid( e ).name()) + ": " + e.what();
- #else
- pimpl->mErrorString = std::string("std::exception: ") + e.what();
- #endif
- ASSIMP_LOG_ERROR(pimpl->mErrorString);
- delete pimpl->mScene; pimpl->mScene = nullptr;
- }
- #endif // ! ASSIMP_CATCH_GLOBAL_EXCEPTIONS
- // either successful or failure - the pointer expresses it anyways
- ASSIMP_END_EXCEPTION_REGION_WITH_ERROR_STRING(const aiScene*, pimpl->mErrorString, pimpl->mException);
- return pimpl->mScene;
- }
- // ------------------------------------------------------------------------------------------------
- // Apply post-processing to the currently bound scene
- const aiScene* Importer::ApplyPostProcessing(unsigned int pFlags) {
- ai_assert(nullptr != pimpl);
- ASSIMP_BEGIN_EXCEPTION_REGION();
- // Return immediately if no scene is active
- if (!pimpl->mScene) {
- return nullptr;
- }
- // If no flags are given, return the current scene with no further action
- if (!pFlags) {
- return pimpl->mScene;
- }
- // In debug builds: run basic flag validation
- ai_assert(_ValidateFlags(pFlags));
- ASSIMP_LOG_INFO("Entering post processing pipeline");
- #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
- // The ValidateDS process plays an exceptional role. It isn't contained in the global
- // list of post-processing steps, so we need to call it manually.
- if (pFlags & aiProcess_ValidateDataStructure) {
- ValidateDSProcess ds;
- ds.ExecuteOnScene (this);
- if (!pimpl->mScene) {
- return nullptr;
- }
- }
- #endif // no validation
- #ifdef ASSIMP_BUILD_DEBUG
- if (pimpl->bExtraVerbose)
- {
- #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
- ASSIMP_LOG_ERROR("Verbose Import is not available due to build settings");
- #endif // no validation
- pFlags |= aiProcess_ValidateDataStructure;
- }
- #else
- if (pimpl->bExtraVerbose) {
- ASSIMP_LOG_WARN("Not a debug build, ignoring extra verbose setting");
- }
- #endif // ! DEBUG
- std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr);
- for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
- BaseProcess* process = pimpl->mPostProcessingSteps[a];
- pimpl->mProgressHandler->UpdatePostProcess(static_cast<int>(a), static_cast<int>(pimpl->mPostProcessingSteps.size()) );
- if( process->IsActive( pFlags)) {
- if (profiler) {
- profiler->BeginRegion("postprocess");
- }
- process->ExecuteOnScene ( this );
- if (profiler) {
- profiler->EndRegion("postprocess");
- }
- }
- if( !pimpl->mScene) {
- break;
- }
- #ifdef ASSIMP_BUILD_DEBUG
- #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
- continue;
- #endif // no validation
- // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
- if (pimpl->bExtraVerbose) {
- ASSIMP_LOG_DEBUG("Verbose Import: re-validating data structures");
- ValidateDSProcess ds;
- ds.ExecuteOnScene (this);
- if( !pimpl->mScene) {
- ASSIMP_LOG_ERROR("Verbose Import: failed to re-validate data structures");
- break;
- }
- }
- #endif // ! DEBUG
- }
- pimpl->mProgressHandler->UpdatePostProcess( static_cast<int>(pimpl->mPostProcessingSteps.size()),
- static_cast<int>(pimpl->mPostProcessingSteps.size()) );
- // update private scene flags
- if( pimpl->mScene ) {
- ScenePriv(pimpl->mScene)->mPPStepsApplied |= pFlags;
- }
- // clear any data allocated by post-process steps
- pimpl->mPPShared->Clean();
- ASSIMP_LOG_INFO("Leaving post processing pipeline");
- ASSIMP_END_EXCEPTION_REGION(const aiScene*);
- return pimpl->mScene;
- }
- // ------------------------------------------------------------------------------------------------
- const aiScene* Importer::ApplyCustomizedPostProcessing( BaseProcess *rootProcess, bool requestValidation ) {
- ai_assert(nullptr != pimpl);
- ASSIMP_BEGIN_EXCEPTION_REGION();
- // Return immediately if no scene is active
- if ( nullptr == pimpl->mScene ) {
- return nullptr;
- }
- // If no flags are given, return the current scene with no further action
- if (nullptr == rootProcess) {
- return pimpl->mScene;
- }
- // In debug builds: run basic flag validation
- ASSIMP_LOG_INFO( "Entering customized post processing pipeline" );
- #ifndef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
- // The ValidateDS process plays an exceptional role. It isn't contained in the global
- // list of post-processing steps, so we need to call it manually.
- if ( requestValidation )
- {
- ValidateDSProcess ds;
- ds.ExecuteOnScene( this );
- if ( !pimpl->mScene ) {
- return nullptr;
- }
- }
- #endif // no validation
- #ifdef ASSIMP_BUILD_DEBUG
- if ( pimpl->bExtraVerbose )
- {
- #ifdef ASSIMP_BUILD_NO_VALIDATEDS_PROCESS
- ASSIMP_LOG_ERROR( "Verbose Import is not available due to build settings" );
- #endif // no validation
- }
- #else
- if ( pimpl->bExtraVerbose ) {
- ASSIMP_LOG_WARN( "Not a debug build, ignoring extra verbose setting" );
- }
- #endif // ! DEBUG
- std::unique_ptr<Profiler> profiler(GetPropertyInteger(AI_CONFIG_GLOB_MEASURE_TIME, 0) ? new Profiler() : nullptr);
- if ( profiler ) {
- profiler->BeginRegion( "postprocess" );
- }
- rootProcess->ExecuteOnScene( this );
- if ( profiler ) {
- profiler->EndRegion( "postprocess" );
- }
- // If the extra verbose mode is active, execute the ValidateDataStructureStep again - after each step
- if ( pimpl->bExtraVerbose || requestValidation ) {
- ASSIMP_LOG_DEBUG( "Verbose Import: revalidating data structures" );
- ValidateDSProcess ds;
- ds.ExecuteOnScene( this );
- if ( !pimpl->mScene ) {
- ASSIMP_LOG_ERROR( "Verbose Import: failed to revalidate data structures" );
- }
- }
- // clear any data allocated by post-process steps
- pimpl->mPPShared->Clean();
- ASSIMP_LOG_INFO( "Leaving customized post processing pipeline" );
- ASSIMP_END_EXCEPTION_REGION( const aiScene* );
- return pimpl->mScene;
- }
- // ------------------------------------------------------------------------------------------------
- // Helper function to check whether an extension is supported by ASSIMP
- bool Importer::IsExtensionSupported(const char* szExtension) const {
- return nullptr != GetImporter(szExtension);
- }
- // ------------------------------------------------------------------------------------------------
- size_t Importer::GetImporterCount() const {
- ai_assert(nullptr != pimpl);
- return pimpl->mImporter.size();
- }
- // ------------------------------------------------------------------------------------------------
- const aiImporterDesc* Importer::GetImporterInfo(size_t index) const {
- ai_assert(nullptr != pimpl);
- if (index >= pimpl->mImporter.size()) {
- return nullptr;
- }
- return pimpl->mImporter[index]->GetInfo();
- }
- // ------------------------------------------------------------------------------------------------
- BaseImporter* Importer::GetImporter (size_t index) const {
- ai_assert(nullptr != pimpl);
- if (index >= pimpl->mImporter.size()) {
- return nullptr;
- }
- return pimpl->mImporter[index];
- }
- // ------------------------------------------------------------------------------------------------
- // Find a loader plugin for a given file extension
- BaseImporter* Importer::GetImporter (const char* szExtension) const {
- ai_assert(nullptr != pimpl);
- return GetImporter(GetImporterIndex(szExtension));
- }
- // ------------------------------------------------------------------------------------------------
- // Find a loader plugin for a given file extension
- size_t Importer::GetImporterIndex (const char* szExtension) const {
- ai_assert(nullptr != pimpl);
- ai_assert(nullptr != szExtension);
- ASSIMP_BEGIN_EXCEPTION_REGION();
- // skip over wild-card and dot characters at string head --
- for ( ; *szExtension == '*' || *szExtension == '.'; ++szExtension );
- std::string ext(szExtension);
- if (ext.empty()) {
- return static_cast<size_t>(-1);
- }
- ext = ai_tolower(ext);
- std::set<std::string> str;
- for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
- str.clear();
- (*i)->GetExtensionList(str);
- for (std::set<std::string>::const_iterator it = str.begin(); it != str.end(); ++it) {
- if (ext == *it) {
- return std::distance(static_cast< std::vector<BaseImporter*>::const_iterator >(pimpl->mImporter.begin()), i);
- }
- }
- }
- ASSIMP_END_EXCEPTION_REGION(size_t);
- return static_cast<size_t>(-1);
- }
- // ------------------------------------------------------------------------------------------------
- // Helper function to build a list of all file extensions supported by ASSIMP
- void Importer::GetExtensionList(aiString& szOut) const {
- ai_assert(nullptr != pimpl);
- ASSIMP_BEGIN_EXCEPTION_REGION();
- std::set<std::string> str;
- for (std::vector<BaseImporter*>::const_iterator i = pimpl->mImporter.begin();i != pimpl->mImporter.end();++i) {
- (*i)->GetExtensionList(str);
- }
- // List can be empty
- if( !str.empty() ) {
- for (std::set<std::string>::const_iterator it = str.begin();; ) {
- szOut.Append("*.");
- szOut.Append((*it).c_str());
- if (++it == str.end()) {
- break;
- }
- szOut.Append(";");
- }
- }
- ASSIMP_END_EXCEPTION_REGION(void);
- }
- // ------------------------------------------------------------------------------------------------
- // Set a configuration property
- bool Importer::SetPropertyInteger(const char* szName, int iValue) {
- ai_assert(nullptr != pimpl);
- bool existing;
- ASSIMP_BEGIN_EXCEPTION_REGION();
- existing = SetGenericProperty<int>(pimpl->mIntProperties, szName,iValue);
- ASSIMP_END_EXCEPTION_REGION(bool);
- return existing;
- }
- // ------------------------------------------------------------------------------------------------
- // Set a configuration property
- bool Importer::SetPropertyFloat(const char* szName, ai_real iValue) {
- ai_assert(nullptr != pimpl);
- bool existing;
- ASSIMP_BEGIN_EXCEPTION_REGION();
- existing = SetGenericProperty<ai_real>(pimpl->mFloatProperties, szName,iValue);
- ASSIMP_END_EXCEPTION_REGION(bool);
- return existing;
- }
- // ------------------------------------------------------------------------------------------------
- // Set a configuration property
- bool Importer::SetPropertyString(const char* szName, const std::string& value) {
- ai_assert(nullptr != pimpl);
- bool existing;
- ASSIMP_BEGIN_EXCEPTION_REGION();
- existing = SetGenericProperty<std::string>(pimpl->mStringProperties, szName,value);
- ASSIMP_END_EXCEPTION_REGION(bool);
- return existing;
- }
- // ------------------------------------------------------------------------------------------------
- // Set a configuration property
- bool Importer::SetPropertyMatrix(const char* szName, const aiMatrix4x4& value) {
- ai_assert(nullptr != pimpl);
- bool existing;
- ASSIMP_BEGIN_EXCEPTION_REGION();
- existing = SetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties, szName,value);
- ASSIMP_END_EXCEPTION_REGION(bool);
- return existing;
- }
- // ------------------------------------------------------------------------------------------------
- // Set a configuration property
- bool Importer::SetPropertyPointer(const char* szName, void* value) {
- ai_assert(nullptr != pimpl);
- bool existing;
- ASSIMP_BEGIN_EXCEPTION_REGION();
- existing = SetGenericProperty<void*>(pimpl->mPointerProperties, szName,value);
- ASSIMP_END_EXCEPTION_REGION(bool);
- return existing;
- }
- // ------------------------------------------------------------------------------------------------
- // Get a configuration property
- int Importer::GetPropertyInteger(const char* szName, int iErrorReturn /*= 0xffffffff*/) const {
- ai_assert(nullptr != pimpl);
- return GetGenericProperty<int>(pimpl->mIntProperties,szName,iErrorReturn);
- }
- // ------------------------------------------------------------------------------------------------
- // Get a configuration property
- ai_real Importer::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*= 10e10*/) const {
- ai_assert(nullptr != pimpl);
- return GetGenericProperty<ai_real>(pimpl->mFloatProperties,szName,iErrorReturn);
- }
- // ------------------------------------------------------------------------------------------------
- // Get a configuration property
- std::string Importer::GetPropertyString(const char* szName, const std::string& iErrorReturn /*= ""*/) const {
- ai_assert(nullptr != pimpl);
- return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
- }
- // ------------------------------------------------------------------------------------------------
- // Get a configuration property
- aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const {
- ai_assert(nullptr != pimpl);
- return GetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties,szName,iErrorReturn);
- }
- // ------------------------------------------------------------------------------------------------
- // Get a configuration property
- void* Importer::GetPropertyPointer(const char* szName, void* iErrorReturn /*= nullptr*/) const {
- ai_assert(nullptr != pimpl);
- return GetGenericProperty<void*>(pimpl->mPointerProperties,szName,iErrorReturn);
- }
- // ------------------------------------------------------------------------------------------------
- // Get the memory requirements of a single node
- inline
- void AddNodeWeight(unsigned int& iScene,const aiNode* pcNode) {
- if ( nullptr == pcNode ) {
- return;
- }
- iScene += sizeof(aiNode);
- iScene += sizeof(unsigned int) * pcNode->mNumMeshes;
- iScene += sizeof(void*) * pcNode->mNumChildren;
- for (unsigned int i = 0; i < pcNode->mNumChildren;++i) {
- AddNodeWeight(iScene,pcNode->mChildren[i]);
- }
- }
- // ------------------------------------------------------------------------------------------------
- // Get the memory requirements of the scene
- void Importer::GetMemoryRequirements(aiMemoryInfo& in) const {
- ai_assert(nullptr != pimpl);
- in = aiMemoryInfo();
- aiScene* mScene = pimpl->mScene;
- // return if we have no scene loaded
- if (!mScene)
- return;
- in.total = sizeof(aiScene);
- // add all meshes
- for (unsigned int i = 0; i < mScene->mNumMeshes;++i) {
- in.meshes += sizeof(aiMesh);
- if (mScene->mMeshes[i]->HasPositions()) {
- in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
- }
- if (mScene->mMeshes[i]->HasNormals()) {
- in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
- }
- if (mScene->mMeshes[i]->HasTangentsAndBitangents()) {
- in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices * 2;
- }
- for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS;++a) {
- if (mScene->mMeshes[i]->HasVertexColors(a)) {
- in.meshes += sizeof(aiColor4D) * mScene->mMeshes[i]->mNumVertices;
- } else {
- break;
- }
- }
- for (unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS;++a) {
- if (mScene->mMeshes[i]->HasTextureCoords(a)) {
- in.meshes += sizeof(aiVector3D) * mScene->mMeshes[i]->mNumVertices;
- } else {
- break;
- }
- }
- if (mScene->mMeshes[i]->HasBones()) {
- in.meshes += sizeof(void*) * mScene->mMeshes[i]->mNumBones;
- for (unsigned int p = 0; p < mScene->mMeshes[i]->mNumBones;++p) {
- in.meshes += sizeof(aiBone);
- in.meshes += mScene->mMeshes[i]->mBones[p]->mNumWeights * sizeof(aiVertexWeight);
- }
- }
- in.meshes += (sizeof(aiFace) + 3 * sizeof(unsigned int))*mScene->mMeshes[i]->mNumFaces;
- }
- in.total += in.meshes;
- // add all embedded textures
- for (unsigned int i = 0; i < mScene->mNumTextures;++i) {
- const aiTexture* pc = mScene->mTextures[i];
- in.textures += sizeof(aiTexture);
- if (pc->mHeight) {
- in.textures += 4 * pc->mHeight * pc->mWidth;
- } else {
- in.textures += pc->mWidth;
- }
- }
- in.total += in.textures;
- // add all animations
- for (unsigned int i = 0; i < mScene->mNumAnimations;++i) {
- const aiAnimation* pc = mScene->mAnimations[i];
- in.animations += sizeof(aiAnimation);
- // add all bone anims
- for (unsigned int a = 0; a < pc->mNumChannels; ++a) {
- const aiNodeAnim* pc2 = pc->mChannels[a];
- in.animations += sizeof(aiNodeAnim);
- in.animations += pc2->mNumPositionKeys * sizeof(aiVectorKey);
- in.animations += pc2->mNumScalingKeys * sizeof(aiVectorKey);
- in.animations += pc2->mNumRotationKeys * sizeof(aiQuatKey);
- }
- }
- in.total += in.animations;
- // add all cameras and all lights
- in.total += in.cameras = sizeof(aiCamera) * mScene->mNumCameras;
- in.total += in.lights = sizeof(aiLight) * mScene->mNumLights;
- // add all nodes
- AddNodeWeight(in.nodes,mScene->mRootNode);
- in.total += in.nodes;
- // add all materials
- for (unsigned int i = 0; i < mScene->mNumMaterials;++i) {
- const aiMaterial* pc = mScene->mMaterials[i];
- in.materials += sizeof(aiMaterial);
- in.materials += pc->mNumAllocated * sizeof(void*);
- for (unsigned int a = 0; a < pc->mNumProperties;++a) {
- in.materials += pc->mProperties[a]->mDataLength;
- }
- }
- in.total += in.materials;
- }
|