Ver Fonte

Merge branch 'master' into UVStreamNames

Kim Kulling há 4 anos atrás
pai
commit
aeaa22cbbd
100 ficheiros alterados com 802 adições e 751 exclusões
  1. 8 7
      CMakeLists.txt
  2. 3 3
      Readme.md
  3. 1 1
      code/AssetLib/3DS/3DSConverter.cpp
  4. 4 3
      code/AssetLib/3DS/3DSExporter.cpp
  5. 9 3
      code/AssetLib/3DS/3DSLoader.cpp
  6. 53 50
      code/AssetLib/3MF/3MFXmlTags.h
  7. 26 11
      code/AssetLib/3MF/D3MFExporter.cpp
  8. 107 99
      code/AssetLib/3MF/D3MFImporter.cpp
  9. 1 1
      code/AssetLib/3MF/D3MFImporter.h
  10. 5 5
      code/AssetLib/3MF/D3MFOpcPackage.cpp
  11. 5 5
      code/AssetLib/AC/ACLoader.cpp
  12. 3 6
      code/AssetLib/AMF/AMFImporter.cpp
  13. 0 1
      code/AssetLib/AMF/AMFImporter.hpp
  14. 2 2
      code/AssetLib/AMF/AMFImporter_Postprocess.cpp
  15. 1 1
      code/AssetLib/ASE/ASELoader.cpp
  16. 8 2
      code/AssetLib/ASE/ASEParser.cpp
  17. 1 1
      code/AssetLib/Assbin/AssbinLoader.cpp
  18. 4 4
      code/AssetLib/B3D/B3DImporter.cpp
  19. 2 2
      code/AssetLib/BVH/BVHLoader.cpp
  20. 4 4
      code/AssetLib/Blender/BlenderDNA.cpp
  21. 8 1
      code/AssetLib/Blender/BlenderDNA.h
  22. 1 1
      code/AssetLib/Blender/BlenderDNA.inl
  23. 9 15
      code/AssetLib/Blender/BlenderLoader.cpp
  24. 0 1
      code/AssetLib/Blender/BlenderLoader.h
  25. 6 6
      code/AssetLib/Blender/BlenderModifier.cpp
  26. 1 1
      code/AssetLib/Blender/BlenderModifier.h
  27. 26 44
      code/AssetLib/C4D/C4DImporter.cpp
  28. 15 24
      code/AssetLib/C4D/C4DImporter.h
  29. 25 20
      code/AssetLib/COB/COBLoader.cpp
  30. 9 9
      code/AssetLib/Collada/ColladaLoader.cpp
  31. 17 29
      code/AssetLib/Collada/ColladaParser.cpp
  32. 1 1
      code/AssetLib/DXF/DXFHelper.h
  33. 7 7
      code/AssetLib/DXF/DXFLoader.cpp
  34. 1 1
      code/AssetLib/FBX/FBXBinaryTokenizer.cpp
  35. 75 24
      code/AssetLib/FBX/FBXConverter.cpp
  36. 1 1
      code/AssetLib/FBX/FBXDocument.cpp
  37. 2 2
      code/AssetLib/FBX/FBXDocumentUtil.cpp
  38. 3 3
      code/AssetLib/FBX/FBXExporter.cpp
  39. 2 2
      code/AssetLib/FBX/FBXMaterial.cpp
  40. 24 24
      code/AssetLib/FBX/FBXMeshGeometry.cpp
  41. 1 1
      code/AssetLib/FBX/FBXProperties.cpp
  42. 2 6
      code/AssetLib/HMP/HMPLoader.cpp
  43. 2 2
      code/AssetLib/IFC/IFCBoolean.cpp
  44. 3 3
      code/AssetLib/IFC/IFCGeometry.cpp
  45. 8 8
      code/AssetLib/IFC/IFCLoader.cpp
  46. 2 2
      code/AssetLib/IFC/IFCMaterial.cpp
  47. 4 4
      code/AssetLib/IFC/IFCProfile.cpp
  48. 1 1
      code/AssetLib/IFC/IFCUtil.cpp
  49. 6 6
      code/AssetLib/Irr/IRRLoader.cpp
  50. 2 2
      code/AssetLib/Irr/IRRMeshLoader.cpp
  51. 1 1
      code/AssetLib/Irr/IRRShared.cpp
  52. 1 1
      code/AssetLib/LWO/LWOBLoader.cpp
  53. 7 7
      code/AssetLib/LWO/LWOLoader.cpp
  54. 2 2
      code/AssetLib/LWO/LWOMaterial.cpp
  55. 2 2
      code/AssetLib/LWS/LWSLoader.cpp
  56. 4 8
      code/AssetLib/M3D/M3DExporter.cpp
  57. 9 19
      code/AssetLib/M3D/M3DImporter.cpp
  58. 0 1
      code/AssetLib/M3D/M3DWrapper.h
  59. 3 35
      code/AssetLib/M3D/m3d.h
  60. 21 23
      code/AssetLib/MD2/MD2Loader.cpp
  61. 28 17
      code/AssetLib/MD3/MD3Loader.cpp
  62. 3 0
      code/AssetLib/MD3/MD3Loader.h
  63. 2 2
      code/AssetLib/MD5/MD5Loader.cpp
  64. 10 10
      code/AssetLib/MDC/MDCLoader.cpp
  65. 5 4
      code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp
  66. 16 4
      code/AssetLib/MDL/MDLLoader.cpp
  67. 4 7
      code/AssetLib/MMD/MMDPmxParser.cpp
  68. 7 2
      code/AssetLib/MS3D/MS3DLoader.cpp
  69. 8 2
      code/AssetLib/NDO/NDOLoader.cpp
  70. 5 5
      code/AssetLib/NFF/NFFLoader.cpp
  71. 5 5
      code/AssetLib/Obj/ObjFileParser.cpp
  72. 15 15
      code/AssetLib/Ogre/OgreBinarySerializer.cpp
  73. 16 16
      code/AssetLib/Ogre/OgreMaterial.cpp
  74. 2 2
      code/AssetLib/Ogre/OgreStructs.cpp
  75. 11 11
      code/AssetLib/Ogre/OgreXmlSerializer.cpp
  76. 15 1
      code/AssetLib/OpenGEX/OpenGEXImporter.cpp
  77. 1 1
      code/AssetLib/Ply/PlyLoader.cpp
  78. 2 2
      code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp
  79. 9 3
      code/AssetLib/Q3D/Q3DLoader.cpp
  80. 11 6
      code/AssetLib/SIB/SIBImporter.cpp
  81. 2 2
      code/AssetLib/STEPParser/STEPFileReader.cpp
  82. 3 3
      code/AssetLib/Unreal/UnrealLoader.cpp
  83. 3 3
      code/AssetLib/X/XFileImporter.cpp
  84. 2 2
      code/AssetLib/X/XFileParser.cpp
  85. 0 4
      code/AssetLib/X3D/X3DImporter.cpp
  86. 0 1
      code/AssetLib/X3D/X3DImporter.hpp
  87. 1 1
      code/AssetLib/XGL/XGLLoader.cpp
  88. 1 1
      code/AssetLib/glTF/glTFExporter.cpp
  89. 13 13
      code/AssetLib/glTF2/glTF2Importer.cpp
  90. 2 2
      code/CApi/CInterfaceIOWrapper.cpp
  91. 6 20
      code/Common/BaseImporter.cpp
  92. 1 1
      code/Common/DefaultIOSystem.cpp
  93. 1 3
      code/Common/DefaultLogger.cpp
  94. 1 1
      code/Common/FileSystemFilter.h
  95. 4 4
      code/Common/Importer.cpp
  96. 15 2
      code/Common/ImporterRegistry.cpp
  97. 1 1
      code/Common/SceneCombiner.cpp
  98. 1 1
      code/Common/Subdivision.cpp
  99. 3 4
      code/Material/MaterialSystem.cpp
  100. 6 6
      code/PostProcessing/ArmaturePopulate.cpp

+ 8 - 7
CMakeLists.txt

@@ -527,12 +527,12 @@ ENDIF()
 MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
 
 SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
-  "Build the C4D importer, which relies on the non-free Melange SDK."
+  "Build the C4D importer, which relies on the non-free Cineware SDK."
 )
 
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
   IF ( MSVC )
-    SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes")
+    SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
 
     # pick the correct prebuilt library
     IF(MSVC15)
@@ -551,22 +551,23 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
       )
     ENDIF()
 
-    SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/libraries/win")
+    SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/libraries/win")
 
     SET(C4D_DEBUG_LIBRARIES
-      "${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_debug.lib"
+      "${C4D_LIB_BASE_PATH}/cinewarelib${C4D_LIB_POSTFIX}/cinewarelib_debug.lib"
       "${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_debug.lib"
     )
     SET(C4D_RELEASE_LIBRARIES
-      "${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_release.lib"
+      "${C4D_LIB_BASE_PATH}/cinewarelib${C4D_LIB_POSTFIX}/cinewarelib_release.lib"
       "${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_release.lib"
     )
 
-    # winsock and winmm are necessary dependencies of melange (this is undocumented, but true.)
+    # winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because
+    # it can be used to communicate with a running Cinema 4D instance
     SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
   ELSE ()
     MESSAGE( FATAL_ERROR
-      "C4D is currently only available on Windows with melange SDK installed in contrib/Melange"
+      "C4D is currently only available on Windows with Cineware SDK installed in contrib/Cineware"
     )
   ENDIF ()
 ELSE ()

+ 3 - 3
Readme.md

@@ -66,9 +66,9 @@ Open Asset Import Library is implemented in C++. The directory structure looks l
 
 The source code is organized in the following way:
 
-	code/Common		The base implementation for importers and the infrastructure
-	code/PostProcessing	The post-processing steps
-	code/<FormatName>	Implementation for import and export for the format
+	code/Common			The base implementation for importers and the infrastructure
+	code/PostProcessing		The post-processing steps
+	code/AssetLib/<FormatName>	Implementation for import and export for the format
 
 ### Where to get help ###
 For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.

+ 1 - 1
code/AssetLib/3DS/3DSConverter.cpp

@@ -69,7 +69,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
     for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) {
         std::string s = mScene->mMaterials[i].mName;
         for (std::string::iterator it = s.begin(); it != s.end(); ++it) {
-            *it = static_cast<char>(::tolower(*it));
+            *it = static_cast<char>(::tolower(static_cast<unsigned char>(*it)));
         }
 
         if (std::string::npos == s.find("default")) continue;

+ 4 - 3
code/AssetLib/3DS/3DSExporter.cpp

@@ -102,13 +102,14 @@ private:
 // preserves the mesh's given name if it has one. |index| is the index
 // of the mesh in |aiScene::mMeshes|.
 std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) {
-    static const std::string underscore = "_";
+    static const char underscore = '_';
     char postfix[10] = { 0 };
     ASSIMP_itoa10(postfix, index);
 
     std::string result = node.mName.C_Str();
     if (mesh.mName.length > 0) {
-        result += underscore + mesh.mName.C_Str();
+        result += underscore;
+        result += mesh.mName.C_Str();
     }
     return result + underscore + postfix;
 }
@@ -378,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;
     }
 

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

@@ -143,7 +143,13 @@ void Discreet3DSImporter::SetupProperties(const Importer * /*pImp*/) {
 // Imports the given file into the given scene structure.
 void Discreet3DSImporter::InternReadFile(const std::string &pFile,
         aiScene *pScene, IOSystem *pIOHandler) {
-    StreamReaderLE theStream(pIOHandler->Open(pFile, "rb"));
+
+    auto theFile = pIOHandler->Open(pFile, "rb");
+    if (!theFile) {
+        throw DeadlyImportError("3DS: Could not open ", pFile);
+    }
+
+    StreamReaderLE theStream(theFile);
 
     // We should have at least one chunk
     if (theStream.GetRemainingSize() < 16) {
@@ -299,7 +305,7 @@ void Discreet3DSImporter::ParseEditorChunk() {
         // print the version number
         char buff[10];
         ASSIMP_itoa10(buff, stream->GetI2());
-        ASSIMP_LOG_INFO_F(std::string("3DS file format version: "), buff);
+        ASSIMP_LOG_INFO("3DS file format version: ", buff);
     } break;
     };
     ASSIMP_3DS_END_CHUNK();
@@ -928,7 +934,7 @@ void Discreet3DSImporter::ParseFaceChunk() {
             }
         }
         if (0xcdcdcdcd == idx) {
-            ASSIMP_LOG_ERROR_F("3DS: Unknown material: ", sz);
+            ASSIMP_LOG_ERROR("3DS: Unknown material: ", sz);
         }
 
         // Now continue and read all material indices

+ 53 - 50
code/AssetLib/3MF/3MFXmlTags.h

@@ -44,63 +44,66 @@ namespace Assimp {
 namespace D3MF {
 
 namespace XmlTag {
+    // Root tag
+    const char* const RootTag = "3MF";
+
     // Meta-data
-    static const std::string meta = "metadata";
-    static const std::string meta_name = "name";
+    const char* const meta = "metadata";
+    const char* const meta_name = "name";
 
     // Model-data specific tags
-    static const std::string model = "model";
-    static const std::string model_unit = "unit";
-    static const std::string metadata = "metadata";
-    static const std::string resources = "resources";
-    static const std::string object = "object";
-    static const std::string mesh = "mesh";
-    static const std::string components = "components";
-    static const std::string component = "component";
-    static const std::string vertices = "vertices";
-    static const std::string vertex = "vertex";
-    static const std::string triangles = "triangles";
-    static const std::string triangle = "triangle";
-    static const std::string x = "x";
-    static const std::string y = "y";
-    static const std::string z = "z";
-    static const std::string v1 = "v1";
-    static const std::string v2 = "v2";
-    static const std::string v3 = "v3";
-    static const std::string id = "id";
-    static const std::string pid = "pid";
-    static const std::string pindex = "pindex";
-    static const std::string p1 = "p1";
-    static const std::string name = "name";
-    static const std::string type = "type";
-    static const std::string build = "build";
-    static const std::string item = "item";
-    static const std::string objectid = "objectid";
-    static const std::string transform = "transform";
+    const char* const model = "model";
+    const char* const model_unit = "unit";
+    const char* const metadata = "metadata";
+    const char* const resources = "resources";
+    const char* const object = "object";
+    const char* const mesh = "mesh";
+    const char* const components = "components";
+    const char* const component = "component";
+    const char* const vertices = "vertices";
+    const char* const vertex = "vertex";
+    const char* const triangles = "triangles";
+    const char* const triangle = "triangle";
+    const char* const x = "x";
+    const char* const y = "y";
+    const char* const z = "z";
+    const char* const v1 = "v1";
+    const char* const v2 = "v2";
+    const char* const v3 = "v3";
+    const char* const id = "id";
+    const char* const pid = "pid";
+    const char* const pindex = "pindex";
+    const char* const p1 = "p1";
+    const char* const name = "name";
+    const char* const type = "type";
+    const char* const build = "build";
+    const char* const item = "item";
+    const char* const objectid = "objectid";
+    const char* const transform = "transform";
 
     // Material definitions
-    static const std::string basematerials = "basematerials";
-    static const std::string basematerials_id = "id";
-    static const std::string basematerials_base = "base";
-    static const std::string basematerials_name = "name";
-    static const std::string basematerials_displaycolor = "displaycolor";
+    const char* const basematerials = "basematerials";
+    const char* const basematerials_id = "id";
+    const char* const basematerials_base = "base";
+    const char* const basematerials_name = "name";
+    const char* const basematerials_displaycolor = "displaycolor";
 
     // Meta info tags
-    static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
-    static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
-    static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
-    static const std::string SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
-    static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships";
-    static const std::string RELS_RELATIONSHIP_NODE = "Relationship";
-    static const std::string RELS_ATTRIB_TARGET = "Target";
-    static const std::string RELS_ATTRIB_TYPE = "Type";
-    static const std::string RELS_ATTRIB_ID = "Id";
-    static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
-    static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
-    static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
-    static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
-    static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
-}
+    const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
+    const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
+    const char* const SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
+    const char* const SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
+    const char* const RELS_RELATIONSHIP_CONTAINER = "Relationships";
+    const char* const RELS_RELATIONSHIP_NODE = "Relationship";
+    const char* const RELS_ATTRIB_TARGET = "Target";
+    const char* const RELS_ATTRIB_TYPE = "Type";
+    const char* const RELS_ATTRIB_ID = "Id";
+    const char* const PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
+    const char* const PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
+    const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
+    const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
+    const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
+    }
 
 } // Namespace D3MF
 } // Namespace Assimp

