diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index dd84ea782..0f9a5f105 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,8 +1,8 @@ --- name: Bug report about: Create a report to help us improve -title: '' -labels: '' +title: 'Bug:' +labels: 'Bug' assignees: '' --- @@ -23,16 +23,10 @@ A clear and concise description of what you expected to happen. **Screenshots** If applicable, add screenshots to help explain your problem. -**Desktop (please complete the following information):** +**Platform (please complete the following information):** - OS: [e.g. iOS] - Browser [e.g. chrome, safari] - Version [e.g. 22] -**Smartphone (please complete the following information):** - - Device: [e.g. iPhone6] - - OS: [e.g. iOS8.1] - - Browser [e.g. stock browser, safari] - - Version [e.g. 22] - **Additional context** Add any other context about the problem here. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md index bbcbbe7d6..87302a0f0 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.md +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -2,7 +2,7 @@ name: Feature request about: Suggest an idea for this project title: '' -labels: '' +labels: 'Feature-Request' assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/tech_debt.md b/.github/ISSUE_TEMPLATE/tech_debt.md new file mode 100644 index 000000000..a1172d932 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/tech_debt.md @@ -0,0 +1,25 @@ +--- +name: Technical debt +about: Create a report to help us to fix and detect tech debts +title: '' +labels: 'Techdebt' +assignees: '' + +--- + +**Describe the technical debt** +A clear and concise description of what the tech debt is about. + +**Better solution** +A clear and concise description of what you would expect. + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Desktop (please complete the following information):** + - OS: [e.g. iOS] + - Browser [e.g. chrome, safari] + - Version [e.g. 22] + +**Additional context** +Add any other context about the problem here. diff --git a/CMakeLists.txt b/CMakeLists.txt index 97a3641f5..7b9d6fc55 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -334,9 +334,9 @@ INCLUDE (FindPkgMacros) INCLUDE (PrecompiledHeader) # Set Assimp project output directory variables. -SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") -SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin") -SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib") +SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for runtime output files") +SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for library output files") +SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" CACHE STRING "Path for archive output files") # Macro used to set the output directories of a target to the # respective Assimp output directories. @@ -527,12 +527,12 @@ ENDIF() MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER ) SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL - "Build the C4D importer, which relies on the non-free Melange SDK." + "Build the C4D importer, which relies on the non-free Cineware SDK." ) IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) IF ( MSVC ) - SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes") + SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes") # pick the correct prebuilt library IF(MSVC15) @@ -551,22 +551,23 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) ) ENDIF() - SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/libraries/win") + SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/libraries/win") SET(C4D_DEBUG_LIBRARIES - "${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_debug.lib" + "${C4D_LIB_BASE_PATH}/cinewarelib${C4D_LIB_POSTFIX}/cinewarelib_debug.lib" "${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_debug.lib" ) SET(C4D_RELEASE_LIBRARIES - "${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_release.lib" + "${C4D_LIB_BASE_PATH}/cinewarelib${C4D_LIB_POSTFIX}/cinewarelib_release.lib" "${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_release.lib" ) - # winsock and winmm are necessary dependencies of melange (this is undocumented, but true.) + # winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because + # it can be used to communicate with a running Cinema 4D instance SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib) ELSE () MESSAGE( FATAL_ERROR - "C4D is currently only available on Windows with melange SDK installed in contrib/Melange" + "C4D is currently only available on Windows with Cineware SDK installed in contrib/Cineware" ) ENDIF () ELSE () diff --git a/Readme.md b/Readme.md index 81fd9fd9d..949d60966 100644 --- a/Readme.md +++ b/Readme.md @@ -42,7 +42,7 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. * [.NET](https://bitbucket.org/Starnick/assimpnet/src/master/) * [Pascal](port/AssimpPascal/Readme.md) * [Javascript (Alpha)](https://github.com/makc/assimp2json) -* [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777) +* [Unity 3d Plugin](https://ricardoreis.net/trilib-2/) * [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status)) * [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port. * [Rust](https://github.com/jkvargas/russimp) @@ -66,9 +66,9 @@ Open Asset Import Library is implemented in C++. The directory structure looks l The source code is organized in the following way: - code/Common The base implementation for importers and the infrastructure - code/PostProcessing The post-processing steps - code/ Implementation for import and export for the format + code/Common The base implementation for importers and the infrastructure + code/PostProcessing The post-processing steps + code/AssetLib/ Implementation for import and export for the format ### Where to get help ### For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format. diff --git a/code/AssetLib/3DS/3DSConverter.cpp b/code/AssetLib/3DS/3DSConverter.cpp index c977867c0..aca16b0d6 100644 --- a/code/AssetLib/3DS/3DSConverter.cpp +++ b/code/AssetLib/3DS/3DSConverter.cpp @@ -69,7 +69,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() { for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) { std::string s = mScene->mMaterials[i].mName; for (std::string::iterator it = s.begin(); it != s.end(); ++it) { - *it = static_cast(::tolower(*it)); + *it = static_cast(::tolower(static_cast(*it))); } if (std::string::npos == s.find("default")) continue; diff --git a/code/AssetLib/3DS/3DSExporter.cpp b/code/AssetLib/3DS/3DSExporter.cpp index 07e9ccfc7..92a6d5aa7 100644 --- a/code/AssetLib/3DS/3DSExporter.cpp +++ b/code/AssetLib/3DS/3DSExporter.cpp @@ -379,7 +379,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type // TODO: handle embedded textures properly if (path.data[0] == '*') { - ASSIMP_LOG_ERROR("Ignoring embedded texture for export: " + std::string(path.C_Str())); + ASSIMP_LOG_ERROR("Ignoring embedded texture for export: ", path.C_Str()); return; } diff --git a/code/AssetLib/3DS/3DSLoader.cpp b/code/AssetLib/3DS/3DSLoader.cpp index a25355ccc..b5e6f749b 100644 --- a/code/AssetLib/3DS/3DSLoader.cpp +++ b/code/AssetLib/3DS/3DSLoader.cpp @@ -143,7 +143,13 @@ void Discreet3DSImporter::SetupProperties(const Importer * /*pImp*/) { // Imports the given file into the given scene structure. void Discreet3DSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { - StreamReaderLE theStream(pIOHandler->Open(pFile, "rb")); + + auto theFile = pIOHandler->Open(pFile, "rb"); + if (!theFile) { + throw DeadlyImportError("3DS: Could not open ", pFile); + } + + StreamReaderLE theStream(theFile); // We should have at least one chunk if (theStream.GetRemainingSize() < 16) { @@ -299,7 +305,7 @@ void Discreet3DSImporter::ParseEditorChunk() { // print the version number char buff[10]; ASSIMP_itoa10(buff, stream->GetI2()); - ASSIMP_LOG_INFO_F(std::string("3DS file format version: "), buff); + ASSIMP_LOG_INFO("3DS file format version: ", buff); } break; }; ASSIMP_3DS_END_CHUNK(); @@ -928,7 +934,7 @@ void Discreet3DSImporter::ParseFaceChunk() { } } if (0xcdcdcdcd == idx) { - ASSIMP_LOG_ERROR_F("3DS: Unknown material: ", sz); + ASSIMP_LOG_ERROR("3DS: Unknown material: ", sz); } // Now continue and read all material indices diff --git a/code/AssetLib/3MF/D3MFOpcPackage.cpp b/code/AssetLib/3MF/D3MFOpcPackage.cpp index d5bbcd618..dbf4f2e10 100644 --- a/code/AssetLib/3MF/D3MFOpcPackage.cpp +++ b/code/AssetLib/3MF/D3MFOpcPackage.cpp @@ -160,9 +160,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) : } } else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) { - ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file); + ASSIMP_LOG_WARN("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file); } else { - ASSIMP_LOG_WARN_F("Ignored file of unknown type: ", file); + ASSIMP_LOG_WARN("Ignored file of unknown type: ", file); } } } diff --git a/code/AssetLib/AC/ACLoader.cpp b/code/AssetLib/AC/ACLoader.cpp index cba84e8b0..078c96e32 100644 --- a/code/AssetLib/AC/ACLoader.cpp +++ b/code/AssetLib/AC/ACLoader.cpp @@ -116,7 +116,7 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name buffer = AcSkipToNextToken(buffer); if (0 != name_length) { if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) { - ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " + std::string(name) + " was expected."); + ASSIMP_LOG_ERROR("AC3D: Unexpected token. ", name, " was expected."); return buffer; } buffer += name_length + 1; @@ -492,7 +492,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, default: // Coerce unknowns to a polygon and warn - ASSIMP_LOG_WARN_F("AC3D: The type flag of a surface is unknown: ", (*it).flags); + ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown: ", (*it).flags); (*it).flags &= ~(Surface::Mask); // fallthrough @@ -690,7 +690,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, if (object.subDiv) { if (configEvalSubdivision) { std::unique_ptr div(Subdivider::Create(Subdivider::CATMULL_CLARKE)); - ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: " + object.name); + ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: ", object.name); std::vector cpy(meshes.size() - oldm, nullptr); div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true); @@ -698,7 +698,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object, // previous meshes are deleted vy Subdivide(). } else { - ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: " + object.name); + ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: ", object.name); } } } @@ -782,7 +782,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile, unsigned int version = HexDigitToDecimal(buffer[4]); char msg[3]; ASSIMP_itoa10(msg, 3, version); - ASSIMP_LOG_INFO_F("AC3D file format version: ", msg); + ASSIMP_LOG_INFO("AC3D file format version: ", msg); std::vector materials; materials.reserve(5); diff --git a/code/AssetLib/AMF/AMFImporter.cpp b/code/AssetLib/AMF/AMFImporter.cpp index 1a3efba9a..615882b6a 100644 --- a/code/AssetLib/AMF/AMFImporter.cpp +++ b/code/AssetLib/AMF/AMFImporter.cpp @@ -205,7 +205,7 @@ void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::s } static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) { - return (isalnum(pChar) || (pChar == '+') || (pChar == '/')); + return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/')); } void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std::vector &pOutputData) const { @@ -268,7 +268,8 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) { mXmlParser = new XmlParser(); if (!mXmlParser->parse(file.get())) { delete mXmlParser; - throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); + mXmlParser = nullptr; + throw DeadlyImportError("Failed to create XML reader for file ", pFile, "."); } // Start reading, search for root tag diff --git a/code/AssetLib/ASE/ASELoader.cpp b/code/AssetLib/ASE/ASELoader.cpp index e1b9c5b83..1a42c2f52 100644 --- a/code/AssetLib/ASE/ASELoader.cpp +++ b/code/AssetLib/ASE/ASELoader.cpp @@ -614,7 +614,7 @@ void ASEImporter::AddNodes(const std::vector &nodes, node->mNumChildren++; // What we did is so great, it is at least worth a debug message - ASSIMP_LOG_VERBOSE_DEBUG("ASE: Generating separate target node (" + snode->mName + ")"); + ASSIMP_LOG_VERBOSE_DEBUG("ASE: Generating separate target node (", snode->mName, ")"); } } diff --git a/code/AssetLib/ASE/ASEParser.cpp b/code/AssetLib/ASE/ASEParser.cpp index 530766730..1f7018b11 100644 --- a/code/AssetLib/ASE/ASEParser.cpp +++ b/code/AssetLib/ASE/ASEParser.cpp @@ -498,6 +498,12 @@ void Parser::ParseLV1MaterialListBlock() { ParseLV2MaterialBlock(sMat); continue; } + if( iDepth == 1 ){ + // CRUDE HACK: support missing brace after "Ascii Scene Exporter v2.51" + LogWarning("Missing closing brace in material list"); + --filePtr; + return; + } } AI_ASE_HANDLE_TOP_LEVEL_SECTION(); } @@ -671,7 +677,7 @@ void Parser::ParseLV3MapBlock(Texture &map) { if (!ParseString(temp, "*MAP_CLASS")) SkipToNextToken(); if (temp != "Bitmap" && temp != "Normal Bump") { - ASSIMP_LOG_WARN_F("ASE: Skipping unknown map type: ", temp); + ASSIMP_LOG_WARN("ASE: Skipping unknown map type: ", temp); parsePath = false; } continue; @@ -1119,7 +1125,7 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) { "this is no spot light or target camera"); } } else { - ASSIMP_LOG_ERROR("ASE: Unknown node transformation: " + temp); + ASSIMP_LOG_ERROR("ASE: Unknown node transformation: ", temp); // mode = 0 } continue; diff --git a/code/AssetLib/Assbin/AssbinLoader.cpp b/code/AssetLib/Assbin/AssbinLoader.cpp index d94a9ed7d..d94407e03 100644 --- a/code/AssetLib/Assbin/AssbinLoader.cpp +++ b/code/AssetLib/Assbin/AssbinLoader.cpp @@ -671,7 +671,7 @@ void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) { void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { IOStream *stream = pIOHandler->Open(pFile, "rb"); if (nullptr == stream) { - return; + throw DeadlyImportError("ASSBIN: Could not open ", pFile); } // signature diff --git a/code/AssetLib/Assxml/AssxmlFileWriter.cpp b/code/AssetLib/Assxml/AssxmlFileWriter.cpp index 6d876b3aa..24fda5955 100644 --- a/code/AssetLib/Assxml/AssxmlFileWriter.cpp +++ b/code/AssetLib/Assxml/AssxmlFileWriter.cpp @@ -598,8 +598,11 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene, if (!mesh->mTextureCoords[a]) break; - ioprintf(io, "\t\t \n", mesh->mNumVertices, - a, mesh->mNumUVComponents[a]); + ioprintf(io, "\t\t \n", + mesh->mNumVertices, + a, + mesh->mTextureCoordsNames[a].C_Str(), + mesh->mNumUVComponents[a]); if (!shortened) { if (mesh->mNumUVComponents[a] == 3) { diff --git a/code/AssetLib/B3D/B3DImporter.cpp b/code/AssetLib/B3D/B3DImporter.cpp index bcdb286be..3d9a5075a 100644 --- a/code/AssetLib/B3D/B3DImporter.cpp +++ b/code/AssetLib/B3D/B3DImporter.cpp @@ -145,7 +145,7 @@ AI_WONT_RETURN void B3DImporter::Oops() { // ------------------------------------------------------------------------------------------------ AI_WONT_RETURN void B3DImporter::Fail(string str) { #ifdef DEBUG_B3D - ASSIMP_LOG_ERROR_F("Error in B3D file data: ", str); + ASSIMP_LOG_ERROR("Error in B3D file data: ", str); #endif throw DeadlyImportError("B3D Importer - error in B3D file data: ", str); } @@ -233,7 +233,7 @@ string B3DImporter::ReadChunk() { tag += char(ReadByte()); } #ifdef DEBUG_B3D - ASSIMP_LOG_DEBUG_F("ReadChunk: ", tag); + ASSIMP_LOG_DEBUG("ReadChunk: ", tag); #endif unsigned sz = (unsigned)ReadInt(); _stack.push_back(_pos + sz); @@ -397,7 +397,7 @@ void B3DImporter::ReadTRIS(int v0) { matid = 0; } else if (matid < 0 || matid >= (int)_materials.size()) { #ifdef DEBUG_B3D - ASSIMP_LOG_ERROR_F("material id=", matid); + ASSIMP_LOG_ERROR("material id=", matid); #endif Fail("Bad material id"); } @@ -417,7 +417,7 @@ void B3DImporter::ReadTRIS(int v0) { int i2 = ReadInt() + v0; if (i0 < 0 || i0 >= (int)_vertices.size() || i1 < 0 || i1 >= (int)_vertices.size() || i2 < 0 || i2 >= (int)_vertices.size()) { #ifdef DEBUG_B3D - ASSIMP_LOG_ERROR_F("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2); + ASSIMP_LOG_ERROR("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2); #endif Fail("Bad triangle index"); continue; diff --git a/code/AssetLib/BVH/BVHLoader.cpp b/code/AssetLib/BVH/BVHLoader.cpp index 8ae99033c..cf78fb6c6 100644 --- a/code/AssetLib/BVH/BVHLoader.cpp +++ b/code/AssetLib/BVH/BVHLoader.cpp @@ -359,7 +359,7 @@ void BVHLoader::ReadMotion(aiScene * /*pScene*/) { std::string BVHLoader::GetNextToken() { // skip any preceding whitespace while (mReader != mBuffer.end()) { - if (!isspace(*mReader)) + if (!isspace((unsigned char)*mReader)) break; // count lines @@ -372,7 +372,7 @@ std::string BVHLoader::GetNextToken() { // collect all chars till the next whitespace. BVH is easy in respect to that. std::string token; while (mReader != mBuffer.end()) { - if (isspace(*mReader)) + if (isspace((unsigned char)*mReader)) break; token.push_back(*mReader); diff --git a/code/AssetLib/Blender/BlenderDNA.cpp b/code/AssetLib/Blender/BlenderDNA.cpp index 4dcb3d654..3da0dce31 100644 --- a/code/AssetLib/Blender/BlenderDNA.cpp +++ b/code/AssetLib/Blender/BlenderDNA.cpp @@ -198,9 +198,9 @@ void DNAParser::Parse() { s.size = offset; } - ASSIMP_LOG_DEBUG_F("BlenderDNA: Got ", dna.structures.size(), " structures with totally ", fields, " fields"); + ASSIMP_LOG_DEBUG("BlenderDNA: Got ", dna.structures.size(), " structures with totally ", fields, " fields"); -#ifdef ASSIMP_BUILD_BLENDER_DEBUG +#if ASSIMP_BUILD_BLENDER_DEBUG_DNA dna.DumpToFile(); #endif @@ -208,7 +208,7 @@ void DNAParser::Parse() { dna.RegisterConverters(); } -#ifdef ASSIMP_BUILD_BLENDER_DEBUG +#if ASSIMP_BUILD_BLENDER_DEBUG_DNA #include // ------------------------------------------------------------------------------------------------ @@ -237,7 +237,7 @@ void DNA ::DumpToFile() { ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt"); } -#endif +#endif // ASSIMP_BUILD_BLENDER_DEBUG_DNA // ------------------------------------------------------------------------------------------------ /*static*/ void DNA ::ExtractArraySize( diff --git a/code/AssetLib/Blender/BlenderDNA.h b/code/AssetLib/Blender/BlenderDNA.h index 090d1be04..f566554b8 100644 --- a/code/AssetLib/Blender/BlenderDNA.h +++ b/code/AssetLib/Blender/BlenderDNA.h @@ -59,6 +59,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define ASSIMP_BUILD_BLENDER_DEBUG #endif +// set this to non-zero to dump BlenderDNA stuff to dna.txt. +// you could set it on the assimp build command line too without touching it here. +// !!! please make sure this is set to 0 in the repo !!! +#ifndef ASSIMP_BUILD_BLENDER_DEBUG_DNA +#define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0 +#endif + // #define ASSIMP_BUILD_BLENDER_NO_STATS namespace Assimp { @@ -495,7 +502,7 @@ public: const Structure &structure, const FileDatabase &db) const; -#ifdef ASSIMP_BUILD_BLENDER_DEBUG +#if ASSIMP_BUILD_BLENDER_DEBUG_DNA // -------------------------------------------------------- /** Dump the DNA to a text file. This is for debugging purposes. * The output file is `dna.txt` in the current working folder*/ diff --git a/code/AssetLib/Blender/BlenderDNA.inl b/code/AssetLib/Blender/BlenderDNA.inl index aebcefa84..a46532057 100644 --- a/code/AssetLib/Blender/BlenderDNA.inl +++ b/code/AssetLib/Blender/BlenderDNA.inl @@ -565,7 +565,7 @@ template <> bool Structure :: ResolvePointer(std::shar // this might happen if DNA::RegisterConverters hasn't been called so far // or if the target type is not contained in `our` DNA. out.reset(); - ASSIMP_LOG_WARN_F( "Failed to find a converter for the `",s.name,"` structure" ); + ASSIMP_LOG_WARN( "Failed to find a converter for the `",s.name,"` structure" ); return false; } diff --git a/code/AssetLib/Blender/BlenderLoader.cpp b/code/AssetLib/Blender/BlenderLoader.cpp index 3722b9c73..7cf4e070e 100644 --- a/code/AssetLib/Blender/BlenderLoader.cpp +++ b/code/AssetLib/Blender/BlenderLoader.cpp @@ -235,9 +235,9 @@ void BlenderImporter::InternReadFile(const std::string &pFile, stream->Read(magic, 3, 1); magic[3] = '\0'; - LogInfo((format(), "Blender version is ", magic[0], ".", magic + 1, + LogInfo("Blender version is ", magic[0], ".", magic + 1, " (64bit: ", file.i64bit ? "true" : "false", - ", little endian: ", file.little ? "true" : "false", ")")); + ", little endian: ", file.little ? "true" : "false", ")"); ParseBlendFile(file, stream); @@ -310,7 +310,7 @@ void BlenderImporter::ExtractScene(Scene &out, const FileDatabase &file) { ss.Convert(out, file); #ifndef ASSIMP_BUILD_BLENDER_NO_STATS - ASSIMP_LOG_INFO_F( + ASSIMP_LOG_INFO( "(Stats) Fields read: ", file.stats().fields_read, ", pointers resolved: ", file.stats().pointers_resolved, ", cache hits: ", file.stats().cache_hits, @@ -420,9 +420,9 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M --s; } - curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower(s[1]); - curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower(s[2]); - curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower(s[3]); + curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower((unsigned char)s[1]); + curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower((unsigned char)s[2]); + curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower((unsigned char)s[3]); curTex->achFormatHint[3] = '\0'; // tex->mHeight = 0; @@ -434,7 +434,7 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M curTex->pcData = reinterpret_cast(ch); - LogInfo("Reading embedded texture, original file was " + std::string(img->name)); + LogInfo("Reading embedded texture, original file was ", img->name); } else { name = aiString(img->name); } @@ -516,7 +516,7 @@ void BlenderImporter::ResolveTexture(aiMaterial *out, const Material *mat, const case Tex::Type_POINTDENSITY: case Tex::Type_VOXELDATA: - LogWarn(std::string("Encountered a texture with an unsupported type: ") + dispnam); + LogWarn("Encountered a texture with an unsupported type: ", dispnam); AddSentinelTexture(out, mat, tex, conv_data); break; @@ -752,7 +752,7 @@ void BlenderImporter::CheckActualType(const ElemBase *dt, const char *check) { // ------------------------------------------------------------------------------------------------ void BlenderImporter::NotSupportedObjectType(const Object *obj, const char *type) { - LogWarn((format(), "Object `", obj->id.name, "` - type is unsupported: `", type, "`, skipping")); + LogWarn("Object `", obj->id.name, "` - type is unsupported: `", type, "`, skipping"); } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/Blender/BlenderModifier.cpp b/code/AssetLib/Blender/BlenderModifier.cpp index 995e20b1c..bc5c8c2d9 100644 --- a/code/AssetLib/Blender/BlenderModifier.cpp +++ b/code/AssetLib/Blender/BlenderModifier.cpp @@ -90,7 +90,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_d const Structure *s = conv_data.db.dna.Get(cur->dna_type); if (!s) { - ASSIMP_LOG_WARN_F("BlendModifier: could not resolve DNA name: ", cur->dna_type); + ASSIMP_LOG_WARN("BlendModifier: could not resolve DNA name: ", cur->dna_type); continue; } @@ -132,7 +132,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_d } } if (curgod) { - ASSIMP_LOG_WARN_F("Couldn't find a handler for modifier: ", dat.name); + ASSIMP_LOG_WARN("Couldn't find a handler for modifier: ", dat.name); } } @@ -140,7 +140,7 @@ void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_d // object, we still can't say whether our modifier implementations were // able to fully do their job. if (ful) { - ASSIMP_LOG_DEBUG_F("BlendModifier: found handlers for ", cnt, " of ", ful, " modifiers on `", orig_object.id.name, + ASSIMP_LOG_DEBUG("BlendModifier: found handlers for ", cnt, " of ", ful, " modifiers on `", orig_object.id.name, "`, check log messages above for errors"); } } @@ -248,7 +248,7 @@ void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const out.mMeshes = nind; out.mNumMeshes *= 2; - ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Mirror` modifier to `", + ASSIMP_LOG_INFO("BlendModifier: Applied the `Mirror` modifier to `", orig_object.id.name, "`"); } @@ -277,7 +277,7 @@ void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data, break; default: - ASSIMP_LOG_WARN_F("BlendModifier: Unrecognized subdivision algorithm: ", mir.subdivType); + ASSIMP_LOG_WARN("BlendModifier: Unrecognized subdivision algorithm: ", mir.subdivType); return; }; @@ -292,7 +292,7 @@ void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data, subd->Subdivide(meshes, out.mNumMeshes, tempmeshes.get(), std::max(mir.renderLevels, mir.levels), true); std::copy(tempmeshes.get(), tempmeshes.get() + out.mNumMeshes, meshes); - ASSIMP_LOG_INFO_F("BlendModifier: Applied the `Subdivision` modifier to `", + ASSIMP_LOG_INFO("BlendModifier: Applied the `Subdivision` modifier to `", orig_object.id.name, "`"); } diff --git a/code/AssetLib/Blender/BlenderModifier.h b/code/AssetLib/Blender/BlenderModifier.h index 7d4096cde..daf120087 100644 --- a/code/AssetLib/Blender/BlenderModifier.h +++ b/code/AssetLib/Blender/BlenderModifier.h @@ -86,7 +86,7 @@ public: const Scene& /*in*/, const Object& /*orig_object*/ ) { - ASSIMP_LOG_INFO_F("This modifier is not supported, skipping: ",orig_modifier.dna_type ); + ASSIMP_LOG_INFO("This modifier is not supported, skipping: ",orig_modifier.dna_type ); return; } }; diff --git a/code/AssetLib/C4D/C4DImporter.cpp b/code/AssetLib/C4D/C4DImporter.cpp index 24fd6f622..434d1429e 100644 --- a/code/AssetLib/C4D/C4DImporter.cpp +++ b/code/AssetLib/C4D/C4DImporter.cpp @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2020, assimp team +Copyright (c) 2006-2021, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, @@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #endif #include "C4DImporter.h" -#include #include #include #include @@ -65,7 +64,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "c4d_file.h" #include "default_alien_overloads.h" -using namespace melange; +namespace { + +aiString aiStringFrom(cineware::String const & cinestring) { + aiString result; + cinestring.GetCString(result.data, MAXLEN-1); + result.length = static_cast(cinestring.GetLength()); + return result; +} + +} + +using namespace Assimp; +using namespace cineware; // overload this function and fill in your own unique data void GetWriterInfo(int &id, String &appname) { @@ -73,9 +84,6 @@ void GetWriterInfo(int &id, String &appname) { appname = "Open Asset Import Library"; } -using namespace Assimp; -using namespace Assimp::Formatter; - namespace Assimp { template<> const char* LogFunctions::Prefix() { static auto prefix = "C4D: "; @@ -97,17 +105,6 @@ static const aiImporterDesc desc = { }; -// ------------------------------------------------------------------------------------------------ -C4DImporter::C4DImporter() -: BaseImporter() { - // empty -} - -// ------------------------------------------------------------------------------------------------ -C4DImporter::~C4DImporter() { - // empty -} - // ------------------------------------------------------------------------------------------------ bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { const std::string& extension = GetExtension(pFile); @@ -125,11 +122,6 @@ const aiImporterDesc* C4DImporter::GetInfo () const { return &desc; } -// ------------------------------------------------------------------------------------------------ -void C4DImporter::SetupProperties(const Importer* /*pImp*/) { - // nothing to be done for the moment -} - // ------------------------------------------------------------------------------------------------ // Imports the given file into the given scene structure. @@ -199,8 +191,8 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS // ------------------------------------------------------------------------------------------------ -bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) { - // based on Melange sample code (C4DImportExport.cpp) +bool C4DImporter::ReadShader(aiMaterial* out, BaseShader* shader) { + // based on Cineware sample code (C4DImportExport.cpp) while(shader) { if(shader->GetType() == Xlayer) { BaseContainer* container = shader->GetDataInstance(); @@ -242,13 +234,11 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) { lsl = lsl->GetNext(); } } else if ( shader->GetType() == Xbitmap ) { - aiString path; - shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1); - path.length = ::strlen(path.data); + auto const path = aiStringFrom(shader->GetFileName().GetString()); out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0)); return true; } else { - LogWarn("ignoring shader type: " + std::string(GetObjectTypeName(shader->GetType()))); + LogWarn("ignoring shader type: ", GetObjectTypeName(shader->GetType())); } shader = shader->GetNext(); } @@ -257,18 +247,15 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) { } // ------------------------------------------------------------------------------------------------ -void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) { - // based on Melange sample code +void C4DImporter::ReadMaterials(BaseMaterial* mat) { + // based on Cineware sample code while (mat) { - const String& name = mat->GetName(); if (mat->GetType() == Mmaterial) { aiMaterial* out = new aiMaterial(); material_mapping[mat] = static_cast(materials.size()); materials.push_back(out); - aiString ai_name; - name.GetCString(ai_name.data, MAXLEN-1); - ai_name.length = ::strlen(ai_name.data); + auto const ai_name = aiStringFrom(mat->GetName()); out->AddProperty(&ai_name, AI_MATKEY_NAME); Material& m = dynamic_cast(*mat); @@ -294,7 +281,7 @@ void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) { ReadShader(out, shader); } } else { - LogWarn("ignoring plugin material: " + std::string(GetObjectTypeName(mat->GetType()))); + LogWarn("ignoring plugin material: ", GetObjectTypeName(mat->GetType())); } mat = mat->GetNext(); } @@ -305,19 +292,15 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) { ai_assert(parent != nullptr ); std::vector nodes; - // based on Melange sample code + // based on Cineware sample code while (object) { - const String& name = object->GetName(); const LONG type = object->GetType(); const Matrix& ml = object->GetMl(); - aiString string; - name.GetCString(string.data, MAXLEN-1); - string.length = ::strlen(string.data); aiNode* const nd = new aiNode(); nd->mParent = parent; - nd->mName = string; + nd->mName = aiStringFrom(object->GetName()); nd->mTransformation.a1 = ml.v1.x; nd->mTransformation.b1 = ml.v1.y; @@ -352,7 +335,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) { meshes.push_back(mesh); } } else { - LogWarn("ignoring object: " + std::string(GetObjectTypeName(type))); + LogWarn("ignoring object: ", GetObjectTypeName(type)); } RecurseHierarchy(object->GetDown(), nd); @@ -370,7 +353,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) { ai_assert(object != nullptr); ai_assert( object->GetType() == Opolygon ); - // based on Melange sample code + // based on Cineware sample code PolygonObject* const polyObject = dynamic_cast(object); ai_assert(polyObject != nullptr); @@ -618,4 +601,3 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) { } #endif // ASSIMP_BUILD_NO_C4D_IMPORTER - diff --git a/code/AssetLib/C4D/C4DImporter.h b/code/AssetLib/C4D/C4DImporter.h index f9406c3e0..c44cf5e37 100644 --- a/code/AssetLib/C4D/C4DImporter.h +++ b/code/AssetLib/C4D/C4DImporter.h @@ -2,7 +2,7 @@ Open Asset Import Library (assimp) ---------------------------------------------------------------------- -Copyright (c) 2006-2020, assimp team +Copyright (c) 2006-2021, assimp team All rights reserved. Redistribution and use of this software in source and binary forms, @@ -56,8 +56,8 @@ struct aiMaterial; struct aiImporterDesc; -namespace melange { - class BaseObject; // c4d_file.h +namespace cineware { + class BaseObject; class PolygonObject; class BaseMaterial; class BaseShader; @@ -71,43 +71,34 @@ namespace Assimp { } // ------------------------------------------------------------------------------------------- -/** Importer class to load Cinema4D files using the Melange library to be obtained from - * www.plugincafe.com +/** Importer class to load Cinema4D files using the Cineware library to be obtained from + * https://developers.maxon.net * - * Note that Melange is not free software. */ + * Note that Cineware is not free software. */ // ------------------------------------------------------------------------------------------- class C4DImporter : public BaseImporter, public LogFunctions { public: - C4DImporter(); - ~C4DImporter(); - bool CanRead( const std::string& pFile, IOSystem* pIOHandler, - bool checkSig) const; + bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override; protected: - // -------------------- - const aiImporterDesc* GetInfo () const; + const aiImporterDesc* GetInfo () const override; - // -------------------- - void SetupProperties(const Importer* pImp); - - // -------------------- - void InternReadFile( const std::string& pFile, aiScene* pScene, - IOSystem* pIOHandler); + void InternReadFile( const std::string& pFile, aiScene*, IOSystem* ) override; private: - void ReadMaterials(melange::BaseMaterial* mat); - void RecurseHierarchy(melange::BaseObject* object, aiNode* parent); - aiMesh* ReadMesh(melange::BaseObject* object); - unsigned int ResolveMaterial(melange::PolygonObject* obj); + void ReadMaterials(cineware::BaseMaterial* mat); + void RecurseHierarchy(cineware::BaseObject* object, aiNode* parent); + aiMesh* ReadMesh(cineware::BaseObject* object); + unsigned int ResolveMaterial(cineware::PolygonObject* obj); - bool ReadShader(aiMaterial* out, melange::BaseShader* shader); + bool ReadShader(aiMaterial* out, cineware::BaseShader* shader); std::vector meshes; std::vector materials; - typedef std::map MaterialMap; + typedef std::map MaterialMap; MaterialMap material_mapping; }; // !class C4DImporter diff --git a/code/AssetLib/COB/COBLoader.cpp b/code/AssetLib/COB/COBLoader.cpp index efe7fc446..94327c683 100644 --- a/code/AssetLib/COB/COBLoader.cpp +++ b/code/AssetLib/COB/COBLoader.cpp @@ -137,7 +137,13 @@ void COBImporter::SetupProperties(const Importer * /*pImp*/) { // Imports the given file into the given scene structure. void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { COB::Scene scene; - std::unique_ptr stream(new StreamReaderLE(pIOHandler->Open(pFile, "rb"))); + + auto file = pIOHandler->Open(pFile, "rb"); + if (!file) { + ThrowException("Could not open " + pFile); + } + + std::unique_ptr stream(new StreamReaderLE(file)); // check header char head[32]; @@ -146,7 +152,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy ThrowException("Could not found magic id: `Caligari`"); } - ASSIMP_LOG_INFO_F("File format tag: ", std::string(head + 9, 6)); + ASSIMP_LOG_INFO("File format tag: ", std::string(head + 9, 6)); if (head[16] != 'L') { ThrowException("File is big-endian, which is not supported"); } @@ -295,8 +301,7 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi } std::unique_ptr defmat; if (!min) { - ASSIMP_LOG_VERBOSE_DEBUG(format() << "Could not resolve material index " - << reflist.first << " - creating default material for this slot"); + ASSIMP_LOG_VERBOSE_DEBUG("Could not resolve material index ", reflist.first, " - creating default material for this slot"); defmat.reset(min = new Material()); } @@ -521,7 +526,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk ++splitter; if (!splitter.match_start("mat# ")) { - ASSIMP_LOG_WARN_F("Expected `mat#` line in `Mat1` chunk ", nfo.id); + ASSIMP_LOG_WARN("Expected `mat#` line in `Mat1` chunk ", nfo.id); return; } @@ -533,7 +538,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk ++splitter; if (!splitter.match_start("shader: ")) { - ASSIMP_LOG_WARN_F("Expected `mat#` line in `Mat1` chunk ", nfo.id); + ASSIMP_LOG_WARN("Expected `mat#` line in `Mat1` chunk ", nfo.id); return; } std::string shader = std::string(splitter[1]); @@ -544,12 +549,12 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk } else if (shader == "phong") { mat.shader = Material::PHONG; } else if (shader != "flat") { - ASSIMP_LOG_WARN_F("Unknown value for `shader` in `Mat1` chunk ", nfo.id); + ASSIMP_LOG_WARN("Unknown value for `shader` in `Mat1` chunk ", nfo.id); } ++splitter; if (!splitter.match_start("rgb ")) { - ASSIMP_LOG_WARN_F("Expected `rgb` line in `Mat1` chunk ", nfo.id); + ASSIMP_LOG_WARN("Expected `rgb` line in `Mat1` chunk ", nfo.id); } const char *rgb = splitter[1]; @@ -557,7 +562,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk ++splitter; if (!splitter.match_start("alpha ")) { - ASSIMP_LOG_WARN_F("Expected `alpha` line in `Mat1` chunk ", nfo.id); + ASSIMP_LOG_WARN("Expected `alpha` line in `Mat1` chunk ", nfo.id); } const char *tokens[10]; @@ -577,7 +582,7 @@ void COBImporter::ReadUnit_Ascii(Scene &out, LineSplitter &splitter, const Chunk } ++splitter; if (!splitter.match_start("Units ")) { - ASSIMP_LOG_WARN_F("Expected `Units` line in `Unit` chunk ", nfo.id); + ASSIMP_LOG_WARN("Expected `Units` line in `Unit` chunk ", nfo.id); return; } @@ -588,12 +593,12 @@ void COBImporter::ReadUnit_Ascii(Scene &out, LineSplitter &splitter, const Chunk const unsigned int t = strtoul10(splitter[1]); nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? ( - ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) : + ASSIMP_LOG_WARN(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) : units[t]; return; } } - ASSIMP_LOG_WARN_F("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); + ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); } // ------------------------------------------------------------------------------------------------ @@ -622,13 +627,13 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk } else if (splitter.match_start("Spot ")) { msh.ltype = Light::SPOT; } else { - ASSIMP_LOG_WARN_F("Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter); + ASSIMP_LOG_WARN("Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter); msh.ltype = Light::SPOT; } ++splitter; if (!splitter.match_start("color ")) { - ASSIMP_LOG_WARN_F("Expected `color` line in `Lght` chunk ", nfo.id); + ASSIMP_LOG_WARN("Expected `color` line in `Lght` chunk ", nfo.id); } const char *rgb = splitter[1]; @@ -636,14 +641,14 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk SkipSpaces(&rgb); if (strncmp(rgb, "cone angle", 10) != 0) { - ASSIMP_LOG_WARN_F("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id); + ASSIMP_LOG_WARN("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id); } SkipSpaces(rgb + 10, &rgb); msh.angle = fast_atof(&rgb); SkipSpaces(&rgb); if (strncmp(rgb, "inner angle", 11) != 0) { - ASSIMP_LOG_WARN_F("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id); + ASSIMP_LOG_WARN("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id); } SkipSpaces(rgb + 11, &rgb); msh.inner_angle = fast_atof(&rgb); @@ -1027,7 +1032,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const mat.type = Material::METAL; break; default: - ASSIMP_LOG_ERROR_F("Unrecognized shader type in `Mat1` chunk with id ", nfo.id); + ASSIMP_LOG_ERROR("Unrecognized shader type in `Mat1` chunk with id ", nfo.id); mat.type = Material::FLAT; } @@ -1042,7 +1047,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const mat.autofacet = Material::SMOOTH; break; default: - ASSIMP_LOG_ERROR_F("Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id); + ASSIMP_LOG_ERROR("Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id); mat.autofacet = Material::FACETED; } mat.autofacet_angle = static_cast(reader.GetI1()); @@ -1170,13 +1175,13 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const if (nd->id == nfo.parent_id) { const unsigned int t = reader.GetI2(); nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? ( - ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) : + ASSIMP_LOG_WARN(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) : units[t]; return; } } - ASSIMP_LOG_WARN_F("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); + ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); } #endif // ASSIMP_BUILD_NO_COB_IMPORTER diff --git a/code/AssetLib/Collada/ColladaLoader.cpp b/code/AssetLib/Collada/ColladaLoader.cpp index 736d20ce5..492e6971f 100644 --- a/code/AssetLib/Collada/ColladaLoader.cpp +++ b/code/AssetLib/Collada/ColladaLoader.cpp @@ -317,7 +317,7 @@ void ColladaLoader::ResolveNodeInstances(const ColladaParser &pParser, const Nod nd = FindNode(pParser.mRootNode, nodeInst.mNode); } if (nullptr == nd) { - ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode); + ASSIMP_LOG_ERROR("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode); } else { // attach this node to the list of children resolved.push_back(nd); @@ -347,7 +347,7 @@ void ColladaLoader::BuildLightsForNode(const ColladaParser &pParser, const Node // find the referred light ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find(lid.mLight); if (srcLightIt == pParser.mLightLibrary.end()) { - ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"", lid.mLight, "\". Skipping."); + ASSIMP_LOG_WARN("Collada: Unable to find light for ID \"", lid.mLight, "\". Skipping."); continue; } const Collada::Light *srcLight = &srcLightIt->second; @@ -412,7 +412,7 @@ void ColladaLoader::BuildCamerasForNode(const ColladaParser &pParser, const Node // find the referred light ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find(cid.mCamera); if (srcCameraIt == pParser.mCameraLibrary.end()) { - ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"", cid.mCamera, "\". Skipping."); + ASSIMP_LOG_WARN("Collada: Unable to find camera for ID \"", cid.mCamera, "\". Skipping."); continue; } const Collada::Camera *srcCamera = &srcCameraIt->second; @@ -486,7 +486,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node } if (nullptr == srcMesh) { - ASSIMP_LOG_WARN_F("Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping."); + ASSIMP_LOG_WARN("Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping."); continue; } } else { @@ -511,7 +511,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node table = &meshMatIt->second; meshMaterial = table->mMatName; } else { - ASSIMP_LOG_WARN_F("Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <", + ASSIMP_LOG_WARN("Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <", mid.mMeshOrController, ">."); if (!mid.mMaterials.empty()) { meshMaterial = mid.mMaterials.begin()->second.mMatName; @@ -883,7 +883,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc if (nullptr != bnode) { bone->mName.Set(FindNameForNode(bnode)); } else { - ASSIMP_LOG_WARN_F("ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"."); + ASSIMP_LOG_WARN("ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"."); } // and insert bone @@ -1184,7 +1184,7 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse else if (subElement == "Z") entry.mSubElement = 2; else - ASSIMP_LOG_WARN_F("Unknown anim subelement <", subElement, ">. Ignoring"); + ASSIMP_LOG_WARN("Unknown anim subelement <", subElement, ">. Ignoring"); } else { // no sub-element following, transformId is remaining string entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1); @@ -1711,7 +1711,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse // find the image referred by this name in the image library of the scene ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find(name); if (imIt == pParser.mImageLibrary.end()) { - ASSIMP_LOG_WARN_F("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\"."); + ASSIMP_LOG_WARN("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\"."); //set default texture file name result.Set(name + ".jpg"); diff --git a/code/AssetLib/Collada/ColladaParser.cpp b/code/AssetLib/Collada/ColladaParser.cpp index 42166fdd4..5dbf0a567 100644 --- a/code/AssetLib/Collada/ColladaParser.cpp +++ b/code/AssetLib/Collada/ColladaParser.cpp @@ -71,7 +71,7 @@ static void ReportWarning(const char *msg, ...) { ai_assert(iLen > 0); va_end(args); - ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer, iLen)); + ASSIMP_LOG_WARN("Validation warning: ", std::string(szBuffer, iLen)); } static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) { @@ -234,7 +234,7 @@ void ColladaParser::UriDecodePath(aiString &ss) { #if defined(_MSC_VER) if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') { #else - if (ss.data[0] == '/' && isalpha(ss.data[1]) && ss.data[2] == ':') { + if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') { #endif --ss.length; ::memmove(ss.data, ss.data + 1, ss.length); @@ -623,8 +623,7 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle controller.mType = Skin; controller.mMethod = Normalized; - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); XmlNode currentNode; while (xmlIt.getNext(currentNode)) { @@ -929,8 +928,7 @@ void ColladaParser::ReadMaterial(XmlNode &node, Collada::Material &pMaterial) { // ------------------------------------------------------------------------------------------------ // Reads a light entry into the given light void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) { - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); XmlNode currentNode; while (xmlIt.getNext(currentNode)) { const std::string ¤tName = currentNode.name(); @@ -991,10 +989,8 @@ void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) { // ------------------------------------------------------------------------------------------------ // Reads a camera entry into the given light void ColladaParser::ReadCamera(XmlNode &node, Collada::Camera &camera) { - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); XmlNode currentNode; - while (xmlIt.getNext(currentNode)) { const std::string ¤tName = currentNode.name(); if (currentName == "orthographic") { @@ -1050,11 +1046,10 @@ void ColladaParser::ReadEffect(XmlNode &node, Collada::Effect &pEffect) { // ------------------------------------------------------------------------------------------------ // Reads an COMMON effect profile void ColladaParser::ReadEffectProfileCommon(XmlNode &node, Collada::Effect &pEffect) { - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); XmlNode currentNode; while (xmlIt.getNext(currentNode)) { - const std::string ¤tName = currentNode.name(); + const std::string currentName = currentNode.name(); if (currentName == "newparam") { // save ID std::string sid = currentNode.attribute("sid").as_string(); @@ -1145,10 +1140,9 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) { if (node.empty()) { return; } - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); - XmlNode currentNode; + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); + XmlNode currentNode; while (xmlIt.getNext(currentNode)) { const std::string ¤tName = currentNode.name(); // MAYA extensions @@ -1208,10 +1202,9 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p if (node.empty()) { return; } - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); - XmlNode currentNode; + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); + XmlNode currentNode; while (xmlIt.getNext(currentNode)) { const std::string ¤tName = currentNode.name(); if (currentName == "color") { @@ -1273,8 +1266,7 @@ void ColladaParser::ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam) return; } - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); XmlNode currentNode; while (xmlIt.getNext(currentNode)) { const std::string ¤tName = currentNode.name(); @@ -1360,8 +1352,7 @@ void ColladaParser::ReadMesh(XmlNode &node, Mesh &pMesh) { return; } - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); XmlNode currentNode; while (xmlIt.getNext(currentNode)) { const std::string ¤tName = currentNode.name(); @@ -1386,8 +1377,7 @@ void ColladaParser::ReadSource(XmlNode &node) { std::string sourceID; XmlParser::getStdStrAttribute(node, "id", sourceID); - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); XmlNode currentNode; while (xmlIt.getNext(currentNode)) { const std::string ¤tName = currentNode.name(); @@ -1490,8 +1480,7 @@ void ColladaParser::ReadAccessor(XmlNode &node, const std::string &pID) { acc.mSource = source.c_str() + 1; // ignore the leading '#' acc.mSize = 0; // gets incremented with every param - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); XmlNode currentNode; while (xmlIt.getNext(currentNode)) { const std::string ¤tName = currentNode.name(); @@ -1608,8 +1597,7 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) { ai_assert(primType != Prim_Invalid); // also a number of elements, but in addition a

primitive collection and probably index counts for all primitives - XmlNodeIterator xmlIt(node); - xmlIt.collectChildrenPreOrder(node); + XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode); XmlNode currentNode; while (xmlIt.getNext(currentNode)) { const std::string ¤tName = currentNode.name(); @@ -2400,7 +2388,7 @@ Collada::InputType ColladaParser::GetTypeForSemantic(const std::string &semantic else if (semantic == "TANGENT" || semantic == "TEXTANGENT") return IT_Tangent; - ASSIMP_LOG_WARN_F("Unknown vertex input type \"", semantic, "\". Ignoring."); + ASSIMP_LOG_WARN("Unknown vertex input type \"", semantic, "\". Ignoring."); return IT_Invalid; } diff --git a/code/AssetLib/DXF/DXFHelper.h b/code/AssetLib/DXF/DXFHelper.h index f7fc470e8..c7e75c3b1 100644 --- a/code/AssetLib/DXF/DXFHelper.h +++ b/code/AssetLib/DXF/DXFHelper.h @@ -135,7 +135,7 @@ public: for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++); splitter++; - ASSIMP_LOG_VERBOSE_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)")); + ASSIMP_LOG_VERBOSE_DEBUG("DXF: skipped over control group (",cnt," lines)"); } } catch(std::logic_error&) { ai_assert(!splitter); diff --git a/code/AssetLib/DXF/DXFLoader.cpp b/code/AssetLib/DXF/DXFLoader.cpp index d4a6be4ad..5d32ed121 100644 --- a/code/AssetLib/DXF/DXFLoader.cpp +++ b/code/AssetLib/DXF/DXFLoader.cpp @@ -63,11 +63,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. using namespace Assimp; // AutoCAD Binary DXF -const std::string AI_DXF_BINARY_IDENT = std::string("AutoCAD Binary DXF\r\n\x1a\0"); -const size_t AI_DXF_BINARY_IDENT_LEN = 24u; +static constexpr char AI_DXF_BINARY_IDENT[] = "AutoCAD Binary DXF\r\n\x1a"; +static constexpr size_t AI_DXF_BINARY_IDENT_LEN = sizeof AI_DXF_BINARY_IDENT; // default vertex color that all uncolored vertices will receive -const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f)); +static const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f)); // color indices for DXF - 16 are supported, the table is // taken directly from the DXF spec. @@ -156,10 +156,10 @@ void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene, } // Check whether this is a binary DXF file - we can't read binary DXF files :-( - char buff[AI_DXF_BINARY_IDENT_LEN+1] = {0}; + char buff[AI_DXF_BINARY_IDENT_LEN] = {0}; file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1); - if (0 == strncmp(AI_DXF_BINARY_IDENT.c_str(),buff,AI_DXF_BINARY_IDENT_LEN)) { + if (0 == memcmp(AI_DXF_BINARY_IDENT,buff,AI_DXF_BINARY_IDENT_LEN)) { throw DeadlyImportError("DXF: Binary files are not supported at the moment"); } @@ -202,7 +202,7 @@ void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene, // comments else if (reader.Is(999)) { - ASSIMP_LOG_INFO_F("DXF Comment: ", reader.Value()); + ASSIMP_LOG_INFO("DXF Comment: ", reader.Value()); } // don't read past the official EOF sign @@ -241,7 +241,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) { } } - ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount); + ASSIMP_LOG_VERBOSE_DEBUG("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount); } if (! output.blocks.size() ) { @@ -372,7 +372,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc // first check if the referenced blocks exists ... const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name); if (it == blocks_by_name.end()) { - ASSIMP_LOG_ERROR_F("DXF: Failed to resolve block reference: ", insert.name,"; skipping" ); + ASSIMP_LOG_ERROR("DXF: Failed to resolve block reference: ", insert.name,"; skipping" ); continue; } @@ -473,7 +473,7 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) { ++reader; } - ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" ); + ASSIMP_LOG_VERBOSE_DEBUG("DXF: got ", output.blocks.size()," entries in BLOCKS" ); } // ------------------------------------------------------------------------------------------------ @@ -549,7 +549,7 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) ++reader; } - ASSIMP_LOG_VERBOSE_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), + ASSIMP_LOG_VERBOSE_DEBUG( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), " inserted blocks in ENTITIES" ); } @@ -654,7 +654,7 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) //} if (vguess && line.positions.size() != vguess) { - ASSIMP_LOG_WARN_F("DXF: unexpected vertex count in polymesh: ", + ASSIMP_LOG_WARN("DXF: unexpected vertex count in polymesh: ", line.positions.size(),", expected ", vguess ); } @@ -670,7 +670,7 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) // to set the 71 and 72 fields, respectively, to valid values. // So just fire a warning. if (iguess && line.counts.size() != iguess) { - ASSIMP_LOG_WARN_F( "DXF: unexpected face count in polymesh: ", line.counts.size(),", expected ", iguess ); + ASSIMP_LOG_WARN( "DXF: unexpected face count in polymesh: ", line.counts.size(),", expected ", iguess ); } } else if (!line.indices.size() && !line.counts.size()) { diff --git a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp index 800d0014d..348812054 100644 --- a/code/AssetLib/FBX/FBXBinaryTokenizer.cpp +++ b/code/AssetLib/FBX/FBXBinaryTokenizer.cpp @@ -459,7 +459,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length) /*Result ignored*/ ReadByte(input, cursor, input + length); /*Result ignored*/ ReadByte(input, cursor, input + length); const uint32_t version = ReadWord(input, cursor, input + length); - ASSIMP_LOG_DEBUG_F("FBX version: ", version); + ASSIMP_LOG_DEBUG("FBX version: ", version); const bool is64bits = version >= 7500; const char *end = input + length; try diff --git a/code/AssetLib/FBX/FBXConverter.cpp b/code/AssetLib/FBX/FBXConverter.cpp index cb033a651..a564b3e9b 100644 --- a/code/AssetLib/FBX/FBXConverter.cpp +++ b/code/AssetLib/FBX/FBXConverter.cpp @@ -811,7 +811,7 @@ bool FBXConverter::GenerateTransformationNodeChain(const Model &model, const std // we need to generate a full node chain to accommodate for assimp's // lack to express pivots and offsets. if ((chainBits & chainMaskComplex) && doc.Settings().preservePivots) { - FBXImporter::LogInfo("generating full transformation chain for node: " + name); + FBXImporter::LogInfo("generating full transformation chain for node: ", name); // query the anim_chain_bits dictionary to find out which chain elements // have associated node animation channels. These can not be dropped @@ -918,7 +918,7 @@ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root const std::vector &indices = ConvertLine(*line, root_node); std::copy(indices.begin(), indices.end(), std::back_inserter(meshes)); } else { - FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name()); + FBXImporter::LogWarn("ignoring unrecognized geometry: ", geo->Name()); } } @@ -944,7 +944,7 @@ FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode * const std::vector &vertices = mesh.GetVertices(); const std::vector &faces = mesh.GetFaceIndexCounts(); if (vertices.empty() || faces.empty()) { - FBXImporter::LogWarn("ignoring empty geometry: " + mesh.Name()); + FBXImporter::LogWarn("ignoring empty geometry: ", mesh.Name()); return temp; } @@ -971,7 +971,7 @@ std::vector FBXConverter::ConvertLine(const LineGeometry &line, ai const std::vector &vertices = line.GetVertices(); const std::vector &indices = line.GetIndices(); if (vertices.empty() || indices.empty()) { - FBXImporter::LogWarn("ignoring empty line: " + line.Name()); + FBXImporter::LogWarn("ignoring empty line: ", line.Name()); return temp; } @@ -1126,6 +1126,8 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c *out_uv++ = aiVector3D(v.x, v.y, 0.0f); } + out_mesh->mTextureCoordsNames[i] = mesh.GetTextureCoordChannelName(i); + out_mesh->mNumUVComponents[i] = 2; } @@ -1542,10 +1544,10 @@ void FBXConverter::ConvertCluster(std::vector &local_mesh_bones, const aiBone *bone = nullptr; if (bone_map.count(deformer_name)) { - ASSIMP_LOG_VERBOSE_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name); + ASSIMP_LOG_VERBOSE_DEBUG("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name); bone = bone_map[deformer_name]; } else { - ASSIMP_LOG_VERBOSE_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name); + ASSIMP_LOG_VERBOSE_DEBUG("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name); bone = new aiBone(); bone->mName = bone_name; @@ -1591,7 +1593,7 @@ void FBXConverter::ConvertCluster(std::vector &local_mesh_bones, const bone_map.insert(std::pair(deformer_name, bone)); } - ASSIMP_LOG_DEBUG_F("bone research: Indicies size: ", out_indices.size()); + ASSIMP_LOG_DEBUG("bone research: Indicies size: ", out_indices.size()); // lookup must be populated in case something goes wrong // this also allocates bones to mesh instance outside @@ -1815,14 +1817,14 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap } } if (index == -1) { - FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material"); continue; } if (uvIndex == -1) { uvIndex = index; } else { - FBXImporter::LogWarn("the UV channel named " + uvSet + + FBXImporter::LogWarn("the UV channel named ", uvSet, " appears at different positions in meshes, results will be wrong"); } } @@ -1839,7 +1841,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap } } if (index == -1) { - FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material"); } if (uvIndex == -1) { @@ -1848,7 +1850,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap } if (uvIndex == -1) { - FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); + FBXImporter::LogWarn("failed to resolve UV channel ", uvSet, ", using first UV channel"); uvIndex = 0; } } @@ -1934,14 +1936,14 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex } } if (index == -1) { - FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material"); continue; } if (uvIndex == -1) { uvIndex = index; } else { - FBXImporter::LogWarn("the UV channel named " + uvSet + + FBXImporter::LogWarn("the UV channel named ", uvSet, " appears at different positions in meshes, results will be wrong"); } } @@ -1958,7 +1960,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex } } if (index == -1) { - FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material"); } if (uvIndex == -1) { @@ -1967,7 +1969,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex } if (uvIndex == -1) { - FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); + FBXImporter::LogWarn("failed to resolve UV channel ", uvSet, ", using first UV channel"); uvIndex = 0; } } @@ -2126,7 +2128,12 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert const aiColor3D &Emissive = GetColorPropertyFromMaterial(props, "Emissive", ok); if (ok) { out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE); - } + } else { + const aiColor3D &emissiveColor = GetColorPropertyFromMaterial(props, "Maya|emissive", ok); + if (ok) { + out_mat->AddProperty(&emissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE); + } + } const aiColor3D &Ambient = GetColorPropertyFromMaterial(props, "Ambient", ok); if (ok) { @@ -2207,6 +2214,52 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert if (ok) { out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0); } + + // PBR material information + const aiColor3D &baseColor = GetColorPropertyFromMaterial(props, "Maya|base_color", ok); + if (ok) { + out_mat->AddProperty(&baseColor, 1, AI_MATKEY_BASE_COLOR); + } + + const float useColorMap = PropertyGet(props, "Maya|use_color_map", ok); + if (ok) { + out_mat->AddProperty(&useColorMap, 1, AI_MATKEY_USE_COLOR_MAP); + } + + const float useMetallicMap = PropertyGet(props, "Maya|use_metallic_map", ok); + if (ok) { + out_mat->AddProperty(&useMetallicMap, 1, AI_MATKEY_USE_METALLIC_MAP); + } + + const float metallicFactor = PropertyGet(props, "Maya|metallic", ok); + if (ok) { + out_mat->AddProperty(&metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR); + } + + const float useRoughnessMap = PropertyGet(props, "Maya|use_roughness_map", ok); + if (ok) { + out_mat->AddProperty(&useRoughnessMap, 1, AI_MATKEY_USE_ROUGHNESS_MAP); + } + + const float roughnessFactor = PropertyGet(props, "Maya|roughness", ok); + if (ok) { + out_mat->AddProperty(&roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR); + } + + const float useEmissiveMap = PropertyGet(props, "Maya|use_emissive_map", ok); + if (ok) { + out_mat->AddProperty(&useEmissiveMap, 1, AI_MATKEY_USE_EMISSIVE_MAP); + } + + const float emissiveIntensity = PropertyGet(props, "Maya|emissive_intensity", ok); + if (ok) { + out_mat->AddProperty(&emissiveIntensity, 1, AI_MATKEY_EMISSIVE_INTENSITY); + } + + const float useAOMap = PropertyGet(props, "Maya|use_ao_map", ok); + if (ok) { + out_mat->AddProperty(&useAOMap, 1, AI_MATKEY_USE_AO_MAP); + } } void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTable &props, const TextureMap &_textures, const MeshGeometry *const mesh) { @@ -2319,14 +2372,14 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa } } if (index == -1) { - FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material"); continue; } if (uvIndex == -1) { uvIndex = index; } else { - FBXImporter::LogWarn("the UV channel named " + uvSet + " appears at different positions in meshes, results will be wrong"); + FBXImporter::LogWarn("the UV channel named ", uvSet, " appears at different positions in meshes, results will be wrong"); } } } else { @@ -2342,7 +2395,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa } } if (index == -1) { - FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material"); + FBXImporter::LogWarn("did not find UV channel named ", uvSet, " in a mesh using this material"); } if (uvIndex == -1) { @@ -2351,7 +2404,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa } if (uvIndex == -1) { - FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel"); + FBXImporter::LogWarn("failed to resolve UV channel ", uvSet, ", using first UV channel"); uvIndex = 0; } } @@ -2574,7 +2627,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) { // empty animations would fail validation, so drop them delete anim; animations.pop_back(); - FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): " + name); + FBXImporter::LogInfo("ignoring empty AnimationStack (using IK?): ", name); return; } @@ -2707,13 +2760,13 @@ void FBXConverter::GenerateNodeAnimations(std::vector &node_anims, ai_assert(node); if (node->TargetProperty().empty()) { - FBXImporter::LogWarn("target property for animation curve not set: " + node->Name()); + FBXImporter::LogWarn("target property for animation curve not set: ", node->Name()); continue; } curve_node = node; if (node->Curves().empty()) { - FBXImporter::LogWarn("no animation curves assigned to AnimationCurveNode: " + node->Name()); + FBXImporter::LogWarn("no animation curves assigned to AnimationCurveNode: ", node->Name()); continue; } @@ -2748,7 +2801,7 @@ void FBXConverter::GenerateNodeAnimations(std::vector &node_anims, if (doc.Settings().optimizeEmptyAnimationCurves && IsRedundantAnimationData(target, comp, (chain[i]->second))) { - FBXImporter::LogVerboseDebug("dropping redundant animation channel for node " + target.Name()); + FBXImporter::LogVerboseDebug("dropping redundant animation channel for node ", target.Name()); continue; } diff --git a/code/AssetLib/FBX/FBXDocument.cpp b/code/AssetLib/FBX/FBXDocument.cpp index a9eb3ad15..7adaadf6c 100644 --- a/code/AssetLib/FBX/FBXDocument.cpp +++ b/code/AssetLib/FBX/FBXDocument.cpp @@ -312,7 +312,7 @@ void Document::ReadHeader() { const Scope& shead = *ehead->Compound(); fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0)); - ASSIMP_LOG_DEBUG_F("FBX Version: ", fbxVersion); + ASSIMP_LOG_DEBUG("FBX Version: ", fbxVersion); // While we may have some success with newer files, we don't support // the older 6.n fbx format diff --git a/code/AssetLib/FBX/FBXDocumentUtil.cpp b/code/AssetLib/FBX/FBXDocumentUtil.cpp index 6ba01aa47..ab15298a8 100644 --- a/code/AssetLib/FBX/FBXDocumentUtil.cpp +++ b/code/AssetLib/FBX/FBXDocumentUtil.cpp @@ -79,7 +79,7 @@ void DOMError(const std::string& message, const Element* element /*= nullptr*/) void DOMWarning(const std::string& message, const Token& token) { if(DefaultLogger::get()) { - ASSIMP_LOG_WARN_F("FBX-DOM", Util::GetTokenText(&token), message); + ASSIMP_LOG_WARN("FBX-DOM", Util::GetTokenText(&token), message); } } @@ -91,7 +91,7 @@ void DOMWarning(const std::string& message, const Element* element /*= nullptr*/ return; } if(DefaultLogger::get()) { - ASSIMP_LOG_WARN("FBX-DOM: " + message); + ASSIMP_LOG_WARN("FBX-DOM: ", message); } } diff --git a/code/AssetLib/FBX/FBXMaterial.cpp b/code/AssetLib/FBX/FBXMaterial.cpp index 3af014bc3..6ada9630b 100644 --- a/code/AssetLib/FBX/FBXMaterial.cpp +++ b/code/AssetLib/FBX/FBXMaterial.cpp @@ -82,7 +82,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con // lower-case shading because Blender (for example) writes "Phong" for (size_t i = 0; i < shading.length(); ++i) { - shading[i] = static_cast(tolower(shading[i])); + shading[i] = static_cast(tolower(static_cast(shading[i]))); } std::string templateName; if(shading == "phong") { @@ -352,7 +352,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std } } catch (const runtime_error& runtimeError) { //we don't need the content data for contents that has already been loaded - ASSIMP_LOG_VERBOSE_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ", + ASSIMP_LOG_VERBOSE_DEBUG("Caught exception in FBXMaterial (likely because content was already loaded): ", runtimeError.what()); } } diff --git a/code/AssetLib/FBX/FBXMeshGeometry.cpp b/code/AssetLib/FBX/FBXMeshGeometry.cpp index 2bca8dff2..5aecb61b5 100644 --- a/code/AssetLib/FBX/FBXMeshGeometry.cpp +++ b/code/AssetLib/FBX/FBXMeshGeometry.cpp @@ -307,8 +307,8 @@ void MeshGeometry::ReadLayerElement(const Scope& layerElement) } } - FBXImporter::LogError(Formatter::format("failed to resolve vertex layer element: ") - << type << ", index: " << typedIndex); + FBXImporter::LogError("failed to resolve vertex layer element: ", + type, ", index: ", typedIndex); } // ------------------------------------------------------------------------------------------------ @@ -324,8 +324,8 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop if (type == "LayerElementUV") { if(index >= AI_MAX_NUMBER_OF_TEXTURECOORDS) { - FBXImporter::LogError(Formatter::format("ignoring UV layer, maximum number of UV channels exceeded: ") - << index << " (limit is " << AI_MAX_NUMBER_OF_TEXTURECOORDS << ")" ); + FBXImporter::LogError("ignoring UV layer, maximum number of UV channels exceeded: ", + index, " (limit is ", AI_MAX_NUMBER_OF_TEXTURECOORDS, ")" ); return; } @@ -402,8 +402,8 @@ void MeshGeometry::ReadVertexData(const std::string& type, int index, const Scop } else if (type == "LayerElementColor") { if(index >= AI_MAX_NUMBER_OF_COLOR_SETS) { - FBXImporter::LogError(Formatter::format("ignoring vertex color layer, maximum number of color sets exceeded: ") - << index << " (limit is " << AI_MAX_NUMBER_OF_COLOR_SETS << ")" ); + FBXImporter::LogError("ignoring vertex color layer, maximum number of color sets exceeded: ", + index, " (limit is ", AI_MAX_NUMBER_OF_COLOR_SETS, ")" ); return; } @@ -449,8 +449,8 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); if (tempData.size() != mapping_offsets.size()) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") - << tempData.size() << ", expected " << mapping_offsets.size()); + FBXImporter::LogError("length of input data unexpected for ByVertice mapping: ", + tempData.size(), ", expected ", mapping_offsets.size()); return; } @@ -470,8 +470,8 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); if (uvIndices.size() != vertex_count) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ") - << uvIndices.size() << ", expected " << vertex_count); + FBXImporter::LogError("length of input data unexpected for ByVertice mapping: ", + uvIndices.size(), ", expected ", vertex_count); return; } @@ -493,8 +493,8 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName)); if (tempData.size() != vertex_count) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ") - << tempData.size() << ", expected " << vertex_count + FBXImporter::LogError("length of input data unexpected for ByPolygon mapping: ", + tempData.size(), ", expected ", vertex_count ); return; } @@ -509,14 +509,14 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, ParseVectorDataArray(uvIndices,GetRequiredElement(source,indexDataElementName)); if (uvIndices.size() > vertex_count) { - FBXImporter::LogWarn(Formatter::format("trimming length of input array for ByPolygonVertex mapping: ") - << uvIndices.size() << ", expected " << vertex_count); + FBXImporter::LogWarn("trimming length of input array for ByPolygonVertex mapping: ", + uvIndices.size(), ", expected ", vertex_count); uvIndices.resize(vertex_count); } if (uvIndices.size() != vertex_count) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygonVertex mapping: ") - << uvIndices.size() << ", expected " << vertex_count); + FBXImporter::LogError("length of input data unexpected for ByPolygonVertex mapping: ", + uvIndices.size(), ", expected ", vertex_count); return; } @@ -537,8 +537,8 @@ void ResolveVertexDataArray(std::vector& data_out, const Scope& source, } } else { - FBXImporter::LogError(Formatter::format("ignoring vertex data channel, access type not implemented: ") - << MappingInformationType << "," << ReferenceInformationType); + FBXImporter::LogError("ignoring vertex data channel, access type not implemented: ", + MappingInformationType, ",", ReferenceInformationType); } } @@ -604,15 +604,15 @@ void MeshGeometry::ReadVertexDataTangents(std::vector& tangents_out, } // ------------------------------------------------------------------------------------------------ -static const std::string BinormalIndexToken = "BinormalIndex"; -static const std::string BinormalsIndexToken = "BinormalsIndex"; +static const char * BinormalIndexToken = "BinormalIndex"; +static const char * BinormalsIndexToken = "BinormalsIndex"; void MeshGeometry::ReadVertexDataBinormals(std::vector& binormals_out, const Scope& source, const std::string& MappingInformationType, const std::string& ReferenceInformationType) { const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal"; - const char * strIdx = source.Elements().count( "Binormals" ) > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str(); + const char * strIdx = source.Elements().count( "Binormals" ) > 0 ? BinormalsIndexToken : BinormalIndexToken; ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType, str, strIdx, @@ -642,10 +642,10 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector& materials_out, cons if (MappingInformationType == "AllSame") { // easy - same material for all faces if (materials_out.empty()) { - FBXImporter::LogError(Formatter::format("expected material index, ignoring")); + FBXImporter::LogError("expected material index, ignoring"); return; } else if (materials_out.size() > 1) { - FBXImporter::LogWarn(Formatter::format("expected only a single material index, ignoring all except the first one")); + FBXImporter::LogWarn("expected only a single material index, ignoring all except the first one"); materials_out.clear(); } @@ -655,14 +655,14 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector& materials_out, cons materials_out.resize(face_count); if(materials_out.size() != face_count) { - FBXImporter::LogError(Formatter::format("length of input data unexpected for ByPolygon mapping: ") - << materials_out.size() << ", expected " << face_count + FBXImporter::LogError("length of input data unexpected for ByPolygon mapping: ", + materials_out.size(), ", expected ", face_count ); return; } } else { - FBXImporter::LogError(Formatter::format("ignoring material assignments, access type not implemented: ") - << MappingInformationType << "," << ReferenceInformationType); + FBXImporter::LogError("ignoring material assignments, access type not implemented: ", + MappingInformationType, ",", ReferenceInformationType); } } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/FBX/FBXProperties.cpp b/code/AssetLib/FBX/FBXProperties.cpp index 1e4cd0ead..1a5ebffd1 100644 --- a/code/AssetLib/FBX/FBXProperties.cpp +++ b/code/AssetLib/FBX/FBXProperties.cpp @@ -131,7 +131,7 @@ Property* ReadTypedProperty(const Element& element) ParseTokenAsFloat(*tok[6])) ); } - else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) { + else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"float") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) { checkTokenCount(tok, 5); return new TypedProperty(ParseTokenAsFloat(*tok[4])); } diff --git a/code/AssetLib/HMP/HMPLoader.cpp b/code/AssetLib/HMP/HMPLoader.cpp index 56401f5c9..cd14cb9c3 100644 --- a/code/AssetLib/HMP/HMPLoader.cpp +++ b/code/AssetLib/HMP/HMPLoader.cpp @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include "AssetLib/HMP/HMPLoader.h" #include "AssetLib/MD2/MD2FileData.h" +#include #include #include #include @@ -151,12 +152,7 @@ void HMPImporter::InternReadFile(const std::string &pFile, InternReadFile_HMP7(); } else { // Print the magic word to the logger - char szBuffer[5]; - szBuffer[0] = ((char *)&iMagic)[0]; - szBuffer[1] = ((char *)&iMagic)[1]; - szBuffer[2] = ((char *)&iMagic)[2]; - szBuffer[3] = ((char *)&iMagic)[3]; - szBuffer[4] = '\0'; + std::string szBuffer = ai_str_toprintable((const char *)&iMagic, sizeof(iMagic)); delete[] mBuffer; mBuffer = nullptr; diff --git a/code/AssetLib/IFC/IFCBoolean.cpp b/code/AssetLib/IFC/IFCBoolean.cpp index 6015920c1..86cac7f46 100644 --- a/code/AssetLib/IFC/IFCBoolean.cpp +++ b/code/AssetLib/IFC/IFCBoolean.cpp @@ -715,7 +715,7 @@ void ProcessBoolean(const Schema_2x3::IfcBooleanResult &boolean, TempMesh &resul // DIFFERENCE if (const Schema_2x3::IfcBooleanResult *const clip = boolean.ToPtr()) { if (clip->Operator != "DIFFERENCE") { - IFCImporter::LogWarn("encountered unsupported boolean operator: " + (std::string)clip->Operator); + IFCImporter::LogWarn("encountered unsupported boolean operator: ", (std::string)clip->Operator); return; } @@ -756,7 +756,7 @@ void ProcessBoolean(const Schema_2x3::IfcBooleanResult &boolean, TempMesh &resul ProcessBooleanExtrudedAreaSolidDifference(as, result, first_operand, conv); } } else { - IFCImporter::LogWarn("skipping unknown IfcBooleanResult entity, type is " + boolean.GetClassName()); + IFCImporter::LogWarn("skipping unknown IfcBooleanResult entity, type is ", boolean.GetClassName()); } } diff --git a/code/AssetLib/IFC/IFCGeometry.cpp b/code/AssetLib/IFC/IFCGeometry.cpp index 664444443..6e645f1ae 100644 --- a/code/AssetLib/IFC/IFCGeometry.cpp +++ b/code/AssetLib/IFC/IFCGeometry.cpp @@ -216,7 +216,7 @@ void ProcessConnectedFaceSet(const Schema_2x3::IfcConnectedFaceSet& fset, TempMe } } else { - IFCImporter::LogWarn("skipping unknown IfcFaceBound entity, type is " + bound.Bound->GetClassName()); + IFCImporter::LogWarn("skipping unknown IfcFaceBound entity, type is ", bound.Bound->GetClassName()); continue; } @@ -729,7 +729,7 @@ void ProcessSweptAreaSolid(const Schema_2x3::IfcSweptAreaSolid& swept, TempMesh& ProcessRevolvedAreaSolid(*rev,meshout,conv); } else { - IFCImporter::LogWarn("skipping unknown IfcSweptAreaSolid entity, type is " + swept.GetClassName()); + IFCImporter::LogWarn("skipping unknown IfcSweptAreaSolid entity, type is ", swept.GetClassName()); } } @@ -781,7 +781,7 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned return false; } else { - IFCImporter::LogWarn("skipping unknown IfcGeometricRepresentationItem entity, type is " + geo.GetClassName()); + IFCImporter::LogWarn("skipping unknown IfcGeometricRepresentationItem entity, type is ", geo.GetClassName()); return false; } diff --git a/code/AssetLib/IFC/IFCLoader.cpp b/code/AssetLib/IFC/IFCLoader.cpp index bdac1801a..daf2cc946 100644 --- a/code/AssetLib/IFC/IFCLoader.cpp +++ b/code/AssetLib/IFC/IFCLoader.cpp @@ -243,12 +243,12 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy } if (!DefaultLogger::isNullLogger()) { - LogDebug("File schema is \'" + head.fileSchema + '\''); + LogDebug("File schema is \'", head.fileSchema, '\''); if (head.timestamp.length()) { - LogDebug("Timestamp \'" + head.timestamp + '\''); + LogDebug("Timestamp \'", head.timestamp, '\''); } if (head.app.length()) { - LogDebug("Application/Exporter identline is \'" + head.app + '\''); + LogDebug("Application/Exporter identline is \'", head.app, '\''); } } @@ -315,7 +315,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // this must be last because objects are evaluated lazily as we process them if (!DefaultLogger::isNullLogger()) { - LogDebug((Formatter::format(), "STEP: evaluated ", db->GetEvaluatedObjectCount(), " object records")); + LogDebug("STEP: evaluated ", db->GetEvaluatedObjectCount(), " object records"); } } @@ -403,7 +403,7 @@ void ResolveObjectPlacement(aiMatrix4x4 &m, const Schema_2x3::IfcObjectPlacement m = tmpM * m; } } else { - IFCImporter::LogWarn("skipping unknown IfcObjectPlacement entity, type is " + place.GetClassName()); + IFCImporter::LogWarn("skipping unknown IfcObjectPlacement entity, type is ", place.GetClassName()); } } @@ -438,7 +438,7 @@ bool ProcessMappedItem(const Schema_2x3::IfcMappedItem &mapped, aiNode *nd_src, bool got = false; for (const Schema_2x3::IfcRepresentationItem &item : repr.Items) { if (!ProcessRepresentationItem(item, localmatid, meshes, conv)) { - IFCImporter::LogWarn("skipping mapped entity of type " + item.GetClassName() + ", no representations could be generated"); + IFCImporter::LogWarn("skipping mapped entity of type ", item.GetClassName(), ", no representations could be generated"); } else got = true; } @@ -856,7 +856,7 @@ void ProcessSpatialStructures(ConversionData &conv) { if (!prod) { continue; } - IFCImporter::LogVerboseDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : "")); + IFCImporter::LogVerboseDebug("looking at spatial structure `", (prod->Name ? prod->Name.Get() : "unnamed"), "`", (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : "")); // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT const STEP::DB::RefMap &refs = conv.db.GetRefs(); diff --git a/code/AssetLib/IFC/IFCMaterial.cpp b/code/AssetLib/IFC/IFCMaterial.cpp index e0146b887..2a79f0754 100644 --- a/code/AssetLib/IFC/IFCMaterial.cpp +++ b/code/AssetLib/IFC/IFCMaterial.cpp @@ -64,7 +64,7 @@ static int ConvertShadingMode(const std::string& name) { else if (name == "PHONG") { return aiShadingMode_Phong; } - IFCImporter::LogWarn("shading mode "+name+" not recognized by Assimp, using Phong instead"); + IFCImporter::LogWarn("shading mode ", name, " not recognized by Assimp, using Phong instead"); return aiShadingMode_Phong; } @@ -145,7 +145,7 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat // not found, create new material const std::string side = static_cast(surf->Side); if( side != "BOTH" ) { - IFCImporter::LogWarn("ignoring surface side marker on IFC::IfcSurfaceStyle: " + side); + IFCImporter::LogWarn("ignoring surface side marker on IFC::IfcSurfaceStyle: ", side); } std::unique_ptr mat(new aiMaterial()); diff --git a/code/AssetLib/IFC/IFCProfile.cpp b/code/AssetLib/IFC/IFCProfile.cpp index f33f8cdbe..4235be181 100644 --- a/code/AssetLib/IFC/IFCProfile.cpp +++ b/code/AssetLib/IFC/IFCProfile.cpp @@ -68,7 +68,7 @@ bool ProcessCurve(const Schema_2x3::IfcCurve& curve, TempMesh& meshout, Convers { std::unique_ptr cv(Curve::Convert(curve,conv)); if (!cv) { - IFCImporter::LogWarn("skipping unknown IfcCurve entity, type is " + curve.GetClassName()); + IFCImporter::LogWarn("skipping unknown IfcCurve entity, type is ", curve.GetClassName()); return false; } @@ -78,7 +78,7 @@ bool ProcessCurve(const Schema_2x3::IfcCurve& curve, TempMesh& meshout, Convers bc->SampleDiscrete(meshout); } catch(const CurveError& cv) { - IFCImporter::LogError(cv.mStr + " (error occurred while processing curve)"); + IFCImporter::LogError(cv.mStr, " (error occurred while processing curve)"); return false; } meshout.mVertcnt.push_back(static_cast(meshout.mVerts.size())); @@ -152,7 +152,7 @@ void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& de meshout.mVertcnt.push_back(12); } else { - IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is " + def.GetClassName()); + IFCImporter::LogWarn("skipping unknown IfcParameterizedProfileDef entity, type is ", def.GetClassName()); return; } @@ -174,7 +174,7 @@ bool ProcessProfile(const Schema_2x3::IfcProfileDef& prof, TempMesh& meshout, Co ProcessParametrizedProfile(*cparam,meshout,conv); } else { - IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is " + prof.GetClassName()); + IFCImporter::LogWarn("skipping unknown IfcProfileDef entity, type is ", prof.GetClassName()); return false; } meshout.RemoveAdjacentDuplicates(); diff --git a/code/AssetLib/IFC/IFCUtil.cpp b/code/AssetLib/IFC/IFCUtil.cpp index b451262e9..8c37cebed 100644 --- a/code/AssetLib/IFC/IFCUtil.cpp +++ b/code/AssetLib/IFC/IFCUtil.cpp @@ -506,7 +506,7 @@ IfcFloat ConvertSIPrefix(const std::string& prefix) return 1e-18f; } else { - IFCImporter::LogError("Unrecognized SI prefix: " + prefix); + IFCImporter::LogError("Unrecognized SI prefix: ", prefix); return 1; } } diff --git a/code/AssetLib/Irr/IRRLoader.cpp b/code/AssetLib/Irr/IRRLoader.cpp index ed92c93bb..cb383e936 100644 --- a/code/AssetLib/Irr/IRRLoader.cpp +++ b/code/AssetLib/Irr/IRRLoader.cpp @@ -639,7 +639,7 @@ void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene, // graph we're currently building aiScene *localScene = batch.GetImport(root->id); if (!localScene) { - ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath); + ASSIMP_LOG_ERROR("IRR: Unable to load external file: ", root->meshPath); break; } attach.push_back(AttachmentInfo(localScene, rootOut)); @@ -859,13 +859,13 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // Check whether we can read from the file if (file.get() == nullptr) { - throw DeadlyImportError("Failed to open IRR file " + pFile); + throw DeadlyImportError("Failed to open IRR file ", pFile); } // Construct the irrXML parser XmlParser st; if (!st.parse( file.get() )) { - return; + throw DeadlyImportError("XML parse error while loading IRR file ", pFile); } pugi::xml_node rootElement = st.getRootNode(); @@ -963,7 +963,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp"); nd = new Node(Node::DUMMY); } else { - ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(attrib.name())); + ASSIMP_LOG_WARN("IRR: Found unknown node: ", attrib.name()); /* We skip the contents of nodes we don't know. * We parse the transformation and all animators @@ -1181,7 +1181,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy lights.pop_back(); curNode->type = Node::DUMMY; - ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value); + ASSIMP_LOG_ERROR("Ignoring light of unknown type: ", prop.value); } } else if ((prop.name == "Mesh" && Node::MESH == curNode->type) || Node::ANIMMESH == curNode->type) { @@ -1225,7 +1225,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy } else if (prop.value == "followSpline") { curAnim->type = Animator::FOLLOW_SPLINE; } else { - ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: " + prop.value); + ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: ", prop.value); curAnim->type = Animator::UNKNOWN; } diff --git a/code/AssetLib/Irr/IRRMeshLoader.cpp b/code/AssetLib/Irr/IRRMeshLoader.cpp index edcff6c83..9350e07b8 100644 --- a/code/AssetLib/Irr/IRRMeshLoader.cpp +++ b/code/AssetLib/Irr/IRRMeshLoader.cpp @@ -135,12 +135,12 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile, // Check whether we can read from the file if (file.get() == NULL) - throw DeadlyImportError("Failed to open IRRMESH file " + pFile); + throw DeadlyImportError("Failed to open IRRMESH file ", pFile); // Construct the irrXML parser XmlParser parser; if (!parser.parse( file.get() )) { - return; + throw DeadlyImportError("XML parse error while loading IRRMESH file ", pFile); } XmlNode root = parser.getRootNode(); diff --git a/code/AssetLib/Irr/IRRShared.cpp b/code/AssetLib/Irr/IRRShared.cpp index b119b063a..b42f34b65 100644 --- a/code/AssetLib/Irr/IRRShared.cpp +++ b/code/AssetLib/Irr/IRRShared.cpp @@ -260,7 +260,7 @@ aiMaterial* IrrlichtBase::ParseMaterial(unsigned int& matFlags) { prop.value == "parallaxmap_trans_add") { matFlags = AI_IRRMESH_MAT_normalmap_ta; } else { - ASSIMP_LOG_WARN("IRRMat: Unrecognized material type: " + prop.value); + ASSIMP_LOG_WARN("IRRMat: Unrecognized material type: ", prop.value); } } diff --git a/code/AssetLib/LWO/LWOBLoader.cpp b/code/AssetLib/LWO/LWOBLoader.cpp index 2654eccf4..8ef40fc21 100644 --- a/code/AssetLib/LWO/LWOBLoader.cpp +++ b/code/AssetLib/LWO/LWOBLoader.cpp @@ -242,7 +242,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i else { // procedural or gradient, not supported - ASSIMP_LOG_ERROR_F("LWOB: Unsupported legacy texture: ", type); + ASSIMP_LOG_ERROR("LWOB: Unsupported legacy texture: ", type); } return tex; diff --git a/code/AssetLib/LWO/LWOLoader.cpp b/code/AssetLib/LWO/LWOLoader.cpp index a9fa08f11..bc62152c5 100644 --- a/code/AssetLib/LWO/LWOLoader.cpp +++ b/code/AssetLib/LWO/LWOLoader.cpp @@ -961,7 +961,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) { switch (type) { case AI_LWO_TXUV: if (dims != 2) { - ASSIMP_LOG_WARN("LWO2: Skipping UV channel \'" + name + "\' with !2 components"); + ASSIMP_LOG_WARN("LWO2: Skipping UV channel \'", name, "\' with !2 components"); return; } base = FindEntry(mCurLayer->mUVChannels, name, perPoly); @@ -969,7 +969,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) { case AI_LWO_WGHT: case AI_LWO_MNVW: if (dims != 1) { - ASSIMP_LOG_WARN("LWO2: Skipping Weight Channel \'" + name + "\' with !1 components"); + ASSIMP_LOG_WARN("LWO2: Skipping Weight Channel \'", name, "\' with !1 components"); return; } base = FindEntry((type == AI_LWO_WGHT ? mCurLayer->mWeightChannels : mCurLayer->mSWeightChannels), name, perPoly); @@ -977,7 +977,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) { case AI_LWO_RGB: case AI_LWO_RGBA: if (dims != 3 && dims != 4) { - ASSIMP_LOG_WARN("LWO2: Skipping Color Map \'" + name + "\' with a dimension > 4 or < 3"); + ASSIMP_LOG_WARN("LWO2: Skipping Color Map \'", name, "\' with a dimension > 4 or < 3"); return; } base = FindEntry(mCurLayer->mVColorChannels, name, perPoly); @@ -1006,7 +1006,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) { if (name == "APS.Level") { // XXX handle this (seems to be subdivision-related). } - ASSIMP_LOG_WARN_F("LWO2: Skipping unknown VMAP/VMAD channel \'", name, "\'"); + ASSIMP_LOG_WARN("LWO2: Skipping unknown VMAP/VMAD channel \'", name, "\'"); return; }; base->Allocate((unsigned int)mCurLayer->mTempPoints.size()); @@ -1026,7 +1026,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) { unsigned int idx = ReadVSizedIntLWO2(mFileBuffer) + mCurLayer->mPointIDXOfs; if (idx >= numPoints) { - ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAP/VMAD entry \'", name, "\', vertex index is out of range"); + ASSIMP_LOG_WARN("LWO2: Failure evaluating VMAP/VMAD entry \'", name, "\', vertex index is out of range"); mFileBuffer += base->dims << 2u; continue; } @@ -1036,7 +1036,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) { // we have already a VMAP entry for this vertex - thus // we need to duplicate the corresponding polygon. if (polyIdx >= numFaces) { - ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAD entry \'", name, "\', polygon index is out of range"); + ASSIMP_LOG_WARN("LWO2: Failure evaluating VMAD entry \'", name, "\', polygon index is out of range"); mFileBuffer += base->dims << 2u; continue; } @@ -1076,7 +1076,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) { CreateNewEntry(mCurLayer->mNormals, srcIdx); } if (!had) { - ASSIMP_LOG_WARN_F("LWO2: Failure evaluating VMAD entry \'", name, "\', vertex index wasn't found in that polygon"); + ASSIMP_LOG_WARN("LWO2: Failure evaluating VMAD entry \'", name, "\', vertex index wasn't found in that polygon"); ai_assert(had); } } diff --git a/code/AssetLib/LWO/LWOMaterial.cpp b/code/AssetLib/LWO/LWOMaterial.cpp index 9d51438d7..178f24265 100644 --- a/code/AssetLib/LWO/LWOMaterial.cpp +++ b/code/AssetLib/LWO/LWOMaterial.cpp @@ -335,7 +335,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface &surf, aiMaterial *pcMat) { m = aiShadingMode_Fresnel; break; } else { - ASSIMP_LOG_WARN_F("LWO2: Unknown surface shader: ", shader.functionName); + ASSIMP_LOG_WARN("LWO2: Unknown surface shader: ", shader.functionName); } } if (surf.mMaximumSmoothAngle <= 0.0) @@ -711,7 +711,7 @@ void LWOImporter::LoadLWO2Surface(unsigned int size) { } } if (derived.size()) { - ASSIMP_LOG_WARN("LWO2: Unable to find source surface: " + derived); + ASSIMP_LOG_WARN("LWO2: Unable to find source surface: ", derived); } } diff --git a/code/AssetLib/LWS/LWSLoader.cpp b/code/AssetLib/LWS/LWSLoader.cpp index a75b90ef9..d469a1064 100644 --- a/code/AssetLib/LWS/LWSLoader.cpp +++ b/code/AssetLib/LWS/LWSLoader.cpp @@ -346,7 +346,7 @@ void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vectormRootNode->mNumChildren == 1) { @@ -538,7 +538,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // get file format version and print to log ++it; unsigned int version = strtoul10((*it).tokens[0].c_str()); - ASSIMP_LOG_INFO("LWS file format version is " + (*it).tokens[0]); + ASSIMP_LOG_INFO("LWS file format version is ", (*it).tokens[0]); first = 0.; last = 60.; fps = 25.; // seems to be a good default frame rate diff --git a/code/AssetLib/M3D/M3DExporter.cpp b/code/AssetLib/M3D/M3DExporter.cpp index 856932947..bcac1d98a 100644 --- a/code/AssetLib/M3D/M3DExporter.cpp +++ b/code/AssetLib/M3D/M3DExporter.cpp @@ -294,21 +294,17 @@ void ExportSceneM3D( // Worker function for exporting a scene to ASCII A3D. // Prototyped and registered in Exporter.cpp void ExportSceneM3DA( - const char *, - IOSystem *, - const aiScene *, - const ExportProperties * + const char *pFile, + IOSystem *pIOSystem, + const aiScene *pScene, + const ExportProperties *pProperties ) { -#ifdef M3D_ASCII // initialize the exporter M3DExporter exporter(pScene, pProperties); // perform ascii export exporter.doExport(pFile, pIOSystem, true); -#else - throw DeadlyExportError("Assimp configured without M3D_ASCII support"); -#endif } // ------------------------------------------------------------------------------------------------ diff --git a/code/AssetLib/M3D/M3DImporter.cpp b/code/AssetLib/M3D/M3DImporter.cpp index b7ba74c8a..38bbd1d4a 100644 --- a/code/AssetLib/M3D/M3DImporter.cpp +++ b/code/AssetLib/M3D/M3DImporter.cpp @@ -95,10 +95,7 @@ static const aiImporterDesc desc = { 0, 0, 0, - "m3d" -#ifdef M3D_ASCII - " a3d" -#endif + "m3d a3d" }; namespace Assimp { @@ -118,9 +115,7 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c const std::string extension = GetExtension(pFile); if (extension == "m3d" -#ifdef M3D_ASCII || extension == "a3d" -#endif ) return true; else if (!extension.length() || checkSig) { @@ -136,13 +131,11 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c */ std::unique_ptr pStream(pIOHandler->Open(pFile, "rb")); unsigned char data[4]; - if (4 != pStream->Read(data, 1, 4)) { + if (!pStream || 4 != pStream->Read(data, 1, 4)) { return false; } return !memcmp(data, "3DMO", 4) /* bin */ -#ifdef M3D_ASCII || !memcmp(data, "3dmo", 4) /* ASCII */ -#endif ; } return false; @@ -175,12 +168,10 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys if (!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) { throw DeadlyImportError("Bad binary header in file ", file, "."); } -#ifdef M3D_ASCII // make sure there's a terminator zero character, as input must be ASCIIZ if (!memcmp(buffer.data(), "3dmo", 4)) { buffer.push_back(0); } -#endif // Get the path for external assets std::string folderName("./"); @@ -193,7 +184,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys } //DefaultLogger::create("/dev/stderr", Logger::VERBOSE); - ASSIMP_LOG_DEBUG_F("M3D: loading ", file); + ASSIMP_LOG_DEBUG("M3D: loading ", file); // let the C SDK do the hard work for us M3DWrapper m3d(pIOHandler, buffer); @@ -209,7 +200,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys pScene->mRootNode->mNumChildren = 0; mScene = pScene; - ASSIMP_LOG_DEBUG("M3D: root node " + m3d.Name()); + ASSIMP_LOG_DEBUG("M3D: root node ", m3d.Name()); // now we just have to fill up the Assimp structures in pScene importMaterials(m3d); @@ -239,7 +230,7 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d) { mScene->mNumMaterials = m3d->nummaterial + 1; mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials]; - ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials); + ASSIMP_LOG_DEBUG("M3D: importMaterials ", mScene->mNumMaterials); // add a default material as first aiMaterial *mat = new aiMaterial; @@ -334,7 +325,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { ai_assert(m3d); mScene->mNumTextures = m3d->numtexture; - ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures); + ASSIMP_LOG_DEBUG("M3D: importTextures ", mScene->mNumTextures); if (!m3d->numtexture || !m3d->texture) { return; @@ -389,7 +380,7 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) { // individually. In assimp there're per mesh vertex and UV lists, and they must be // indexed simultaneously. void M3DImporter::importMeshes(const M3DWrapper &m3d) { - ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface); + ASSIMP_LOG_DEBUG("M3D: importMeshes ", m3d->numface); if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) { return; @@ -508,7 +499,7 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo ai_assert(mScene != nullptr); ai_assert(m3d); - ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); + ASSIMP_LOG_DEBUG("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid); if (!m3d->numbone || !m3d->bone) { return; @@ -549,7 +540,7 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) { mScene->mNumAnimations = m3d->numaction; - ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations); + ASSIMP_LOG_DEBUG("M3D: importAnimations ", mScene->mNumAnimations); if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) { return; @@ -712,7 +703,7 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector ai_assert(vertexids != nullptr); ai_assert(m3d); - ASSIMP_LOG_DEBUG_F("M3D: populateMesh numvertices ", vertices->size(), " numfaces ", faces->size(), + ASSIMP_LOG_DEBUG("M3D: populateMesh numvertices ", vertices->size(), " numfaces ", faces->size(), " numnormals ", normals->size(), " numtexcoord ", texcoords->size(), " numbones ", m3d->numbone); if (vertices->size() && faces->size()) { diff --git a/code/AssetLib/M3D/M3DWrapper.h b/code/AssetLib/M3D/M3DWrapper.h index 5c370e607..782e908d2 100644 --- a/code/AssetLib/M3D/M3DWrapper.h +++ b/code/AssetLib/M3D/M3DWrapper.h @@ -54,7 +54,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // Assimp specific M3D configuration. Comment out these defines to remove functionality //#define ASSIMP_USE_M3D_READFILECB -//#define M3D_ASCII #include "m3d.h" diff --git a/code/AssetLib/M3D/m3d.h b/code/AssetLib/M3D/m3d.h index dfc30aec3..68265959e 100644 --- a/code/AssetLib/M3D/m3d.h +++ b/code/AssetLib/M3D/m3d.h @@ -231,14 +231,9 @@ enum { typedef struct { uint8_t format; uint8_t id; -#ifdef M3D_ASCII #define M3D_PROPERTYDEF(f, i, n) \ { (f), (i), (char *)(n) } char *key; -#else -#define M3D_PROPERTYDEF(f, i, n) \ - { (f), (i) } -#endif } m3dpd_t; /* material property types */ @@ -376,18 +371,11 @@ enum { #define M3D_CMDMAXARG 8 /* if you increase this, add more arguments to the macro below */ typedef struct { -#ifdef M3D_ASCII #define M3D_CMDDEF(t, n, p, a, b, c, d, e, f, g, h) \ { \ (char *)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } \ } char *key; -#else -#define M3D_CMDDEF(t, n, p, a, b, c, d, e, f, g, h) \ - { \ - (p), { (a), (b), (c), (d), (e), (f), (g), (h) } \ - } -#endif uint8_t p; uint8_t a[M3D_CMDMAXARG]; } m3dcd_t; @@ -2059,15 +2047,13 @@ unsigned char *_m3dstbi_zlib_compress(unsigned char *data, int data_len, int *ou #define M3D_CHUNKMAGIC(m, a, b, c, d) ((m)[0] == (a) && (m)[1] == (b) && (m)[2] == (c) && (m)[3] == (d)) -#ifdef M3D_ASCII #include /* sprintf and strtod cares about number locale */ #include /* get sprintf */ -#endif #ifdef M3D_PROFILING #include #endif -#if !defined(M3D_NOIMPORTER) && defined(M3D_ASCII) +#if !defined(M3D_NOIMPORTER) /* helper functions for the ASCII parser */ static char *_m3d_findarg(char *s) { while (s && *s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n') @@ -2118,7 +2104,7 @@ static char *_m3d_getfloat(char *s, M3D_FLOAT *ret) { return _m3d_findarg(e); } #endif -#if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_ASCII) || defined(M3D_EXPORTER)) +#if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER)) /* helper function to create safe strings */ char *_m3d_safestr(char *in, int morelines) { char *out, *o, *i = in; @@ -2426,21 +2412,17 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d #ifndef M3D_NOWEIGHTS m3ds_t *sk; #endif -#ifdef M3D_ASCII m3ds_t s; M3D_INDEX bi[M3D_BONEMAXLEVEL + 1], level; const char *ol; char *ptr, *pe, *fn; -#endif #ifdef M3D_PROFILING struct timeval tv0, tv1, tvd; gettimeofday(&tv0, NULL); #endif if (!data || (!M3D_CHUNKMAGIC(data, '3', 'D', 'M', 'O') -#ifdef M3D_ASCII && !M3D_CHUNKMAGIC(data, '3', 'd', 'm', 'o') -#endif )) return NULL; model = (m3d_t *)M3D_MALLOC(sizeof(m3d_t)); @@ -2457,7 +2439,6 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d model->texture = mtllib->texture; model->flags |= M3D_FLG_MTLLIB; } -#ifdef M3D_ASCII /* ASCII variant? */ if (M3D_CHUNKMAGIC(data, '3', 'd', 'm', 'o')) { model->errcode = M3D_ERR_BADFILE; @@ -3034,7 +3015,6 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d setlocale(LC_NUMERIC, ol); goto postprocess; } -#endif /* Binary variant */ if (!M3D_CHUNKMAGIC(data + 8, 'H', 'E', 'A', 'D')) { buff = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char *)data + 8, ((m3dchunk_t *)data)->length - 8, @@ -3698,9 +3678,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d } } /* calculate normals, normalize skin weights, create bone/vertex cross-references and calculate transform matrices */ -#ifdef M3D_ASCII postprocess: -#endif if (model) { M3D_LOG("Post-process"); #ifdef M3D_PROFILING @@ -3989,7 +3967,6 @@ void m3d_free(m3d_t *model) { unsigned int i, j; if (!model) return; -#ifdef M3D_ASCII /* if model imported from ASCII, we have to free all strings as well */ if (model->flags & M3D_FLG_FREESTR) { if (model->name) M3D_FREE(model->name); @@ -4047,7 +4024,6 @@ void m3d_free(m3d_t *model) { if (model->preview.data) M3D_FREE(model->preview.data); } -#endif if (model->flags & M3D_FLG_FREERAW) M3D_FREE(model->raw); if (model->tmap) M3D_FREE(model->tmap); @@ -4315,7 +4291,6 @@ static void _m3d_round(int quality, m3dv_t *src, m3dv_t *dst) { if (dst->w == (M3D_FLOAT)-0.0) dst->w = (M3D_FLOAT)0.0; } -#ifdef M3D_ASCII /* add a bone to ascii output */ static char *_m3d_prtbone(char *ptr, m3db_t *bone, M3D_INDEX numbone, M3D_INDEX parent, uint32_t level, M3D_INDEX *vrtxidx) { uint32_t i, j; @@ -4334,16 +4309,13 @@ static char *_m3d_prtbone(char *ptr, m3db_t *bone, M3D_INDEX numbone, M3D_INDEX } return ptr; } -#endif /** * Function to encode an in-memory model into on storage Model 3D format */ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size) { -#ifdef M3D_ASCII const char *ol; char *ptr; -#endif char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fc_s, hi_s, fi_s; char *sn = NULL, *sl = NULL, *sa = NULL, *sd = NULL; unsigned char *out = NULL, *z = NULL, weights[M3D_NUMBONE], *norm = NULL; @@ -4369,9 +4341,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size return NULL; } model->errcode = M3D_SUCCESS; -#ifdef M3D_ASCII if (flags & M3D_EXP_ASCII) quality = M3D_EXP_DOUBLE; -#endif vrtxidx = (M3D_INDEX *)M3D_MALLOC(model->numvertex * sizeof(M3D_INDEX)); if (!vrtxidx) goto memerr; memset(vrtxidx, 255, model->numvertex * sizeof(M3D_INDEX)); @@ -4800,7 +4770,6 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size } M3D_LOG("Serializing model"); -#ifdef M3D_ASCII if (flags & M3D_EXP_ASCII) { /* use CRLF to make model creators on Win happy... */ sd = _m3d_safestr(model->desc, 1); @@ -5073,7 +5042,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size ptr += sprintf(ptr, "\r\n"); } /* mathematical shapes face */ - if (model->numshape !(flags & M3D_EXP_NOFACE)) { + if (model->numshape && (!(flags & M3D_EXP_NOFACE))) { for (j = 0; j < model->numshape; j++) { sn = _m3d_safestr(model->shape[j].name, 0); if (!sn) { @@ -5287,7 +5256,6 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size if (!out) goto memerr; out[len] = 0; } else -#endif { /* stricly only use LF (newline) in binary */ sd = _m3d_safestr(model->desc, 3); diff --git a/code/AssetLib/MD2/MD2Loader.cpp b/code/AssetLib/MD2/MD2Loader.cpp index 9ccbcdfca..b7bf24ef7 100644 --- a/code/AssetLib/MD2/MD2Loader.cpp +++ b/code/AssetLib/MD2/MD2Loader.cpp @@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include @@ -148,46 +149,39 @@ void MD2Importer::ValidateHeader( ) if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE && m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE) { - char szBuffer[5]; - szBuffer[0] = ((char*)&m_pcHeader->magic)[0]; - szBuffer[1] = ((char*)&m_pcHeader->magic)[1]; - szBuffer[2] = ((char*)&m_pcHeader->magic)[2]; - szBuffer[3] = ((char*)&m_pcHeader->magic)[3]; - szBuffer[4] = '\0'; - - throw DeadlyImportError("Invalid MD2 magic word: should be IDP2, the " - "magic word found is " + std::string(szBuffer)); + throw DeadlyImportError("Invalid MD2 magic word: expected IDP2, found ", + ai_str_toprintable((char *)&m_pcHeader->magic, 4)); } // check file format version if (m_pcHeader->version != 8) - ASSIMP_LOG_WARN( "Unsupported md2 file version. Continuing happily ..."); + ASSIMP_LOG_WARN( "Unsupported MD2 file version. Continuing happily ..."); // check some values whether they are valid if (0 == m_pcHeader->numFrames) - throw DeadlyImportError( "Invalid md2 file: NUM_FRAMES is 0"); + throw DeadlyImportError( "Invalid MD2 file: NUM_FRAMES is 0"); if (m_pcHeader->offsetEnd > (uint32_t)fileSize) - throw DeadlyImportError( "Invalid md2 file: File is too small"); + throw DeadlyImportError( "Invalid MD2 file: File is too small"); if (m_pcHeader->numSkins > AI_MAX_ALLOC(MD2::Skin)) { - throw DeadlyImportError("Invalid MD2 header: too many skins, would overflow"); + throw DeadlyImportError("Invalid MD2 header: Too many skins, would overflow"); } if (m_pcHeader->numVertices > AI_MAX_ALLOC(MD2::Vertex)) { - throw DeadlyImportError("Invalid MD2 header: too many vertices, would overflow"); + throw DeadlyImportError("Invalid MD2 header: Too many vertices, would overflow"); } if (m_pcHeader->numTexCoords > AI_MAX_ALLOC(MD2::TexCoord)) { - throw DeadlyImportError("Invalid MD2 header: too many texcoords, would overflow"); + throw DeadlyImportError("Invalid MD2 header: Too many texcoords, would overflow"); } if (m_pcHeader->numTriangles > AI_MAX_ALLOC(MD2::Triangle)) { - throw DeadlyImportError("Invalid MD2 header: too many triangles, would overflow"); + throw DeadlyImportError("Invalid MD2 header: Too many triangles, would overflow"); } if (m_pcHeader->numFrames > AI_MAX_ALLOC(MD2::Frame)) { - throw DeadlyImportError("Invalid MD2 header: too many frames, would overflow"); + throw DeadlyImportError("Invalid MD2 header: Too many frames, would overflow"); } // -1 because Frame already contains one @@ -199,7 +193,7 @@ void MD2Importer::ValidateHeader( ) m_pcHeader->offsetFrames + m_pcHeader->numFrames * frameSize >= fileSize || m_pcHeader->offsetEnd > fileSize) { - throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file"); + throw DeadlyImportError("Invalid MD2 header: Some offsets are outside the file"); } if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS) @@ -210,7 +204,7 @@ void MD2Importer::ValidateHeader( ) ASSIMP_LOG_WARN("The model contains more vertices than Quake 2 supports"); if (m_pcHeader->numFrames <= configFrameID ) - throw DeadlyImportError("The requested frame is not existing the file"); + throw DeadlyImportError("MD2: The requested frame (", configFrameID, ") does not exist in the file"); } // ------------------------------------------------------------------------------------------------ @@ -433,10 +427,6 @@ void MD2Importer::InternReadFile( const std::string& pFile, aiVector3D& vNormal = pcMesh->mNormals[iCurrent]; LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal); - // flip z and y to become right-handed - std::swap((float&)vNormal.z,(float&)vNormal.y); - std::swap((float&)vec.z,(float&)vec.y); - if (m_pcHeader->numTexCoords) { // validate texture coordinates iIndex = pcTriangles[i].textureIndices[c]; @@ -454,7 +444,15 @@ void MD2Importer::InternReadFile( const std::string& pFile, } pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent; } + // flip the face order + std::swap( pScene->mMeshes[0]->mFaces[i].mIndices[0], pScene->mMeshes[0]->mFaces[i].mIndices[2] ); } + // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system + pScene->mRootNode->mTransformation = aiMatrix4x4( + 1.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, -1.f, 0.f, 0.f, + 0.f, 0.f, 0.f, 1.f); } #endif // !! ASSIMP_BUILD_NO_MD2_IMPORTER diff --git a/code/AssetLib/MD3/MD3Loader.cpp b/code/AssetLib/MD3/MD3Loader.cpp index e27079766..abaabe47f 100644 --- a/code/AssetLib/MD3/MD3Loader.cpp +++ b/code/AssetLib/MD3/MD3Loader.cpp @@ -101,7 +101,7 @@ Q3Shader::BlendFunc StringToBlendFunc(const std::string &m) { if (m == "GL_ONE_MINUS_DST_COLOR") { return Q3Shader::BLEND_GL_ONE_MINUS_DST_COLOR; } - ASSIMP_LOG_ERROR("Q3Shader: Unknown blend function: " + m); + ASSIMP_LOG_ERROR("Q3Shader: Unknown blend function: ", m); return Q3Shader::BLEND_NONE; } @@ -112,7 +112,7 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem * if (!file.get()) return false; // if we can't access the file, don't worry and return - ASSIMP_LOG_INFO_F("Loading Quake3 shader file ", pFile); + ASSIMP_LOG_INFO("Loading Quake3 shader file ", pFile); // read file in memory const size_t s = file->FileSize(); @@ -196,11 +196,11 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem * // 'cull' specifies culling behaviour for the model else if (TokenMatchI(buff, "cull", 4)) { SkipSpaces(&buff); - if (!ASSIMP_strincmp(buff, "back", 4)) { + if (!ASSIMP_strincmp(buff, "back", 4)) { // render face's backside, does not function in Q3 engine (bug) curData->cull = Q3Shader::CULL_CCW; - } else if (!ASSIMP_strincmp(buff, "front", 5)) { + } else if (!ASSIMP_strincmp(buff, "front", 5)) { // is not valid keyword in Q3, but occurs in shaders curData->cull = Q3Shader::CULL_CW; - } else if (!ASSIMP_strincmp(buff, "none", 4) || !ASSIMP_strincmp(buff, "disable", 7)) { + } else if (!ASSIMP_strincmp(buff, "none", 4) || !ASSIMP_strincmp(buff, "twosided", 8) || !ASSIMP_strincmp(buff, "disable", 7)) { curData->cull = Q3Shader::CULL_NONE; } else { ASSIMP_LOG_ERROR("Q3Shader: Unrecognized cull mode"); @@ -226,7 +226,7 @@ bool Q3Shader::LoadSkin(SkinData &fill, const std::string &pFile, IOSystem *io) if (!file.get()) return false; // if we can't access the file, don't worry and return - ASSIMP_LOG_INFO("Loading Quake3 skin file " + pFile); + ASSIMP_LOG_INFO("Loading Quake3 skin file ", pFile); // read file in memory const size_t s = file->FileSize(); @@ -450,6 +450,9 @@ void MD3Importer::SetupProperties(const Importer *pImp) { // AI_CONFIG_IMPORT_MD3_SKIN_NAME configSkinFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SKIN_NAME, "default")); + // AI_CONFIG_IMPORT_MD3_LOAD_SHADERS + configLoadShaders = (pImp->GetPropertyBool(AI_CONFIG_IMPORT_MD3_LOAD_SHADERS, true)); + // AI_CONFIG_IMPORT_MD3_SHADER_SRC configShaderFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SHADER_SRC, "")); @@ -483,8 +486,9 @@ void MD3Importer::ReadShader(Q3Shader::ShaderData &fill) const { // If no specific dir or file is given, use our default search behaviour if (!configShaderFile.length()) { - if (!Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + model_file + ".shader", mIOHandler)) { - Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + filename + ".shader", mIOHandler); + const char sep = mIOHandler->getOsSeparator(); + if (!Q3Shader::LoadShader(fill, path + ".." + sep + ".." + sep + ".." + sep + "scripts" + sep + model_file + ".shader", mIOHandler)) { + Q3Shader::LoadShader(fill, path + ".." + sep + ".." + sep + ".." + sep + "scripts" + sep + filename + ".shader", mIOHandler); } } else { // If the given string specifies a file, load this file. @@ -702,7 +706,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy } filename = mFile.substr(s), path = mFile.substr(0, s); for (std::string::iterator it = filename.begin(); it != filename.end(); ++it) { - *it = static_cast(tolower(*it)); + *it = static_cast(tolower(static_cast(*it))); } // Load multi-part model file, if necessary @@ -780,7 +784,9 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy // And check whether we can locate a shader file for this model Q3Shader::ShaderData shaders; - ReadShader(shaders); + if (configLoadShaders){ + ReadShader(shaders); + } // Adjust all texture paths in the shader const char *header_name = pcHeader->NAME; @@ -851,7 +857,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy if (it != skins.textures.end()) { texture_name = &*(_texture_name = (*it).second).begin(); - ASSIMP_LOG_VERBOSE_DEBUG_F("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME); + ASSIMP_LOG_VERBOSE_DEBUG("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME); (*it).resolved = true; // mark entry as resolved } @@ -862,7 +868,12 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy std::string convertedPath; if (texture_name) { - ConvertPath(texture_name, header_name, convertedPath); + if (configLoadShaders){ + ConvertPath(texture_name, header_name, convertedPath); + } + else{ + convertedPath = texture_name; + } } const Q3Shader::ShaderDataBlock *shader = nullptr; @@ -880,9 +891,9 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy if (dit != shaders.blocks.end()) { // We made it! shader = &*dit; - ASSIMP_LOG_INFO("Found shader record for " + without_ext); + ASSIMP_LOG_INFO("Found shader record for ", without_ext); } else { - ASSIMP_LOG_WARN("Unable to find shader record for " + without_ext); + ASSIMP_LOG_WARN("Unable to find shader record for ", without_ext); } } @@ -985,8 +996,8 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[index].U; pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[index].V; } - // Flip face order if necessary - if (!shader || shader->cull == Q3Shader::CULL_CW) { + // Flip face order normally, unless shader is backfacing + if (!(shader && shader->cull == Q3Shader::CULL_CCW)) { std::swap(pcMesh->mFaces[i].mIndices[2], pcMesh->mFaces[i].mIndices[1]); } ++pcTriangles; @@ -1000,7 +1011,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy if (!DefaultLogger::isNullLogger()) { for (std::list::const_iterator it = skins.textures.begin(); it != skins.textures.end(); ++it) { if (!(*it).resolved) { - ASSIMP_LOG_ERROR_F("MD3: Failed to match skin ", (*it).first, " to surface ", (*it).second); + ASSIMP_LOG_ERROR("MD3: Failed to match skin ", (*it).first, " to surface ", (*it).second); } } } diff --git a/code/AssetLib/MD3/MD3Loader.h b/code/AssetLib/MD3/MD3Loader.h index d34df2d77..1a4e5982c 100644 --- a/code/AssetLib/MD3/MD3Loader.h +++ b/code/AssetLib/MD3/MD3Loader.h @@ -297,6 +297,9 @@ protected: /** Configuration option: name of skin file to be read */ std::string configSkinFile; + /** Configuration option: whether to load shaders */ + bool configLoadShaders; + /** Configuration option: name or path of shader */ std::string configShaderFile; diff --git a/code/AssetLib/MD5/MD5Loader.cpp b/code/AssetLib/MD5/MD5Loader.cpp index b99638cd2..0d9c77b71 100644 --- a/code/AssetLib/MD5/MD5Loader.cpp +++ b/code/AssetLib/MD5/MD5Loader.cpp @@ -345,7 +345,7 @@ void MD5Importer::LoadMD5MeshFile() { // Check whether we can read from the file if (file.get() == nullptr || !file->FileSize()) { - ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + filename); + ASSIMP_LOG_WARN("Failed to access MD5MESH file: ", filename); return; } mHadMD5Mesh = true; @@ -567,7 +567,7 @@ void MD5Importer::LoadMD5AnimFile() { // Check whether we can read from the file if (!file.get() || !file->FileSize()) { - ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile); + ASSIMP_LOG_WARN("Failed to read MD5ANIM file: ", pFile); return; } diff --git a/code/AssetLib/MDC/MDCLoader.cpp b/code/AssetLib/MDC/MDCLoader.cpp index 17a349768..8f089bbd8 100644 --- a/code/AssetLib/MDC/MDCLoader.cpp +++ b/code/AssetLib/MDC/MDCLoader.cpp @@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include @@ -143,16 +144,8 @@ void MDCImporter::ValidateHeader() { if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE && pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE) { - char szBuffer[5]; - szBuffer[0] = ((char *)&pcHeader->ulIdent)[0]; - szBuffer[1] = ((char *)&pcHeader->ulIdent)[1]; - szBuffer[2] = ((char *)&pcHeader->ulIdent)[2]; - szBuffer[3] = ((char *)&pcHeader->ulIdent)[3]; - szBuffer[4] = '\0'; - - throw DeadlyImportError("Invalid MDC magic word: should be IDPC, the " - "magic word found is " + - std::string(szBuffer)); + throw DeadlyImportError("Invalid MDC magic word: expected IDPC, found ", + ai_str_toprintable((char *)&pcHeader->ulIdent, 4)); } if (pcHeader->ulVersion != AI_MDC_VERSION) { @@ -465,6 +458,13 @@ void MDCImporter::InternReadFile( pcMat->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0)); } } + + // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system + pScene->mRootNode->mTransformation = aiMatrix4x4( + 1.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + 0.f, -1.f, 0.f, 0.f, + 0.f, 0.f, 0.f, 1.f); } #endif // !! ASSIMP_BUILD_NO_MDC_IMPORTER diff --git a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp index eee9ed346..e6576b344 100644 --- a/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp +++ b/code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp @@ -869,7 +869,7 @@ void HL1MDLLoader::read_meshes() { scene_mesh->mNormals[v] = bind_pose_normals[pTrivert->normindex]; scene_mesh->mTextureCoords[0][v] = aiVector3D( pTrivert->s * texcoords_s_scale, - pTrivert->t * texcoords_t_scale, 0); + pTrivert->t * -texcoords_t_scale, 0); } // Add face and indices. @@ -880,9 +880,9 @@ void HL1MDLLoader::read_meshes() { aiFace *face = &scene_mesh->mFaces[f]; face->mNumIndices = 3; face->mIndices = new unsigned int[3]; - face->mIndices[0] = mesh_faces[f].v0; + face->mIndices[0] = mesh_faces[f].v2; face->mIndices[1] = mesh_faces[f].v1; - face->mIndices[2] = mesh_faces[f].v2; + face->mIndices[2] = mesh_faces[f].v0; } // Add mesh bones. @@ -1343,7 +1343,7 @@ bool HL1MDLLoader::get_num_blend_controllers(const int num_blend_animations, int return true; default: num_blend_controllers = 0; - ASSIMP_LOG_WARN(MDL_HALFLIFE_LOG_HEADER "Unsupported number of blend animations (" + std::to_string(num_blend_animations) + ")"); + ASSIMP_LOG_WARN(MDL_HALFLIFE_LOG_HEADER "Unsupported number of blend animations (", num_blend_animations, ")"); return false; } } diff --git a/code/AssetLib/MDL/MDLLoader.cpp b/code/AssetLib/MDL/MDLLoader.cpp index a4286a716..51d76e740 100644 --- a/code/AssetLib/MDL/MDLLoader.cpp +++ b/code/AssetLib/MDL/MDLLoader.cpp @@ -199,6 +199,7 @@ void MDLImporter::InternReadFile(const std::string &pFile, const uint32_t iMagicWord = *((uint32_t *)mBuffer); // Determine the file subtype and call the appropriate member function + bool is_half_life = false; // Original Quake1 format if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) { @@ -240,6 +241,7 @@ void MDLImporter::InternReadFile(const std::string &pFile, else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord) { iGSFileVersion = 0; + is_half_life = true; HalfLife::HalfLifeMDLBaseHeader *pHeader = (HalfLife::HalfLifeMDLBaseHeader *)mBuffer; if (pHeader->version == AI_MDL_HL1_VERSION) { @@ -252,12 +254,22 @@ void MDLImporter::InternReadFile(const std::string &pFile, } else { // print the magic word to the log file throw DeadlyImportError("Unknown MDL subformat ", pFile, - ". Magic word (", std::string((char *)&iMagicWord, 4), ") is not known"); + ". Magic word (", ai_str_toprintable((const char *)&iMagicWord, sizeof(iMagicWord)), ") is not known"); } - // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system - pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, - 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); + if (is_half_life){ + // Now rotate the whole scene 90 degrees around the z and x axes to convert to internal coordinate system + pScene->mRootNode->mTransformation = aiMatrix4x4( + 0.f, -1.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, + -1.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 0.f, 1.f); + } + else { + // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system + pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, + 0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); + } DeleteBufferAndCleanup(); } catch (...) { diff --git a/code/AssetLib/MMD/MMDPmxParser.cpp b/code/AssetLib/MMD/MMDPmxParser.cpp index cb4787efd..d57dc169a 100644 --- a/code/AssetLib/MMD/MMDPmxParser.cpp +++ b/code/AssetLib/MMD/MMDPmxParser.cpp @@ -478,8 +478,7 @@ namespace pmx void PmxSoftBody::Read(std::istream * /*stream*/, PmxSetting * /*setting*/) { - std::cerr << "Not Implemented Exception" << std::endl; - throw DeadlyImportError("MMD: Not Implemented Exception"); + throw DeadlyImportError("MMD: Soft Body support is not implemented."); } void PmxModel::Init() @@ -516,15 +515,13 @@ namespace pmx char magic[4]; stream->read((char*) magic, sizeof(char) * 4); if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20) - { - std::cerr << "invalid magic number." << std::endl; - throw DeadlyImportError("MMD: invalid magic number."); + { + throw DeadlyImportError("MMD: Invalid magic number."); } stream->read((char*) &version, sizeof(float)); if (version != 2.0f && version != 2.1f) { - std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl; - throw DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but ", ai_to_string(version)); + throw DeadlyImportError("MMD: Unsupported version (must be 2.0 or 2.1): ", ai_to_string(version)); } this->setting.Read(stream); diff --git a/code/AssetLib/MS3D/MS3DLoader.cpp b/code/AssetLib/MS3D/MS3DLoader.cpp index 192bcbe41..e4057a43a 100644 --- a/code/AssetLib/MS3D/MS3DLoader.cpp +++ b/code/AssetLib/MS3D/MS3DLoader.cpp @@ -215,7 +215,12 @@ void MS3DImporter :: CollectChildJoints(const std::vector& joints, ai void MS3DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { - StreamReaderLE stream(pIOHandler->Open(pFile,"rb")); + + auto file = pIOHandler->Open(pFile, "rb"); + if (!file) + throw DeadlyImportError("MS3D: Could not open ", pFile); + + StreamReaderLE stream(file); // CanRead() should have done this already char head[10]; @@ -382,7 +387,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile, } const std::string& s = std::string(reinterpret_cast(stream.GetPtr()),len); - ASSIMP_LOG_DEBUG_F("MS3D: Model comment: ", s); + ASSIMP_LOG_DEBUG("MS3D: Model comment: ", s); } if(stream.GetRemainingSize() > 4 && inrange((stream >> subversion,subversion),1u,3u)) { diff --git a/code/AssetLib/NDO/NDOLoader.cpp b/code/AssetLib/NDO/NDOLoader.cpp index 77fe3e36c..0abc09dc8 100644 --- a/code/AssetLib/NDO/NDOLoader.cpp +++ b/code/AssetLib/NDO/NDOLoader.cpp @@ -116,7 +116,13 @@ void NDOImporter::SetupProperties(const Importer* /*pImp*/) void NDOImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { - StreamReaderBE reader(pIOHandler->Open( pFile, "rb")); + + auto file = pIOHandler->Open( pFile, "rb"); + if (!file) { + throw DeadlyImportError("Nendo: Could not open ", pFile); + } + + StreamReaderBE reader(file); // first 9 bytes are nendo file format ("nendo 1.n") const char* head = (const char*)reader.GetPtr(); @@ -141,7 +147,7 @@ void NDOImporter::InternReadFile( const std::string& pFile, ASSIMP_LOG_INFO("NDO file format is 1.2"); } else { - ASSIMP_LOG_WARN_F( "Unrecognized nendo file format version, continuing happily ... :", (head+6)); + ASSIMP_LOG_WARN( "Unrecognized nendo file format version, continuing happily ... :", (head+6)); } reader.IncPtr(2); /* skip flags */ diff --git a/code/AssetLib/NFF/NFFLoader.cpp b/code/AssetLib/NFF/NFFLoader.cpp index 11cce0990..15f46b5e6 100644 --- a/code/AssetLib/NFF/NFFLoader.cpp +++ b/code/AssetLib/NFF/NFFLoader.cpp @@ -132,7 +132,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector &output, // Check whether we can read from the file if (!file.get()) { - ASSIMP_LOG_ERROR("NFF2: Unable to open material library " + path + "."); + ASSIMP_LOG_ERROR("NFF2: Unable to open material library ", path, "."); return; } @@ -150,7 +150,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector &output, // The file should start with the magic sequence "mat" if (!TokenMatch(buffer, "mat", 3)) { - ASSIMP_LOG_ERROR_F("NFF2: Not a valid material library ", path, "."); + ASSIMP_LOG_ERROR("NFF2: Not a valid material library ", path, "."); return; } @@ -164,7 +164,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector &output, // 'version' defines the version of the file format if (TokenMatch(sz, "version", 7)) { - ASSIMP_LOG_INFO_F("NFF (Sense8) material library file format: ", std::string(sz)); + ASSIMP_LOG_INFO("NFF (Sense8) material library file format: ", std::string(sz)); } // 'matdef' starts a new material in the file else if (TokenMatch(sz, "matdef", 6)) { @@ -177,7 +177,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector &output, // check whether we have an active material at the moment if (!IsLineEnd(*sz)) { if (!curShader) { - ASSIMP_LOG_ERROR_F("NFF2 material library: Found element ", sz, "but there is no active material"); + ASSIMP_LOG_ERROR("NFF2 material library: Found element ", sz, "but there is no active material"); continue; } } else @@ -277,7 +277,7 @@ void NFFImporter::InternReadFile(const std::string &pFile, while (GetNextLine(buffer, line)) { SkipSpaces(line, &sz); if (TokenMatch(sz, "version", 7)) { - ASSIMP_LOG_INFO_F("NFF (Sense8) file format: ", sz); + ASSIMP_LOG_INFO("NFF (Sense8) file format: ", sz); } else if (TokenMatch(sz, "viewpos", 7)) { AI_NFF_PARSE_TRIPLE(camPos); hasCam = true; diff --git a/code/AssetLib/Obj/ObjFileParser.cpp b/code/AssetLib/Obj/ObjFileParser.cpp index a8039ae23..767805c10 100644 --- a/code/AssetLib/Obj/ObjFileParser.cpp +++ b/code/AssetLib/Obj/ObjFileParser.cpp @@ -556,7 +556,7 @@ void ObjFileParser::getMaterialDesc() { // This may be the case if the material library is missing. We don't want to lose all // materials if that happens, so create a new named material instead of discarding it // completely. - ASSIMP_LOG_ERROR("OBJ: failed to locate material " + strName + ", creating new material"); + ASSIMP_LOG_ERROR("OBJ: failed to locate material ", strName, ", creating new material"); m_pModel->m_pCurrentMaterial = new ObjFile::Material(); m_pModel->m_pCurrentMaterial->MaterialName.Set(strName); m_pModel->m_MaterialLib.push_back(strName); @@ -620,12 +620,12 @@ void ObjFileParser::getMaterialLib() { IOStream *pFile = m_pIO->Open(absName); if (nullptr == pFile) { - ASSIMP_LOG_ERROR("OBJ: Unable to locate material file " + strMatName); + ASSIMP_LOG_ERROR("OBJ: Unable to locate material file ", strMatName); std::string strMatFallbackName = m_originalObjFileName.substr(0, m_originalObjFileName.length() - 3) + "mtl"; - ASSIMP_LOG_INFO("OBJ: Opening fallback material file " + strMatFallbackName); + ASSIMP_LOG_INFO("OBJ: Opening fallback material file ", strMatFallbackName); pFile = m_pIO->Open(strMatFallbackName); if (!pFile) { - ASSIMP_LOG_ERROR("OBJ: Unable to locate fallback material file " + strMatFallbackName); + ASSIMP_LOG_ERROR("OBJ: Unable to locate fallback material file ", strMatFallbackName); m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); return; } @@ -660,7 +660,7 @@ void ObjFileParser::getNewMaterial() { std::map::iterator it = m_pModel->m_MaterialMap.find(strMat); if (it == m_pModel->m_MaterialMap.end()) { // Show a warning, if material was not found - ASSIMP_LOG_WARN("OBJ: Unsupported material requested: " + strMat); + ASSIMP_LOG_WARN("OBJ: Unsupported material requested: ", strMat); m_pModel->m_pCurrentMaterial = m_pModel->m_pDefaultMaterial; } else { // Set new material diff --git a/code/AssetLib/Ogre/OgreBinarySerializer.cpp b/code/AssetLib/Ogre/OgreBinarySerializer.cpp index 0fc18feb9..fc975a5cc 100644 --- a/code/AssetLib/Ogre/OgreBinarySerializer.cpp +++ b/code/AssetLib/Ogre/OgreBinarySerializer.cpp @@ -55,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. namespace Assimp { namespace Ogre { -const std::string MESH_VERSION_1_8 = "[MeshSerializer_v1.8]"; -const std::string SKELETON_VERSION_1_8 = "[Serializer_v1.80]"; -const std::string SKELETON_VERSION_1_1 = "[Serializer_v1.10]"; +static constexpr auto MESH_VERSION_1_8 = "[MeshSerializer_v1.8]"; +static constexpr auto SKELETON_VERSION_1_8 = "[Serializer_v1.80]"; +static constexpr auto SKELETON_VERSION_1_1 = "[Serializer_v1.10]"; const unsigned short HEADER_CHUNK_ID = 0x1000; @@ -155,7 +155,7 @@ uint16_t OgreBinarySerializer::ReadHeader(bool readLen) { #if (OGRE_BINARY_SERIALIZER_DEBUG == 1) if (id != HEADER_CHUNK_ID) { - ASSIMP_LOG_DEBUG(Formatter::format() << (assetMode == AM_Mesh ? MeshHeaderToString(static_cast(id)) : SkeletonHeaderToString(static_cast(id)))); + ASSIMP_LOG_DEBUG((assetMode == AM_Mesh ? MeshHeaderToString(static_cast(id)) : SkeletonHeaderToString(static_cast(id)))); } #endif @@ -168,7 +168,7 @@ void OgreBinarySerializer::RollbackHeader() { void OgreBinarySerializer::SkipBytes(size_t numBytes) { #if (OGRE_BINARY_SERIALIZER_DEBUG == 1) - ASSIMP_LOG_VERBOSE_DEBUG_F("Skipping ", numBytes, " bytes"); + ASSIMP_LOG_VERBOSE_DEBUG("Skipping ", numBytes, " bytes"); #endif m_reader->IncPtr(numBytes); @@ -208,7 +208,7 @@ void OgreBinarySerializer::ReadMesh(Mesh *mesh) { mesh->hasSkeletalAnimations = Read(); ASSIMP_LOG_VERBOSE_DEBUG("Reading Mesh"); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Skeletal animations: ", mesh->hasSkeletalAnimations ? "true" : "false"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Skeletal animations: ", mesh->hasSkeletalAnimations ? "true" : "false"); if (!AtEnd()) { uint16_t id = ReadHeader(); @@ -364,9 +364,9 @@ void OgreBinarySerializer::ReadSubMesh(Mesh *mesh) { submesh->indexData->faceCount = static_cast(submesh->indexData->count / 3); submesh->indexData->is32bit = Read(); - ASSIMP_LOG_VERBOSE_DEBUG_F("Reading SubMesh ", mesh->subMeshes.size()); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Material: '", submesh->materialRef, "'"); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Uses shared geometry: ", submesh->usesSharedVertexData ? "true" : "false"); + ASSIMP_LOG_VERBOSE_DEBUG("Reading SubMesh ", mesh->subMeshes.size()); + ASSIMP_LOG_VERBOSE_DEBUG(" - Material: '", submesh->materialRef, "'"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Uses shared geometry: ", submesh->usesSharedVertexData ? "true" : "false"); // Index buffer if (submesh->indexData->count > 0) { @@ -374,7 +374,7 @@ void OgreBinarySerializer::ReadSubMesh(Mesh *mesh) { uint8_t *indexBuffer = ReadBytes(numBytes); submesh->indexData->buffer = MemoryStreamPtr(new Assimp::MemoryIOStream(indexBuffer, numBytes, true)); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - ", submesh->indexData->faceCount, + ASSIMP_LOG_VERBOSE_DEBUG(" - ", submesh->indexData->faceCount, " faces from ", submesh->indexData->count, (submesh->indexData->is32bit ? " 32bit" : " 16bit"), " indexes of ", numBytes, " bytes"); } @@ -475,7 +475,7 @@ void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh) { } submesh->name = ReadLine(); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - SubMesh ", submesh->index, " name '", submesh->name, "'"); + ASSIMP_LOG_VERBOSE_DEBUG(" - SubMesh ", submesh->index, " name '", submesh->name, "'"); if (!AtEnd()) id = ReadHeader(); @@ -488,7 +488,7 @@ void OgreBinarySerializer::ReadSubMeshNames(Mesh *mesh) { void OgreBinarySerializer::ReadGeometry(VertexData *dest) { dest->count = Read(); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Reading geometry of ", dest->count, " vertices"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Reading geometry of ", dest->count, " vertices"); if (!AtEnd()) { uint16_t id = ReadHeader(); @@ -536,7 +536,7 @@ void OgreBinarySerializer::ReadGeometryVertexElement(VertexData *dest) { element.offset = Read(); element.index = Read(); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Vertex element ", element.SemanticToString(), " of type ", + ASSIMP_LOG_VERBOSE_DEBUG(" - Vertex element ", element.SemanticToString(), " of type ", element.TypeToString(), " index=", element.index, " source=", element.source); dest->vertexElements.push_back(element); @@ -557,7 +557,7 @@ void OgreBinarySerializer::ReadGeometryVertexBuffer(VertexData *dest) { uint8_t *vertexBuffer = ReadBytes(numBytes); dest->vertexBindings[bindIndex] = MemoryStreamPtr(new Assimp::MemoryIOStream(vertexBuffer, numBytes, true)); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Read vertex buffer for source ", bindIndex, " of ", numBytes, " bytes"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Read vertex buffer for source ", bindIndex, " of ", numBytes, " bytes"); } void OgreBinarySerializer::ReadEdgeList(Mesh * /*mesh*/) { @@ -777,12 +777,12 @@ bool OgreBinarySerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml MemoryStreamReaderPtr OgreBinarySerializer::OpenReader(Assimp::IOSystem *pIOHandler, const std::string &filename) { if (!EndsWith(filename, ".skeleton", false)) { - ASSIMP_LOG_ERROR_F("Imported Mesh is referencing to unsupported '", filename, "' skeleton file."); + ASSIMP_LOG_ERROR("Imported Mesh is referencing to unsupported '", filename, "' skeleton file."); return MemoryStreamReaderPtr(); } if (!pIOHandler->Exists(filename)) { - ASSIMP_LOG_ERROR_F("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh."); + ASSIMP_LOG_ERROR("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh."); return MemoryStreamReaderPtr(); } @@ -874,7 +874,7 @@ void OgreBinarySerializer::ReadBone(Skeleton *skeleton) { throw DeadlyImportError("Ogre Skeleton bone indexes not contiguous. Error at bone index ", bone->id); } - ASSIMP_LOG_VERBOSE_DEBUG_F(" ", bone->id, " ", bone->name); + ASSIMP_LOG_VERBOSE_DEBUG(" ", bone->id, " ", bone->name); skeleton->bones.push_back(bone); } @@ -919,7 +919,7 @@ void OgreBinarySerializer::ReadSkeletonAnimation(Skeleton *skeleton) { skeleton->animations.push_back(anim); - ASSIMP_LOG_VERBOSE_DEBUG_F(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)"); + ASSIMP_LOG_VERBOSE_DEBUG(" ", anim->name, " (", anim->length, " sec, ", anim->tracks.size(), " tracks)"); } void OgreBinarySerializer::ReadSkeletonAnimationTrack(Skeleton * /*skeleton*/, Animation *dest) { diff --git a/code/AssetLib/Ogre/OgreMaterial.cpp b/code/AssetLib/Ogre/OgreMaterial.cpp index eced651f6..295dedde6 100644 --- a/code/AssetLib/Ogre/OgreMaterial.cpp +++ b/code/AssetLib/Ogre/OgreMaterial.cpp @@ -160,16 +160,16 @@ aiMaterial *OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste if (materialFile) { break; } - ASSIMP_LOG_VERBOSE_DEBUG_F("Source file for material '", materialName, "' ", potentialFiles[i], " does not exist"); + ASSIMP_LOG_VERBOSE_DEBUG("Source file for material '", materialName, "' ", potentialFiles[i], " does not exist"); } if (!materialFile) { - ASSIMP_LOG_ERROR_F("Failed to find source file for material '", materialName, "'"); + ASSIMP_LOG_ERROR("Failed to find source file for material '", materialName, "'"); return 0; } std::unique_ptr stream(materialFile); if (stream->FileSize() == 0) { - ASSIMP_LOG_WARN_F("Source file for material '", materialName, "' is empty (size is 0 bytes)"); + ASSIMP_LOG_WARN("Source file for material '", materialName, "' is empty (size is 0 bytes)"); return 0; } @@ -184,7 +184,7 @@ aiMaterial *OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste ss << &data[0]; } - ASSIMP_LOG_VERBOSE_DEBUG_F("Reading material '", materialName, "'"); + ASSIMP_LOG_VERBOSE_DEBUG("Reading material '", materialName, "'"); aiMaterial *material = new aiMaterial(); m_textures.clear(); @@ -219,11 +219,11 @@ aiMaterial *OgreImporter::ReadMaterial(const std::string &pFile, Assimp::IOSyste NextAfterNewLine(ss, linePart); if (linePart != partBlockStart) { - ASSIMP_LOG_ERROR_F("Invalid material: block start missing near index ", ss.tellg()); + ASSIMP_LOG_ERROR("Invalid material: block start missing near index ", ss.tellg()); return material; } - ASSIMP_LOG_VERBOSE_DEBUG_F("material '", materialName, "'"); + ASSIMP_LOG_VERBOSE_DEBUG("material '", materialName, "'"); while (linePart != partBlockEnd) { // Proceed to the first technique @@ -303,11 +303,11 @@ bool OgreImporter::ReadTechnique(const std::string &techniqueName, stringstream ss >> linePart; if (linePart != partBlockStart) { - ASSIMP_LOG_ERROR_F("Invalid material: Technique block start missing near index ", ss.tellg()); + ASSIMP_LOG_ERROR("Invalid material: Technique block start missing near index ", ss.tellg()); return false; } - ASSIMP_LOG_VERBOSE_DEBUG_F(" technique '", techniqueName, "'"); + ASSIMP_LOG_VERBOSE_DEBUG(" technique '", techniqueName, "'"); const string partPass = "pass"; @@ -334,11 +334,11 @@ bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMat ss >> linePart; if (linePart != partBlockStart) { - ASSIMP_LOG_ERROR_F("Invalid material: Pass block start missing near index ", ss.tellg()); + ASSIMP_LOG_ERROR("Invalid material: Pass block start missing near index ", ss.tellg()); return false; } - ASSIMP_LOG_VERBOSE_DEBUG_F(" pass '", passName, "'"); + ASSIMP_LOG_VERBOSE_DEBUG(" pass '", passName, "'"); const string partAmbient = "ambient"; const string partDiffuse = "diffuse"; @@ -362,7 +362,7 @@ bool OgreImporter::ReadPass(const std::string &passName, stringstream &ss, aiMat ss >> r >> g >> b; const aiColor3D color(r, g, b); - ASSIMP_LOG_VERBOSE_DEBUG_F(" ", linePart, " ", r, " ", g, " ", b); + ASSIMP_LOG_VERBOSE_DEBUG(" ", linePart, " ", r, " ", g, " ", b); if (linePart == partAmbient) { material->AddProperty(&color, 1, AI_MATKEY_COLOR_AMBIENT); @@ -386,11 +386,11 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr ss >> linePart; if (linePart != partBlockStart) { - ASSIMP_LOG_ERROR_F("Invalid material: Texture unit block start missing near index ", ss.tellg()); + ASSIMP_LOG_ERROR("Invalid material: Texture unit block start missing near index ", ss.tellg()); return false; } - ASSIMP_LOG_VERBOSE_DEBUG_F(" texture_unit '", textureUnitName, "'"); + ASSIMP_LOG_VERBOSE_DEBUG(" texture_unit '", textureUnitName, "'"); const string partTexture = "texture"; const string partTextCoordSet = "tex_coord_set"; @@ -420,7 +420,7 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr if (posSuffix != string::npos && posUnderscore != string::npos && posSuffix > posUnderscore) { string identifier = ai_tolower(textureRef.substr(posUnderscore, posSuffix - posUnderscore)); - ASSIMP_LOG_VERBOSE_DEBUG_F("Detecting texture type from filename postfix '", identifier, "'"); + ASSIMP_LOG_VERBOSE_DEBUG("Detecting texture type from filename postfix '", identifier, "'"); if (identifier == "_n" || identifier == "_nrm" || identifier == "_nrml" || identifier == "_normal" || identifier == "_normals" || identifier == "_normalmap") { textureType = aiTextureType_NORMALS; @@ -477,14 +477,14 @@ bool OgreImporter::ReadTextureUnit(const std::string &textureUnitName, stringstr return false; } if (textureType == aiTextureType_NONE) { - ASSIMP_LOG_WARN("Failed to detect texture type for '" + textureRef + "', ignoring texture_unit."); + ASSIMP_LOG_WARN("Failed to detect texture type for '", textureRef, "', ignoring texture_unit."); return false; } unsigned int textureTypeIndex = m_textures[textureType]; m_textures[textureType]++; - ASSIMP_LOG_VERBOSE_DEBUG_F(" texture '", textureRef, "' type ", textureType, + ASSIMP_LOG_VERBOSE_DEBUG(" texture '", textureRef, "' type ", textureType, " index ", textureTypeIndex, " UV ", uvCoord); aiString assimpTextureRef(textureRef); diff --git a/code/AssetLib/Ogre/OgreStructs.cpp b/code/AssetLib/Ogre/OgreStructs.cpp index 90e2d4465..a2d861172 100644 --- a/code/AssetLib/Ogre/OgreStructs.cpp +++ b/code/AssetLib/Ogre/OgreStructs.cpp @@ -545,7 +545,7 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) { dest->mNumUVComponents[0] = static_cast(uv1Element->ComponentCount()); dest->mTextureCoords[0] = new aiVector3D[dest->mNumVertices]; } else { - ASSIMP_LOG_WARN(Formatter::format() << "Ogre imported UV0 type " << uv1Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); + ASSIMP_LOG_WARN("Ogre imported UV0 type ", uv1Element->TypeToString(), " is not compatible with Assimp. Ignoring UV."); uv1 = 0; } } @@ -554,7 +554,7 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) { dest->mNumUVComponents[1] = static_cast(uv2Element->ComponentCount()); dest->mTextureCoords[1] = new aiVector3D[dest->mNumVertices]; } else { - ASSIMP_LOG_WARN(Formatter::format() << "Ogre imported UV0 type " << uv2Element->TypeToString() << " is not compatible with Assimp. Ignoring UV."); + ASSIMP_LOG_WARN("Ogre imported UV0 type ", uv2Element->TypeToString(), " is not compatible with Assimp. Ignoring UV."); uv2 = 0; } } diff --git a/code/AssetLib/Ogre/OgreXmlSerializer.cpp b/code/AssetLib/Ogre/OgreXmlSerializer.cpp index 938ae48f3..70671f251 100644 --- a/code/AssetLib/Ogre/OgreXmlSerializer.cpp +++ b/code/AssetLib/Ogre/OgreXmlSerializer.cpp @@ -256,7 +256,7 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) { void OgreXmlSerializer::ReadGeometry(XmlNode &node, VertexDataXml *dest) { dest->count = ReadAttribute(node, "vertexcount"); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Reading geometry of ", dest->count, " vertices"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Reading geometry of ", dest->count, " vertices"); for (XmlNode currentNode : node.children()) { const std::string ¤tName = currentNode.name(); @@ -290,7 +290,7 @@ void OgreXmlSerializer::ReadGeometryVertexBuffer(XmlNode &node, VertexDataXml *d dest->tangents.reserve(dest->count); } if (uvs > 0) { - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Contains ", uvs, " texture coords"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Contains ", uvs, " texture coords"); dest->uvs.resize(uvs); for (size_t i = 0, len = dest->uvs.size(); i < len; ++i) { dest->uvs[i].reserve(dest->count); @@ -365,9 +365,9 @@ void OgreXmlSerializer::ReadSubMesh(XmlNode &node, MeshXml *mesh) { submesh->usesSharedVertexData = ReadAttribute(node, anUseSharedVertices); } - ASSIMP_LOG_VERBOSE_DEBUG_F("Reading SubMesh ", mesh->subMeshes.size()); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Material: '", submesh->materialRef, "'"); - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Uses shared geometry: ", (submesh->usesSharedVertexData ? "true" : "false")); + ASSIMP_LOG_VERBOSE_DEBUG("Reading SubMesh ", mesh->subMeshes.size()); + ASSIMP_LOG_VERBOSE_DEBUG(" - Material: '", submesh->materialRef, "'"); + ASSIMP_LOG_VERBOSE_DEBUG(" - Uses shared geometry: ", (submesh->usesSharedVertexData ? "true" : "false")); // TODO: maybe we have always just 1 faces and 1 geometry and always in this order. this loop will only work correct, when the order // of faces and geometry changed, and not if we have more than one of one @@ -398,7 +398,7 @@ void OgreXmlSerializer::ReadSubMesh(XmlNode &node, MeshXml *mesh) { } } if (submesh->indexData->faces.size() == submesh->indexData->faceCount) { - ASSIMP_LOG_VERBOSE_DEBUG_F(" - Faces ", submesh->indexData->faceCount); + ASSIMP_LOG_VERBOSE_DEBUG(" - Faces ", submesh->indexData->faceCount); } else { throw DeadlyImportError("Read only ", submesh->indexData->faces.size(), " faces when should have read ", submesh->indexData->faceCount); } @@ -459,7 +459,7 @@ void OgreXmlSerializer::ReadBoneAssignments(XmlNode &node, VertexDataXml *dest) } } - ASSIMP_LOG_VERBOSE_DEBUG_F(" - ", dest->boneAssignments.size(), " bone assignments"); + ASSIMP_LOG_VERBOSE_DEBUG(" - ", dest->boneAssignments.size(), " bone assignments"); } // Skeleton @@ -515,12 +515,12 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, Mesh *mesh) XmlParserPtr OgreXmlSerializer::OpenXmlParser(Assimp::IOSystem *pIOHandler, const std::string &filename) { if (!EndsWith(filename, ".skeleton.xml", false)) { - ASSIMP_LOG_ERROR_F("Imported Mesh is referencing to unsupported '", filename, "' skeleton file."); + ASSIMP_LOG_ERROR("Imported Mesh is referencing to unsupported '", filename, "' skeleton file."); return XmlParserPtr(); } if (!pIOHandler->Exists(filename)) { - ASSIMP_LOG_ERROR_F("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh."); + ASSIMP_LOG_ERROR("Failed to find skeleton file '", filename, "' that is referenced by imported Mesh."); return XmlParserPtr(); } @@ -631,7 +631,7 @@ void OgreXmlSerializer::ReadAnimationKeyFrames(XmlNode &node, Animation *anim, V if (axis.Equal(zeroVec)) { axis.x = 1.0f; if (angle != 0) { - ASSIMP_LOG_WARN_F("Found invalid a key frame with a zero rotation axis in animation: ", anim->name); + ASSIMP_LOG_WARN("Found invalid a key frame with a zero rotation axis in animation: ", anim->name); } } keyframe.rotation = aiQuaternion(axis, angle); @@ -741,7 +741,7 @@ void OgreXmlSerializer::ReadBones(XmlNode &node, Skeleton *skeleton) { as per the Ogre skeleton spec. It might be more that other (later) code in this imported does not break. */ for (size_t i = 0, len = skeleton->bones.size(); i < len; ++i) { Bone *b = skeleton->bones[i]; - ASSIMP_LOG_VERBOSE_DEBUG_F(" ", b->id, " ", b->name); + ASSIMP_LOG_VERBOSE_DEBUG(" ", b->id, " ", b->name); if (b->id != static_cast(i)) { throw DeadlyImportError("Bone ids are not in sequence starting from 0. Missing index ", i); diff --git a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp index b29aeeeb1..05507944e 100644 --- a/code/AssetLib/OpenGEX/OpenGEXImporter.cpp +++ b/code/AssetLib/OpenGEX/OpenGEXImporter.cpp @@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include +#include #include #include @@ -223,6 +224,18 @@ static void propId2StdString(Property *prop, std::string &name, std::string &key } } +//------------------------------------------------------------------------------------------------ +static void logDDLParserMessage (LogSeverity severity, const std::string &rawmsg) { + std::string msg = ai_str_toprintable(rawmsg); + switch (severity) { + case ddl_debug_msg: ASSIMP_LOG_DEBUG(msg); break; + case ddl_info_msg: ASSIMP_LOG_INFO(msg); break; + case ddl_warn_msg: ASSIMP_LOG_WARN(msg); break; + case ddl_error_msg: ASSIMP_LOG_ERROR(msg); break; + default: ASSIMP_LOG_VERBOSE_DEBUG(msg); break; + } +} + //------------------------------------------------------------------------------------------------ OpenGEXImporter::VertexContainer::VertexContainer() : m_numColors(0), m_colors(nullptr), m_numUVComps(), m_textureCoords() { @@ -306,6 +319,7 @@ void OpenGEXImporter::InternReadFile(const std::string &filename, aiScene *pScen pIOHandler->Close(file); OpenDDLParser myParser; + myParser.setLogCallback(&logDDLParserMessage); myParser.setBuffer(&buffer[0], buffer.size()); bool success(myParser.parse()); if (success) { @@ -712,7 +726,7 @@ void OpenGEXImporter::handleMeshNode(ODDLParser::DDLNode *node, aiScene *pScene) } else if ("quads" == propKey) { m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON; } else { - ASSIMP_LOG_WARN_F(propKey, " is not supported primitive type."); + ASSIMP_LOG_WARN(propKey, " is not supported primitive type."); } } } @@ -735,22 +749,22 @@ enum MeshAttribute { TexCoord }; -static const std::string PosToken = "position"; -static const std::string ColToken = "color"; -static const std::string NormalToken = "normal"; -static const std::string TexCoordToken = "texcoord"; +constexpr auto PosToken = "position"; +constexpr auto ColToken = "color"; +constexpr auto NormalToken = "normal"; +constexpr auto TexCoordToken = "texcoord"; //------------------------------------------------------------------------------------------------ static MeshAttribute getAttributeByName(const char *attribName) { ai_assert(nullptr != attribName); - if (0 == strncmp(PosToken.c_str(), attribName, PosToken.size())) { + if (0 == strcmp(PosToken, attribName)) { return Position; - } else if (0 == strncmp(ColToken.c_str(), attribName, ColToken.size())) { + } else if (0 == strcmp(ColToken, attribName)) { return Color; - } else if (0 == strncmp(NormalToken.c_str(), attribName, NormalToken.size())) { + } else if (0 == strcmp(NormalToken, attribName)) { return Normal; - } else if (0 == strncmp(TexCoordToken.c_str(), attribName, TexCoordToken.size())) { + } else if (0 == strcmp(TexCoordToken, attribName)) { return TexCoord; } diff --git a/code/AssetLib/Ply/PlyLoader.cpp b/code/AssetLib/Ply/PlyLoader.cpp index ce52636dd..93d48bcbf 100644 --- a/code/AssetLib/Ply/PlyLoader.cpp +++ b/code/AssetLib/Ply/PlyLoader.cpp @@ -172,7 +172,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy (headerCheck[1] != 'L' && headerCheck[1] != 'l') || (headerCheck[2] != 'Y' && headerCheck[2] != 'y')) { streamedBuffer.close(); - throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there"); + throw DeadlyImportError("Invalid .ply file: Incorrect magic number (expected 'ply' or 'PLY')."); } std::vector mBuffer2; diff --git a/code/AssetLib/Ply/PlyParser.cpp b/code/AssetLib/Ply/PlyParser.cpp index 4b416d1a1..59cb6b976 100644 --- a/code/AssetLib/Ply/PlyParser.cpp +++ b/code/AssetLib/Ply/PlyParser.cpp @@ -419,7 +419,8 @@ bool PLY::DOM::ParseHeader(IOStreamBuffer &streamBuffer, std::vector if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) { // add the element to the list of elements alElements.push_back(out); - } else if (TokenMatch(buffer, "end_header", 10)) { + } else if ( TokenMatch(buffer, "end_header\r", 11) || //checks for header end with /r/n ending + TokenMatch(buffer, "end_header", 10)) { //checks for /n ending, if it doesn't end with /r/n // we have reached the end of the header break; } else { diff --git a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp index 7d9e1f6eb..becfa41fc 100644 --- a/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp +++ b/code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp @@ -446,7 +446,7 @@ void Q3BSPFileImporter::createMaterials(const Q3BSP::Q3BSPModel *pModel, aiScene normalizePathName(tmp, texName); if (!importTextureFromArchive(pModel, pArchive, pScene, pMatHelper, textureId)) { - ASSIMP_LOG_ERROR("Cannot import texture from archive " + texName); + ASSIMP_LOG_ERROR("Cannot import texture from archive ", texName); } } } diff --git a/code/AssetLib/Q3D/Q3DLoader.cpp b/code/AssetLib/Q3D/Q3DLoader.cpp index b52f86672..f81026547 100644 --- a/code/AssetLib/Q3D/Q3DLoader.cpp +++ b/code/AssetLib/Q3D/Q3DLoader.cpp @@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. // internal headers #include "Q3DLoader.h" +#include #include #include #include @@ -106,7 +107,12 @@ const aiImporterDesc *Q3DImporter::GetInfo() const { // Imports the given file into the given scene structure. void Q3DImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { - StreamReaderLE stream(pIOHandler->Open(pFile, "rb")); + + auto file = pIOHandler->Open(pFile, "rb"); + if (!file) + throw DeadlyImportError("Quick3D: Could not open ", pFile); + + StreamReaderLE stream(file); // The header is 22 bytes large if (stream.GetRemainingSize() < 22) @@ -115,11 +121,11 @@ void Q3DImporter::InternReadFile(const std::string &pFile, // Check the file's signature if (ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Do", 8) && ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Ds", 8)) { - throw DeadlyImportError("Not a Quick3D file. Signature string is: ", std::string((const char *)stream.GetPtr(), 8)); + throw DeadlyImportError("Not a Quick3D file. Signature string is: ", ai_str_toprintable((const char *)stream.GetPtr(), 8)); } // Print the file format version - ASSIMP_LOG_INFO_F("Quick3D File format version: ", + ASSIMP_LOG_INFO("Quick3D File format version: ", std::string(&((const char *)stream.GetPtr())[8], 2)); // ... an store it diff --git a/code/AssetLib/SIB/SIBImporter.cpp b/code/AssetLib/SIB/SIBImporter.cpp index 6898fb65c..0321e7064 100644 --- a/code/AssetLib/SIB/SIBImporter.cpp +++ b/code/AssetLib/SIB/SIBImporter.cpp @@ -68,6 +68,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include #include #include +#include #include @@ -166,21 +167,20 @@ static aiColor3D ReadColor(StreamReaderLE *stream) { } static void UnknownChunk(StreamReaderLE * /*stream*/, const SIBChunk &chunk) { - char temp[5] = { + char temp[4] = { static_cast((chunk.Tag >> 24) & 0xff), static_cast((chunk.Tag >> 16) & 0xff), static_cast((chunk.Tag >> 8) & 0xff), - static_cast(chunk.Tag & 0xff), '\0' + static_cast(chunk.Tag & 0xff) }; - ASSIMP_LOG_WARN((Formatter::format(), "SIB: Skipping unknown '", temp, "' chunk.")); + ASSIMP_LOG_WARN("SIB: Skipping unknown '", ai_str_toprintable(temp, 4), "' chunk."); } // Reads a UTF-16LE string and returns it at UTF-8. static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) { if (nullptr == stream || 0 == numWChars) { - static const aiString empty; - return empty; + return aiString(); } // Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8) @@ -804,7 +804,12 @@ static void ReadScene(SIB *sib, StreamReaderLE *stream) { // Imports the given file into the given scene structure. void SIBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { - StreamReaderLE stream(pIOHandler->Open(pFile, "rb")); + + auto file = pIOHandler->Open(pFile, "rb"); + if (!file) + throw DeadlyImportError("SIB: Could not open ", pFile); + + StreamReaderLE stream(file); // We should have at least one chunk if (stream.GetRemainingSize() < 16) diff --git a/code/AssetLib/STEPParser/STEPFileReader.cpp b/code/AssetLib/STEPParser/STEPFileReader.cpp index cbf8c07c2..e97ea1e28 100644 --- a/code/AssetLib/STEPParser/STEPFileReader.cpp +++ b/code/AssetLib/STEPParser/STEPFileReader.cpp @@ -297,8 +297,8 @@ void STEP::ReadFile(DB& db,const EXPRESS::ConversionSchema& scheme, } if ( !DefaultLogger::isNullLogger()){ - ASSIMP_LOG_DEBUG((Formatter::format(),"STEP: got ",map.size()," object records with ", - db.GetRefs().size()," inverse index entries")); + ASSIMP_LOG_DEBUG("STEP: got ",map.size()," object records with ", + db.GetRefs().size()," inverse index entries"); } } diff --git a/code/AssetLib/Unreal/UnrealLoader.cpp b/code/AssetLib/Unreal/UnrealLoader.cpp index 499b49c05..e3ebc05c3 100644 --- a/code/AssetLib/Unreal/UnrealLoader.cpp +++ b/code/AssetLib/Unreal/UnrealLoader.cpp @@ -228,9 +228,9 @@ void UnrealImporter::InternReadFile(const std::string &pFile, a_path = extension + "_a.3d"; uc_path = extension + ".uc"; - ASSIMP_LOG_DEBUG_F("UNREAL: data file is ", d_path); - ASSIMP_LOG_DEBUG_F("UNREAL: aniv file is ", a_path); - ASSIMP_LOG_DEBUG_F("UNREAL: uc file is ", uc_path); + ASSIMP_LOG_DEBUG("UNREAL: data file is ", d_path); + ASSIMP_LOG_DEBUG("UNREAL: aniv file is ", a_path); + ASSIMP_LOG_DEBUG("UNREAL: uc file is ", uc_path); // and open the files ... we can't live without them std::unique_ptr p(pIOHandler->Open(d_path)); diff --git a/code/AssetLib/X/XFileImporter.cpp b/code/AssetLib/X/XFileImporter.cpp index cb245ed74..df1aba331 100644 --- a/code/AssetLib/X/XFileImporter.cpp +++ b/code/AssetLib/X/XFileImporter.cpp @@ -602,7 +602,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vectorparse(stream.get())) { - return; + throw DeadlyImportError("XML parse error while loading XGL file ", pFile); } TempScope scope; diff --git a/code/AssetLib/glTF/glTFExporter.cpp b/code/AssetLib/glTF/glTFExporter.cpp index 215f24493..c2f96973b 100644 --- a/code/AssetLib/glTF/glTFExporter.cpp +++ b/code/AssetLib/glTF/glTFExporter.cpp @@ -607,7 +607,7 @@ void glTFExporter::ExportMeshes() else msg = "mesh must has vertices and faces."; - ASSIMP_LOG_WARN_F("GLTF: can not use Open3DGC-compression: ", msg); + ASSIMP_LOG_WARN("GLTF: can not use Open3DGC-compression: ", msg); comp_allow = false; } diff --git a/code/AssetLib/glTF2/glTF2Asset.h b/code/AssetLib/glTF2/glTF2Asset.h index 26a2f64c3..6aa0f92ed 100644 --- a/code/AssetLib/glTF2/glTF2Asset.h +++ b/code/AssetLib/glTF2/glTF2Asset.h @@ -1118,11 +1118,13 @@ public: bool KHR_materials_transmission; bool KHR_draco_mesh_compression; bool FB_ngon_encoding; + bool KHR_texture_basisu; } extensionsUsed; //! Keeps info about the required extensions struct RequiredExtensions { bool KHR_draco_mesh_compression; + bool KHR_texture_basisu; } extensionsRequired; AssetMetadata asset; diff --git a/code/AssetLib/glTF2/glTF2Asset.inl b/code/AssetLib/glTF2/glTF2Asset.inl index 8a793c144..b51ac20c2 100644 --- a/code/AssetLib/glTF2/glTF2Asset.inl +++ b/code/AssetLib/glTF2/glTF2Asset.inl @@ -58,7 +58,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #pragma clang diagnostic ignored "-Wsign-compare" #elif defined(__GNUC__) #pragma GCC diagnostic push +#if (__GNUC__ > 4) #pragma GCC diagnostic ignored "-Wbool-compare" +#endif #pragma GCC diagnostic ignored "-Wsign-compare" #endif @@ -1144,6 +1146,7 @@ inline Image::Image() : } inline void Image::Read(Value &obj, Asset &r) { + //basisu: no need to handle .ktx2, .basis, load as is if (!mDataLength) { Value *curUri = FindString(obj, "uri"); if (nullptr != curUri) { @@ -2124,6 +2127,7 @@ inline void Asset::ReadExtensionsUsed(Document &doc) { CHECK_EXT(KHR_materials_clearcoat); CHECK_EXT(KHR_materials_transmission); CHECK_EXT(KHR_draco_mesh_compression); + CHECK_EXT(KHR_texture_basisu); #undef CHECK_EXT } diff --git a/code/AssetLib/glTF2/glTF2AssetWriter.inl b/code/AssetLib/glTF2/glTF2AssetWriter.inl index 01a28d4b7..bf7dbbb2e 100644 --- a/code/AssetLib/glTF2/glTF2AssetWriter.inl +++ b/code/AssetLib/glTF2/glTF2AssetWriter.inl @@ -250,6 +250,7 @@ namespace glTF2 { inline void Write(Value& obj, Image& img, AssetWriter& w) { + //basisu: no need to handle .ktx2, .basis, write as is if (img.bufferView) { obj.AddMember("bufferView", img.bufferView->index, w.mAl); obj.AddMember("mimeType", Value(img.mimeType, w.mAl).Move(), w.mAl); @@ -892,10 +893,22 @@ namespace glTF2 { if (this->mAsset.extensionsUsed.FB_ngon_encoding) { exts.PushBack(StringRef("FB_ngon_encoding"), mAl); } + + if (this->mAsset.extensionsUsed.KHR_texture_basisu) { + exts.PushBack(StringRef("KHR_texture_basisu"), mAl); + } } if (!exts.Empty()) mDoc.AddMember("extensionsUsed", exts, mAl); + + //basisu extensionRequired + Value extsReq; + extsReq.SetArray(); + if (this->mAsset.extensionsUsed.KHR_texture_basisu) { + extsReq.PushBack(StringRef("KHR_texture_basisu"), mAl); + mDoc.AddMember("extensionsRequired", extsReq, mAl); + } } template diff --git a/code/AssetLib/glTF2/glTF2Exporter.cpp b/code/AssetLib/glTF2/glTF2Exporter.cpp index 6105792d2..fe592f342 100644 --- a/code/AssetLib/glTF2/glTF2Exporter.cpp +++ b/code/AssetLib/glTF2/glTF2Exporter.cpp @@ -494,7 +494,6 @@ void glTF2Exporter::GetMatTexProp(const aiMaterial* mat, float& prop, const char void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTextureType tt, unsigned int slot = 0) { - if (mat->GetTextureCount(tt) > 0) { aiString tex; @@ -507,6 +506,7 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe texture = mAsset->textures.Get(it->second); } + bool useBasisUniversal = false; if (!texture) { std::string texId = mAsset->FindUniqueID("", "texture"); texture = mAsset->textures.Create(texId); @@ -519,18 +519,46 @@ void glTF2Exporter::GetMatTex(const aiMaterial* mat, Ref& texture, aiTe aiTexture* curTex = mScene->mTextures[atoi(&path[1])]; texture->source->name = curTex->mFilename.C_Str(); - - // The asset has its own buffer, see Image::SetData - texture->source->SetData(reinterpret_cast(curTex->pcData), curTex->mWidth, *mAsset); - + + //basisu: embedded ktx2, bu if (curTex->achFormatHint[0]) { std::string mimeType = "image/"; - mimeType += (memcmp(curTex->achFormatHint, "jpg", 3) == 0) ? "jpeg" : curTex->achFormatHint; + if(memcmp(curTex->achFormatHint, "jpg", 3) == 0) + mimeType += "jpeg"; + else if(memcmp(curTex->achFormatHint, "ktx", 3) == 0) { + useBasisUniversal = true; + mimeType += "ktx"; + } + else if(memcmp(curTex->achFormatHint, "kx2", 3) == 0) { + useBasisUniversal = true; + mimeType += "ktx2"; + } + else if(memcmp(curTex->achFormatHint, "bu", 2) == 0) { + useBasisUniversal = true; + mimeType += "basis"; + } + else + mimeType += curTex->achFormatHint; texture->source->mimeType = mimeType; } + + // The asset has its own buffer, see Image::SetData + //basisu: "image/ktx2", "image/basis" as is + texture->source->SetData(reinterpret_cast(curTex->pcData), curTex->mWidth, *mAsset); } else { texture->source->uri = path; + if(texture->source->uri.find(".ktx")!=std::string::npos || + texture->source->uri.find(".basis")!=std::string::npos) + { + useBasisUniversal = true; + } + } + + //basisu + if(useBasisUniversal) { + mAsset->extensionsUsed.KHR_texture_basisu = true; + mAsset->extensionsRequired.KHR_texture_basisu = true; } GetTexSampler(mat, texture, tt, slot); diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index f34b1b451..c62989c3b 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -325,7 +325,7 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M void glTF2Importer::ImportMaterials(glTF2::Asset &r) { const unsigned int numImportedMaterials = unsigned(r.materials.Size()); - ASSIMP_LOG_DEBUG_F("Importing ", numImportedMaterials, " materials"); + ASSIMP_LOG_DEBUG("Importing ", numImportedMaterials, " materials"); Material defaultMaterial; mScene->mNumMaterials = numImportedMaterials + 1; @@ -402,7 +402,7 @@ aiColor4D* GetVertexColorsForType(glTF2::Ref input) { } void glTF2Importer::ImportMeshes(glTF2::Asset &r) { - ASSIMP_LOG_DEBUG_F("Importing ", r.meshes.Size(), " meshes"); + ASSIMP_LOG_DEBUG("Importing ", r.meshes.Size(), " meshes"); std::vector> meshes; unsigned int k = 0; @@ -455,14 +455,14 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { if (attr.normal.size() > 0 && attr.normal[0]) { if (attr.normal[0]->count != aim->mNumVertices) { - DefaultLogger::get()->warn("Normal count in mesh \"" + mesh.name + "\" does not match the vertex count, normals ignored."); + DefaultLogger::get()->warn("Normal count in mesh \"", mesh.name, "\" does not match the vertex count, normals ignored."); } else { attr.normal[0]->ExtractData(aim->mNormals); // only extract tangents if normals are present if (attr.tangent.size() > 0 && attr.tangent[0]) { if (attr.tangent[0]->count != aim->mNumVertices) { - DefaultLogger::get()->warn("Tangent count in mesh \"" + mesh.name + "\" does not match the vertex count, tangents ignored."); + DefaultLogger::get()->warn("Tangent count in mesh \"", mesh.name, "\" does not match the vertex count, tangents ignored."); } else { // generate bitangents from normals and tangents according to spec Tangent *tangents = nullptr; @@ -485,7 +485,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) { if (attr.color[c]->count != aim->mNumVertices) { - DefaultLogger::get()->warn("Color stream size in mesh \"" + mesh.name + + DefaultLogger::get()->warn("Color stream size in mesh \"", mesh.name, "\" does not match the vertex count"); continue; } @@ -508,7 +508,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } if (attr.texcoord[tc]->count != aim->mNumVertices) { - DefaultLogger::get()->warn("Texcoord stream size in mesh \"" + mesh.name + + DefaultLogger::get()->warn("Texcoord stream size in mesh \"", mesh.name, "\" does not match the vertex count"); continue; } @@ -539,7 +539,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { if (needPositions) { if (target.position[0]->count != aim->mNumVertices) { - ASSIMP_LOG_WARN_F("Positions of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count"); + ASSIMP_LOG_WARN("Positions of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count"); } else { aiVector3D *positionDiff = nullptr; target.position[0]->ExtractData(positionDiff); @@ -551,7 +551,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } if (needNormals) { if (target.normal[0]->count != aim->mNumVertices) { - ASSIMP_LOG_WARN_F("Normals of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count"); + ASSIMP_LOG_WARN("Normals of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count"); } else { aiVector3D *normalDiff = nullptr; target.normal[0]->ExtractData(normalDiff); @@ -563,7 +563,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } if (needTangents) { if (target.tangent[0]->count != aim->mNumVertices) { - ASSIMP_LOG_WARN_F("Tangents of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count"); + ASSIMP_LOG_WARN("Tangents of target ", i, " in mesh \"", mesh.name, "\" does not match the vertex count"); } else { Tangent *tangent = nullptr; attr.tangent[0]->ExtractData(tangent); @@ -785,7 +785,7 @@ void glTF2Importer::ImportCameras(glTF2::Asset &r) { if (!r.cameras.Size()) return; const unsigned int numCameras = r.cameras.Size(); - ASSIMP_LOG_DEBUG_F("Importing ", numCameras, " cameras"); + ASSIMP_LOG_DEBUG("Importing ", numCameras, " cameras"); mScene->mNumCameras = numCameras; mScene->mCameras = new aiCamera *[numCameras]; std::fill(mScene->mCameras, mScene->mCameras + numCameras, nullptr); @@ -822,7 +822,7 @@ void glTF2Importer::ImportLights(glTF2::Asset &r) { return; const unsigned int numLights = r.lights.Size(); - ASSIMP_LOG_DEBUG_F("Importing ", numLights, " lights"); + ASSIMP_LOG_DEBUG("Importing ", numLights, " lights"); mScene->mNumLights = numLights; mScene->mLights = new aiLight *[numLights]; std::fill(mScene->mLights, mScene->mLights + numLights, nullptr); @@ -1263,7 +1263,7 @@ aiMeshMorphAnim *CreateMeshMorphAnim(glTF2::Asset&, Node &node, AnimationSampler static const float kMillisecondsFromSeconds = 1000.f; - if (nullptr != samplers.weight) { + if (samplers.weight && samplers.weight->input && samplers.weight->output) { float *times = nullptr; samplers.weight->input->ExtractData(times); float *values = nullptr; @@ -1329,7 +1329,7 @@ void glTF2Importer::ImportAnimations(glTF2::Asset &r) { if (!r.scene) return; const unsigned numAnimations = r.animations.Size(); - ASSIMP_LOG_DEBUG_F("Importing ", numAnimations, " animations"); + ASSIMP_LOG_DEBUG("Importing ", numAnimations, " animations"); mScene->mNumAnimations = numAnimations; if (mScene->mNumAnimations == 0) { return; @@ -1445,7 +1445,7 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { if (numEmbeddedTexs == 0) return; - ASSIMP_LOG_DEBUG_F("Importing ", numEmbeddedTexs, " embedded textures"); + ASSIMP_LOG_DEBUG("Importing ", numEmbeddedTexs, " embedded textures"); mScene->mTextures = new aiTexture *[numEmbeddedTexs]; std::fill(mScene->mTextures, mScene->mTextures + numEmbeddedTexs, nullptr); @@ -1476,6 +1476,12 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { if (strcmp(ext, "jpeg") == 0) { ext = "jpg"; } + else if(strcmp(ext, "ktx2") == 0) { //basisu: ktx remains + ext = "kx2"; + } + else if(strcmp(ext, "basis") == 0) { //basisu + ext = "bu"; + } size_t len = strlen(ext); if (len <= 3) { diff --git a/code/CMakeLists.txt b/code/CMakeLists.txt index 439715845..be1619e81 100644 --- a/code/CMakeLists.txt +++ b/code/CMakeLists.txt @@ -1139,6 +1139,9 @@ ELSE() TARGET_COMPILE_OPTIONS(assimp PRIVATE -Werror) ENDIF() +# adds C_FLAGS required to compile zip.c on old GCC 4.x compiler +TARGET_COMPILE_FEATURES(assimp PUBLIC c_std_99) + TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC $ $ diff --git a/code/Common/BaseImporter.cpp b/code/Common/BaseImporter.cpp index 2783a8372..0f41e9e65 100644 --- a/code/Common/BaseImporter.cpp +++ b/code/Common/BaseImporter.cpp @@ -83,7 +83,7 @@ void BaseImporter::UpdateImporterScale(Importer *pImp) { // Set active scaling pImp->SetPropertyFloat(AI_CONFIG_APP_SCALE_KEY, static_cast(activeScale)); - ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: ", activeScale); + ASSIMP_LOG_DEBUG("UpdateImporterScale scale set: ", activeScale); } // ------------------------------------------------------------------------------------------------ @@ -179,7 +179,7 @@ void BaseImporter::GetExtensionList(std::set &extensions) { } for (size_t i = 0; i < read; ++i) { - buffer[i] = static_cast(::tolower(buffer[i])); + buffer[i] = static_cast(::tolower((unsigned char)buffer[i])); } // It is not a proper handling of unicode files here ... @@ -200,7 +200,7 @@ void BaseImporter::GetExtensionList(std::set &extensions) { token.clear(); const char *ptr(tokens[i]); for (size_t tokIdx = 0; tokIdx < len; ++tokIdx) { - token.push_back(static_cast(tolower(*ptr))); + token.push_back(static_cast(tolower(static_cast(*ptr)))); ++ptr; } const char *r = strstr(buffer, token.c_str()); @@ -209,13 +209,13 @@ void BaseImporter::GetExtensionList(std::set &extensions) { } // We need to make sure that we didn't accidentially identify the end of another token as our token, // e.g. in a previous version the "gltf " present in some gltf files was detected as "f " - if (noAlphaBeforeTokens && (r != buffer && isalpha(r[-1]))) { + if (noAlphaBeforeTokens && (r != buffer && isalpha(static_cast(r[-1])))) { continue; } // We got a match, either we don't care where it is, or it happens to // be in the beginning of the file / line if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') { - ASSIMP_LOG_DEBUG_F("Found positive match for header keyword: ", tokens[i]); + ASSIMP_LOG_DEBUG("Found positive match for header keyword: ", tokens[i]); return true; } } @@ -604,7 +604,7 @@ void BatchLoader::LoadAll() { if (!DefaultLogger::isNullLogger()) { ASSIMP_LOG_INFO("%%% BEGIN EXTERNAL FILE %%%"); - ASSIMP_LOG_INFO_F("File: ", (*it).file); + ASSIMP_LOG_INFO("File: ", (*it).file); } m_data->pImporter->ReadFile((*it).file, pp); (*it).scene = m_data->pImporter->GetOrphanedScene(); diff --git a/code/Common/DefaultIOSystem.cpp b/code/Common/DefaultIOSystem.cpp index ec7a311cf..98d51a17d 100644 --- a/code/Common/DefaultIOSystem.cpp +++ b/code/Common/DefaultIOSystem.cpp @@ -176,7 +176,7 @@ inline static std::string MakeAbsolutePath(const char *in) { if (!ret) { // preserve the input path, maybe someone else is able to fix // the path before it is accessed (e.g. our file system filter) - ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in)); + ASSIMP_LOG_WARN("Invalid path: ", std::string(in)); out = in; } return out; diff --git a/code/Common/DefaultLogger.cpp b/code/Common/DefaultLogger.cpp index aa13ca5ce..da43a7a7e 100644 --- a/code/Common/DefaultLogger.cpp +++ b/code/Common/DefaultLogger.cpp @@ -169,7 +169,7 @@ void Logger::debug(const char *message) { // sometimes importers will include data from the input file // (i.e. node names) in their messages. if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { - return; + return OnDebug(""); } return OnDebug(message); } @@ -177,11 +177,9 @@ void Logger::debug(const char *message) { // ---------------------------------------------------------------------------------- void Logger::verboseDebug(const char *message) { - // SECURITY FIX: otherwise it's easy to produce overruns since - // sometimes importers will include data from the input file - // (i.e. node names) in their messages. + // SECURITY FIX: see above if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { - return; + return OnVerboseDebug(""); } return OnVerboseDebug(message); } @@ -191,7 +189,7 @@ void Logger::info(const char *message) { // SECURITY FIX: see above if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { - return; + return OnInfo(""); } return OnInfo(message); } @@ -201,7 +199,7 @@ void Logger::warn(const char *message) { // SECURITY FIX: see above if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { - return; + return OnWarn(""); } return OnWarn(message); } @@ -210,7 +208,7 @@ void Logger::warn(const char *message) { void Logger::error(const char *message) { // SECURITY FIX: see above if (strlen(message) > MAX_LOG_MESSAGE_LENGTH) { - return; + return OnError(""); } return OnError(message); } diff --git a/code/Common/Exporter.cpp b/code/Common/Exporter.cpp index 20cbb05d6..ebcc955df 100644 --- a/code/Common/Exporter.cpp +++ b/code/Common/Exporter.cpp @@ -343,9 +343,11 @@ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const cha delete pimpl->blob; pimpl->blob = nullptr; } + + auto baseName = pProperties ? pProperties->GetPropertyString(AI_CONFIG_EXPORT_BLOB_NAME, AI_BLOBIO_MAGIC) : AI_BLOBIO_MAGIC; std::shared_ptr old = pimpl->mIOSystem; - BlobIOSystem* blobio = new BlobIOSystem(); + BlobIOSystem *blobio = new BlobIOSystem(baseName); pimpl->mIOSystem = std::shared_ptr( blobio ); if (AI_SUCCESS != Export(pScene,pFormatId,blobio->GetMagicFileName(), pPreprocessing, pProperties)) { diff --git a/code/Common/FileSystemFilter.h b/code/Common/FileSystemFilter.h index 92f199870..6585f9df6 100644 --- a/code/Common/FileSystemFilter.h +++ b/code/Common/FileSystemFilter.h @@ -89,7 +89,7 @@ public: mBase += getOsSeparator(); } - DefaultLogger::get()->info("Import root directory is \'" + mBase + "\'"); + DefaultLogger::get()->info("Import root directory is \'", mBase, "\'"); } /** Destructor. */ diff --git a/code/Common/Importer.cpp b/code/Common/Importer.cpp index 8cea2cd09..a2ad041fb 100644 --- a/code/Common/Importer.cpp +++ b/code/Common/Importer.cpp @@ -232,7 +232,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp) { #ifdef ASSIMP_BUILD_DEBUG if (IsExtensionSupported(*it)) { - ASSIMP_LOG_WARN_F("The file extension ", *it, " is already in use"); + ASSIMP_LOG_WARN("The file extension ", *it, " is already in use"); } #endif baked += *it; @@ -240,7 +240,7 @@ aiReturn Importer::RegisterLoader(BaseImporter* pImp) { // add the loader pimpl->mImporter.push_back(pImp); - ASSIMP_LOG_INFO_F("Registering custom importer for these file extensions: ", baked); + ASSIMP_LOG_INFO("Registering custom importer for these file extensions: ", baked); ASSIMP_END_EXCEPTION_REGION(aiReturn); return AI_SUCCESS; @@ -519,7 +519,7 @@ const aiScene* Importer::ReadFileFromMemory( const void* pBuffer, // ------------------------------------------------------------------------------------------------ void WriteLogOpening(const std::string& file) { - ASSIMP_LOG_INFO_F("Load ", file); + ASSIMP_LOG_INFO("Load ", file); // print a full version dump. This is nice because we don't // need to ask the authors of incoming bug reports for @@ -665,7 +665,7 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) { if ( nullptr != desc ) { ext = desc->mName; } - ASSIMP_LOG_INFO("Found a matching importer for this file format: " + ext + "." ); + ASSIMP_LOG_INFO("Found a matching importer for this file format: ", ext, "." ); pimpl->mProgressHandler->UpdateFileRead( 0, fileSize ); if (profiler) { diff --git a/code/Common/SceneCombiner.cpp b/code/Common/SceneCombiner.cpp index fe00dfe1f..555d46b6a 100644 --- a/code/Common/SceneCombiner.cpp +++ b/code/Common/SceneCombiner.cpp @@ -612,7 +612,7 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vectormName.data, + ASSIMP_LOG_ERROR("SceneCombiner: Failed to resolve attachment ", (*it).node->mName.data, " ", (*it).attachToNode->mName.data); } } diff --git a/code/Common/Subdivision.cpp b/code/Common/Subdivision.cpp index 76fc83404..9e7577a04 100644 --- a/code/Common/Subdivision.cpp +++ b/code/Common/Subdivision.cpp @@ -336,7 +336,7 @@ void CatmullClarkSubdivider::InternSubdivide( // Report the number of bad edges. bad edges are referenced by less than two // faces in the mesh. They occur at outer model boundaries in non-closed // shapes. - ASSIMP_LOG_VERBOSE_DEBUG_F("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ", + ASSIMP_LOG_VERBOSE_DEBUG("Catmull-Clark Subdivider: got ", bad_cnt, " bad edges touching only one face (totally ", static_cast(edges.size()), " edges). "); } } diff --git a/code/Material/MaterialSystem.cpp b/code/Material/MaterialSystem.cpp index 310dea29d..c35a1aa93 100644 --- a/code/Material/MaterialSystem.cpp +++ b/code/Material/MaterialSystem.cpp @@ -160,7 +160,7 @@ aiReturn aiGetMaterialFloatArray(const aiMaterial *pMat, break; } if (!IsSpace(*cur)) { - ASSIMP_LOG_ERROR("Material property" + std::string(pKey) + + ASSIMP_LOG_ERROR("Material property", pKey, " is a string; failed to parse a float array out of it."); return AI_FAILURE; } @@ -238,7 +238,7 @@ aiReturn aiGetMaterialIntegerArray(const aiMaterial *pMat, break; } if (!IsSpace(*cur)) { - ASSIMP_LOG_ERROR("Material property" + std::string(pKey) + + ASSIMP_LOG_ERROR("Material property", pKey, " is a string; failed to parse an integer array out of it."); return AI_FAILURE; } @@ -306,8 +306,7 @@ aiReturn aiGetMaterialString(const aiMaterial *pMat, memcpy(pOut->data, prop->mData + 4, pOut->length + 1); } else { // TODO - implement lexical cast as well - ASSIMP_LOG_ERROR("Material property" + std::string(pKey) + - " was found, but is no string"); + ASSIMP_LOG_ERROR("Material property", pKey, " was found, but is no string"); return AI_FAILURE; } return AI_SUCCESS; diff --git a/code/PostProcessing/ArmaturePopulate.cpp b/code/PostProcessing/ArmaturePopulate.cpp index 88b0b2d7c..fdf7508d0 100644 --- a/code/PostProcessing/ArmaturePopulate.cpp +++ b/code/PostProcessing/ArmaturePopulate.cpp @@ -77,12 +77,12 @@ void ArmaturePopulate::Execute(aiScene *out) { BuildBoneStack(out->mRootNode, out->mRootNode, out, bones, bone_stack, nodes); - ASSIMP_LOG_DEBUG_F("Bone stack size: ", bone_stack.size()); + ASSIMP_LOG_DEBUG("Bone stack size: ", bone_stack.size()); for (std::pair kvp : bone_stack) { aiBone *bone = kvp.first; aiNode *bone_node = kvp.second; - ASSIMP_LOG_VERBOSE_DEBUG_F("active node lookup: ", bone->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG("active node lookup: ", bone->mName.C_Str()); // lcl transform grab - done in generate_nodes :) // bone->mOffsetMatrix = bone_node->mTransformation; @@ -179,7 +179,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *, if (node == nullptr) { node_stack.clear(); BuildNodeList(root_node, node_stack); - ASSIMP_LOG_VERBOSE_DEBUG_F("Resetting bone stack: nullptr element ", bone->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG("Resetting bone stack: nullptr element ", bone->mName.C_Str()); node = GetNodeFromStack(bone->mName, node_stack); @@ -189,7 +189,7 @@ void ArmaturePopulate::BuildBoneStack(aiNode *, } } - ASSIMP_LOG_VERBOSE_DEBUG_F("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG("Successfully added bone[", bone->mName.C_Str(), "] to stack and bone node is: ", node->mName.C_Str()); bone_stack.insert(std::pair(bone, node)); } @@ -203,7 +203,7 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node, std::vector &bone_list) { while (nullptr != bone_node) { if (!IsBoneNode(bone_node->mName, bone_list)) { - ASSIMP_LOG_VERBOSE_DEBUG_F("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); + ASSIMP_LOG_VERBOSE_DEBUG("GetArmatureRoot() Found valid armature: ", bone_node->mName.C_Str()); return bone_node; } @@ -247,7 +247,7 @@ aiNode *ArmaturePopulate::GetNodeFromStack(const aiString &node_name, } if (found != nullptr) { - ASSIMP_LOG_INFO_F("Removed node from stack: ", found->mName.C_Str()); + ASSIMP_LOG_INFO("Removed node from stack: ", found->mName.C_Str()); // now pop the element from the node list nodes.erase(iter); diff --git a/code/PostProcessing/CalcTangentsProcess.cpp b/code/PostProcessing/CalcTangentsProcess.cpp index cdafda3b6..46feff4a1 100644 --- a/code/PostProcessing/CalcTangentsProcess.cpp +++ b/code/PostProcessing/CalcTangentsProcess.cpp @@ -129,7 +129,7 @@ bool CalcTangentsProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshIndex) { return false; } if (configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV]) { - ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"), configSourceUV)); + ASSIMP_LOG_ERROR("Failed to compute tangents; need UV data in channel", configSourceUV); return false; } diff --git a/code/PostProcessing/DeboneProcess.cpp b/code/PostProcessing/DeboneProcess.cpp index b5ed66268..3783bb65c 100644 --- a/code/PostProcessing/DeboneProcess.cpp +++ b/code/PostProcessing/DeboneProcess.cpp @@ -148,7 +148,7 @@ void DeboneProcess::Execute( aiScene* pScene) } if(!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_INFO_F("Removed %u bones. Input bones:", in - out, ". Output bones: ", out); + ASSIMP_LOG_INFO("Removed %u bones. Input bones:", in - out, ". Output bones: ", out); } // and destroy the source mesh. It should be completely contained inside the new submeshes diff --git a/code/PostProcessing/EmbedTexturesProcess.cpp b/code/PostProcessing/EmbedTexturesProcess.cpp index dc304ff9c..7e435e556 100644 --- a/code/PostProcessing/EmbedTexturesProcess.cpp +++ b/code/PostProcessing/EmbedTexturesProcess.cpp @@ -93,7 +93,7 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) { } } - ASSIMP_LOG_INFO_F("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." ); + ASSIMP_LOG_INFO("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." ); } bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { @@ -103,7 +103,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { // Test path directly std::ifstream file(imagePath, std::ios::binary | std::ios::ate); if ((imageSize = file.tellg()) == std::streampos(-1)) { - ASSIMP_LOG_WARN_F("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder."); + ASSIMP_LOG_WARN("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder."); // Test path in root path imagePath = mRootPath + path; @@ -113,7 +113,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const { imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u); file.open(imagePath, std::ios::binary | std::ios::ate); if ((imageSize = file.tellg()) == std::streampos(-1)) { - ASSIMP_LOG_ERROR_F("EmbedTexturesProcess: Unable to embed texture: ", path, "."); + ASSIMP_LOG_ERROR("EmbedTexturesProcess: Unable to embed texture: ", path, "."); return false; } } diff --git a/code/PostProcessing/FindDegenerates.cpp b/code/PostProcessing/FindDegenerates.cpp index 1fc58cf59..eae91ff02 100644 --- a/code/PostProcessing/FindDegenerates.cpp +++ b/code/PostProcessing/FindDegenerates.cpp @@ -291,7 +291,7 @@ evil_jump_outside: } if (deg && !DefaultLogger::isNullLogger()) { - ASSIMP_LOG_WARN_F( "Found ", deg, " degenerated primitives"); + ASSIMP_LOG_WARN( "Found ", deg, " degenerated primitives"); } return false; } diff --git a/code/PostProcessing/FindInstancesProcess.cpp b/code/PostProcessing/FindInstancesProcess.cpp index 98527e531..ab5f52b78 100644 --- a/code/PostProcessing/FindInstancesProcess.cpp +++ b/code/PostProcessing/FindInstancesProcess.cpp @@ -267,7 +267,7 @@ void FindInstancesProcess::Execute( aiScene* pScene) // write to log if (!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_INFO_F( "FindInstancesProcess finished. Found ", (pScene->mNumMeshes - numMeshesOut), " instances" ); + ASSIMP_LOG_INFO( "FindInstancesProcess finished. Found ", (pScene->mNumMeshes - numMeshesOut), " instances" ); } pScene->mNumMeshes = numMeshesOut; } else { diff --git a/code/PostProcessing/FindInvalidDataProcess.cpp b/code/PostProcessing/FindInvalidDataProcess.cpp index 9c19c606a..ea7d99094 100644 --- a/code/PostProcessing/FindInvalidDataProcess.cpp +++ b/code/PostProcessing/FindInvalidDataProcess.cpp @@ -200,7 +200,7 @@ inline bool ProcessArray(T *&in, unsigned int num, const char *name, const std::vector &dirtyMask, bool mayBeIdentical = false, bool mayBeZero = true) { const char *err = ValidateArrayContents(in, num, dirtyMask, mayBeIdentical, mayBeZero); if (err) { - ASSIMP_LOG_ERROR_F("FindInvalidDataProcess fails on mesh ", name, ": ", err); + ASSIMP_LOG_ERROR("FindInvalidDataProcess fails on mesh ", name, ": ", err); delete[] in; in = nullptr; return true; diff --git a/code/PostProcessing/FixNormalsStep.cpp b/code/PostProcessing/FixNormalsStep.cpp index 850da5e25..09b1f1908 100644 --- a/code/PostProcessing/FixNormalsStep.cpp +++ b/code/PostProcessing/FixNormalsStep.cpp @@ -164,7 +164,7 @@ bool FixInfacingNormalsProcess::ProcessMesh( aiMesh* pcMesh, unsigned int index) // now compare the volumes of the bounding boxes if (std::fabs(fDelta0_x * fDelta0_y * fDelta0_z) < std::fabs(fDelta1_x * fDelta1_yz)) { if (!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_INFO_F("Mesh ", index, ": Normals are facing inwards (or the mesh is planar)", index); + ASSIMP_LOG_INFO("Mesh ", index, ": Normals are facing inwards (or the mesh is planar)", index); } // Invert normals diff --git a/code/PostProcessing/ImproveCacheLocality.cpp b/code/PostProcessing/ImproveCacheLocality.cpp index 38d5c5a5b..3243c40b4 100644 --- a/code/PostProcessing/ImproveCacheLocality.cpp +++ b/code/PostProcessing/ImproveCacheLocality.cpp @@ -109,7 +109,7 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene) { } if (!DefaultLogger::isNullLogger()) { if (numf > 0) { - ASSIMP_LOG_INFO_F("Cache relevant are ", numm, " meshes (", numf, " faces). Average output ACMR is ", out / numf); + ASSIMP_LOG_INFO("Cache relevant are ", numm, " meshes (", numf, " faces). Average output ACMR is ", out / numf); } ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess finished. "); } @@ -355,7 +355,7 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me // very intense verbose logging ... prepare for much text if there are many meshes if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { - ASSIMP_LOG_VERBOSE_DEBUG_F("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f); + ASSIMP_LOG_VERBOSE_DEBUG("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f); } fACMR2 *= pMesh->mNumFaces; diff --git a/code/PostProcessing/JoinVerticesProcess.cpp b/code/PostProcessing/JoinVerticesProcess.cpp index 22b399471..60c64f3bf 100644 --- a/code/PostProcessing/JoinVerticesProcess.cpp +++ b/code/PostProcessing/JoinVerticesProcess.cpp @@ -100,7 +100,7 @@ void JoinVerticesProcess::Execute( aiScene* pScene) if (iNumOldVertices == iNumVertices) { ASSIMP_LOG_DEBUG("JoinVerticesProcess finished "); } else { - ASSIMP_LOG_INFO_F("JoinVerticesProcess finished | Verts in: ", iNumOldVertices, + ASSIMP_LOG_INFO("JoinVerticesProcess finished | Verts in: ", iNumOldVertices, " out: ", iNumVertices, " | ~", ((iNumOldVertices - iNumVertices) / (float)iNumOldVertices) * 100.f ); } @@ -373,7 +373,7 @@ int JoinVerticesProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex) } if (!DefaultLogger::isNullLogger() && DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { - ASSIMP_LOG_VERBOSE_DEBUG_F( + ASSIMP_LOG_VERBOSE_DEBUG( "Mesh ",meshIndex, " (", (pMesh->mName.length ? pMesh->mName.data : "unnamed"), diff --git a/code/PostProcessing/LimitBoneWeightsProcess.cpp b/code/PostProcessing/LimitBoneWeightsProcess.cpp index c7ecf1b00..fb8b49b91 100644 --- a/code/PostProcessing/LimitBoneWeightsProcess.cpp +++ b/code/PostProcessing/LimitBoneWeightsProcess.cpp @@ -191,6 +191,6 @@ void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh) pMesh->mNumBones = writeBone; if (!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones); + ASSIMP_LOG_INFO("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones); } } diff --git a/code/PostProcessing/OptimizeGraph.cpp b/code/PostProcessing/OptimizeGraph.cpp index ad49b635a..e33c2ab18 100644 --- a/code/PostProcessing/OptimizeGraph.cpp +++ b/code/PostProcessing/OptimizeGraph.cpp @@ -335,7 +335,7 @@ void OptimizeGraphProcess::Execute(aiScene *pScene) { pScene->mRootNode->mParent = nullptr; if (!DefaultLogger::isNullLogger()) { if (nodes_in != nodes_out) { - ASSIMP_LOG_INFO_F("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out); + ASSIMP_LOG_INFO("OptimizeGraphProcess finished; Input nodes: ", nodes_in, ", Output nodes: ", nodes_out); } else { ASSIMP_LOG_DEBUG("OptimizeGraphProcess finished"); } diff --git a/code/PostProcessing/OptimizeMeshes.cpp b/code/PostProcessing/OptimizeMeshes.cpp index dd81644de..939284ee4 100644 --- a/code/PostProcessing/OptimizeMeshes.cpp +++ b/code/PostProcessing/OptimizeMeshes.cpp @@ -151,7 +151,7 @@ void OptimizeMeshesProcess::Execute( aiScene* pScene) std::copy(output.begin(),output.end(),mScene->mMeshes); if (output.size() != num_old) { - ASSIMP_LOG_DEBUG_F("OptimizeMeshesProcess finished. Input meshes: ", num_old, ", Output meshes: ", pScene->mNumMeshes); + ASSIMP_LOG_DEBUG("OptimizeMeshesProcess finished. Input meshes: ", num_old, ", Output meshes: ", pScene->mNumMeshes); } else { ASSIMP_LOG_DEBUG( "OptimizeMeshesProcess finished" ); } diff --git a/code/PostProcessing/PretransformVertices.cpp b/code/PostProcessing/PretransformVertices.cpp index d1740f30b..e9a3af0d2 100644 --- a/code/PostProcessing/PretransformVertices.cpp +++ b/code/PostProcessing/PretransformVertices.cpp @@ -429,7 +429,7 @@ void PretransformVertices::Execute(aiScene *pScene) { const unsigned int iOldNodes = CountNodes(pScene->mRootNode); if (configTransform) { - pScene->mRootNode->mTransformation = configTransformation; + pScene->mRootNode->mTransformation = configTransformation * pScene->mRootNode->mTransformation; } // first compute absolute transformation matrices for all nodes @@ -680,9 +680,9 @@ void PretransformVertices::Execute(aiScene *pScene) { if (!DefaultLogger::isNullLogger()) { ASSIMP_LOG_DEBUG("PretransformVerticesProcess finished"); - ASSIMP_LOG_INFO_F("Removed ", iOldNodes, " nodes and ", iOldAnimationChannels, " animation channels (", + ASSIMP_LOG_INFO("Removed ", iOldNodes, " nodes and ", iOldAnimationChannels, " animation channels (", CountNodes(pScene->mRootNode), " output nodes)"); - ASSIMP_LOG_INFO_F("Kept ", pScene->mNumLights, " lights and ", pScene->mNumCameras, " cameras."); - ASSIMP_LOG_INFO_F("Moved ", iOldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")"); + ASSIMP_LOG_INFO("Kept ", pScene->mNumLights, " lights and ", pScene->mNumCameras, " cameras."); + ASSIMP_LOG_INFO("Moved ", iOldMeshes, " meshes to WCS (number of output meshes: ", pScene->mNumMeshes, ")"); } } diff --git a/code/PostProcessing/RemoveRedundantMaterials.cpp b/code/PostProcessing/RemoveRedundantMaterials.cpp index 5264d3608..c252f37a5 100644 --- a/code/PostProcessing/RemoveRedundantMaterials.cpp +++ b/code/PostProcessing/RemoveRedundantMaterials.cpp @@ -122,7 +122,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) // Keep this material even if no mesh references it abReferenced[i] = true; - ASSIMP_LOG_VERBOSE_DEBUG_F( "Found positive match in exclusion list: \'", name.data, "\'"); + ASSIMP_LOG_VERBOSE_DEBUG( "Found positive match in exclusion list: \'", name.data, "\'"); } } } @@ -215,7 +215,7 @@ void RemoveRedundantMatsProcess::Execute( aiScene* pScene) } else { - ASSIMP_LOG_INFO_F("RemoveRedundantMatsProcess finished. Removed ", redundantRemoved, " redundant and ", + ASSIMP_LOG_INFO("RemoveRedundantMatsProcess finished. Removed ", redundantRemoved, " redundant and ", unreferencedRemoved, " unused materials."); } } diff --git a/code/PostProcessing/SplitByBoneCountProcess.cpp b/code/PostProcessing/SplitByBoneCountProcess.cpp index 1f4170a6a..2613d8561 100644 --- a/code/PostProcessing/SplitByBoneCountProcess.cpp +++ b/code/PostProcessing/SplitByBoneCountProcess.cpp @@ -103,7 +103,7 @@ void SplitByBoneCountProcess::Execute( aiScene* pScene) if( !isNecessary ) { - ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess early-out: no meshes with more than " << mMaxBoneCount << " bones." ); + ASSIMP_LOG_DEBUG("SplitByBoneCountProcess early-out: no meshes with more than ", mMaxBoneCount, " bones." ); return; } @@ -151,7 +151,7 @@ void SplitByBoneCountProcess::Execute( aiScene* pScene) // recurse through all nodes and translate the node's mesh indices to fit the new mesh array UpdateNode( pScene->mRootNode); - ASSIMP_LOG_DEBUG( format() << "SplitByBoneCountProcess end: split " << mSubMeshIndices.size() << " meshes into " << meshes.size() << " submeshes." ); + ASSIMP_LOG_DEBUG( "SplitByBoneCountProcess end: split ", mSubMeshIndices.size(), " meshes into ", meshes.size(), " submeshes." ); } // ------------------------------------------------------------------------------------------------ diff --git a/code/PostProcessing/TextureTransform.cpp b/code/PostProcessing/TextureTransform.cpp index a2f20a082..681b047c0 100644 --- a/code/PostProcessing/TextureTransform.cpp +++ b/code/PostProcessing/TextureTransform.cpp @@ -108,7 +108,7 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info) if (rounded) { out -= rounded * static_cast(AI_MATH_PI); - ASSIMP_LOG_INFO_F("Texture coordinate rotation ", info.mRotation, " can be simplified to ", out); + ASSIMP_LOG_INFO("Texture coordinate rotation ", info.mRotation, " can be simplified to ", out); } // Next step - convert negative rotation angles to positives @@ -448,7 +448,7 @@ void TextureTransformStep::Execute( aiScene* pScene) if (size > AI_MAX_NUMBER_OF_TEXTURECOORDS) { if (!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_ERROR_F(static_cast(trafo.size()), " UV channels required but just ", + ASSIMP_LOG_ERROR(static_cast(trafo.size()), " UV channels required but just ", AI_MAX_NUMBER_OF_TEXTURECOORDS, " available"); } size = AI_MAX_NUMBER_OF_TEXTURECOORDS; @@ -557,7 +557,7 @@ void TextureTransformStep::Execute( aiScene* pScene) if (!DefaultLogger::isNullLogger()) { if (transformedChannels) { - ASSIMP_LOG_INFO_F("TransformUVCoordsProcess end: ", outChannels, " output channels (in: ", inChannels, ", modified: ", transformedChannels,")"); + ASSIMP_LOG_INFO("TransformUVCoordsProcess end: ", outChannels, " output channels (in: ", inChannels, ", modified: ", transformedChannels,")"); } else { ASSIMP_LOG_DEBUG("TransformUVCoordsProcess finished"); } diff --git a/code/PostProcessing/ValidateDataStructure.cpp b/code/PostProcessing/ValidateDataStructure.cpp index 3058ca6ce..6a872ef11 100644 --- a/code/PostProcessing/ValidateDataStructure.cpp +++ b/code/PostProcessing/ValidateDataStructure.cpp @@ -99,7 +99,7 @@ void ValidateDSProcess::ReportWarning(const char *msg, ...) { ai_assert(iLen > 0); va_end(args); - ASSIMP_LOG_WARN("Validation warning: " + std::string(szBuffer, iLen)); + ASSIMP_LOG_WARN("Validation warning: ", std::string(szBuffer, iLen)); } // ------------------------------------------------------------------------------------------------ diff --git a/contrib/draco/src/draco/io/parser_utils.cc b/contrib/draco/src/draco/io/parser_utils.cc index 753a1b314..4f95f6f84 100644 --- a/contrib/draco/src/draco/io/parser_utils.cc +++ b/contrib/draco/src/draco/io/parser_utils.cc @@ -252,7 +252,7 @@ DecoderBuffer ParseLineIntoDecoderBuffer(DecoderBuffer *buffer) { std::string ToLower(const std::string &str) { std::string out; - std::transform(str.begin(), str.end(), std::back_inserter(out), tolower); + std::transform(str.begin(), str.end(), std::back_inserter(out), [](unsigned char c){return tolower(c);}); return out; } diff --git a/contrib/draco/src/draco/io/ply_reader.cc b/contrib/draco/src/draco/io/ply_reader.cc index ea7f2689a..cb32df225 100644 --- a/contrib/draco/src/draco/io/ply_reader.cc +++ b/contrib/draco/src/draco/io/ply_reader.cc @@ -268,14 +268,14 @@ std::vector PlyReader::SplitWords(const std::string &line) { while ((end = line.find_first_of(" \t\n\v\f\r", start)) != std::string::npos) { const std::string word(line.substr(start, end - start)); - if (!std::all_of(word.begin(), word.end(), isspace)) { + if (!std::all_of(word.begin(), word.end(), [](unsigned char c){return isspace(c);})) { output.push_back(word); } start = end + 1; } const std::string last_word(line.substr(start)); - if (!std::all_of(last_word.begin(), last_word.end(), isspace)) { + if (!std::all_of(last_word.begin(), last_word.end(), [](unsigned char c){return isspace(c);})) { output.push_back(last_word); } return output; diff --git a/contrib/gtest/include/gtest/internal/gtest-param-util.h b/contrib/gtest/include/gtest/internal/gtest-param-util.h index 82cab9b02..9d725a433 100644 --- a/contrib/gtest/include/gtest/internal/gtest-param-util.h +++ b/contrib/gtest/include/gtest/internal/gtest-param-util.h @@ -644,7 +644,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase { // Check for invalid characters for (std::string::size_type index = 0; index < name.size(); ++index) { - if (!isalnum(name[index]) && name[index] != '_') + if (!IsAlNum(name[index]) && name[index] != '_') return false; } diff --git a/contrib/openddlparser/code/OpenDDLParser.cpp b/contrib/openddlparser/code/OpenDDLParser.cpp index 024c26f41..6a9f802ec 100644 --- a/contrib/openddlparser/code/OpenDDLParser.cpp +++ b/contrib/openddlparser/code/OpenDDLParser.cpp @@ -72,13 +72,15 @@ const char *getTypeToken(Value::ValueType type) { } static void logInvalidTokenError(char *in, const std::string &exp, OpenDDLParser::logCallback callback) { - std::stringstream stream; - stream << "Invalid token \"" << *in << "\"" - << " expected \"" << exp << "\"" << std::endl; - std::string full(in); - std::string part(full.substr(0, 50)); - stream << part; - callback(ddl_error_msg, stream.str()); + if (callback) { + std::string full(in); + std::string part(full.substr(0, 50)); + std::stringstream stream; + stream << "Invalid token \"" << *in << "\" " + << "(expected \"" << exp << "\") " + << "in: \"" << part << "\""; + callback(ddl_error_msg, stream.str()); + } } static bool isIntegerType(Value::ValueType integerType) { @@ -111,26 +113,8 @@ static DDLNode *createDDLNode(Text *id, OpenDDLParser *parser) { return node; } -static void logMessage(LogSeverity severity, const std::string &msg) { - std::string log; - if (ddl_debug_msg == severity) { - log += "Debug:"; - } else if (ddl_info_msg == severity) { - log += "Info :"; - } else if (ddl_warn_msg == severity) { - log += "Warn :"; - } else if (ddl_error_msg == severity) { - log += "Error:"; - } else { - log += "None :"; - } - - log += msg; - std::cout << log; -} - OpenDDLParser::OpenDDLParser() : - m_logCallback(logMessage), + m_logCallback(nullptr), m_buffer(), m_stack(), m_context(nullptr) { @@ -138,7 +122,7 @@ OpenDDLParser::OpenDDLParser() : } OpenDDLParser::OpenDDLParser(const char *buffer, size_t len) : - m_logCallback(&logMessage), m_buffer(), m_context(nullptr) { + m_logCallback(nullptr), m_buffer(), m_context(nullptr) { if (0 != len) { setBuffer(buffer, len); } @@ -149,13 +133,8 @@ OpenDDLParser::~OpenDDLParser() { } void OpenDDLParser::setLogCallback(logCallback callback) { - if (nullptr != callback) { - // install user-specific log callback - m_logCallback = callback; - } else { - // install default log callback - m_logCallback = &logMessage; - } + // install user-specific log callback; null = no log callback + m_logCallback = callback; } OpenDDLParser::logCallback OpenDDLParser::getLogCallback() const { diff --git a/contrib/pugixml/readme.txt b/contrib/pugixml/readme.txt index 5beb08a90..bfb1875cb 100644 --- a/contrib/pugixml/readme.txt +++ b/contrib/pugixml/readme.txt @@ -1,7 +1,7 @@ -pugixml 1.9 - an XML processing library +pugixml 1.11 - an XML processing library -Copyright (C) 2006-2018, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) -Report bugs and download new versions at http://pugixml.org/ +Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) +Report bugs and download new versions at https://pugixml.org/ This is the distribution of pugixml, which is a C++ XML processing library, which consists of a DOM-like interface with rich traversal/modification @@ -13,8 +13,6 @@ automatically during parsing/saving). The distribution contains the following folders: - contrib/ - various contributions to pugixml - docs/ - documentation docs/samples - pugixml usage examples docs/quickstart.html - quick start guide @@ -28,7 +26,7 @@ The distribution contains the following folders: This library is distributed under the MIT License: -Copyright (c) 2006-2018 Arseny Kapoulkine +Copyright (c) 2006-2019 Arseny Kapoulkine Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation diff --git a/contrib/pugixml/src/pugiconfig.hpp b/contrib/pugixml/src/pugiconfig.hpp index 065b3c8bb..03f854bf1 100644 --- a/contrib/pugixml/src/pugiconfig.hpp +++ b/contrib/pugixml/src/pugiconfig.hpp @@ -1,8 +1,8 @@ /** - * pugixml parser - version 1.9 + * pugixml parser - version 1.11 * -------------------------------------------------------- - * Copyright (C) 2006-2018, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ + * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end * of this file. @@ -30,10 +30,8 @@ // #define PUGIXML_NO_EXCEPTIONS // Set this to control attributes for public classes/functions, i.e.: -//#ifdef _WIN32 -//#define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL -//#define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL -//#endif +// #define PUGIXML_API __declspec(dllexport) // to export all public symbols from DLL +// #define PUGIXML_CLASS __declspec(dllimport) // to import all classes from DLL // #define PUGIXML_FUNCTION __fastcall // to set calling conventions to all public functions to fastcall // In absence of PUGIXML_CLASS/PUGIXML_FUNCTION definitions PUGIXML_API is used instead @@ -42,16 +40,19 @@ // #define PUGIXML_MEMORY_OUTPUT_STACK 10240 // #define PUGIXML_MEMORY_XPATH_PAGE_SIZE 4096 +// Tune this constant to adjust max nesting for XPath queries +// #define PUGIXML_XPATH_DEPTH_LIMIT 1024 + // Uncomment this to switch to header-only version #define PUGIXML_HEADER_ONLY // Uncomment this to enable long long support -//#define PUGIXML_HAS_LONG_LONG +// #define PUGIXML_HAS_LONG_LONG #endif /** - * Copyright (c) 2006-2018 Arseny Kapoulkine + * Copyright (c) 2006-2020 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/contrib/pugixml/src/pugixml.cpp b/contrib/pugixml/src/pugixml.cpp index 2afff09dd..efdcdf699 100644 --- a/contrib/pugixml/src/pugixml.cpp +++ b/contrib/pugixml/src/pugixml.cpp @@ -1,8 +1,8 @@ /** - * pugixml parser - version 1.9 + * pugixml parser - version 1.11 * -------------------------------------------------------- - * Copyright (C) 2006-2018, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ + * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end * of this file. @@ -378,7 +378,7 @@ PUGI__NS_BEGIN static PUGI__UNSIGNED_OVERFLOW unsigned int hash(const void* key) { - unsigned int h = static_cast(reinterpret_cast(key)); + unsigned int h = static_cast(reinterpret_cast(key) & 0xffffffff); // MurmurHash3 32-bit finalizer h ^= h >> 16; @@ -1861,7 +1861,7 @@ PUGI__NS_BEGIN enum chartypex_t { ctx_special_pcdata = 1, // Any symbol >= 0 and < 32 (except \t, \r, \n), &, <, > - ctx_special_attr = 2, // Any symbol >= 0 and < 32 (except \t), &, <, >, " + ctx_special_attr = 2, // Any symbol >= 0 and < 32, &, <, ", ' ctx_start_symbol = 4, // Any symbol > 127, a-z, A-Z, _ ctx_digit = 8, // 0-9 ctx_symbol = 16 // Any symbol > 127, a-z, A-Z, 0-9, _, -, . @@ -1869,10 +1869,10 @@ PUGI__NS_BEGIN static const unsigned char chartypex_table[256] = { - 3, 3, 3, 3, 3, 3, 3, 3, 3, 0, 2, 3, 3, 2, 3, 3, // 0-15 + 3, 3, 3, 3, 3, 3, 3, 3, 3, 2, 2, 3, 3, 2, 3, 3, // 0-15 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 16-31 - 0, 0, 2, 0, 0, 0, 3, 0, 0, 0, 0, 0, 0, 16, 16, 0, // 32-47 - 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 3, 0, // 48-63 + 0, 0, 2, 0, 0, 0, 3, 2, 0, 0, 0, 0, 0, 16, 16, 0, // 32-47 + 24, 24, 24, 24, 24, 24, 24, 24, 24, 24, 0, 0, 3, 0, 1, 0, // 48-63 0, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, // 64-79 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 0, 0, 0, 0, 20, // 80-95 @@ -2709,7 +2709,7 @@ PUGI__NS_BEGIN { PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_trim_pcdata == 0x0800); - switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4)) // get bitmask for flags (eol escapes trim) + switch (((optmask >> 4) & 3) | ((optmask >> 9) & 4)) // get bitmask for flags (trim eol escapes); this simultaneously checks 3 options from assertion above { case 0: return strconv_pcdata_impl::parse; case 1: return strconv_pcdata_impl::parse; @@ -2878,7 +2878,7 @@ PUGI__NS_BEGIN { PUGI__STATIC_ASSERT(parse_escapes == 0x10 && parse_eol == 0x20 && parse_wconv_attribute == 0x40 && parse_wnorm_attribute == 0x80); - switch ((optmask >> 4) & 15) // get bitmask for flags (wconv wnorm eol escapes) + switch ((optmask >> 4) & 15) // get bitmask for flags (wnorm wconv eol escapes); this simultaneously checks 4 options from assertion above { case 0: return strconv_attribute_impl::parse_simple; case 1: return strconv_attribute_impl::parse_simple; @@ -3903,7 +3903,7 @@ PUGI__NS_BEGIN xml_encoding encoding; }; - PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type) + PUGI__FN void text_output_escaped(xml_buffered_writer& writer, const char_t* s, chartypex_t type, unsigned int flags) { while (*s) { @@ -3930,7 +3930,17 @@ PUGI__NS_BEGIN ++s; break; case '"': - writer.write('&', 'q', 'u', 'o', 't', ';'); + if (flags & format_attribute_single_quote) + writer.write('"'); + else + writer.write('&', 'q', 'u', 'o', 't', ';'); + ++s; + break; + case '\'': + if (flags & format_attribute_single_quote) + writer.write('&', 'a', 'p', 'o', 's', ';'); + else + writer.write('\''); ++s; break; default: // s is not a usual symbol @@ -3938,7 +3948,8 @@ PUGI__NS_BEGIN unsigned int ch = static_cast(*s++); assert(ch < 32); - writer.write('&', '#', static_cast((ch / 10) + '0'), static_cast((ch % 10) + '0'), ';'); + if (!(flags & format_skip_control_chars)) + writer.write('&', '#', static_cast((ch / 10) + '0'), static_cast((ch % 10) + '0'), ';'); } } } @@ -3949,7 +3960,7 @@ PUGI__NS_BEGIN if (flags & format_no_escapes) writer.write_string(s); else - text_output_escaped(writer, s, type); + text_output_escaped(writer, s, type, flags); } PUGI__FN void text_output_cdata(xml_buffered_writer& writer, const char_t* s) @@ -4063,6 +4074,7 @@ PUGI__NS_BEGIN PUGI__FN void node_output_attributes(xml_buffered_writer& writer, xml_node_struct* node, const char_t* indent, size_t indent_length, unsigned int flags, unsigned int depth) { const char_t* default_name = PUGIXML_TEXT(":anonymous"); + const char_t enquotation_char = (flags & format_attribute_single_quote) ? '\'' : '"'; for (xml_attribute_struct* a = node->first_attribute; a; a = a->next_attribute) { @@ -4078,12 +4090,12 @@ PUGI__NS_BEGIN } writer.write_string(a->name ? a->name + 0 : default_name); - writer.write('=', '"'); + writer.write('=', enquotation_char); if (a->value) text_output(writer, a->value, ctx_special_attr, flags); - writer.write('"'); + writer.write(enquotation_char); } } @@ -4423,6 +4435,9 @@ PUGI__NS_BEGIN while (sit && sit != sn) { + // loop invariant: dit is inside the subtree rooted at dn + assert(dit); + // when a tree is copied into one of the descendants, we need to skip that subtree to avoid an infinite loop if (sit != dn) { @@ -4452,9 +4467,14 @@ PUGI__NS_BEGIN sit = sit->parent; dit = dit->parent; + + // loop invariant: dit is inside the subtree rooted at dn while sit is inside sn + assert(sit == sn || dit); } while (sit != sn); } + + assert(!sit || dit == dn->parent); } PUGI__FN void node_copy_attribute(xml_attribute_struct* da, xml_attribute_struct* sa) @@ -4653,19 +4673,19 @@ PUGI__NS_BEGIN } template - PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, float value) + PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, float value, int precision) { char buf[128]; - PUGI__SNPRINTF(buf, "%.9g", value); + PUGI__SNPRINTF(buf, "%.*g", precision, double(value)); return set_value_ascii(dest, header, header_mask, buf); } template - PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, double value) + PUGI__FN bool set_value_convert(String& dest, Header& header, uintptr_t header_mask, double value, int precision) { char buf[128]; - PUGI__SNPRINTF(buf, "%.17g", value); + PUGI__SNPRINTF(buf, "%.*g", precision, value); return set_value_ascii(dest, header, header_mask, buf); } @@ -4688,6 +4708,7 @@ PUGI__NS_BEGIN char_t* buffer = 0; size_t length = 0; + // coverity[var_deref_model] if (!impl::convert_buffer(buffer, length, buffer_encoding, contents, size, is_mutable)) return impl::make_parse_result(status_out_of_memory); // delete original buffer if we performed a conversion @@ -4960,7 +4981,12 @@ PUGI__NS_BEGIN #if defined(PUGI__MSVC_CRT_VERSION) || defined(__BORLANDC__) || (defined(__MINGW32__) && (!defined(__STRICT_ANSI__) || defined(__MINGW64_VERSION_MAJOR))) PUGI__FN FILE* open_file_wide(const wchar_t* path, const wchar_t* mode) { +#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 + FILE* file = 0; + return _wfopen_s(&file, path, mode) == 0 ? file : 0; +#else return _wfopen(path, mode); +#endif } #else PUGI__FN char* convert_path_heap(const wchar_t* str) @@ -5004,6 +5030,16 @@ PUGI__NS_BEGIN } #endif + PUGI__FN FILE* open_file(const char* path, const char* mode) + { +#if defined(PUGI__MSVC_CRT_VERSION) && PUGI__MSVC_CRT_VERSION >= 1400 + FILE* file = 0; + return fopen_s(&file, path, mode) == 0 ? file : 0; +#else + return fopen(path, mode); +#endif + } + PUGI__FN bool save_file_impl(const xml_document& doc, FILE* file, const char_t* indent, unsigned int flags, xml_encoding encoding) { if (!file) return false; @@ -5329,14 +5365,28 @@ namespace pugi { if (!_attr) return false; - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, default_double_precision); + } + + PUGI__FN bool xml_attribute::set_value(double rhs, int precision) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, precision); } PUGI__FN bool xml_attribute::set_value(float rhs) { if (!_attr) return false; - return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs); + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, default_float_precision); + } + + PUGI__FN bool xml_attribute::set_value(float rhs, int precision) + { + if (!_attr) return false; + + return impl::set_value_convert(_attr->value, _attr->header, impl::xml_memory_page_value_allocated_mask, rhs, precision); } PUGI__FN bool xml_attribute::set_value(bool rhs) @@ -6046,6 +6096,27 @@ namespace pugi return true; } + PUGI__FN bool xml_node::remove_attributes() + { + if (!_root) return false; + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return false; + + for (xml_attribute_struct* attr = _root->first_attribute; attr; ) + { + xml_attribute_struct* next = attr->next_attribute; + + impl::destroy_attribute(attr, alloc); + + attr = next; + } + + _root->first_attribute = 0; + + return true; + } + PUGI__FN bool xml_node::remove_child(const char_t* name_) { return remove_child(child(name_)); @@ -6064,6 +6135,27 @@ namespace pugi return true; } + PUGI__FN bool xml_node::remove_children() + { + if (!_root) return false; + + impl::xml_allocator& alloc = impl::get_allocator(_root); + if (!alloc.reserve()) return false; + + for (xml_node_struct* cur = _root->first_child; cur; ) + { + xml_node_struct* next = cur->next_sibling; + + impl::destroy_node(cur, alloc); + + cur = next; + } + + _root->first_child = 0; + + return true; + } + PUGI__FN xml_parse_result xml_node::append_buffer(const void* contents, size_t size, unsigned int options, xml_encoding encoding) { // append_buffer is only valid for elements/documents @@ -6164,16 +6256,9 @@ namespace pugi PUGI__FN xml_node xml_node::first_element_by_path(const char_t* path_, char_t delimiter) const { - xml_node found = *this; // Current search context. + xml_node context = path_[0] == delimiter ? root() : *this; - if (!_root || !path_[0]) return found; - - if (path_[0] == delimiter) - { - // Absolute path; e.g. '/foo/bar' - found = found.root(); - ++path_; - } + if (!context._root) return xml_node(); const char_t* path_segment = path_; @@ -6183,19 +6268,19 @@ namespace pugi while (*path_segment_end && *path_segment_end != delimiter) ++path_segment_end; - if (path_segment == path_segment_end) return found; + if (path_segment == path_segment_end) return context; const char_t* next_segment = path_segment_end; while (*next_segment == delimiter) ++next_segment; if (*path_segment == '.' && path_segment + 1 == path_segment_end) - return found.first_element_by_path(next_segment, delimiter); + return context.first_element_by_path(next_segment, delimiter); else if (*path_segment == '.' && *(path_segment+1) == '.' && path_segment + 2 == path_segment_end) - return found.parent().first_element_by_path(next_segment, delimiter); + return context.parent().first_element_by_path(next_segment, delimiter); else { - for (xml_node_struct* j = found._root->first_child; j; j = j->next_sibling) + for (xml_node_struct* j = context._root->first_child; j; j = j->next_sibling) { if (j->name && impl::strequalrange(j->name, path_segment, static_cast(path_segment_end - path_segment))) { @@ -6490,14 +6575,28 @@ namespace pugi { xml_node_struct* dn = _data_new(); - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, default_float_precision) : false; + } + + PUGI__FN bool xml_text::set(float rhs, int precision) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, precision) : false; } PUGI__FN bool xml_text::set(double rhs) { xml_node_struct* dn = _data_new(); - return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs) : false; + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, default_double_precision) : false; + } + + PUGI__FN bool xml_text::set(double rhs, int precision) + { + xml_node_struct* dn = _data_new(); + + return dn ? impl::set_value_convert(dn->value, dn->header, impl::xml_memory_page_value_allocated_mask, rhs, precision) : false; } PUGI__FN bool xml_text::set(bool rhs) @@ -6873,8 +6972,7 @@ namespace pugi { reset(); - for (xml_node cur = proto.first_child(); cur; cur = cur.next_sibling()) - append_copy(cur); + impl::node_copy_tree(_root, proto._root); } PUGI__FN void xml_document::_create() @@ -7104,7 +7202,7 @@ namespace pugi reset(); using impl::auto_deleter; // MSVC7 workaround - auto_deleter file(fopen(path_, "rb"), impl::close_file); + auto_deleter file(impl::open_file(path_, "rb"), impl::close_file); return impl::load_file_impl(static_cast(_root), file.data, options, encoding, &_buffer); } @@ -7187,7 +7285,7 @@ namespace pugi PUGI__FN bool xml_document::save_file(const char* path_, const char_t* indent, unsigned int flags, xml_encoding encoding) const { using impl::auto_deleter; // MSVC7 workaround - auto_deleter file(fopen(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file); + auto_deleter file(impl::open_file(path_, (flags & format_save_file_text) ? "w" : "wb"), impl::close_file); return impl::save_file_impl(*this, file.data, indent, flags, encoding); } @@ -7331,14 +7429,14 @@ PUGI__NS_BEGIN } }; - template void swap(T& lhs, T& rhs) + template inline void swap(T& lhs, T& rhs) { T temp = lhs; lhs = rhs; rhs = temp; } - template I min_element(I begin, I end, const Pred& pred) + template PUGI__FN I min_element(I begin, I end, const Pred& pred) { I result = begin; @@ -7349,17 +7447,20 @@ PUGI__NS_BEGIN return result; } - template void reverse(I begin, I end) + template PUGI__FN void reverse(I begin, I end) { - while (end - begin > 1) swap(*begin++, *--end); + while (end - begin > 1) + swap(*begin++, *--end); } - template I unique(I begin, I end) + template PUGI__FN I unique(I begin, I end) { // fast skip head - while (end - begin > 1 && *begin != *(begin + 1)) begin++; + while (end - begin > 1 && *begin != *(begin + 1)) + begin++; - if (begin == end) return begin; + if (begin == end) + return begin; // last written element I write = begin++; @@ -7377,7 +7478,7 @@ PUGI__NS_BEGIN return write + 1; } - template void insertion_sort(T* begin, T* end, const Pred& pred) + template PUGI__FN void insertion_sort(T* begin, T* end, const Pred& pred) { if (begin == end) return; @@ -7399,16 +7500,19 @@ PUGI__NS_BEGIN } } - template I median3(I first, I middle, I last, const Pred& pred) + template inline I median3(I first, I middle, I last, const Pred& pred) { - if (pred(*middle, *first)) swap(middle, first); - if (pred(*last, *middle)) swap(last, middle); - if (pred(*middle, *first)) swap(middle, first); + if (pred(*middle, *first)) + swap(middle, first); + if (pred(*last, *middle)) + swap(last, middle); + if (pred(*middle, *first)) + swap(middle, first); return middle; } - template void partition3(T* begin, T* end, T pivot, const Pred& pred, T** out_eqbeg, T** out_eqend) + template PUGI__FN void partition3(T* begin, T* end, T pivot, const Pred& pred, T** out_eqbeg, T** out_eqend) { // invariant: array is split into 4 groups: = < ? > (each variable denotes the boundary between the groups) T* eq = begin; @@ -7435,7 +7539,7 @@ PUGI__NS_BEGIN *out_eqend = gt; } - template void sort(I begin, I end, const Pred& pred) + template PUGI__FN void sort(I begin, I end, const Pred& pred) { // sort large chunks while (end - begin > 16) @@ -7464,6 +7568,41 @@ PUGI__NS_BEGIN // insertion sort small chunk insertion_sort(begin, end, pred); } + + PUGI__FN bool hash_insert(const void** table, size_t size, const void* key) + { + assert(key); + + unsigned int h = static_cast(reinterpret_cast(key)); + + // MurmurHash3 32-bit finalizer + h ^= h >> 16; + h *= 0x85ebca6bu; + h ^= h >> 13; + h *= 0xc2b2ae35u; + h ^= h >> 16; + + size_t hashmod = size - 1; + size_t bucket = h & hashmod; + + for (size_t probe = 0; probe <= hashmod; ++probe) + { + if (table[bucket] == 0) + { + table[bucket] = key; + return true; + } + + if (table[bucket] == key) + return false; + + // hash collision, quadratic probing + bucket = (bucket + probe + 1) & hashmod; + } + + assert(false && "Hash table is full"); // unreachable + return false; + } PUGI__NS_END // Allocator used for AST and evaluation stacks @@ -8053,15 +8192,6 @@ PUGI__NS_BEGIN } }; - struct duplicate_comparator - { - bool operator()(const xpath_node& lhs, const xpath_node& rhs) const - { - if (lhs.attribute()) return rhs.attribute() ? lhs.attribute() < rhs.attribute() : true; - else return rhs.attribute() ? false : lhs.node() < rhs.node(); - } - }; - PUGI__FN double gen_nan() { #if defined(__STDC_IEC_559__) || ((FLT_RADIX - 0 == 2) && (FLT_MAX_EXP - 0 == 128) && (FLT_MANT_DIG - 0 == 24)) @@ -8069,7 +8199,7 @@ PUGI__NS_BEGIN typedef uint32_t UI; // BCC5 workaround union { float f; UI i; } u; u.i = 0x7fc00000; - return u.f; + return double(u.f); #else // fallback const volatile double zero = 0.0; @@ -8849,12 +8979,42 @@ PUGI__NS_BEGIN _end = pos; } - void remove_duplicates() + void remove_duplicates(xpath_allocator* alloc) { - if (_type == xpath_node_set::type_unsorted) - sort(_begin, _end, duplicate_comparator()); + if (_type == xpath_node_set::type_unsorted && _end - _begin > 2) + { + xpath_allocator_capture cr(alloc); - _end = unique(_begin, _end); + size_t size_ = static_cast(_end - _begin); + + size_t hash_size = 1; + while (hash_size < size_ + size_ / 2) hash_size *= 2; + + const void** hash_data = static_cast(alloc->allocate(hash_size * sizeof(void**))); + if (!hash_data) return; + + memset(hash_data, 0, hash_size * sizeof(const void**)); + + xpath_node* write = _begin; + + for (xpath_node* it = _begin; it != _end; ++it) + { + const void* attr = it->attribute().internal_object(); + const void* node = it->node().internal_object(); + const void* key = attr ? attr : node; + + if (key && hash_insert(hash_data, hash_size, key)) + { + *write++ = *it; + } + } + + _end = write; + } + else + { + _end = unique(_begin, _end); + } } xpath_node_set::type_t type() const @@ -9611,7 +9771,7 @@ PUGI__NS_BEGIN { xpath_context c(*it, i, size); - if (expr->eval_number(c, stack) == i) + if (expr->eval_number(c, stack) == static_cast(i)) { *last++ = *it; @@ -9635,11 +9795,11 @@ PUGI__NS_BEGIN double er = expr->eval_number(c, stack); - if (er >= 1.0 && er <= size) + if (er >= 1.0 && er <= static_cast(size)) { size_t eri = static_cast(er); - if (er == eri) + if (er == static_cast(eri)) { xpath_node r = last[eri - 1]; @@ -10083,6 +10243,7 @@ PUGI__NS_BEGIN bool once = (axis == axis_attribute && _test == nodetest_name) || (!_right && eval_once(axis_type, eval)) || + // coverity[mixed_enums] (_right && !_right->_next && _right->_test == predicate_constant_one); xpath_node_set_raw ns; @@ -10115,7 +10276,7 @@ PUGI__NS_BEGIN // child, attribute and self axes always generate unique set of nodes // for other axis, if the set stayed sorted, it stayed unique because the traversal algorithms do not visit the same node twice if (axis != axis_child && axis != axis_attribute && axis != axis_self && ns.type() == xpath_node_set::type_unsorted) - ns.remove_duplicates(); + ns.remove_duplicates(stack.temp); return ns; } @@ -10275,35 +10436,38 @@ PUGI__NS_BEGIN if (_rettype == xpath_type_boolean) return _data.variable->get_boolean(); + + // variable needs to be converted to the correct type, this is handled by the fallthrough block below + break; } - // fallthrough default: - { - switch (_rettype) - { - case xpath_type_number: - return convert_number_to_boolean(eval_number(c, stack)); - - case xpath_type_string: - { - xpath_allocator_capture cr(stack.result); - - return !eval_string(c, stack).empty(); - } - - case xpath_type_node_set: - { - xpath_allocator_capture cr(stack.result); - - return !eval_node_set(c, stack, nodeset_eval_any).empty(); - } - - default: - assert(false && "Wrong expression for return type boolean"); // unreachable - return false; - } + ; } + + // none of the ast types that return the value directly matched, we need to perform type conversion + switch (_rettype) + { + case xpath_type_number: + return convert_number_to_boolean(eval_number(c, stack)); + + case xpath_type_string: + { + xpath_allocator_capture cr(stack.result); + + return !eval_string(c, stack).empty(); + } + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.result); + + return !eval_node_set(c, stack, nodeset_eval_any).empty(); + } + + default: + assert(false && "Wrong expression for return type boolean"); // unreachable + return false; } } @@ -10410,36 +10574,38 @@ PUGI__NS_BEGIN if (_rettype == xpath_type_number) return _data.variable->get_number(); + + // variable needs to be converted to the correct type, this is handled by the fallthrough block below + break; } - // fallthrough default: - { - switch (_rettype) - { - case xpath_type_boolean: - return eval_boolean(c, stack) ? 1 : 0; - - case xpath_type_string: - { - xpath_allocator_capture cr(stack.result); - - return convert_string_to_number(eval_string(c, stack).c_str()); - } - - case xpath_type_node_set: - { - xpath_allocator_capture cr(stack.result); - - return convert_string_to_number(eval_string(c, stack).c_str()); - } - - default: - assert(false && "Wrong expression for return type number"); // unreachable - return 0; - } - + ; } + + // none of the ast types that return the value directly matched, we need to perform type conversion + switch (_rettype) + { + case xpath_type_boolean: + return eval_boolean(c, stack) ? 1 : 0; + + case xpath_type_string: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(eval_string(c, stack).c_str()); + } + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.result); + + return convert_string_to_number(eval_string(c, stack).c_str()); + } + + default: + assert(false && "Wrong expression for return type number"); // unreachable + return 0; } } @@ -10596,7 +10762,7 @@ PUGI__NS_BEGIN double first = round_nearest(_right->eval_number(c, stack)); if (is_nan(first)) return xpath_string(); // NaN - else if (first >= s_length + 1) return xpath_string(); + else if (first >= static_cast(s_length + 1)) return xpath_string(); size_t pos = first < 1 ? 1 : static_cast(first); assert(1 <= pos && pos <= s_length + 1); @@ -10620,12 +10786,12 @@ PUGI__NS_BEGIN double last = first + round_nearest(_right->_next->eval_number(c, stack)); if (is_nan(first) || is_nan(last)) return xpath_string(); - else if (first >= s_length + 1) return xpath_string(); + else if (first >= static_cast(s_length + 1)) return xpath_string(); else if (first >= last) return xpath_string(); else if (last < 1) return xpath_string(); size_t pos = first < 1 ? 1 : static_cast(first); - size_t end = last >= s_length + 1 ? s_length + 1 : static_cast(last); + size_t end = last >= static_cast(s_length + 1) ? s_length + 1 : static_cast(last); assert(1 <= pos && pos <= end && end <= s_length + 1); const char_t* rbegin = s.c_str() + (pos - 1); @@ -10694,34 +10860,37 @@ PUGI__NS_BEGIN if (_rettype == xpath_type_string) return xpath_string::from_const(_data.variable->get_string()); + + // variable needs to be converted to the correct type, this is handled by the fallthrough block below + break; } - // fallthrough default: - { - switch (_rettype) - { - case xpath_type_boolean: - return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); - - case xpath_type_number: - return convert_number_to_string(eval_number(c, stack), stack.result); - - case xpath_type_node_set: - { - xpath_allocator_capture cr(stack.temp); - - xpath_stack swapped_stack = {stack.temp, stack.result}; - - xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first); - return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result); - } - - default: - assert(false && "Wrong expression for return type string"); // unreachable - return xpath_string(); - } + ; } + + // none of the ast types that return the value directly matched, we need to perform type conversion + switch (_rettype) + { + case xpath_type_boolean: + return xpath_string::from_const(eval_boolean(c, stack) ? PUGIXML_TEXT("true") : PUGIXML_TEXT("false")); + + case xpath_type_number: + return convert_number_to_string(eval_number(c, stack), stack.result); + + case xpath_type_node_set: + { + xpath_allocator_capture cr(stack.temp); + + xpath_stack swapped_stack = {stack.temp, stack.result}; + + xpath_node_set_raw ns = eval_node_set(c, swapped_stack, nodeset_eval_first); + return ns.empty() ? xpath_string() : string_value(ns.first(), stack.result); + } + + default: + assert(false && "Wrong expression for return type string"); // unreachable + return xpath_string(); } } @@ -10735,16 +10904,16 @@ PUGI__NS_BEGIN xpath_stack swapped_stack = {stack.temp, stack.result}; - xpath_node_set_raw ls = _left->eval_node_set(c, swapped_stack, eval); - xpath_node_set_raw rs = _right->eval_node_set(c, stack, eval); + xpath_node_set_raw ls = _left->eval_node_set(c, stack, eval); + xpath_node_set_raw rs = _right->eval_node_set(c, swapped_stack, eval); // we can optimize merging two sorted sets, but this is a very rare operation, so don't bother - rs.set_type(xpath_node_set::type_unsorted); + ls.set_type(xpath_node_set::type_unsorted); - rs.append(ls.begin(), ls.end(), stack.result); - rs.remove_duplicates(); + ls.append(rs.begin(), rs.end(), stack.result); + ls.remove_duplicates(stack.temp); - return rs; + return ls; } case ast_filter: @@ -10843,13 +11012,18 @@ PUGI__NS_BEGIN return ns; } + + // variable needs to be converted to the correct type, this is handled by the fallthrough block below + break; } - // fallthrough default: - assert(false && "Wrong expression for return type node set"); // unreachable - return xpath_node_set_raw(); + ; } + + // none of the ast types that return the value directly matched, but conversions to node set are invalid + assert(false && "Wrong expression for return type node set"); // unreachable + return xpath_node_set_raw(); } void optimize(xpath_allocator* alloc) @@ -10863,6 +11037,7 @@ PUGI__NS_BEGIN if (_next) _next->optimize(alloc); + // coverity[var_deref_model] optimize_self(alloc); } @@ -10871,13 +11046,14 @@ PUGI__NS_BEGIN // Rewrite [position()=expr] with [expr] // Note that this step has to go before classification to recognize [position()=1] if ((_type == ast_filter || _type == ast_predicate) && + _right && // workaround for clang static analyzer (_right is never null for ast_filter/ast_predicate) _right->_type == ast_op_equal && _right->_left->_type == ast_func_position && _right->_right->_rettype == xpath_type_number) { _right = _right->_right; } // Classify filter/predicate ops to perform various optimizations during evaluation - if (_type == ast_filter || _type == ast_predicate) + if ((_type == ast_filter || _type == ast_predicate) && _right) // workaround for clang static analyzer (_right is never null for ast_filter/ast_predicate) { assert(_test == predicate_default); @@ -10893,8 +11069,8 @@ PUGI__NS_BEGIN // The former is a full form of //foo, the latter is much faster since it executes the node test immediately // Do a similar kind of rewrite for self/descendant/descendant-or-self axes // Note that we only rewrite positionally invariant steps (//foo[1] != /descendant::foo[1]) - if (_type == ast_step && (_axis == axis_child || _axis == axis_self || _axis == axis_descendant || _axis == axis_descendant_or_self) && _left && - _left->_type == ast_step && _left->_axis == axis_descendant_or_self && _left->_test == nodetest_type_node && !_left->_right && + if (_type == ast_step && (_axis == axis_child || _axis == axis_self || _axis == axis_descendant || _axis == axis_descendant_or_self) && + _left && _left->_type == ast_step && _left->_axis == axis_descendant_or_self && _left->_test == nodetest_type_node && !_left->_right && is_posinv_step()) { if (_axis == axis_child || _axis == axis_descendant) @@ -10906,7 +11082,9 @@ PUGI__NS_BEGIN } // Use optimized lookup table implementation for translate() with constant arguments - if (_type == ast_func_translate && _right->_type == ast_string_constant && _right->_next->_type == ast_string_constant) + if (_type == ast_func_translate && + _right && // workaround for clang static analyzer (_right is never null for ast_func_translate) + _right->_type == ast_string_constant && _right->_next->_type == ast_string_constant) { unsigned char* table = translate_table_generate(alloc, _right->_data.string, _right->_next->_data.string); @@ -10919,6 +11097,8 @@ PUGI__NS_BEGIN // Use optimized path for @attr = 'value' or @attr = $value if (_type == ast_op_equal && + _left && _right && // workaround for clang static analyzer and Coverity (_left and _right are never null for ast_op_equal) + // coverity[mixed_enums] _left->_type == ast_step && _left->_axis == axis_attribute && _left->_test == nodetest_name && !_left->_left && !_left->_right && (_right->_type == ast_string_constant || (_right->_type == ast_variable && _right->_rettype == xpath_type_string))) { @@ -10978,6 +11158,14 @@ PUGI__NS_BEGIN } }; + static const size_t xpath_ast_depth_limit = + #ifdef PUGIXML_XPATH_DEPTH_LIMIT + PUGIXML_XPATH_DEPTH_LIMIT + #else + 1024 + #endif + ; + struct xpath_parser { xpath_allocator* _alloc; @@ -10990,6 +11178,8 @@ PUGI__NS_BEGIN char_t _scratch[32]; + size_t _depth; + xpath_ast_node* error(const char* message) { _result->error = message; @@ -11006,6 +11196,11 @@ PUGI__NS_BEGIN return 0; } + xpath_ast_node* error_rec() + { + return error("Exceeded maximum allowed query depth"); + } + void* alloc_node() { return _alloc->allocate(sizeof(xpath_ast_node)); @@ -11361,6 +11556,8 @@ PUGI__NS_BEGIN return error("Unrecognized function call"); _lexer.next(); + size_t old_depth = _depth; + while (_lexer.current() != lex_close_brace) { if (argc > 0) @@ -11370,6 +11567,9 @@ PUGI__NS_BEGIN _lexer.next(); } + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + xpath_ast_node* n = parse_expression(); if (!n) return 0; @@ -11382,6 +11582,8 @@ PUGI__NS_BEGIN _lexer.next(); + _depth = old_depth; + return parse_function(function, argc, args); } @@ -11398,10 +11600,15 @@ PUGI__NS_BEGIN xpath_ast_node* n = parse_primary_expression(); if (!n) return 0; + size_t old_depth = _depth; + while (_lexer.current() == lex_open_square_brace) { _lexer.next(); + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + if (n->rettype() != xpath_type_node_set) return error("Predicate has to be applied to node set"); @@ -11417,6 +11624,8 @@ PUGI__NS_BEGIN _lexer.next(); } + _depth = old_depth; + return n; } @@ -11568,12 +11777,17 @@ PUGI__NS_BEGIN xpath_ast_node* n = alloc_node(ast_step, set, axis, nt_type, nt_name_copy); if (!n) return 0; + size_t old_depth = _depth; + xpath_ast_node* last = 0; while (_lexer.current() == lex_open_square_brace) { _lexer.next(); + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + xpath_ast_node* expr = parse_expression(); if (!expr) return 0; @@ -11590,6 +11804,8 @@ PUGI__NS_BEGIN last = pred; } + _depth = old_depth; + return n; } @@ -11599,11 +11815,16 @@ PUGI__NS_BEGIN xpath_ast_node* n = parse_step(set); if (!n) return 0; + size_t old_depth = _depth; + while (_lexer.current() == lex_slash || _lexer.current() == lex_double_slash) { lexeme_t l = _lexer.current(); _lexer.next(); + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + if (l == lex_double_slash) { n = alloc_node(ast_step, n, axis_descendant_or_self, nodetest_type_node, 0); @@ -11614,6 +11835,8 @@ PUGI__NS_BEGIN if (!n) return 0; } + _depth = old_depth; + return n; } @@ -11799,6 +12022,9 @@ PUGI__NS_BEGIN { _lexer.next(); + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + xpath_ast_node* rhs = parse_path_or_unary_expression(); if (!rhs) return 0; @@ -11844,13 +12070,22 @@ PUGI__NS_BEGIN // | MultiplicativeExpr 'mod' UnaryExpr xpath_ast_node* parse_expression(int limit = 0) { + size_t old_depth = _depth; + + if (++_depth > xpath_ast_depth_limit) + return error_rec(); + xpath_ast_node* n = parse_path_or_unary_expression(); if (!n) return 0; - return parse_expression_rec(n, limit); + n = parse_expression_rec(n, limit); + + _depth = old_depth; + + return n; } - xpath_parser(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result): _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result) + xpath_parser(const char_t* query, xpath_variable_set* variables, xpath_allocator* alloc, xpath_parse_result* result): _alloc(alloc), _lexer(query), _query(query), _variables(variables), _result(result), _depth(0) { } @@ -11859,6 +12094,8 @@ PUGI__NS_BEGIN xpath_ast_node* n = parse_expression(); if (!n) return 0; + assert(_depth == 0); + // check if there are unparsed tokens left if (_lexer.current() != lex_eof) return error("Incorrect query"); @@ -12013,74 +12250,61 @@ namespace pugi size_t size_ = static_cast(end_ - begin_); - if (size_ <= 1) + // use internal buffer for 0 or 1 elements, heap buffer otherwise + xpath_node* storage = (size_ <= 1) ? _storage : static_cast(impl::xml_memory::allocate(size_ * sizeof(xpath_node))); + + if (!storage) { - // deallocate old buffer - if (_begin != &_storage) impl::xml_memory::deallocate(_begin); - - // use internal buffer - if (begin_ != end_) _storage = *begin_; - - _begin = &_storage; - _end = &_storage + size_; - _type = type_; + #ifdef PUGIXML_NO_EXCEPTIONS + return; + #else + throw std::bad_alloc(); + #endif } - else - { - // make heap copy - xpath_node* storage = static_cast(impl::xml_memory::allocate(size_ * sizeof(xpath_node))); - if (!storage) - { - #ifdef PUGIXML_NO_EXCEPTIONS - return; - #else - throw std::bad_alloc(); - #endif - } + // deallocate old buffer + if (_begin != _storage) + impl::xml_memory::deallocate(_begin); + // size check is necessary because for begin_ = end_ = nullptr, memcpy is UB + if (size_) memcpy(storage, begin_, size_ * sizeof(xpath_node)); - // deallocate old buffer - if (_begin != &_storage) impl::xml_memory::deallocate(_begin); - - // finalize - _begin = storage; - _end = storage + size_; - _type = type_; - } + _begin = storage; + _end = storage + size_; + _type = type_; } #ifdef PUGIXML_HAS_MOVE PUGI__FN void xpath_node_set::_move(xpath_node_set& rhs) PUGIXML_NOEXCEPT { _type = rhs._type; - _storage = rhs._storage; - _begin = (rhs._begin == &rhs._storage) ? &_storage : rhs._begin; + _storage[0] = rhs._storage[0]; + _begin = (rhs._begin == rhs._storage) ? _storage : rhs._begin; _end = _begin + (rhs._end - rhs._begin); rhs._type = type_unsorted; - rhs._begin = &rhs._storage; - rhs._end = rhs._begin; + rhs._begin = rhs._storage; + rhs._end = rhs._storage; } #endif - PUGI__FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(&_storage), _end(&_storage) + PUGI__FN xpath_node_set::xpath_node_set(): _type(type_unsorted), _begin(_storage), _end(_storage) { } - PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_unsorted), _begin(&_storage), _end(&_storage) + PUGI__FN xpath_node_set::xpath_node_set(const_iterator begin_, const_iterator end_, type_t type_): _type(type_unsorted), _begin(_storage), _end(_storage) { _assign(begin_, end_, type_); } PUGI__FN xpath_node_set::~xpath_node_set() { - if (_begin != &_storage) + if (_begin != _storage) impl::xml_memory::deallocate(_begin); } - PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(&_storage), _end(&_storage) + PUGI__FN xpath_node_set::xpath_node_set(const xpath_node_set& ns): _type(type_unsorted), _begin(_storage), _end(_storage) { _assign(ns._begin, ns._end, ns._type); } @@ -12095,7 +12319,7 @@ namespace pugi } #ifdef PUGIXML_HAS_MOVE - PUGI__FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs) PUGIXML_NOEXCEPT: _type(type_unsorted), _begin(&_storage), _end(&_storage) + PUGI__FN xpath_node_set::xpath_node_set(xpath_node_set&& rhs) PUGIXML_NOEXCEPT: _type(type_unsorted), _begin(_storage), _end(_storage) { _move(rhs); } @@ -12104,7 +12328,7 @@ namespace pugi { if (this == &rhs) return *this; - if (_begin != &_storage) + if (_begin != _storage) impl::xml_memory::deallocate(_begin); _move(rhs); @@ -12771,7 +12995,7 @@ namespace pugi #endif /** - * Copyright (c) 2006-2018 Arseny Kapoulkine + * Copyright (c) 2006-2020 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/contrib/pugixml/src/pugixml.hpp b/contrib/pugixml/src/pugixml.hpp index 1775600f1..7e2ce7776 100644 --- a/contrib/pugixml/src/pugixml.hpp +++ b/contrib/pugixml/src/pugixml.hpp @@ -1,8 +1,8 @@ /** - * pugixml parser - version 1.9 + * pugixml parser - version 1.11 * -------------------------------------------------------- - * Copyright (C) 2006-2018, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) - * Report bugs and download new versions at http://pugixml.org/ + * Copyright (C) 2006-2020, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com) + * Report bugs and download new versions at https://pugixml.org/ * * This library is distributed under the MIT License. See notice at the end * of this file. @@ -12,8 +12,9 @@ */ #ifndef PUGIXML_VERSION -// Define version macro; evaluates to major * 100 + minor so that it's safe to use in less-than comparisons -# define PUGIXML_VERSION 190 +// Define version macro; evaluates to major * 1000 + minor * 10 + patch so that it's safe to use in less-than comparisons +// Note: pugixml used major * 100 + minor * 10 + patch format up until 1.9 (which had version identifier 190); starting from pugixml 1.10, the minor version number is two digits +# define PUGIXML_VERSION 1110 #endif // Include user configuration file (this can define various configuration macros) @@ -110,6 +111,15 @@ # endif #endif +// If C++ is 2011 or higher, use 'nullptr' +#ifndef PUGIXML_NULL +# if __cplusplus >= 201103 +# define PUGIXML_NULL nullptr +# else +# define PUGIXML_NULL 0 +# endif +#endif + // Character interface macros #ifdef PUGIXML_WCHAR_MODE # define PUGIXML_TEXT(t) L ## t @@ -252,10 +262,19 @@ namespace pugi // Don't output empty element tags, instead writing an explicit start and end tag even if there are no children. This flag is off by default. const unsigned int format_no_empty_element_tags = 0x80; + // Skip characters belonging to range [0; 32) instead of "&#xNN;" encoding. This flag is off by default. + const unsigned int format_skip_control_chars = 0x100; + + // Use single quotes ' instead of double quotes " for enclosing attribute values. This flag is off by default. + const unsigned int format_attribute_single_quote = 0x200; + // The default set of formatting flags. // Nodes are indented depending on their depth in DOM tree, a default declaration is output if document has none. const unsigned int format_default = format_indent; + const int default_double_precision = 17; + const int default_float_precision = 9; + // Forward declarations struct xml_attribute_struct; struct xml_node_struct; @@ -403,7 +422,9 @@ namespace pugi bool set_value(long rhs); bool set_value(unsigned long rhs); bool set_value(double rhs); + bool set_value(double rhs, int precision); bool set_value(float rhs); + bool set_value(float rhs, int precision); bool set_value(bool rhs); #ifdef PUGIXML_HAS_LONG_LONG @@ -569,10 +590,16 @@ namespace pugi bool remove_attribute(const xml_attribute& a); bool remove_attribute(const char_t* name); + // Remove all attributes + bool remove_attributes(); + // Remove specified child bool remove_child(const xml_node& n); bool remove_child(const char_t* name); + // Remove all children + bool remove_children(); + // Parses buffer as an XML document fragment and appends all nodes as children of the current node. // Copies/converts the buffer, so it may be deleted or changed after the function returns. // Note: append_buffer allocates memory that has the lifetime of the owning document; removing the appended nodes does not immediately reclaim that memory. @@ -643,15 +670,15 @@ namespace pugi #ifndef PUGIXML_NO_XPATH // Select single node by evaluating XPath query. Returns first node from the resulting node set. - xpath_node select_node(const char_t* query, xpath_variable_set* variables = 0) const; + xpath_node select_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; xpath_node select_node(const xpath_query& query) const; // Select node set by evaluating XPath query - xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = 0) const; + xpath_node_set select_nodes(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; xpath_node_set select_nodes(const xpath_query& query) const; // (deprecated: use select_node instead) Select single node by evaluating XPath query. - PUGIXML_DEPRECATED xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = 0) const; + PUGIXML_DEPRECATED xpath_node select_single_node(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL) const; PUGIXML_DEPRECATED xpath_node select_single_node(const xpath_query& query) const; #endif @@ -754,7 +781,9 @@ namespace pugi bool set(long rhs); bool set(unsigned long rhs); bool set(double rhs); + bool set(double rhs, int precision); bool set(float rhs); + bool set(float rhs, int precision); bool set(bool rhs); #ifdef PUGIXML_HAS_LONG_LONG @@ -1192,7 +1221,7 @@ namespace pugi public: // Construct a compiled object from XPath expression. // If PUGIXML_NO_EXCEPTIONS is not defined, throws xpath_exception on compilation errors. - explicit xpath_query(const char_t* query, xpath_variable_set* variables = 0); + explicit xpath_query(const char_t* query, xpath_variable_set* variables = PUGIXML_NULL); // Constructor xpath_query(); @@ -1251,11 +1280,12 @@ namespace pugi }; #ifndef PUGIXML_NO_EXCEPTIONS - -#ifdef _MSC_VER -# pragma warning(push) -# pragma warning( disable: 4275 ) -#endif + #if defined(_MSC_VER) + // C4275 can be ignored in Visual C++ if you are deriving + // from a type in the Standard C++ Library + #pragma warning(push) + #pragma warning(disable: 4275) + #endif // XPath exception class class PUGIXML_CLASS xpath_exception: public std::exception { @@ -1272,10 +1302,11 @@ namespace pugi // Get parse result const xpath_parse_result& result() const; }; + #if defined(_MSC_VER) + #pragma warning(pop) + #endif #endif -#ifdef _MSC_VER -# pragma warning(pop) -#endif + // XPath node class (either xml_node or xml_attribute) class PUGIXML_CLASS xpath_node { @@ -1379,7 +1410,7 @@ namespace pugi private: type_t _type; - xpath_node _storage; + xpath_node _storage[1]; xpath_node* _begin; xpath_node* _end; @@ -1443,7 +1474,7 @@ namespace std #endif /** - * Copyright (c) 2006-2018 Arseny Kapoulkine + * Copyright (c) 2006-2020 Arseny Kapoulkine * * Permission is hereby granted, free of charge, to any person * obtaining a copy of this software and associated documentation diff --git a/include/assimp/Bitmap.h b/include/assimp/Bitmap.h index d56bb4c73..e4ce194d9 100644 --- a/include/assimp/Bitmap.h +++ b/include/assimp/Bitmap.h @@ -75,13 +75,12 @@ protected: uint32_t offset; // We define the struct size because sizeof(Header) might return a wrong result because of structure padding. - // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field). - static const std::size_t header_size = - sizeof(uint16_t) + // type - sizeof(uint32_t) + // size - sizeof(uint16_t) + // reserved1 - sizeof(uint16_t) + // reserved2 - sizeof(uint32_t); // offset + static constexpr std::size_t header_size = + sizeof(type) + + sizeof(size) + + sizeof(reserved1) + + sizeof(reserved2) + + sizeof(offset); }; struct DIB { @@ -98,22 +97,21 @@ protected: uint32_t nb_important_colors; // We define the struct size because sizeof(DIB) might return a wrong result because of structure padding. - // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field). - static const std::size_t dib_size = - sizeof(uint32_t) + // size - sizeof(int32_t) + // width - sizeof(int32_t) + // height - sizeof(uint16_t) + // planes - sizeof(uint16_t) + // bits_per_pixel - sizeof(uint32_t) + // compression - sizeof(uint32_t) + // image_size - sizeof(int32_t) + // x_resolution - sizeof(int32_t) + // y_resolution - sizeof(uint32_t) + // nb_colors - sizeof(uint32_t); // nb_important_colors + static constexpr std::size_t dib_size = + sizeof(size) + + sizeof(width) + + sizeof(height) + + sizeof(planes) + + sizeof(bits_per_pixel) + + sizeof(compression) + + sizeof(image_size) + + sizeof(x_resolution) + + sizeof(y_resolution) + + sizeof(nb_colors) + + sizeof(nb_important_colors); }; - static const std::size_t mBytesPerPixel = 4; + static constexpr std::size_t mBytesPerPixel = 4; public: static void Save(aiTexture* texture, IOStream* file); diff --git a/include/assimp/BlobIOSystem.h b/include/assimp/BlobIOSystem.h index 4e3d5c2a3..0abf166bc 100644 --- a/include/assimp/BlobIOSystem.h +++ b/include/assimp/BlobIOSystem.h @@ -194,8 +194,14 @@ class BlobIOSystem : public IOSystem { friend class BlobIOStream; typedef std::pair BlobEntry; + public: - BlobIOSystem() { + BlobIOSystem() : + baseName{AI_BLOBIO_MAGIC} { + } + + BlobIOSystem(const std::string &baseName) : + baseName(baseName) { } virtual ~BlobIOSystem() { @@ -207,27 +213,32 @@ public: public: // ------------------------------------------------------------------- const char *GetMagicFileName() const { - return AI_BLOBIO_MAGIC; + return baseName.c_str(); } // ------------------------------------------------------------------- aiExportDataBlob *GetBlobChain() { + const auto magicName = std::string(this->GetMagicFileName()); + const bool hasBaseName = baseName != AI_BLOBIO_MAGIC; + // one must be the master aiExportDataBlob *master = nullptr, *cur; + for (const BlobEntry &blobby : blobs) { - if (blobby.first == AI_BLOBIO_MAGIC) { + if (blobby.first == magicName) { master = blobby.second; + master->name.Set(hasBaseName ? blobby.first : ""); break; } } + if (!master) { ASSIMP_LOG_ERROR("BlobIOSystem: no data written or master file was not closed properly."); return nullptr; } - master->name.Set(""); - cur = master; + for (const BlobEntry &blobby : blobs) { if (blobby.second == master) { continue; @@ -236,9 +247,13 @@ public: cur->next = blobby.second; cur = cur->next; - // extract the file extension from the file written - const std::string::size_type s = blobby.first.find_first_of('.'); - cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s + 1)); + if (hasBaseName) { + cur->name.Set(blobby.first); + } else { + // extract the file extension from the file written + const std::string::size_type s = blobby.first.find_first_of('.'); + cur->name.Set(s == std::string::npos ? blobby.first : blobby.first.substr(s + 1)); + } } // give up blob ownership @@ -283,6 +298,7 @@ private: } private: + std::string baseName; std::set created; std::vector blobs; }; diff --git a/include/assimp/Exceptional.h b/include/assimp/Exceptional.h index 36d60d63a..98e2a3321 100644 --- a/include/assimp/Exceptional.h +++ b/include/assimp/Exceptional.h @@ -71,6 +71,9 @@ protected: * nullptr instead of a valid aiScene then. */ class ASSIMP_API DeadlyImportError : public DeadlyErrorBase { public: + DeadlyImportError(const char *message) : + DeadlyErrorBase(Assimp::Formatter::format(), std::forward(message)) {} + /** Constructor with arguments */ template explicit DeadlyImportError(T&&... args) : diff --git a/include/assimp/LineSplitter.h b/include/assimp/LineSplitter.h index 7cb71476c..44e6f0f1e 100644 --- a/include/assimp/LineSplitter.h +++ b/include/assimp/LineSplitter.h @@ -72,7 +72,7 @@ for(LineSplitter splitter(stream);splitter;++splitter) { if (strtol(splitter[2]) > 5) { .. } } - ASSIMP_LOG_VERBOSE_DEBUG_F("Current line is: ", splitter.get_index()); + ASSIMP_LOG_VERBOSE_DEBUG("Current line is: ", splitter.get_index()); } @endcode */ diff --git a/include/assimp/LogAux.h b/include/assimp/LogAux.h index b0a1f9ddd..065433648 100644 --- a/include/assimp/LogAux.h +++ b/include/assimp/LogAux.h @@ -64,82 +64,49 @@ public: template static void ThrowException(T&&... args) { - throw DeadlyImportError(Prefix(), args...); + throw DeadlyImportError(Prefix(), std::forward(args)...); } // ------------------------------------------------------------------------------------------------ - static void LogWarn(const Formatter::format& message) { + template + static void LogWarn(T&&... args) { if (!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_WARN(Prefix()+(std::string)message); + ASSIMP_LOG_WARN(Prefix(), std::forward(args)...); } } // ------------------------------------------------------------------------------------------------ - static void LogError(const Formatter::format& message) { + template + static void LogError(T&&... args) { if (!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_ERROR(Prefix()+(std::string)message); + ASSIMP_LOG_ERROR(Prefix(), std::forward(args)...); } } // ------------------------------------------------------------------------------------------------ - static void LogInfo(const Formatter::format& message) { + template + static void LogInfo(T&&... args) { if (!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_INFO(Prefix()+(std::string)message); + ASSIMP_LOG_INFO(Prefix(), std::forward(args)...); } } // ------------------------------------------------------------------------------------------------ - static void LogDebug(const Formatter::format& message) { + template + static void LogDebug(T&&... args) { if (!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_DEBUG(Prefix()+(std::string)message); - } - } - - static void LogVerboseDebug(const Formatter::format& message) { - if (!DefaultLogger::isNullLogger()) { - ASSIMP_LOG_VERBOSE_DEBUG(Prefix()+(std::string)message); - } - } - - // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462 -#if !defined(__GNUC__) || !defined(__APPLE__) || __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6) - - // ------------------------------------------------------------------------------------------------ - static void LogWarn (const char* message) { - if (!DefaultLogger::isNullLogger()) { - LogWarn(Formatter::format(message)); + ASSIMP_LOG_DEBUG(Prefix(), std::forward(args)...); } } // ------------------------------------------------------------------------------------------------ - static void LogError (const char* message) { + template + static void LogVerboseDebug(T&&... args) { if (!DefaultLogger::isNullLogger()) { - LogError(Formatter::format(message)); + ASSIMP_LOG_VERBOSE_DEBUG(Prefix(), std::forward(args)...); } } - // ------------------------------------------------------------------------------------------------ - static void LogInfo (const char* message) { - if (!DefaultLogger::isNullLogger()) { - LogInfo(Formatter::format(message)); - } - } - - // ------------------------------------------------------------------------------------------------ - static void LogDebug (const char* message) { - if (!DefaultLogger::isNullLogger()) { - LogDebug(Formatter::format(message)); - } - } - - // ------------------------------------------------------------------------------------------------ - static void LogVerboseDebug (const char* message) { - if (!DefaultLogger::isNullLogger()) { - LogVerboseDebug(Formatter::format(message)); - } - } -#endif - private: static const char* Prefix(); diff --git a/include/assimp/Logger.hpp b/include/assimp/Logger.hpp index ee6eab507..3ca4a6cb2 100644 --- a/include/assimp/Logger.hpp +++ b/include/assimp/Logger.hpp @@ -99,34 +99,54 @@ public: virtual ~Logger(); // ---------------------------------------------------------------------- - /** @brief Writes a debug message - * @param message Debug message*/ + /** @brief Writes a info message + * @param message Info message*/ void debug(const char* message); - void debug(const std::string &message); + + template + void debug(T&&... args) { + debug(formatMessage(std::forward(args)...).c_str()); + } // ---------------------------------------------------------------------- /** @brief Writes a debug message * @param message Debug message*/ - void verboseDebug(const char *message); - void verboseDebug(const std::string &message); + void verboseDebug(const char* message); + + template + void verboseDebug(T&&... args) { + verboseDebug(formatMessage(std::forward(args)...).c_str()); + } // ---------------------------------------------------------------------- /** @brief Writes a info message * @param message Info message*/ void info(const char* message); - void info(const std::string &message); + + template + void info(T&&... args) { + info(formatMessage(std::forward(args)...).c_str()); + } // ---------------------------------------------------------------------- /** @brief Writes a warning message * @param message Warn message*/ void warn(const char* message); - void warn(const std::string &message); + + template + void warn(T&&... args) { + warn(formatMessage(std::forward(args)...).c_str()); + } // ---------------------------------------------------------------------- /** @brief Writes an error message - * @param message Error message*/ + * @param message Info message*/ void error(const char* message); - void error(const std::string &message); + + template + void error(T&&... args) { + error(formatMessage(std::forward(args)...).c_str()); + } // ---------------------------------------------------------------------- /** @brief Set a new log severity. @@ -224,6 +244,15 @@ protected: * the function is left. */ virtual void OnError(const char* message) = 0; +protected: + std::string formatMessage(Assimp::Formatter::format f) { + return f; + } + + template + std::string formatMessage(Assimp::Formatter::format f, U&& u, T&&... args) { + return formatMessage(std::move(f << std::forward(u)), std::forward(args)...); + } protected: LogSeverity m_Severity; @@ -266,66 +295,22 @@ Logger::LogSeverity Logger::getLogSeverity() const { return m_Severity; } -// ---------------------------------------------------------------------------------- -inline -void Logger::debug(const std::string &message) { - return debug(message.c_str()); -} - -// ---------------------------------------------------------------------------------- -inline void Logger::verboseDebug(const std::string &message) { - return verboseDebug(message.c_str()); -} - -// ---------------------------------------------------------------------------------- -inline -void Logger::error(const std::string &message) { - return error(message.c_str()); -} - -// ---------------------------------------------------------------------------------- -inline -void Logger::warn(const std::string &message) { - return warn(message.c_str()); -} - -// ---------------------------------------------------------------------------------- -inline -void Logger::info(const std::string &message) { - return info(message.c_str()); -} - } // Namespace Assimp // ------------------------------------------------------------------------------------------------ -#define ASSIMP_LOG_WARN_F(string, ...) \ - Assimp::DefaultLogger::get()->warn((Assimp::Formatter::format(string), __VA_ARGS__)) +#define ASSIMP_LOG_WARN(...) \ + Assimp::DefaultLogger::get()->warn(__VA_ARGS__) -#define ASSIMP_LOG_ERROR_F(string, ...) \ - Assimp::DefaultLogger::get()->error((Assimp::Formatter::format(string), __VA_ARGS__)) +#define ASSIMP_LOG_ERROR(...) \ + Assimp::DefaultLogger::get()->error(__VA_ARGS__) -#define ASSIMP_LOG_DEBUG_F(string, ...) \ - Assimp::DefaultLogger::get()->debug((Assimp::Formatter::format(string), __VA_ARGS__)) +#define ASSIMP_LOG_DEBUG(...) \ + Assimp::DefaultLogger::get()->debug(__VA_ARGS__) -#define ASSIMP_LOG_VERBOSE_DEBUG_F(string, ...) \ - Assimp::DefaultLogger::get()->verboseDebug((Assimp::Formatter::format(string), __VA_ARGS__)) +#define ASSIMP_LOG_VERBOSE_DEBUG(...) \ + Assimp::DefaultLogger::get()->verboseDebug(__VA_ARGS__) -#define ASSIMP_LOG_INFO_F(string, ...) \ - Assimp::DefaultLogger::get()->info((Assimp::Formatter::format(string), __VA_ARGS__)) - -#define ASSIMP_LOG_WARN(string) \ - Assimp::DefaultLogger::get()->warn(string) - -#define ASSIMP_LOG_ERROR(string) \ - Assimp::DefaultLogger::get()->error(string) - -#define ASSIMP_LOG_DEBUG(string) \ - Assimp::DefaultLogger::get()->debug(string) - -#define ASSIMP_LOG_VERBOSE_DEBUG(string) \ - Assimp::DefaultLogger::get()->verboseDebug(string) - -#define ASSIMP_LOG_INFO(string) \ - Assimp::DefaultLogger::get()->info(string) +#define ASSIMP_LOG_INFO(...) \ + Assimp::DefaultLogger::get()->info(__VA_ARGS__) #endif // !! INCLUDED_AI_LOGGER_H diff --git a/include/assimp/ParsingUtils.h b/include/assimp/ParsingUtils.h index b52b0610e..b5074869e 100644 --- a/include/assimp/ParsingUtils.h +++ b/include/assimp/ParsingUtils.h @@ -262,7 +262,7 @@ AI_FORCE_INLINE unsigned int tokenize(const string_type &str, std::vector elapsedSeconds = std::chrono::system_clock::now() - regions[region]; - ASSIMP_LOG_DEBUG((format("END `"),region,"`, dt= ", elapsedSeconds.count()," s")); + ASSIMP_LOG_DEBUG("END `",region,"`, dt= ", elapsedSeconds.count()," s"); } private: diff --git a/include/assimp/StringComparison.h b/include/assimp/StringComparison.h index 6dad01294..b0161664f 100644 --- a/include/assimp/StringComparison.h +++ b/include/assimp/StringComparison.h @@ -146,8 +146,8 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2) { #else char c1, c2; do { - c1 = tolower(*s1++); - c2 = tolower(*s2++); + c1 = tolower((unsigned char)*(s1++)); + c2 = tolower((unsigned char)*(s2++)); } while (c1 && (c1 == c2)); return c1 - c2; #endif @@ -197,8 +197,8 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) { unsigned int p = 0; do { if (p++ >= n) return 0; - c1 = tolower(*s1++); - c2 = tolower(*s2++); + c1 = tolower((unsigned char)*(s1++)); + c2 = tolower((unsigned char)*(s2++)); } while (c1 && (c1 == c2)); return c1 - c2; diff --git a/include/assimp/StringUtils.h b/include/assimp/StringUtils.h index d536b2f0a..025a826d2 100644 --- a/include/assimp/StringUtils.h +++ b/include/assimp/StringUtils.h @@ -157,7 +157,7 @@ AI_FORCE_INLINE std::string ai_decimal_to_hexa(T toConvert) { ss >> result; for (size_t i = 0; i < result.size(); ++i) { - result[i] = (char)toupper(result[i]); + result[i] = (char)toupper((unsigned char)result[i]); } return result; @@ -249,4 +249,31 @@ AI_FORCE_INLINE std::string ai_str_toupper(const std::string &in) { return out; } +// --------------------------------------------------------------------------------- +/// @brief Make a string printable by replacing all non-printable characters with +/// the specified placeholder character. +/// @param in The incoming string. +/// @param placeholder Placeholder character, default is a question mark. +/// @return The string, with all non-printable characters replaced. +AI_FORCE_INLINE std::string ai_str_toprintable(const std::string &in, char placeholder = '?') { + std::string out(in); + std::transform(out.begin(), out.end(), out.begin(), [placeholder] (unsigned char c) { + return isprint(c) ? (char)c : placeholder; + }); + return out; +} + +// --------------------------------------------------------------------------------- +/// @brief Make a string printable by replacing all non-printable characters with +/// the specified placeholder character. +/// @param in The incoming string. +/// @param len The length of the incoming string. +/// @param placeholder Placeholder character, default is a question mark. +/// @return The string, with all non-printable characters replaced. Will return an +/// empty string if in is null or len is <= 0. +AI_FORCE_INLINE std::string ai_str_toprintable(const char *in, int len, char placeholder = '?') { + return (in && len > 0) ? ai_str_toprintable(std::string(in, len), placeholder) : std::string(); +} + + #endif // INCLUDED_AI_STRINGUTILS_H diff --git a/include/assimp/TinyFormatter.h b/include/assimp/TinyFormatter.h index ace20be5c..112f19013 100644 --- a/include/assimp/TinyFormatter.h +++ b/include/assimp/TinyFormatter.h @@ -88,9 +88,17 @@ public: underlying << sin; } + // Same problem as the copy constructor below, but with root cause is that stream move + // is not permitted on older GCC versions. Small performance impact on those platforms. +#if defined(__GNUC__) && (__GNUC__ == 4 && __GNUC_MINOR__ <= 9) + basic_formatter(basic_formatter&& other) { + underlying << (string)other; + } +#else basic_formatter(basic_formatter&& other) : underlying(std::move(other.underlying)) { } +#endif // The problem described here: // https://sourceforge.net/tracker/?func=detail&atid=1067632&aid=3358562&group_id=226462 diff --git a/include/assimp/XmlParser.h b/include/assimp/XmlParser.h index 91fb9907f..18d48f337 100644 --- a/include/assimp/XmlParser.h +++ b/include/assimp/XmlParser.h @@ -66,6 +66,8 @@ struct find_node_by_name_predicate { } }; +/// @brief Will convert an attribute to its int value. +/// @tparam TNodeType The node type. template struct NodeConverter { public: @@ -78,19 +80,37 @@ public: using XmlNode = pugi::xml_node; using XmlAttribute = pugi::xml_attribute; +/// @brief The Xml-Parser class. +/// +/// Use this parser if you have to import any kind of xml-format. +/// +/// An example: +/// @code +/// TXmlParser theParser; +/// if (theParser.parse(fileStream)) { +/// auto node = theParser.getRootNode(); +/// for ( auto currentNode : node.children()) { +/// // Will loop over all children +/// } +/// } +/// @endcode +/// @tparam TNodeType template class TXmlParser { public: + /// @brief The default class constructor. TXmlParser() : mDoc(nullptr), mData() { // empty } + /// @brief The class destructor. ~TXmlParser() { clear(); } + /// @brief Will clear the parsed xml-file. void clear() { if(mData.empty()) { mDoc = nullptr; @@ -101,6 +121,9 @@ public: mDoc = nullptr; } + /// @brief Will search for a child-node by its name + /// @param name [in] The name of the child-node. + /// @return The node instance or nullptr, if nothing was found. TNodeType *findNode(const std::string &name) { if (name.empty()) { return nullptr; @@ -119,10 +142,16 @@ public: return &mCurrent; } + /// @brief Will return true, if the node is a child-node. + /// @param name [in] The name of the child node to look for. + /// @return true, if the node is a child-node or false if not. bool hasNode(const std::string &name) { return nullptr != findNode(name); } + /// @brief Will parse an xml-file from a given stream. + /// @param stream The input stream. + /// @return true, if the parsing was successful, false if not. bool parse(IOStream *stream) { if (nullptr == stream) { ASSIMP_LOG_DEBUG("Stream is nullptr."); @@ -138,34 +167,67 @@ public: pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full); if (parse_result.status == pugi::status_ok) { return true; - } else { - ASSIMP_LOG_DEBUG("Error while parse xml."); - return false; - } + } + + ASSIMP_LOG_DEBUG("Error while parse xml.", std::string(parse_result.description()), " @ ", parse_result.offset); + + return false; } + /// @brief Will return truem if a root node is there. + /// @return true in case of an existing root. + bool hasRoot() const { + return nullptr != mDoc; + } + /// @brief Will return the document pointer, is nullptr if no xml-file was parsed. + /// @return The pointer showing to the document. pugi::xml_document *getDocument() const { return mDoc; } + /// @brief Will return the root node, const version. + /// @return The root node. const TNodeType getRootNode() const { + static pugi::xml_node none; + if (nullptr == mDoc) { + return none; + } return mDoc->root(); } + /// @brief Will return the root node, non-const version. + /// @return The root node. TNodeType getRootNode() { + static pugi::xml_node none; + if (nullptr == mDoc) { + return none; + } return mDoc->root(); } + /// @brief Will check if a node with the given name is in. + /// @param node [in] The node to look in. + /// @param name [in] The name of the child-node. + /// @return true, if node was found, false if not. static inline bool hasNode(XmlNode &node, const char *name) { pugi::xml_node child = node.find_child(find_node_by_name_predicate(name)); return !child.empty(); } + /// @brief Will check if an attribute is part of the XmlNode. + /// @param xmlNode [in] The node to search in. + /// @param name [in} The attribute name to look for. + /// @return true, if the was found, false if not. static inline bool hasAttribute(XmlNode &xmlNode, const char *name) { pugi::xml_attribute attr = xmlNode.attribute(name); return !attr.empty(); } + /// @brief Will try to get an unsigned int attribute value. + /// @param xmlNode [in] The node to search in. + /// @param name [in] The attribute name to look for. + /// @param val [out] The unsigned int value from the attribute. + /// @return true, if the node contains an attribute with the given name and if the value is an unsigned int. static inline bool getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val) { pugi::xml_attribute attr = xmlNode.attribute(name); if (attr.empty()) { @@ -176,6 +238,11 @@ public: return true; } + /// @brief Will try to get an int attribute value. + /// @param xmlNode [in] The node to search in. + /// @param name [in] The attribute name to look for. + /// @param val [out] The int value from the attribute. + /// @return true, if the node contains an attribute with the given name and if the value is an int. static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val ) { pugi::xml_attribute attr = xmlNode.attribute(name); if (attr.empty()) { @@ -186,6 +253,11 @@ public: return true; } + /// @brief Will try to get a real attribute value. + /// @param xmlNode [in] The node to search in. + /// @param name [in] The attribute name to look for. + /// @param val [out] The real value from the attribute. + /// @return true, if the node contains an attribute with the given name and if the value is a real. static inline bool getRealAttribute( XmlNode &xmlNode, const char *name, ai_real &val ) { pugi::xml_attribute attr = xmlNode.attribute(name); if (attr.empty()) { @@ -199,7 +271,12 @@ public: return true; } - static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val ) { + /// @brief Will try to get a float attribute value. + /// @param xmlNode [in] The node to search in. + /// @param name [in] The attribute name to look for. + /// @param val [out] The float value from the attribute. + /// @return true, if the node contains an attribute with the given name and if the value is a float. + static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val) { pugi::xml_attribute attr = xmlNode.attribute(name); if (attr.empty()) { return false; @@ -210,7 +287,12 @@ public: } - static inline bool getDoubleAttribute( XmlNode &xmlNode, const char *name, double &val ) { + /// @brief Will try to get a double attribute value. + /// @param xmlNode [in] The node to search in. + /// @param name [in] The attribute name to look for. + /// @param val [out] The double value from the attribute. + /// @return true, if the node contains an attribute with the given name and if the value is a double. + static inline bool getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val) { pugi::xml_attribute attr = xmlNode.attribute(name); if (attr.empty()) { return false; @@ -220,6 +302,11 @@ public: return true; } + /// @brief Will try to get a std::string attribute value. + /// @param xmlNode [in] The node to search in. + /// @param name [in] The attribute name to look for. + /// @param val [out] The std::string value from the attribute. + /// @return true, if the node contains an attribute with the given name and if the value is a std::string. static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) { pugi::xml_attribute attr = xmlNode.attribute(name); if (attr.empty()) { @@ -230,6 +317,11 @@ public: return true; } + /// @brief Will try to get a bool attribute value. + /// @param xmlNode [in] The node to search in. + /// @param name [in] The attribute name to look for. + /// @param val [out] The bool value from the attribute. + /// @return true, if the node contains an attribute with the given name and if the value is a bool. static inline bool getBoolAttribute( XmlNode &xmlNode, const char *name, bool &val ) { pugi::xml_attribute attr = xmlNode.attribute(name); if (attr.empty()) { @@ -241,6 +333,10 @@ public: } + /// @brief Will try to get the value of the node as a string. + /// @param node [in] The node to search in. + /// @param text [out] The value as a text. + /// @return true, if the value can be read out. static inline bool getValueAsString( XmlNode &node, std::string &text ) { text = std::string(); if (node.empty()) { @@ -252,6 +348,10 @@ public: return true; } + /// @brief Will try to get the value of the node as a float. + /// @param node [in] The node to search in. + /// @param text [out] The value as a float. + /// @return true, if the value can be read out. static inline bool getValueAsFloat( XmlNode &node, ai_real &v ) { if (node.empty()) { return false; @@ -271,17 +371,36 @@ public: using XmlParser = TXmlParser; +/// @brief This class declares an iterator to loop through all children of the root node. class XmlNodeIterator { public: - XmlNodeIterator(XmlNode &parent) : + /// @brief The iteration mode. + enum IterationMode { + PreOrderMode, ///< Pre-ordering, get the values, continue the iteration. + PostOrderMode ///< Post-ordering, continue the iteration, get the values. + }; + /// @brief The class constructor + /// @param parent [in] The xml parent to to iterate through. + /// @param mode [in] The iteration mode. + explicit XmlNodeIterator(XmlNode &parent, IterationMode mode) : mParent(parent), mNodes(), mIndex(0) { + if (mode == PreOrderMode) { + collectChildrenPreOrder(parent); + } else { + collectChildrenPostOrder(parent); + } + } + + /// @brief The class destructor. + ~XmlNodeIterator() { // empty } + /// @brief Will iterate through all children in pre-order iteration. + /// @param node [in] The nod to iterate through. void collectChildrenPreOrder( XmlNode &node ) { - if (node != mParent && node.type() == pugi::node_element) { mNodes.push_back(node); } @@ -290,6 +409,8 @@ public: } } + /// @brief Will iterate through all children in post-order iteration. + /// @param node [in] The nod to iterate through. void collectChildrenPostOrder(XmlNode &node) { for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { collectChildrenPostOrder(currentNode); @@ -299,6 +420,9 @@ public: } } + /// @brief Will iterate through all collected nodes. + /// @param next The next node, if there is any. + /// @return true, if there is a node left. bool getNext(XmlNode &next) { if (mIndex == mNodes.size()) { return false; @@ -310,14 +434,19 @@ public: return true; } + /// @brief Will return the number of collected nodes. + /// @return The number of collected nodes. size_t size() const { return mNodes.size(); } + /// @brief Returns true, if the node is empty. + /// @return true, if the node is empty, false if not. bool isEmpty() const { return mNodes.empty(); } + /// @brief Will clear all collected nodes. void clear() { if (mNodes.empty()) { return; diff --git a/include/assimp/camera.h b/include/assimp/camera.h index d7324d10d..6a7acadbb 100644 --- a/include/assimp/camera.h +++ b/include/assimp/camera.h @@ -137,7 +137,7 @@ struct aiCamera */ C_STRUCT aiVector3D mLookAt; - /** Half horizontal field of view angle, in radians. + /** Horizontal field of view angle, in radians. * * The field of view angle is the angle between the center * line of the screen and the left or right border. diff --git a/include/assimp/cexport.h b/include/assimp/cexport.h index 2e84b1f30..44843af0e 100644 --- a/include/assimp/cexport.h +++ b/include/assimp/cexport.h @@ -205,16 +205,22 @@ struct aiExportDataBlob { void *data; /** Name of the blob. An empty string always - indicates the first (and primary) blob, - which contains the actual file data. - Any other blobs are auxiliary files produced - by exporters (i.e. material files). Existence - of such files depends on the file format. Most - formats don't split assets across multiple files. - - If used, blob names usually contain the file - extension that should be used when writing - the data to disc. + * indicates the first (and primary) blob, + * which contains the actual file data. + * Any other blobs are auxiliary files produced + * by exporters (i.e. material files). Existence + * of such files depends on the file format. Most + * formats don't split assets across multiple files. + * + * If used, blob names usually contain the file + * extension that should be used when writing + * the data to disc. + * + * The blob names generated can be influenced by + * setting the #AI_CONFIG_EXPORT_BLOB_NAME export + * property to the name that is used for the master + * blob. All other names are typically derived from + * the base name, by the file format exporter. */ C_STRUCT aiString name; diff --git a/include/assimp/config.h.in b/include/assimp/config.h.in index d78568da7..a89d4e837 100644 --- a/include/assimp/config.h.in +++ b/include/assimp/config.h.in @@ -669,7 +669,7 @@ enum aiComponent // --------------------------------------------------------------------------- /** @brief Set wether the importer shall not remove empty bones. - * + * * Empty bone are often used to define connections for other models. */ #define AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES \ @@ -854,6 +854,15 @@ enum aiComponent #define AI_CONFIG_IMPORT_MD3_SKIN_NAME \ "IMPORT_MD3_SKIN_NAME" +// --------------------------------------------------------------------------- +/** @brief Specify if to try load Quake 3 shader files. This also controls + * original surface name handling: when disabled it will be used unchanged. + * + * Property type: bool. Default value: true. + */ +#define AI_CONFIG_IMPORT_MD3_LOAD_SHADERS \ + "IMPORT_MD3_LOAD_SHADERS" + // --------------------------------------------------------------------------- /** @brief Specify the Quake 3 shader file to be used for a particular * MD3 file. This can also be a search path. @@ -1058,7 +1067,7 @@ enum aiComponent #define AI_CONFIG_EXPORT_XFILE_64BIT "EXPORT_XFILE_64BIT" /** @brief Specifies whether the assimp export shall be able to export point clouds - * + * * When this flag is not defined the render data has to contain valid faces. * Point clouds are only a collection of vertices which have nor spatial organization * by a face and the validation process will remove them. Enabling this feature will @@ -1066,6 +1075,23 @@ enum aiComponent */ #define AI_CONFIG_EXPORT_POINT_CLOUDS "EXPORT_POINT_CLOUDS" +/** + * @brief Specifies the blob name, assimp uses for exporting. + * + * Some formats require auxiliary files to be written, that need to be linked back into + * the original file. For example, OBJ files export materials to a separate MTL file and + * use the `mtllib` keyword to reference this file. + * + * When exporting blobs using #ExportToBlob, assimp does not know the name of the blob + * file and thus outputs `mtllib $blobfile.mtl`, which might not be desired, since the + * MTL file might be called differently. + * + * This property can be used to give the exporter a hint on how to use the magic + * `$blobfile` keyword. If the exporter detects the keyword and is provided with a name + * for the blob, it instead uses this name. + */ +#define AI_CONFIG_EXPORT_BLOB_NAME "EXPORT_BLOB_NAME" + /** * @brief Specifies a gobal key factor for scale, float value */ diff --git a/include/assimp/fast_atof.h b/include/assimp/fast_atof.h index 9ea49c85c..aea793f35 100644 --- a/include/assimp/fast_atof.h +++ b/include/assimp/fast_atof.h @@ -29,6 +29,7 @@ #include "StringComparison.h" #include #include +#include #ifdef _MSC_VER # include @@ -193,7 +194,7 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino if ( *in < '0' || *in > '9' ) { // The string is known to be bad, so don't risk printing the whole thing. - throw ExceptionType("The string \"", std::string(in).substr(0, 100), "\" cannot be converted into a value." ); + throw ExceptionType("The string \"", ai_str_toprintable(in, 30), "\" cannot be converted into a value." ); } for ( ;; ) { @@ -205,7 +206,7 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino // numeric overflow, we rely on you if ( new_value < value ) { - ASSIMP_LOG_WARN_F( "Converting the string \"", in, "\" into a value resulted in overflow." ); + ASSIMP_LOG_WARN( "Converting the string \"", in, "\" into a value resulted in overflow." ); return 0; } @@ -293,7 +294,7 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true) if (!(c[0] >= '0' && c[0] <= '9') && !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) { // The string is known to be bad, so don't risk printing the whole thing. - throw ExceptionType("Cannot parse string \"", std::string(c).substr(0, 100), + throw ExceptionType("Cannot parse string \"", ai_str_toprintable(c, 30), "\" as a real number: does not start with digit " "or decimal point followed by digit."); } diff --git a/include/assimp/material.h b/include/assimp/material.h index f3daa62dc..08c0491c0 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -920,6 +920,18 @@ extern "C" { #define AI_MATKEY_SHADER_PRIMITIVE "?sh.ps", 0, 0 #define AI_MATKEY_SHADER_COMPUTE "?sh.cs", 0, 0 +// --------------------------------------------------------------------------- +// PBR material support +#define AI_MATKEY_USE_COLOR_MAP "$mat.useColorMap", 0, 0 +#define AI_MATKEY_BASE_COLOR "$clr.base", 0, 0 +#define AI_MATKEY_USE_METALLIC_MAP "$mat.useMetallicMap", 0, 0 +#define AI_MATKEY_METALLIC_FACTOR "$mat.metallicFactor", 0, 0 +#define AI_MATKEY_USE_ROUGHNESS_MAP "$mat.useRoughnessMap", 0, 0 +#define AI_MATKEY_ROUGHNESS_FACTOR "$mat.roughnessFactor", 0, 0 +#define AI_MATKEY_USE_EMISSIVE_MAP "$mat.useEmissiveMap", 0, 0 +#define AI_MATKEY_EMISSIVE_INTENSITY "$mat.emissiveIntensity", 0, 0 +#define AI_MATKEY_USE_AO_MAP "$mat.useAOMap", 0, 0 + // --------------------------------------------------------------------------- // Pure key names for all texture-related properties //! @cond MATS_DOC_FULL diff --git a/include/assimp/mesh.h b/include/assimp/mesh.h index 427dba008..989ed3800 100644 --- a/include/assimp/mesh.h +++ b/include/assimp/mesh.h @@ -674,6 +674,10 @@ struct aiMesh { */ C_STRUCT aiVector3D *mTextureCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + /** Vertex stream names. + */ + C_STRUCT aiString mTextureCoordsNames[AI_MAX_NUMBER_OF_TEXTURECOORDS]; + /** Specifies the number of components for a given UV channel. * Up to three channels are supported (UVW, for accessing volume * or cube maps). If the value is 2 for a given channel n, the diff --git a/include/assimp/metadata.h b/include/assimp/metadata.h index fdc88be56..551a9aba4 100644 --- a/include/assimp/metadata.h +++ b/include/assimp/metadata.h @@ -156,7 +156,7 @@ struct aiMetadata { #ifdef __cplusplus - /** + /** * @brief The default constructor, set all members to zero by default. */ aiMetadata() AI_NO_EXCEPT @@ -202,17 +202,17 @@ struct aiMetadata { } break; case AI_AISTRING: { aiString v; - rhs.Get(mKeys[i], v); + rhs.Get(static_cast(i), v); mValues[i].mData = new aiString(v); } break; case AI_AIVECTOR3D: { aiVector3D v; - rhs.Get(mKeys[i], v); + rhs.Get(static_cast(i), v); mValues[i].mData = new aiVector3D(v); } break; case AI_AIMETADATA: { aiMetadata v; - rhs.Get(mKeys[i], v); + rhs.Get(static_cast(i), v); mValues[i].mData = new aiMetadata(v); } break; #ifndef SWIG diff --git a/port/PyAssimp/pyassimp/core.py b/port/PyAssimp/pyassimp/core.py index 37beac886..35ad882b3 100644 --- a/port/PyAssimp/pyassimp/core.py +++ b/port/PyAssimp/pyassimp/core.py @@ -211,7 +211,7 @@ def _init(self, target = None, parent = None): else: # starts with 'm' but not iterable - setattr(target, name, obj) + setattr(target, m, obj) logger.debug("Added " + name + " as self." + name + " (type: " + str(type(obj)) + ")") if _is_init_type(obj): diff --git a/port/PyAssimp/pyassimp/helper.py b/port/PyAssimp/pyassimp/helper.py index 5c1aca827..7a4b2bdcb 100644 --- a/port/PyAssimp/pyassimp/helper.py +++ b/port/PyAssimp/pyassimp/helper.py @@ -27,6 +27,7 @@ if os.name=='posix': additional_dirs.append('./') additional_dirs.append('/usr/lib/') additional_dirs.append('/usr/lib/x86_64-linux-gnu/') + additional_dirs.append('/usr/lib/aarch64-linux-gnu/') additional_dirs.append('/usr/local/lib/') if 'LD_LIBRARY_PATH' in os.environ: diff --git a/test/unit/Common/utXmlParser.cpp b/test/unit/Common/utXmlParser.cpp index c27669dd1..7e992f9df 100644 --- a/test/unit/Common/utXmlParser.cpp +++ b/test/unit/Common/utXmlParser.cpp @@ -73,9 +73,7 @@ TEST_F(utXmlParser, parse_xml_and_traverse_test) { EXPECT_TRUE(result); XmlNode root = parser.getRootNode(); - XmlNodeIterator nodeIt(root); - EXPECT_TRUE(nodeIt.isEmpty()); - nodeIt.collectChildrenPreOrder(root); + XmlNodeIterator nodeIt(root, XmlNodeIterator::PreOrderMode); const size_t numNodes = nodeIt.size(); bool empty = nodeIt.isEmpty(); EXPECT_FALSE(empty); diff --git a/test/unit/utImporter.cpp b/test/unit/utImporter.cpp index 65b7f99ee..9d3b971a3 100644 --- a/test/unit/utImporter.cpp +++ b/test/unit/utImporter.cpp @@ -280,104 +280,84 @@ TEST_F(ImporterTest, SearchFileHeaderForTokenTest) { // BaseImporter::SearchFileHeaderForToken( &ioSystem, assetPath, Token, 2 ) } +namespace { +// Description for an importer which fails in specific ways. +aiImporterDesc s_failingImporterDescription = { + "Failing importer", + "assimp team", + "", + "", + 0, + 1, + 0, + 1, + 0, + "fail" +}; -namespace -{ - // Description for an importer which fails in specific ways. - aiImporterDesc s_failingImporterDescription = { - "Failing importer", - "assimp team", - "", - "", - 0, - 1, - 0, - 1, - 0, - "fail" - }; +// This importer fails in specific ways. +class FailingImporter : public Assimp::BaseImporter { +public: + virtual ~FailingImporter() = default; + virtual bool CanRead(const std::string &, Assimp::IOSystem *, bool) const override { + return true; + } - // This importer fails in specific ways. - class FailingImporter : public Assimp::BaseImporter { - public: - virtual ~FailingImporter() = default; - virtual bool CanRead( const std::string&, Assimp::IOSystem*, bool ) const override - { - return true; +protected: + const aiImporterDesc *GetInfo() const override { + return &s_failingImporterDescription; + } + + void InternReadFile(const std::string &pFile, aiScene *, Assimp::IOSystem *) override { + if (pFile == "deadlyImportError.fail") { + throw DeadlyImportError("Deadly import error test. Details: ", 42, " More Details: ", "Failure"); + } else if (pFile == "stdException.fail") { + throw std::runtime_error("std::exception test"); + } else if (pFile == "unexpectedException.fail") { + throw 5; } + } +}; +} // namespace - protected: - virtual const aiImporterDesc* GetInfo() const override { return &s_failingImporterDescription; } - - virtual void InternReadFile( const std::string& pFile, aiScene*, Assimp::IOSystem* ) override - { - if (pFile == "deadlyImportError.fail") - { - throw DeadlyImportError("Deadly import error test. Details: ", 42, " More Details: ", "Failure"); - } - else if (pFile == "stdException.fail") - { - throw std::runtime_error("std::exception test"); - } - else if (pFile == "unexpectedException.fail") - { - throw 5; - } - } - }; -} - -TEST_F(ImporterTest, deadlyImportError) -{ +TEST_F(ImporterTest, deadlyImportError) { pImp->RegisterLoader(new FailingImporter); pImp->SetIOHandler(new TestIOSystem); - const aiScene* scene = pImp->ReadFile("deadlyImportError.fail", 0); + const aiScene *scene = pImp->ReadFile("deadlyImportError.fail", 0); EXPECT_EQ(scene, nullptr); EXPECT_STREQ(pImp->GetErrorString(), "Deadly import error test. Details: 42 More Details: Failure"); EXPECT_NE(pImp->GetException(), std::exception_ptr()); } -TEST_F(ImporterTest, stdException) -{ +TEST_F(ImporterTest, stdException) { pImp->RegisterLoader(new FailingImporter); pImp->SetIOHandler(new TestIOSystem); - const aiScene* scene = pImp->ReadFile("stdException.fail", 0); + const aiScene *scene = pImp->ReadFile("stdException.fail", 0); EXPECT_EQ(scene, nullptr); EXPECT_STREQ(pImp->GetErrorString(), "std::exception test"); EXPECT_NE(pImp->GetException(), std::exception_ptr()); - try - { + try { std::rethrow_exception(pImp->GetException()); - } - catch(const std::exception& e) - { + } catch (const std::exception &e) { EXPECT_STREQ(e.what(), "std::exception test"); - } - catch(...) - { + } catch (...) { EXPECT_TRUE(false); } } -TEST_F(ImporterTest, unexpectedException) -{ +TEST_F(ImporterTest, unexpectedException) { pImp->RegisterLoader(new FailingImporter); pImp->SetIOHandler(new TestIOSystem); - const aiScene* scene = pImp->ReadFile("unexpectedException.fail", 0); + const aiScene *scene = pImp->ReadFile("unexpectedException.fail", 0); EXPECT_EQ(scene, nullptr); EXPECT_STREQ(pImp->GetErrorString(), "Unknown exception"); ASSERT_NE(pImp->GetException(), std::exception_ptr()); - try - { + try { std::rethrow_exception(pImp->GetException()); - } - catch(int x) - { + } catch (int x) { EXPECT_EQ(x, 5); - } - catch(...) - { + } catch (...) { EXPECT_TRUE(false); } } diff --git a/tools/assimp_view/Material.cpp b/tools/assimp_view/Material.cpp index 8141fb58c..bcc93011e 100644 --- a/tools/assimp_view/Material.cpp +++ b/tools/assimp_view/Material.cpp @@ -272,7 +272,7 @@ bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString) szExtFound - 1 - info.cFileName); for (unsigned int i = 0; i < iSizeFound;++i) - info.cFileName[i] = (CHAR)tolower(info.cFileName[i]); + info.cFileName[i] = (CHAR)tolower((unsigned char)info.cFileName[i]); if (0 == memcmp(info.cFileName,szFile2, std::min(iSizeFound,iSize))) { @@ -354,7 +354,7 @@ int CMaterialManager::FindValidPath(aiString* p_szString) for (unsigned int i = 0;;++i) { if ('\0' == szTemp[i])break; - szTemp[i] = (char)tolower(szTemp[i]); + szTemp[i] = (char)tolower((unsigned char)szTemp[i]); } if(TryLongerPath(szTemp,p_szString))return 1;