Explorar el Código

Merge branch 'master' into master

Kim Kulling hace 4 años
padre
commit
29e5f5fed1
Se han modificado 100 ficheros con 715 adiciones y 504 borrados
  1. 1 1
      code/AssetLib/3DS/3DSExporter.cpp
  2. 2 2
      code/AssetLib/3DS/3DSLoader.cpp
  3. 2 2
      code/AssetLib/3MF/D3MFOpcPackage.cpp
  4. 5 5
      code/AssetLib/AC/ACLoader.cpp
  5. 1 1
      code/AssetLib/ASE/ASELoader.cpp
  6. 2 2
      code/AssetLib/ASE/ASEParser.cpp
  7. 5 2
      code/AssetLib/Assxml/AssxmlFileWriter.cpp
  8. 4 4
      code/AssetLib/B3D/B3DImporter.cpp
  9. 1 1
      code/AssetLib/Blender/BlenderDNA.cpp
  10. 1 1
      code/AssetLib/Blender/BlenderDNA.inl
  11. 6 6
      code/AssetLib/Blender/BlenderLoader.cpp
  12. 6 6
      code/AssetLib/Blender/BlenderModifier.cpp
  13. 1 1
      code/AssetLib/Blender/BlenderModifier.h
  14. 3 3
      code/AssetLib/C4D/C4DImporter.cpp
  15. 18 19
      code/AssetLib/COB/COBLoader.cpp
  16. 8 8
      code/AssetLib/Collada/ColladaLoader.cpp
  17. 16 28
      code/AssetLib/Collada/ColladaParser.cpp
  18. 1 1
      code/AssetLib/DXF/DXFHelper.h
  19. 12 12
      code/AssetLib/DXF/DXFLoader.cpp
  20. 1 1
      code/AssetLib/FBX/FBXBinaryTokenizer.cpp
  21. 77 24
      code/AssetLib/FBX/FBXConverter.cpp
  22. 1 1
      code/AssetLib/FBX/FBXDocument.cpp
  23. 2 2
      code/AssetLib/FBX/FBXDocumentUtil.cpp
  24. 1 1
      code/AssetLib/FBX/FBXMaterial.cpp
  25. 27 27
      code/AssetLib/FBX/FBXMeshGeometry.cpp
  26. 1 1
      code/AssetLib/FBX/FBXProperties.cpp
  27. 2 2
      code/AssetLib/IFC/IFCBoolean.cpp
  28. 3 3
      code/AssetLib/IFC/IFCGeometry.cpp
  29. 7 7
      code/AssetLib/IFC/IFCLoader.cpp
  30. 2 2
      code/AssetLib/IFC/IFCMaterial.cpp
  31. 4 4
      code/AssetLib/IFC/IFCProfile.cpp
  32. 1 1
      code/AssetLib/IFC/IFCUtil.cpp
  33. 4 4
      code/AssetLib/Irr/IRRLoader.cpp
  34. 1 1
      code/AssetLib/Irr/IRRShared.cpp
  35. 1 1
      code/AssetLib/LWO/LWOBLoader.cpp
  36. 7 7
      code/AssetLib/LWO/LWOLoader.cpp
  37. 2 2
      code/AssetLib/LWO/LWOMaterial.cpp
  38. 2 2
      code/AssetLib/LWS/LWSLoader.cpp
  39. 8 8
      code/AssetLib/M3D/M3DImporter.cpp
  40. 27 16
      code/AssetLib/MD3/MD3Loader.cpp
  41. 3 0
      code/AssetLib/MD3/MD3Loader.h
  42. 2 2
      code/AssetLib/MD5/MD5Loader.cpp
  43. 1 1
      code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp
  44. 1 1
      code/AssetLib/MS3D/MS3DLoader.cpp
  45. 1 1
      code/AssetLib/NDO/NDOLoader.cpp
  46. 5 5
      code/AssetLib/NFF/NFFLoader.cpp
  47. 5 5
      code/AssetLib/Obj/ObjFileParser.cpp
  48. 18 18
      code/AssetLib/Ogre/OgreBinarySerializer.cpp
  49. 16 16
      code/AssetLib/Ogre/OgreMaterial.cpp
  50. 2 2
      code/AssetLib/Ogre/OgreStructs.cpp
  51. 11 11
      code/AssetLib/Ogre/OgreXmlSerializer.cpp
  52. 9 9
      code/AssetLib/OpenGEX/OpenGEXImporter.cpp
  53. 1 1
      code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp
  54. 1 1
      code/AssetLib/Q3D/Q3DLoader.cpp
  55. 2 3
      code/AssetLib/SIB/SIBImporter.cpp
  56. 2 2
      code/AssetLib/STEPParser/STEPFileReader.cpp
  57. 3 3
      code/AssetLib/Unreal/UnrealLoader.cpp
  58. 1 1
      code/AssetLib/X/XFileImporter.cpp
  59. 1 1
      code/AssetLib/glTF/glTFExporter.cpp
  60. 2 0
      code/AssetLib/glTF2/glTF2Asset.h
  61. 2 0
      code/AssetLib/glTF2/glTF2Asset.inl
  62. 13 0
      code/AssetLib/glTF2/glTF2AssetWriter.inl
  63. 34 6
      code/AssetLib/glTF2/glTF2Exporter.cpp
  64. 20 14
      code/AssetLib/glTF2/glTF2Importer.cpp
  65. 3 3
      code/Common/BaseImporter.cpp
  66. 1 1
      code/Common/DefaultIOSystem.cpp
  67. 1 3
      code/Common/DefaultLogger.cpp
  68. 1 1
      code/Common/FileSystemFilter.h
  69. 4 4
      code/Common/Importer.cpp
  70. 1 1
      code/Common/SceneCombiner.cpp
  71. 1 1
      code/Common/Subdivision.cpp
  72. 3 4
      code/Material/MaterialSystem.cpp
  73. 6 6
      code/PostProcessing/ArmaturePopulate.cpp
  74. 1 1
      code/PostProcessing/CalcTangentsProcess.cpp
  75. 1 1
      code/PostProcessing/DeboneProcess.cpp
  76. 3 3
      code/PostProcessing/EmbedTexturesProcess.cpp
  77. 1 1
      code/PostProcessing/FindDegenerates.cpp
  78. 1 1
      code/PostProcessing/FindInstancesProcess.cpp
  79. 1 1
      code/PostProcessing/FindInvalidDataProcess.cpp
  80. 1 1
      code/PostProcessing/FixNormalsStep.cpp
  81. 2 2
      code/PostProcessing/ImproveCacheLocality.cpp
  82. 2 2
      code/PostProcessing/JoinVerticesProcess.cpp
  83. 1 1
      code/PostProcessing/LimitBoneWeightsProcess.cpp
  84. 1 1
      code/PostProcessing/OptimizeGraph.cpp
  85. 1 1
      code/PostProcessing/OptimizeMeshes.cpp
  86. 3 3
      code/PostProcessing/PretransformVertices.cpp
  87. 2 2
      code/PostProcessing/RemoveRedundantMaterials.cpp
  88. 2 2
      code/PostProcessing/SplitByBoneCountProcess.cpp
  89. 3 3
      code/PostProcessing/TextureTransform.cpp
  90. 1 1
      code/PostProcessing/ValidateDataStructure.cpp
  91. 3 0
      include/assimp/Exceptional.h
  92. 1 1
      include/assimp/LineSplitter.h
  93. 16 49
      include/assimp/LogAux.h
  94. 48 63
      include/assimp/Logger.hpp
  95. 2 2
      include/assimp/Profiler.h
  96. 137 10
      include/assimp/XmlParser.h
  97. 11 2
      include/assimp/config.h.in
  98. 1 1
      include/assimp/fast_atof.h
  99. 12 0
      include/assimp/material.h
  100. 4 0
      include/assimp/mesh.h

