diff --git a/code/Assimp.cpp b/code/Assimp.cpp index 676903d10..bb789bda4 100644 --- a/code/Assimp.cpp +++ b/code/Assimp.cpp @@ -38,42 +38,63 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -/** @file Implementation of the Plain-C API */ - - +/** @file Assimp.cpp + * @brief Implementation of the Plain-C API + */ #include "AssimpPCH.h" #include "../include/assimp.h" - -// public ASSIMP headers #include "../include/aiFileIO.h" #include "GenericProperty.h" -#if (defined AI_C_THREADSAFE) +// ------------------------------------------------------------------------------------------------ +#ifdef AI_C_THREADSAFE # include # include #endif - +// ------------------------------------------------------------------------------------------------ using namespace Assimp; - /** Stores the importer objects for all active import processes */ -typedef std::map< const aiScene*, Assimp::Importer* > ImporterMap; +typedef std::map ImporterMap; + +/** Stores the LogStream objects for all active C log streams */ +struct mpred { + bool operator () (const aiLogStream& s0, const aiLogStream& s1) const { + return s0.callback LogStreamMap; + +/** Stores the LogStream objects allocated by #aiGetPredefinedLogStream */ +typedef std::list PredefLogStreamMap; /** Local storage of all active import processes */ static ImporterMap gActiveImports; +/** Local storage of all active log streams */ +static LogStreamMap gActiveLogStreams; + +/** Local storage of LogStreams allocated by #aiGetPredefinedLogStream */ +static PredefLogStreamMap gPredefinedStreams; + /** Error message of the last failed import process */ static std::string gLastErrorString; -/** Configuration properties */ -static ImporterPimpl::IntPropertyMap gIntProperties; -static ImporterPimpl::FloatPropertyMap gFloatProperties; -static ImporterPimpl::StringPropertyMap gStringProperties; +/** Verbose logging active or not? */ +static aiBool gVerboseLogging = false; -#if (defined AI_C_THREADSAFE) +/** Configuration properties */ +static ImporterPimpl::IntPropertyMap gIntProperties; +static ImporterPimpl::FloatPropertyMap gFloatProperties; +static ImporterPimpl::StringPropertyMap gStringProperties; + +#ifdef AI_C_THREADSAFE /** Global mutex to manage the access to the importer map */ static boost::mutex gMutex; + +/** Global mutex to manage the access to the logstream map */ +static boost::mutex gLogStreamMutex; #endif class CIOSystemWrapper; @@ -90,46 +111,43 @@ public: : mFile(pFile) {} - // ------------------------------------------------------------------- + // ................................................................... size_t Read(void* pvBuffer, size_t pSize, - size_t pCount) - { + size_t pCount + ){ // need to typecast here as C has no void* return mFile->ReadProc(mFile,(char*)pvBuffer,pSize,pCount); } - // ------------------------------------------------------------------- + // ................................................................... size_t Write(const void* pvBuffer, size_t pSize, - size_t pCount) - { + size_t pCount + ){ // need to typecast here as C has no void* return mFile->WriteProc(mFile,(const char*)pvBuffer,pSize,pCount); } - // ------------------------------------------------------------------- + // ................................................................... aiReturn Seek(size_t pOffset, - aiOrigin pOrigin) - { + aiOrigin pOrigin + ){ return mFile->SeekProc(mFile,pOffset,pOrigin); } - // ------------------------------------------------------------------- - size_t Tell(void) const - { + // ................................................................... + size_t Tell(void) const { return mFile->TellProc(mFile); } - // ------------------------------------------------------------------- - size_t FileSize() const - { + // ................................................................... + size_t FileSize() const { return mFile->FileSizeProc(mFile); } - // ------------------------------------------------------------------- - void Flush () - { + // ................................................................... + void Flush () { return mFile->FlushProc(mFile); } @@ -137,20 +155,17 @@ private: aiFile* mFile; }; - // ------------------------------------------------------------------------------------------------ // Custom IOStream implementation for the C-API class CIOSystemWrapper : public IOSystem { public: - CIOSystemWrapper(aiFileIO* pFile) : mFileSystem(pFile) {} - // ------------------------------------------------------------------- - bool Exists( const char* pFile) const - { + // ................................................................... + bool Exists( const char* pFile) const { CIOSystemWrapper* pip = const_cast(this); IOStream* p = pip->Open(pFile); if (p){ @@ -160,40 +175,80 @@ public: return false; } - // ------------------------------------------------------------------- - char getOsSeparator() const - { - // FIXME + // ................................................................... + char getOsSeparator() const { +#ifndef _WIN32 return '/'; +#else + return '\\'; +#endif } - // ------------------------------------------------------------------- - IOStream* Open(const char* pFile,const char* pMode = "rb") - { + // ................................................................... + IOStream* Open(const char* pFile,const char* pMode = "rb") { aiFile* p = mFileSystem->OpenProc(mFileSystem,pFile,pMode); - if (!p)return NULL; + if (!p) { + return NULL; + } return new CIOStreamWrapper(p); } - // ------------------------------------------------------------------- - void Close( IOStream* pFile) - { - if (!pFile)return; + // ................................................................... + void Close( IOStream* pFile) { + if (!pFile) { + return; + } mFileSystem->CloseProc(mFileSystem,((CIOStreamWrapper*) pFile)->mFile); delete pFile; } +private: + aiFileIO* mFileSystem; +}; +// ------------------------------------------------------------------------------------------------ +// Custom LogStream implementation for the C-API +class LogToCallbackRedirector : public LogStream +{ +public: + LogToCallbackRedirector(const aiLogStream& s) + : stream (s) { + ai_assert(NULL != s.callback); + } + + ~LogToCallbackRedirector() { +#ifdef AI_C_THREADSAFE + boost::mutex::scoped_lock lock(gLogStreamMutex); +#endif + // (HACK) Check whether the 'stream.user' pointer points to a + // custom LogStream allocated by #aiGetPredefinedLogStream. + // In this case, we need to delete it, too. Of course, this + // might cause strange problems, but the chance is quite low. + + PredefLogStreamMap::iterator it = std::find(gPredefinedStreams.begin(), + gPredefinedStreams.end(), (Assimp::LogStream*)stream.user); + + if (it != gPredefinedStreams.end()) { + delete *it; + gPredefinedStreams.erase(it); + } + } + + /** @copydoc LogStream::write */ + void write(const char* message) { + stream.callback(message,stream.user); + } private: - - aiFileIO* mFileSystem; + aiLogStream stream; }; // ------------------------------------------------------------------------------------------------ void ReportSceneNotFoundError() { - DefaultLogger::get()->error("Unable to find the Importer instance for this scene. " - "Are you sure it has been created by aiImportFile(ex)(...)?"); + DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. " + "Are you playing fools with us? Don't mix cpp and c API. Thanks."); + + assert(false); } // ------------------------------------------------------------------------------------------------ @@ -208,19 +263,23 @@ const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, aiFileIO* pFS) { ai_assert(NULL != pFile); - // create an Importer for this file Assimp::Importer* imp = new Assimp::Importer; +#ifdef AI_C_THREADSAFE + boost::mutex::scoped_lock lock(gMutex); +#endif // copy the global property lists to the Importer instance - // (we are a friend of Importer) imp->pimpl->mIntProperties = gIntProperties; imp->pimpl->mFloatProperties = gFloatProperties; imp->pimpl->mStringProperties = gStringProperties; +#ifdef AI_C_THREADSAFE + lock.unlock(); +#endif + // setup a custom IO system if necessary - if (pFS) - { + if (pFS) { imp->SetIOHandler( new CIOSystemWrapper (pFS) ); } @@ -228,15 +287,13 @@ const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, const aiScene* scene = imp->ReadFile( pFile, pFlags); // if succeeded, place it in the collection of active processes - if( scene) - { -#if (defined AI_C_THREADSAFE) - boost::mutex::scoped_lock lock(gMutex); + if( scene) { +#ifdef AI_C_THREADSAFE + lock.lock(); #endif gActiveImports[scene] = imp; } - else - { + else { // if failed, extract error code and destroy the import gLastErrorString = imp->GetErrorString(); delete imp; @@ -250,18 +307,18 @@ const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags, // Releases all resources associated with the given import process. void aiReleaseImport( const aiScene* pScene) { - if (!pScene)return; + if (!pScene) { + return; + } - // lock the mutex -#if (defined AI_C_THREADSAFE) +#ifdef AI_C_THREADSAFE boost::mutex::scoped_lock lock(gMutex); #endif // find the importer associated with this data ImporterMap::iterator it = gActiveImports.find( pScene); // it should be there... else the user is playing fools with us - if( it == gActiveImports.end()) - { + if( it == gActiveImports.end()) { ReportSceneNotFoundError(); return; } @@ -271,6 +328,120 @@ void aiReleaseImport( const aiScene* pScene) gActiveImports.erase( it); } +// ------------------------------------------------------------------------------------------------ +ASSIMP_API const aiScene* aiApplyPostProcessing(const aiScene* pScene, + unsigned int pFlags) +{ +#ifdef AI_C_THREADSAFE + boost::mutex::scoped_lock lock(gMutex); +#endif + // find the importer associated with this data + ImporterMap::iterator it = gActiveImports.find( pScene); + // it should be there... else the user is playing fools with us + if( it == gActiveImports.end()) { + ReportSceneNotFoundError(); + return NULL; + } +#ifdef AI_C_THREADSAFE + lock.unlock(); +#endif + const aiScene* sc = it->second->ApplyPostProcessing(pFlags); +#ifdef AI_C_THREADSAFE + lock.lock(); +#endif + if (!sc) { + // kill the importer, the data dies with it + delete it->second; + gActiveImports.erase( it); + return NULL; + } + + return it->first; +} + +// ------------------------------------------------------------------------------------------------ +void CallbackToLogRedirector (const char* msg, char* dt) +{ + ai_assert(NULL != msg && NULL != dt); + LogStream* s = (LogStream*)dt; + + s->write(msg); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API aiLogStream aiGetPredefinedLogStream(aiDefaultLogStream pStream,const char* file) +{ + aiLogStream sout; + LogStream* stream = LogStream::createDefaultStream(pStream,file); + if (!stream) { + sout.callback = NULL; + } + else { + sout.callback = &CallbackToLogRedirector; + sout.user = (char*)stream; + } + gPredefinedStreams.push_back(stream); + return sout; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiAttachLogStream( const aiLogStream* stream ) +{ +#ifdef AI_C_THREADSAFE + boost::mutex::scoped_lock lock(gLogStreamMutex); +#endif + LogStream* lg = new LogToCallbackRedirector(*stream); + gActiveLogStreams[*stream] = lg; + + if (DefaultLogger::isNullLogger()) { + DefaultLogger::create(NULL,(gVerboseLogging == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL)); + } + DefaultLogger::get()->attachStream(lg); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API aiReturn aiDetachLogStream( const aiLogStream* stream) +{ +#ifdef AI_C_THREADSAFE + boost::mutex::scoped_lock lock(gLogStreamMutex); +#endif + // find the logstream associated with this data + LogStreamMap::iterator it = gActiveLogStreams.find( *stream); + // it should be there... else the user is playing fools with us + if( it == gActiveLogStreams.end()) { + return AI_FAILURE; + } + delete it->second; + gActiveLogStreams.erase( it); + + if (gActiveLogStreams.empty()) { + DefaultLogger::kill(); + } + return AI_SUCCESS; +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiDetachAllLogStreams(void) +{ +#ifdef AI_C_THREADSAFE + boost::mutex::scoped_lock lock(gLogStreamMutex); +#endif + for (LogStreamMap::iterator it = gActiveLogStreams.begin(); it != gActiveLogStreams.end(); ++it) { + delete it->second; + } + gActiveLogStreams.clear(); + DefaultLogger::kill(); +} + +// ------------------------------------------------------------------------------------------------ +ASSIMP_API void aiEnableVerboseLogging(aiBool d) +{ + if (!DefaultLogger::isNullLogger()) { + DefaultLogger::get()->setLogSeverity((d == AI_TRUE ? Logger::VERBOSE : Logger::NORMAL)); + } + gVerboseLogging = d; +} + // ------------------------------------------------------------------------------------------------ // Returns the error text of the last failed import process. const char* aiGetErrorString() @@ -280,25 +451,20 @@ const char* aiGetErrorString() // ------------------------------------------------------------------------------------------------ // Returns the error text of the last failed import process. -int aiIsExtensionSupported(const char* szExtension) +aiBool aiIsExtensionSupported(const char* szExtension) { ai_assert(NULL != szExtension); - - // lock the mutex -#if (defined AI_C_THREADSAFE) +#ifdef AI_C_THREADSAFE boost::mutex::scoped_lock lock(gMutex); #endif if (!gActiveImports.empty()) { - return (int)((*(gActiveImports.begin())).second->IsExtensionSupported( szExtension )); + return ((*(gActiveImports.begin())).second->IsExtensionSupported( szExtension )) ? AI_TRUE : AI_FALSE; } - // need to create a temporary Importer instance. - // TODO: Find a better solution ... - Assimp::Importer* pcTemp = new Assimp::Importer(); - int i = (int)pcTemp->IsExtensionSupported(std::string(szExtension)); - delete pcTemp; - return i; + // fixme: no need to create a temporary Importer instance just for that .. + Assimp::Importer tmp; + return tmp.IsExtensionSupported(std::string(szExtension)) ? AI_TRUE : AI_FALSE; } // ------------------------------------------------------------------------------------------------ @@ -306,9 +472,7 @@ int aiIsExtensionSupported(const char* szExtension) void aiGetExtensionList(aiString* szOut) { ai_assert(NULL != szOut); - - // lock the mutex -#if (defined AI_C_THREADSAFE) +#ifdef AI_C_THREADSAFE boost::mutex::scoped_lock lock(gMutex); #endif @@ -317,65 +481,85 @@ void aiGetExtensionList(aiString* szOut) (*(gActiveImports.begin())).second->GetExtensionList(*szOut); return; } - // need to create a temporary Importer instance. - // TODO: Find a better solution ... - Assimp::Importer* pcTemp = new Assimp::Importer(); - pcTemp->GetExtensionList(*szOut); - delete pcTemp; + // fixme: no need to create a temporary Importer instance just for that .. + Assimp::Importer tmp; + tmp.GetExtensionList(*szOut); } // ------------------------------------------------------------------------------------------------ +// Get the memory requirements for a particular import. void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn, C_STRUCT aiMemoryInfo* in) { -// lock the mutex -#if (defined AI_C_THREADSAFE) +#ifdef AI_C_THREADSAFE boost::mutex::scoped_lock lock(gMutex); #endif // find the importer associated with this data ImporterMap::iterator it = gActiveImports.find( pIn); // it should be there... else the user is playing fools with us - if( it == gActiveImports.end()) - { + if( it == gActiveImports.end()) { ReportSceneNotFoundError(); return; } // get memory statistics +#ifdef AI_C_THREADSAFE + lock.unlock(); +#endif it->second->GetMemoryRequirements(*in); } // ------------------------------------------------------------------------------------------------ +// Importer::SetPropertyInteger ASSIMP_API void aiSetImportPropertyInteger(const char* szName, int value) { +#ifdef AI_C_THREADSAFE + boost::mutex::scoped_lock lock(gMutex); +#endif SetGenericProperty(gIntProperties,szName,value,NULL); } // ------------------------------------------------------------------------------------------------ +// Importer::SetPropertyFloat ASSIMP_API void aiSetImportPropertyFloat(const char* szName, float value) { +#ifdef AI_C_THREADSAFE + boost::mutex::scoped_lock lock(gMutex); +#endif SetGenericProperty(gFloatProperties,szName,value,NULL); } // ------------------------------------------------------------------------------------------------ +// Importer::SetPropertyString ASSIMP_API void aiSetImportPropertyString(const char* szName, const C_STRUCT aiString* st) { - if (!st)return; - + if (!st) { + return; + } +#ifdef AI_C_THREADSAFE + boost::mutex::scoped_lock lock(gMutex); +#endif SetGenericProperty(gStringProperties,szName, std::string( st->data ),NULL); } // ------------------------------------------------------------------------------------------------ +// Rotation matrix to quaternion ASSIMP_API void aiCreateQuaternionFromMatrix(aiQuaternion* quat,const aiMatrix3x3* mat) { + ai_assert(NULL != quat && NULL != mat); *quat = aiQuaternion(*mat); } // ------------------------------------------------------------------------------------------------ -ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat, aiVector3D* scaling, - aiQuaternion* rotation,aiVector3D* position) +// Affline matrix decomposition +ASSIMP_API void aiDecomposeMatrix(const aiMatrix4x4* mat,aiVector3D* scaling, + aiQuaternion* rotation, + aiVector3D* position) { + ai_assert(NULL != rotation && NULL != position && NULL != scaling && NULL != mat); mat->Decompose(*scaling,*rotation,*position); } + + diff --git a/code/DefaultLogger.cpp b/code/DefaultLogger.cpp index 099b0f2e6..9a9b95884 100644 --- a/code/DefaultLogger.cpp +++ b/code/DefaultLogger.cpp @@ -88,14 +88,14 @@ struct LogStreamInfo // ---------------------------------------------------------------------------------- // Construct a default log stream -LogStream* LogStream::createDefaultStream(DefaultLogStreams streams, +LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, const char* name /*= "AssimpLog.txt"*/, IOSystem* io /*= NULL*/) { switch (streams) { // This is a platform-specific feature - case DLS_DEBUGGER: + case aiDefaultLogStream_DEBUGGER: #ifdef WIN32 return new Win32DebugLogStream(); #else @@ -103,11 +103,11 @@ LogStream* LogStream::createDefaultStream(DefaultLogStreams streams, #endif // Platform-independent default streams - case DLS_CERR: + case aiDefaultLogStream_STDERR: return new StdOStreamLogStream(std::cerr); - case DLS_COUT: + case aiDefaultLogStream_STDOUT: return new StdOStreamLogStream(std::cout); - case DLS_FILE: + case aiDefaultLogStream_FILE: return (name && *name ? new FileLogStream(name,io) : NULL); default: // We don't know this default log stream, so raise an assertion @@ -123,7 +123,7 @@ LogStream* LogStream::createDefaultStream(DefaultLogStreams streams, // Creates the only singleton instance Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/, LogSeverity severity /*= NORMAL*/, - unsigned int defStreams /*= DLS_DEBUGGER | DLS_FILE*/, + unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/, IOSystem* io /*= NULL*/) { // enter the mutex here to avoid concurrency problems @@ -138,20 +138,20 @@ Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/, // Attach default log streams // Stream the log to the MSVC debugger? - if (defStreams & DLS_DEBUGGER) - m_pLogger->attachStream( LogStream::createDefaultStream(DLS_DEBUGGER)); + if (defStreams & aiDefaultLogStream_DEBUGGER) + m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER)); // Stream the log to COUT? - if (defStreams & DLS_COUT) - m_pLogger->attachStream( LogStream::createDefaultStream(DLS_COUT)); + if (defStreams & aiDefaultLogStream_STDOUT) + m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT)); // Stream the log to CERR? - if (defStreams & DLS_CERR) - m_pLogger->attachStream( LogStream::createDefaultStream(DLS_CERR)); + if (defStreams & aiDefaultLogStream_STDERR) + m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR)); // Stream the log to a file - if (defStreams & DLS_FILE && name && *name) - m_pLogger->attachStream( LogStream::createDefaultStream(DLS_FILE,name,io)); + if (defStreams & aiDefaultLogStream_FILE && name && *name) + m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io)); return m_pLogger; } diff --git a/code/PlyLoader.cpp b/code/PlyLoader.cpp index e2cb649d9..806d3c750 100644 --- a/code/PlyLoader.cpp +++ b/code/PlyLoader.cpp @@ -794,38 +794,39 @@ void PLYImporter::LoadFaces(std::vector* pvOut) { // normally we have only one triangle strip instance where // a value of -1 indicates a restart of the strip - for (std::vector::const_iterator i = pcList->alInstances.begin(); - i != pcList->alInstances.end();++i) - { + bool flip = false; + for (std::vector::const_iterator i = pcList->alInstances.begin();i != pcList->alInstances.end();++i) { const std::vector& quak = (*i).alProperties[iProperty].avList; pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); int aiTable[2] = {-1,-1}; for (std::vector::const_iterator a = quak.begin();a != quak.end();++a) { const int p = PLY::PropertyInstance::ConvertTo(*a,eType); - if (-1 == p) - { + + if (-1 == p) { // restart the strip ... aiTable[0] = aiTable[1] = -1; + flip = false; continue; } - if (-1 == aiTable[0]) - { + if (-1 == aiTable[0]) { aiTable[0] = p; continue; } - if (-1 == aiTable[1]) - { + if (-1 == aiTable[1]) { aiTable[1] = p; continue; } pvOut->push_back(PLY::Face()); PLY::Face& sFace = pvOut->back(); - sFace.mIndices.push_back((unsigned int)aiTable[0]); - sFace.mIndices.push_back((unsigned int)aiTable[1]); - sFace.mIndices.push_back((unsigned int)p); - + sFace.mIndices[0] = aiTable[0]; + sFace.mIndices[1] = aiTable[1]; + sFace.mIndices[2] = p; + if ((flip = !flip)) { + std::swap(sFace.mIndices[0],sFace.mIndices[1]); + } + aiTable[0] = aiTable[1]; aiTable[1] = p; } diff --git a/doc/AssimpDoc_Html/AssimpDoc.chm b/doc/AssimpDoc_Html/AssimpDoc.chm index 5fcd0768a..009e44a40 100644 Binary files a/doc/AssimpDoc_Html/AssimpDoc.chm and b/doc/AssimpDoc_Html/AssimpDoc.chm differ diff --git a/include/DefaultLogger.h b/include/DefaultLogger.h index eeee24181..0f814aec6 100644 --- a/include/DefaultLogger.h +++ b/include/DefaultLogger.h @@ -37,7 +37,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ---------------------------------------------------------------------- */ - /** @file DefaultLogger.h */ @@ -54,100 +53,127 @@ namespace Assimp { class IOStream; struct LogStreamInfo; -//! Default log file name +/** default name of logfile */ #define ASSIMP_DEFAULT_LOG_NAME "AssimpLog.txt" // ------------------------------------------------------------------------------------ -/** @class DefaultLogger - * @brief Default logging implementation. +/** @class DefaultLogger + * @brief Primary logging implementation of Assimp. * - * todo .... move static stuff to Logger where it belongs to. + * The library stores its primary #Logger as a static member of this class. + * #get() returns this primary logger. By default the underlying implementation is + * just a #NullLogger which rejects all log messages. By calling #create(), logging + * is turned on. To capture the log output multiple log streams (#LogStream) can be + * attach to the logger. Some default streams for common streaming locations (such as + * a file, std::cout, OutputDebugString()) are also provided. + * + * If you wish to customize the logging at an even deeper level supply your own + * implementation of #Logger to #set(). + * @note The whole logging stuff causes a small extra overhead for all imports. */ class ASSIMP_API DefaultLogger : - public Logger -{ + public Logger { public: - /** @brief Creates a default logging instance (DefaultLogger) - * @param name Name for log file. Only valid in combination - * with the DLS_FILE flag. - * @param severity Log severity, VERBOSE will activate debug messages - * @param defStreams Default log streams to be attached. Bitwise - * combination of the DefaultLogStreams enumerated - * values. If DLS_FILE is specified, but an empty - * string is passed for 'name' no log file is created. - * @param io IOSystem to be used to open external files (such as the - * log file). Pass NULL for the default implementation. + // ---------------------------------------------------------------------- + /** @brief Creates a logging instance. + * @param name Name for log file. Only valid in combination + * with the aiDefaultLogStream_FILE flag. + * @param severity Log severity, VERBOSE turns on debug messages + * @param defStreams Default log streams to be attached. Any bitwise + * combination of the aiDefaultLogStream enumerated values. + * If #aiDefaultLogStream_FILE is specified but an empty string is + * passed for 'name', no log file is created at all. + * @param io IOSystem to be used to open external files (such as the + * log file). Pass NULL to rely on the default implementation. * - * This replaces the default NullLogger with a DefaultLogger instance. + * This replaces the default #NullLogger with a #DefaultLogger instance. + * @note You can't */ static Logger *create(const char* name = ASSIMP_DEFAULT_LOG_NAME, LogSeverity severity = NORMAL, - unsigned int defStreams = DLS_DEBUGGER | DLS_FILE, + unsigned int defStreams = aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE, IOSystem* io = NULL); - /** @brief Setup a custom implementation of the Logger interface as - * default logger. + // ---------------------------------------------------------------------- + /** @brief Setup a custom #Logger implementation. * - * Use this if the provided DefaultLogger class doesn't fit into + * Use this if the provided #DefaultLogger class doesn't fit into * your needs. If the provided message formatting is OK for you, - * it is easier to use create() to create a DefaultLogger and to attach - * your own custom output streams to it than using this method. + * it's much easier to use #create() and to attach your own custom + * output streams to it. * @param logger Pass NULL to setup a default NullLogger */ static void set (Logger *logger); + // ---------------------------------------------------------------------- /** @brief Getter for singleton instance - * @return Only instance. This is never null, but it could be a + * @return Only instance. This is never null, but it could be a * NullLogger. Use isNullLogger to check this. */ static Logger *get(); - /** @brief Return whether a default NullLogger is currently active - * @return true if the current logger is a NullLogger. - * Use create() or set() to setup a custom logger. + // ---------------------------------------------------------------------- + /** @brief Return whether a #NullLogger is currently active + * @return true if the current logger is a #NullLogger. + * Use create() or set() to setup a logger that does actually do + * something else than just rejecting all log messages. */ static bool isNullLogger(); - /** @brief Will kill the singleton instance and setup a NullLogger as logger */ + // ---------------------------------------------------------------------- + /** @brief Kills the current singleton logger and replaces it with a + * #NullLogger instance. + */ static void kill(); - /** @brief Attach a stream to the logger. */ - /* override */ bool attachStream(LogStream *pStream, + // ---------------------------------------------------------------------- + /** @copydoc Logger::attachStream + */ + bool attachStream(LogStream *pStream, unsigned int severity); - /** @brief Detach a still attached stream from logger */ - /* override */ bool detatchStream(LogStream *pStream, + // ---------------------------------------------------------------------- + /** @copydoc Logger::detatchStream + */ + bool detatchStream(LogStream *pStream, unsigned int severity); + private: - /** @brief Logs debug infos, only been written when severity level VERBOSE is set */ - /* override */ void OnDebug(const char* message); - - /** @brief Logs an info message */ - /* override */ void OnInfo(const char* message); - - /** @brief Logs a warning message */ - /* override */ void OnWarn(const char* message); - - /** @brief Logs an error message */ - /* override */ void OnError(const char* message); - - - /** @brief Private construction for internal use by create(). + // ---------------------------------------------------------------------- + /** @briefPrivate construction for internal use by create(). * @param severity Logging granularity */ DefaultLogger(LogSeverity severity); - /** @brief Destructor */ + // ---------------------------------------------------------------------- + /** @briefDestructor */ ~DefaultLogger(); +private: + + /** @brief Logs debug infos, only been written when severity level VERBOSE is set */ + void OnDebug(const char* message); + + /** @brief Logs an info message */ + void OnInfo(const char* message); + + /** @brief Logs a warning message */ + void OnWarn(const char* message); + + /** @brief Logs an error message */ + void OnError(const char* message); + + // ---------------------------------------------------------------------- /** @brief Writes a message to all streams */ void WriteToStreams(const char* message, ErrorSeverity ErrorSev ); - /** @brief Returns the thread id. - * @remark This is an OS specific feature, if not supported, a zero will be returned. + // ---------------------------------------------------------------------- + /** @brief Returns the thread id. + * @note This is an OS specific feature, if not supported, a + * zero will be returned. */ unsigned int GetThreadID(); diff --git a/include/LogStream.h b/include/LogStream.h index f2b4d6114..670c0747e 100644 --- a/include/LogStream.h +++ b/include/LogStream.h @@ -44,49 +44,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_LOGSTREAM_H #define INCLUDED_AI_LOGSTREAM_H - #include "aiTypes.h" - namespace Assimp { class IOSystem; -// ------------------------------------------------------------------------------------ -/** @enum DefaultLogStreams - * @brief Enumerates default log streams supported by DefaultLogger - * - * These streams can be allocated using LogStream::createDefaultStream. - */ -enum DefaultLogStreams -{ - // Stream the log to a file - DLS_FILE = 0x1, - - // Stream the log to std::cout - DLS_COUT = 0x2, - - // Stream the log to std::cerr - DLS_CERR = 0x4, - - // MSVC only: Stream the log the the debugger - DLS_DEBUGGER = 0x8 -}; // !enum DefaultLogStreams - // ------------------------------------------------------------------------------------ /** @class LogStream - * @brief Abstract interface for log stream implementations. + * @brief Abstract interface for log stream implementations. * - * Several default implementations are provided, see DefaultLogStreams for more - * details. In most cases it shouldn't be necessary to write a custom log stream. + * Several default implementations are provided, see #aiDefaultLogStream for more + * details. Writing your own implementation of LogStream is just necessary if these + * are not enough for your purposes. */ -class ASSIMP_API LogStream : public Intern::AllocateFromAssimpHeap -{ +class ASSIMP_API LogStream + : public Intern::AllocateFromAssimpHeap { protected: /** @brief Default constructor */ - LogStream(); - + LogStream() { + } public: /** @brief Virtual destructor */ - virtual ~LogStream(); + virtual ~LogStream() { + } // ------------------------------------------------------------------- /** @brief Overwrite this for your own output methods @@ -94,39 +73,25 @@ public: * Log messages *may* consist of multiple lines and you shouldn't * expect a consistent formatting. If you want custom formatting * (e.g. generate HTML), supply a custom instance of Logger to - * DefaultLogger:set(). Usually you can *expect* that a log message - * is exactly one line long, terminated with a single \n sequence. - * @param message Message to be written + * #DefaultLogger:set(). Usually you can *expect* that a log message + * is exactly one line and terminated with a single \n character. + * @param message Message to be written */ virtual void write(const char* message) = 0; // ------------------------------------------------------------------- /** @brief Creates a default log stream * @param streams Type of the default stream - * @param name For DLS_FILE: name of the output file - * @param io For DLS_FILE: IOSystem to be used to open the output file. - * Pass NULL for the default implementation. - * @return New LogStream instance - you're responsible for it's destruction! + * @param name For aiDefaultLogStream_FILE: name of the output file + * @param io For aiDefaultLogStream_FILE: IOSystem to be used to open the output + * file. Pass NULL for the default implementation. + * @return New LogStream instance. */ - static LogStream* createDefaultStream(DefaultLogStreams streams, + static LogStream* createDefaultStream(aiDefaultLogStream stream, const char* name = "AssimpLog.txt", - IOSystem* io = NULL); + IOSystem* io = NULL); + }; // !class LogStream - -// ------------------------------------------------------------------------------------ -// Default constructor -inline LogStream::LogStream() -{ - // empty -} - -// ------------------------------------------------------------------------------------ -// Virtual destructor -inline LogStream::~LogStream() -{ - // empty -} - // ------------------------------------------------------------------------------------ } // Namespace Assimp diff --git a/include/Logger.h b/include/Logger.h index 45dff2cc0..0ece1ec49 100644 --- a/include/Logger.h +++ b/include/Logger.h @@ -41,31 +41,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /** @file Logger.h * @brief Abstract base class 'Logger', base of the logging system. */ - #ifndef INCLUDED_AI_LOGGER_H #define INCLUDED_AI_LOGGER_H #include "aiTypes.h" namespace Assimp { - class LogStream; -// maximum length of a log message. Longer messages are rejected. +// Maximum length of a log message. Longer messages are rejected. #define MAX_LOG_MESSAGE_LENGTH 1024u // ---------------------------------------------------------------------------------- /** @class Logger * @brief Abstract interface for logger implementations. - * Assimp provides a default implementation ('DefaultLogger'). + * Assimp provides a default implementation and uses it for almost all + * logging stuff ('DefaultLogger'). This class defines just basic logging + * behaviour and is not of interest for you. */ -class ASSIMP_API Logger : public Intern::AllocateFromAssimpHeap +class ASSIMP_API Logger + : public Intern::AllocateFromAssimpHeap { public: + + // ---------------------------------------------------------------------- /** @enum LogSeverity * @brief Log severity to describe the granularity of logging. - * - * This is a general property of a Logger instance, NORMAL means - * that debug messages are rejected immediately. */ enum LogSeverity { @@ -73,6 +73,7 @@ public: VERBOSE //!< Debug infos will be logged, too }; + // ---------------------------------------------------------------------- /** @enum ErrorSeverity * @brief Description for severity of a log message. * @@ -93,35 +94,42 @@ public: /** @brief Virtual destructor */ virtual ~Logger(); + // ---------------------------------------------------------------------- /** @brief Writes a debug message - * @param message Debug message + * @param message Debug message */ void debug(const std::string &message); + // ---------------------------------------------------------------------- /** @brief Writes a info message - * @param message Info message + * @param message Info message */ void info(const std::string &message); + // ---------------------------------------------------------------------- /** @brief Writes a warning message - * @param message Warn message + * @param message Warn message */ void warn(const std::string &message); + // ---------------------------------------------------------------------- /** @brief Writes an error message - * @param message Error message + * @param message Error message */ void error(const std::string &message); + // ---------------------------------------------------------------------- /** @brief Set a new log severity. - * @param log_severity New severity for logging + * @param log_severity New severity for logging */ void setLogSeverity(LogSeverity log_severity); - /** @brief Get the current log severity + // ---------------------------------------------------------------------- + /** @brief Get the current log severity */ LogSeverity getLogSeverity() const; + // ---------------------------------------------------------------------- /** @brief Attach a new logstream * * The logger takes ownership of the stream and is responsible @@ -137,6 +145,7 @@ public: virtual bool attachStream(LogStream *pStream, unsigned int severity = DEBUGGING | ERR | WARN | INFO) = 0; + // ---------------------------------------------------------------------- /** @brief Detach a still attached stream from the logger (or * modify the filter flags bits) * @param pStream Logstream instance for detaching @@ -157,35 +166,39 @@ protected: /** Construction with a given log severity */ Logger(LogSeverity severity); - /** @brief Called as a request to write a specific debug message - * @param message Debug message. Never longer than - * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0'). - * @note The message string is only valid until the scope of - * the function is left. + // ---------------------------------------------------------------------- + /** @brief Called as a request to write a specific debug message + * @param message Debug message. Never longer than + * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0'). + * @note The message string is only valid until the scope of + * the function is left. */ virtual void OnDebug(const char* message)= 0; - /** @brief Called as a request to write a specific info message - * @param message Info message. Never longer than - * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0'). - * @note The message string is only valid until the scope of - * the function is left. + // ---------------------------------------------------------------------- + /** @brief Called as a request to write a specific info message + * @param message Info message. Never longer than + * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0'). + * @note The message string is only valid until the scope of + * the function is left. */ virtual void OnInfo(const char* message) = 0; - /** @brief Called as a request to write a specific warn message - * @param message Warn message. Never longer than - * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0'). - * @note The message string is only valid until the scope of - * the function is left. + // ---------------------------------------------------------------------- + /** @brief Called as a request to write a specific warn message + * @param message Warn message. Never longer than + * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0'). + * @note The message string is only valid until the scope of + * the function is left. */ virtual void OnWarn(const char* essage) = 0; - /** @brief Called as a request to write a specific error message - * @param message Error message. Never longer than - * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0'). - * @note The message string is only valid until the scope of - * the function is left. + // ---------------------------------------------------------------------- + /** @brief Called as a request to write a specific error message + * @param message Error message. Never longer than + * MAX_LOG_MESSAGE_LENGTH characters (exluding the '0'). + * @note The message string is only valid until the scope of + * the function is left. */ virtual void OnError(const char* message) = 0; diff --git a/include/NullLogger.h b/include/NullLogger.h index 0ef19f841..f1fb95a05 100644 --- a/include/NullLogger.h +++ b/include/NullLogger.h @@ -45,15 +45,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_NULLLOGGER_H #define INCLUDED_AI_NULLLOGGER_H -#include "../include/Logger.h" - +#include "Logger.h" namespace Assimp { - // --------------------------------------------------------------------------- /** @class NullLogger - * @brief Empty logging implementation. Does nothing. Used by default - * if the application hasn't specified a custom logger (or DefaultLogger) - * via DefaultLogger::set() or DefaultLogger::create(); + * @brief Empty logging implementation. + * + * Does nothing. Used by default if the application hasn't requested a + * custom logger via #DefaultLogger::set() or #DefaultLogger::create(); */ class ASSIMP_API NullLogger : public Logger { @@ -93,7 +92,5 @@ public: private: }; - } - #endif // !! AI_NULLLOGGER_H_INCLUDED diff --git a/include/aiFileIO.h b/include/aiFileIO.h index 262e43d58..c7ddd7ff4 100644 --- a/include/aiFileIO.h +++ b/include/aiFileIO.h @@ -40,18 +40,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file aiFileIO.h - * @brief Defines generic routines to access memory-mapped files + * @brief Defines generic C routines to access memory-mapped files */ - #ifndef AI_FILEIO_H_INC #define AI_FILEIO_H_INC #include "aiTypes.h" - #ifdef __cplusplus extern "C" { #endif - struct aiFileIO; struct aiFile; @@ -60,13 +57,13 @@ typedef size_t (*aiFileWriteProc) (C_STRUCT aiFile*, const char*, size_t, si typedef size_t (*aiFileReadProc) (C_STRUCT aiFile*, char*, size_t,size_t); typedef size_t (*aiFileTellProc) (C_STRUCT aiFile*); typedef void (*aiFileFlushProc) (C_STRUCT aiFile*); -typedef aiReturn (*aiFileSeek)(aiFile*, size_t, aiOrigin); +typedef aiReturn (*aiFileSeek)(C_STRUCT aiFile*, size_t, aiOrigin); // aiFileIO callbackss typedef aiFile* (*aiFileOpenProc) (C_STRUCT aiFileIO*, const char*, const char*); typedef void (*aiFileCloseProc) (C_STRUCT aiFileIO*, C_STRUCT aiFile*); -// represents user-defined data +// Represents user-defined data typedef char* aiUserData; // ---------------------------------------------------------------------------------- @@ -79,13 +76,15 @@ typedef char* aiUserData; */ struct aiFileIO { - //! Function used to open a new file + /** Function used to open a new file + */ aiFileOpenProc OpenProc; - //! Function used to close an existing file + /** Function used to close an existing file + */ aiFileCloseProc CloseProc; - //! User-defined data + /** User-defined, opaque data */ aiUserData UserData; }; @@ -93,44 +92,47 @@ struct aiFileIO /** @class aiFile * @brief Represents a read/write file * - * Actually, it is a data structure to wrap a set of fXXXX (e.g fopen) + * Actually, it's a data structure to wrap a set of fXXXX (e.g fopen) * replacement functions * * The default implementation of the functions utilizes the fXXX functions from * the CRT. However, you can supply a custom implementation to Assimp by - * also supplying a custom aiFileIO. Use this to enable reading from other sources, - * such as ZIPs or memory locations. + * delivering a custom aiFileIO. Use this to enable reading from other sources, + * such as ZIP archives or memory locations. */ struct aiFile { - //! Function used to read from a file + /** Callback to read from a file */ aiFileReadProc ReadProc; - //! Function used to write to a file + /** Callback to write to a file */ aiFileWriteProc WriteProc; - //! Function used to retrieve the current - //! position of the file cursor (ftell()) + /** Callback to retrieve the current position of + * the file cursor (ftell()) + */ aiFileTellProc TellProc; - //! Function used to retrieve the size of the file, in bytes + /** Callback to retrieve the size of the file, + * in bytes + */ aiFileTellProc FileSizeProc; - //! Function used to set the current position - //! of the file cursor (fseek()) + /** Callback to set the current position + * of the file cursor (fseek()) + */ aiFileSeek SeekProc; - //! Function used to flush the file contents + /** Callback to flush the file contents + */ aiFileFlushProc FlushProc; - //! User-defined data + /** User-defined, opaque data + */ aiUserData UserData; }; - #ifdef __cplusplus } #endif - - #endif // AI_FILEIO_H_INC diff --git a/include/aiMaterial.h b/include/aiMaterial.h index 139c8ced2..d4851fc4a 100644 --- a/include/aiMaterial.h +++ b/include/aiMaterial.h @@ -56,47 +56,6 @@ extern "C" { #define AI_DEFAULT_MATERIAL_NAME "DefaultMaterial" #define AI_DEFAULT_TEXTURED_MATERIAL_NAME "TexturedDefaultMaterial" -// --------------------------------------------------------------------------- -/** @brief A very primitive RTTI system to store the data type of a - * material property. - */ -enum aiPropertyTypeInfo -{ - /** Array of single-precision (32 Bit) floats - * - * It is possible to use aiGetMaterialInteger[Array]() (or the C++-API - * aiMaterial::Get()) to query properties stored in floating-point format. - * The material system performs the type conversion automatically. - */ - aiPTI_Float = 0x1, - - /** The material property is an aiString. - * - * Arrays of strings aren't possible, aiGetMaterialString() (or the - * C++-API aiMaterial::Get()) *must* be used to query a string property. - */ - aiPTI_String = 0x3, - - /** Array of (32 Bit) integers - * - * It is possible to use aiGetMaterialFloat[Array]() (or the C++-API - * aiMaterial::Get()) to query properties stored in integer format. - * The material system performs the type conversion automatically. - */ - aiPTI_Integer = 0x4, - - - /** Simple binary buffer, content undefined. Not convertible to anything. - */ - aiPTI_Buffer = 0x5, - - - /** This value is not used. It is just there to force the - * compiler to map this enum to a 32 Bit integer. - */ - _aiPTI_Force32Bit = 0x9fffffff -}; - // --------------------------------------------------------------------------- /** @brief Defines how the Nth texture of a specific type is combined with * the result of all previous layers. @@ -420,12 +379,11 @@ enum aiShadingMode // --------------------------------------------------------------------------- /** @brief Defines some mixed flags for a particular texture. * - * Usually you'll tell your cg artists how textures have to look like ... - * and hopefully the follow these rules. If they don't, restrict access - * to the coffee machine for them. That should help. - * However, if you use Assimp for completely generic loading purposes you - * might also need to process these flags in order to display as many - * 'unknown' 3D models as possible correctly. + * Usually you'll instruct your cg artists how textures have to look like ... + * and how they will be processed in your application. However, if you use + * Assimp for completely generic loading purposes you might also need to + * process these flags in order to display as many 'unknown' 3D models as + * possible correctly. * * This corresponds to the #AI_MATKEY_TEXFLAGS property. */ @@ -435,7 +393,6 @@ enum aiTextureFlags */ aiTextureFlags_Invert = 0x1, - /** Explicit request to the application to process the alpha channel * of the texture. * @@ -450,11 +407,9 @@ enum aiTextureFlags /** Explicit request to the application to ignore the alpha channel * of the texture. * - * Mutually exclusive with #aiTextureFlags_IgnoreAlpha. + * Mutually exclusive with #aiTextureFlags_UseAlpha. */ aiTextureFlags_IgnoreAlpha = 0x4, - - /** @cond never * This value is not used. It forces the compiler to use at least @@ -560,6 +515,48 @@ struct aiUVTransform #include "./Compiler/poppack1.h" +//! @cond AI_DOX_INCLUDE_INTERNAL +// --------------------------------------------------------------------------- +/** @brief A very primitive RTTI system for the contents of material + * properties. + */ +enum aiPropertyTypeInfo +{ + /** Array of single-precision (32 Bit) floats + * + * It is possible to use aiGetMaterialInteger[Array]() (or the C++-API + * aiMaterial::Get()) to query properties stored in floating-point format. + * The material system performs the type conversion automatically. + */ + aiPTI_Float = 0x1, + + /** The material property is an aiString. + * + * Arrays of strings aren't possible, aiGetMaterialString() (or the + * C++-API aiMaterial::Get()) *must* be used to query a string property. + */ + aiPTI_String = 0x3, + + /** Array of (32 Bit) integers + * + * It is possible to use aiGetMaterialFloat[Array]() (or the C++-API + * aiMaterial::Get()) to query properties stored in integer format. + * The material system performs the type conversion automatically. + */ + aiPTI_Integer = 0x4, + + + /** Simple binary buffer, content undefined. Not convertible to anything. + */ + aiPTI_Buffer = 0x5, + + + /** This value is not used. It is just there to force the + * compiler to map this enum to a 32 Bit integer. + */ + _aiPTI_Force32Bit = 0x9fffffff +}; + // --------------------------------------------------------------------------- /** @brief Data structure for a single material property * @@ -576,37 +573,30 @@ struct aiUVTransform * 2nd: Public, but ignored by the #aiProcess_RemoveRedundantMaterials * post-processing step. * ~ - * A temporary property for internal use. If someone forgets to - * cleanup, some of these might still be contained in the output. - * Don't complain! If you understood what the first paragraph tried - * to tell you, you wouldn't even know. + * A temporary property for internal use. * @endcode * @see aiMaterial */ struct aiMaterialProperty { /** Specifies the name of the property (key) - * - * Keys are case insensitive. + * Keys are generally case insensitive. */ C_STRUCT aiString mKey; - /** Textures: Specifies the exact usage semantic. - * - * For non-texture properties, this member is always 0 - * or #aiTextureType_NONE. + /** Textures: Specifies their exact usage semantic. + * For non-texture properties, this member is always 0 + * (or, better-said, #aiTextureType_NONE). */ unsigned int mSemantic; - /** Textures: Specifies the index of the texture - * + /** Textures: Specifies the index of the texture. * For non-texture properties, this member is always 0. */ unsigned int mIndex; /** Size of the buffer mData is pointing to, in bytes. - * - * This value may not be 0. + * This value may not be 0. */ unsigned int mDataLength; @@ -619,8 +609,7 @@ struct aiMaterialProperty */ C_ENUM aiPropertyTypeInfo mType; - /** Binary buffer to hold the property's value - * + /** Binary buffer to hold the property's value. * The size of the buffer is always mDataLength. */ char* mData; @@ -638,6 +627,7 @@ struct aiMaterialProperty #endif }; +//! @endcond #ifdef __cplusplus } // We need to leave the "C" block here to allow template member functions @@ -1177,15 +1167,15 @@ extern "C" { // --------------------------------------------------------------------------- /** @brief Retrieve a material property with a specific key from the material -* -* @param pMat Pointer to the input material. May not be NULL -* @param pKey Key to search for. One of the AI_MATKEY_XXX constants. -* @param type Specifies the type of the texture to be retrieved ( -* e.g. diffuse, specular, height map ...) -* @param index Index of the texture to be retrieved. -* @param pPropOut Pointer to receive a pointer to a valid aiMaterialProperty -* structure or NULL if the key has not been found. -*/ + * + * @param pMat Pointer to the input material. May not be NULL + * @param pKey Key to search for. One of the AI_MATKEY_XXX constants. + * @param type Specifies the type of the texture to be retrieved ( + * e.g. diffuse, specular, height map ...) + * @param index Index of the texture to be retrieved. + * @param pPropOut Pointer to receive a pointer to a valid aiMaterialProperty + * structure or NULL if the key has not been found. + */ // --------------------------------------------------------------------------- ASSIMP_API C_ENUM aiReturn aiGetMaterialProperty( const C_STRUCT aiMaterial* pMat, @@ -1196,30 +1186,30 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialProperty( // --------------------------------------------------------------------------- /** @brief Retrieve an array of float values with a specific key -* from the material -* -* Pass one of the AI_MATKEY_XXX constants for the last three parameters (the -* example reads the #AI_MATKEY_UVTRANSFORM property of the first diffuse texture) -* @code -* aiUVTransform trafo; -* unsigned int max = sizeof(aiUVTransform); -* if (AI_SUCCESS != aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE,0), -* (float*)&trafo, &max) || sizeof(aiUVTransform) != max) -* { -* // error handling -* } -* @endcode -* -* @param pMat Pointer to the input material. May not be NULL -* @param pKey Key to search for. One of the AI_MATKEY_XXX constants. -* @param pOut Pointer to a buffer to receive the result. -* @param pMax Specifies the size of the given buffer, in float's. -* Receives the number of values (not bytes!) read. -* @param type (see the code sample above) -* @param index (see the code sample above) -* @return Specifies whether the key has been found. If not, the output -* arrays remains unmodified and pMax is set to 0. -*/ + * from the material + * + * Pass one of the AI_MATKEY_XXX constants for the last three parameters (the + * example reads the #AI_MATKEY_UVTRANSFORM property of the first diffuse texture) + * @code + * aiUVTransform trafo; + * unsigned int max = sizeof(aiUVTransform); + * if (AI_SUCCESS != aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE,0), + * (float*)&trafo, &max) || sizeof(aiUVTransform) != max) + * { + * // error handling + * } + * @endcode + * + * @param pMat Pointer to the input material. May not be NULL + * @param pKey Key to search for. One of the AI_MATKEY_XXX constants. + * @param pOut Pointer to a buffer to receive the result. + * @param pMax Specifies the size of the given buffer, in float's. + * Receives the number of values (not bytes!) read. + * @param type (see the code sample above) + * @param index (see the code sample above) + * @return Specifies whether the key has been found. If not, the output + * arrays remains unmodified and pMax is set to 0. + */ // --------------------------------------------------------------------------- ASSIMP_API C_ENUM aiReturn aiGetMaterialFloatArray( const C_STRUCT aiMaterial* pMat, @@ -1272,11 +1262,10 @@ inline aiReturn aiGetMaterialFloat(const aiMaterial* pMat, // --------------------------------------------------------------------------- /** @brief Retrieve an array of integer values with a specific key -* from a material -* -* See the sample for aiGetMaterialFloatArray for more information. -*/ -// --------------------------------------------------------------------------- + * from a material + * + * See the sample for aiGetMaterialFloatArray for more information. + */ ASSIMP_API C_ENUM aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* pMat, const char* pKey, unsigned int type, @@ -1289,9 +1278,9 @@ ASSIMP_API C_ENUM aiReturn aiGetMaterialIntegerArray(const C_STRUCT aiMaterial* // --------------------------------------------------------------------------- /** @brief Retrieve an integer property with a specific key from a material -* -* See the sample for aiGetMaterialFloat for more information. -*/ + * + * See the sample for aiGetMaterialFloat for more information. + */ // --------------------------------------------------------------------------- inline aiReturn aiGetMaterialInteger(const C_STRUCT aiMaterial* pMat, const char* pKey, diff --git a/include/aiTypes.h b/include/aiTypes.h index 3ff2a8053..307f45197 100644 --- a/include/aiTypes.h +++ b/include/aiTypes.h @@ -40,12 +40,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ /** @file aiTypes.h -*/ - + * Basic data types and primitives, such as vectors or colors. + */ #ifndef AI_TYPES_H_INC #define AI_TYPES_H_INC -// Some CRT headers +// Some runtime headers #include #include #include @@ -67,17 +67,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace Intern { + // -------------------------------------------------------------------- /** @brief Internal helper class to utilize our internal new/delete * routines for allocating object of this and derived classes. * * By doing this you can safely share class objects between Assimp * and the application - it works even over DLL boundaries. A good - * example is the IOSystem where the application allocates its custom - * IOSystem, then calls Importer::SetIOSystem(). When the Importer - * destructs, Assimp calls operator delete on the stored IOSystem. + * example is the #IOSystem where the application allocates its custom + * #IOSystem, then calls #Importer::SetIOSystem(). When the Importer + * destructs, Assimp calls operator delete on the stored #IOSystem. * If it lies on a different heap than Assimp is working with, * the application is determined to crash. */ + // -------------------------------------------------------------------- struct ASSIMP_API AllocateFromAssimpHeap { // new/delete overload @@ -122,7 +124,6 @@ struct aiPlane float a,b,c,d; } PACK_STRUCT; // !struct aiPlane - // ---------------------------------------------------------------------------------- /** Represents a ray */ @@ -141,8 +142,6 @@ struct aiRay C_STRUCT aiVector3D pos, dir; } PACK_STRUCT; // !struct aiRay - - // ---------------------------------------------------------------------------------- /** Represents a color in Red-Green-Blue space. */ @@ -153,43 +152,48 @@ struct aiColor3D aiColor3D (float _r, float _g, float _b) : r(_r), g(_g), b(_b) {} aiColor3D (const aiColor3D& o) : r(o.r), g(o.g), b(o.b) {} - // Component-wise comparison + /** Component-wise comparison */ // TODO: add epsilon? bool operator == (const aiColor3D& other) const {return r == other.r && g == other.g && b == other.b;} - // Component-wise inverse comparison + /** Component-wise inverse comparison */ // TODO: add epsilon? bool operator != (const aiColor3D& other) const {return r != other.r || g != other.g || b != other.b;} - // Component-wise addition + /** Component-wise addition */ aiColor3D operator+(const aiColor3D& c) const { return aiColor3D(r+c.r,g+c.g,b+c.b); } - // Component-wise subtraction + /** Component-wise subtraction */ aiColor3D operator-(const aiColor3D& c) const { return aiColor3D(r+c.r,g+c.g,b+c.b); } - // Component-wise multiplication + /** Component-wise multiplication */ aiColor3D operator*(const aiColor3D& c) const { return aiColor3D(r*c.r,g*c.g,b*c.b); } - // Multiply with a scalar + /** Multiply with a scalar */ aiColor3D operator*(float f) const { return aiColor3D(r*f,g*f,b*f); } - // Access a specific color component - float operator[](unsigned int i) const {return *(&r + i);} - float& operator[](unsigned int i) {return *(&r + i);} + /** Access a specific color component */ + float operator[](unsigned int i) const { + return *(&r + i); + } - // Check whether a color is black - bool IsBlack() const - { + /** Access a specific color component */ + float& operator[](unsigned int i) { + return *(&r + i); + } + + /** Check whether a color is black */ + bool IsBlack() const { static const float epsilon = 10e-3f; return fabs( r ) < epsilon && fabs( g ) < epsilon && fabs( b ) < epsilon; } @@ -214,24 +218,28 @@ struct aiColor4D aiColor4D (const aiColor4D& o) : r(o.r), g(o.g), b(o.b), a(o.a) {} - // Component-wise comparison + /** Component-wise comparison */ // TODO: add epsilon? bool operator == (const aiColor4D& other) const { return r == other.r && g == other.g && b == other.b && a == other.a; } - // Component-wise inverse comparison + /** Component-wise inverse comparison */ // TODO: add epsilon? bool operator != (const aiColor4D& other) const { return r != other.r || g != other.g || b != other.b || a != other.a; } - // Access a specific color component - inline float operator[](unsigned int i) const {return *(&r + i);} - inline float& operator[](unsigned int i) {return *(&r + i);} + /** Access a specific color component */ + inline float operator[](unsigned int i) const { + return *(&r + i); + } + /** Access a specific color component */ + inline float& operator[](unsigned int i) { + return *(&r + i); + } - // Check whether a color is black - // TODO: add epsilon? + /** Check whether a color is black */ inline bool IsBlack() const { // The alpha component doesn't care here. black is black. @@ -244,11 +252,8 @@ struct aiColor4D //! Red, green, blue and alpha color values float r, g, b, a; } PACK_STRUCT; // !struct aiColor4D - - #include "./Compiler/poppack1.h" - // ---------------------------------------------------------------------------------- /** Represents a string, zero byte terminated. * @@ -258,8 +263,7 @@ struct aiColor4D struct aiString { #ifdef __cplusplus - - //! Default constructor, the string is set to have zero length + /** Default constructor, the string is set to have zero length */ aiString() : length(0) { @@ -271,7 +275,7 @@ struct aiString #endif } - //! Copy constructor + /** Copy constructor */ aiString(const aiString& rOther) : length(rOther.length) { @@ -279,7 +283,7 @@ struct aiString data[length] = '\0'; } - //! Constructor from std::string + /** Constructor from std::string */ aiString(const std::string& pString) : length(pString.length()) { @@ -287,69 +291,65 @@ struct aiString data[length] = '\0'; } - //! Copy a std::string to the aiString - void Set( const std::string& pString) - { - if( pString.length() > MAXLEN - 1) + /** Copy a std::string to the aiString */ + void Set( const std::string& pString) { + if( pString.length() > MAXLEN - 1) { return; + } length = pString.length(); ::memcpy( data, pString.c_str(), length); data[length] = 0; } - //! Copy a const char* to the aiString - void Set( const char* sz) - { + /** Copy a const char* to the aiString */ + void Set( const char* sz) { const size_t len = ::strlen(sz); - if( len > MAXLEN - 1) + if( len > MAXLEN - 1) { return; + } length = len; ::memcpy( data, sz, len); data[len] = 0; } - // Assign a const char* to the string - aiString& operator = (const char* sz) - { + /** Assign a const char* to the string */ + aiString& operator = (const char* sz) { Set(sz); return *this; } - // Assign a cstd::string to the string - aiString& operator = ( const std::string& pString) - { + /** Assign a cstd::string to the string */ + aiString& operator = ( const std::string& pString) { Set(pString); return *this; } - //! Comparison operator - bool operator==(const aiString& other) const - { + /** Comparison operator */ + bool operator==(const aiString& other) const { return (length == other.length && 0 == strcmp(this->data,other.data)); } - //! Inverse comparison operator - bool operator!=(const aiString& other) const - { + /** Inverse comparison operator */ + bool operator!=(const aiString& other) const { return (length != other.length || 0 != ::strcmp(this->data,other.data)); } - //! Append a string to the string - void Append (const char* app) - { + /** Append a string to the string */ + void Append (const char* app) { const size_t len = ::strlen(app); - if (!len)return; - - if (length + len >= MAXLEN) + if (!len) { return; + } + if (length + len >= MAXLEN) { + return; + } ::memcpy(&data[length],app,len+1); length += len; } - //! Clear the string - reset its length to zero - void Clear () - { + /** Clear the string - reset its length to zero */ + void Clear () { length = 0; data[0] = '\0'; @@ -361,74 +361,107 @@ struct aiString #endif // !__cplusplus - //! Length of the string excluding the terminal 0 + /** Length of the string excluding the terminal 0 */ size_t length; - //! String buffer. Size limit is MAXLEN + /** String buffer. Size limit is MAXLEN */ char data[MAXLEN]; } ; // !struct aiString // ---------------------------------------------------------------------------------- -/** Standard return type for all library functions. -* -* To check whether or not a function failed check against -* AI_SUCCESS. The error codes are mainly used by the C-API. -*/ +/** Standard return type for some library functions. + * Rarely used, and if, mostly in the C API. + */ enum aiReturn { - //! Indicates that a function was successful - AI_SUCCESS = 0x0, + /** Indicates that a function was successful */ + aiReturn_SUCCESS = 0x0, - //! Indicates that a function failed - AI_FAILURE = -0x1, + /** Indicates that a function failed */ + aiReturn_FAILURE = -0x1, - //! Indicates that a file was invalid - AI_INVALIDFILE = -0x2, + /** Indicates that not enough memory was available + * to perform the requested operation + */ + aiReturn_OUTOFMEMORY = -0x3, - //! Indicates that not enough memory was available - //! to perform the requested operation - AI_OUTOFMEMORY = -0x3, - - //! Indicates that an illegal argument has been - //! passed to a function. This is rarely used, - //! most functions assert in this case. - AI_INVALIDARG = -0x4, - - //! Force 32-bit size enum + /** @cond never + * Force 32-bit size enum + */ _AI_ENFORCE_ENUM_SIZE = 0x7fffffff }; // !enum aiReturn +// just for backwards compatibility, don't use these constants anymore +#define AI_SUCCESS aiReturn_SUCCESS +#define AI_FAILURE aiReturn_FAILURE +#define AI_OUTOFMEMORY aiReturn_OUTOFMEMORY // ---------------------------------------------------------------------------------- -/** Seek origins (for the virtual file system API) -*/ +/** Seek origins (for the virtual file system API). + * Much cooler than using SEEK_SET, SEEK_CUR or SEEK_END. + */ enum aiOrigin { - //! Beginning of the file + /** Beginning of the file */ aiOrigin_SET = 0x0, - //! Current position of the file pointer + /** Current position of the file pointer */ aiOrigin_CUR = 0x1, - //! End of the file, offsets must be negative + /** End of the file, offsets must be negative */ aiOrigin_END = 0x2, - //! Force 32-bit size enum + /** @cond never + * Force 32-bit size enum + */ _AI_ORIGIN_ENFORCE_ENUM_SIZE = 0x7fffffff }; // !enum aiOrigin +// ---------------------------------------------------------------------------------- +/** @brief Enumerates predefined log streaming destinations. + * Logging to these streams can be enabled with a single call to + * #LogStream::createDefaultStream or #aiAttachPredefinedLogStream(), + * respectively. + */ +enum aiDefaultLogStream +{ + /** Stream the log to a file */ + aiDefaultLogStream_FILE = 0x1, + + /** Stream the log to std::cout */ + aiDefaultLogStream_STDOUT = 0x2, + + /** Stream the log to std::cerr */ + aiDefaultLogStream_STDERR = 0x4, + + /** MSVC only: Stream the log the the debugger + * (this relies on OutputDebugString from the Win32 SDK) + */ + aiDefaultLogStream_DEBUGGER = 0x8, + + /** @cond never + * Force 32-bit size enum + */ + _AI_DLS_ENFORCE_ENUM_SIZE = 0x7fffffff +}; // !enum aiDefaultLogStream + +// just for backwards compatibility, don't use these constants anymore +#define DLS_FILE aiDefaultLogStream_FILE +#define DLS_STDOUT aiDefaultLogStream_STDOUT +#define DLS_STDERR aiDefaultLogStream_STDERR +#define DLS_DEBUGGER aiDefaultLogStream_DEBUGGER // ---------------------------------------------------------------------------------- -/** Stores the memory requirements for different parts (e.g. meshes, materials, - * animations) of an import. +/** Stores the memory requirements for different components (e.g. meshes, materials, + * animations) of an import. All sizes are in bytes. * @see Importer::GetMemoryRequirements() */ struct aiMemoryInfo { #ifdef __cplusplus - //! Default constructor + /** Default constructor */ aiMemoryInfo() : textures (0) , materials (0) @@ -442,32 +475,31 @@ struct aiMemoryInfo #endif - //! Storage allocated for texture data, in bytes + /** Storage allocated for texture data */ unsigned int textures; - //! Storage allocated for material data, in bytes + /** Storage allocated for material data */ unsigned int materials; - //! Storage allocated for mesh data, in bytes + /** Storage allocated for mesh data */ unsigned int meshes; - //! Storage allocated for node data, in bytes + /** Storage allocated for node data */ unsigned int nodes; - //! Storage allocated for animation data, in bytes + /** Storage allocated for animation data */ unsigned int animations; - //! Storage allocated for camera data, in bytes + /** Storage allocated for camera data */ unsigned int cameras; - //! Storage allocated for light data, in bytes + /** Storage allocated for light data */ unsigned int lights; - //! Storage allocated for the full import, in bytes + /** Total storage allocated for the full import. */ unsigned int total; }; // !struct aiMemoryInfo - #ifdef __cplusplus } #endif //! __cplusplus @@ -476,8 +508,4 @@ struct aiMemoryInfo #include "aiVector3D.inl" #include "aiMatrix3x3.inl" #include "aiMatrix4x4.inl" - - - #endif //!! include guard - diff --git a/include/assimp.h b/include/assimp.h index 49d8315e1..fc46f8343 100644 --- a/include/assimp.h +++ b/include/assimp.h @@ -39,154 +39,289 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. --------------------------------------------------------------------------- */ -/** @file assimp.h - @brief Defines the C-API to the Asset Import Library. */ +/** @file assimp.h + * @brief Defines the C-API to the Open Asset Import Library. + */ #ifndef AI_ASSIMP_H_INC #define AI_ASSIMP_H_INC - #include "aiTypes.h" #ifdef __cplusplus extern "C" { #endif -struct aiScene; -struct aiFileIO; -struct aiString; +struct aiScene; // aiScene.h +struct aiFileIO; // aiFileIO.h +typedef void (*aiLogStreamCallback)(const char* /* message */, char* /* user */); +// -------------------------------------------------------------------------------- +/** Represents a log stream. A log stream receives all log messages and streams + * them somewhere. + * @see aiGetPredefinedLogStream + * @see aiAttachLogStream + * @see aiDetachLogStream + */ +// -------------------------------------------------------------------------------- +struct aiLogStream +{ + /** callback to be called */ + aiLogStreamCallback callback; -// --------------------------------------------------------------------------- + /** user data to be passed to the callback */ + char* user; +}; + +/** Our own C boolean type */ +typedef int aiBool; + +#define AI_FALSE 0 +#define AI_TRUE 1 + +// -------------------------------------------------------------------------------- /** Reads the given file and returns its content. -* -* If the call succeeds, the imported data is returned in an aiScene structure. -* The data is intended to be read-only, it stays property of the ASSIMP -* library and will be stable until aiReleaseImport() is called. After you're -* done with it, call aiReleaseImport() to free the resources associated with -* this file. If the import fails, NULL is returned instead. Call -* aiGetErrorString() to retrieve a human-readable error text. -* @param pFile Path and filename of the file to be imported, -* expected to be a null-terminated c-string. NULL is not a valid value. -* @param pFlags Optional post processing steps to be executed after -* a successful import. Provide a bitwise combination of the -* #aiPostProcessSteps flags. -* @return Pointer to the imported data or NULL if the import failed. -*/ -// --------------------------------------------------------------------------- -ASSIMP_API const C_STRUCT aiScene* aiImportFile( const char* pFile, + * + * If the call succeeds, the imported data is returned in an aiScene structure. + * The data is intended to be read-only, it stays property of the ASSIMP + * library and will be stable until aiReleaseImport() is called. After you're + * done with it, call aiReleaseImport() to free the resources associated with + * this file. If the import fails, NULL is returned instead. Call + * aiGetErrorString() to retrieve a human-readable error text. + * @param pFile Path and filename of the file to be imported, + * expected to be a null-terminated c-string. NULL is not a valid value. + * @param pFlags Optional post processing steps to be executed after + * a successful import. Provide a bitwise combination of the + * #aiPostProcessSteps flags. + * @return Pointer to the imported data or NULL if the import failed. + */ +ASSIMP_API const C_STRUCT aiScene* aiImportFile( + const char* pFile, unsigned int pFlags); - -// --------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- /** Reads the given file using user-defined I/O functions and returns -* its content. -* -* If the call succeeds, the imported data is returned in an aiScene structure. -* The data is intended to be read-only, it stays property of the ASSIMP -* library and will be stable until aiReleaseImport() is called. After you're -* done with it, call aiReleaseImport() to free the resources associated with -* this file. If the import fails, NULL is returned instead. Call -* aiGetErrorString() to retrieve a human-readable error text. -* @param pFile Path and filename of the file to be imported, -* expected to be a null-terminated c-string. NULL is not a valid value. -* @param pFlags Optional post processing steps to be executed after -* a successful import. Provide a bitwise combination of the -* #aiPostProcessSteps flags. -* @param pFS aiFileIO structure. Will be used to open the model file itself -* and any other files the loader needs to open. -* @return Pointer to the imported data or NULL if the import failed. -*/ -// --------------------------------------------------------------------------- + * its content. + * + * If the call succeeds, the imported data is returned in an aiScene structure. + * The data is intended to be read-only, it stays property of the ASSIMP + * library and will be stable until aiReleaseImport() is called. After you're + * done with it, call aiReleaseImport() to free the resources associated with + * this file. If the import fails, NULL is returned instead. Call + * aiGetErrorString() to retrieve a human-readable error text. + * @param pFile Path and filename of the file to be imported, + * expected to be a null-terminated c-string. NULL is not a valid value. + * @param pFlags Optional post processing steps to be executed after + * a successful import. Provide a bitwise combination of the + * #aiPostProcessSteps flags. + * @param pFS aiFileIO structure. Will be used to open the model file itself + * and any other files the loader needs to open. + * @return Pointer to the imported data or NULL if the import failed. + * @note Include for the definition of #aiFioeIO. + */ ASSIMP_API const C_STRUCT aiScene* aiImportFileEx( const char* pFile, - unsigned int pFlags, + unsigned int pFlags, C_STRUCT aiFileIO* pFS); +// -------------------------------------------------------------------------------- +/** Apply post-processing to an already-imported scene. + * + * This is strictly equivalent to calling #aiImportFile()/#aiImportFileEx with the + * same flags. However, you can use this separate function to inspect the imported + * scene first to fine-tune your post-processing setup. + * @param pScene Scene to work on. + * @param pFlags Provide a bitwise combination of the #aiPostProcessSteps flags. + * @return A pointer to the post-processed data. Post processing is done in-place, + * meaning this is still the same #aiScene which you passed for pScene. However, + * _if_ post-processing failed, the scene could now be NULL. That's quite a rare + * case, post processing steps are not really designed to 'fail'. To be exact, + * the #aiProcess_ValidateDS flag is currently the only post processing step + * which can actually cause the scene to be reset to NULL. + */ +ASSIMP_API const C_STRUCT aiScene* aiApplyPostProcessing( + const C_STRUCT aiScene* pScene, + unsigned int pFlags); -// --------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- +/** Get one of the predefine log streams. This is the quick'n'easy solution to + * access Assimp's log system. Attaching a log stream can slightly reduce Assimp's + * overall import performance. + * + * Usage is rather simple: + * @code + * aiLogStreamCallback c = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"log.txt",NULL); + * if (NULL != c) { + * aiAttachLogStream(c); + * } + * @endcode + * + * @param One of the #aiDefaultLogStream enumerated values. + * @param file Solely for the #aiDefaultLogStream_FILE flag: specifies the file to write to. + * Pass NULL for all other flags. + * @return The log stream. callback is set to NULL if something went wrong. + */ +ASSIMP_API C_STRUCT aiLogStream aiGetPredefinedLogStream( + C_ENUM aiDefaultLogStream pStreams, + const char* file); + +// -------------------------------------------------------------------------------- +/** Attach a custom log stream to the libraries' logging system. + * + * Attaching a log stream can slightly reduce Assimp's overall import + * performance. Multiple log-streams can be attached. + * @param stream Describes the new log stream. + * @note To ensure proepr destruction of the logging system, you need to manually + * call aiDetachLogStream() on every single log stream you attach. + * Alternatively (for the lazy folks) #aiDetachAllLogStreams is provided. + */ +ASSIMP_API void aiAttachLogStream( + const C_STRUCT aiLogStream* stream); + +// -------------------------------------------------------------------------------- +/** Enable verbose logging. Verbose logging includes debug-related stuff and + * detailed import statistics. This can have severe impact on import performance + * and memory consumption. However, it might be useful to find out why a file + * didn't read correctly. + * @param d AI_TRUE or AI_FALSE, your decision. + */ +ASSIMP_API void aiEnableVerboseLogging(aiBool d); + +// -------------------------------------------------------------------------------- +/** Detach a custom log stream from the libraries' logging system. + * + * This is the counterpart of #aiAttachPredefinedLogStream. If you attached a stream, + * don't forget to detach it again. + * @param stream The log stream to be detached. + * @return AI_SUCCESS if the log stream has been detached successfully. + * @see aiDetachAllLogStreams + */ +ASSIMP_API C_ENUM aiReturn aiDetachLogStream( + const C_STRUCT aiLogStream* stream); + +// -------------------------------------------------------------------------------- +/** Detach all active log streams from the libraries' logging system. + * This ensures that the logging system is terminated properly and all + * resources allocated by it are actually freed. If you attached a stream, + * don't forget to detach it again. + * @see aiAttachLogStream + * @see aiDetachLogStream + */ +ASSIMP_API void aiDetachAllLogStreams(void); + +// -------------------------------------------------------------------------------- /** Releases all resources associated with the given import process. -* -* Call this function after you're done with the imported data. -* @param pScene The imported data to release. NULL is a valid value. -*/ -// --------------------------------------------------------------------------- -ASSIMP_API void aiReleaseImport( const C_STRUCT aiScene* pScene); + * + * Call this function after you're done with the imported data. + * @param pScene The imported data to release. NULL is a valid value. + */ +ASSIMP_API void aiReleaseImport( + const C_STRUCT aiScene* pScene); - -// --------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- /** Returns the error text of the last failed import process. -* -* @return A textual description of the error that occurred at the last -* import process. NULL if there was no error. -*/ -// --------------------------------------------------------------------------- + * + * @return A textual description of the error that occurred at the last + * import process. NULL if there was no error. There can't be an error if you + * got a non-NULL #aiScene from #aiImportFile/#aiImportFileEx/#aiApplyPostProcessing. + */ ASSIMP_API const char* aiGetErrorString(); - -// --------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- /** Returns whether a given file extension is supported by ASSIMP -* -* @param szExtension Extension for which the function queries support. -* Must include a leading dot '.'. Example: ".3ds", ".md3" -* @return 1 if the extension is supported, 0 otherwise -*/ -// --------------------------------------------------------------------------- -ASSIMP_API int aiIsExtensionSupported(const char* szExtension); + * + * @param szExtension Extension for which the function queries support for. + * Must include a leading dot '.'. Example: ".3ds", ".md3" + * @return AI_TRUE if the file extension is supported. + */ +ASSIMP_API aiBool aiIsExtensionSupported( + const char* szExtension); - -// --------------------------------------------------------------------------- -/** Get a full list of all file extensions generally supported by ASSIMP. +// -------------------------------------------------------------------------------- +/** Get a list of all file extensions supported by ASSIMP. * * If a file extension is contained in the list this does, of course, not * mean that ASSIMP is able to load all files with this extension. * @param szOut String to receive the extension list. * Format of the list: "*.3ds;*.obj;*.dae". NULL is not a valid parameter. -*/ -// --------------------------------------------------------------------------- -ASSIMP_API void aiGetExtensionList(C_STRUCT aiString* szOut); + */ +ASSIMP_API void aiGetExtensionList( + C_STRUCT aiString* szOut); - -// --------------------------------------------------------------------------- +// -------------------------------------------------------------------------------- /** Get the storage required by an imported asset * @param pIn Input asset. * @param in Data structure to be filled. */ -// --------------------------------------------------------------------------- -ASSIMP_API void aiGetMemoryRequirements(const C_STRUCT aiScene* pIn, +ASSIMP_API void aiGetMemoryRequirements( + const C_STRUCT aiScene* pIn, C_STRUCT aiMemoryInfo* in); - -// --------------------------------------------------------------------------- -/** Set an integer property. This is the C-version of - * #Assimp::Importer::SetPropertyInteger(). In the C-API properties are shared by - * all imports. It is not possible to specify them per asset. +// -------------------------------------------------------------------------------- +/** Set an integer property. * - * @param szName Name of the configuration property to be set. All constants - * are defined in the aiConfig.h header file. + * This is the C-version of #Assimp::Importer::SetPropertyInteger(). In the C + * interface, properties are always shared by all imports. It is not possible to + * specify them per import. + * + * @param szName Name of the configuration property to be set. All supported + * public properties are defined in the aiConfig.h header file (#AI_CONFIG_XXX). * @param value New value for the property */ -// --------------------------------------------------------------------------- -ASSIMP_API void aiSetImportPropertyInteger(const char* szName, int value); +ASSIMP_API void aiSetImportPropertyInteger( + const char* szName, + int value); -// --------------------------------------------------------------------------- -/** @see aiSetImportPropertyInteger() +// -------------------------------------------------------------------------------- +/** Set a floating-point property. + * + * This is the C-version of #Assimp::Importer::SetPropertyFloat(). In the C + * interface, properties are always shared by all imports. It is not possible to + * specify them per import. + * + * @param szName Name of the configuration property to be set. All supported + * public properties are defined in the aiConfig.h header file (#AI_CONFIG_XXX). + * @param value New value for the property */ -ASSIMP_API void aiSetImportPropertyFloat(const char* szName, float value); +ASSIMP_API void aiSetImportPropertyFloat( + const char* szName, + float value); -// --------------------------------------------------------------------------- -/** @see aiSetImportPropertyInteger() +// -------------------------------------------------------------------------------- +/** Set a string property. + * + * This is the C-version of #Assimp::Importer::SetPropertyString(). In the C + * interface, properties are always shared by all imports. It is not possible to + * specify them per import. + * + * @param szName Name of the configuration property to be set. All supported + * public properties are defined in the aiConfig.h header file (#AI_CONFIG_XXX). + * @param value New value for the property */ -ASSIMP_API void aiSetImportPropertyString(const char* szName, +ASSIMP_API void aiSetImportPropertyString( + const char* szName, const C_STRUCT aiString* st); -// --------------------------------------------------------------------------- -/** @see aiQuaternion(const aiMatrix3x3& pRotMatrix) +// -------------------------------------------------------------------------------- +/** Construct a quaternion from a 3x3 rotation matrix. + * @param quat Receives the output quaternion. + * @param mat Matrix to 'quaternionize'. + * @see aiQuaternion(const aiMatrix3x3& pRotMatrix) */ -ASSIMP_API void aiCreateQuaternionFromMatrix(C_STRUCT aiQuaternion* quat,const C_STRUCT aiMatrix3x3* mat); +ASSIMP_API void aiCreateQuaternionFromMatrix( + C_STRUCT aiQuaternion* quat, + const C_STRUCT aiMatrix3x3* mat); -// --------------------------------------------------------------------------- -/** @see aiMatrix4x4::Decompose (aiVector3D&, aiQuaternion&, aiVector3D&) const; +// -------------------------------------------------------------------------------- +/** Decompose a transformation matrix into its rotational, translational and + * scaling components. + * + * @param mat Matrix to decompose + * @param scaling Receives the scaling component + * @param rotation Receives the rotational component + * @param position Receives the translational component. + * @see aiMatrix4x4::Decompose (aiVector3D&, aiQuaternion&, aiVector3D&) const; */ -ASSIMP_API void aiDecomposeMatrix(const C_STRUCT aiMatrix4x4* mat, +ASSIMP_API void aiDecomposeMatrix( + const C_STRUCT aiMatrix4x4* mat, C_STRUCT aiVector3D* scaling, C_STRUCT aiQuaternion* rotation, C_STRUCT aiVector3D* position); diff --git a/include/assimp.hpp b/include/assimp.hpp index 8f6fca490..86b02ec30 100644 --- a/include/assimp.hpp +++ b/include/assimp.hpp @@ -336,7 +336,7 @@ public: * #aiPostProcessSteps flags. * @return A pointer to the post-processed data. This is still the * same as the pointer returned by #ReadFile(). However, if - * post-processing fails severly the scene could now be NULL. + * post-processing fails, the scene could now be NULL. * That's quite a rare case, post processing steps are not really * designed to 'fail'. To be exact, the #aiProcess_ValidateDS * flag is currently the only post processing step which can actually diff --git a/mkutil/revision.h b/mkutil/revision.h index d014a80f5..a1828ebf1 100644 --- a/mkutil/revision.h +++ b/mkutil/revision.h @@ -1 +1 @@ -#define SVNRevision 412 +#define SVNRevision 423 diff --git a/test/RunSingleUnitTestSuite.bat b/test/RunSingleUnitTestSuite.bat index f3f657fc7..4a6a8998a 100644 --- a/test/RunSingleUnitTestSuite.bat +++ b/test/RunSingleUnitTestSuite.bat @@ -13,8 +13,6 @@ rem FIRSTUTNA - if the test wasn't found, receives the test name rem FIRSTUTFAILUR - if the test failed, receives the test name rem rem ------------------------------------------------------------------------------ - -rem Check whether the IF NOT EXIST %BINDIR%\%1\unit.exe ( echo NOT AVAILABLE. Please rebuild this configuration diff --git a/test/RunUnitTestSuite.bat b/test/RunUnitTestSuite.bat index 95b689f08..269e8e93d 100644 --- a/test/RunUnitTestSuite.bat +++ b/test/RunUnitTestSuite.bat @@ -85,7 +85,7 @@ IF %FIRSTUTNA% == nil ( ) IF %FIRSTUTFAILURE% == nil ( - echo All tests have been successful. Everything is fine. + echo All tests have been successful. ) ELSE ( echo One or more tests failed. ) diff --git a/test/unit/Main.cpp b/test/unit/Main.cpp index f2965ccc7..6f4994ab2 100644 --- a/test/unit/Main.cpp +++ b/test/unit/Main.cpp @@ -18,9 +18,19 @@ int main (int argc, char* argv[]) time_t t;time(&t); srand((unsigned int)t); - // create a logger - Assimp::DefaultLogger::create("AssimpLog.txt",Assimp::Logger::VERBOSE, - Assimp::DLS_DEBUGGER | Assimp::DLS_FILE); + // ............................................................................ + + // create a logger from both CPP + Assimp::DefaultLogger::create("AssimpLog_Cpp.txt",Assimp::Logger::VERBOSE, + aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE); + + // .. and C. They should smoothly work together + aiEnableVerboseLogging(AI_TRUE); + aiAttachLogStream(&aiGetPredefinedLogStream( + aiDefaultLogStream_FILE, + "AssimpLog_C.txt")); + + // ............................................................................ // Informiert Test-Listener ueber Testresultate CPPUNIT_NS :: TestResult testresult; @@ -49,8 +59,13 @@ int main (int argc, char* argv[]) xml.write (); #endif - // kill the logger again - Assimp::DefaultLogger::kill(); + // ............................................................................ + // but shutdown must be done from C to ensure proper deallocation + aiDetachAllLogStreams(); + if (!Assimp::DefaultLogger::isNullLogger()) { + return 1; + } + // ............................................................................ // Rueckmeldung, ob Tests erfolgreich waren return collectedresults.wasSuccessful () ? 0 : 1; diff --git a/test/unit/UnitTestPCH.h b/test/unit/UnitTestPCH.h index 3b0479b11..56bbaa29f 100644 --- a/test/unit/UnitTestPCH.h +++ b/test/unit/UnitTestPCH.h @@ -6,6 +6,7 @@ // We need to be sure to have the same STL settings as Assimp #include +#include "assimp.h" // CPPUNIT #include diff --git a/test/unit/utRemoveComponent.cpp b/test/unit/utRemoveComponent.cpp index 4fee4d5f8..1c9e23030 100644 --- a/test/unit/utRemoveComponent.cpp +++ b/test/unit/utRemoveComponent.cpp @@ -50,6 +50,7 @@ void RemoveVCProcessTest :: setUp (void) // COMPILE TEST: MaterialHelper may no add any extra members, // so we don't need a virtual destructor char check[sizeof(MaterialHelper) == sizeof(aiMaterial) ? 10 : -1]; + check[0] = 0; } void RemoveVCProcessTest :: tearDown (void) diff --git a/test/unit/utTriangulate.cpp b/test/unit/utTriangulate.cpp index 7810d7e38..58b9f5a96 100644 --- a/test/unit/utTriangulate.cpp +++ b/test/unit/utTriangulate.cpp @@ -38,8 +38,8 @@ void TriangulateProcessTest :: setUp (void) // construct fully convex input data in ccw winding, xy plane aiVector3D& v = pcMesh->mVertices[pcMesh->mNumVertices++]; v.z = 0.f; - v.x = cos (p * AI_MATH_TWO_PI/face.mNumIndices); - v.y = sin (p * AI_MATH_TWO_PI/face.mNumIndices); + v.x = cos (p * (float)(AI_MATH_TWO_PI)/face.mNumIndices); + v.y = sin (p * (float)(AI_MATH_TWO_PI)/face.mNumIndices); } } } diff --git a/tools/assimp_cmd/Main.cpp b/tools/assimp_cmd/Main.cpp index e9442de27..90d1888d7 100644 --- a/tools/assimp_cmd/Main.cpp +++ b/tools/assimp_cmd/Main.cpp @@ -129,9 +129,9 @@ const aiScene* ImportModel(const ImportData& imp, const std::string& path) unsigned int flags = 0; if (imp.logFile.length()) - flags |= DLS_FILE; + flags |= aiDefaultLogStream_FILE; if (imp.showLog) - flags |= DLS_CERR; + flags |= aiDefaultLogStream_STDERR; DefaultLogger::create(imp.logFile.c_str(),imp.verbose ? Logger::VERBOSE : Logger::NORMAL,flags); } diff --git a/workspaces/vc8/assimp.vcproj b/workspaces/vc8/assimp.vcproj index a624e4d3c..416d10893 100644 --- a/workspaces/vc8/assimp.vcproj +++ b/workspaces/vc8/assimp.vcproj @@ -1132,130 +1132,6 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1324,6 +1200,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -1296,6 +1172,142 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +