diff --git a/Readme.md b/Readme.md index a6f2e3d3d..4ee8a0e90 100644 --- a/Readme.md +++ b/Readme.md @@ -32,8 +32,8 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki #### Supported file formats #### -A full list [is here](http://assimp.org/main_features_formats.html). __Importers__: + - 3D - 3DS - 3MF @@ -109,6 +109,8 @@ __Exporters__: - STEP - glTF 1.0 (partial) - glTF 2.0 (partial) +- 3MF ( experimental ) +- FBX ( experimental ) ### Building ### Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do. diff --git a/code/3DSConverter.cpp b/code/3DSConverter.cpp index cbc6d31d2..081da1bcf 100644 --- a/code/3DSConverter.cpp +++ b/code/3DSConverter.cpp @@ -72,7 +72,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() unsigned int idx( NotSet ); for (unsigned int i = 0; i < mScene->mMaterials.size();++i) { - std::string s = mScene->mMaterials[i].mName; + std::string &s = mScene->mMaterials[i].mName; for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) { *it = static_cast< char >( ::tolower( *it ) ); } diff --git a/code/AMFImporter_Postprocess.cpp b/code/AMFImporter_Postprocess.cpp index f048e1178..192544fcb 100644 --- a/code/AMFImporter_Postprocess.cpp +++ b/code/AMFImporter_Postprocess.cpp @@ -156,10 +156,11 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string& TextureConverted_Index = 0; for(const SPP_Texture& tex_convd: mTexture_Converted) { - if(tex_convd.ID == TextureConverted_ID) - return TextureConverted_Index; - else - TextureConverted_Index++; + if ( tex_convd.ID == TextureConverted_ID ) { + return TextureConverted_Index; + } else { + ++TextureConverted_Index; + } } // diff --git a/code/ASEParser.cpp b/code/ASEParser.cpp index 59af24a10..b953f8d96 100644 --- a/code/ASEParser.cpp +++ b/code/ASEParser.cpp @@ -267,7 +267,9 @@ void Parser::Parse() // at the file extension (ASE, ASK, ASC) // ************************************************************* - if (fmt)iFileFormat = fmt; + if ( fmt ) { + iFileFormat = fmt; + } continue; } // main scene information @@ -427,28 +429,25 @@ void Parser::ParseLV1SoftSkinBlock() // Reserve enough storage vert.mBoneWeights.reserve(numWeights); - for (unsigned int w = 0; w < numWeights;++w) - { - std::string bone; + std::string bone; + for (unsigned int w = 0; w < numWeights;++w) { + bone.clear(); ParseString(bone,"*MESH_SOFTSKINVERTS.Bone"); // Find the bone in the mesh's list std::pair me; me.first = -1; - for (unsigned int n = 0; n < curMesh->mBones.size();++n) - { - if (curMesh->mBones[n].mName == bone) - { + for (unsigned int n = 0; n < curMesh->mBones.size();++n) { + if (curMesh->mBones[n].mName == bone) { me.first = n; break; } } - if (-1 == me.first) - { + if (-1 == me.first) { // We don't have this bone yet, so add it to the list - me.first = (int)curMesh->mBones.size(); - curMesh->mBones.push_back(ASE::Bone(bone)); + me.first = static_cast( curMesh->mBones.size() ); + curMesh->mBones.push_back( ASE::Bone( bone ) ); } ParseLV4MeshFloat( me.second ); @@ -745,6 +744,7 @@ void Parser::ParseLV3MapBlock(Texture& map) // empty the texture won't be used later. // *********************************************************** bool parsePath = true; + std::string temp; while (true) { if ('*' == *filePtr) @@ -753,7 +753,7 @@ void Parser::ParseLV3MapBlock(Texture& map) // type of map if (TokenMatch(filePtr,"MAP_CLASS" ,9)) { - std::string temp; + temp.clear(); if(!ParseString(temp,"*MAP_CLASS")) SkipToNextToken(); if (temp != "Bitmap" && temp != "Normal Bump") diff --git a/code/BVHLoader.cpp b/code/BVHLoader.cpp index dfeeb60ac..0b2a818ae 100644 --- a/code/BVHLoader.cpp +++ b/code/BVHLoader.cpp @@ -199,6 +199,7 @@ aiNode* BVHLoader::ReadNode() Node& internNode = mNodes.back(); // now read the node's contents + std::string siteToken; while( 1) { std::string token = GetNextToken(); @@ -218,7 +219,8 @@ aiNode* BVHLoader::ReadNode() else if( token == "End") { // The real symbol is "End Site". Second part comes in a separate token - std::string siteToken = GetNextToken(); + siteToken.clear(); + siteToken = GetNextToken(); if( siteToken != "Site") ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." ); @@ -262,21 +264,18 @@ aiNode* BVHLoader::ReadEndSite( const std::string& pParentName) aiNode* node = new aiNode( "EndSite_" + pParentName); // now read the node's contents. Only possible entry is "OFFSET" - while( 1) - { - std::string token = GetNextToken(); + std::string token; + while( 1) { + token.clear(); + token = GetNextToken(); // end node's offset - if( token == "OFFSET") - { + if( token == "OFFSET") { ReadNodeOffset( node); - } - else if( token == "}") - { + } else if( token == "}") { // we're done with the end node break; - } else - { + } else { // everything else is a parse error ThrowException( format() << "Unknown keyword \"" << token << "\"." ); } @@ -296,8 +295,10 @@ void BVHLoader::ReadNodeOffset( aiNode* pNode) offset.z = GetNextTokenAsFloat(); // build a transformation matrix from it - pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y, - 0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f); + pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, + 0.0f, 1.0f, 0.0f, offset.y, + 0.0f, 0.0f, 1.0f, offset.z, + 0.0f, 0.0f, 0.0f, 1.0f); } // ------------------------------------------------------------------------------------------------ diff --git a/code/BaseImporter.cpp b/code/BaseImporter.cpp index 67c743285..4782e9e2d 100644 --- a/code/BaseImporter.cpp +++ b/code/BaseImporter.cpp @@ -251,7 +251,8 @@ void BaseImporter::GetExtensionList(std::set& extensions) { /* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile, const void* _magic, unsigned int num, unsigned int offset, unsigned int size) { - ai_assert(size <= 16 && _magic); + ai_assert( size <= 16 ); + ai_assert( _magic ); if (!pIOHandler) { return false; diff --git a/code/ColladaExporter.cpp b/code/ColladaExporter.cpp index dc6b15ec4..96421a532 100644 --- a/code/ColladaExporter.cpp +++ b/code/ColladaExporter.cpp @@ -1269,7 +1269,8 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) mOutput << startstr << "" << endstr; PushTag(); - + + std::string node_idstr; for (size_t a = 0; a < anim->mNumChannels; ++a) { const aiNodeAnim * nodeAnim = anim->mChannels[a]; @@ -1277,7 +1278,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys || nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue; { - const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input"); + node_idstr.clear(); + node_idstr += nodeAnim->mNodeName.data; + node_idstr += std::string( "_matrix-input" ); std::vector frames; for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { @@ -1289,12 +1292,14 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) } { - const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output"); + node_idstr.clear(); + + node_idstr += nodeAnim->mNodeName.data; + node_idstr += std::string("_matrix-output"); std::vector keyframes; keyframes.reserve(nodeAnim->mNumPositionKeys * 16); for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) { - aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue; aiMatrix4x4 ScalingM; // identity ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z; @@ -1361,7 +1366,6 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) PopTag(); mOutput << startstr << "" << endstr; } - } for (size_t a = 0; a < anim->mNumChannels; ++a) { diff --git a/code/ColladaLoader.cpp b/code/ColladaLoader.cpp index 959a905ae..01ba1c400 100644 --- a/code/ColladaLoader.cpp +++ b/code/ColladaLoader.cpp @@ -1121,6 +1121,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars continue; // now check all channels if they affect the current node + std::string targetID, subElement; for( std::vector::const_iterator cit = pSrcAnim->mChannels.begin(); cit != pSrcAnim->mChannels.end(); ++cit) { @@ -1147,7 +1148,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars } if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos) continue; - std::string targetID = srcChannel.mTarget.substr( 0, slashPos); + + targetID.clear(); + targetID = srcChannel.mTarget.substr( 0, slashPos); if( targetID != srcNode->mID) continue; @@ -1160,7 +1163,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1); - std::string subElement = srcChannel.mTarget.substr( dotPos+1); + subElement.clear(); + subElement = srcChannel.mTarget.substr( dotPos+1); if( subElement == "ANGLE") entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle else if( subElement == "X") @@ -1181,7 +1185,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars if (bracketPos != std::string::npos) { entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1); - std::string subElement = srcChannel.mTarget.substr(bracketPos); + subElement.clear(); + subElement = srcChannel.mTarget.substr(bracketPos); if (subElement == "(0)(0)") entry.mSubElement = 0; @@ -1215,7 +1220,6 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars entry.mSubElement = 14; else if (subElement == "(3)(3)") entry.mSubElement = 15; - } // determine which transform step is affected by this channel diff --git a/code/D3MFExporter.cpp b/code/D3MFExporter.cpp index b89e81ce6..204e6f77b 100644 --- a/code/D3MFExporter.cpp +++ b/code/D3MFExporter.cpp @@ -117,6 +117,7 @@ bool D3MFExporter::exportArchive( const char *file ) { if ( nullptr == m_zipArchive ) { return false; } + ok |= exportContentTypes(); ok |= export3DModel(); ok |= exportRelations(); @@ -181,6 +182,8 @@ bool D3MFExporter::export3DModel() { mModelOutput << "<" << XmlTag::resources << ">"; mModelOutput << std::endl; + writeMetaData(); + writeBaseMaterials(); writeObjects(); @@ -209,22 +212,45 @@ void D3MFExporter::writeHeader() { mModelOutput << std::endl; } +void D3MFExporter::writeMetaData() { + if ( nullptr == mScene->mMetaData ) { + return; + } + + const unsigned int numMetaEntries( mScene->mMetaData->mNumProperties ); + if ( 0 == numMetaEntries ) { + return; + } + + const aiString *key; + const aiMetadataEntry *entry(nullptr); + for ( size_t i = 0; i < numMetaEntries; ++i ) { + mScene->mMetaData->Get( i, key, entry ); + std::string k( key->C_Str() ); + aiString value; + mScene->mMetaData->Get( k, value ); + mModelOutput << "<" << XmlTag::meta << " " << XmlTag::meta_name << "=\"" << key->C_Str() << "\">"; + mModelOutput << value.C_Str(); + mModelOutput << "" << std::endl; + } +} + void D3MFExporter::writeBaseMaterials() { mModelOutput << "\n"; + std::string strName, hexDiffuseColor , tmp; for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) { aiMaterial *mat = mScene->mMaterials[ i ]; - std::string strName; aiString name; if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) { strName = "basemat_" + to_string( i ); } else { strName = name.C_Str(); } - std::string hexDiffuseColor; aiColor4D color; if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) { + hexDiffuseColor.clear(); + tmp.clear(); hexDiffuseColor = "#"; - std::string tmp; tmp = DecimalToHexa( color.r ); hexDiffuseColor += tmp; diff --git a/code/D3MFExporter.h b/code/D3MFExporter.h index b553e0ab5..110862b99 100644 --- a/code/D3MFExporter.h +++ b/code/D3MFExporter.h @@ -76,6 +76,7 @@ public: protected: void writeHeader(); + void writeMetaData(); void writeBaseMaterials(); void writeObjects(); void writeMesh( aiMesh *mesh ); diff --git a/code/D3MFImporter.cpp b/code/D3MFImporter.cpp index 3fffa5aeb..2732c73c4 100644 --- a/code/D3MFImporter.cpp +++ b/code/D3MFImporter.cpp @@ -94,14 +94,17 @@ public: scene->mRootNode = new aiNode(); std::vector children; + std::string nodeName; while(ReadToEndElement(D3MF::XmlTag::model)) { - const std::string nodeName( xmlReader->getNodeName() ); + nodeName = xmlReader->getNodeName(); if( nodeName == D3MF::XmlTag::object) { children.push_back(ReadObject(scene)); } else if( nodeName == D3MF::XmlTag::build) { // } else if ( nodeName == D3MF::XmlTag::basematerials ) { ReadBaseMaterials(); + } else if ( nodeName == D3MF::XmlTag::meta ) { + ReadMetadata(); } } @@ -109,19 +112,31 @@ public: scene->mRootNode->mName.Set( "3MF" ); } + // import the metadata + if ( !mMetaData.empty() ) { + const size_t numMeta( mMetaData.size() ); + scene->mMetaData = aiMetadata::Alloc( numMeta ); + for ( size_t i = 0; i < numMeta; ++i ) { + aiString val( mMetaData[ i ].value ); + scene->mMetaData->Set( i, mMetaData[ i ].name, val ); + } + } + + // import the meshes scene->mNumMeshes = static_cast( mMeshes.size()); scene->mMeshes = new aiMesh*[scene->mNumMeshes](); - std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes); + // import the materials scene->mNumMaterials = static_cast( mMatArray.size() ); if ( 0 != scene->mNumMaterials ) { scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ]; std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials ); } + + // create the scenegraph scene->mRootNode->mNumChildren = static_cast(children.size()); scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren](); - std::copy(children.begin(), children.end(), scene->mRootNode->mChildren); } @@ -180,6 +195,21 @@ private: return mesh; } + void ReadMetadata() { + const std::string name = xmlReader->getAttributeValue( D3MF::XmlTag::meta_name.c_str() ); + xmlReader->read(); + const std::string value = xmlReader->getNodeData(); + + if ( name.empty() ) { + return; + } + + MetaEntry entry; + entry.name = name; + entry.value = value; + mMetaData.push_back( entry ); + } + void ImportVertices(aiMesh* mesh) { std::vector vertices; while(ReadToEndElement(D3MF::XmlTag::vertices)) { @@ -253,7 +283,7 @@ private: MatIdArray = it->second; } } - MatIdArray.push_back( newMatIdx ); + MatIdArray.push_back( static_cast( newMatIdx ) ); mMatId2MatArray[ mActiveMatGroup ] = MatIdArray; } @@ -371,8 +401,12 @@ private: return false; } - private: + struct MetaEntry { + std::string name; + std::string value; + }; + std::vector mMetaData; std::vector mMeshes; MatArray mMatArray; unsigned int mActiveMatGroup; diff --git a/code/D3MFOpcPackage.cpp b/code/D3MFOpcPackage.cpp index 2f7c8a25e..3bf545813 100644 --- a/code/D3MFOpcPackage.cpp +++ b/code/D3MFOpcPackage.cpp @@ -288,8 +288,8 @@ bool D3MFZipArchive::Exists(const char* pFile) const { return false; } - std::string rFile(pFile); - std::map::const_iterator it = m_ArchiveMap.find(rFile); + std::string filename(pFile); + std::map::const_iterator it = m_ArchiveMap.find(filename); bool exist( false ); if(it != m_ArchiveMap.end()) { exist = true; diff --git a/code/DXFHelper.h b/code/DXFHelper.h index 5aaf4844f..49ca2814d 100644 --- a/code/DXFHelper.h +++ b/code/DXFHelper.h @@ -169,7 +169,6 @@ public: } private: - LineSplitter splitter; int groupcode; std::string value; diff --git a/code/DefaultIOSystem.cpp b/code/DefaultIOSystem.cpp index 5e50be8bd..36c14e41d 100644 --- a/code/DefaultIOSystem.cpp +++ b/code/DefaultIOSystem.cpp @@ -76,7 +76,7 @@ bool DefaultIOSystem::Exists( const char* pFile) const #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(pFile, strlen(pFile), NULL); + bool isUnicode = IsTextUnicode(pFile, static_cast(strlen(pFile)), NULL); if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT); @@ -110,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode) FILE* file; #ifdef _WIN32 wchar_t fileName16[PATHLIMIT]; - bool isUnicode = IsTextUnicode(strFile, strlen(strFile), NULL ); + bool isUnicode = IsTextUnicode(strFile, static_cast(strlen(strFile)), NULL ); if (isUnicode) { MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT); std::string mode8(strMode); @@ -158,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out) { ai_assert(in && _out); #if defined( _MSC_VER ) || defined( __MINGW32__ ) - bool isUnicode = IsTextUnicode(in, strlen(in), NULL); + bool isUnicode = IsTextUnicode(in, static_cast(strlen(in)), NULL); if (isUnicode) { wchar_t out16[PATHLIMIT]; wchar_t in16[PATHLIMIT]; diff --git a/code/DefaultLogger.cpp b/code/DefaultLogger.cpp index ad101174c..2871a4131 100644 --- a/code/DefaultLogger.cpp +++ b/code/DefaultLogger.cpp @@ -45,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * @brief Implementation of DefaultLogger (and Logger) */ - // Default log streams #include "Win32DebugLogStream.h" #include "StdOStreamLogStream.h" @@ -62,8 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef ASSIMP_BUILD_SINGLETHREADED # include # include - -std::mutex loggerMutex; + std::mutex loggerMutex; #endif namespace Assimp { @@ -76,22 +74,19 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War // ---------------------------------------------------------------------------------- // Represents a log-stream + its error severity -struct LogStreamInfo -{ - unsigned int m_uiErrorSeverity; - LogStream *m_pStream; +struct LogStreamInfo { + unsigned int m_uiErrorSeverity; + LogStream *m_pStream; // Constructor LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) : m_uiErrorSeverity( uiErrorSev ), - m_pStream( pStream ) - { + m_pStream( pStream ) { // empty } // Destructor - ~LogStreamInfo() - { + ~LogStreamInfo() { delete m_pStream; } }; @@ -109,7 +104,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, #ifdef WIN32 return new Win32DebugLogStream(); #else - return NULL; + return nullptr; #endif // Platform-independent default streams @@ -118,7 +113,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, case aiDefaultLogStream_STDOUT: return new StdOStreamLogStream(std::cout); case aiDefaultLogStream_FILE: - return (name && *name ? new FileLogStream(name,io) : NULL); + return (name && *name ? new FileLogStream(name,io) : nullptr ); default: // We don't know this default log stream, so raise an assertion ai_assert(false); @@ -134,34 +129,38 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream streams, Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/, LogSeverity severity /*= NORMAL*/, unsigned int defStreams /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/, - IOSystem* io /*= NULL*/) -{ + IOSystem* io /*= NULL*/) { // enter the mutex here to avoid concurrency problems #ifndef ASSIMP_BUILD_SINGLETHREADED std::lock_guard lock(loggerMutex); #endif - if (m_pLogger && !isNullLogger() ) + if ( m_pLogger && !isNullLogger() ) { delete m_pLogger; + } m_pLogger = new DefaultLogger( severity ); // Attach default log streams // Stream the log to the MSVC debugger? - if (defStreams & aiDefaultLogStream_DEBUGGER) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER)); + if ( defStreams & aiDefaultLogStream_DEBUGGER ) { + m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) ); + } // Stream the log to COUT? - if (defStreams & aiDefaultLogStream_STDOUT) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT)); + if ( defStreams & aiDefaultLogStream_STDOUT ) { + m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) ); + } // Stream the log to CERR? - if (defStreams & aiDefaultLogStream_STDERR) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR)); + if ( defStreams & aiDefaultLogStream_STDERR ) { + m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) ); + } // Stream the log to a file - if (defStreams & aiDefaultLogStream_FILE && name && *name) - m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io)); + if ( defStreams & aiDefaultLogStream_FILE && name && *name ) { + m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) ); + } return m_pLogger; } @@ -200,7 +199,6 @@ void Logger::warn(const char* message) { // ---------------------------------------------------------------------------------- void Logger::error(const char* message) { - // SECURITY FIX: see above if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) { return; @@ -209,23 +207,24 @@ void Logger::error(const char* message) { } // ---------------------------------------------------------------------------------- -void DefaultLogger::set( Logger *logger ) -{ +void DefaultLogger::set( Logger *logger ) { // enter the mutex here to avoid concurrency problems #ifndef ASSIMP_BUILD_SINGLETHREADED std::lock_guard lock(loggerMutex); #endif - if (!logger)logger = &s_pNullLogger; - if (m_pLogger && !isNullLogger() ) + if ( nullptr == logger ) { + logger = &s_pNullLogger; + } + if ( nullptr != m_pLogger && !isNullLogger() ) { delete m_pLogger; + } DefaultLogger::m_pLogger = logger; } // ---------------------------------------------------------------------------------- -bool DefaultLogger::isNullLogger() -{ +bool DefaultLogger::isNullLogger() { return m_pLogger == &s_pNullLogger; } @@ -236,8 +235,7 @@ Logger *DefaultLogger::get() { // ---------------------------------------------------------------------------------- // Kills the only instance -void DefaultLogger::kill() -{ +void DefaultLogger::kill() { // enter the mutex here to avoid concurrency problems #ifndef ASSIMP_BUILD_SINGLETHREADED std::lock_guard lock(loggerMutex); @@ -252,10 +250,10 @@ void DefaultLogger::kill() // ---------------------------------------------------------------------------------- // Debug message -void DefaultLogger::OnDebug( const char* message ) -{ - if ( m_Severity == Logger::NORMAL ) - return; +void DefaultLogger::OnDebug( const char* message ) { + if ( m_Severity == Logger::NORMAL ) { + return; + } static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; char msg[Size]; @@ -266,8 +264,7 @@ void DefaultLogger::OnDebug( const char* message ) // ---------------------------------------------------------------------------------- // Logs an info -void DefaultLogger::OnInfo( const char* message ) -{ +void DefaultLogger::OnInfo( const char* message ){ static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; char msg[Size]; ai_snprintf(msg, Size, "Info, T%u: %s", GetThreadID(), message ); @@ -277,8 +274,7 @@ void DefaultLogger::OnInfo( const char* message ) // ---------------------------------------------------------------------------------- // Logs a warning -void DefaultLogger::OnWarn( const char* message ) -{ +void DefaultLogger::OnWarn( const char* message ) { static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; char msg[Size]; ai_snprintf(msg, Size, "Warn, T%u: %s", GetThreadID(), message ); @@ -288,8 +284,7 @@ void DefaultLogger::OnWarn( const char* message ) // ---------------------------------------------------------------------------------- // Logs an error -void DefaultLogger::OnError( const char* message ) -{ +void DefaultLogger::OnError( const char* message ) { static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16; char msg[ Size ]; ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message ); @@ -299,10 +294,10 @@ void DefaultLogger::OnError( const char* message ) // ---------------------------------------------------------------------------------- // Will attach a new stream -bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) -{ - if (!pStream) +bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) { + if ( nullptr == pStream ) { return false; + } if (0 == severity) { severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging; @@ -312,8 +307,7 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) it != m_StreamArray.end(); ++it ) { - if ( (*it)->m_pStream == pStream ) - { + if ( (*it)->m_pStream == pStream ) { (*it)->m_uiErrorSeverity |= severity; return true; } @@ -326,34 +320,31 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) // ---------------------------------------------------------------------------------- // Detach a stream -bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) -{ - if (!pStream) +bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) { + if ( nullptr == pStream ) { return false; + } if (0 == severity) { severity = SeverityAll; } - for ( StreamIt it = m_StreamArray.begin(); - it != m_StreamArray.end(); - ++it ) - { - if ( (*it)->m_pStream == pStream ) - { + bool res( false ); + for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { + if ( (*it)->m_pStream == pStream ) { (*it)->m_uiErrorSeverity &= ~severity; - if ( (*it)->m_uiErrorSeverity == 0 ) - { + if ( (*it)->m_uiErrorSeverity == 0 ) { // don't delete the underlying stream 'cause the caller gains ownership again - (**it).m_pStream = NULL; + (**it).m_pStream = nullptr; delete *it; m_StreamArray.erase( it ); + res = true; break; } return true; } } - return false; + return res; } // ---------------------------------------------------------------------------------- @@ -361,15 +352,13 @@ bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) DefaultLogger::DefaultLogger(LogSeverity severity) : Logger ( severity ) , noRepeatMsg (false) - , lastLen( 0 ) -{ + , lastLen( 0 ) { lastMsg[0] = '\0'; } // ---------------------------------------------------------------------------------- // Destructor -DefaultLogger::~DefaultLogger() -{ +DefaultLogger::~DefaultLogger() { for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) { // also frees the underlying stream, we are its owner. delete *it; @@ -378,9 +367,8 @@ DefaultLogger::~DefaultLogger() // ---------------------------------------------------------------------------------- // Writes message to stream -void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) -{ - ai_assert(NULL != message); +void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) { + ai_assert(nullptr != message); // Check whether this is a repeated message if (! ::strncmp( message,lastMsg, lastLen-1)) diff --git a/code/EmbedTexturesProcess.cpp b/code/EmbedTexturesProcess.cpp index addfb9746..076339468 100644 --- a/code/EmbedTexturesProcess.cpp +++ b/code/EmbedTexturesProcess.cpp @@ -99,22 +99,22 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) { } bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { - uint32_t imageSize = 0; - std::string imagePath = path; + std::streampos imageSize = 0; + std::string imagePath = path; // Test path directly std::ifstream file(imagePath, std::ios::binary | std::ios::ate); - if ((imageSize = file.tellg()) == -1u) { + if ((imageSize = file.tellg()) == std::streampos(-1)) { DefaultLogger::get()->warn("EmbedTexturesProcess: Cannot find image: " + imagePath + ". Will try to find it in root folder."); // Test path in root path imagePath = mRootPath + path; file.open(imagePath, std::ios::binary | std::ios::ate); - if ((imageSize = file.tellg()) == -1u) { + if ((imageSize = file.tellg()) == std::streampos(-1)) { // Test path basename in root path imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u); file.open(imagePath, std::ios::binary | std::ios::ate); - if ((imageSize = file.tellg()) == -1u) { + if ((imageSize = file.tellg()) == std::streampos(-1)) { DefaultLogger::get()->error("EmbedTexturesProcess: Unable to embed texture: " + path + "."); return false; } @@ -134,7 +134,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { // Add the new texture auto pTexture = new aiTexture(); pTexture->mHeight = 0; // Means that this is still compressed - pTexture->mWidth = imageSize; + pTexture->mWidth = static_cast(imageSize); pTexture->pcData = imageContent; auto extension = path.substr(path.find_last_of('.') + 1u); diff --git a/code/Exporter.cpp b/code/Exporter.cpp index 4951c70ef..49523e658 100644 --- a/code/Exporter.cpp +++ b/code/Exporter.cpp @@ -308,7 +308,8 @@ bool IsVerboseFormat(const aiScene* pScene) { } // ------------------------------------------------------------------------------------------------ -aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) { +aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, + unsigned int pPreprocessing, const ExportProperties* pProperties) { ASSIMP_BEGIN_EXCEPTION_REGION(); // when they create scenes from scratch, users will likely create them not in verbose diff --git a/code/FBXConverter.cpp b/code/FBXConverter.cpp index 9bb023b4e..f3a908dd4 100644 --- a/code/FBXConverter.cpp +++ b/code/FBXConverter.cpp @@ -704,7 +704,7 @@ void Converter::GenerateTransformationNodeChain( const Model& model, std::vector aiMatrix4x4::Scaling( GeometricScaling, chain[ TransformationComp_GeometricScaling ] ); aiVector3D GeometricScalingInverse = GeometricScaling; bool canscale = true; - for (size_t i = 0; i < 3; ++i) { + for (unsigned int i = 0; i < 3; ++i) { if ( std::fabs( GeometricScalingInverse[i] ) > zero_epsilon ) { GeometricScalingInverse[i] = 1.0f / GeometricScaling[i]; } else { @@ -1642,9 +1642,8 @@ void Converter::TrySetTextureProperties( aiMaterial* out_mat, const TextureMap& } void Converter::TrySetTextureProperties( aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, - const std::string& propName, - aiTextureType target, const MeshGeometry* const mesh ) -{ + const std::string& propName, + aiTextureType target, const MeshGeometry* const mesh ) { LayeredTextureMap::const_iterator it = layeredTextures.find( propName ); if ( it == layeredTextures.end() ) { return; @@ -1888,11 +1887,11 @@ void Converter::SetShadingPropertiesCommon( aiMaterial* out_mat, const PropertyT // TransparentColor / TransparencyFactor... gee thanks FBX :rolleyes: const aiColor3D& Transparent = GetColorPropertyFactored( props, "TransparentColor", "TransparencyFactor", ok ); - float CalculatedOpacity = 1.0; + float CalculatedOpacity = 1.0f; if ( ok ) { out_mat->AddProperty( &Transparent, 1, AI_MATKEY_COLOR_TRANSPARENT ); // as calculated by FBX SDK 2017: - CalculatedOpacity = 1.0 - ((Transparent.r + Transparent.g + Transparent.b) / 3.0); + CalculatedOpacity = 1.0f - ((Transparent.r + Transparent.g + Transparent.b) / 3.0f); } // use of TransparencyFactor is inconsistent. diff --git a/code/FBXExportNode.cpp b/code/FBXExportNode.cpp index f218f068d..596901989 100644 --- a/code/FBXExportNode.cpp +++ b/code/FBXExportNode.cpp @@ -182,7 +182,7 @@ void FBX::Node::Begin(Assimp::StreamWriterLE &s) s.PutU4(0); // total property section length // node name - s.PutU1(name.size()); // length of node name + s.PutU1(uint8_t(name.size())); // length of node name s.PutString(name); // node name as raw bytes // property data comes after here @@ -217,8 +217,8 @@ void FBX::Node::EndProperties( ai_assert(pos > property_start); size_t property_section_size = pos - property_start; s.Seek(start_pos + 4); - s.PutU4(num_properties); - s.PutU4(property_section_size); + s.PutU4(uint32_t(num_properties)); + s.PutU4(uint32_t(property_section_size)); s.Seek(pos); } @@ -232,7 +232,7 @@ void FBX::Node::End( // now go back and write initial pos this->end_pos = s.Tell(); s.Seek(start_pos); - s.PutU4(end_pos); + s.PutU4(uint32_t(end_pos)); s.Seek(end_pos); } @@ -251,9 +251,9 @@ void FBX::Node::WritePropertyNode( Node node(name); node.Begin(s); s.PutU1('d'); - s.PutU4(v.size()); // number of elements + s.PutU4(uint32_t(v.size())); // number of elements s.PutU4(0); // no encoding (1 would be zip-compressed) - s.PutU4(v.size() * 8); // data size + s.PutU4(uint32_t(v.size()) * 8); // data size for (auto it = v.begin(); it != v.end(); ++it) { s.PutF8(*it); } node.EndProperties(s, 1); node.End(s, false); @@ -271,9 +271,9 @@ void FBX::Node::WritePropertyNode( Node node(name); node.Begin(s); s.PutU1('i'); - s.PutU4(v.size()); // number of elements + s.PutU4(uint32_t(v.size())); // number of elements s.PutU4(0); // no encoding (1 would be zip-compressed) - s.PutU4(v.size() * 4); // data size + s.PutU4(uint32_t(v.size()) * 4); // data size for (auto it = v.begin(); it != v.end(); ++it) { s.PutI4(*it); } node.EndProperties(s, 1); node.End(s, false); diff --git a/code/FBXExportProperty.cpp b/code/FBXExportProperty.cpp index 1beaa4d27..975e9a09a 100644 --- a/code/FBXExportProperty.cpp +++ b/code/FBXExportProperty.cpp @@ -127,8 +127,8 @@ FBX::Property::Property(const aiMatrix4x4& vm) : type('d'), data(8*16) { double* d = reinterpret_cast(data.data()); - for (size_t c = 0; c < 4; ++c) { - for (size_t r = 0; r < 4; ++r) { + for (unsigned int c = 0; c < 4; ++c) { + for (unsigned int r = 0; r < 4; ++r) { d[4*c+r] = vm[r][c]; } } @@ -164,15 +164,15 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) case 'L': s.PutI8(*(reinterpret_cast(data.data()))); return; case 'S': case 'R': - s.PutU4(data.size()); + s.PutU4(uint32_t(data.size())); for (size_t i = 0; i < data.size(); ++i) { s.PutU1(data[i]); } return; case 'i': N = data.size() / 4; - s.PutU4(N); // number of elements + s.PutU4(uint32_t(N)); // number of elements s.PutU4(0); // no encoding (1 would be zip-compressed) // TODO: compress if large? - s.PutU4(data.size()); // data size + s.PutU4(uint32_t(data.size())); // data size d = data.data(); for (size_t i = 0; i < N; ++i) { s.PutI4((reinterpret_cast(d))[i]); @@ -180,10 +180,10 @@ void FBX::Property::Dump(Assimp::StreamWriterLE &s) return; case 'd': N = data.size() / 8; - s.PutU4(N); // number of elements + s.PutU4(uint32_t(N)); // number of elements s.PutU4(0); // no encoding (1 would be zip-compressed) // TODO: compress if large? - s.PutU4(data.size()); // data size + s.PutU4(uint32_t(data.size())); // data size d = data.data(); for (size_t i = 0; i < N; ++i) { s.PutF8((reinterpret_cast(d))[i]); diff --git a/code/FBXExporter.cpp b/code/FBXExporter.cpp index a2e6024ed..9ba5c0333 100644 --- a/code/FBXExporter.cpp +++ b/code/FBXExporter.cpp @@ -460,7 +460,7 @@ size_t count_images(const aiScene* scene) { ){ const aiTextureType textype = static_cast(tt); const size_t texcount = mat->GetTextureCount(textype); - for (size_t j = 0; j < texcount; ++j) { + for (unsigned int j = 0; j < texcount; ++j) { mat->GetTexture(textype, j, &texpath); images.insert(std::string(texpath.C_Str())); } @@ -593,7 +593,7 @@ void FBXExporter::WriteDefinitions () // Model / FbxNode // <~~ node heirarchy - count = count_nodes(mScene->mRootNode) - 1; // (not counting root node) + count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node) if (count) { n = FBX::Node("ObjectType", Property("Model")); n.AddChild("Count", count); @@ -763,7 +763,7 @@ void FBXExporter::WriteDefinitions () // Video / FbxVideo // one for each image file. - count = count_images(mScene); + count = int32_t(count_images(mScene)); if (count) { n = FBX::Node("ObjectType", Property("Video")); n.AddChild("Count", count); @@ -792,7 +792,7 @@ void FBXExporter::WriteDefinitions () // Texture / FbxFileTexture // <~~ aiTexture - count = count_textures(mScene); + count = int32_t(count_textures(mScene)); if (count) { n = FBX::Node("ObjectType", Property("Texture")); n.AddChild("Count", count); @@ -848,7 +848,7 @@ void FBXExporter::WriteDefinitions () } // Deformer - count = count_deformers(mScene); + count = int32_t(count_deformers(mScene)); if (count) { n = FBX::Node("ObjectType", Property("Deformer")); n.AddChild("Count", count); @@ -943,7 +943,7 @@ void FBXExporter::WriteObjects () std::vector vertex_indices; // map of vertex value to its index in the data vector std::map index_by_vertex_value; - size_t index = 0; + int32_t index = 0; for (size_t vi = 0; vi < m->mNumVertices; ++vi) { aiVector3D vtx = m->mVertices[vi]; auto elem = index_by_vertex_value.find(vtx); @@ -955,7 +955,7 @@ void FBXExporter::WriteObjects () flattened_vertices.push_back(vtx[2]); ++index; } else { - vertex_indices.push_back(elem->second); + vertex_indices.push_back(int32_t(elem->second)); } } FBX::Node::WritePropertyNode( @@ -1052,7 +1052,7 @@ void FBXExporter::WriteObjects () std::vector uv_data; std::vector uv_indices; std::map index_by_uv; - size_t index = 0; + int32_t index = 0; for (size_t fi = 0; fi < m->mNumFaces; ++fi) { const aiFace &f = m->mFaces[fi]; for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) { @@ -1062,7 +1062,7 @@ void FBXExporter::WriteObjects () if (elem == index_by_uv.end()) { index_by_uv[uv] = index; uv_indices.push_back(index); - for (size_t x = 0; x < m->mNumUVComponents[uvi]; ++x) { + for (unsigned int x = 0; x < m->mNumUVComponents[uvi]; ++x) { uv_data.push_back(uv[x]); } ++index; @@ -1208,13 +1208,13 @@ void FBXExporter::WriteObjects () // and usualy are completely ignored when loading. // One notable exception is the "Opacity" property, // which Blender uses as (1.0 - alpha). - c.r = 0; c.g = 0; c.b = 0; + c.r = 0.0f; c.g = 0.0f; c.b = 0.0f; m->Get(AI_MATKEY_COLOR_EMISSIVE, c); p.AddP70vector("Emissive", c.r, c.g, c.b); - c.r = 0.2; c.g = 0.2; c.b = 0.2; + c.r = 0.2f; c.g = 0.2f; c.b = 0.2f; m->Get(AI_MATKEY_COLOR_AMBIENT, c); p.AddP70vector("Ambient", c.r, c.g, c.b); - c.r = 0.8; c.g = 0.8; c.b = 0.8; + c.r = 0.8f; c.g = 0.8f; c.b = 0.8f; m->Get(AI_MATKEY_COLOR_DIFFUSE, c); p.AddP70vector("Diffuse", c.r, c.g, c.b); // The FBX SDK determines "Opacity" from transparency colour (RGB) @@ -1223,29 +1223,29 @@ void FBXExporter::WriteObjects () // so we should take it from AI_MATKEY_OPACITY if possible. // It might make more sense to use TransparencyFactor, // but Blender actually loads "Opacity" correctly, so let's use it. - f = 1.0; + f = 1.0f; if (m->Get(AI_MATKEY_COLOR_TRANSPARENT, c) == aiReturn_SUCCESS) { - f = 1.0 - ((c.r + c.g + c.b) / 3); + f = 1.0f - ((c.r + c.g + c.b) / 3.0f); } m->Get(AI_MATKEY_OPACITY, f); p.AddP70double("Opacity", f); if (phong) { // specular color is multiplied by shininess_strength - c.r = 0.2; c.g = 0.2; c.b = 0.2; + c.r = 0.2f; c.g = 0.2f; c.b = 0.2f; m->Get(AI_MATKEY_COLOR_SPECULAR, c); - f = 1.0; + f = 1.0f; m->Get(AI_MATKEY_SHININESS_STRENGTH, f); p.AddP70vector("Specular", f*c.r, f*c.g, f*c.b); - f = 20.0; + f = 20.0f; m->Get(AI_MATKEY_SHININESS, f); p.AddP70double("Shininess", f); // Legacy "Reflectivity" is F*F*((R+G+B)/3), // where F is the proportion of light reflected (AKA reflectivity), // and RGB is the reflective colour of the material. // No idea why, but we might as well set it the same way. - f = 0.0; + f = 0.0f; m->Get(AI_MATKEY_REFLECTIVITY, f); - c.r = 1.0, c.g = 1.0, c.b = 1.0; + c.r = 1.0f, c.g = 1.0f, c.b = 1.0f; m->Get(AI_MATKEY_COLOR_REFLECTIVE, c); p.AddP70double("Reflectivity", f*f*((c.r+c.g+c.b)/3.0)); } @@ -1269,7 +1269,7 @@ void FBXExporter::WriteObjects () const aiTextureType textype = static_cast(tt); const size_t texcount = mat->GetTextureCount(textype); for (size_t j = 0; j < texcount; ++j) { - mat->GetTexture(textype, j, &texpath); + mat->GetTexture(textype, (unsigned int)j, &texpath); const std::string texstring = texpath.C_Str(); auto elem = uid_by_image.find(texstring); if (elem == uid_by_image.end()) { @@ -1591,7 +1591,7 @@ void FBXExporter::WriteObjects () std::vector vertex_indices; // map of vertex value to its index in the data vector std::map index_by_vertex_value; - size_t index = 0; + int32_t index = 0; for (size_t vi = 0; vi < m->mNumVertices; ++vi) { aiVector3D vtx = m->mVertices[vi]; auto elem = index_by_vertex_value.find(vtx); @@ -1600,7 +1600,7 @@ void FBXExporter::WriteObjects () index_by_vertex_value[vtx] = index; ++index; } else { - vertex_indices.push_back(elem->second); + vertex_indices.push_back(int32_t(elem->second)); } } @@ -1616,7 +1616,7 @@ void FBXExporter::WriteObjects () // as it can be instanced to many nodes. // All we can do is assume no instancing, // and take the first node we find that contains the mesh. - aiNode* mesh_node = get_node_for_mesh(mi, mScene->mRootNode); + aiNode* mesh_node = get_node_for_mesh((unsigned int)mi, mScene->mRootNode); aiMatrix4x4 mesh_xform = get_world_transform(mesh_node, mScene); // now make a subdeformer for each bone in the skeleton @@ -1682,7 +1682,7 @@ void FBXExporter::WriteObjects () // this should be the same as the bone's mOffsetMatrix. // if it's not the same, the skeleton isn't in the bind pose. - const float epsilon = 1e-5; // some error is to be expected + const float epsilon = 1e-5f; // some error is to be expected bool bone_xform_okay = true; if (b && ! tr.Equal(b->mOffsetMatrix, epsilon)) { not_in_bind_pose.insert(b); @@ -2002,7 +2002,7 @@ void FBXExporter::WriteModelNodes( transform_chain.emplace_back(elem->first, t); break; case 'r': // rotation - r *= DEG; + r *= float(DEG); transform_chain.emplace_back(elem->first, r); break; case 's': // scale diff --git a/code/Importer.cpp b/code/Importer.cpp index feddadf58..6422ca6d0 100644 --- a/code/Importer.cpp +++ b/code/Importer.cpp @@ -622,7 +622,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) if (s != std::string::npos) { DefaultLogger::get()->info("File extension not known, trying signature-based detection"); for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) { - if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) { imp = pimpl->mImporter[a]; break; @@ -947,6 +946,7 @@ BaseImporter* Importer::GetImporter (const char* szExtension) const size_t Importer::GetImporterIndex (const char* szExtension) const { ai_assert(szExtension); + ASSIMP_BEGIN_EXCEPTION_REGION(); // skip over wildcard and dot characters at string head -- diff --git a/code/Importer/IFC/IFCLoader.cpp b/code/Importer/IFC/IFCLoader.cpp index 5acc89545..9faf68cbb 100644 --- a/code/Importer/IFC/IFCLoader.cpp +++ b/code/Importer/IFC/IFCLoader.cpp @@ -583,9 +583,8 @@ typedef std::map Metadata; // ------------------------------------------------------------------------------------------------ void ProcessMetadata(const Schema_2x3::ListOf< Schema_2x3::Lazy< Schema_2x3::IfcProperty >, 1, 0 >& set, ConversionData& conv, Metadata& properties, - const std::string& prefix = "", - unsigned int nest = 0) -{ + const std::string& prefix = "", + unsigned int nest = 0) { for(const Schema_2x3::IfcProperty& property : set) { const std::string& key = prefix.length() > 0 ? (prefix + "." + property.Name) : property.Name; if (const Schema_2x3::IfcPropertySingleValue* const singleValue = property.ToPtr()) { diff --git a/code/ObjExporter.cpp b/code/ObjExporter.cpp index 9beb418f3..d08b5f859 100644 --- a/code/ObjExporter.cpp +++ b/code/ObjExporter.cpp @@ -132,18 +132,18 @@ ObjExporter::ObjExporter(const char* _filename, const aiScene* pScene, bool noMt mOutputMat.precision(16); WriteGeometryFile(noMtl); - if (!noMtl) + if ( !noMtl ) { WriteMaterialFile(); + } } // ------------------------------------------------------------------------------------------------ ObjExporter::~ObjExporter() { - + // empty } // ------------------------------------------------------------------------------------------------ -std::string ObjExporter :: GetMaterialLibName() -{ +std::string ObjExporter::GetMaterialLibName() { // within the Obj file, we use just the relative file name with the path stripped const std::string& s = GetMaterialLibFileName(); std::string::size_type il = s.find_last_of("/\\"); @@ -158,8 +158,9 @@ std::string ObjExporter :: GetMaterialLibName() std::string ObjExporter::GetMaterialLibFileName() { // Remove existing .obj file extension so that the final material file name will be fileName.mtl and not fileName.obj.mtl size_t lastdot = filename.find_last_of('.'); - if (lastdot != std::string::npos) - return filename.substr(0, lastdot) + MaterialExt; + if ( lastdot != std::string::npos ) { + return filename.substr( 0, lastdot ) + MaterialExt; + } return filename + MaterialExt; } @@ -172,8 +173,7 @@ void ObjExporter::WriteHeader(std::ostringstream& out) { } // ------------------------------------------------------------------------------------------------ -std::string ObjExporter::GetMaterialName(unsigned int index) -{ +std::string ObjExporter::GetMaterialName(unsigned int index) { const aiMaterial* const mat = pScene->mMaterials[index]; if ( nullptr == mat ) { static const std::string EmptyStr; @@ -191,8 +191,7 @@ std::string ObjExporter::GetMaterialName(unsigned int index) } // ------------------------------------------------------------------------------------------------ -void ObjExporter::WriteMaterialFile() -{ +void ObjExporter::WriteMaterialFile() { WriteHeader(mOutputMat); for(unsigned int i = 0; i < pScene->mNumMaterials; ++i) { @@ -310,8 +309,9 @@ void ObjExporter::WriteGeometryFile(bool noMtl) { if (!m.name.empty()) { mOutput << "g " << m.name << endl; } - if (!noMtl) + if ( !noMtl ) { mOutput << "usemtl " << m.matname << endl; + } for(const Face& f : m.faces) { mOutput << f.kind << ' '; @@ -382,7 +382,7 @@ void ObjExporter::colIndexMap::getColors( std::vector &colors ) { // ------------------------------------------------------------------------------------------------ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4x4& mat) { - mMeshes.push_back(MeshInstance()); + mMeshes.push_back(MeshInstance() ); MeshInstance& mesh = mMeshes.back(); mesh.name = std::string( name.data, name.length ); @@ -436,8 +436,7 @@ void ObjExporter::AddMesh(const aiString& name, const aiMesh* m, const aiMatrix4 } // ------------------------------------------------------------------------------------------------ -void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) -{ +void ObjExporter::AddNode(const aiNode* nd, const aiMatrix4x4& mParent) { const aiMatrix4x4& mAbs = mParent * nd->mTransformation; for(unsigned int i = 0; i < nd->mNumMeshes; ++i) { diff --git a/code/ObjFileImporter.cpp b/code/ObjFileImporter.cpp index 02d6ac581..bce94ebbb 100644 --- a/code/ObjFileImporter.cpp +++ b/code/ObjFileImporter.cpp @@ -207,30 +207,24 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene // Create the root node of the scene pScene->mRootNode = new aiNode; - if ( !pModel->m_ModelName.empty() ) - { + if ( !pModel->m_ModelName.empty() ) { // Set the name of the scene pScene->mRootNode->mName.Set(pModel->m_ModelName); - } - else - { + } else { // This is a fatal error, so break down the application ai_assert(false); } // Create nodes for the whole scene std::vector MeshArray; - for (size_t index = 0; index < pModel->m_Objects.size(); index++) - { + for (size_t index = 0; index < pModel->m_Objects.size(); ++index ) { createNodes(pModel, pModel->m_Objects[ index ], pScene->mRootNode, pScene, MeshArray); } // Create mesh pointer buffer for this scene - if (pScene->mNumMeshes > 0) - { + if (pScene->mNumMeshes > 0) { pScene->mMeshes = new aiMesh*[ MeshArray.size() ]; - for (size_t index =0; index < MeshArray.size(); index++) - { + for (size_t index =0; index < MeshArray.size(); ++index ) { pScene->mMeshes[ index ] = MeshArray[ index ]; } } @@ -261,8 +255,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile appendChildToParentNode( pParent, pNode ); } - for ( size_t i=0; i< pObject->m_Meshes.size(); i++ ) - { + for ( size_t i=0; i< pObject->m_Meshes.size(); ++i ) { unsigned int meshId = pObject->m_Meshes[ i ]; aiMesh *pMesh = createTopology( pModel, pObject, meshId ); if( pMesh ) { @@ -275,8 +268,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile } // Create all nodes from the sub-objects stored in the current object - if ( !pObject->m_SubObjects.empty() ) - { + if ( !pObject->m_SubObjects.empty() ) { size_t numChilds = pObject->m_SubObjects.size(); pNode->mNumChildren = static_cast( numChilds ); pNode->mChildren = new aiNode*[ numChilds ]; @@ -286,16 +278,14 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model* pModel, const ObjFile // Set mesh instances into scene- and node-instances const size_t meshSizeDiff = MeshArray.size()- oldMeshSize; - if ( meshSizeDiff > 0 ) - { + if ( meshSizeDiff > 0 ) { pNode->mMeshes = new unsigned int[ meshSizeDiff ]; pNode->mNumMeshes = static_cast( meshSizeDiff ); size_t index = 0; - for (size_t i = oldMeshSize; i < MeshArray.size(); i++) - { + for (size_t i = oldMeshSize; i < MeshArray.size(); ++i ) { pNode->mMeshes[ index ] = pScene->mNumMeshes; pScene->mNumMeshes++; - index++; + ++index; } } diff --git a/code/ObjFileParser.cpp b/code/ObjFileParser.cpp index ae95edbcb..7cd2d36c2 100644 --- a/code/ObjFileParser.cpp +++ b/code/ObjFileParser.cpp @@ -612,13 +612,14 @@ void ObjFileParser::getMaterialLib() { if ( '/' != *path.rbegin() ) { path += '/'; } - absName = path + strMatName; + absName += path; + absName += strMatName; } else { absName = strMatName; } - IOStream *pFile = m_pIO->Open( absName ); - if (!pFile ) { + IOStream *pFile = m_pIO->Open( absName ); + if ( nullptr == pFile ) { DefaultLogger::get()->error("OBJ: Unable to locate material file " + strMatName); std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl"; DefaultLogger::get()->info("OBJ: Opening fallback material file " + strMatFallbackName); diff --git a/code/OgreParsingUtils.h b/code/OgreParsingUtils.h index a77b94121..c6b6e0caf 100644 --- a/code/OgreParsingUtils.h +++ b/code/OgreParsingUtils.h @@ -52,27 +52,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include -namespace Assimp -{ -namespace Ogre -{ +namespace Assimp { +namespace Ogre { /// Returns a lower cased copy of @s. -static inline std::string ToLower(std::string s) +static AI_FORCE_INLINE +std::string ToLower(std::string s) { std::transform(s.begin(), s.end(), s.begin(), ::tolower); return s; } /// Returns if @c s ends with @c suffix. If @c caseSensitive is false, both strings will be lower cased before matching. -static inline bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) -{ - if (s.empty() || suffix.empty()) - { +static AI_FORCE_INLINE +bool EndsWith(const std::string &s, const std::string &suffix, bool caseSensitive = true) { + if (s.empty() || suffix.empty()) { return false; - } - else if (s.length() < suffix.length()) - { + } else if (s.length() < suffix.length()) { return false; } @@ -82,48 +78,43 @@ static inline bool EndsWith(const std::string &s, const std::string &suffix, boo size_t len = suffix.length(); std::string sSuffix = s.substr(s.length()-len, len); + return (ASSIMP_stricmp(sSuffix, suffix) == 0); } // Below trim functions adapted from http://stackoverflow.com/questions/216823/whats-the-best-way-to-trim-stdstring /// Trim from start -static inline std::string &TrimLeft(std::string &s, bool newlines = true) -{ - if (!newlines) - { +static AI_FORCE_INLINE +std::string &TrimLeft(std::string &s, bool newlines = true) { + if (!newlines) { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpace(c); })); - } - else - { + } else { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine(c); })); } return s; } /// Trim from end -static inline std::string &TrimRight(std::string &s, bool newlines = true) -{ - if (!newlines) - { +static AI_FORCE_INLINE +std::string &TrimRight(std::string &s, bool newlines = true) { + if (!newlines) { s.erase(std::find_if(s.rbegin(), s.rend(), [](char c) { return !Assimp::IsSpace(c); }).base(),s.end()); - } - else - { + } else { s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](char c) { return !Assimp::IsSpaceOrNewLine(c); })); } return s; } /// Trim from both ends -static inline std::string &Trim(std::string &s, bool newlines = true) -{ +static AI_FORCE_INLINE +std::string &Trim(std::string &s, bool newlines = true) { return TrimLeft(TrimRight(s, newlines), newlines); } /// Skips a line from current @ss position until a newline. Returns the skipped part. -static inline std::string SkipLine(std::stringstream &ss) -{ +static AI_FORCE_INLINE +std::string SkipLine(std::stringstream &ss) { std::string skipped; getline(ss, skipped); return skipped; @@ -131,8 +122,8 @@ static inline std::string SkipLine(std::stringstream &ss) /// Skips a line and reads next element from @c ss to @c nextElement. /** @return Skipped line content until newline. */ -static inline std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) -{ +static AI_FORCE_INLINE +std::string NextAfterNewLine(std::stringstream &ss, std::string &nextElement) { std::string skipped = SkipLine(ss); ss >> nextElement; return skipped; diff --git a/code/OgreXmlSerializer.cpp b/code/OgreXmlSerializer.cpp index 78acaa7fd..12b2bcbd9 100644 --- a/code/OgreXmlSerializer.cpp +++ b/code/OgreXmlSerializer.cpp @@ -213,18 +213,18 @@ std::string &OgreXmlSerializer::SkipCurrentNode() DefaultLogger::get()->debug("Skipping node <" + m_currentNodeName + ">"); #endif - for(;;) - { - if (!m_reader->read()) - { + for(;;) { + if (!m_reader->read()) { m_currentNodeName = ""; return m_currentNodeName; } - if (m_reader->getNodeType() != irr::io::EXN_ELEMENT_END) + if ( m_reader->getNodeType() != irr::io::EXN_ELEMENT_END ) { continue; - else if (std::string(m_reader->getNodeName()) == m_currentNodeName) + } else if ( std::string( m_reader->getNodeName() ) == m_currentNodeName ) { break; + } } + return NextNode(); } @@ -303,17 +303,16 @@ static const char *anZ = "z"; // Mesh -MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) -{ +MeshXml *OgreXmlSerializer::ImportMesh(XmlReader *reader) { OgreXmlSerializer serializer(reader); MeshXml *mesh = new MeshXml(); serializer.ReadMesh(mesh); + return mesh; } -void OgreXmlSerializer::ReadMesh(MeshXml *mesh) -{ +void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { if (NextNode() != nnMesh) { throw DeadlyImportError("Root node is <" + m_currentNodeName + "> expecting "); } diff --git a/code/SceneCombiner.cpp b/code/SceneCombiner.cpp index 8647bd1ba..589291131 100644 --- a/code/SceneCombiner.cpp +++ b/code/SceneCombiner.cpp @@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include #include "time.h" #include @@ -806,8 +807,9 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, for (std::vector::const_iterator it = begin; it != end;++it) { if ((*it)->mNormals) { ::memcpy(pv2,(*it)->mNormals,(*it)->mNumVertices*sizeof(aiVector3D)); + } else { + DefaultLogger::get()->warn( "JoinMeshes: Normals expected but input mesh contains no normals" ); } - else DefaultLogger::get()->warn("JoinMeshes: Normals expected but input mesh contains no normals"); pv2 += (*it)->mNumVertices; } } @@ -817,28 +819,29 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, pv2 = out->mTangents = new aiVector3D[out->mNumVertices]; aiVector3D* pv2b = out->mBitangents = new aiVector3D[out->mNumVertices]; - for (std::vector::const_iterator it = begin; it != end;++it) { + for (std::vector::const_iterator it = begin; it != end;++it) { if ((*it)->mTangents) { ::memcpy(pv2, (*it)->mTangents, (*it)->mNumVertices*sizeof(aiVector3D)); ::memcpy(pv2b,(*it)->mBitangents,(*it)->mNumVertices*sizeof(aiVector3D)); + } else { + DefaultLogger::get()->warn( "JoinMeshes: Tangents expected but input mesh contains no tangents" ); } - else DefaultLogger::get()->warn("JoinMeshes: Tangents expected but input mesh contains no tangents"); pv2 += (*it)->mNumVertices; pv2b += (*it)->mNumVertices; } } // copy texture coordinates unsigned int n = 0; - while ((**begin).HasTextureCoords(n)) { + while ((**begin).HasTextureCoords(n)) { out->mNumUVComponents[n] = (*begin)->mNumUVComponents[n]; pv2 = out->mTextureCoords[n] = new aiVector3D[out->mNumVertices]; for (std::vector::const_iterator it = begin; it != end;++it) { - if ((*it)->mTextureCoords[n]) { ::memcpy(pv2,(*it)->mTextureCoords[n],(*it)->mNumVertices*sizeof(aiVector3D)); + } else { + DefaultLogger::get()->warn( "JoinMeshes: UVs expected but input mesh contains no UVs" ); } - else DefaultLogger::get()->warn("JoinMeshes: UVs expected but input mesh contains no UVs"); pv2 += (*it)->mNumVertices; } ++n; @@ -848,11 +851,11 @@ void SceneCombiner::MergeMeshes(aiMesh** _out, unsigned int /*flags*/, while ((**begin).HasVertexColors(n)) { aiColor4D* pv2 = out->mColors[n] = new aiColor4D[out->mNumVertices]; for (std::vector::const_iterator it = begin; it != end;++it) { - if ((*it)->mColors[n]) { ::memcpy(pv2,(*it)->mColors[n],(*it)->mNumVertices*sizeof(aiColor4D)); + } else { + DefaultLogger::get()->warn( "JoinMeshes: VCs expected but input mesh contains no VCs" ); } - else DefaultLogger::get()->warn("JoinMeshes: VCs expected but input mesh contains no VCs"); pv2 += (*it)->mNumVertices; } ++n; @@ -1001,7 +1004,12 @@ void SceneCombiner::CopyScene(aiScene** _dest,const aiScene* src,bool allocate) *_dest = new aiScene(); } aiScene* dest = *_dest; - ai_assert(dest); + ai_assert(nullptr != dest); + + // copy metadata + if ( nullptr != src->mMetaData ) { + dest->mMetaData = new aiMetadata( *src->mMetaData ); + } // copy animations dest->mNumAnimations = src->mNumAnimations; diff --git a/code/XFileParser.cpp b/code/XFileParser.cpp index bda59ba59..4dd2c990b 100644 --- a/code/XFileParser.cpp +++ b/code/XFileParser.cpp @@ -1076,8 +1076,8 @@ std::string XFileParser::GetNextToken() { return s; } len = ReadBinDWord(); - const int bounds( mEnd - mP ); - const int iLen( len ); + const int bounds = int( mEnd - mP ); + const int iLen = int( len ); if ( iLen < 0 ) { return s; } diff --git a/include/assimp/DefaultLogger.hpp b/include/assimp/DefaultLogger.hpp index d6a88b0f3..1f0c899be 100644 --- a/include/assimp/DefaultLogger.hpp +++ b/include/assimp/DefaultLogger.hpp @@ -131,9 +131,7 @@ public: bool detatchStream(LogStream *pStream, unsigned int severity); - private: - // ---------------------------------------------------------------------- /** @briefPrivate construction for internal use by create(). * @param severity Logging granularity */ @@ -143,8 +141,6 @@ private: /** @briefDestructor */ ~DefaultLogger(); -private: - /** @brief Logs debug infos, only been written when severity level VERBOSE is set */ void OnDebug(const char* message); diff --git a/include/assimp/ParsingUtils.h b/include/assimp/ParsingUtils.h index 40e183a5c..4553072db 100644 --- a/include/assimp/ParsingUtils.h +++ b/include/assimp/ParsingUtils.h @@ -115,8 +115,8 @@ bool IsSpaceOrNewLine( char_t in) { // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out) -{ +AI_FORCE_INLINE +bool SkipSpaces( const char_t* in, const char_t** out) { while( *in == ( char_t )' ' || *in == ( char_t )'\t' ) { ++in; } @@ -126,15 +126,15 @@ AI_FORCE_INLINE bool SkipSpaces( const char_t* in, const char_t** out) // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipSpaces( const char_t** inout) -{ +AI_FORCE_INLINE +bool SkipSpaces( const char_t** inout) { return SkipSpaces(*inout,inout); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out) -{ +AI_FORCE_INLINE +bool SkipLine( const char_t* in, const char_t** out) { while( *in != ( char_t )'\r' && *in != ( char_t )'\n' && *in != ( char_t )'\0' ) { ++in; } @@ -149,15 +149,15 @@ AI_FORCE_INLINE bool SkipLine( const char_t* in, const char_t** out) // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipLine( const char_t** inout) -{ +AI_FORCE_INLINE +bool SkipLine( const char_t** inout) { return SkipLine(*inout,inout); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) -{ +AI_FORCE_INLINE +bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) { while( *in == ( char_t )' ' || *in == ( char_t )'\t' || *in == ( char_t )'\r' || *in == ( char_t )'\n' ) { ++in; } @@ -167,15 +167,15 @@ AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t* in, const char_t** out) // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool SkipSpacesAndLineEnd( const char_t** inout) -{ +AI_FORCE_INLINE +bool SkipSpacesAndLineEnd( const char_t** inout) { return SkipSpacesAndLineEnd(*inout,inout); } // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) -{ +AI_FORCE_INLINE +bool GetNextLine( const char_t*& buffer, char_t out[ BufferSize ] ) { if( ( char_t )'\0' == *buffer ) { return false; } @@ -203,7 +203,8 @@ AI_FORCE_INLINE bool IsNumeric( char_t in) // --------------------------------------------------------------------------------- template -AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len) +AI_FORCE_INLINE +bool TokenMatch(char_t*& in, const char* token, unsigned int len) { if (!::strncmp(token,in,len) && IsSpaceOrNewLine(in[len])) { if (in[len] != '\0') { @@ -223,26 +224,32 @@ AI_FORCE_INLINE bool TokenMatch(char_t*& in, const char* token, unsigned int len * @param token Token to check for * @param len Number of characters to check */ -AI_FORCE_INLINE bool TokenMatchI(const char*& in, const char* token, unsigned int len) -{ +AI_FORCE_INLINE +bool TokenMatchI(const char*& in, const char* token, unsigned int len) { if (!ASSIMP_strincmp(token,in,len) && IsSpaceOrNewLine(in[len])) { in += len+1; return true; } return false; } + // --------------------------------------------------------------------------------- -AI_FORCE_INLINE void SkipToken(const char*& in) -{ +AI_FORCE_INLINE +void SkipToken(const char*& in) { SkipSpaces(&in); - while (!IsSpaceOrNewLine(*in))++in; + while ( !IsSpaceOrNewLine( *in ) ) { + ++in; + } } + // --------------------------------------------------------------------------------- -AI_FORCE_INLINE std::string GetNextToken(const char*& in) -{ +AI_FORCE_INLINE +std::string GetNextToken(const char*& in) { SkipSpacesAndLineEnd(&in); const char* cur = in; - while (!IsSpaceOrNewLine(*in))++in; + while ( !IsSpaceOrNewLine( *in ) ) { + ++in; + } return std::string(cur,(size_t)(in-cur)); } diff --git a/include/assimp/StreamWriter.h b/include/assimp/StreamWriter.h index e955a7255..6f492df90 100644 --- a/include/assimp/StreamWriter.h +++ b/include/assimp/StreamWriter.h @@ -104,7 +104,7 @@ public: // --------------------------------------------------------------------- ~StreamWriter() { - stream->Write(&buffer[0], 1, buffer.size()); + stream->Write(buffer.data(), 1, buffer.size()); stream->Flush(); } @@ -114,7 +114,7 @@ public: /** Flush the contents of the internal buffer, and the output IOStream */ void Flush() { - stream->Write(&buffer[0], 1, buffer.size()); + stream->Write(buffer.data(), 1, buffer.size()); stream->Flush(); buffer.clear(); cursor = 0; diff --git a/include/assimp/StringComparison.h b/include/assimp/StringComparison.h index 1fada49dd..aea7f001a 100644 --- a/include/assimp/StringComparison.h +++ b/include/assimp/StringComparison.h @@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define INCLUDED_AI_STRING_WORKERS_H #include +#include #include "StringComparison.h" #include @@ -72,8 +73,8 @@ namespace Assimp { * @param number Number to be written * @return Length of the output string, excluding the '\0' */ -inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) -{ +AI_FORCE_INLINE +unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) { ai_assert(NULL != out); // write the unary minus to indicate we have a negative number @@ -91,7 +92,7 @@ inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) const unsigned int digit = number / cur; if (mustPrint || digit > 0 || 1 == cur) { - // print all future zeroes from now + // print all future zeroe's from now mustPrint = true; *out++ = '0'+static_cast(digit); @@ -116,8 +117,8 @@ inline unsigned int ASSIMP_itoa10( char* out, unsigned int max, int32_t number) * size of the array automatically. */ template -inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) -{ +AI_FORCE_INLINE +unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) { return ASSIMP_itoa10(out,length,number); } @@ -132,9 +133,10 @@ inline unsigned int ASSIMP_itoa10( char(& out)[length], int32_t number) * @param s2 Second input string * @return 0 if the given strings are identical */ -inline int ASSIMP_stricmp(const char *s1, const char *s2) -{ - ai_assert(NULL != s1 && NULL != s2); +AI_FORCE_INLINE +int ASSIMP_stricmp(const char *s1, const char *s2) { + ai_assert( NULL != s1 ); + ai_assert( NULL != s2 ); #if (defined _MSC_VER) @@ -161,8 +163,8 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2) * @param b Second string * @return 0 if a == b */ -inline int ASSIMP_stricmp(const std::string& a, const std::string& b) -{ +AI_FORCE_INLINE +int ASSIMP_stricmp(const std::string& a, const std::string& b) { int i = (int)b.length()-(int)a.length(); return (i ? i : ASSIMP_stricmp(a.c_str(),b.c_str())); } @@ -179,10 +181,13 @@ inline int ASSIMP_stricmp(const std::string& a, const std::string& b) * @param n Macimum number of characters to compare * @return 0 if the given strings are identical */ -inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) -{ - ai_assert(NULL != s1 && NULL != s2); - if (!n)return 0; +AI_FORCE_INLINE +int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) { + ai_assert( NULL != s1 ); + ai_assert( NULL != s2 ); + if ( !n ) { + return 0; + } #if (defined _MSC_VER) @@ -213,14 +218,16 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) * * todo: move somewhere where it fits better in than here */ -inline unsigned int integer_pow (unsigned int base, unsigned int power) -{ +AI_FORCE_INLINE +unsigned int integer_pow( unsigned int base, unsigned int power ) { unsigned int res = 1; - for (unsigned int i = 0; i < power;++i) + for ( unsigned int i = 0; i < power; ++i ) { res *= base; + } return res; } + } // end of namespace #endif // ! AI_STRINGCOMPARISON_H_INC diff --git a/include/assimp/StringUtils.h b/include/assimp/StringUtils.h index 157454126..906898b53 100644 --- a/include/assimp/StringUtils.h +++ b/include/assimp/StringUtils.h @@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #ifndef INCLUDED_AI_STRINGUTILS_H #define INCLUDED_AI_STRINGUTILS_H +#include + #include #include #include @@ -55,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// @return The number of written characters if the buffer size was big enough. If an encoding error occurs, a negative number is returned. #if defined(_MSC_VER) && _MSC_VER < 1900 - inline + AI_FORCE_INLINE int c99_ai_vsnprintf(char *outBuf, size_t size, const char *format, va_list ap) { int count(-1); if (0 != size) { @@ -68,7 +70,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. return count; } - inline + AI_FORCE_INLINE int ai_snprintf(char *outBuf, size_t size, const char *format, ...) { int count; va_list ap; @@ -89,7 +91,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// @param value The value to write into the std::string. /// @return The value as a std::string template -inline +AI_FORCE_INLINE std::string to_string( T value ) { std::ostringstream os; os << value; @@ -102,7 +104,7 @@ std::string to_string( T value ) { /// @param begin The first character of the string. /// @param end The last character /// @return The float value, 0.0f in cas of an error. -inline +AI_FORCE_INLINE float ai_strtof( const char *begin, const char *end ) { if ( nullptr == begin ) { return 0.0f; @@ -124,7 +126,7 @@ float ai_strtof( const char *begin, const char *end ) { /// @param toConvert Value to convert /// @return The hexadecimal string, is empty in case of an error. template -inline +AI_FORCE_INLINE std::string DecimalToHexa( T toConvert ) { std::string result; std::stringstream ss; diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index 2dba61abc..70a604de9 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -67,6 +67,7 @@ typedef enum aiMetadataType { AI_DOUBLE = 4, AI_AISTRING = 5, AI_AIVECTOR3D = 6, + AI_META_MAX = 7, #ifndef SWIG FORCE_32BIT = INT_MAX @@ -130,42 +131,103 @@ struct aiMetadata { */ aiMetadata() : mNumProperties(0) - , mKeys(NULL) - , mValues(NULL) { + , mKeys(nullptr) + , mValues(nullptr) { // empty } + aiMetadata( const aiMetadata &rhs ) + : mNumProperties( rhs.mNumProperties ) + , mKeys( nullptr ) + , mValues( nullptr ) { + mKeys = new aiString[ mNumProperties ]; + for ( unsigned int i = 0; i < mNumProperties; ++i ) { + mKeys[ i ] = rhs.mKeys[ i ]; + } + mValues = new aiMetadataEntry[ mNumProperties ]; + for ( unsigned int i = 0; i < mNumProperties; ++i ) { + mValues[ i ].mType = rhs.mValues[ i ].mType; + switch ( rhs.mValues[ i ].mType ) { + case AI_BOOL: + mValues[ i ].mData = new bool( rhs.mValues[i].mData ); + break; + case AI_INT32: { + int32_t v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( int32_t ) ); + mValues[ i ].mData = new int32_t( v ); + } + break; + case AI_UINT64: { + uint64_t v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( uint64_t ) ); + mValues[ i ].mData = new uint64_t( v ); + } + break; + case AI_FLOAT: { + float v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( float ) ); + mValues[ i ].mData = new float( v ); + } + break; + case AI_DOUBLE: { + double v; + ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( double ) ); + mValues[ i ].mData = new double( v ); + } + break; + case AI_AISTRING: { + aiString v; + rhs.Get( mKeys[ i ], v ); + mValues[ i ].mData = new aiString( v ); + } + break; + case AI_AIVECTOR3D: { + aiVector3D v; + rhs.Get( mKeys[ i ], v ); + mValues[ i ].mData = new aiVector3D( v ); + } + break; +#ifndef SWIG + case FORCE_32BIT: +#endif + default: + break; + } + + } + } + /** * @brief The destructor. */ ~aiMetadata() { delete [] mKeys; - mKeys = NULL; + mKeys = nullptr; if (mValues) { // Delete each metadata entry for (unsigned i=0; i(data); + delete static_cast< bool* >( data ); break; case AI_INT32: - delete static_cast(data); + delete static_cast< int32_t* >( data ); break; case AI_UINT64: - delete static_cast(data); + delete static_cast< uint64_t* >( data ); break; case AI_FLOAT: - delete static_cast(data); + delete static_cast< float* >( data ); break; case AI_DOUBLE: - delete static_cast(data); + delete static_cast< double* >( data ); break; case AI_AISTRING: - delete static_cast(data); + delete static_cast< aiString* >( data ); break; case AI_AIVECTOR3D: - delete static_cast(data); + delete static_cast< aiVector3D* >( data ); break; #ifndef SWIG case FORCE_32BIT: @@ -177,7 +239,7 @@ struct aiMetadata { // Delete the metadata array delete [] mValues; - mValues = NULL; + mValues = nullptr; } } @@ -208,8 +270,8 @@ struct aiMetadata { } template - inline void Add(const std::string& key, const T& value) - { + inline + void Add(const std::string& key, const T& value) { aiString* new_keys = new aiString[mNumProperties + 1]; aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1]; @@ -256,7 +318,7 @@ struct aiMetadata { template inline - bool Get( unsigned index, T& value ) { + bool Get( unsigned index, T& value ) const { // In range assertion if ( index >= mNumProperties ) { return false; @@ -277,7 +339,7 @@ struct aiMetadata { template inline - bool Get( const aiString& key, T& value ) { + bool Get( const aiString& key, T& value ) const { // Search for the given key for ( unsigned int i = 0; i < mNumProperties; ++i ) { if ( mKeys[ i ] == key ) { @@ -288,7 +350,8 @@ struct aiMetadata { } template - inline bool Get( const std::string& key, T& value ) { + inline + bool Get( const std::string& key, T& value ) const { return Get(aiString(key), value); } @@ -297,7 +360,8 @@ struct aiMetadata { /// \param [out] pKey - pointer to the key value. /// \param [out] pEntry - pointer to the entry: type and value. /// \return false - if pIndex is out of range, else - true. - inline bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) { + inline + bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) const { if ( index >= mNumProperties ) { return false; } diff --git a/test/unit/utMetadata.cpp b/test/unit/utMetadata.cpp index 7fda143b7..42f632bce 100644 --- a/test/unit/utMetadata.cpp +++ b/test/unit/utMetadata.cpp @@ -181,3 +181,74 @@ TEST_F( utMetadata, get_set_aiVector3D_Test ) { EXPECT_TRUE( success ); } +TEST_F( utMetadata, copy_test ) { + m_data = aiMetadata::Alloc( AI_META_MAX ); + bool bv = true; + m_data->Set( 0, "bool", bv ); + int32_t i32v = -10; + m_data->Set( 1, "int32", i32v ); + uint64_t ui64v = static_cast( 10 ); + m_data->Set( 2, "uint64", ui64v ); + float fv = 1.0f; + m_data->Set( 3, "float", fv ); + double dv = 2.0; + m_data->Set( 4, "double", dv ); + const aiString strVal( std::string( "test" ) ); + m_data->Set( 5, "aiString", strVal ); + aiVector3D vecVal( 1, 2, 3 ); + m_data->Set( 6, "aiVector3D", vecVal ); + + aiMetadata copy( *m_data ); + EXPECT_EQ( 7, copy.mNumProperties ); + + // bool test + { + bool v; + EXPECT_TRUE( copy.Get( "bool", v ) ); + EXPECT_EQ( bv, v ); + } + + // int32_t test + { + int32_t v; + bool ok = copy.Get( "int32", v ); + EXPECT_TRUE( ok ); + EXPECT_EQ( i32v, v ); + } + + // uint64_t test + { + uint64_t v; + bool ok = copy.Get( "uint64", v ); + EXPECT_TRUE( ok ); + EXPECT_EQ( ui64v, v ); + } + + // float test + { + float v; + EXPECT_TRUE( copy.Get( "float", v ) ); + EXPECT_EQ( fv, v ); + } + + // double test + { + double v; + EXPECT_TRUE( copy.Get( "double", v ) ); + EXPECT_EQ( dv, v ); + } + + // bool test + { + aiString v; + EXPECT_TRUE( copy.Get( "aiString", v ) ); + EXPECT_EQ( strVal, v ); + } + + // bool test + { + aiVector3D v; + EXPECT_TRUE( copy.Get( "aiVector3D", v ) ); + EXPECT_EQ( vecVal, v ); + } +}