+ 1 - 1
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;
     }
 

+ 2 - 2
code/AssetLib/3DS/3DSLoader.cpp

@@ -305,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();
@@ -934,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

+ 2 - 2
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);
         }
     }
 }

+ 5 - 5
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<Subdivider> 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<aiMesh *> 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<Material> materials;
     materials.reserve(5);

+ 1 - 1
code/AssetLib/ASE/ASELoader.cpp

@@ -614,7 +614,7 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &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, ")");
         }
     }
 

+ 2 - 2
code/AssetLib/ASE/ASEParser.cpp

@@ -677,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;
@@ -1125,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;

+ 5 - 2
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<TextureCoords num=\"%u\" set=\"%u\" num_components=\"%u\"> \n", mesh->mNumVertices,
-                        a, mesh->mNumUVComponents[a]);
+                ioprintf(io, "\t\t<TextureCoords num=\"%u\" set=\"%u\" name=\"%s\" num_components=\"%u\"> \n",
+                         mesh->mNumVertices,
+                         a,
+                         mesh->mTextureCoordsNames[a].C_Str(),
+                         mesh->mNumUVComponents[a]);
 
                 if (!shortened) {
                     if (mesh->mNumUVComponents[a] == 3) {

+ 4 - 4
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;

+ 1 - 1
code/AssetLib/Blender/BlenderDNA.cpp

@@ -198,7 +198,7 @@ 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");
 
 #if ASSIMP_BUILD_BLENDER_DEBUG_DNA
     dna.DumpToFile();

+ 1 - 1
code/AssetLib/Blender/BlenderDNA.inl

@@ -565,7 +565,7 @@ template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(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;
     }
 

+ 6 - 6
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,
@@ -434,7 +434,7 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M
 
         curTex->pcData = reinterpret_cast<aiTexel *>(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");
 }
 
 // ------------------------------------------------------------------------------------------------

+ 6 - 6
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, "`");
 }
 