+ 26 - 11
code/AssetLib/3MF/D3MFExporter.cpp

@@ -307,18 +307,26 @@ void D3MFExporter::writeMesh(aiMesh *mesh) {
         return;
     }
 
-    mModelOutput << "<" << XmlTag::mesh << ">" << std::endl;
-    mModelOutput << "<" << XmlTag::vertices << ">" << std::endl;
+    mModelOutput << "<"
+                 << XmlTag::mesh
+                 << ">" << "\n";
+    mModelOutput << "<"
+                 << XmlTag::vertices
+                 << ">" << "\n";
     for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
         writeVertex(mesh->mVertices[i]);
     }
-    mModelOutput << "</" << XmlTag::vertices << ">" << std::endl;
+    mModelOutput << "</"
+                 << XmlTag::vertices << ">"
+                 << "\n";
 
     const unsigned int matIdx(mesh->mMaterialIndex);
 
     writeFaces(mesh, matIdx);
 
-    mModelOutput << "</" << XmlTag::mesh << ">" << std::endl;
+    mModelOutput << "</"
+                 << XmlTag::mesh << ">"
+                 << "\n";
 }
 
 void D3MFExporter::writeVertex(const aiVector3D &pos) {
@@ -334,27 +342,34 @@ void D3MFExporter::writeFaces(aiMesh *mesh, unsigned int matIdx) {
     if (!mesh->HasFaces()) {
         return;
     }
-    mModelOutput << "<" << XmlTag::triangles << ">" << std::endl;
+    mModelOutput << "<"
+                 << XmlTag::triangles << ">"
+                 << "\n";
     for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
         aiFace &currentFace = mesh->mFaces[i];
         mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\""
                      << currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2]
                      << "\" pid=\"1\" p1=\"" + ai_to_string(matIdx) + "\" />";
-        mModelOutput << std::endl;
+        mModelOutput << "\n";
     }
-    mModelOutput << "</" << XmlTag::triangles << ">";
-    mModelOutput << std::endl;
+    mModelOutput << "</"
+                 << XmlTag::triangles
+                 << ">";
+    mModelOutput << "\n";
 }
 
 void D3MFExporter::writeBuild() {
-    mModelOutput << "<" << XmlTag::build << ">" << std::endl;
+    mModelOutput << "<"
+                 << XmlTag::build
+                 << ">"
+                 << "\n";
 
     for (size_t i = 0; i < mBuildItems.size(); ++i) {
         mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>";
-        mModelOutput << std::endl;
+        mModelOutput << "\n";
     }
     mModelOutput << "</" << XmlTag::build << ">";
-    mModelOutput << std::endl;
+    mModelOutput << "\n";
 }
 
 void D3MFExporter::zipContentType(const std::string &filename) {

+ 107 - 99
code/AssetLib/3MF/D3MFImporter.cpp

@@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
 
 #include "D3MFImporter.h"
+#include "3MFXmlTags.h"
+#include "D3MFOpcPackage.h"
 
 #include <assimp/StringComparison.h>
 #include <assimp/StringUtils.h>
@@ -51,17 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
+#include <assimp/fast_atof.h>
+
 #include <cassert>
 #include <map>
 #include <memory>
 #include <string>
 #include <vector>
-
-#include "3MFXmlTags.h"
-#include "D3MFOpcPackage.h"
-#include <assimp/fast_atof.h>
-
 #include <iomanip>
+#include <string.h>
 
 namespace Assimp {
 namespace D3MF {
@@ -72,32 +72,39 @@ enum class ResourceType {
     RT_Unknown
 }; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
 
-class Resource
-{
+class Resource {
 public:
-    Resource(int id) :
-            mId(id) {}
+    int mId;
 
-    virtual ~Resource() {}
+    Resource(int id) :
+            mId(id) {
+        // empty
+    }
 
-    int mId;
+    virtual ~Resource() {
+        // empty
+    }
 
-    virtual ResourceType getType() {
+    virtual ResourceType getType() const {
         return ResourceType::RT_Unknown;
     }
 };
 
 class BaseMaterials : public Resource {
 public:
+    std::vector<aiMaterial *> mMaterials;
+    std::vector<unsigned int> mMaterialIndex;
+
     BaseMaterials(int id) :
             Resource(id),
             mMaterials(),
-            mMaterialIndex() {}
+            mMaterialIndex() {
+        // empty
+    }
 
-    std::vector<aiMaterial *> mMaterials;
-    std::vector<unsigned int> mMaterialIndex;
+    ~BaseMaterials() = default;
 
-    virtual ResourceType getType() {
+    ResourceType getType() const override {
         return ResourceType::RT_BaseMaterials;
     }
 };
@@ -109,24 +116,26 @@ struct Component {
 
 class Object : public Resource {
 public:
-    std::vector<aiMesh*> mMeshes;
+    std::vector<aiMesh *> mMeshes;
     std::vector<unsigned int> mMeshIndex;
     std::vector<Component> mComponents;
     std::string mName;
 
     Object(int id) :
             Resource(id),
-            mName(std::string("Object_") + ai_to_string(id)) {}
+            mName(std::string("Object_") + ai_to_string(id)) {
+        // empty
+    }
+
+    ~Object() = default;
 
-    virtual ResourceType getType() {
+    ResourceType getType() const override {
         return ResourceType::RT_Object;
     }
 };
 
-
 class XmlSerializer {
 public:
-
     XmlSerializer(XmlParser *xmlParser) :
             mResourcesDictionnary(),
             mMaterialCount(0),
@@ -136,7 +145,7 @@ public:
     }
 
     ~XmlSerializer() {
-        for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
+        for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it ) {
             delete it->second;
         }
     }
@@ -146,28 +155,28 @@ public:
             return;
         }
 
-        scene->mRootNode = new aiNode("3MF");
+        scene->mRootNode = new aiNode(XmlTag::RootTag);
 
-        XmlNode node = mXmlParser->getRootNode().child("model");
+        XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
         if (node.empty()) {
             return;
         }
-        XmlNode resNode = node.child("resources");
-        for (XmlNode currentNode = resNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            const std::string &currentNodeName = currentNode.name();
-            if (currentNodeName == D3MF::XmlTag::object) {
-                ReadObject(currentNode);;
-            } else if (currentNodeName == D3MF::XmlTag::basematerials) {
+        XmlNode resNode = node.child(XmlTag::resources);
+        for (auto &currentNode : resNode.children()) {
+            const std::string currentNodeName = currentNode.name();
+            if (currentNodeName == XmlTag::object) {
+                ReadObject(currentNode);
+            } else if (currentNodeName == XmlTag::basematerials) {
                 ReadBaseMaterials(currentNode);
-            } else if (currentNodeName == D3MF::XmlTag::meta) {
+            } else if (currentNodeName == XmlTag::meta) {
                 ReadMetadata(currentNode);
             }
         }
 
-        XmlNode buildNode = node.child("build");
-        for (XmlNode currentNode = buildNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            const std::string &currentNodeName = currentNode.name();
-            if (currentNodeName == D3MF::XmlTag::item) {
+        XmlNode buildNode = node.child(XmlTag::build);
+        for (auto &currentNode : buildNode.children()) {
+            const std::string currentNodeName = currentNode.name();
+            if (currentNodeName == XmlTag::item) {
                 int objectId = -1;
                 std::string transformationMatrixStr;
                 aiMatrix4x4 transformationMatrix;
@@ -186,10 +195,9 @@ public:
             }
         }
 
-
         // import the metadata
         if (!mMetaData.empty()) {
-            const size_t numMeta(mMetaData.size());
+            const size_t numMeta = mMetaData.size();
             scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
             for (size_t i = 0; i < numMeta; ++i) {
                 aiString val(mMetaData[i].value);
@@ -201,22 +209,22 @@ public:
         scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
         if (scene->mNumMeshes != 0) {
             scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
-            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
+            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
                 if (it->second->getType() == ResourceType::RT_Object) {
-                    Object *obj = static_cast<Object*>(it->second);
+                    Object *obj = static_cast<Object *>(it->second);
+                    ai_assert(nullptr != obj);
                     for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
                         scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
                     }
                 }
             }
         }
-        
 
         // import the materials
-        scene->mNumMaterials = static_cast<unsigned int>(mMaterialCount);
+        scene->mNumMaterials = mMaterialCount;
         if (scene->mNumMaterials != 0) {
             scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
-            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) {
+            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
                 if (it->second->getType() == ResourceType::RT_BaseMaterials) {
                     BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
                     for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) {
@@ -228,35 +236,36 @@ public:
     }
 
 private:
+    void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
+        ai_assert(nullptr != obj);
 
-    void addObjectToNode(aiNode* parent, Object* obj, aiMatrix4x4 nodeTransform) {
         aiNode *sceneNode = new aiNode(obj->mName);
         sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
         sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
         std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
 
         sceneNode->mTransformation = nodeTransform;
-
-        parent->addChildren(1, &sceneNode);
+        if (nullptr != parent) {
+            parent->addChildren(1, &sceneNode);
+        }
 
         for (size_t i = 0; i < obj->mComponents.size(); ++i) {
             Component c = obj->mComponents[i];
             auto it = mResourcesDictionnary.find(c.mObjectId);
             if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
-                addObjectToNode(sceneNode, static_cast<Object*>(it->second), c.mTransformation);
+                addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
             }
-            
         }
     }
 
-    bool getNodeAttribute(const XmlNode& node, const std::string& attribute, std::string& value) {
+    bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
         pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
         if (!objectAttribute.empty()) {
             value = objectAttribute.as_string();
             return true;
-        } else {
-            return false;
         }
+
+        return false;
     }
 
     bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
@@ -265,9 +274,9 @@ private:
         if (ret) {
             value = std::atoi(strValue.c_str());
             return true;
-        } else {
-            return false;
-        }
+        } 
+
+        return false;
     }
 
     aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
@@ -287,7 +296,7 @@ private:
             }
         }
         if (currentNumber.size() > 0) {
-            float f = std::stof(currentNumber);
+            const float f = std::stof(currentNumber);
             numbers.push_back(f);
         }
 
@@ -311,29 +320,26 @@ private:
         transformMatrix.b4 = numbers[10];
         transformMatrix.c4 = numbers[11];
         transformMatrix.d4 = 1;
+
         return transformMatrix;
     }
 
     void ReadObject(XmlNode &node) {
         int id = -1, pid = -1, pindex = -1;
-        bool hasId = getNodeAttribute(node, D3MF::XmlTag::id, id);
-        //bool hasType = getNodeAttribute(node, D3MF::XmlTag::type, type); not used currently
-        bool hasPid = getNodeAttribute(node, D3MF::XmlTag::pid, pid);
-        bool hasPindex = getNodeAttribute(node, D3MF::XmlTag::pindex, pindex);
-
-        std::string idStr = ai_to_string(id);
-
+        bool hasId = getNodeAttribute(node, XmlTag::id, id);
+        bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
+        bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
         if (!hasId) {
             return;
         }
 
         Object *obj = new Object(id);
 
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
+        for (XmlNode &currentNode : node.children()) {
             const std::string &currentName = currentNode.name();
             if (currentName == D3MF::XmlTag::mesh) {
                 auto mesh = ReadMesh(currentNode);
-                mesh->mName.Set(idStr);
+                mesh->mName.Set(ai_to_string(id));
 
                 if (hasPid) {
                     auto it = mResourcesDictionnary.find(pid);
@@ -347,8 +353,9 @@ private:
                 obj->mMeshIndex.push_back(mMeshCount);
                 mMeshCount++;
             } else if (currentName == D3MF::XmlTag::components) {
-                for (XmlNode currentSubNode = currentNode.first_child(); currentSubNode; currentSubNode = currentSubNode.next_sibling()) {
-                    if (currentSubNode.name() == D3MF::XmlTag::component) {
+                for (XmlNode &currentSubNode : currentNode.children()) {
+                    const std::string subNodeName = currentSubNode.name();
+                    if (subNodeName == D3MF::XmlTag::component) {
                         int objectId = -1;
                         std::string componentTransformStr;
                         aiMatrix4x4 componentTransform;
@@ -356,8 +363,9 @@ private:
                             componentTransform = parseTransformMatrix(componentTransformStr);
                         }
 
-                        if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId))
+                        if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
                             obj->mComponents.push_back({ objectId, componentTransform });
+                        }
                     }
                 }
             }
@@ -369,21 +377,20 @@ private:
     aiMesh *ReadMesh(XmlNode &node) {
         aiMesh *mesh = new aiMesh();
 
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            const std::string &currentName = currentNode.name();
-            if (currentName == D3MF::XmlTag::vertices) {
+        for (XmlNode &currentNode : node.children()) {
+            const std::string currentName = currentNode.name();
+            if (currentName == XmlTag::vertices) {
                 ImportVertices(currentNode, mesh);
-            } else if (currentName == D3MF::XmlTag::triangles) {
+            } else if (currentName == XmlTag::triangles) {
                 ImportTriangles(currentNode, mesh);
             }
-
         }
 
         return mesh;
     }
 
     void ReadMetadata(XmlNode &node) {
-        pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name.c_str());
+        pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
         const std::string name = attribute.as_string();
         const std::string value = node.value();
         if (name.empty()) {
@@ -398,9 +405,9 @@ private:
 
     void ImportVertices(XmlNode &node, aiMesh *mesh) {
         std::vector<aiVector3D> vertices;
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            const std::string &currentName = currentNode.name();
-            if (currentName == D3MF::XmlTag::vertex) {
+        for (XmlNode &currentNode : node.children()) {
+            const std::string currentName = currentNode.name();
+            if (currentName == XmlTag::vertex) {
                 vertices.push_back(ReadVertex(currentNode));
             }
         }
@@ -412,29 +419,28 @@ private:
 
     aiVector3D ReadVertex(XmlNode &node) {
         aiVector3D vertex;
-        vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::x.c_str()).as_string(), nullptr);
-        vertex.y = ai_strtof(node.attribute(D3MF::XmlTag::y.c_str()).as_string(), nullptr);
-        vertex.z = ai_strtof(node.attribute(D3MF::XmlTag::z.c_str()).as_string(), nullptr);
+        vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
+        vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
+        vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
 
         return vertex;
     }
 
     void ImportTriangles(XmlNode &node, aiMesh *mesh) {
         std::vector<aiFace> faces;
-        for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            const std::string &currentName = currentNode.name();
-            if (currentName == D3MF::XmlTag::triangle) {
+        for (XmlNode &currentNode : node.children()) {
+            const std::string currentName = currentNode.name();
+            if (currentName == XmlTag::triangle) {
                 aiFace face = ReadTriangle(currentNode);
                 faces.push_back(face);
 
-                int pid = 0, p1;
+                int pid = 0, p1 = 0;
                 bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
                 bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
 
                 if (hasPid && hasP1) {
                     auto it = mResourcesDictionnary.find(pid);
-                    if (it != mResourcesDictionnary.end())
-                    {
+                    if (it != mResourcesDictionnary.end()) {
                         if (it->second->getType() == ResourceType::RT_BaseMaterials) {
                             BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
                             mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
@@ -457,9 +463,9 @@ private:
 
         face.mNumIndices = 3;
         face.mIndices = new unsigned int[face.mNumIndices];
-        face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v1.c_str()).as_string()));
-        face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v2.c_str()).as_string()));
-        face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v3.c_str()).as_string()));
+        face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
+        face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
+        face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
 
         return face;
     }
@@ -467,14 +473,14 @@ private:
     void ReadBaseMaterials(XmlNode &node) {
         int id = -1;
         if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) {
-            BaseMaterials* baseMaterials = new BaseMaterials(id);
+            BaseMaterials *baseMaterials = new BaseMaterials(id);
 
-            for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling())
-            {
-                if (currentNode.name() == D3MF::XmlTag::basematerials_base) {
+            for (XmlNode &currentNode : node.children()) {
+                const std::string currentName = currentNode.name();
+                if (currentName == XmlTag::basematerials_base) {
                     baseMaterials->mMaterialIndex.push_back(mMaterialCount);
                     baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id));
-                    mMaterialCount++;
+                    ++mMaterialCount;
                 }
             }
 
@@ -488,7 +494,7 @@ private:
         }
 
         //format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
-        const size_t len(strlen(color));
+        const size_t len = strlen(color);
         if (9 != len && 7 != len) {
             return false;
         }
@@ -517,7 +523,7 @@ private:
     }
 
     void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
-        const char *color = node.attribute(D3MF::XmlTag::basematerials_displaycolor.c_str()).as_string();
+        const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
         aiColor4D diffuse;
         if (parseColor(color, diffuse)) {
             mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
@@ -531,7 +537,7 @@ private:
         bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
 
         std::string stdMaterialName;
-        std::string strId(ai_to_string(basematerialsId));
+        const std::string strId(ai_to_string(basematerialsId));
         stdMaterialName += "id";
         stdMaterialName += strId;
         stdMaterialName += "_";
@@ -556,13 +562,15 @@ private:
         std::string value;
     };
     std::vector<MetaEntry> mMetaData;
-    std::map<unsigned int, Resource*> mResourcesDictionnary;
+    std::map<unsigned int, Resource *> mResourcesDictionnary;
     unsigned int mMaterialCount, mMeshCount;
     XmlParser *mXmlParser;
 };
 
 } //namespace D3MF
 
+using namespace D3MF;
+
 static const aiImporterDesc desc = {
     "3mf Importer",
     "",
@@ -596,7 +604,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
         if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
             return false;
         }
-        D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
+        D3MFOpcPackage opcPackage(pIOHandler, filename);
         return opcPackage.validate();
     }
 
@@ -612,11 +620,11 @@ const aiImporterDesc *D3MFImporter::GetInfo() const {
 }
 
 void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
-    D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
+    D3MFOpcPackage opcPackage(pIOHandler, filename);
 
     XmlParser xmlParser;
     if (xmlParser.parse(opcPackage.RootStream())) {
-        D3MF::XmlSerializer xmlSerializer(&xmlParser);
+        XmlSerializer xmlSerializer(&xmlParser);
         xmlSerializer.ImportXml(pScene);
     }
 }

+ 1 - 1
code/AssetLib/3MF/D3MFImporter.h

@@ -47,9 +47,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp {
 
+/// @brief  The 3MF-importer class.
 class D3MFImporter : public BaseImporter {
 public:
-    // BaseImporter interface
     D3MFImporter();
     ~D3MFImporter();
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;

+ 5 - 5
code/AssetLib/3MF/D3MFOpcPackage.cpp

@@ -103,9 +103,9 @@ public:
             std::string name = currentNode.name();
             if (name == "Relationship") {
                 OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
-                relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID.c_str()).as_string();
-                relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE.c_str()).as_string();
-                relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET.c_str()).as_string();
+                relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID).as_string();
+                relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string();
+                relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string();
                 if (validateRels(relPtr)) {
                     m_relationShips.push_back(relPtr);
                 }
@@ -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);

+ 3 - 6
code/AssetLib/AMF/AMFImporter.cpp

@@ -205,7 +205,7 @@ void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::s
 }
 
 static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) {
-    return (isalnum(pChar) || (pChar == '+') || (pChar == '/'));
+    return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/'));
 }
 
 void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std::vector<uint8_t> &pOutputData) const {
@@ -268,7 +268,8 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
     mXmlParser = new XmlParser();
     if (!mXmlParser->parse(file.get())) {
         delete mXmlParser;
-        throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
+        mXmlParser = nullptr;
+        throw DeadlyImportError("Failed to create XML reader for file ", pFile, ".");
     }
 
     // Start reading, search for root tag <amf>
@@ -517,10 +518,6 @@ bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool p
     return false;
 }
 
-void AMFImporter::GetExtensionList(std::set<std::string> &pExtensionList) {
-    pExtensionList.insert("amf");
-}
-
 const aiImporterDesc *AMFImporter::GetInfo() const {
     return &Description;
 }

+ 0 - 1
code/AssetLib/AMF/AMFImporter.hpp

@@ -277,7 +277,6 @@ public:
     void ParseHelper_Node_Enter(AMFNodeElementBase *child);
     void ParseHelper_Node_Exit();
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
-    void GetExtensionList(std::set<std::string> &pExtensionList);
     void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
     const aiImporterDesc *GetInfo() const;
     bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;

+ 2 - 2
code/AssetLib/AMF/AMFImporter_Postprocess.cpp