+ 1 - 1
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;
     }
 };

+ 3 - 3
code/AssetLib/C4D/C4DImporter.cpp

@@ -238,7 +238,7 @@ bool C4DImporter::ReadShader(aiMaterial* out, BaseShader* shader) {
             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();
     }
@@ -281,7 +281,7 @@ void C4DImporter::ReadMaterials(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();
     }
@@ -335,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);

+ 18 - 19
code/AssetLib/COB/COBLoader.cpp

@@ -152,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");
     }
@@ -301,8 +301,7 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
                     }
                     std::unique_ptr<const Material> 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());
                     }
@@ -527,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;
     }
 
@@ -539,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]);
@@ -550,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];
@@ -563,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];
@@ -583,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;
     }
 
@@ -594,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");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -628,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];
@@ -642,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);
@@ -1033,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;
     }
 
@@ -1048,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<float>(reader.GetI1());
@@ -1176,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

+ 8 - 8
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");

+ 16 - 28
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) {
@@ -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 &currentName = 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 &currentName = 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 &currentName = 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 &currentName = 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 &currentName = 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 &currentName = 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 &currentName = 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 &currentName = 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 &currentName = currentNode.name();
@@ -1608,8 +1597,7 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
     ai_assert(primType != Prim_Invalid);
 
     // also a number of <input> elements, but in addition a <p> 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 &currentName = 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;
 }
 

+ 1 - 1
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);

+ 12 - 12
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<CR><LF><SUB><NULL>
-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()) {

+ 1 - 1
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

+ 77 - 24
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<unsigned int> &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<aiVector3D> &vertices = mesh.GetVertices();
     const std::vector<unsigned int> &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<unsigned int> FBXConverter::ConvertLine(const LineGeometry &line, ai
     const std::vector<aiVector3D> &vertices = line.GetVertices();
     const std::vector<int> &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<aiBone *> &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<aiBone *> &local_mesh_bones, const
         bone_map.insert(std::pair<const std::string, aiBone *>(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<float>(props, "Maya|use_color_map", ok);
+    if (ok) {
+        out_mat->AddProperty(&useColorMap, 1, AI_MATKEY_USE_COLOR_MAP);
+    }
+
+    const float useMetallicMap = PropertyGet<float>(props, "Maya|use_metallic_map", ok);
+    if (ok) {
+        out_mat->AddProperty(&useMetallicMap, 1, AI_MATKEY_USE_METALLIC_MAP);
+    }
+
+    const float metallicFactor = PropertyGet<float>(props, "Maya|metallic", ok);
+    if (ok) {
+        out_mat->AddProperty(&metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR);
+    }
+
+    const float useRoughnessMap = PropertyGet<float>(props, "Maya|use_roughness_map", ok);
+    if (ok) {
+        out_mat->AddProperty(&useRoughnessMap, 1, AI_MATKEY_USE_ROUGHNESS_MAP);
+    }
+
+    const float roughnessFactor = PropertyGet<float>(props, "Maya|roughness", ok);
+    if (ok) {
+        out_mat->AddProperty(&roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR);
+    }
+
+    const float useEmissiveMap = PropertyGet<float>(props, "Maya|use_emissive_map", ok);
+    if (ok) {
+        out_mat->AddProperty(&useEmissiveMap, 1, AI_MATKEY_USE_EMISSIVE_MAP);
+    }
+
+    const float emissiveIntensity = PropertyGet<float>(props, "Maya|emissive_intensity", ok);
+    if (ok) {
+        out_mat->AddProperty(&emissiveIntensity, 1, AI_MATKEY_EMISSIVE_INTENSITY);
+    }
+
+    const float useAOMap = PropertyGet<float>(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<aiNodeAnim *> &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<aiNodeAnim *> &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;
             }
 

+ 1 - 1
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

+ 2 - 2
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);
     }
 }
 

+ 1 - 1
code/AssetLib/FBX/FBXMaterial.cpp

@@ -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());
         }
     }

+ 27 - 27
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<T>& 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<T>& 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<T>& 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<T>& 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<T>& 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<aiVector3D>& 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<aiVector3D>& 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<int>& 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<int>& 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);
     }
 }
 // ------------------------------------------------------------------------------------------------

+ 1 - 1
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<float>(ParseTokenAsFloat(*tok[4]));
     }

+ 2 - 2
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<Schema_2x3::IfcBooleanResult>()) {
         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());
     }
 }
 

+ 3 - 3
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;
     }
 

+ 7 - 7
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();

+ 2 - 2
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<std::string>(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<aiMaterial> mat(new aiMaterial());

+ 4 - 4
code/AssetLib/IFC/IFCProfile.cpp

@@ -68,7 +68,7 @@ bool ProcessCurve(const Schema_2x3::IfcCurve& curve,  TempMesh& meshout, Convers
 {
     std::unique_ptr<const Curve> 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<unsigned int>(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();

+ 1 - 1
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;
     }
 }

+ 4 - 4
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));
@@ -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;
 										}

+ 1 - 1
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);
 					}
 				}
 

+ 1 - 1
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;

+ 7 - 7
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);
                 }
             }

+ 2 - 2
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);
         }
     }
 

+ 2 - 2
code/AssetLib/LWS/LWSLoader.cpp

@@ -346,7 +346,7 @@ void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vector<Attachm
         if (src.path.length()) {
             obj = batch.GetImport(src.id);
             if (!obj) {
-                ASSIMP_LOG_ERROR("LWS: Failed to read external file " + src.path);
+                ASSIMP_LOG_ERROR("LWS: Failed to read external file ", src.path);
             } else {
                 if (obj->mRootNode->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

+ 8 - 8
code/AssetLib/M3D/M3DImporter.cpp

@@ -184,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);
@@ -200,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);
@@ -230,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;
@@ -325,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;
@@ -380,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;
@@ -499,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;
@@ -540,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;
@@ -703,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()) {

+ 27 - 16
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.
@@ -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<Q3Shader::SkinData::TextureEntry>::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);
             }
         }
     }