@@ -428,10 +428,10 @@ void AMFImporter::Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const st
 
                     if (pBiggerThan != nullptr) {
                         bool found = false;
-
+                        const size_t biggerThan = *pBiggerThan;
                         for (const SComplexFace &face : pFaceList) {
                             for (size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) {
-                                if (face.Face.mIndices[idx_vert] > *pBiggerThan) {
+                                if (face.Face.mIndices[idx_vert] > biggerThan) {
                                     rv = face.Face.mIndices[idx_vert];
                                     found = true;
                                     break;

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

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

@@ -498,6 +498,12 @@ void Parser::ParseLV1MaterialListBlock() {
                 ParseLV2MaterialBlock(sMat);
                 continue;
             }
+            if( iDepth == 1 ){
+                // CRUDE HACK: support missing brace after "Ascii Scene Exporter v2.51"
+                LogWarning("Missing closing brace in material list");
+                --filePtr;
+                return;
+            }
         }
         AI_ASE_HANDLE_TOP_LEVEL_SECTION();
     }
@@ -671,7 +677,7 @@ void Parser::ParseLV3MapBlock(Texture &map) {
                 if (!ParseString(temp, "*MAP_CLASS"))
                     SkipToNextToken();
                 if (temp != "Bitmap" && temp != "Normal Bump") {
-                    ASSIMP_LOG_WARN_F("ASE: Skipping unknown map type: ", temp);
+                    ASSIMP_LOG_WARN("ASE: Skipping unknown map type: ", temp);
                     parsePath = false;
                 }
                 continue;
@@ -1119,7 +1125,7 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) {
                                          "this is no spot light or target camera");
                     }
                 } else {
-                    ASSIMP_LOG_ERROR("ASE: Unknown node transformation: " + temp);
+                    ASSIMP_LOG_ERROR("ASE: Unknown node transformation: ", temp);
                     // mode = 0
                 }
                 continue;

+ 1 - 1
code/AssetLib/Assbin/AssbinLoader.cpp

@@ -671,7 +671,7 @@ void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) {
 void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
     IOStream *stream = pIOHandler->Open(pFile, "rb");
     if (nullptr == stream) {
-        return;
+        throw DeadlyImportError("ASSBIN: Could not open ", pFile);
     }
 
     // signature

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

+ 2 - 2
code/AssetLib/BVH/BVHLoader.cpp

@@ -359,7 +359,7 @@ void BVHLoader::ReadMotion(aiScene * /*pScene*/) {
 std::string BVHLoader::GetNextToken() {
     // skip any preceding whitespace
     while (mReader != mBuffer.end()) {
-        if (!isspace(*mReader))
+        if (!isspace((unsigned char)*mReader))
             break;
 
         // count lines
@@ -372,7 +372,7 @@ std::string BVHLoader::GetNextToken() {
     // collect all chars till the next whitespace. BVH is easy in respect to that.
     std::string token;
     while (mReader != mBuffer.end()) {
-        if (isspace(*mReader))
+        if (isspace((unsigned char)*mReader))
             break;
 
         token.push_back(*mReader);

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

@@ -198,9 +198,9 @@ void DNAParser::Parse() {
         s.size = offset;
     }
 
-    ASSIMP_LOG_DEBUG_F("BlenderDNA: Got ", dna.structures.size(), " structures with totally ", fields, " fields");
+    ASSIMP_LOG_DEBUG("BlenderDNA: Got ", dna.structures.size(), " structures with totally ", fields, " fields");
 
-#ifdef ASSIMP_BUILD_BLENDER_DEBUG
+#if ASSIMP_BUILD_BLENDER_DEBUG_DNA
     dna.DumpToFile();
 #endif
 
@@ -208,7 +208,7 @@ void DNAParser::Parse() {
     dna.RegisterConverters();
 }
 
-#ifdef ASSIMP_BUILD_BLENDER_DEBUG
+#if ASSIMP_BUILD_BLENDER_DEBUG_DNA
 
 #include <fstream>
 // ------------------------------------------------------------------------------------------------
@@ -237,7 +237,7 @@ void DNA ::DumpToFile() {
 
     ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt");
 }
-#endif
+#endif // ASSIMP_BUILD_BLENDER_DEBUG_DNA
 
 // ------------------------------------------------------------------------------------------------
 /*static*/ void DNA ::ExtractArraySize(

+ 8 - 1
code/AssetLib/Blender/BlenderDNA.h

@@ -59,6 +59,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define ASSIMP_BUILD_BLENDER_DEBUG
 #endif
 
+// set this to non-zero to dump BlenderDNA stuff to dna.txt.
+// you could set it on the assimp build command line too without touching it here.
+// !!! please make sure this is set to 0 in the repo !!!
+#ifndef ASSIMP_BUILD_BLENDER_DEBUG_DNA
+#define ASSIMP_BUILD_BLENDER_DEBUG_DNA 0
+#endif
+
 // #define ASSIMP_BUILD_BLENDER_NO_STATS
 
 namespace Assimp {
@@ -495,7 +502,7 @@ public:
             const Structure &structure,
             const FileDatabase &db) const;
 
-#ifdef ASSIMP_BUILD_BLENDER_DEBUG
+#if ASSIMP_BUILD_BLENDER_DEBUG_DNA
     // --------------------------------------------------------
     /** Dump the DNA to a text file. This is for debugging purposes.
      *  The output file is `dna.txt` in the current working folder*/

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

+ 9 - 15
code/AssetLib/Blender/BlenderLoader.cpp

@@ -132,12 +132,6 @@ bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bo
     return false;
 }
 
-// ------------------------------------------------------------------------------------------------
-// List all extensions handled by this loader
-void BlenderImporter::GetExtensionList(std::set<std::string> &app) {
-    app.insert("blend");
-}
-
 // ------------------------------------------------------------------------------------------------
 // Loader registry entry
 const aiImporterDesc *BlenderImporter::GetInfo() const {
@@ -241,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);
 
@@ -316,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,
@@ -426,9 +420,9 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M
             --s;
         }
 
-        curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower(s[1]);
-        curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower(s[2]);
-        curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower(s[3]);
+        curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower((unsigned char)s[1]);
+        curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower((unsigned char)s[2]);
+        curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower((unsigned char)s[3]);
         curTex->achFormatHint[3] = '\0';
 
         // tex->mHeight = 0;
@@ -440,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);
     }
@@ -522,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;
 
@@ -758,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");
 }
 
 // ------------------------------------------------------------------------------------------------

+ 0 - 1
code/AssetLib/Blender/BlenderLoader.h

@@ -110,7 +110,6 @@ public:
 
 protected:
     const aiImporterDesc* GetInfo () const;
-    void GetExtensionList(std::set<std::string>& app);
     void SetupProperties(const Importer* pImp);
     void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
     void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream);

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

+ 26 - 44
code/AssetLib/C4D/C4DImporter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2020, assimp team
+Copyright (c) 2006-2021, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endif
 
 #include "C4DImporter.h"
-#include <assimp/TinyFormatter.h>
 #include <memory>
 #include <assimp/IOSystem.hpp>
 #include <assimp/scene.h>
@@ -65,7 +64,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "c4d_file.h"
 #include "default_alien_overloads.h"
 
-using namespace melange;
+namespace {
+
+aiString aiStringFrom(cineware::String const & cinestring) {
+    aiString result;
+    cinestring.GetCString(result.data, MAXLEN-1);
+    result.length = static_cast<ai_uint32>(cinestring.GetLength());
+    return result;
+}
+
+}
+
+using namespace Assimp;
+using namespace cineware;
 
 // overload this function and fill in your own unique data
 void GetWriterInfo(int &id, String &appname) {
@@ -73,9 +84,6 @@ void GetWriterInfo(int &id, String &appname) {
     appname = "Open Asset Import Library";
 }
 
-using namespace Assimp;
-using namespace Assimp::Formatter;
-
 namespace Assimp {
     template<> const char* LogFunctions<C4DImporter>::Prefix() {
         static auto prefix = "C4D: ";
@@ -97,17 +105,6 @@ static const aiImporterDesc desc = {
 };
 
 
-// ------------------------------------------------------------------------------------------------
-C4DImporter::C4DImporter()
-: BaseImporter() {
-    // empty
-}
-
-// ------------------------------------------------------------------------------------------------
-C4DImporter::~C4DImporter() {
-    // empty
-}
-
 // ------------------------------------------------------------------------------------------------
 bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
     const std::string& extension = GetExtension(pFile);
@@ -125,11 +122,6 @@ const aiImporterDesc* C4DImporter::GetInfo () const {
     return &desc;
 }
 
-// ------------------------------------------------------------------------------------------------
-void C4DImporter::SetupProperties(const Importer* /*pImp*/) {
-    // nothing to be done for the moment
-}
-
 
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
@@ -199,8 +191,8 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
 
 
 // ------------------------------------------------------------------------------------------------
-bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
-    // based on Melange sample code (C4DImportExport.cpp)
+bool C4DImporter::ReadShader(aiMaterial* out, BaseShader* shader) {
+    // based on Cineware sample code (C4DImportExport.cpp)
     while(shader) {
         if(shader->GetType() == Xlayer) {
             BaseContainer* container = shader->GetDataInstance();
@@ -242,13 +234,11 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
                 lsl = lsl->GetNext();
             }
         } else if ( shader->GetType() == Xbitmap ) {
-            aiString path;
-            shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1);
-            path.length = ::strlen(path.data);
+            auto const path = aiStringFrom(shader->GetFileName().GetString());
             out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
             return true;
         } else {
-            LogWarn("ignoring shader type: " + std::string(GetObjectTypeName(shader->GetType())));
+            LogWarn("ignoring shader type: ", GetObjectTypeName(shader->GetType()));
         }
         shader = shader->GetNext();
     }
@@ -257,18 +247,15 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
 }
 
 // ------------------------------------------------------------------------------------------------
-void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) {
-    // based on Melange sample code
+void C4DImporter::ReadMaterials(BaseMaterial* mat) {
+    // based on Cineware sample code
     while (mat) {
-        const String& name = mat->GetName();
         if (mat->GetType() == Mmaterial) {
             aiMaterial* out = new aiMaterial();
             material_mapping[mat] = static_cast<unsigned int>(materials.size());
             materials.push_back(out);
 
-            aiString ai_name;
-            name.GetCString(ai_name.data, MAXLEN-1);
-            ai_name.length = ::strlen(ai_name.data);
+            auto const ai_name = aiStringFrom(mat->GetName());
             out->AddProperty(&ai_name, AI_MATKEY_NAME);
 
             Material& m = dynamic_cast<Material&>(*mat);
@@ -294,7 +281,7 @@ void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) {
                 ReadShader(out, shader);
             }
         } else {
-            LogWarn("ignoring plugin material: " + std::string(GetObjectTypeName(mat->GetType())));
+            LogWarn("ignoring plugin material: ", GetObjectTypeName(mat->GetType()));
         }
         mat = mat->GetNext();
     }
@@ -305,19 +292,15 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
     ai_assert(parent != nullptr );
     std::vector<aiNode*> nodes;
 
-    // based on Melange sample code
+    // based on Cineware sample code
     while (object) {
-        const String& name = object->GetName();
         const LONG type = object->GetType();
         const Matrix& ml = object->GetMl();
 
-        aiString string;
-        name.GetCString(string.data, MAXLEN-1);
-        string.length = ::strlen(string.data);
         aiNode* const nd = new aiNode();
 
         nd->mParent = parent;
-        nd->mName = string;
+        nd->mName = aiStringFrom(object->GetName());
 
         nd->mTransformation.a1 = ml.v1.x;
         nd->mTransformation.b1 = ml.v1.y;
@@ -352,7 +335,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
                 meshes.push_back(mesh);
             }
         } else {
-            LogWarn("ignoring object: " + std::string(GetObjectTypeName(type)));
+            LogWarn("ignoring object: ", GetObjectTypeName(type));
         }
 
         RecurseHierarchy(object->GetDown(), nd);
@@ -370,7 +353,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
     ai_assert(object != nullptr);
     ai_assert( object->GetType() == Opolygon );
 
-    // based on Melange sample code
+    // based on Cineware sample code
     PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
     ai_assert(polyObject != nullptr);
 
@@ -618,4 +601,3 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) {
 }
 
 #endif // ASSIMP_BUILD_NO_C4D_IMPORTER
-

+ 15 - 24
code/AssetLib/C4D/C4DImporter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2020, assimp team
+Copyright (c) 2006-2021, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -56,8 +56,8 @@ struct aiMaterial;
 
 struct aiImporterDesc;
 
-namespace melange {
-    class BaseObject; // c4d_file.h
+namespace cineware {
+    class BaseObject;
     class PolygonObject;
     class BaseMaterial;
     class BaseShader;
@@ -71,43 +71,34 @@ namespace Assimp  {
     }
 
 // -------------------------------------------------------------------------------------------
-/** Importer class to load Cinema4D files using the Melange library to be obtained from
- *  www.plugincafe.com
+/** Importer class to load Cinema4D files using the Cineware library to be obtained from
+ *  https://developers.maxon.net
  *
- *  Note that Melange is not free software. */
+ *  Note that Cineware is not free software. */
 // -------------------------------------------------------------------------------------------
 class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
 public:
-    C4DImporter();
-    ~C4DImporter();
-    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+    bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override;
 
 protected:
 
-    // --------------------
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc* GetInfo () const override;
 
-    // --------------------
-    void SetupProperties(const Importer* pImp);
-
-    // --------------------
-    void InternReadFile( const std::string& pFile, aiScene* pScene,
-        IOSystem* pIOHandler);
+    void InternReadFile( const std::string& pFile, aiScene*, IOSystem* ) override;
 
 private:
 
-    void ReadMaterials(melange::BaseMaterial* mat);
-    void RecurseHierarchy(melange::BaseObject* object, aiNode* parent);
-    aiMesh* ReadMesh(melange::BaseObject* object);
-    unsigned int ResolveMaterial(melange::PolygonObject* obj);
+    void ReadMaterials(cineware::BaseMaterial* mat);
+    void RecurseHierarchy(cineware::BaseObject* object, aiNode* parent);
+    aiMesh* ReadMesh(cineware::BaseObject* object);
+    unsigned int ResolveMaterial(cineware::PolygonObject* obj);
 
-    bool ReadShader(aiMaterial* out, melange::BaseShader* shader);
+    bool ReadShader(aiMaterial* out, cineware::BaseShader* shader);
 
     std::vector<aiMesh*> meshes;
     std::vector<aiMaterial*> materials;
 
-    typedef std::map<melange::BaseMaterial*, unsigned int> MaterialMap;
+    typedef std::map<cineware::BaseMaterial*, unsigned int> MaterialMap;
     MaterialMap material_mapping;
 
 }; // !class C4DImporter

+ 25 - 20
code/AssetLib/COB/COBLoader.cpp

@@ -137,7 +137,13 @@ void COBImporter::SetupProperties(const Importer * /*pImp*/) {
 // Imports the given file into the given scene structure.
 void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
     COB::Scene scene;
-    std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(pIOHandler->Open(pFile, "rb")));
+
+    auto file = pIOHandler->Open(pFile, "rb");
+    if (!file) {
+        ThrowException("Could not open " + pFile);
+    }
+
+    std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(file));
 
     // check header
     char head[32];
@@ -146,7 +152,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
         ThrowException("Could not found magic id: `Caligari`");
     }
 
-    ASSIMP_LOG_INFO_F("File format tag: ", std::string(head + 9, 6));
+    ASSIMP_LOG_INFO("File format tag: ", std::string(head + 9, 6));
     if (head[16] != 'L') {
         ThrowException("File is big-endian, which is not supported");
     }
@@ -295,8 +301,7 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
                     }
                     std::unique_ptr<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());
                     }
@@ -521,7 +526,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
 
     ++splitter;
     if (!splitter.match_start("mat# ")) {
-        ASSIMP_LOG_WARN_F("Expected `mat#` line in `Mat1` chunk ", nfo.id);
+        ASSIMP_LOG_WARN("Expected `mat#` line in `Mat1` chunk ", nfo.id);
         return;
     }
 
@@ -533,7 +538,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
     ++splitter;
 
     if (!splitter.match_start("shader: ")) {
-        ASSIMP_LOG_WARN_F("Expected `mat#` line in `Mat1` chunk ", nfo.id);
+        ASSIMP_LOG_WARN("Expected `mat#` line in `Mat1` chunk ", nfo.id);
         return;
     }
     std::string shader = std::string(splitter[1]);
@@ -544,12 +549,12 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
     } else if (shader == "phong") {
         mat.shader = Material::PHONG;
     } else if (shader != "flat") {
-        ASSIMP_LOG_WARN_F("Unknown value for `shader` in `Mat1` chunk ", nfo.id);
+        ASSIMP_LOG_WARN("Unknown value for `shader` in `Mat1` chunk ", nfo.id);
     }
 
     ++splitter;
     if (!splitter.match_start("rgb ")) {
-        ASSIMP_LOG_WARN_F("Expected `rgb` line in `Mat1` chunk ", nfo.id);
+        ASSIMP_LOG_WARN("Expected `rgb` line in `Mat1` chunk ", nfo.id);
     }
 
     const char *rgb = splitter[1];
@@ -557,7 +562,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
 
     ++splitter;
     if (!splitter.match_start("alpha ")) {
-        ASSIMP_LOG_WARN_F("Expected `alpha` line in `Mat1` chunk ", nfo.id);
+        ASSIMP_LOG_WARN("Expected `alpha` line in `Mat1` chunk ", nfo.id);
     }
 
     const char *tokens[10];
@@ -577,7 +582,7 @@ void COBImporter::ReadUnit_Ascii(Scene &out, LineSplitter &splitter, const Chunk
     }
     ++splitter;
     if (!splitter.match_start("Units ")) {
-        ASSIMP_LOG_WARN_F("Expected `Units` line in `Unit` chunk ", nfo.id);
+        ASSIMP_LOG_WARN("Expected `Units` line in `Unit` chunk ", nfo.id);
         return;
     }
 
@@ -588,12 +593,12 @@ void COBImporter::ReadUnit_Ascii(Scene &out, LineSplitter &splitter, const Chunk
             const unsigned int t = strtoul10(splitter[1]);
 
             nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? (
-                                                                             ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) :
+                                                                             ASSIMP_LOG_WARN(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) :
                                                                      units[t];
             return;
         }
     }