+ 3 - 0
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;
 

+ 2 - 2
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;
     }
 

+ 1 - 1
code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp

@@ -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;
     }
 }

+ 1 - 1
code/AssetLib/MS3D/MS3DLoader.cpp

@@ -387,7 +387,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
                 }
 
                 const std::string& s = std::string(reinterpret_cast<char*>(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)) {

+ 1 - 1
code/AssetLib/NDO/NDOLoader.cpp

@@ -147,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 */

+ 5 - 5
code/AssetLib/NFF/NFFLoader.cpp

@@ -132,7 +132,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector<ShadingInfo> &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<ShadingInfo> &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<ShadingInfo> &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<ShadingInfo> &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;

+ 5 - 5
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<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
             return;
         }
@@ -660,7 +660,7 @@ void ObjFileParser::getNewMaterial() {
     std::map<std::string, ObjFile::Material *>::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

+ 18 - 18
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<MeshChunkId>(id)) : SkeletonHeaderToString(static_cast<SkeletonChunkId>(id))));
+        ASSIMP_LOG_DEBUG((assetMode == AM_Mesh ? MeshHeaderToString(static_cast<MeshChunkId>(id)) : SkeletonHeaderToString(static_cast<SkeletonChunkId>(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<bool>();
 
     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<uint32_t>(submesh->indexData->count / 3);
     submesh->indexData->is32bit = Read<bool>();
 
-    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<uint32_t>();
 
-    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<uint16_t>();
     element.index = Read<uint16_t>();
 
-    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) {

+ 16 - 16
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<IOStream> 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);

+ 2 - 2
code/AssetLib/Ogre/OgreStructs.cpp

@@ -545,7 +545,7 @@ aiMesh *SubMesh::ConvertToAssimpMesh(Mesh *parent) {
             dest->mNumUVComponents[0] = static_cast<unsigned int>(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<unsigned int>(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;
         }
     }

+ 11 - 11
code/AssetLib/Ogre/OgreXmlSerializer.cpp

@@ -256,7 +256,7 @@ void OgreXmlSerializer::ReadMesh(MeshXml *mesh) {
 
 void OgreXmlSerializer::ReadGeometry(XmlNode &node, VertexDataXml *dest) {
     dest->count = ReadAttribute<uint32_t>(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 &currentName = 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<bool>(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<uint16_t>(i)) {
             throw DeadlyImportError("Bone ids are not in sequence starting from 0. Missing index ", i);

+ 9 - 9
code/AssetLib/OpenGEX/OpenGEXImporter.cpp

@@ -726,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.");
             }
         }
     }
@@ -749,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;
     }
 

+ 1 - 1
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);
                 }
             }
         }

+ 1 - 1
code/AssetLib/Q3D/Q3DLoader.cpp

@@ -125,7 +125,7 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
     }
 
     // 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

+ 2 - 3
code/AssetLib/SIB/SIBImporter.cpp

@@ -174,14 +174,13 @@ static void UnknownChunk(StreamReaderLE * /*stream*/, const SIBChunk &chunk) {
         static_cast<char>(chunk.Tag & 0xff)
     };
 
-    ASSIMP_LOG_WARN((Formatter::format(), "SIB: Skipping unknown '", ai_str_toprintable(temp, 4), "' 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)

+ 2 - 2
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");
     }
 }
 

+ 3 - 3
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<IOStream> p(pIOHandler->Open(d_path));

+ 1 - 1
code/AssetLib/X/XFileImporter.cpp