-    ASSIMP_LOG_WARN_F("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
+    ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -622,13 +627,13 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk
     } else if (splitter.match_start("Spot ")) {
         msh.ltype = Light::SPOT;
     } else {
-        ASSIMP_LOG_WARN_F("Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter);
+        ASSIMP_LOG_WARN("Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter);
         msh.ltype = Light::SPOT;
     }
 
     ++splitter;
     if (!splitter.match_start("color ")) {
-        ASSIMP_LOG_WARN_F("Expected `color` line in `Lght` chunk ", nfo.id);
+        ASSIMP_LOG_WARN("Expected `color` line in `Lght` chunk ", nfo.id);
     }
 
     const char *rgb = splitter[1];
@@ -636,14 +641,14 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk
 
     SkipSpaces(&rgb);
     if (strncmp(rgb, "cone angle", 10) != 0) {
-        ASSIMP_LOG_WARN_F("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id);
+        ASSIMP_LOG_WARN("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id);
     }
     SkipSpaces(rgb + 10, &rgb);
     msh.angle = fast_atof(&rgb);
 
     SkipSpaces(&rgb);
     if (strncmp(rgb, "inner angle", 11) != 0) {
-        ASSIMP_LOG_WARN_F("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
+        ASSIMP_LOG_WARN("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
     }
     SkipSpaces(rgb + 11, &rgb);
     msh.inner_angle = fast_atof(&rgb);
@@ -1027,7 +1032,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
         mat.type = Material::METAL;
         break;
     default:
-        ASSIMP_LOG_ERROR_F("Unrecognized shader type in `Mat1` chunk with id ", nfo.id);
+        ASSIMP_LOG_ERROR("Unrecognized shader type in `Mat1` chunk with id ", nfo.id);
         mat.type = Material::FLAT;
     }
 
@@ -1042,7 +1047,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
         mat.autofacet = Material::SMOOTH;
         break;
     default:
-        ASSIMP_LOG_ERROR_F("Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id);
+        ASSIMP_LOG_ERROR("Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id);
         mat.autofacet = Material::FACETED;
     }
     mat.autofacet_angle = static_cast<float>(reader.GetI1());
@@ -1170,13 +1175,13 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
         if (nd->id == nfo.parent_id) {
             const unsigned int t = reader.GetI2();
             nd->unit_scale = t >= sizeof(units) / sizeof(units[0]) ? (
-                                                                             ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) :
+                                                                             ASSIMP_LOG_WARN(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id), 1.f) :
                                                                      units[t];
 
             return;
         }
     }
-    ASSIMP_LOG_WARN_F("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
+    ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
 }
 
 #endif // ASSIMP_BUILD_NO_COB_IMPORTER

+ 9 - 9
code/AssetLib/Collada/ColladaLoader.cpp

@@ -75,7 +75,7 @@ static const aiImporterDesc desc = {
     3,
     1,
     5,
-    "dae zae"
+    "dae xml zae"
 };
 
 static const float kMillisecondsFromSeconds = 1000.f;
@@ -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");

+ 17 - 29
code/AssetLib/Collada/ColladaParser.cpp

@@ -71,7 +71,7 @@ static void ReportWarning(const char *msg, ...) {
     ai_assert(iLen > 0);
 
     va_end(args);
-    ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer, iLen));
+    ASSIMP_LOG_WARN("Validation warning: ", std::string(szBuffer, iLen));
 }
 
 static bool FindCommonKey(const std::string &collada_key, const MetaKeyPairVector &key_renaming, size_t &found_index) {
@@ -234,7 +234,7 @@ void ColladaParser::UriDecodePath(aiString &ss) {
 #if defined(_MSC_VER)
     if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
 #else
-    if (ss.data[0] == '/' && isalpha(ss.data[1]) && ss.data[2] == ':') {
+    if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
 #endif
         --ss.length;
         ::memmove(ss.data, ss.data + 1, ss.length);
@@ -623,8 +623,7 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
     controller.mType = Skin;
     controller.mMethod = Normalized;
 
-    XmlNodeIterator xmlIt(node);
-    xmlIt.collectChildrenPreOrder(node);
+    XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
     XmlNode currentNode;
     while (xmlIt.getNext(currentNode)) {
 
@@ -929,8 +928,7 @@ void ColladaParser::ReadMaterial(XmlNode &node, Collada::Material &pMaterial) {
 // ------------------------------------------------------------------------------------------------
 // Reads a light entry into the given light
 void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
-    XmlNodeIterator xmlIt(node);
-    xmlIt.collectChildrenPreOrder(node);
+    XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
     XmlNode currentNode;
     while (xmlIt.getNext(currentNode)) {
         const std::string &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);

+ 7 - 7
code/AssetLib/DXF/DXFLoader.cpp

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

+ 75 - 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;
     }
 
@@ -1544,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;
 
@@ -1593,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
@@ -1817,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");
                         }
                     }
@@ -1841,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) {
@@ -1850,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;
                 }
             }
@@ -1936,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");
                         }
                     }
@@ -1960,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) {
@@ -1969,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;
                 }
             }
@@ -2128,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) {
@@ -2209,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) {
@@ -2321,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 {
@@ -2344,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) {
@@ -2353,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;
                     }
                 }
@@ -2576,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;
     }
 
@@ -2709,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;
         }
 
@@ -2750,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);
     }
 }
 

+ 3 - 3
code/AssetLib/FBX/FBXExporter.cpp

@@ -1789,13 +1789,13 @@ void FBXExporter::WriteObjects ()
             blendchannel_uid, blendshape_name + FBX::SEPARATOR + "SubDeformer", "BlendShapeChannel"
         );
         sdnode.AddChild("Version", int32_t(100));
-        sdnode.AddChild("DeformPercent", int32_t(100));
+        sdnode.AddChild("DeformPercent", float_t(0.0));
         FBX::Node p("Properties70");
-        p.AddP70numberA("DeformPercent", 100.);
+        p.AddP70numberA("DeformPercent", 0.0);
         sdnode.AddChild(p);
         // TODO: Normally just one weight per channel, adding stub for later development
         std::vector<float>fFullWeights;
-        fFullWeights.push_back(0.);
+        fFullWeights.push_back(100.);
         sdnode.AddChild("FullWeights", fFullWeights);
         sdnode.Dump(outstream, binary, indent);
 

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

@@ -82,7 +82,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
 
     // lower-case shading because Blender (for example) writes "Phong"
     for (size_t i = 0; i < shading.length(); ++i) {
-        shading[i] = static_cast<char>(tolower(shading[i]));
+        shading[i] = static_cast<char>(tolower(static_cast<unsigned char>(shading[i])));
     }
     std::string templateName;
     if(shading == "phong") {
@@ -352,7 +352,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
             }
         } catch (const runtime_error& runtimeError) {
             //we don't need the content data for contents that has already been loaded
-            ASSIMP_LOG_VERBOSE_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
+            ASSIMP_LOG_VERBOSE_DEBUG("Caught exception in FBXMaterial (likely because content was already loaded): ",
                     runtimeError.what());
         }
     }

+ 24 - 24
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);
     }
 }
 
@@ -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 - 6
code/AssetLib/HMP/HMPLoader.cpp

@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AssetLib/HMP/HMPLoader.h"
 #include "AssetLib/MD2/MD2FileData.h"
 
+#include <assimp/StringUtils.h>
 #include <assimp/importerdesc.h>
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
@@ -151,12 +152,7 @@ void HMPImporter::InternReadFile(const std::string &pFile,
         InternReadFile_HMP7();
     } else {
         // Print the magic word to the logger
-        char szBuffer[5];
-        szBuffer[0] = ((char *)&iMagic)[0];
-        szBuffer[1] = ((char *)&iMagic)[1];
-        szBuffer[2] = ((char *)&iMagic)[2];
-        szBuffer[3] = ((char *)&iMagic)[3];
-        szBuffer[4] = '\0';
+        std::string szBuffer = ai_str_toprintable((const char *)&iMagic, sizeof(iMagic));
     
         delete[] mBuffer;
         mBuffer = nullptr;

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

+ 8 - 8
code/AssetLib/IFC/IFCLoader.cpp

@@ -115,7 +115,7 @@ static const aiImporterDesc desc = {
     0,
     0,
     0,
-    "ifc ifczip stp"
+    "ifc ifczip step stp"
 };
 
 // ------------------------------------------------------------------------------------------------
@@ -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;
     }
 }

+ 6 - 6
code/AssetLib/Irr/IRRLoader.cpp

@@ -639,7 +639,7 @@ void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
 			// graph we're currently building
 			aiScene *localScene = batch.GetImport(root->id);
 			if (!localScene) {
-				ASSIMP_LOG_ERROR("IRR: Unable to load external file: " + root->meshPath);
+				ASSIMP_LOG_ERROR("IRR: Unable to load external file: ", root->meshPath);
 				break;
 			}
 			attach.push_back(AttachmentInfo(localScene, rootOut));
@@ -859,13 +859,13 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 
 	// Check whether we can read from the file
 	if (file.get() == nullptr) {
-		throw DeadlyImportError("Failed to open IRR file " + pFile);
+        throw DeadlyImportError("Failed to open IRR file ", pFile);
 	}
 
 	// Construct the irrXML parser
 	XmlParser st;
     if (!st.parse( file.get() )) {
-        return;
+        throw DeadlyImportError("XML parse error while loading IRR file ", pFile);
     }
     pugi::xml_node rootElement = st.getRootNode();
 