@@ -602,7 +602,7 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Materi
             }
 
             if( oldMat.sceneIndex == SIZE_MAX ) {
-                ASSIMP_LOG_WARN_F( "Could not resolve global material reference \"", oldMat.mName, "\"" );
+                ASSIMP_LOG_WARN( "Could not resolve global material reference \"", oldMat.mName, "\"" );
                 oldMat.sceneIndex = 0;
             }
 

+ 1 - 1
code/AssetLib/glTF/glTFExporter.cpp

@@ -604,7 +604,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;
 		}
 

+ 2 - 0
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;

+ 2 - 0
code/AssetLib/glTF2/glTF2Asset.inl

@@ -1144,6 +1144,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 +2125,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
 }

+ 13 - 0
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<class T>

+ 34 - 6
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>& 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>& 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>& 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<uint8_t *>(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<uint8_t *>(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);

+ 20 - 14
code/AssetLib/glTF2/glTF2Importer.cpp

@@ -325,7 +325,7 @@ static aiMaterial *ImportMaterial(std::vector<int> &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<glTF2::Accessor> 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<std::unique_ptr<aiMesh>> 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) {

+ 3 - 3
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<float>(activeScale));
 
-    ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: ", activeScale);
+    ASSIMP_LOG_DEBUG("UpdateImporterScale scale set: ", activeScale);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -215,7 +215,7 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
             // 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();

+ 1 - 1
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;

+ 1 - 3
code/Common/DefaultLogger.cpp

@@ -177,9 +177,7 @@ 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;
     }

+ 1 - 1
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. */

+ 4 - 4
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) {

+ 1 - 1
code/Common/SceneCombiner.cpp

@@ -612,7 +612,7 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
                 }
             }
             if (!(*it).resolved) {
-                ASSIMP_LOG_ERROR_F("SceneCombiner: Failed to resolve attachment ", (*it).node->mName.data,
+                ASSIMP_LOG_ERROR("SceneCombiner: Failed to resolve attachment ", (*it).node->mName.data,
                         " ", (*it).attachToNode->mName.data);
             }
         }

+ 1 - 1
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<unsigned int>(edges.size()), " edges). ");
             }
         }

+ 3 - 4
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;

+ 6 - 6
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<aiBone *, aiNode *> 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<aiBone *, aiNode *>(bone, node));
     }
@@ -203,7 +203,7 @@ aiNode *ArmaturePopulate::GetArmatureRoot(aiNode *bone_node,
                                           std::vector<aiBone *> &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);
 

+ 1 - 1
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;
     }
 

+ 1 - 1
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

+ 3 - 3
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;
             }
         }

+ 1 - 1
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;
 }

+ 1 - 1
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 {

+ 1 - 1
code/PostProcessing/FindInvalidDataProcess.cpp

@@ -200,7 +200,7 @@ inline bool ProcessArray(T *&in, unsigned int num, const char *name,
         const std::vector<bool> &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;

+ 1 - 1
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

+ 2 - 2
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;

+ 2 - 2
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"),

+ 1 - 1
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);
     }
 }

+ 1 - 1
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");
 		}

+ 1 - 1
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" );
     }

+ 3 - 3
code/PostProcessing/PretransformVertices.cpp

@@ -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, ")");
 	}
 }

+ 2 - 2
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.");
     }
 }

+ 2 - 2
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." );
 }
 
 // ------------------------------------------------------------------------------------------------

+ 3 - 3
code/PostProcessing/TextureTransform.cpp

@@ -108,7 +108,7 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
         if (rounded)
         {
             out -= rounded * static_cast<float>(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<unsigned int>(trafo.size()), " UV channels required but just ", 
+                ASSIMP_LOG_ERROR(static_cast<unsigned int>(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");
         }

+ 1 - 1
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));
 }
 
 // ------------------------------------------------------------------------------------------------

+ 3 - 0
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<const char*>(message)) {}
+
     /** Constructor with arguments */
     template<typename... T>
     explicit DeadlyImportError(T&&... args) :

+ 1 - 1
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
 */

+ 16 - 49
include/assimp/LogAux.h

@@ -64,81 +64,48 @@ public:
     template<typename... T>
     static void ThrowException(T&&... args)
     {
-        throw DeadlyImportError(Prefix(), args...);
+        throw DeadlyImportError(Prefix(), std::forward<T>(args)...);
     }
 
     // ------------------------------------------------------------------------------------------------
-    static void LogWarn(const Formatter::format& message)   {
-        if (!DefaultLogger::isNullLogger()) {
-            ASSIMP_LOG_WARN(Prefix()+(std::string)message);
-        }
-    }
-
-    // ------------------------------------------------------------------------------------------------
-    static void LogError(const Formatter::format& message)  {
-        if (!DefaultLogger::isNullLogger()) {
-            ASSIMP_LOG_ERROR(Prefix()+(std::string)message);
-        }
-    }
-
-    // ------------------------------------------------------------------------------------------------
-    static void LogInfo(const Formatter::format& message)   {
-        if (!DefaultLogger::isNullLogger()) {
-            ASSIMP_LOG_INFO(Prefix()+(std::string)message);
-        }
-    }
-
-    // ------------------------------------------------------------------------------------------------
-    static void LogDebug(const Formatter::format& message)  {
-        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) {
+    template<typename... T>
+    static void LogWarn(T&&... args) {
         if (!DefaultLogger::isNullLogger()) {
-            LogWarn(Formatter::format(message));
+            ASSIMP_LOG_WARN(Prefix(), std::forward<T>(args)...);
         }
     }
 
     // ------------------------------------------------------------------------------------------------
-    static void LogError  (const char* message) {
+    template<typename... T>
+    static void LogError(T&&... args)  {
         if (!DefaultLogger::isNullLogger()) {
-            LogError(Formatter::format(message));
+            ASSIMP_LOG_ERROR(Prefix(), std::forward<T>(args)...);
         }
     }
 
     // ------------------------------------------------------------------------------------------------
-    static void LogInfo  (const char* message) {
+    template<typename... T>
+    static void LogInfo(T&&... args)  {
         if (!DefaultLogger::isNullLogger()) {
-            LogInfo(Formatter::format(message));
+            ASSIMP_LOG_INFO(Prefix(), std::forward<T>(args)...);
         }
     }
 
     // ------------------------------------------------------------------------------------------------
-    static void LogDebug  (const char* message) {
+    template<typename... T>
+    static void LogDebug(T&&... args)  {
         if (!DefaultLogger::isNullLogger()) {
-            LogDebug(Formatter::format(message));
+            ASSIMP_LOG_DEBUG(Prefix(), std::forward<T>(args)...);
         }
     }
 
     // ------------------------------------------------------------------------------------------------
-    static void LogVerboseDebug  (const char* message) {
+    template<typename... T>
+    static void LogVerboseDebug(T&&... args)  {
         if (!DefaultLogger::isNullLogger()) {
-            LogVerboseDebug(Formatter::format(message));
+            ASSIMP_LOG_VERBOSE_DEBUG(Prefix(), std::forward<T>(args)...);
         }
     }
-#endif
 
 private:
     static const char* Prefix();

+ 48 - 63
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<typename... T>
+    void debug(T&&... args) {
+        debug(formatMessage(std::forward<T>(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<typename... T>
+    void verboseDebug(T&&... args) {
+        verboseDebug(formatMessage(std::forward<T>(args)...).c_str());
+    }
 
     // ----------------------------------------------------------------------
     /** @brief  Writes a info message
      *  @param  message Info message*/
     void info(const char* message);
-    void info(const std::string &message);
+
+    template<typename... T>
+    void info(T&&... args) {
+        info(formatMessage(std::forward<T>(args)...).c_str());
+    }
 
     // ----------------------------------------------------------------------
     /** @brief  Writes a warning message
      *  @param  message Warn message*/
     void warn(const char* message);
-    void warn(const std::string &message);
+
+    template<typename... T>
+    void warn(T&&... args) {
+        warn(formatMessage(std::forward<T>(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<typename... T>
+    void error(T&&... args) {
+        error(formatMessage(std::forward<T>(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<typename... T, typename U>
+    std::string formatMessage(Assimp::Formatter::format f, U&& u, T&&... args) {
+        return formatMessage(std::move(f << std::forward<U>(u)), std::forward<T>(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_ERROR_F(string, ...) \
-	Assimp::DefaultLogger::get()->error((Assimp::Formatter::format(string), __VA_ARGS__))
-
-#define ASSIMP_LOG_DEBUG_F(string, ...) \
-	Assimp::DefaultLogger::get()->debug((Assimp::Formatter::format(string), __VA_ARGS__))
-
-#define ASSIMP_LOG_VERBOSE_DEBUG_F(string, ...) \
-	Assimp::DefaultLogger::get()->verboseDebug((Assimp::Formatter::format(string), __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_WARN(...) \
+	Assimp::DefaultLogger::get()->warn(__VA_ARGS__)
 
-#define ASSIMP_LOG_ERROR(string) \
-	Assimp::DefaultLogger::get()->error(string)
+#define ASSIMP_LOG_ERROR(...) \
+	Assimp::DefaultLogger::get()->error(__VA_ARGS__)
 
-#define ASSIMP_LOG_DEBUG(string) \
-	Assimp::DefaultLogger::get()->debug(string)
+#define ASSIMP_LOG_DEBUG(...) \
+	Assimp::DefaultLogger::get()->debug(__VA_ARGS__)
 
-#define ASSIMP_LOG_VERBOSE_DEBUG(string) \
-	Assimp::DefaultLogger::get()->verboseDebug(string)
+#define ASSIMP_LOG_VERBOSE_DEBUG(...) \
+	Assimp::DefaultLogger::get()->verboseDebug(__VA_ARGS__)
 
-#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

+ 2 - 2
include/assimp/Profiler.h

@@ -76,7 +76,7 @@ public:
     /** Start a named timer */
     void BeginRegion(const std::string& region) {
         regions[region] = std::chrono::system_clock::now();
-        ASSIMP_LOG_DEBUG((format("START `"),region,"`"));
+        ASSIMP_LOG_DEBUG("START `",region,"`");
     }
 
 
@@ -88,7 +88,7 @@ public:
         }
 
         std::chrono::duration<double> 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:

+ 137 - 10
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 <class TNodeType>
 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<XmlNode> theParser;
+/// if (theParser.parse(fileStream)) {
+///     auto node = theParser.getRootNode();
+///     for ( auto currentNode : node.children()) {
+///         // Will loop over all children
+///     }
+/// }
+/// @endcode
+/// @tparam TNodeType 
 template <class TNodeType>
 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,36 +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 {
-            std::ostringstream oss;
-            oss << "Error while parsing XML: " << parse_result.description() << " @ " << parse_result.offset;
-            ASSIMP_LOG_DEBUG(oss.str());
-            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()) {
@@ -178,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()) {
@@ -188,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()) {
@@ -201,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;
@@ -212,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;
@@ -222,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()) {
@@ -232,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()) {
@@ -243,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()) {
@@ -254,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;
@@ -273,17 +371,36 @@ public:
 
 using XmlParser = TXmlParser<pugi::xml_node>;
 
+///	@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);
         }
@@ -292,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);
@@ -301,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;
@@ -312,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;

+ 11 - 2
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

+ 1 - 1
include/assimp/fast_atof.h

@@ -206,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;
         }
 

+ 12 - 0
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

+ 4 - 0
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

Algunos archivos no se mostraron porque demasiados archivos cambiaron en este cambio