@@ -963,7 +963,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 						ASSIMP_LOG_ERROR("IRR: Billboards are not supported by Assimp");
 						nd = new Node(Node::DUMMY);
 					} else {
-						ASSIMP_LOG_WARN("IRR: Found unknown node: " + std::string(attrib.name()));
+						ASSIMP_LOG_WARN("IRR: Found unknown node: ", attrib.name());
 
 						/*  We skip the contents of nodes we don't know.
                          *  We parse the transformation and all animators
@@ -1181,7 +1181,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 											lights.pop_back();
 											curNode->type = Node::DUMMY;
 
-											ASSIMP_LOG_ERROR("Ignoring light of unknown type: " + prop.value);
+											ASSIMP_LOG_ERROR("Ignoring light of unknown type: ", prop.value);
 										}
 									} else if ((prop.name == "Mesh" && Node::MESH == curNode->type) ||
 											   Node::ANIMMESH == curNode->type) {
@@ -1225,7 +1225,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 										} else if (prop.value == "followSpline") {
 											curAnim->type = Animator::FOLLOW_SPLINE;
 										} else {
-											ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: " + prop.value);
+											ASSIMP_LOG_WARN("IRR: Ignoring unknown animator: ", prop.value);
 
 											curAnim->type = Animator::UNKNOWN;
 										}

+ 2 - 2
code/AssetLib/Irr/IRRMeshLoader.cpp

@@ -135,12 +135,12 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile,
 
 	// Check whether we can read from the file
 	if (file.get() == NULL)
-		throw DeadlyImportError("Failed to open IRRMESH file " + pFile);
+        throw DeadlyImportError("Failed to open IRRMESH file ", pFile);
 
 	// Construct the irrXML parser
 	XmlParser parser;
     if (!parser.parse( file.get() )) {
-        return;
+        throw DeadlyImportError("XML parse error while loading IRRMESH file ", pFile);
     }
     XmlNode root = parser.getRootNode();
 

+ 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

+ 4 - 8
code/AssetLib/M3D/M3DExporter.cpp

@@ -294,21 +294,17 @@ void ExportSceneM3D(
 // Worker function for exporting a scene to ASCII A3D.
 // Prototyped and registered in Exporter.cpp
 void ExportSceneM3DA(
-        const char *,
-        IOSystem *,
-        const aiScene *,
-        const ExportProperties *
+        const char *pFile,
+        IOSystem *pIOSystem,
+        const aiScene *pScene,
+        const ExportProperties *pProperties
 
 ) {
-#ifdef M3D_ASCII
     // initialize the exporter
     M3DExporter exporter(pScene, pProperties);
 
     // perform ascii export
     exporter.doExport(pFile, pIOSystem, true);
-#else
-    throw DeadlyExportError("Assimp configured without M3D_ASCII support");
-#endif
 }
 
 // ------------------------------------------------------------------------------------------------

+ 9 - 19
code/AssetLib/M3D/M3DImporter.cpp

@@ -95,11 +95,7 @@ static const aiImporterDesc desc = {
     0,
     0,
     0,
-#ifdef M3D_ASCII
     "m3d a3d"
-#else
-    "m3d"
-#endif
 };
 
 namespace Assimp {
@@ -119,9 +115,7 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
     const std::string extension = GetExtension(pFile);
 
     if (extension == "m3d"
-#ifdef M3D_ASCII
             || extension == "a3d"
-#endif
     )
         return true;
     else if (!extension.length() || checkSig) {
@@ -137,13 +131,11 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
         */
         std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb"));
         unsigned char data[4];
-        if (4 != pStream->Read(data, 1, 4)) {
+        if (!pStream || 4 != pStream->Read(data, 1, 4)) {
             return false;
         }
         return !memcmp(data, "3DMO", 4) /* bin */
-#ifdef M3D_ASCII
                || !memcmp(data, "3dmo", 4) /* ASCII */
-#endif
                 ;
     }
     return false;
@@ -176,12 +168,10 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys
     if (!memcmp(buffer.data(), "3DMO", 4) && memcmp(buffer.data() + 4, &fileSize, 4)) {
         throw DeadlyImportError("Bad binary header in file ", file, ".");
     }
-#ifdef M3D_ASCII
     // make sure there's a terminator zero character, as input must be ASCIIZ
     if (!memcmp(buffer.data(), "3dmo", 4)) {
         buffer.push_back(0);
     }
-#endif
 
     // Get the path for external assets
     std::string folderName("./");
@@ -194,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);
@@ -210,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);
@@ -240,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;
@@ -335,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;
@@ -390,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;
@@ -509,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;
@@ -550,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;
@@ -713,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()) {

+ 0 - 1
code/AssetLib/M3D/M3DWrapper.h

@@ -54,7 +54,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // Assimp specific M3D configuration. Comment out these defines to remove functionality
 //#define ASSIMP_USE_M3D_READFILECB
-//#define M3D_ASCII
 
 #include "m3d.h"
 

+ 3 - 35
code/AssetLib/M3D/m3d.h

@@ -231,14 +231,9 @@ enum {
 typedef struct {
     uint8_t format;
     uint8_t id;
-#ifdef M3D_ASCII
 #define M3D_PROPERTYDEF(f, i, n) \
     { (f), (i), (char *)(n) }
     char *key;
-#else
-#define M3D_PROPERTYDEF(f, i, n) \
-    { (f), (i) }
-#endif
 } m3dpd_t;
 
 /* material property types */
@@ -376,18 +371,11 @@ enum {
 
 #define M3D_CMDMAXARG 8 /* if you increase this, add more arguments to the macro below */
 typedef struct {
-#ifdef M3D_ASCII
 #define M3D_CMDDEF(t, n, p, a, b, c, d, e, f, g, h)                  \
     {                                                                \
         (char *)(n), (p), { (a), (b), (c), (d), (e), (f), (g), (h) } \
     }
     char *key;
-#else
-#define M3D_CMDDEF(t, n, p, a, b, c, d, e, f, g, h)     \
-    {                                                   \
-        (p), { (a), (b), (c), (d), (e), (f), (g), (h) } \
-    }
-#endif
     uint8_t p;
     uint8_t a[M3D_CMDMAXARG];
 } m3dcd_t;
@@ -2059,15 +2047,13 @@ unsigned char *_m3dstbi_zlib_compress(unsigned char *data, int data_len, int *ou
 
 #define M3D_CHUNKMAGIC(m, a, b, c, d) ((m)[0] == (a) && (m)[1] == (b) && (m)[2] == (c) && (m)[3] == (d))
 
-#ifdef M3D_ASCII
 #include <locale.h> /* sprintf and strtod cares about number locale */
 #include <stdio.h> /* get sprintf */
-#endif
 #ifdef M3D_PROFILING
 #include <sys/time.h>
 #endif
 
-#if !defined(M3D_NOIMPORTER) && defined(M3D_ASCII)
+#if !defined(M3D_NOIMPORTER) 
 /* helper functions for the ASCII parser */
 static char *_m3d_findarg(char *s) {
     while (s && *s && *s != ' ' && *s != '\t' && *s != '\r' && *s != '\n')
@@ -2118,7 +2104,7 @@ static char *_m3d_getfloat(char *s, M3D_FLOAT *ret) {
     return _m3d_findarg(e);
 }
 #endif
-#if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_ASCII) || defined(M3D_EXPORTER))
+#if !defined(M3D_NODUP) && (!defined(M3D_NOIMPORTER) || defined(M3D_EXPORTER))
 /* helper function to create safe strings */
 char *_m3d_safestr(char *in, int morelines) {
     char *out, *o, *i = in;
@@ -2426,21 +2412,17 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d
 #ifndef M3D_NOWEIGHTS
     m3ds_t *sk;
 #endif
-#ifdef M3D_ASCII
     m3ds_t s;
     M3D_INDEX bi[M3D_BONEMAXLEVEL + 1], level;
     const char *ol;
     char *ptr, *pe, *fn;
-#endif
 #ifdef M3D_PROFILING
     struct timeval tv0, tv1, tvd;
     gettimeofday(&tv0, NULL);
 #endif
 
     if (!data || (!M3D_CHUNKMAGIC(data, '3', 'D', 'M', 'O')
-#ifdef M3D_ASCII
                          && !M3D_CHUNKMAGIC(data, '3', 'd', 'm', 'o')
-#endif
                                  ))
         return NULL;
     model = (m3d_t *)M3D_MALLOC(sizeof(m3d_t));
@@ -2457,7 +2439,6 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d
         model->texture = mtllib->texture;
         model->flags |= M3D_FLG_MTLLIB;
     }
-#ifdef M3D_ASCII
     /* ASCII variant? */
     if (M3D_CHUNKMAGIC(data, '3', 'd', 'm', 'o')) {
         model->errcode = M3D_ERR_BADFILE;
@@ -3034,7 +3015,6 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d
         setlocale(LC_NUMERIC, ol);
         goto postprocess;
     }
-#endif
     /* Binary variant */
     if (!M3D_CHUNKMAGIC(data + 8, 'H', 'E', 'A', 'D')) {
         buff = (unsigned char *)stbi_zlib_decode_malloc_guesssize_headerflag((const char *)data + 8, ((m3dchunk_t *)data)->length - 8,
@@ -3698,9 +3678,7 @@ m3d_t *m3d_load(unsigned char *data, m3dread_t readfilecb, m3dfree_t freecb, m3d
         }
     }
     /* calculate normals, normalize skin weights, create bone/vertex cross-references and calculate transform matrices */
-#ifdef M3D_ASCII
 postprocess:
-#endif
     if (model) {
         M3D_LOG("Post-process");
 #ifdef M3D_PROFILING
@@ -3989,7 +3967,6 @@ void m3d_free(m3d_t *model) {
     unsigned int i, j;
 
     if (!model) return;
-#ifdef M3D_ASCII
     /* if model imported from ASCII, we have to free all strings as well */
     if (model->flags & M3D_FLG_FREESTR) {
         if (model->name) M3D_FREE(model->name);
@@ -4047,7 +4024,6 @@ void m3d_free(m3d_t *model) {
         if (model->preview.data)
             M3D_FREE(model->preview.data);
     }
-#endif
     if (model->flags & M3D_FLG_FREERAW) M3D_FREE(model->raw);
 
     if (model->tmap) M3D_FREE(model->tmap);
@@ -4315,7 +4291,6 @@ static void _m3d_round(int quality, m3dv_t *src, m3dv_t *dst) {
     if (dst->w == (M3D_FLOAT)-0.0) dst->w = (M3D_FLOAT)0.0;
 }
 
-#ifdef M3D_ASCII
 /* add a bone to ascii output */
 static char *_m3d_prtbone(char *ptr, m3db_t *bone, M3D_INDEX numbone, M3D_INDEX parent, uint32_t level, M3D_INDEX *vrtxidx) {
     uint32_t i, j;
@@ -4334,16 +4309,13 @@ static char *_m3d_prtbone(char *ptr, m3db_t *bone, M3D_INDEX numbone, M3D_INDEX
     }
     return ptr;
 }
-#endif
 
 /**
  * Function to encode an in-memory model into on storage Model 3D format
  */
 unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size) {
-#ifdef M3D_ASCII
     const char *ol;
     char *ptr;
-#endif
     char vc_s, vi_s, si_s, ci_s, ti_s, bi_s, nb_s, sk_s, fc_s, hi_s, fi_s;
     char *sn = NULL, *sl = NULL, *sa = NULL, *sd = NULL;
     unsigned char *out = NULL, *z = NULL, weights[M3D_NUMBONE], *norm = NULL;
@@ -4369,9 +4341,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
         return NULL;
     }
     model->errcode = M3D_SUCCESS;
-#ifdef M3D_ASCII
     if (flags & M3D_EXP_ASCII) quality = M3D_EXP_DOUBLE;
-#endif
     vrtxidx = (M3D_INDEX *)M3D_MALLOC(model->numvertex * sizeof(M3D_INDEX));
     if (!vrtxidx) goto memerr;
     memset(vrtxidx, 255, model->numvertex * sizeof(M3D_INDEX));
@@ -4800,7 +4770,6 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
     }
 
     M3D_LOG("Serializing model");
-#ifdef M3D_ASCII
     if (flags & M3D_EXP_ASCII) {
         /* use CRLF to make model creators on Win happy... */
         sd = _m3d_safestr(model->desc, 1);
@@ -5073,7 +5042,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
             ptr += sprintf(ptr, "\r\n");
         }
         /* mathematical shapes face */
-        if (model->numshape !(flags & M3D_EXP_NOFACE)) {
+        if (model->numshape && (!(flags & M3D_EXP_NOFACE))) {
             for (j = 0; j < model->numshape; j++) {
                 sn = _m3d_safestr(model->shape[j].name, 0);
                 if (!sn) {
@@ -5287,7 +5256,6 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
         if (!out) goto memerr;
         out[len] = 0;
     } else
-#endif
     {
         /* stricly only use LF (newline) in binary */
         sd = _m3d_safestr(model->desc, 3);

+ 21 - 23
code/AssetLib/MD2/MD2Loader.cpp

@@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 #include <assimp/scene.h>
 #include <assimp/importerdesc.h>
+#include <assimp/StringUtils.h>
 
 #include <memory>
 
@@ -148,46 +149,39 @@ void MD2Importer::ValidateHeader( )
     if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE &&
         m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE)
     {
-        char szBuffer[5];
-        szBuffer[0] = ((char*)&m_pcHeader->magic)[0];
-        szBuffer[1] = ((char*)&m_pcHeader->magic)[1];
-        szBuffer[2] = ((char*)&m_pcHeader->magic)[2];
-        szBuffer[3] = ((char*)&m_pcHeader->magic)[3];
-        szBuffer[4] = '\0';
-
-        throw DeadlyImportError("Invalid MD2 magic word: should be IDP2, the "
-            "magic word found is " + std::string(szBuffer));
+        throw DeadlyImportError("Invalid MD2 magic word: expected IDP2, found ",
+                                ai_str_toprintable((char *)&m_pcHeader->magic, 4));
     }
 
     // check file format version
     if (m_pcHeader->version != 8)
-        ASSIMP_LOG_WARN( "Unsupported md2 file version. Continuing happily ...");
+        ASSIMP_LOG_WARN( "Unsupported MD2 file version. Continuing happily ...");
 
     // check some values whether they are valid
     if (0 == m_pcHeader->numFrames)
-        throw DeadlyImportError( "Invalid md2 file: NUM_FRAMES is 0");
+        throw DeadlyImportError( "Invalid MD2 file: NUM_FRAMES is 0");
 
     if (m_pcHeader->offsetEnd > (uint32_t)fileSize)
-        throw DeadlyImportError( "Invalid md2 file: File is too small");
+        throw DeadlyImportError( "Invalid MD2 file: File is too small");
 
     if (m_pcHeader->numSkins > AI_MAX_ALLOC(MD2::Skin)) {
-        throw DeadlyImportError("Invalid MD2 header: too many skins, would overflow");
+        throw DeadlyImportError("Invalid MD2 header: Too many skins, would overflow");
     }
 
     if (m_pcHeader->numVertices > AI_MAX_ALLOC(MD2::Vertex)) {
-        throw DeadlyImportError("Invalid MD2 header: too many vertices, would overflow");
+        throw DeadlyImportError("Invalid MD2 header: Too many vertices, would overflow");
     }
 
     if (m_pcHeader->numTexCoords > AI_MAX_ALLOC(MD2::TexCoord)) {
-        throw DeadlyImportError("Invalid MD2 header: too many texcoords, would overflow");
+        throw DeadlyImportError("Invalid MD2 header: Too many texcoords, would overflow");
     }
 
     if (m_pcHeader->numTriangles > AI_MAX_ALLOC(MD2::Triangle)) {
-        throw DeadlyImportError("Invalid MD2 header: too many triangles, would overflow");
+        throw DeadlyImportError("Invalid MD2 header: Too many triangles, would overflow");
     }
 
     if (m_pcHeader->numFrames > AI_MAX_ALLOC(MD2::Frame)) {
-        throw DeadlyImportError("Invalid MD2 header: too many frames, would overflow");
+        throw DeadlyImportError("Invalid MD2 header: Too many frames, would overflow");
     }
 
     // -1 because Frame already contains one
@@ -199,7 +193,7 @@ void MD2Importer::ValidateHeader( )
         m_pcHeader->offsetFrames    + m_pcHeader->numFrames * frameSize                 >= fileSize ||
         m_pcHeader->offsetEnd           > fileSize)
     {
-        throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file");
+        throw DeadlyImportError("Invalid MD2 header: Some offsets are outside the file");
     }
 
     if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS)
@@ -210,7 +204,7 @@ void MD2Importer::ValidateHeader( )
         ASSIMP_LOG_WARN("The model contains more vertices than Quake 2 supports");
 
     if (m_pcHeader->numFrames <= configFrameID )
-        throw DeadlyImportError("The requested frame is not existing the file");
+        throw DeadlyImportError("MD2: The requested frame (", configFrameID, ") does not exist in the file");
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -433,10 +427,6 @@ void MD2Importer::InternReadFile( const std::string& pFile,
             aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
             LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
 
-            // flip z and y to become right-handed
-            std::swap((float&)vNormal.z,(float&)vNormal.y);
-            std::swap((float&)vec.z,(float&)vec.y);
-
             if (m_pcHeader->numTexCoords)   {
                 // validate texture coordinates
                 iIndex = pcTriangles[i].textureIndices[c];
@@ -454,7 +444,15 @@ void MD2Importer::InternReadFile( const std::string& pFile,
             }
             pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent;
         }
+        // flip the face order
+        std::swap( pScene->mMeshes[0]->mFaces[i].mIndices[0], pScene->mMeshes[0]->mFaces[i].mIndices[2] );
     }
+    // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
+    pScene->mRootNode->mTransformation = aiMatrix4x4(
+            1.f, 0.f, 0.f, 0.f,
+            0.f, 0.f, 1.f, 0.f,
+            0.f, -1.f, 0.f, 0.f,
+            0.f, 0.f, 0.f, 1.f);
 }
 
 #endif // !! ASSIMP_BUILD_NO_MD2_IMPORTER

+ 28 - 17
code/AssetLib/MD3/MD3Loader.cpp

@@ -101,7 +101,7 @@ Q3Shader::BlendFunc StringToBlendFunc(const std::string &m) {
     if (m == "GL_ONE_MINUS_DST_COLOR") {
         return Q3Shader::BLEND_GL_ONE_MINUS_DST_COLOR;
     }
-    ASSIMP_LOG_ERROR("Q3Shader: Unknown blend function: " + m);
+    ASSIMP_LOG_ERROR("Q3Shader: Unknown blend function: ", m);
     return Q3Shader::BLEND_NONE;
 }
 
@@ -112,7 +112,7 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem *
     if (!file.get())
         return false; // if we can't access the file, don't worry and return
 
-    ASSIMP_LOG_INFO_F("Loading Quake3 shader file ", pFile);
+    ASSIMP_LOG_INFO("Loading Quake3 shader file ", pFile);
 
     // read file in memory
     const size_t s = file->FileSize();
@@ -196,11 +196,11 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem *
                 // 'cull' specifies culling behaviour for the model
                 else if (TokenMatchI(buff, "cull", 4)) {
                     SkipSpaces(&buff);
-                    if (!ASSIMP_strincmp(buff, "back", 4)) {
+                    if (!ASSIMP_strincmp(buff, "back", 4)) { // render face's backside, does not function in Q3 engine (bug)
                         curData->cull = Q3Shader::CULL_CCW;
-                    } else if (!ASSIMP_strincmp(buff, "front", 5)) {
+                    } else if (!ASSIMP_strincmp(buff, "front", 5)) { // is not valid keyword in Q3, but occurs in shaders
                         curData->cull = Q3Shader::CULL_CW;
-                    } else if (!ASSIMP_strincmp(buff, "none", 4) || !ASSIMP_strincmp(buff, "disable", 7)) {
+                    } else if (!ASSIMP_strincmp(buff, "none", 4) || !ASSIMP_strincmp(buff, "twosided", 8) || !ASSIMP_strincmp(buff, "disable", 7)) {
                         curData->cull = Q3Shader::CULL_NONE;
                     } else {
                         ASSIMP_LOG_ERROR("Q3Shader: Unrecognized cull mode");
@@ -226,7 +226,7 @@ bool Q3Shader::LoadSkin(SkinData &fill, const std::string &pFile, IOSystem *io)
     if (!file.get())
         return false; // if we can't access the file, don't worry and return
 
-    ASSIMP_LOG_INFO("Loading Quake3 skin file " + pFile);
+    ASSIMP_LOG_INFO("Loading Quake3 skin file ", pFile);
 
     // read file in memory
     const size_t s = file->FileSize();
@@ -450,6 +450,9 @@ void MD3Importer::SetupProperties(const Importer *pImp) {
     // AI_CONFIG_IMPORT_MD3_SKIN_NAME
     configSkinFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SKIN_NAME, "default"));
 
+    // AI_CONFIG_IMPORT_MD3_LOAD_SHADERS
+    configLoadShaders = (pImp->GetPropertyBool(AI_CONFIG_IMPORT_MD3_LOAD_SHADERS, true));
+
     // AI_CONFIG_IMPORT_MD3_SHADER_SRC
     configShaderFile = (pImp->GetPropertyString(AI_CONFIG_IMPORT_MD3_SHADER_SRC, ""));
 
@@ -483,8 +486,9 @@ void MD3Importer::ReadShader(Q3Shader::ShaderData &fill) const {
 
     // If no specific dir or file is given, use our default search behaviour
     if (!configShaderFile.length()) {
-        if (!Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + model_file + ".shader", mIOHandler)) {
-            Q3Shader::LoadShader(fill, path + "..\\..\\..\\scripts\\" + filename + ".shader", mIOHandler);
+        const char sep = mIOHandler->getOsSeparator();
+        if (!Q3Shader::LoadShader(fill, path + ".." + sep + ".." + sep + ".." + sep + "scripts" + sep + model_file + ".shader", mIOHandler)) {
+             Q3Shader::LoadShader(fill, path + ".." + sep + ".." + sep + ".." + sep + "scripts" + sep + filename + ".shader", mIOHandler);
         }
     } else {
         // If the given string specifies a file, load this file.
@@ -702,7 +706,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
     }
     filename = mFile.substr(s), path = mFile.substr(0, s);
     for (std::string::iterator it = filename.begin(); it != filename.end(); ++it) {
-        *it = static_cast<char>(tolower(*it));
+        *it = static_cast<char>(tolower(static_cast<unsigned char>(*it)));
     }
 
     // Load multi-part model file, if necessary
@@ -780,7 +784,9 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 
     // And check whether we can locate a shader file for this model
     Q3Shader::ShaderData shaders;
-    ReadShader(shaders);
+    if (configLoadShaders){
+        ReadShader(shaders);
+    }
 
     // Adjust all texture paths in the shader
     const char *header_name = pcHeader->NAME;
@@ -851,7 +857,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 
         if (it != skins.textures.end()) {
             texture_name = &*(_texture_name = (*it).second).begin();
-            ASSIMP_LOG_VERBOSE_DEBUG_F("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME);
+            ASSIMP_LOG_VERBOSE_DEBUG("MD3: Assigning skin texture ", (*it).second, " to surface ", pcSurfaces->NAME);
             (*it).resolved = true; // mark entry as resolved
         }
 
@@ -862,7 +868,12 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 
         std::string convertedPath;
         if (texture_name) {
-            ConvertPath(texture_name, header_name, convertedPath);
+            if (configLoadShaders){
+                ConvertPath(texture_name, header_name, convertedPath);
+            }
+            else{
+                convertedPath = texture_name;
+            }
         }
 
         const Q3Shader::ShaderDataBlock *shader = nullptr;
@@ -880,9 +891,9 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
             if (dit != shaders.blocks.end()) {
                 // We made it!
                 shader = &*dit;
-                ASSIMP_LOG_INFO("Found shader record for " + without_ext);
+                ASSIMP_LOG_INFO("Found shader record for ", without_ext);
             } else {
-                ASSIMP_LOG_WARN("Unable to find shader record for " + without_ext);
+                ASSIMP_LOG_WARN("Unable to find shader record for ", without_ext);
             }
         }
 
@@ -985,8 +996,8 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
                 pcMesh->mTextureCoords[0][iCurrent].x = pcUVs[index].U;
                 pcMesh->mTextureCoords[0][iCurrent].y = 1.0f - pcUVs[index].V;
             }
-            // Flip face order if necessary
-            if (!shader || shader->cull == Q3Shader::CULL_CW) {
+            // Flip face order normally, unless shader is backfacing
+            if (!(shader && shader->cull == Q3Shader::CULL_CCW)) {
                 std::swap(pcMesh->mFaces[i].mIndices[2], pcMesh->mFaces[i].mIndices[1]);
             }
             ++pcTriangles;
@@ -1000,7 +1011,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
     if (!DefaultLogger::isNullLogger()) {
         for (std::list<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;
     }
 

+ 10 - 10
code/AssetLib/MDC/MDCLoader.cpp

@@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/Importer.hpp>
+#include <assimp/StringUtils.h>
 
 #include <memory>
 
@@ -143,16 +144,8 @@ void MDCImporter::ValidateHeader() {
 
     if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE &&
             pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE) {
-        char szBuffer[5];
-        szBuffer[0] = ((char *)&pcHeader->ulIdent)[0];
-        szBuffer[1] = ((char *)&pcHeader->ulIdent)[1];
-        szBuffer[2] = ((char *)&pcHeader->ulIdent)[2];
-        szBuffer[3] = ((char *)&pcHeader->ulIdent)[3];
-        szBuffer[4] = '\0';
-
-        throw DeadlyImportError("Invalid MDC magic word: should be IDPC, the "
-                                "magic word found is " +
-                                std::string(szBuffer));
+        throw DeadlyImportError("Invalid MDC magic word: expected IDPC, found ",
+                                ai_str_toprintable((char *)&pcHeader->ulIdent, 4));
     }
 
     if (pcHeader->ulVersion != AI_MDC_VERSION) {
@@ -465,6 +458,13 @@ void MDCImporter::InternReadFile(
             pcMat->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
         }
     }
+
+    // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
+    pScene->mRootNode->mTransformation = aiMatrix4x4(
+            1.f, 0.f, 0.f, 0.f,
+            0.f, 0.f, 1.f, 0.f,
+            0.f, -1.f, 0.f, 0.f,
+            0.f, 0.f, 0.f, 1.f);
 }
 
 #endif // !! ASSIMP_BUILD_NO_MDC_IMPORTER

+ 5 - 4
code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp

@@ -57,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <iomanip>
 #include <sstream>
+#include <map>
 
 #ifdef MDL_HALFLIFE_LOG_WARN_HEADER
 #undef MDL_HALFLIFE_LOG_WARN_HEADER
@@ -868,7 +869,7 @@ void HL1MDLLoader::read_meshes() {
                         scene_mesh->mNormals[v] = bind_pose_normals[pTrivert->normindex];
                         scene_mesh->mTextureCoords[0][v] = aiVector3D(
                                 pTrivert->s * texcoords_s_scale,
-                                pTrivert->t * texcoords_t_scale, 0);
+                                pTrivert->t * -texcoords_t_scale, 0);
                     }
 
                     // Add face and indices.
@@ -879,9 +880,9 @@ void HL1MDLLoader::read_meshes() {
                         aiFace *face = &scene_mesh->mFaces[f];
                         face->mNumIndices = 3;
                         face->mIndices = new unsigned int[3];
-                        face->mIndices[0] = mesh_faces[f].v0;
+                        face->mIndices[0] = mesh_faces[f].v2;
                         face->mIndices[1] = mesh_faces[f].v1;
-                        face->mIndices[2] = mesh_faces[f].v2;
+                        face->mIndices[2] = mesh_faces[f].v0;
                     }
 
                     // Add mesh bones.
@@ -1342,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;
     }
 }

+ 16 - 4
code/AssetLib/MDL/MDLLoader.cpp

@@ -199,6 +199,7 @@ void MDLImporter::InternReadFile(const std::string &pFile,
         const uint32_t iMagicWord = *((uint32_t *)mBuffer);
 
         // Determine the file subtype and call the appropriate member function
+        bool is_half_life = false;
 
         // Original Quake1 format
         if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) {
@@ -240,6 +241,7 @@ void MDLImporter::InternReadFile(const std::string &pFile,
         else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
                  AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord) {
             iGSFileVersion = 0;
+            is_half_life = true;
 
             HalfLife::HalfLifeMDLBaseHeader *pHeader = (HalfLife::HalfLifeMDLBaseHeader *)mBuffer;
             if (pHeader->version == AI_MDL_HL1_VERSION) {
@@ -252,12 +254,22 @@ void MDLImporter::InternReadFile(const std::string &pFile,
         } else {
             // print the magic word to the log file
             throw DeadlyImportError("Unknown MDL subformat ", pFile,
-                                    ". Magic word (", std::string((char *)&iMagicWord, 4), ") is not known");
+                                    ". Magic word (", ai_str_toprintable((const char *)&iMagicWord, sizeof(iMagicWord)), ") is not known");
         }
 
-        // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
-        pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f,
-                0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
+        if (is_half_life){
+            // Now rotate the whole scene 90 degrees around the z and x axes to convert to internal coordinate system
+            pScene->mRootNode->mTransformation = aiMatrix4x4(
+                    0.f, -1.f, 0.f, 0.f,
+                    0.f, 0.f, 1.f, 0.f,
+                    -1.f, 0.f, 0.f, 0.f,
+                    0.f, 0.f, 0.f, 1.f);
+        }
+        else {
+            // Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
+            pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f,
+                    0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
+        }
 
         DeleteBufferAndCleanup();
     } catch (...) {

+ 4 - 7
code/AssetLib/MMD/MMDPmxParser.cpp

@@ -478,8 +478,7 @@ namespace pmx
 
     void PmxSoftBody::Read(std::istream * /*stream*/, PmxSetting * /*setting*/)
 	{
-		std::cerr << "Not Implemented Exception" << std::endl;
-        throw DeadlyImportError("MMD: Not Implemented Exception");
+        throw DeadlyImportError("MMD: Soft Body support is not implemented.");
     }
 
 	void PmxModel::Init()
@@ -516,15 +515,13 @@ namespace pmx
 		char magic[4];
 		stream->read((char*) magic, sizeof(char) * 4);
 		if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20)
-		{
-			std::cerr << "invalid magic number." << std::endl;
-      throw DeadlyImportError("MMD: invalid magic number.");
+        {
+      throw DeadlyImportError("MMD: Invalid magic number.");
     }
 		stream->read((char*) &version, sizeof(float));
 		if (version != 2.0f && version != 2.1f)
 		{
-			std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl;
-            throw DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but ", ai_to_string(version));
+            throw DeadlyImportError("MMD: Unsupported version (must be 2.0 or 2.1): ", ai_to_string(version));
     }
 		this->setting.Read(stream);
 

+ 7 - 2
code/AssetLib/MS3D/MS3DLoader.cpp

@@ -215,7 +215,12 @@ void MS3DImporter :: CollectChildJoints(const std::vector<TempJoint>& joints, ai
 void MS3DImporter::InternReadFile( const std::string& pFile,
     aiScene* pScene, IOSystem* pIOHandler)
 {
-    StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
+
+    auto file = pIOHandler->Open(pFile, "rb");
+    if (!file)
+        throw DeadlyImportError("MS3D: Could not open ", pFile);
+
+    StreamReaderLE stream(file);
 
     // CanRead() should have done this already
     char head[10];
@@ -382,7 +387,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
                 }
 
                 const std::string& s = std::string(reinterpret_cast<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)) {

+ 8 - 2
code/AssetLib/NDO/NDOLoader.cpp

@@ -116,7 +116,13 @@ void NDOImporter::SetupProperties(const Importer* /*pImp*/)
 void NDOImporter::InternReadFile( const std::string& pFile,
     aiScene* pScene, IOSystem* pIOHandler)
 {
-    StreamReaderBE reader(pIOHandler->Open( pFile, "rb"));
+
+    auto file = pIOHandler->Open( pFile, "rb");
+    if (!file) {
+        throw DeadlyImportError("Nendo: Could not open ", pFile);
+    }
+
+    StreamReaderBE reader(file);
 
     // first 9 bytes are nendo file format ("nendo 1.n")
     const char* head = (const char*)reader.GetPtr();
@@ -141,7 +147,7 @@ void NDOImporter::InternReadFile( const std::string& pFile,
         ASSIMP_LOG_INFO("NDO file format is 1.2");
     }
     else {
-        ASSIMP_LOG_WARN_F( "Unrecognized nendo file format version, continuing happily ... :", (head+6));
+        ASSIMP_LOG_WARN( "Unrecognized nendo file format version, continuing happily ... :", (head+6));
     }
 
     reader.IncPtr(2); /* skip flags */

+ 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

+ 15 - 15
code/AssetLib/Ogre/OgreBinarySerializer.cpp

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

+ 15 - 1
code/AssetLib/OpenGEX/OpenGEXImporter.cpp

@@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/DefaultIOSystem.h>
 #include <assimp/StringComparison.h>
+#include <assimp/StringUtils.h>
 #include <assimp/DefaultLogger.hpp>
 
 #include <assimp/ai_assert.h>
@@ -223,6 +224,18 @@ static void propId2StdString(Property *prop, std::string &name, std::string &key
     }
 }
 
+//------------------------------------------------------------------------------------------------
+static void logDDLParserMessage (LogSeverity severity, const std::string &rawmsg) {
+    std::string msg = ai_str_toprintable(rawmsg);
+    switch (severity) {
+    case ddl_debug_msg: ASSIMP_LOG_DEBUG(msg);         break;
+    case ddl_info_msg:  ASSIMP_LOG_INFO(msg);          break;
+    case ddl_warn_msg:  ASSIMP_LOG_WARN(msg);          break;
+    case ddl_error_msg: ASSIMP_LOG_ERROR(msg);         break;
+    default:            ASSIMP_LOG_VERBOSE_DEBUG(msg); break;
+    }
+}
+
 //------------------------------------------------------------------------------------------------
 OpenGEXImporter::VertexContainer::VertexContainer() :
         m_numColors(0), m_colors(nullptr), m_numUVComps(), m_textureCoords() {
@@ -306,6 +319,7 @@ void OpenGEXImporter::InternReadFile(const std::string &filename, aiScene *pScen
     pIOHandler->Close(file);
 
     OpenDDLParser myParser;
+    myParser.setLogCallback(&logDDLParserMessage);
     myParser.setBuffer(&buffer[0], buffer.size());
     bool success(myParser.parse());
     if (success) {
@@ -712,7 +726,7 @@ void OpenGEXImporter::handleMeshNode(ODDLParser::DDLNode *node, aiScene *pScene)
             } else if ("quads" == propKey) {
                 m_currentMesh->mPrimitiveTypes |= aiPrimitiveType_POLYGON;
             } else {
-                ASSIMP_LOG_WARN_F(propKey, " is not supported primitive type.");
+                ASSIMP_LOG_WARN(propKey, " is not supported primitive type.");
             }
         }
     }

+ 1 - 1
code/AssetLib/Ply/PlyLoader.cpp

@@ -172,7 +172,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
             (headerCheck[1] != 'L' && headerCheck[1] != 'l') ||
             (headerCheck[2] != 'Y' && headerCheck[2] != 'y')) {
         streamedBuffer.close();
-        throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there");
+        throw DeadlyImportError("Invalid .ply file: Incorrect magic number (expected 'ply' or 'PLY').");
     }
 
     std::vector<char> mBuffer2;

+ 2 - 2
code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp

@@ -75,7 +75,7 @@ static const aiImporterDesc desc = {
     0,
     0,
     0,
-    "pk3"
+    "bsp pk3"
 };
 
 namespace Assimp {
@@ -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);
                 }
             }
         }

+ 9 - 3
code/AssetLib/Q3D/Q3DLoader.cpp

@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 // internal headers
 #include "Q3DLoader.h"
+#include <assimp/StringUtils.h>
 #include <assimp/StreamReader.h>
 #include <assimp/fast_atof.h>
 #include <assimp/importerdesc.h>
@@ -106,7 +107,12 @@ const aiImporterDesc *Q3DImporter::GetInfo() const {
 // Imports the given file into the given scene structure.
 void Q3DImporter::InternReadFile(const std::string &pFile,
         aiScene *pScene, IOSystem *pIOHandler) {
-    StreamReaderLE stream(pIOHandler->Open(pFile, "rb"));
+
+    auto file = pIOHandler->Open(pFile, "rb");
+    if (!file)
+        throw DeadlyImportError("Quick3D: Could not open ", pFile);
+
+    StreamReaderLE stream(file);
 
     // The header is 22 bytes large
     if (stream.GetRemainingSize() < 22)
@@ -115,11 +121,11 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
     // Check the file's signature
     if (ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Do", 8) &&
             ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Ds", 8)) {
-        throw DeadlyImportError("Not a Quick3D file. Signature string is: ", std::string((const char *)stream.GetPtr(), 8));
+        throw DeadlyImportError("Not a Quick3D file. Signature string is: ", ai_str_toprintable((const char *)stream.GetPtr(), 8));
     }
 
     // Print the file format version
-    ASSIMP_LOG_INFO_F("Quick3D File format version: ",
+    ASSIMP_LOG_INFO("Quick3D File format version: ",
             std::string(&((const char *)stream.GetPtr())[8], 2));
 
     // ... an store it

+ 11 - 6
code/AssetLib/SIB/SIBImporter.cpp

@@ -68,6 +68,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
+#include <assimp/StringUtils.h>
 
 #include <map>
 
@@ -166,21 +167,20 @@ static aiColor3D ReadColor(StreamReaderLE *stream) {
 }
 
 static void UnknownChunk(StreamReaderLE * /*stream*/, const SIBChunk &chunk) {
-    char temp[5] = {
+    char temp[4] = {
         static_cast<char>((chunk.Tag >> 24) & 0xff),
         static_cast<char>((chunk.Tag >> 16) & 0xff),
         static_cast<char>((chunk.Tag >> 8) & 0xff),
-        static_cast<char>(chunk.Tag & 0xff), '\0'
+        static_cast<char>(chunk.Tag & 0xff)
     };
 
-    ASSIMP_LOG_WARN((Formatter::format(), "SIB: Skipping unknown '", temp, "' chunk."));
+    ASSIMP_LOG_WARN("SIB: Skipping unknown '", ai_str_toprintable(temp, 4), "' chunk.");
 }
 
 // Reads a UTF-16LE string and returns it at UTF-8.
 static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) {
     if (nullptr == stream || 0 == numWChars) {
-        static const aiString empty;
-        return empty;
+        return aiString();
     }
 
     // Allocate buffers (max expansion is 1 byte -> 4 bytes for UTF-8)
@@ -804,7 +804,12 @@ static void ReadScene(SIB *sib, StreamReaderLE *stream) {
 // Imports the given file into the given scene structure.
 void SIBImporter::InternReadFile(const std::string &pFile,
         aiScene *pScene, IOSystem *pIOHandler) {
-    StreamReaderLE stream(pIOHandler->Open(pFile, "rb"));
+
+    auto file = pIOHandler->Open(pFile, "rb");
+    if (!file)
+        throw DeadlyImportError("SIB: Could not open ", pFile);
+
+    StreamReaderLE stream(file);
 
     // We should have at least one chunk
     if (stream.GetRemainingSize() < 16)

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

+ 3 - 3
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;
             }
 
@@ -667,8 +667,8 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Materi
 
                 // convert to lower case for easier comparison
                 for ( unsigned int c = 0; c < sz.length(); ++c ) {
-                    if ( isalpha( sz[ c ] ) ) {
-                        sz[ c ] = (char) tolower( sz[ c ] );
+                    if ( isalpha( (unsigned char) sz[ c ] ) ) {
+                        sz[ c ] = (char) tolower( (unsigned char) sz[ c ] );
                     }
                 }
 

+ 2 - 2
code/AssetLib/X/XFileParser.cpp

@@ -1245,13 +1245,13 @@ unsigned int XFileParser::ReadInt() {
         }
 
         // at least one digit expected
-        if (!isdigit(*mP))
+        if (!isdigit((unsigned char)*mP))
             ThrowException("Number expected.");
 
         // read digits
         unsigned int number = 0;
         while (mP < mEnd) {
-            if (!isdigit(*mP))
+            if (!isdigit((unsigned char)*mP))
                 break;
             number = number * 10 + (*mP - 48);
             mP++;

+ 0 - 4
code/AssetLib/X3D/X3DImporter.cpp

@@ -167,10 +167,6 @@ bool X3DImporter::CanRead( const std::string &pFile, IOSystem * /*pIOHandler*/,
     return false;
 }
 
-void X3DImporter::GetExtensionList( std::set<std::string> &extensionList ) {
-    extensionList.insert("x3d");
-}
-
 void X3DImporter::InternReadFile( const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler ) {
     std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
     if (!stream) {

+ 0 - 1
code/AssetLib/X3D/X3DImporter.hpp

@@ -307,7 +307,6 @@ public:
     /// \param [in] pIOHandler - pointer to IO helper object.
     void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
-    void GetExtensionList(std::set<std::string> &pExtensionList);
     void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
     const aiImporterDesc *GetInfo() const;
     void Clear();

+ 1 - 1
code/AssetLib/XGL/XGLLoader.cpp

@@ -200,7 +200,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 	// parse the XML file
     mXmlParser = new XmlParser;
     if (!mXmlParser->parse(stream.get())) {
-		return;
+        throw DeadlyImportError("XML parse error while loading XGL file ", pFile);
 	}
 
 	TempScope scope;

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

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

+ 2 - 2
code/CApi/CInterfaceIOWrapper.cpp

@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp {
 
-CIOStreamWrapper::~CIOStreamWrapper(void) {
+CIOStreamWrapper::~CIOStreamWrapper() {
     /* Various places depend on this destructor to close the file */
     if (mFile) {
         mIO->mFileSystem->CloseProc(mIO->mFileSystem, mFile);
@@ -78,7 +78,7 @@ aiReturn CIOStreamWrapper::Seek(size_t pOffset,
 }
 
 // ...................................................................
-size_t CIOStreamWrapper::Tell(void) const {
+size_t CIOStreamWrapper::Tell() const {
     return mFile->TellProc(mFile);
 }
 

+ 6 - 20
code/Common/BaseImporter.cpp

@@ -65,20 +65,6 @@ using namespace Assimp;
 // Constructor to be privately used by Importer
 BaseImporter::BaseImporter() AI_NO_EXCEPT
         : m_progress() {
-    /**
-    * Assimp Importer
-    * unit conversions available
-    * if you need another measurment unit add it below.
-    * it's currently defined in assimp that we prefer meters.
-    *
-    * NOTE: Initialised here rather than in the header file
-    * to workaround a VS2013 bug with brace initialisers
-    * */
-    importerUnits[ImporterUnits::M] = 1.0;
-    importerUnits[ImporterUnits::CM] = 0.01;
-    importerUnits[ImporterUnits::MM] = 0.001;
-    importerUnits[ImporterUnits::INCHES] = 0.0254;
-    importerUnits[ImporterUnits::FEET] = 0.3048;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -97,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: %f", activeScale);
+    ASSIMP_LOG_DEBUG("UpdateImporterScale scale set: ", activeScale);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -193,7 +179,7 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
         }
 
         for (size_t i = 0; i < read; ++i) {
-            buffer[i] = static_cast<char>(::tolower(buffer[i]));
+            buffer[i] = static_cast<char>(::tolower((unsigned char)buffer[i]));
         }
 
         // It is not a proper handling of unicode files here ...
@@ -214,7 +200,7 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
             token.clear();
             const char *ptr(tokens[i]);
             for (size_t tokIdx = 0; tokIdx < len; ++tokIdx) {
-                token.push_back(static_cast<char>(tolower(*ptr)));
+                token.push_back(static_cast<char>(tolower(static_cast<unsigned char>(*ptr))));
                 ++ptr;
             }
             const char *r = strstr(buffer, token.c_str());
@@ -223,13 +209,13 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
             }
             // We need to make sure that we didn't accidentially identify the end of another token as our token,
             // e.g. in a previous version the "gltf " present in some gltf files was detected as "f "
-            if (noAlphaBeforeTokens && (r != buffer && isalpha(r[-1]))) {
+            if (noAlphaBeforeTokens && (r != buffer && isalpha(static_cast<unsigned char>(r[-1])))) {
                 continue;
             }
             // We got a match, either we don't care where it is, or it happens to
             // be in the beginning of the file / line
             if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
-                ASSIMP_LOG_DEBUG_F("Found positive match for header keyword: ", tokens[i]);
+                ASSIMP_LOG_DEBUG("Found positive match for header keyword: ", tokens[i]);
                 return true;
             }
         }
@@ -618,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) {

+ 15 - 2
code/Common/ImporterRegistry.cpp

@@ -48,6 +48,7 @@ corresponding preprocessor flag to selectively disable formats.
 
 #include <assimp/BaseImporter.h>
 #include <vector>
+#include <cstdlib>
 
 // ------------------------------------------------------------------------------------------------
 // Importers
@@ -204,7 +205,17 @@ corresponding preprocessor flag to selectively disable formats.
 namespace Assimp {
 
 // ------------------------------------------------------------------------------------------------
-void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
+void GetImporterInstanceList(std::vector<BaseImporter *> &out) {    
+    
+    // Some importers may be unimplemented or otherwise unsuitable for general use
+    // in their current state. Devs can set ASSIMP_ENABLE_DEV_IMPORTERS in their
+    // local environment to enable them, otherwise they're left out of the registry.
+    const char *envStr = std::getenv("ASSIMP_ENABLE_DEV_IMPORTERS");
+    bool devImportersEnabled = envStr && strcmp(envStr, "0");
+
+    // Ensure no unused var warnings if all uses are #ifndef'd away below:
+    (void)devImportersEnabled;
+
     // ----------------------------------------------------------------------------
     // Add an instance of each worker class here
     // (register_new_importers_here)
@@ -354,7 +365,9 @@ void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
     out.push_back(new D3MFImporter());
 #endif
 #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
-    out.push_back(new X3DImporter());
+    if (devImportersEnabled) { // https://github.com/assimp/assimp/issues/3647
+        out.push_back(new X3DImporter());
+    }
 #endif
 #ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
     out.push_back(new MMDImporter());

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

Alguns ficheiros não foram mostrados porque muitos ficheiros mudaram neste diff