Переглянути джерело

Merge branch 'master' into kimkulling/fix_invalid_delete_issue-5307

Kim Kulling 1 рік тому
батько
коміт
3c18be8747
100 змінених файлів з 1329 додано та 1366 видалено
  1. 9 14
      Readme.md
  2. 6 4
      code/AssetLib/3DS/3DSConverter.cpp
  3. 2 4
      code/AssetLib/3DS/3DSExporter.h
  4. 4 6
      code/AssetLib/3DS/3DSLoader.cpp
  5. 1 2
      code/AssetLib/3DS/3DSLoader.h
  6. 1 5
      code/AssetLib/3MF/D3MFImporter.cpp
  7. 2 2
      code/AssetLib/3MF/D3MFImporter.h
  8. 5 5
      code/AssetLib/3MF/D3MFOpcPackage.cpp
  9. 3 3
      code/AssetLib/3MF/XmlSerializer.cpp
  10. 4 2
      code/AssetLib/AC/ACLoader.cpp
  11. 1 1
      code/AssetLib/AMF/AMFImporter.cpp
  12. 50 51
      code/AssetLib/AMF/AMFImporter.hpp
  13. 4 2
      code/AssetLib/ASE/ASELoader.cpp
  14. 3 1
      code/AssetLib/ASE/ASEParser.cpp
  15. 1 1
      code/AssetLib/Assbin/AssbinLoader.cpp
  16. 12 10
      code/AssetLib/B3D/B3DImporter.cpp
  17. 25 25
      code/AssetLib/BVH/BVHLoader.cpp
  18. 1 6
      code/AssetLib/Blender/BlenderLoader.cpp
  19. 5 11
      code/AssetLib/COB/COBLoader.cpp
  20. 8 8
      code/AssetLib/COB/COBLoader.h
  21. 4 11
      code/AssetLib/CSM/CSMLoader.cpp
  22. 3 4
      code/AssetLib/CSM/CSMLoader.h
  23. 1 5
      code/AssetLib/Collada/ColladaLoader.cpp
  24. 1 1
      code/AssetLib/Collada/ColladaLoader.h
  25. 2 2
      code/AssetLib/DXF/DXFLoader.cpp
  26. 1 0
      code/AssetLib/FBX/FBXBinaryTokenizer.cpp
  27. 11 10
      code/AssetLib/FBX/FBXConverter.cpp
  28. 5 7
      code/AssetLib/FBX/FBXExporter.cpp
  29. 13 18
      code/AssetLib/FBX/FBXImporter.cpp
  30. 1 1
      code/AssetLib/FBX/FBXImporter.h
  31. 1 1
      code/AssetLib/HMP/HMPLoader.cpp
  32. 2 2
      code/AssetLib/IFC/IFCLoader.cpp
  33. 1 1
      code/AssetLib/IFC/IFCOpenings.cpp
  34. 1 9
      code/AssetLib/IQM/IQMImporter.cpp
  35. 3 3
      code/AssetLib/Irr/IRRLoader.cpp
  36. 1 1
      code/AssetLib/Irr/IRRMeshLoader.cpp
  37. 181 206
      code/AssetLib/LWO/LWOBLoader.cpp
  38. 1 5
      code/AssetLib/LWS/LWSLoader.cpp
  39. 1 1
      code/AssetLib/LWS/LWSLoader.h
  40. 1 1
      code/AssetLib/M3D/M3DImporter.cpp
  41. 2 9
      code/AssetLib/MD2/MD2Loader.cpp
  42. 1 1
      code/AssetLib/MD2/MD2Loader.h
  43. 1 1
      code/AssetLib/MD3/MD3Loader.cpp
  44. 1 5
      code/AssetLib/MD5/MD5Loader.cpp
  45. 1 1
      code/AssetLib/MD5/MD5Loader.h
  46. 1 5
      code/AssetLib/MDC/MDCLoader.cpp
  47. 1 1
      code/AssetLib/MDC/MDCLoader.h
  48. 1 5
      code/AssetLib/MDL/MDLLoader.cpp
  49. 4 7
      code/AssetLib/MDL/MDLLoader.h
  50. 1 5
      code/AssetLib/MMD/MMDImporter.cpp
  51. 7 19
      code/AssetLib/MMD/MMDImporter.h
  52. 1 4
      code/AssetLib/MS3D/MS3DLoader.cpp
  53. 2 1
      code/AssetLib/MS3D/MS3DLoader.h
  54. 2 10
      code/AssetLib/NDO/NDOLoader.cpp
  55. 2 2
      code/AssetLib/NDO/NDOLoader.h
  56. 15 20
      code/AssetLib/NFF/NFFLoader.cpp
  57. 2 2
      code/AssetLib/NFF/NFFLoader.h
  58. 124 129
      code/AssetLib/OFF/OFFLoader.cpp
  59. 2 2
      code/AssetLib/OFF/OFFLoader.h
  60. 10 3
      code/AssetLib/Obj/ObjFileImporter.cpp
  61. 1 1
      code/AssetLib/Ogre/OgreImporter.cpp
  62. 38 38
      code/AssetLib/OpenGEX/OpenGEXImporter.cpp
  63. 26 28
      code/AssetLib/Ply/PlyLoader.cpp
  64. 1 1
      code/AssetLib/Ply/PlyLoader.h
  65. 7 2
      code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp
  66. 1 0
      code/AssetLib/Q3BSP/Q3BSPFileImporter.h
  67. 10 15
      code/AssetLib/Q3D/Q3DLoader.cpp
  68. 4 10
      code/AssetLib/Raw/RawLoader.cpp
  69. 2 2
      code/AssetLib/Raw/RawLoader.h
  70. 5 12
      code/AssetLib/SIB/SIBImporter.cpp
  71. 2 2
      code/AssetLib/SIB/SIBImporter.h
  72. 4 2
      code/AssetLib/SMD/SMDLoader.cpp
  73. 21 20
      code/AssetLib/STL/STLLoader.cpp
  74. 4 6
      code/AssetLib/Terragen/TerragenLoader.cpp
  75. 1 1
      code/AssetLib/Terragen/TerragenLoader.h
  76. 9 7
      code/AssetLib/Unreal/UnrealLoader.cpp
  77. 216 218
      code/AssetLib/X/XFileImporter.cpp
  78. 1 1
      code/AssetLib/X/XFileImporter.h
  79. 114 102
      code/AssetLib/XGL/XGLLoader.cpp
  80. 14 18
      code/AssetLib/XGL/XGLLoader.h
  81. 1 5
      code/AssetLib/glTF/glTFImporter.cpp
  82. 102 71
      code/AssetLib/glTF2/glTF2Exporter.cpp
  83. 1 1
      code/AssetLib/glTF2/glTF2Importer.cpp
  84. 7 2
      code/CMakeLists.txt
  85. 5 1
      code/Common/Compression.cpp
  86. 111 102
      code/PostProcessing/ImproveCacheLocality.cpp
  87. 4 7
      code/PostProcessing/PretransformVertices.cpp
  88. 16 3
      contrib/zlib/zconf.h.included
  89. 4 0
      include/assimp/BaseImporter.h
  90. 0 1
      include/assimp/ParsingUtils.h
  91. 13 0
      include/assimp/config.h.in
  92. 7 1
      include/assimp/mesh.h
  93. 2 0
      include/assimp/vector3.h
  94. 1 0
      samples/SimpleTexturedDirectx11/CMakeLists.txt
  95. 1 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp
  96. 1 0
      samples/SimpleTexturedOpenGL/CMakeLists.txt
  97. 1 0
      samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp
  98. BIN
      test/models/glTF2/simple_skin/quad_skin.glb
  99. 3 0
      test/unit/utBlendImportAreaLight.cpp
  100. 5 2
      test/unit/utBlenderWork.cpp

+ 9 - 14
Readme.md

@@ -6,20 +6,14 @@ Open Asset Import Library is a library to load various 3d file formats into a sh
 ### Current project status ###
 [![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp) 
 ![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
-<a href="https://scan.coverity.com/projects/5607">
-  <img alt="Coverity Scan Build Status"
-       src="https://scan.coverity.com/projects/5607/badge.svg"/>
-</a>
 [![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
-
-[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
 [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
 [![Percentage of issues still open](http://isitmaintained.com/badge/open/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Percentage of issues still open")
 <br>
 
 APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
-Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
+Additionally, assimp features various __mesh post-processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
 
 ### Latest Doc's ###
 Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/). 
@@ -58,20 +52,21 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file.
 
 ### Other tools ###
 [open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
+[Assimp-Viewer(]https://github.com/assimp/assimp_view) is an experimental implementation for an Asset-Viewer based on ImGUI and Assimp (experimental).
 
 #### Repository structure ####
-Open Asset Import Library is implemented in C++. The directory structure looks like:
+Open Asset Import Library is implemented in C++. The directory structure looks like this:
 
 	/code		Source code
 	/contrib	Third-party libraries
 	/doc		Documentation (doxysource and pre-compiled docs)
-	/fuzz           Contains the test-code for the Google-Fuzzer project
+	/fuzz           Contains the test code for the Google Fuzzer project
 	/include	Public header C and C++ header files
-	/scripts 	Scripts used to generate the loading code for some formats
+	/scripts 	Scripts are used to generate the loading code for some formats
 	/port		Ports to other languages and scripts to maintain those.
 	/test		Unit- and regression tests, test suite of models
 	/tools		Tools (old assimp viewer, command line `assimp`)
-	/samples	A small number of samples to illustrate possible use-cases for Assimp
+	/samples	A small number of samples to illustrate possible use cases for Assimp
 
 The source code is organized in the following way:
 
@@ -79,9 +74,9 @@ The source code is organized in the following way:
 	code/CApi                       Special implementations which are only used for the C-API
 	code/Geometry                   A collection of geometry tools
 	code/Material                   The material system
-	code/PBR                        An exporter for physical based models
+	code/PBR                        An exporter for physical-based models
 	code/PostProcessing		The post-processing steps
-	code/AssetLib/<FormatName>	Implementation for import and export for the format
+	code/AssetLib/<FormatName>	Implementation for import and export of the format
 
 ### Contributing ###
 Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
@@ -118,4 +113,4 @@ and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you ma
 For the legal details, see the `LICENSE` file.
 
 ### Why this name ###
-Sorry, we're germans :-), no english native speakers ...
+Sorry, we're germans :-), no English native speakers ...

+ 6 - 4
code/AssetLib/3DS/3DSConverter.cpp

@@ -52,9 +52,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <cctype>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const unsigned int NotSet = 0xcdcdcdcd;
+static constexpr unsigned int NotSet = 0xcdcdcdcd;
 
 // ------------------------------------------------------------------------------------------------
 // Setup final material indices, generae a default material if necessary
@@ -68,7 +68,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
     unsigned int idx(NotSet);
     for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) {
         std::string s = mScene->mMaterials[i].mName;
-        for (char & it : s) {
+        for (char &it : s) {
             it = static_cast<char>(::tolower(static_cast<unsigned char>(it)));
         }
 
@@ -262,7 +262,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
         unsigned int iWire = 1;
         mat.AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
     }
-    [[fallthrough]];
+        [[fallthrough]];
 
     case D3DS::Discreet3DS::Gouraud:
         eShading = aiShadingMode_Gouraud;
@@ -805,4 +805,6 @@ void Discreet3DSImporter::ConvertScene(aiScene *pcOut) {
     }
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER

+ 2 - 4
code/AssetLib/3DS/3DSExporter.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2022, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -57,8 +56,7 @@ struct aiNode;
 struct aiMaterial;
 struct aiMesh;
 
-namespace Assimp
-{
+namespace Assimp {
 
 // ------------------------------------------------------------------------------------------------
 /**
@@ -88,7 +86,7 @@ private:
 
     std::map<const aiNode*, aiMatrix4x4> trafos;
 
-    typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
+    using MeshesByNodeMap = std::multimap<const aiNode*, unsigned int>;
     MeshesByNodeMap meshes;
 
 };

+ 4 - 6
code/AssetLib/3DS/3DSLoader.cpp

@@ -54,9 +54,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Discreet 3DS Importer",
     "",
     "",
@@ -103,10 +103,6 @@ Discreet3DSImporter::Discreet3DSImporter() :
     // empty
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-Discreet3DSImporter::~Discreet3DSImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@@ -1339,4 +1335,6 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
     (void)bGamma;
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER

+ 1 - 2
code/AssetLib/3DS/3DSLoader.h

@@ -59,7 +59,6 @@ struct aiNode;
 
 namespace Assimp    {
 
-
 using namespace D3DS;
 
 // ---------------------------------------------------------------------------------
@@ -68,7 +67,7 @@ using namespace D3DS;
 class Discreet3DSImporter : public BaseImporter {
 public:
     Discreet3DSImporter();
-    ~Discreet3DSImporter() override;
+    ~Discreet3DSImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 1 - 5
code/AssetLib/3MF/D3MFImporter.cpp

@@ -68,7 +68,7 @@ namespace Assimp {
 
 using namespace D3MF;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "3mf Importer",
     "",
     "",
@@ -81,10 +81,6 @@ static const aiImporterDesc desc = {
     "3mf"
 };
 
-D3MFImporter::D3MFImporter() = default;
-
-D3MFImporter::~D3MFImporter() = default;
-
 bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const {
     if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
         return false;

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

@@ -56,10 +56,10 @@ namespace Assimp {
 class D3MFImporter : public BaseImporter {
 public:
     /// @brief The default class constructor.
-    D3MFImporter();
+    D3MFImporter() = default;
 
     ///	@brief  The class destructor.
-    ~D3MFImporter() override;
+    ~D3MFImporter() override = default;
 
     /// @brief Performs the data format detection.
     /// @param pFile        The filename to check.

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

@@ -68,7 +68,7 @@ using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
 class OpcPackageRelationshipReader {
 public:
     OpcPackageRelationshipReader(XmlParser &parser) :
-            m_relationShips() {
+            mRelations() {
         XmlNode root = parser.getRootNode();
         ParseRootNode(root);
     }
@@ -108,13 +108,13 @@ public:
                 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);
+                    mRelations.push_back(relPtr);
                 }
             }
         }
     }
 
-    std::vector<OpcPackageRelationshipPtr> m_relationShips;
+    std::vector<OpcPackageRelationshipPtr> mRelations;
 };
 
 static bool IsEmbeddedTexture( const std::string &filename ) {
@@ -214,11 +214,11 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
 
     OpcPackageRelationshipReader reader(xmlParser);
 
-    auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) {
+    auto itr = std::find_if(reader.mRelations.begin(), reader.mRelations.end(), [](const OpcPackageRelationshipPtr &rel) {
         return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
     });
 
-    if (itr == reader.m_relationShips.end()) {
+    if (itr == reader.mRelations.end()) {
         throw DeadlyImportError("Cannot find ", XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
     }
 

+ 3 - 3
code/AssetLib/3MF/XmlSerializer.cpp

@@ -49,12 +49,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace D3MF {
 
-static const int IdNotSet = -1;
+static constexpr int IdNotSet = -1;
 
 namespace {
 
-static const size_t ColRGBA_Len = 9;
-static const size_t ColRGB_Len = 7;
+static constexpr size_t ColRGBA_Len = 9;
+static constexpr size_t ColRGB_Len = 7;
 
 // format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
 bool validateColorString(const char *color) {

+ 4 - 2
code/AssetLib/AC/ACLoader.cpp

@@ -60,9 +60,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/Importer.hpp>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "AC3D Importer",
     "",
     "",
@@ -862,4 +862,6 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
     }
 }
 
+} // namespace Assimp
+
 #endif //!defined ASSIMP_BUILD_NO_AC_IMPORTER

+ 1 - 1
code/AssetLib/AMF/AMFImporter.cpp

@@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp {
 
-const aiImporterDesc AMFImporter::Description = {
+static constexpr aiImporterDesc Description = {
     "Additive manufacturing file format(AMF) Importer",
     "smalcom",
     "",

+ 50 - 51
code/AssetLib/AMF/AMFImporter.hpp

@@ -98,8 +98,12 @@ namespace Assimp {
 ///            old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3>
 ///
 class AMFImporter : public BaseImporter {
-private:
-    struct SPP_Material; // forward declaration
+    using AMFMetaDataArray = std::vector<AMFMetadata *>;
+    using MeshArray = std::vector<aiMesh *>;
+    using NodeArray = std::vector<aiNode *>;
+
+public:
+    struct SPP_Material;
 
     /// Data type for post-processing step. More suitable container for part of material's composition.
     struct SPP_Composite {
@@ -107,7 +111,22 @@ private:
         std::string Formula; ///< Formula for calculating ratio of \ref Material.
     };
 
-    /// \struct SPP_Material
+    /// Data type for post-processing step. More suitable container for texture.
+    struct SPP_Texture {
+        std::string ID;
+        size_t Width, Height, Depth;
+        bool Tiled;
+        char FormatHint[9]; // 8 for string + 1 for terminator.
+        uint8_t *Data;
+    };
+
+    /// Data type for post-processing step. Contain face data.
+    struct SComplexFace {
+        aiFace Face; ///< Face vertices.
+        const AMFColor *Color; ///< Face color. Equal to nullptr if color is not set for the face.
+        const AMFTexMap *TexMap; ///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face.
+    };
+
     /// Data type for post-processing step. More suitable container for material.
     struct SPP_Material {
         std::string ID; ///< Material ID.
@@ -123,26 +142,37 @@ private:
         aiColor4D GetColor(const float pX, const float pY, const float pZ) const;
     };
 
-    /// Data type for post-processing step. More suitable container for texture.
-    struct SPP_Texture {
-        std::string ID;
-        size_t Width, Height, Depth;
-        bool Tiled;
-        char FormatHint[9]; // 8 for string + 1 for terminator.
-        uint8_t *Data;
-    };
+    /// Default constructor.
+    AMFImporter() AI_NO_EXCEPT;
 
-    /// Data type for post-processing step. Contain face data.
-    struct SComplexFace {
-        aiFace Face; ///< Face vertices.
-        const AMFColor *Color; ///< Face color. Equal to nullptr if color is not set for the face.
-        const AMFTexMap *TexMap; ///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face.
-    };
+    /// Default destructor.
+    ~AMFImporter() override;
 
-    using AMFMetaDataArray = std::vector<AMFMetadata*>;
-    using MeshArray = std::vector<aiMesh*>;
-    using NodeArray = std::vector<aiNode*>;
+    /// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
+    /// Also exception can be thrown if trouble will found.
+    /// \param [in] pFile - name of file to be parsed.
+    /// \param [in] pIOHandler - pointer to IO helper object.
+    void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
+    void ParseHelper_Node_Enter(AMFNodeElementBase *child);
+    void ParseHelper_Node_Exit();
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const override;
+    void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
+    const aiImporterDesc *GetInfo() const override;
+    bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;
+    bool Find_ConvertedNode(const std::string &pID, NodeArray &nodeArray, aiNode **pNode) const;
+    bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const;
+    AI_WONT_RETURN void Throw_CloseNotFound(const std::string &nodeName) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX;
+    void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
+    bool XML_SearchNode(const std::string &nodeName);
+    void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString);
+    AMFImporter(const AMFImporter &pScene) = delete;
+    AMFImporter &operator=(const AMFImporter &pScene) = delete;
 
+private:
     /// Clear all temporary data.
     void Clear();
 
@@ -262,40 +292,9 @@ private:
     /// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>.
     void ParseNode_TexMap(XmlNode &node, const bool pUseOldName = false);
 
-public:
-    /// Default constructor.
-    AMFImporter() AI_NO_EXCEPT;
 
-    /// Default destructor.
-    ~AMFImporter() override;
-
-    /// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
-    /// Also exception can be thrown if trouble will found.
-    /// \param [in] pFile - name of file to be parsed.
-    /// \param [in] pIOHandler - pointer to IO helper object.
-    void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
-    void ParseHelper_Node_Enter(AMFNodeElementBase *child);
-    void ParseHelper_Node_Exit();
-    bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const override;
-    void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
-    const aiImporterDesc *GetInfo() const override;
-    bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;
-    bool Find_ConvertedNode(const std::string &pID, NodeArray &nodeArray, aiNode **pNode) const;
-    bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const;
-    AI_WONT_RETURN void Throw_CloseNotFound(const std::string &nodeName) AI_WONT_RETURN_SUFFIX;
-    AI_WONT_RETURN void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
-    AI_WONT_RETURN void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
-    AI_WONT_RETURN void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX;
-    AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX;
-    void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
-    bool XML_SearchNode(const std::string &nodeName);
-    void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString);
-    AMFImporter(const AMFImporter &pScene) = delete;
-    AMFImporter &operator=(const AMFImporter &pScene) = delete;
 
 private:
-    static const aiImporterDesc Description;
-
     AMFNodeElementBase *mNodeElement_Cur; ///< Current element.
     std::list<AMFNodeElementBase *> mNodeElement_List; ///< All elements of scene graph.
     XmlParser *mXmlParser;

+ 4 - 2
code/AssetLib/ASE/ASELoader.cpp

@@ -63,10 +63,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // utilities
 #include <assimp/fast_atof.h>
 
-using namespace Assimp;
+namespace Assimp {
 using namespace Assimp::ASE;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "ASE Importer",
     "",
     "",
@@ -1262,6 +1262,8 @@ bool ASEImporter::GenerateNormals(ASE::Mesh &mesh) {
     return false;
 }
 
+}
+
 #endif // ASSIMP_BUILD_NO_3DS_IMPORTER
 
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

+ 3 - 1
code/AssetLib/ASE/ASEParser.cpp

@@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/fast_atof.h>
 #include <assimp/DefaultLogger.hpp>
 
-using namespace Assimp;
+namespace Assimp {
 using namespace Assimp::ASE;
 
 // ------------------------------------------------------------------------------------------------
@@ -1864,6 +1864,8 @@ void Parser::ParseLV4MeshLong(unsigned int &iOut) {
     iOut = strtoul10(filePtr, &filePtr);
 }
 
+}
+
 #endif // ASSIMP_BUILD_NO_3DS_IMPORTER
 
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

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

@@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Assimp Binary Importer",
     "Gargaj / Conspiracy",
     "",

+ 12 - 10
code/AssetLib/B3D/B3DImporter.cpp

@@ -59,10 +59,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 using namespace std;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "BlitzBasic 3D Importer",
     "",
     "",
@@ -79,9 +79,9 @@ static const aiImporterDesc desc = {
 #pragma warning(disable : 4018)
 #endif
 
-//#define DEBUG_B3D
+// #define DEBUG_B3D
 
-template<typename T>
+template <typename T>
 void DeleteAllBarePointers(std::vector<T> &x) {
     for (auto p : x) {
         delete p;
@@ -329,7 +329,7 @@ void B3DImporter::ReadBRUS() {
             mat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED);
         }
 
-        //Textures
+        // Textures
         for (int i = 0; i < n_texs; ++i) {
             int texid = ReadInt();
             if (texid < -1 || (texid >= 0 && texid >= static_cast<int>(_textures.size()))) {
@@ -372,7 +372,7 @@ void B3DImporter::ReadVRTS() {
         }
 
         if (_vflags & 2) {
-            ReadQuat(); //skip v 4bytes...
+            ReadQuat(); // skip v 4bytes...
         }
 
         for (int j = 0; j < _tcsets; ++j) {
@@ -704,22 +704,22 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
         }
     }
 
-    //nodes
+    // nodes
     scene->mRootNode = _nodes[0];
     _nodes.clear(); // node ownership now belongs to scene
 
-    //material
+    // material
     if (!_materials.size()) {
         _materials.emplace_back(std::unique_ptr<aiMaterial>(new aiMaterial));
     }
     scene->mNumMaterials = static_cast<unsigned int>(_materials.size());
     scene->mMaterials = unique_to_array(_materials);
 
-    //meshes
+    // meshes
     scene->mNumMeshes = static_cast<unsigned int>(_meshes.size());
     scene->mMeshes = unique_to_array(_meshes);
 
-    //animations
+    // animations
     if (_animations.size() == 1 && _nodeAnims.size()) {
 
         aiAnimation *anim = _animations.back().get();
@@ -738,4 +738,6 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
     flip.Execute(scene);
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER

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

@@ -55,10 +55,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <map>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
+
 using namespace Assimp::Formatter;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "BVH Importer (MoCap)",
     "",
     "",
@@ -73,8 +74,8 @@ static const aiImporterDesc desc = {
 
 // ------------------------------------------------------------------------------------------------
 // Aborts the file reading with an exception
-template<typename... T>
-AI_WONT_RETURN void BVHLoader::ThrowException(T&&... args) {
+template <typename... T>
+AI_WONT_RETURN void BVHLoader::ThrowException(T &&...args) {
     throw DeadlyImportError(mFileName, ":", mLine, " - ", args...);
 }
 
@@ -426,7 +427,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
         nodeAnim->mNodeName.Set(nodeName);
         std::map<BVHLoader::ChannelType, int> channelMap;
 
-        //Build map of channels
+        // Build map of channels
         for (unsigned int channel = 0; channel < node.mChannels.size(); ++channel) {
             channelMap[node.mChannels[channel]] = channel;
         }
@@ -441,7 +442,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
 
                 // Now compute all translations
                 for (BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel + 1)) {
-                    //Find channel in node
+                    // Find channel in node
                     std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
 
                     if (mapIter == channelMap.end())
@@ -485,30 +486,27 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
             for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) {
                 aiMatrix4x4 temp;
                 aiMatrix3x3 rotMatrix;
-				for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++ channelIdx) {
-					switch (node.mChannels[channelIdx]) {
-                    case Channel_RotationX:
-                        {
+                for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++channelIdx) {
+                    switch (node.mChannels[channelIdx]) {
+                    case Channel_RotationX: {
                         const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
-                        aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp);
-                        }
-                        break;
-                    case Channel_RotationY:
-                        {
+                        aiMatrix4x4::RotationX(angle, temp);
+                        rotMatrix *= aiMatrix3x3(temp);
+                    } break;
+                    case Channel_RotationY: {
                         const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
-                        aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp);
-                        }
-                        break;
-                    case Channel_RotationZ:
-                        {
+                        aiMatrix4x4::RotationY(angle, temp);
+                        rotMatrix *= aiMatrix3x3(temp);
+                    } break;
+                    case Channel_RotationZ: {
                         const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
-                        aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp);
-                        }
-                        break;
+                        aiMatrix4x4::RotationZ(angle, temp);
+                        rotMatrix *= aiMatrix3x3(temp);
+                    } break;
                     default:
                         break;
-					}
-				}
+                    }
+                }
                 rotkey->mTime = double(fr);
                 rotkey->mValue = aiQuaternion(rotMatrix);
                 ++rotkey;
@@ -525,4 +523,6 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
     }
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER

+ 1 - 6
code/AssetLib/Blender/BlenderLoader.cpp

@@ -69,11 +69,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // zlib is needed for compressed blend files
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
 #include "Common/Compression.h"
-/* #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-#    include <zlib.h>
-#  else
-#    include "../contrib/zlib/zlib.h"
-#  endif*/
 #endif
 
 namespace Assimp {
@@ -89,7 +84,7 @@ using namespace Assimp;
 using namespace Assimp::Blender;
 using namespace Assimp::Formatter;
 
-static const aiImporterDesc blenderDesc = {
+static constexpr aiImporterDesc blenderDesc = {
     "Blender 3D Importer (http://www.blender3d.org)",
     "",
     "",

+ 5 - 11
code/AssetLib/COB/COBLoader.cpp

@@ -61,11 +61,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 using namespace Assimp::COB;
 using namespace Assimp::Formatter;
 
-static const float units[] = {
+static constexpr float units[] = {
     1000.f,
     100.f,
     1.f,
@@ -76,7 +76,7 @@ static const float units[] = {
     1.f / 1609.344f
 };
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "TrueSpace Object Importer",
     "",
     "",
@@ -89,14 +89,6 @@ static const aiImporterDesc desc = {
     "cob scn"
 };
 
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-COBImporter::COBImporter() = default;
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-COBImporter::~COBImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool COBImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@@ -1172,4 +1164,6 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
     ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
 }
 
+}
+
 #endif // ASSIMP_BUILD_NO_COB_IMPORTER

+ 8 - 8
code/AssetLib/COB/COBLoader.h

@@ -56,16 +56,16 @@ class LineSplitter;
 
 // TinyFormatter.h
 namespace Formatter {
-template <typename T, typename TR, typename A>
-class basic_formatter;
-typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format;
+    template <typename T, typename TR, typename A>
+    class basic_formatter;
+    typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format;
 } // namespace Formatter
 
 // COBScene.h
 namespace COB {
-struct ChunkInfo;
-struct Node;
-struct Scene;
+    struct ChunkInfo;
+    struct Node;
+    struct Scene;
 } // namespace COB
 
 // -------------------------------------------------------------------------------------------
@@ -75,8 +75,8 @@ struct Scene;
 // -------------------------------------------------------------------------------------------
 class COBImporter : public BaseImporter {
 public:
-    COBImporter();
-    ~COBImporter() override;
+    COBImporter() = default;
+    ~COBImporter() override = default;
 
     // --------------------
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler,

+ 4 - 11
code/AssetLib/CSM/CSMLoader.cpp

@@ -44,9 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  CSMLoader.cpp
  *  Implementation of the CSM importer class.
  */
-
-
-
 #ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
 
 #include "CSMLoader.h"
@@ -63,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "CharacterStudio Motion Importer (MoCap)",
     "",
     "",
@@ -79,13 +76,9 @@ static const aiImporterDesc desc = {
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
-CSMImporter::CSMImporter()
-: noSkeletonMesh()
-{}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-CSMImporter::~CSMImporter() = default;
+CSMImporter::CSMImporter() : noSkeletonMesh(){
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.

+ 3 - 4
code/AssetLib/CSM/CSMLoader.h

@@ -61,7 +61,7 @@ namespace Assimp {
 class CSMImporter : public BaseImporter {
 public:
     CSMImporter();
-    ~CSMImporter() override;
+    ~CSMImporter() override = default;
 
     // -------------------------------------------------------------------
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
@@ -81,9 +81,8 @@ protected:
 private:
     bool noSkeletonMesh;
 
-}; // end of class CSMImporter
+};
 
-} // end of namespace Assimp
+} // namespace Assimp
 
 #endif // AI_AC3DIMPORTER_H_INC
-

+ 1 - 5
code/AssetLib/Collada/ColladaLoader.cpp

@@ -64,7 +64,7 @@ namespace Assimp {
 using namespace Assimp::Formatter;
 using namespace Assimp::Collada;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Collada Importer",
     "",
     "",
@@ -101,10 +101,6 @@ ColladaLoader::ColladaLoader() :
     // empty
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-ColladaLoader::~ColladaLoader() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

+ 1 - 1
code/AssetLib/Collada/ColladaLoader.h

@@ -86,7 +86,7 @@ public:
     ColladaLoader();
 
     /// The class destructor.
-    ~ColladaLoader() override;
+    ~ColladaLoader() override = default;
 
     /// Returns whether the class can handle the format of the given file.
     /// @see BaseImporter::CanRead() for more details.

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

@@ -70,7 +70,7 @@ static const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f));
 
 // color indices for DXF - 16 are supported, the table is
 // taken directly from the DXF spec.
-static aiColor4D g_aclrDxfIndexColors[] = {
+static const aiColor4D g_aclrDxfIndexColors[] = {
     aiColor4D(0.6f, 0.6f, 0.6f, 1.0f),
     aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red
     aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green
@@ -97,7 +97,7 @@ static const int GroupCode_XComp = 10;
 static const int GroupCode_YComp = 20;
 static const int GroupCode_ZComp = 30;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Drawing Interchange Format (DXF) Importer",
     "",
     "",

+ 1 - 0
code/AssetLib/FBX/FBXBinaryTokenizer.cpp

@@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "FBXUtil.h"
 #include <assimp/defs.h>
 #include <stdint.h>
+#include <cstdint>
 #include <assimp/Exceptional.h>
 #include <assimp/ByteSwapper.h>
 #include <assimp/DefaultLogger.hpp>

+ 11 - 10
code/AssetLib/FBX/FBXConverter.cpp

@@ -577,16 +577,17 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
     bool is_id[3] = { true, true, true };
 
     aiMatrix4x4 temp[3];
-    if (std::fabs(rotation.z) > angle_epsilon) {
-        aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]);
+    const auto rot = AI_DEG_TO_RAD(rotation);
+    if (std::fabs(rot.z) > angle_epsilon) {
+        aiMatrix4x4::RotationZ(rot.z, temp[2]);
         is_id[2] = false;
     }
-    if (std::fabs(rotation.y) > angle_epsilon) {
-        aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]);
+    if (std::fabs(rot.y) > angle_epsilon) {
+        aiMatrix4x4::RotationY(rot.y, temp[1]);
         is_id[1] = false;
     }
-    if (std::fabs(rotation.x) > angle_epsilon) {
-        aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]);
+    if (std::fabs(rot.x) > angle_epsilon) {
+        aiMatrix4x4::RotationX(rot.x, temp[0]);
         is_id[0] = false;
     }
 
@@ -3225,7 +3226,6 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
     aiVector3D defTranslate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f));
     aiVector3D defRotation = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f));
     aiVector3D defScale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f));
-    aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder);
 
     aiVectorKey* outTranslations = new aiVectorKey[keyCount];
     aiQuatKey* outRotations = new aiQuatKey[keyCount];
@@ -3241,8 +3241,9 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
     }
 
     if (keyframeLists[TransformationComp_Rotation].size() > 0) {
-        InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder);
+        InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], AI_DEG_TO_RAD(defRotation), maxTime, minTime, rotOrder);
     } else {
+        aiQuaternion defQuat = EulerToQuaternion(AI_DEG_TO_RAD(defRotation), rotOrder);
         for (size_t i = 0; i < keyCount; ++i) {
             outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
             outRotations[i].mValue = defQuat;
@@ -3264,7 +3265,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
 
     const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
     if (ok && preRotation.SquareLength() > zero_epsilon) {
-        const aiQuaternion preQuat = EulerToQuaternion(preRotation, Model::RotOrder_EulerXYZ);
+        const aiQuaternion preQuat = EulerToQuaternion(AI_DEG_TO_RAD(preRotation), Model::RotOrder_EulerXYZ);
         for (size_t i = 0; i < keyCount; ++i) {
             outRotations[i].mValue = preQuat * outRotations[i].mValue;
         }
@@ -3272,7 +3273,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
 
     const aiVector3D& postRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok);
     if (ok && postRotation.SquareLength() > zero_epsilon) {
-        const aiQuaternion postQuat = EulerToQuaternion(postRotation, Model::RotOrder_EulerXYZ);
+        const aiQuaternion postQuat = EulerToQuaternion(AI_DEG_TO_RAD(postRotation), Model::RotOrder_EulerXYZ);
         for (size_t i = 0; i < keyCount; ++i) {
             outRotations[i].mValue = outRotations[i].mValue * postQuat;
         }

+ 5 - 7
code/AssetLib/FBX/FBXExporter.cpp

@@ -74,8 +74,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // https://code.blender.org/2013/08/fbx-binary-file-format-specification/
 // https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure
 
-const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian
-
 using namespace Assimp;
 using namespace Assimp::FBX;
 
@@ -1391,7 +1389,7 @@ void FBXExporter::WriteObjects ()
         aiMaterial* m = mScene->mMaterials[i];
 
         // these are used to receive material data
-        float f; aiColor3D c;
+        ai_real f; aiColor3D c;
 
         // start the node record
         FBX::Node n("Material");
@@ -2434,7 +2432,7 @@ void FBXExporter::WriteObjects ()
                 aiMatrix4x4 m(k.mValue.GetMatrix());
                 aiVector3D qs, qr, qt;
                 m.Decompose(qs, qr, qt);
-                qr *= DEG;
+                qr = AI_RAD_TO_DEG(qr);
                 xval.push_back(qr.x);
                 yval.push_back(qr.y);
                 zval.push_back(qr.z);
@@ -2515,9 +2513,10 @@ void FBXExporter::WriteModelNode(
             );
         }
         if (r != zero) {
+            r = AI_RAD_TO_DEG(r);
             p.AddP70(
                 "Lcl Rotation", "Lcl Rotation", "", "A",
-                double(DEG*r.x), double(DEG*r.y), double(DEG*r.z)
+                double(r.x), double(r.y), double(r.z)
             );
         }
         if (s != one) {
@@ -2601,8 +2600,7 @@ void FBXExporter::WriteModelNodes(
             transform_chain.emplace_back(elem->first, t);
             break;
         case 'r': // rotation
-            r *= float(DEG);
-            transform_chain.emplace_back(elem->first, r);
+            transform_chain.emplace_back(elem->first, AI_RAD_TO_DEG(r));
             break;
         case 's': // scale
             transform_chain.emplace_back(elem->first, s);

+ 13 - 18
code/AssetLib/FBX/FBXImporter.cpp

@@ -72,30 +72,25 @@ using namespace Assimp::Formatter;
 using namespace Assimp::FBX;
 
 namespace {
-
-static const aiImporterDesc desc = {
-	"Autodesk FBX Importer",
-	"",
-	"",
-	"",
-	aiImporterFlags_SupportTextFlavour,
-	0,
-	0,
-	0,
-	0,
-	"fbx"
-};
+    static constexpr aiImporterDesc desc = {
+	    "Autodesk FBX Importer",
+	    "",
+	    "",
+	    "",
+	    aiImporterFlags_SupportTextFlavour,
+	    0,
+	    0,
+	    0,
+	    0,
+	    "fbx"
+    };
 }
 
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by #Importer
-FBXImporter::FBXImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool FBXImporter::CanRead(const std::string & pFile, IOSystem * pIOHandler, bool /*checkSig*/) const {
 	// at least ASCII-FBX files usually have a 'FBX' somewhere in their head
-	static const char *tokens[] = { "fbx" };
+	static const char *tokens[] = { " \n\r\n " };
 	return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
 }
 

+ 1 - 1
code/AssetLib/FBX/FBXImporter.h

@@ -70,7 +70,7 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
 class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
 public:
     /// @brief The class constructor.
-    FBXImporter();
+    FBXImporter() = default;
 
     ///	@brief The class destructor, default implementation.
     ~FBXImporter() override = default;

+ 1 - 1
code/AssetLib/HMP/HMPLoader.cpp

@@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "3D GameStudio Heightmap (HMP) Importer",
     "",
     "",

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

@@ -103,7 +103,7 @@ void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType &dt, ConversionData &co
 
 } // namespace
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Industry Foundation Classes (IFC) Importer",
     "",
     "",
@@ -185,7 +185,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
                 size_t total = 0;
                 int read = 0;
                 do {
-                    int bufferSize = fileInfo.uncompressed_size < INT16_MAX ? fileInfo.uncompressed_size : INT16_MAX;
+                    unsigned bufferSize = fileInfo.uncompressed_size < INT16_MAX ? static_cast<unsigned>(fileInfo.uncompressed_size) : INT16_MAX;
                     void *buffer = malloc(bufferSize);
                     read = unzReadCurrentFile(zip, buffer, bufferSize);
                     if (read > 0) {

+ 1 - 1
code/AssetLib/IFC/IFCOpenings.cpp

@@ -1372,7 +1372,7 @@ std::vector<IfcVector2> GetContourInPlane2D(const std::shared_ptr<TempMesh>& mes
     const std::vector<IfcVector3>& va = mesh->mVerts;
     if(va.size() <= 2) {
         std::stringstream msg;
-        msg << "Skipping: Only " << va.size() << " verticies in opening mesh.";
+        msg << "Skipping: Only " << va.size() << " vertices in opening mesh.";
         IFCImporter::LogDebug(msg.str().c_str());
         ok = false;
         return contour;

+ 1 - 9
code/AssetLib/IQM/IQMImporter.cpp

@@ -59,7 +59,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // http://sauerbraten.org/iqm/
 // https://github.com/lsalzman/iqm
 
-
 inline void swap_block( uint32_t *block, size_t size ){
     (void)block; // suppress 'unreferenced formal parameter' MSVC warning
     size >>= 2;
@@ -67,7 +66,7 @@ inline void swap_block( uint32_t *block, size_t size ){
         AI_SWAP4( block[ i ] );
 }
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Inter-Quake Model Importer",
     "",
     "",
@@ -100,13 +99,6 @@ bool IQMImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
         if (!pIOHandler) {
             return true;
         }
-        /*
-         * don't use CheckMagicToken because that checks with swapped bytes too, leading to false
-         * positives. This magic is not uint32_t, but char[4], so memcmp is the best way
-
-        const char* tokens[] = {"3DMO", "3dmo"};
-        return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4);
-        */
         std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb"));
         unsigned char data[15];
         if (!pStream || 15 != pStream->Read(data, 1, 15)) {

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

@@ -66,7 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Irrlicht Scene Reader",
     "",
     "",
@@ -575,8 +575,8 @@ void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis
                 m->mSemantic = prop->mSemantic;
                 m->mType = aiPTI_Float;
 
-                m->mDataLength = 12;
-                m->mData = new char[12];
+                m->mDataLength = sizeof(aiVector3D);
+                m->mData = new char[m->mDataLength];
                 *((aiVector3D *)m->mData) = axis;
                 p.push_back(m);
             }

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

@@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Irrlicht Mesh Reader",
     "",
     "",

+ 181 - 206
code/AssetLib/LWO/LWOBLoader.cpp

@@ -51,64 +51,56 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "LWOLoader.h"
 using namespace Assimp;
 
-
 // ------------------------------------------------------------------------------------------------
-void LWOImporter::LoadLWOBFile()
-{
+void LWOImporter::LoadLWOBFile() {
     LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
     bool running = true;
-    while (running)
-    {
-        if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break;
+    while (running) {
+        if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)
+            break;
         const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
 
-        if (mFileBuffer + head.length > end)
-        {
+        if (mFileBuffer + head.length > end) {
             throw DeadlyImportError("LWOB: Invalid chunk length");
         }
         uint8_t* const next = mFileBuffer+head.length;
-        switch (head.type)
-        {
+        switch (head.type) {
             // vertex list
-        case AI_LWO_PNTS:
-            {
+            case AI_LWO_PNTS: {
                 if (!mCurLayer->mTempPoints.empty())
                     ASSIMP_LOG_WARN("LWO: PNTS chunk encountered twice");
-                else LoadLWOPoints(head.length);
-                break;
-            }
-            // face list
-        case AI_LWO_POLS:
-            {
+                else
+                    LoadLWOPoints(head.length);
+                } break;
+            case AI_LWO_POLS: {                 // face list
+                    if (!mCurLayer->mFaces.empty())
+                        ASSIMP_LOG_WARN("LWO: POLS chunk encountered twice");
+                    else
+                        LoadLWOBPolygons(head.length);
+                } break;
+                
+            case AI_LWO_SRFS: // list of tags
+                {
+                    if (!mTags->empty())
+                        ASSIMP_LOG_WARN("LWO: SRFS chunk encountered twice");
+                    else
+                        LoadLWOTags(head.length);
+                } break;
 
-                if (!mCurLayer->mFaces.empty())
-                    ASSIMP_LOG_WARN("LWO: POLS chunk encountered twice");
-                else LoadLWOBPolygons(head.length);
-                break;
-            }
-            // list of tags
-        case AI_LWO_SRFS:
-            {
-                if (!mTags->empty())
-                    ASSIMP_LOG_WARN("LWO: SRFS chunk encountered twice");
-                else LoadLWOTags(head.length);
-                break;
-            }
+            case AI_LWO_SURF: // surface chunk
+                {
+                    LoadLWOBSurface(head.length);
+                } break;
 
-            // surface chunk
-        case AI_LWO_SURF:
-            {
-                LoadLWOBSurface(head.length);
+            default:
                 break;
-            }
         }
         mFileBuffer = next;
     }
 }
 
 // ------------------------------------------------------------------------------------------------
-void LWOImporter::LoadLWOBPolygons(unsigned int length)
-{
+void LWOImporter::LoadLWOBPolygons(unsigned int length) {
     // first find out how many faces and vertices we'll finally need
     LE_NCONST uint16_t* const end   = (LE_NCONST uint16_t*)(mFileBuffer+length);
     LE_NCONST uint16_t* cursor      = (LE_NCONST uint16_t*)mFileBuffer;
@@ -123,8 +115,7 @@ void LWOImporter::LoadLWOBPolygons(unsigned int length)
     CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end);
 
     // allocate the output array and copy face indices
-    if (iNumFaces)
-    {
+    if (iNumFaces) {
         cursor = (LE_NCONST uint16_t*)mFileBuffer;
 
         mCurLayer->mFaces.resize(iNumFaces);
@@ -135,10 +126,8 @@ void LWOImporter::LoadLWOBPolygons(unsigned int length)
 
 // ------------------------------------------------------------------------------------------------
 void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces,
-    LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max)
-{
-    while (cursor < end && max--)
-    {
+    LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max) {
+    while (cursor < end && max--) {
         uint16_t numIndices;
         // must have 2 shorts left for numIndices and surface
         if (end - cursor < 2) {
@@ -154,8 +143,7 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face
         cursor += numIndices;
         int16_t surface;
         ::memcpy(&surface, cursor++, 2);
-        if (surface < 0)
-        {
+        if (surface < 0) {
             // there are detail polygons
             ::memcpy(&numIndices, cursor++, 2);
             CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
@@ -167,18 +155,14 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face
 void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
     LE_NCONST uint16_t*& cursor,
     const uint16_t* const end,
-    unsigned int max)
-{
-    while (cursor < end && max--)
-    {
+    unsigned int max) {
+    while (cursor < end && max--) {
         LWO::Face& face = *it;++it;
         uint16_t numIndices;
         ::memcpy(&numIndices, cursor++, 2);
         face.mNumIndices = numIndices;
-        if(face.mNumIndices)
-        {
-            if (cursor + face.mNumIndices >= end)
-            {
+        if(face.mNumIndices) {
+            if (cursor + face.mNumIndices >= end) {
                 break;
             }
             face.mIndices = new unsigned int[face.mNumIndices];
@@ -187,8 +171,7 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
                 uint16_t index;
                 ::memcpy(&index, cursor++, 2);
                 mi = index;
-                if (mi > mCurLayer->mTempPoints.size())
-                {
+                if (mi > mCurLayer->mTempPoints.size()) {
                     ASSIMP_LOG_WARN("LWOB: face index is out of range");
                     mi = (unsigned int)mCurLayer->mTempPoints.size()-1;
                 }
@@ -198,15 +181,13 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
         }
         int16_t surface;
         ::memcpy(&surface, cursor++, 2);
-        if (surface < 0)
-        {
+        if (surface < 0) {
             surface = -surface;
 
             // there are detail polygons.
             uint16_t numPolygons;
             ::memcpy(&numPolygons, cursor++, 2);
-            if (cursor < end)
-            {
+            if (cursor < end) {
                 CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
             }
         }
@@ -215,8 +196,7 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
 }
 
 // ------------------------------------------------------------------------------------------------
-LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size)
-{
+LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size) {
     list.emplace_back();
     LWO::Texture* tex = &list.back();
 
@@ -224,8 +204,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i
     GetS0(type,size);
     const char* s = type.c_str();
 
-    if(strstr(s, "Image Map"))
-    {
+    if(strstr(s, "Image Map")) {
         // Determine mapping type
         if(strstr(s, "Planar"))
             tex->mapMode = LWO::Texture::Planar;
@@ -237,9 +216,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i
             tex->mapMode = LWO::Texture::Cubic;
         else if(strstr(s, "Front"))
             tex->mapMode = LWO::Texture::FrontProjection;
-    }
-    else
-    {
+    } else {
         // procedural or gradient, not supported
         ASSIMP_LOG_ERROR("LWOB: Unsupported legacy texture: ", type);
     }
@@ -248,8 +225,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i
 }
 
 // ------------------------------------------------------------------------------------------------
-void LWOImporter::LoadLWOBSurface(unsigned int size)
-{
+void LWOImporter::LoadLWOBSurface(unsigned int size) {
     LE_NCONST uint8_t* const end = mFileBuffer + size;
 
     mSurfaces->push_back( LWO::Surface () );
@@ -277,148 +253,147 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
         }
 
         uint8_t* const next = mFileBuffer+head.length;
-        switch (head.type)
-        {
-        // diffuse color
-        case AI_LWO_COLR:
-            {
-                AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3);
-                surf.mColor.r = GetU1() / 255.0f;
-                surf.mColor.g = GetU1() / 255.0f;
-                surf.mColor.b = GetU1() / 255.0f;
-                break;
-            }
-        // diffuse strength ...
-        case AI_LWO_DIFF:
-            {
-                AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2);
-                surf.mDiffuseValue = GetU2() / 255.0f;
-                break;
-            }
-        // specular strength ...
-        case AI_LWO_SPEC:
-            {
-                AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2);
-                surf.mSpecularValue = GetU2() / 255.0f;
-                break;
-            }
-        // luminosity ...
-        case AI_LWO_LUMI:
-            {
-                AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2);
-                surf.mLuminosity = GetU2() / 255.0f;
-                break;
-            }
-        // transparency
-        case AI_LWO_TRAN:
-            {
-                AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2);
-                surf.mTransparency = GetU2() / 255.0f;
-                break;
-            }
-        // surface flags
-        case AI_LWO_FLAG:
-            {
-                AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2);
-                uint16_t flag = GetU2();
-                if (flag & 0x4 )   surf.mMaximumSmoothAngle = 1.56207f;
-                if (flag & 0x8 )   surf.mColorHighlights = 1.f;
-                if (flag & 0x100)  surf.bDoubleSided = true;
-                break;
-            }
-        // maximum smoothing angle
-        case AI_LWO_SMAN:
-            {
-                AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
-                surf.mMaximumSmoothAngle = std::fabs( GetF4() );
-                break;
-            }
-        // glossiness
-        case AI_LWO_GLOS:
-            {
-                AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2);
-                surf.mGlossiness = (float)GetU2();
-                break;
-            }
-        // color texture
-        case AI_LWO_CTEX:
-            {
-                pTex = SetupNewTextureLWOB(surf.mColorTextures,
-                    head.length);
-                break;
-            }
-        // diffuse texture
-        case AI_LWO_DTEX:
-            {
-                pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
-                    head.length);
-                break;
-            }
-        // specular texture
-        case AI_LWO_STEX:
-            {
-                pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
-                    head.length);
-                break;
-            }
-        // bump texture
-        case AI_LWO_BTEX:
-            {
-                pTex = SetupNewTextureLWOB(surf.mBumpTextures,
-                    head.length);
-                break;
-            }
-        // transparency texture
-        case AI_LWO_TTEX:
-            {
-                pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
-                    head.length);
-                break;
-            }
-        // texture path
-        case AI_LWO_TIMG:
-            {
-                if (pTex)   {
-                    GetS0(pTex->mFileName,head.length);
-                } else {
-                    ASSIMP_LOG_WARN("LWOB: Unexpected TIMG chunk");
+        switch (head.type) {
+            // diffuse color
+            case AI_LWO_COLR:
+                {
+                    AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3);
+                    surf.mColor.r = GetU1() / 255.0f;
+                    surf.mColor.g = GetU1() / 255.0f;
+                    surf.mColor.b = GetU1() / 255.0f;
+                    break;
                 }
-                break;
-            }
-        // texture strength
-        case AI_LWO_TVAL:
-            {
-                AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1);
-                if (pTex)   {
-                    pTex->mStrength = (float)GetU1()/ 255.f;
-                } else {
-                    ASSIMP_LOG_ERROR("LWOB: Unexpected TVAL chunk");
+            // diffuse strength ...
+            case AI_LWO_DIFF:
+                {
+                    AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2);
+                    surf.mDiffuseValue = GetU2() / 255.0f;
+                    break;
                 }
-                break;
-            }
-        // texture flags
-        case AI_LWO_TFLG:
-            {
-                AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2);
-
-                if (nullptr != pTex) {
-                    const uint16_t s = GetU2();
-                    if (s & 1)
-                        pTex->majorAxis = LWO::Texture::AXIS_X;
-                    else if (s & 2)
-                        pTex->majorAxis = LWO::Texture::AXIS_Y;
-                    else if (s & 4)
-                        pTex->majorAxis = LWO::Texture::AXIS_Z;
-
-                    if (s & 16) {
-                        ASSIMP_LOG_WARN("LWOB: Ignoring \'negate\' flag on texture");
+            // specular strength ...
+            case AI_LWO_SPEC:
+                {
+                    AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2);
+                    surf.mSpecularValue = GetU2() / 255.0f;
+                    break;
+                }
+            // luminosity ...
+            case AI_LWO_LUMI:
+                {
+                    AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2);
+                    surf.mLuminosity = GetU2() / 255.0f;
+                    break;
+                }
+            // transparency
+            case AI_LWO_TRAN:
+                {
+                    AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2);
+                    surf.mTransparency = GetU2() / 255.0f;
+                    break;
+                }
+            // surface flags
+            case AI_LWO_FLAG:
+                {
+                    AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2);
+                    uint16_t flag = GetU2();
+                    if (flag & 0x4 )   surf.mMaximumSmoothAngle = 1.56207f;
+                    if (flag & 0x8 )   surf.mColorHighlights = 1.f;
+                    if (flag & 0x100)  surf.bDoubleSided = true;
+                    break;
+                }
+            // maximum smoothing angle
+            case AI_LWO_SMAN:
+                {
+                    AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
+                    surf.mMaximumSmoothAngle = std::fabs( GetF4() );
+                    break;
+                }
+            // glossiness
+            case AI_LWO_GLOS:
+                {
+                    AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2);
+                    surf.mGlossiness = (float)GetU2();
+                    break;
+                }
+            // color texture
+            case AI_LWO_CTEX:
+                {
+                    pTex = SetupNewTextureLWOB(surf.mColorTextures,
+                        head.length);
+                    break;
+                }
+            // diffuse texture
+            case AI_LWO_DTEX:
+                {
+                    pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
+                        head.length);
+                    break;
+                }
+            // specular texture
+            case AI_LWO_STEX:
+                {
+                    pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
+                        head.length);
+                    break;
+                }
+            // bump texture
+            case AI_LWO_BTEX:
+                {
+                    pTex = SetupNewTextureLWOB(surf.mBumpTextures,
+                        head.length);
+                    break;
+                }
+            // transparency texture
+            case AI_LWO_TTEX:
+                {
+                    pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
+                        head.length);
+                    break;
+                }
+            // texture path
+            case AI_LWO_TIMG:
+                {
+                    if (pTex)   {
+                        GetS0(pTex->mFileName,head.length);
+                    } else {
+                        ASSIMP_LOG_WARN("LWOB: Unexpected TIMG chunk");
                     }
+                    break;
                 }
-                else {
-                    ASSIMP_LOG_WARN("LWOB: Unexpected TFLG chunk");
+            // texture strength
+            case AI_LWO_TVAL:
+                {
+                    AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1);
+                    if (pTex)   {
+                        pTex->mStrength = (float)GetU1()/ 255.f;
+                    } else {
+                        ASSIMP_LOG_ERROR("LWOB: Unexpected TVAL chunk");
+                    }
+                    break;
+                }
+            // texture flags
+            case AI_LWO_TFLG:
+                {
+                    AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2);
+
+                    if (nullptr != pTex) {
+                        const uint16_t s = GetU2();
+                        if (s & 1)
+                            pTex->majorAxis = LWO::Texture::AXIS_X;
+                        else if (s & 2)
+                            pTex->majorAxis = LWO::Texture::AXIS_Y;
+                        else if (s & 4)
+                            pTex->majorAxis = LWO::Texture::AXIS_Z;
+
+                        if (s & 16) {
+                            ASSIMP_LOG_WARN("LWOB: Ignoring \'negate\' flag on texture");
+                        }
+                    }
+                    else {
+                        ASSIMP_LOG_WARN("LWOB: Unexpected TFLG chunk");
+                    }
+                    break;
                 }
-                break;
-            }
         }
         mFileBuffer = next;
     }

+ 1 - 5
code/AssetLib/LWS/LWSLoader.cpp

@@ -63,7 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "LightWave Scene Importer",
     "",
     "",
@@ -139,10 +139,6 @@ LWSImporter::LWSImporter() :
     // nothing to do here
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-LWSImporter::~LWSImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

+ 1 - 1
code/AssetLib/LWS/LWSLoader.h

@@ -174,7 +174,7 @@ struct NodeDesc {
 class LWSImporter : public BaseImporter {
 public:
     LWSImporter();
-    ~LWSImporter() override;
+    ~LWSImporter() override = default;
 
     // -------------------------------------------------------------------
     // Check whether we can read a specific file

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

@@ -85,7 +85,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       are listed in aiScene->mRootNode->children, but all without meshes
 */
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Model 3D Importer",
     "",
     "",

+ 2 - 9
code/AssetLib/MD2/MD2Loader.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2022, assimp team
 
-
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -41,7 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ---------------------------------------------------------------------------
 */
 
-
 #ifndef ASSIMP_BUILD_NO_MD2_IMPORTER
 
 /** @file Implementation of the MD2 importer class */
@@ -65,7 +62,7 @@ using namespace Assimp::MD2;
 #   define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0])))
 #endif
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Quake II Mesh Importer",
     "",
     "",
@@ -79,7 +76,7 @@ static const aiImporterDesc desc = {
 };
 
 // ------------------------------------------------------------------------------------------------
-// Helper function to lookup a normal in Quake 2's precalculated table
+// Helper function to lookup a normal in Quake 2's pre-calculated table
 void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut)
 {
     // make sure the normal index has a valid value
@@ -100,10 +97,6 @@ MD2Importer::MD2Importer()
     fileSize()
 {}
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-MD2Importer::~MD2Importer() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const

+ 1 - 1
code/AssetLib/MD2/MD2Loader.h

@@ -63,7 +63,7 @@ using namespace MD2;
 class MD2Importer : public BaseImporter {
 public:
     MD2Importer();
-    ~MD2Importer() override;
+    ~MD2Importer() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 1 - 1
code/AssetLib/MD3/MD3Loader.cpp

@@ -70,7 +70,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Quake III Mesh Importer",
     "",
     "",

+ 1 - 5
code/AssetLib/MD5/MD5Loader.cpp

@@ -64,7 +64,7 @@ using namespace Assimp;
 // Minimum weight value. Weights inside [-n ... n] are ignored
 #define AI_MD5_WEIGHT_EPSILON Math::getEpsilon<float>()
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Doom 3 / MD5 Mesh Importer",
     "",
     "",
@@ -92,10 +92,6 @@ MD5Importer::MD5Importer() :
     // empty
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-MD5Importer::~MD5Importer() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

+ 1 - 1
code/AssetLib/MD5/MD5Loader.h

@@ -65,7 +65,7 @@ using namespace Assimp::MD5;
 class MD5Importer : public BaseImporter {
 public:
     MD5Importer();
-    ~MD5Importer() override;
+    ~MD5Importer() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 1 - 5
code/AssetLib/MDC/MDCLoader.cpp

@@ -60,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 using namespace Assimp::MDC;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Return To Castle Wolfenstein Mesh Importer",
     "",
     "",
@@ -103,10 +103,6 @@ MDCImporter::MDCImporter() :
     // empty
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-MDCImporter::~MDCImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

+ 1 - 1
code/AssetLib/MDC/MDCLoader.h

@@ -62,7 +62,7 @@ using namespace MDC;
 class MDCImporter : public BaseImporter {
 public:
     MDCImporter();
-    ~MDCImporter() override;
+    ~MDCImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 1 - 5
code/AssetLib/MDL/MDLLoader.cpp

@@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Quake Mesh / 3D GameStudio Mesh Importer",
     "",
     "",
@@ -96,10 +96,6 @@ MDLImporter::MDLImporter() :
     // empty
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-MDLImporter::~MDLImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

+ 4 - 7
code/AssetLib/MDL/MDLLoader.h

@@ -39,10 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
-
-/**  @file MDLLoader.h
- *   @brief Declaration of the loader for MDL files
- */
+/// @file MDLLoader.h
+/// @brief Declaration of the loader for MDL files
 #pragma once
 #ifndef AI_MDLLOADER_H_INCLUDED
 #define AI_MDLLOADER_H_INCLUDED
@@ -83,11 +81,10 @@ using namespace MDL;
  *  them all with a single 1000-line function-beast. However, it has been
  *  split into several code paths to make the code easier to read and maintain.
 */
-class MDLImporter : public BaseImporter
-{
+class MDLImporter : public BaseImporter {
 public:
     MDLImporter();
-    ~MDLImporter() override;
+    ~MDLImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 1 - 5
code/AssetLib/MMD/MMDImporter.cpp

@@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <memory>
 #include <sstream>
 
-static const aiImporterDesc desc = { "MMD Importer",
+static constexpr aiImporterDesc desc = { "MMD Importer",
     "",
     "",
     "surfaces supported?",
@@ -81,10 +81,6 @@ MMDImporter::MMDImporter() :
     m_strAbsPath = io.getOsSeparator();
 }
 
-// ------------------------------------------------------------------------------------------------
-//  Destructor.
-MMDImporter::~MMDImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 //  Returns true, if file is an pmx file.
 bool MMDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler,

+ 7 - 19
code/AssetLib/MMD/MMDImporter.h

@@ -50,46 +50,34 @@ struct aiMesh;
 namespace Assimp {
 
 // ------------------------------------------------------------------------------------------------
-/// \class  MMDImporter
-/// \brief  Imports MMD a pmx/pmd/vmd file
+/// @class  MMDImporter
+/// @brief  Imports MMD a pmx/pmd/vmd file
 // ------------------------------------------------------------------------------------------------
 class MMDImporter : public BaseImporter {
 public:
-    /// \brief  Default constructor
+    /// @brief  Default constructor
     MMDImporter();
 
-    /// \brief  Destructor
-    ~MMDImporter() override;
+    /// @brief  Destructor
+    ~MMDImporter() override = default;
 
 public:
-    /// \brief  Returns whether the class can handle the format of the given file.
-    /// \remark See BaseImporter::CanRead() for details.
+    /// @brief  Returns whether the class can handle the format of the given file.
+    /// @remark See BaseImporter::CanRead() for details.
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override;
 
 private:
-    //! \brief  Appends the supported extension.
     const aiImporterDesc* GetInfo() const override;
-
-    //! \brief  File import implementation.
     void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
-
-    //! \brief  Create the data from imported content.
     void CreateDataFromImport(const pmx::PmxModel* pModel, aiScene* pScene);
-
-    //! \brief Create the mesh
     aiMesh* CreateMesh(const pmx::PmxModel* pModel, const int indexStart, const int indexCount);
-
-    //! \brief Create the material
     aiMaterial* CreateMaterial(const pmx::PmxMaterial* pMat, const pmx::PmxModel* pModel);
 
 private:
-    //! Data buffer
     std::vector<char> m_Buffer;
-    //! Absolute pathname of model in file system
     std::string m_strAbsPath;
 };
 
-// ------------------------------------------------------------------------------------------------
 
 } // Namespace Assimp
 

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

@@ -60,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Milkshape 3D Importer",
     "",
     "",
@@ -84,9 +84,6 @@ MS3DImporter::MS3DImporter()
     : mScene()
 {}
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-MS3DImporter::~MS3DImporter() = default;
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool MS3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const

+ 2 - 1
code/AssetLib/MS3D/MS3DLoader.h

@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/BaseImporter.h>
 #include <assimp/StreamReader.h>
+
 struct aiNode;
 
 namespace Assimp {
@@ -58,7 +59,7 @@ namespace Assimp {
 class MS3DImporter : public BaseImporter {
 public:
     MS3DImporter();
-    ~MS3DImporter() override;
+    ~MS3DImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

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

@@ -43,8 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  Implementation of the NDO importer class.
  */
 
-
 #ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
+
 #include "NDOLoader.h"
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
@@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Nendo Mesh Importer",
     "",
     "",
@@ -69,14 +69,6 @@ static const aiImporterDesc desc = {
     "ndo"
 };
 
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-NDOImporter::NDOImporter() = default;
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-NDOImporter::~NDOImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const

+ 2 - 2
code/AssetLib/NDO/NDOLoader.h

@@ -65,8 +65,8 @@ class Importer;
 */
 class NDOImporter : public BaseImporter {
 public:
-    NDOImporter();
-    ~NDOImporter() override;
+    NDOImporter() = default; 
+    ~NDOImporter() override = default;
 
     //! Represents a single edge
     struct Edge {

+ 15 - 20
code/AssetLib/NFF/NFFLoader.cpp

@@ -56,9 +56,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Neutral File Format Importer",
     "",
     "",
@@ -71,14 +71,6 @@ static const aiImporterDesc desc = {
     "enff nff"
 };
 
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-NFFImporter::NFFImporter() = default;
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-NFFImporter::~NFFImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool NFFImporter::CanRead(const std::string & pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
@@ -94,7 +86,7 @@ const aiImporterDesc *NFFImporter::GetInfo() const {
 // ------------------------------------------------------------------------------------------------
 #define AI_NFF_PARSE_FLOAT(f) \
     SkipSpaces(&sz);          \
-    if (!::IsLineEnd(*sz)) sz = fast_atoreal_move<ai_real>(sz, (ai_real &)f);
+    if (!IsLineEnd(*sz)) sz = fast_atoreal_move<ai_real>(sz, (ai_real &)f);
 
 // ------------------------------------------------------------------------------------------------
 #define AI_NFF_PARSE_TRIPLE(v) \
@@ -338,8 +330,8 @@ void NFFImporter::InternReadFile(const std::string &pFile,
                         break;
                 }
 
-                // read the numbr of vertices
-                unsigned int num = ::strtoul10(sz, &sz);
+                // read the number of vertices
+                unsigned int num = strtoul10(sz, &sz);
 
                 // temporary storage
                 std::vector<aiColor4D> tempColors;
@@ -365,7 +357,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
                         // color definition
                         if (TokenMatch(sz, "0x", 2)) {
                             hasColor = true;
-                            unsigned int numIdx = ::strtoul16(sz, &sz);
+                            unsigned int numIdx = strtoul16(sz, &sz);
                             aiColor4D clr;
                             clr.a = 1.f;
 
@@ -403,15 +395,16 @@ void NFFImporter::InternReadFile(const std::string &pFile,
                 }
 
                 AI_NFF2_GET_NEXT_TOKEN();
-                if (!num) throw DeadlyImportError("NFF2: There are zero vertices");
-                num = ::strtoul10(sz, &sz);
+                if (!num)
+                    throw DeadlyImportError("NFF2: There are zero vertices");
+                num = strtoul10(sz, &sz);
 
                 std::vector<unsigned int> tempIdx;
                 tempIdx.reserve(10);
                 for (unsigned int i = 0; i < num; ++i) {
                     AI_NFF2_GET_NEXT_TOKEN();
                     SkipSpaces(line, &sz);
-                    unsigned int numIdx = ::strtoul10(sz, &sz);
+                    unsigned int numIdx = strtoul10(sz, &sz);
 
                     // read all faces indices
                     if (numIdx) {
@@ -421,7 +414,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
 
                         for (unsigned int a = 0; a < numIdx; ++a) {
                             SkipSpaces(sz, &sz);
-                            unsigned int m = ::strtoul10(sz, &sz);
+                            unsigned int m = strtoul10(sz, &sz);
                             if (m >= (unsigned int)tempPositions.size()) {
                                 ASSIMP_LOG_ERROR("NFF2: Vertex index overflow");
                                 m = 0;
@@ -446,7 +439,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
                         if (TokenMatch(sz, "0x", 2)) {
                             hasColor = true;
                             const char *sz2 = sz;
-                            numIdx = ::strtoul16(sz, &sz);
+                            numIdx = strtoul16(sz, &sz);
                             const unsigned int diff = (unsigned int)(sz - sz2);
 
                             // 0xRRGGBB
@@ -518,7 +511,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
                         // Material ID?
                         else if (!materialTable.empty() && TokenMatch(sz, "matid", 5)) {
                             SkipSpaces(&sz);
-                            matIdx = ::strtoul10(sz, &sz);
+                            matIdx = strtoul10(sz, &sz);
                             if (matIdx >= materialTable.size()) {
                                 ASSIMP_LOG_ERROR("NFF2: Material index overflow.");
                                 matIdx = 0;
@@ -1165,4 +1158,6 @@ void NFFImporter::InternReadFile(const std::string &pFile,
     pScene->mRootNode = root;
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_NFF_IMPORTER

+ 2 - 2
code/AssetLib/NFF/NFFLoader.h

@@ -63,8 +63,8 @@ namespace Assimp {
 */
 class NFFImporter : public BaseImporter {
 public:
-    NFFImporter();
-    ~NFFImporter() override;
+    NFFImporter() = default;
+    ~NFFImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 124 - 129
code/AssetLib/OFF/OFFLoader.cpp

@@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the OFF importer class
  */
 
-
 #ifndef ASSIMP_BUILD_NO_OFF_IMPORTER
 
 // internal headers
@@ -56,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/importerdesc.h>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "OFF Importer",
     "",
     "",
@@ -71,99 +70,92 @@ static const aiImporterDesc desc = {
     "off"
 };
 
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-OFFImporter::OFFImporter() = default;
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-OFFImporter::~OFFImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
-bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const
-{
-    static const char* tokens[] = { "off" };
-    return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens),3);
+bool OFFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
+    static const char *tokens[] = { "off" };
+    return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens), 3);
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiImporterDesc* OFFImporter::GetInfo () const
-{
+const aiImporterDesc *OFFImporter::GetInfo() const {
     return &desc;
 }
 
-
 // skip blank space, lines and comments
-static void NextToken(const char **car, const char* end) {
-  SkipSpacesAndLineEnd(car);
-  while (*car < end && (**car == '#' || **car == '\n' || **car == '\r')) {
-    SkipLine(car);
+static void NextToken(const char **car, const char *end) {
     SkipSpacesAndLineEnd(car);
-  }
+    while (*car < end && (**car == '#' || **car == '\n' || **car == '\r')) {
+        SkipLine(car);
+        SkipSpacesAndLineEnd(car);
+    }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
-void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
-    std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
+void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
+    std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
 
     // Check whether we can read from the file
     if (file == nullptr) {
-      throw DeadlyImportError("Failed to open OFF file ", pFile, ".");
+        throw DeadlyImportError("Failed to open OFF file ", pFile, ".");
     }
 
     // allocate storage and copy the contents of the file to a memory buffer
     std::vector<char> mBuffer2;
-    TextFileToBuffer(file.get(),mBuffer2);
-    const char* buffer = &mBuffer2[0];
+    TextFileToBuffer(file.get(), mBuffer2);
+    const char *buffer = &mBuffer2[0];
 
     // Proper OFF header parser. We only implement normal loading for now.
     bool hasTexCoord = false, hasNormals = false, hasColors = false;
     bool hasHomogenous = false, hasDimension = false;
     unsigned int dimensions = 3;
-    const char* car = buffer;
-    const char* end = buffer + mBuffer2.size();
+    const char *car = buffer;
+    const char *end = buffer + mBuffer2.size();
     NextToken(&car, end);
 
     if (car < end - 2 && car[0] == 'S' && car[1] == 'T') {
-      hasTexCoord = true; car += 2;
+        hasTexCoord = true;
+        car += 2;
     }
     if (car < end - 1 && car[0] == 'C') {
-      hasColors = true; car++;
+        hasColors = true;
+        car++;
     }
-    if (car < end- 1 && car[0] == 'N') {
-      hasNormals = true; car++;
+    if (car < end - 1 && car[0] == 'N') {
+        hasNormals = true;
+        car++;
     }
     if (car < end - 1 && car[0] == '4') {
-      hasHomogenous = true; car++;
+        hasHomogenous = true;
+        car++;
     }
     if (car < end - 1 && car[0] == 'n') {
-      hasDimension = true; car++;
+        hasDimension = true;
+        car++;
     }
     if (car < end - 3 && car[0] == 'O' && car[1] == 'F' && car[2] == 'F') {
         car += 3;
-	NextToken(&car, end);
+        NextToken(&car, end);
     } else {
-      // in case there is no OFF header (which is allowed by the
-      // specification...), then we might have unintentionally read an
-      // additional dimension from the primitive count fields
-      dimensions = 3;
-      hasHomogenous = false;
-      NextToken(&car, end);
-
-      // at this point the next token should be an integer number
-      if (car >= end - 1 || *car < '0' || *car > '9') {
-	throw DeadlyImportError("OFF: Header is invalid");
-      }
+        // in case there is no OFF header (which is allowed by the
+        // specification...), then we might have unintentionally read an
+        // additional dimension from the primitive count fields
+        dimensions = 3;
+        hasHomogenous = false;
+        NextToken(&car, end);
+
+        // at this point the next token should be an integer number
+        if (car >= end - 1 || *car < '0' || *car > '9') {
+            throw DeadlyImportError("OFF: Header is invalid");
+        }
     }
     if (hasDimension) {
         dimensions = strtoul10(car, &car);
-	NextToken(&car, end);
+        NextToken(&car, end);
     }
     if (dimensions > 3) {
-        throw DeadlyImportError
-	  ("OFF: Number of vertex coordinates higher than 3 unsupported");
+        throw DeadlyImportError("OFF: Number of vertex coordinates higher than 3 unsupported");
     }
 
     NextToken(&car, end);
@@ -171,7 +163,7 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
     NextToken(&car, end);
     const unsigned int numFaces = strtoul10(car, &car);
     NextToken(&car, end);
-    strtoul10(car, &car);  // skip edge count
+    strtoul10(car, &car); // skip edge count
     NextToken(&car, end);
 
     if (!numVertices) {
@@ -182,13 +174,13 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
     }
 
     pScene->mNumMeshes = 1;
-    pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ];
+    pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
 
-    aiMesh* mesh = new aiMesh();
+    aiMesh *mesh = new aiMesh();
     pScene->mMeshes[0] = mesh;
 
     mesh->mNumFaces = numFaces;
-    aiFace* faces = new aiFace[mesh->mNumFaces];
+    aiFace *faces = new aiFace[mesh->mNumFaces];
     mesh->mFaces = faces;
 
     mesh->mNumVertices = numVertices;
@@ -206,100 +198,101 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
 
     // now read all vertex lines
     for (unsigned int i = 0; i < numVertices; ++i) {
-        if(!GetNextLine(buffer, line)) {
+        if (!GetNextLine(buffer, line)) {
             ASSIMP_LOG_ERROR("OFF: The number of verts in the header is incorrect");
             break;
         }
-        aiVector3D& v = mesh->mVertices[i];
+        aiVector3D &v = mesh->mVertices[i];
         sz = line;
 
-	// helper array to write a for loop over possible dimension values
-	ai_real* vec[3] = {&v.x, &v.y, &v.z};
-
-	// stop at dimensions: this allows loading 1D or 2D coordinate vertices
-        for (unsigned int dim = 0; dim < dimensions; ++dim ) {
-	    SkipSpaces(&sz);
-	    sz = fast_atoreal_move<ai_real>(sz, *vec[dim]);
-	}
-
-	// if has homogeneous coordinate, divide others by this one
-	if (hasHomogenous) {
-	    SkipSpaces(&sz);
-	    ai_real w = 1.;
-	    sz = fast_atoreal_move<ai_real>(sz, w);
-            for (unsigned int dim = 0; dim < dimensions; ++dim ) {
-	        *(vec[dim]) /= w;
-	    }
-	}
-
-	// read optional normals
-	if (hasNormals) {
-	    aiVector3D& n = mesh->mNormals[i];
-	    SkipSpaces(&sz);
-	    sz = fast_atoreal_move<ai_real>(sz,(ai_real&)n.x);
-	    SkipSpaces(&sz);
-	    sz = fast_atoreal_move<ai_real>(sz,(ai_real&)n.y);
-	    SkipSpaces(&sz);
-	    fast_atoreal_move<ai_real>(sz,(ai_real&)n.z);
-	}
-
-	// reading colors is a pain because the specification says it can be
-	// integers or floats, and any number of them between 1 and 4 included,
-	// until the next comment or end of line
-	// in theory should be testing type !
-	if (hasColors) {
-	    aiColor4D& c = mesh->mColors[0][i];
-	    SkipSpaces(&sz);
-	    sz = fast_atoreal_move<ai_real>(sz,(ai_real&)c.r);
+        // helper array to write a for loop over possible dimension values
+        ai_real *vec[3] = { &v.x, &v.y, &v.z };
+
+        // stop at dimensions: this allows loading 1D or 2D coordinate vertices
+        for (unsigned int dim = 0; dim < dimensions; ++dim) {
+            SkipSpaces(&sz);
+            sz = fast_atoreal_move<ai_real>(sz, *vec[dim]);
+        }
+
+        // if has homogeneous coordinate, divide others by this one
+        if (hasHomogenous) {
+            SkipSpaces(&sz);
+            ai_real w = 1.;
+            sz = fast_atoreal_move<ai_real>(sz, w);
+            for (unsigned int dim = 0; dim < dimensions; ++dim) {
+                *(vec[dim]) /= w;
+            }
+        }
+
+        // read optional normals
+        if (hasNormals) {
+            aiVector3D &n = mesh->mNormals[i];
+            SkipSpaces(&sz);
+            sz = fast_atoreal_move<ai_real>(sz, (ai_real &)n.x);
+            SkipSpaces(&sz);
+            sz = fast_atoreal_move<ai_real>(sz, (ai_real &)n.y);
+            SkipSpaces(&sz);
+            fast_atoreal_move<ai_real>(sz, (ai_real &)n.z);
+        }
+
+        // reading colors is a pain because the specification says it can be
+        // integers or floats, and any number of them between 1 and 4 included,
+        // until the next comment or end of line
+        // in theory should be testing type !
+        if (hasColors) {
+            aiColor4D &c = mesh->mColors[0][i];
+            SkipSpaces(&sz);
+            sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.r);
             if (*sz != '#' && *sz != '\n' && *sz != '\r') {
-	        SkipSpaces(&sz);
-	        sz = fast_atoreal_move<ai_real>(sz,(ai_real&)c.g);
+                SkipSpaces(&sz);
+                sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.g);
             } else {
-	        c.g = 0.;
-	    }
+                c.g = 0.;
+            }
             if (*sz != '#' && *sz != '\n' && *sz != '\r') {
-	        SkipSpaces(&sz);
-	        sz = fast_atoreal_move<ai_real>(sz,(ai_real&)c.b);
+                SkipSpaces(&sz);
+                sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.b);
             } else {
-	        c.b = 0.;
-	    }
+                c.b = 0.;
+            }
             if (*sz != '#' && *sz != '\n' && *sz != '\r') {
-	        SkipSpaces(&sz);
-	        sz = fast_atoreal_move<ai_real>(sz,(ai_real&)c.a);
+                SkipSpaces(&sz);
+                sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.a);
             } else {
-	        c.a = 1.;
-	    }
-	}
+                c.a = 1.;
+            }
+        }
         if (hasTexCoord) {
-	    aiVector3D& t = mesh->mTextureCoords[0][i];
-	    SkipSpaces(&sz);
-	    sz = fast_atoreal_move<ai_real>(sz,(ai_real&)t.x);
-	    SkipSpaces(&sz);
-	    fast_atoreal_move<ai_real>(sz,(ai_real&)t.y);
-	}
+            aiVector3D &t = mesh->mTextureCoords[0][i];
+            SkipSpaces(&sz);
+            sz = fast_atoreal_move<ai_real>(sz, (ai_real &)t.x);
+            SkipSpaces(&sz);
+            fast_atoreal_move<ai_real>(sz, (ai_real &)t.y);
+        }
     }
 
     // load faces with their indices
     faces = mesh->mFaces;
-    for (unsigned int i = 0; i < numFaces; ) {
-        if(!GetNextLine(buffer,line)) {
+    for (unsigned int i = 0; i < numFaces;) {
+        if (!GetNextLine(buffer, line)) {
             ASSIMP_LOG_ERROR("OFF: The number of faces in the header is incorrect");
             throw DeadlyImportError("OFF: The number of faces in the header is incorrect");
         }
         unsigned int idx;
-        sz = line; SkipSpaces(&sz);
-        idx = strtoul10(sz,&sz);
-        if(!idx || idx > 9) {
-	        ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed");
+        sz = line;
+        SkipSpaces(&sz);
+        idx = strtoul10(sz, &sz);
+        if (!idx || idx > 9) {
+            ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed");
             --mesh->mNumFaces;
             ++i;
             continue;
-	    }
-	    faces->mNumIndices = idx;
+        }
+        faces->mNumIndices = idx;
         faces->mIndices = new unsigned int[faces->mNumIndices];
-        for (unsigned int m = 0; m < faces->mNumIndices;++m) {
+        for (unsigned int m = 0; m < faces->mNumIndices; ++m) {
             SkipSpaces(&sz);
-            idx = strtoul10(sz,&sz);
+            idx = strtoul10(sz, &sz);
             if (idx >= numVertices) {
                 ASSIMP_LOG_ERROR("OFF: Vertex index is out of range");
                 idx = numVertices - 1;
@@ -314,20 +307,22 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
     pScene->mRootNode = new aiNode();
     pScene->mRootNode->mName.Set("<OFFRoot>");
     pScene->mRootNode->mNumMeshes = 1;
-    pScene->mRootNode->mMeshes = new unsigned int [pScene->mRootNode->mNumMeshes];
+    pScene->mRootNode->mMeshes = new unsigned int[pScene->mRootNode->mNumMeshes];
     pScene->mRootNode->mMeshes[0] = 0;
 
     // generate a default material
     pScene->mNumMaterials = 1;
-    pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials];
-    aiMaterial* pcMat = new aiMaterial();
+    pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
+    aiMaterial *pcMat = new aiMaterial();
 
-    aiColor4D clr( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 1.0 ) );
-    pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE);
+    aiColor4D clr(ai_real(0.6), ai_real(0.6), ai_real(0.6), ai_real(1.0));
+    pcMat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
     pScene->mMaterials[0] = pcMat;
 
     const int twosided = 1;
     pcMat->AddProperty(&twosided, 1, AI_MATKEY_TWOSIDED);
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_OFF_IMPORTER

+ 2 - 2
code/AssetLib/OFF/OFFLoader.h

@@ -57,8 +57,8 @@ namespace Assimp {
 */
 class OFFImporter : public BaseImporter {
 public:
-    OFFImporter();
-    ~OFFImporter() override;
+    OFFImporter() = default;
+    ~OFFImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 10 - 3
code/AssetLib/Obj/ObjFileImporter.cpp

@@ -54,7 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/ObjMaterial.h>
 #include <memory>
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Wavefront Object Importer",
     "",
     "",
@@ -78,7 +78,9 @@ using namespace std;
 ObjFileImporter::ObjFileImporter() :
         m_Buffer(),
         m_pRootObject(nullptr),
-        m_strAbsPath(std::string(1, DefaultIOSystem().getOsSeparator())) {}
+        m_strAbsPath(std::string(1, DefaultIOSystem().getOsSeparator())) {
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
 //  Destructor.
@@ -101,8 +103,13 @@ const aiImporterDesc *ObjFileImporter::GetInfo() const {
 // ------------------------------------------------------------------------------------------------
 //  Obj-file import implementation
 void ObjFileImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSystem *pIOHandler) {
+    if (m_pRootObject != nullptr) {
+        delete m_pRootObject;
+        m_pRootObject = nullptr;
+    }
+
     // Read file into memory
-    static const std::string mode = "rb";
+    static constexpr char mode[] = "rb";
     auto streamCloser = [&](IOStream *pStream) {
         pIOHandler->Close(pStream);
     };

+ 1 - 1
code/AssetLib/Ogre/OgreImporter.cpp

@@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/Importer.hpp>
 #include <memory>
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Ogre3D Mesh Importer",
     "",
     "",

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

@@ -52,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/scene.h>
 #include <openddlparser/OpenDDLParser.h>
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Open Game Engine Exchange",
     "",
     "",
@@ -66,42 +66,42 @@ static const aiImporterDesc desc = {
 };
 
 namespace Grammar {
-    static const char* MetricType = "Metric";
-    static const char *Metric_DistanceType = "distance";
-    static const char *Metric_AngleType = "angle";
-    static const char *Metric_TimeType = "time";
-    static const char *Metric_UpType = "up";
-    static const char *NameType = "Name";
-    static const char *ObjectRefType = "ObjectRef";
-    static const char *MaterialRefType = "MaterialRef";
-    static const char *MetricKeyType = "key";
-    static const char *GeometryNodeType = "GeometryNode";
-    static const char *CameraNodeType = "CameraNode";
-    static const char *LightNodeType = "LightNode";
-    static const char *GeometryObjectType = "GeometryObject";
-    static const char *CameraObjectType = "CameraObject";
-    static const char *LightObjectType = "LightObject";
-    static const char *TransformType = "Transform";
-    static const char *MeshType = "Mesh";
-    static const char *VertexArrayType = "VertexArray";
-    static const char *IndexArrayType = "IndexArray";
-    static const char *MaterialType = "Material";
-    static const char *ColorType = "Color";
-    static const char *ParamType = "Param";
-    static const char *TextureType = "Texture";
-    static const char *AttenType = "Atten";
-
-    static const char *DiffuseColorToken = "diffuse";
-    static const char *SpecularColorToken = "specular";
-    static const char *EmissionColorToken = "emission";
-
-    static const char *DiffuseTextureToken = "diffuse";
-    static const char *DiffuseSpecularTextureToken = "specular";
-    static const char *SpecularPowerTextureToken = "specular_power";
-    static const char *EmissionTextureToken = "emission";
-    static const char *OpacyTextureToken = "opacity";
-    static const char *TransparencyTextureToken = "transparency";
-    static const char *NormalTextureToken = "normal";
+    static constexpr char MetricType[] = "Metric";
+    static constexpr char Metric_DistanceType[] = "distance";
+    static constexpr char Metric_AngleType[] = "angle";
+    static constexpr char Metric_TimeType[] = "time";
+    static constexpr char Metric_UpType[] = "up";
+    static constexpr char NameType[] = "Name";
+    static constexpr char ObjectRefType[] = "ObjectRef";
+    static constexpr char MaterialRefType[] = "MaterialRef";
+    static constexpr char MetricKeyType[] = "key";
+    static constexpr char GeometryNodeType[] = "GeometryNode";
+    static constexpr char CameraNodeType[] = "CameraNode";
+    static constexpr char LightNodeType[] = "LightNode";
+    static constexpr char GeometryObjectType[] = "GeometryObject";
+    static constexpr char CameraObjectType[] = "CameraObject";
+    static constexpr char LightObjectType[] = "LightObject";
+    static constexpr char TransformType[] = "Transform";
+    static constexpr char MeshType[] = "Mesh";
+    static constexpr char VertexArrayType[] = "VertexArray";
+    static constexpr char IndexArrayType[] = "IndexArray";
+    static constexpr char MaterialType[] = "Material";
+    static constexpr char ColorType[] = "Color";
+    static constexpr char ParamType[] = "Param";
+    static constexpr char TextureType[] = "Texture";
+    static constexpr char AttenType[] = "Atten";
+
+    static constexpr char DiffuseColorToken[] = "diffuse";
+    static constexpr char SpecularColorToken[] = "specular";
+    static constexpr char EmissionColorToken[] = "emission";
+
+    static constexpr char DiffuseTextureToken[] = "diffuse";
+    static constexpr char DiffuseSpecularTextureToken[] = "specular";
+    static constexpr char SpecularPowerTextureToken[] = "specular_power";
+    static constexpr char EmissionTextureToken[] = "emission";
+    static constexpr char OpacyTextureToken[] = "opacity";
+    static constexpr char TransparencyTextureToken[] = "transparency";
+    static constexpr char NormalTextureToken[] = "normal";
 
     enum TokenType {
         NoneType = -1,
@@ -139,7 +139,7 @@ namespace Grammar {
             return false;
         }
 
-        int idx(-1);
+        int idx = -1;
         for (size_t i = 0; i < 4; i++) {
             if (ValidMetricToken[i] == token) {
                 idx = (int)i;

+ 26 - 28
code/AssetLib/Ply/PlyLoader.cpp

@@ -53,9 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 #include <memory>
 
-using namespace ::Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Stanford Polygon Library (PLY) Importer",
     "",
     "",
@@ -71,16 +71,16 @@ static const aiImporterDesc desc = {
 // ------------------------------------------------------------------------------------------------
 // Internal stuff
 namespace {
-// ------------------------------------------------------------------------------------------------
-// Checks that property index is within range
-template <class T>
-inline const T &GetProperty(const std::vector<T> &props, int idx) {
-    if (static_cast<size_t>(idx) >= props.size()) {
-        throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
-    }
+    // ------------------------------------------------------------------------------------------------
+    // Checks that property index is within range
+    template <class T>
+    inline const T &GetProperty(const std::vector<T> &props, int idx) {
+        if (static_cast<size_t>(idx) >= props.size()) {
+            throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
+        }
 
-    return props[idx];
-}
+        return props[idx];
+    }
 } // namespace
 
 // ------------------------------------------------------------------------------------------------
@@ -92,10 +92,6 @@ PLYImporter::PLYImporter() :
     // empty
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-PLYImporter::~PLYImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@@ -215,7 +211,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
         throw DeadlyImportError("Invalid .ply file: Missing format specification");
     }
 
-    //free the file buffer
+    // free the file buffer
     streamedBuffer.close();
 
     if (mGeneratedMesh == nullptr) {
@@ -376,7 +372,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
             haveNormal = true;
         }
 
-        //Colors
+        // Colors
         aiColor4D cOut;
         bool haveColor = false;
         if (0xFFFFFFFF != aiColors[0]) {
@@ -415,7 +411,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
             haveColor = true;
         }
 
-        //Texture coordinates
+        // Texture coordinates
         aiVector3D tOut;
         tOut.z = 0;
         bool haveTextureCoords = false;
@@ -431,7 +427,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
             haveTextureCoords = true;
         }
 
-        //create aiMesh if needed
+        // create aiMesh if needed
         if (nullptr == mGeneratedMesh) {
             mGeneratedMesh = new aiMesh();
             mGeneratedMesh->mMaterialIndex = 0;
@@ -512,8 +508,8 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
     bool bIsTriStrip = false;
 
     // index of the material index property
-    //unsigned int iMaterialIndex = 0xFFFFFFFF;
-    //PLY::EDataType eType2 = EDT_Char;
+    // unsigned int iMaterialIndex = 0xFFFFFFFF;
+    // PLY::EDataType eType2 = EDT_Char;
 
     // texture coordinates
     unsigned int iTextureCoord = 0xFFFFFFFF;
@@ -595,7 +591,7 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
             if (0xFFFFFFFF != iTextureCoord) {
                 const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
 
-                //should be 6 coords
+                // should be 6 coords
                 std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
                         GetProperty(instElement->alProperties, iTextureCoord).avList.begin();
 
@@ -625,7 +621,7 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
             // a value of -1 indicates a restart of the strip
             bool flip = false;
             const std::vector<PLY::PropertyInstance::ValueUnion> &quak = GetProperty(instElement->alProperties, iProperty).avList;
-            //pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption
+            // pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption
 
             int aiTable[2] = { -1, -1 };
             for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin(); a != quak.end(); ++a) {
@@ -863,7 +859,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
             const int two_sided = 1;
             pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
 
-            //default texture
+            // default texture
             if (!defaultTexture.empty()) {
                 const aiString name(defaultTexture.c_str());
                 pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
@@ -873,7 +869,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
                 pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
             }
 
-            //set to wireframe, so when using this material info we can switch to points rendering
+            // set to wireframe, so when using this material info we can switch to points rendering
             if (pointsOnly) {
                 const int wireframe = 1;
                 pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
@@ -890,7 +886,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
         int iMode = (int)aiShadingMode_Gouraud;
         pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
 
-        //generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color
+        // generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color
         aiColor3D clr;
         clr.b = clr.g = clr.r = 1.0f;
         pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
@@ -906,13 +902,13 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
             pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
         }
 
-        //default texture
+        // default texture
         if (!defaultTexture.empty()) {
             const aiString name(defaultTexture.c_str());
             pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
         }
 
-        //set to wireframe, so when using this material info we can switch to points rendering
+        // set to wireframe, so when using this material info we can switch to points rendering
         if (pointsOnly) {
             const int wireframe = 1;
             pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
@@ -922,4 +918,6 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
     }
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER

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

@@ -65,7 +65,7 @@ using namespace PLY;
 class PLYImporter : public BaseImporter {
 public:
     PLYImporter();
-    ~PLYImporter() override;
+    ~PLYImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

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

@@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <sstream>
 #include <vector>
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Quake III BSP Importer",
     "",
     "",
@@ -146,7 +146,11 @@ Q3BSPFileImporter::Q3BSPFileImporter() :
 // ------------------------------------------------------------------------------------------------
 //  Destructor.
 Q3BSPFileImporter::~Q3BSPFileImporter() {
-    // Clear face-to-material map
+    clear();
+}
+
+// ------------------------------------------------------------------------------------------------
+void Q3BSPFileImporter::clear() {
     for (FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) {
         const std::string &matName = it->first;
         if (!matName.empty()) {
@@ -173,6 +177,7 @@ const aiImporterDesc *Q3BSPFileImporter::GetInfo() const {
 // ------------------------------------------------------------------------------------------------
 //  Import method.
 void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene, IOSystem *ioHandler) {
+    clear();
     ZipArchiveIOSystem Archive(ioHandler, rFile);
     if (!Archive.isOpen()) {
         throw DeadlyImportError("Failed to open file ", rFile, ".");

+ 1 - 0
code/AssetLib/Q3BSP/Q3BSPFileImporter.h

@@ -81,6 +81,7 @@ protected:
     using FaceMapIt = std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>* >::iterator;
     using FaceMapConstIt = std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*>::const_iterator;
 
+    void clear();
     const aiImporterDesc* GetInfo () const override;
     void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
     void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName );

+ 10 - 15
code/AssetLib/Q3D/Q3DLoader.cpp

@@ -55,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Quick3D Importer",
     "",
     "",
@@ -127,7 +127,7 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
     std::vector<Material> materials;
     try {
         materials.reserve(numMats);
-    } catch(const std::bad_alloc&) {
+    } catch (const std::bad_alloc &) {
         ASSIMP_LOG_ERROR("Invalid alloc for materials.");
         throw DeadlyImportError("Invalid Quick3D-file, material allocation failed.");
     }
@@ -135,7 +135,7 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
     std::vector<Mesh> meshes;
     try {
         meshes.reserve(numMeshes);
-    } catch(const std::bad_alloc&) {
+    } catch (const std::bad_alloc &) {
         ASSIMP_LOG_ERROR("Invalid alloc for meshes.");
         throw DeadlyImportError("Invalid Quick3D-file, mesh allocation failed.");
     }
@@ -237,7 +237,6 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
                 if (minor > '0' && major == '3')
                     stream.IncPtr(mesh.faces.size());
             }
-            // stream.IncPtr(4); // unknown value here
         } break;
 
             // materials chunk
@@ -275,8 +274,6 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
                 // read the transparency
                 mat.transparency = stream.GetF4();
 
-                // unknown value here
-                // stream.IncPtr(4);
                 // FIX: it could be the texture index ...
                 mat.texIdx = (unsigned int)stream.GetI4();
             }
@@ -425,7 +422,8 @@ outer:
     pScene->mMeshes = new aiMesh *[pScene->mNumMaterials];
 
     for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i) {
-        if (fidx[i].empty()) continue;
+        if (fidx[i].empty())
+            continue;
 
         // Allocate a mesh and a material
         aiMesh *mesh = pScene->mMeshes[real] = new aiMesh();
@@ -548,14 +546,9 @@ outer:
     // Now we need to attach the meshes to the root node of the scene
     pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
     pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
-    for (unsigned int i = 0; i < pScene->mNumMeshes; ++i)
+    for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
         pScene->mRootNode->mMeshes[i] = i;
-
-    /*pScene->mRootNode->mTransformation *= aiMatrix4x4(
-        1.f, 0.f, 0.f, 0.f,
-        0.f, -1.f,0.f, 0.f,
-        0.f, 0.f, 1.f, 0.f,
-        0.f, 0.f, 0.f, 1.f);*/
+    }
 
     // Add cameras and light sources to the scene root node
     pScene->mRootNode->mNumChildren = pScene->mNumLights + pScene->mNumCameras;
@@ -577,4 +570,6 @@ outer:
     }
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_Q3D_IMPORTER

+ 4 - 10
code/AssetLib/Raw/RawLoader.cpp

@@ -55,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Raw Importer",
     "",
     "",
@@ -70,14 +70,6 @@ static const aiImporterDesc desc = {
     "raw"
 };
 
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-RAWImporter::RAWImporter() = default;
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-RAWImporter::~RAWImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool RAWImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
@@ -295,4 +287,6 @@ void RAWImporter::InternReadFile(const std::string &pFile,
     }
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_RAW_IMPORTER

+ 2 - 2
code/AssetLib/Raw/RawLoader.h

@@ -57,8 +57,8 @@ namespace Assimp {
 */
 class RAWImporter : public BaseImporter {
 public:
-    RAWImporter();
-    ~RAWImporter() override;
+    RAWImporter() = default;
+    ~RAWImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 5 - 12
code/AssetLib/SIB/SIBImporter.cpp

@@ -69,9 +69,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <map>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Silo SIB Importer",
     "Richard Mitton (http://www.codersnotes.com/about)",
     "",
@@ -94,7 +94,7 @@ enum {
     N
 };
 
-typedef std::pair<uint32_t, uint32_t> SIBPair;
+using SIBPair = std::pair<uint32_t, uint32_t>;
 
 struct SIBEdge {
     uint32_t faceA, faceB;
@@ -199,15 +199,6 @@ static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) {
 
     return result;
 }
-
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-SIBImporter::SIBImporter() = default;
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-SIBImporter::~SIBImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool SIBImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
@@ -882,4 +873,6 @@ void SIBImporter::InternReadFile(const std::string &pFile,
     }
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_SIB_IMPORTER

+ 2 - 2
code/AssetLib/SIB/SIBImporter.h

@@ -57,8 +57,8 @@ namespace Assimp {
 */
 class ASSIMP_API SIBImporter : public BaseImporter {
 public:
-    SIBImporter();
-    ~SIBImporter() override;
+    SIBImporter() = default;
+    ~SIBImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 4 - 2
code/AssetLib/SMD/SMDLoader.cpp

@@ -64,9 +64,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define strtok_s strtok_r
 #endif
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Valve SMD Importer",
     "",
     "",
@@ -1077,4 +1077,6 @@ void SMDImporter::ParseVertex(const char* szCurrent,
     SMDI_PARSE_RETURN;
 }
 
+}
+
 #endif // !! ASSIMP_BUILD_NO_SMD_IMPORTER

+ 21 - 20
code/AssetLib/STL/STLLoader.cpp

@@ -52,11 +52,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 
 namespace {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Stereolithography (STL) Importer",
     "",
     "",
@@ -129,7 +129,7 @@ STLImporter::STLImporter() :
         mBuffer(),
         mFileSize(0),
         mScene() {
-   // empty
+    // empty
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -250,13 +250,13 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
         sz += 5; // skip the "solid"
         SkipSpaces(&sz);
         const char *szMe = sz;
-        while (!::IsSpaceOrNewLine(*sz)) {
+        while (!IsSpaceOrNewLine(*sz)) {
             sz++;
         }
 
         size_t temp = (size_t)(sz - szMe);
         // setup the name of the node
-        if ( temp ) {
+        if (temp) {
             if (temp >= MAXLEN) {
                 throw DeadlyImportError("STL: Node name too long");
             }
@@ -303,7 +303,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
                     normalBuffer.emplace_back(vn);
                     normalBuffer.emplace_back(vn);
                 }
-            } else if (!strncmp(sz, "vertex", 6) && ::IsSpaceOrNewLine(*(sz + 6))) { // vertex 1.50000 1.50000 0.00000
+            } else if (!strncmp(sz, "vertex", 6) && IsSpaceOrNewLine(*(sz + 6))) { // vertex 1.50000 1.50000 0.00000
                 if (faceVertexCounter >= 3) {
                     ASSIMP_LOG_ERROR("STL: a facet with more than 3 vertices has been found");
                     ++sz;
@@ -325,14 +325,14 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
             } else if (!::strncmp(sz, "endsolid", 8)) {
                 do {
                     ++sz;
-                } while (!::IsLineEnd(*sz));
+                } while (!IsLineEnd(*sz));
                 SkipSpacesAndLineEnd(&sz);
                 // finished!
                 break;
             } else { // else skip the whole identifier
                 do {
                     ++sz;
-                } while (!::IsSpaceOrNewLine(*sz));
+                } while (!IsSpaceOrNewLine(*sz));
             }
         }
 
@@ -349,14 +349,14 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
             throw DeadlyImportError("Normal buffer size does not match position buffer size");
         }
 
-        // only process positionbuffer when filled, else exception when accessing with index operator
+        // only process position buffer when filled, else exception when accessing with index operator
         // see line 353: only warning is triggered
-        // see line 373(now): access to empty positionbuffer with index operator forced exception
+        // see line 373(now): access to empty position buffer with index operator forced exception
         if (!positionBuffer.empty()) {
             pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3);
             pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size());
             pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
-            for (size_t i=0; i<pMesh->mNumVertices; ++i ) {
+            for (size_t i = 0; i < pMesh->mNumVertices; ++i) {
                 pMesh->mVertices[i].x = positionBuffer[i].x;
                 pMesh->mVertices[i].y = positionBuffer[i].y;
                 pMesh->mVertices[i].z = positionBuffer[i].z;
@@ -366,7 +366,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
         // also only process normalBuffer when filled, else exception when accessing with index operator
         if (!normalBuffer.empty()) {
             pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
-            for (size_t i=0; i<pMesh->mNumVertices; ++i ) {
+            for (size_t i = 0; i < pMesh->mNumVertices; ++i) {
                 pMesh->mNormals[i].x = normalBuffer[i].x;
                 pMesh->mNormals[i].y = normalBuffer[i].y;
                 pMesh->mNormals[i].z = normalBuffer[i].z;
@@ -450,9 +450,8 @@ bool STLImporter::LoadBinaryFile() {
     aiVector3D *vp = pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
     aiVector3D *vn = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
 
-    typedef aiVector3t<float> aiVector3F;
-    aiVector3F *theVec;
-    aiVector3F theVec3F;
+    aiVector3f *theVec;
+    aiVector3f theVec3F;
 
     for (unsigned int i = 0; i < pMesh->mNumFaces; ++i) {
         // NOTE: Blender sometimes writes empty normals ... this is not
@@ -460,8 +459,8 @@ bool STLImporter::LoadBinaryFile() {
 
         // There's one normal for the face in the STL; use it three times
         // for vertex normals
-        theVec = (aiVector3F *)sz;
-        ::memcpy(&theVec3F, theVec, sizeof(aiVector3F));
+        theVec = (aiVector3f *)sz;
+        ::memcpy(&theVec3F, theVec, sizeof(aiVector3f));
         vn->x = theVec3F.x;
         vn->y = theVec3F.y;
         vn->z = theVec3F.z;
@@ -471,7 +470,7 @@ bool STLImporter::LoadBinaryFile() {
         vn += 3;
 
         // vertex 1
-        ::memcpy(&theVec3F, theVec, sizeof(aiVector3F));
+        ::memcpy(&theVec3F, theVec, sizeof(aiVector3f));
         vp->x = theVec3F.x;
         vp->y = theVec3F.y;
         vp->z = theVec3F.z;
@@ -479,7 +478,7 @@ bool STLImporter::LoadBinaryFile() {
         ++vp;
 
         // vertex 2
-        ::memcpy(&theVec3F, theVec, sizeof(aiVector3F));
+        ::memcpy(&theVec3F, theVec, sizeof(aiVector3f));
         vp->x = theVec3F.x;
         vp->y = theVec3F.y;
         vp->z = theVec3F.z;
@@ -487,7 +486,7 @@ bool STLImporter::LoadBinaryFile() {
         ++vp;
 
         // vertex 3
-        ::memcpy(&theVec3F, theVec, sizeof(aiVector3F));
+        ::memcpy(&theVec3F, theVec, sizeof(aiVector3f));
         vp->x = theVec3F.x;
         vp->y = theVec3F.y;
         vp->z = theVec3F.z;
@@ -570,4 +569,6 @@ void STLImporter::pushMeshesToNode(std::vector<unsigned int> &meshIndices, aiNod
     meshIndices.clear();
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_STL_IMPORTER

+ 4 - 6
code/AssetLib/Terragen/TerragenLoader.cpp

@@ -51,9 +51,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 #include <assimp/Importer.hpp>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Terragen Heightmap Importer",
     "",
     "",
@@ -73,10 +73,6 @@ TerragenImporter::TerragenImporter() :
     // empty
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-TerragenImporter::~TerragenImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@@ -244,4 +240,6 @@ void TerragenImporter::InternReadFile(const std::string &pFile,
     pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_TERRAGEN_IMPORTER

+ 1 - 1
code/AssetLib/Terragen/TerragenLoader.h

@@ -73,7 +73,7 @@ namespace Assimp {
 class TerragenImporter : public BaseImporter {
 public:
     TerragenImporter();
-    ~TerragenImporter() override;
+    ~TerragenImporter() override = default;
 
     // -------------------------------------------------------------------
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler,

+ 9 - 7
code/AssetLib/Unreal/UnrealLoader.cpp

@@ -63,7 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <cstdint>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 
 namespace Unreal {
 
@@ -152,7 +152,7 @@ inline void DecompressVertex(aiVector3D &v, int32_t in) {
 
 } // end namespace Unreal
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Unreal Mesh Importer",
     "",
     "",
@@ -178,7 +178,7 @@ UnrealImporter::~UnrealImporter() = default;
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
-bool UnrealImporter::CanRead(const std::string & filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
+bool UnrealImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
     return SimpleExtensionCheck(filename, "3d", "uc");
 }
 
@@ -336,12 +336,12 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
                         tempTextures.emplace_back();
                         std::pair<std::string, std::string> &me = tempTextures.back();
                         for (; !IsLineEnd(*data); ++data) {
-                            if (!::ASSIMP_strincmp(data, "NAME=", 5)) {
+                            if (!ASSIMP_strincmp(data, "NAME=", 5)) {
                                 const char *d = data += 5;
                                 for (; !IsSpaceOrNewLine(*data); ++data)
                                     ;
                                 me.first = std::string(d, (size_t)(data - d));
-                            } else if (!::ASSIMP_strincmp(data, "FILE=", 5)) {
+                            } else if (!ASSIMP_strincmp(data, "FILE=", 5)) {
                                 const char *d = data += 5;
                                 for (; !IsSpaceOrNewLine(*data); ++data)
                                     ;
@@ -363,10 +363,10 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
                         std::pair<unsigned int, std::string> &me = textures.back();
 
                         for (; !IsLineEnd(*data); ++data) {
-                            if (!::ASSIMP_strincmp(data, "NUM=", 4)) {
+                            if (!ASSIMP_strincmp(data, "NUM=", 4)) {
                                 data += 4;
                                 me.first = strtoul10(data, &data);
-                            } else if (!::ASSIMP_strincmp(data, "TEXTURE=", 8)) {
+                            } else if (!ASSIMP_strincmp(data, "TEXTURE=", 8)) {
                                 data += 8;
                                 const char *d = data;
                                 for (; !IsSpaceOrNewLine(*data); ++data)
@@ -516,4 +516,6 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
     flipper.Execute(pScene);
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_3D_IMPORTER

+ 216 - 218
code/AssetLib/X/XFileImporter.cpp

@@ -57,10 +57,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <cctype>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
+
 using namespace Assimp::Formatter;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Direct3D XFile Importer",
     "",
     "",
@@ -73,142 +74,137 @@ static const aiImporterDesc desc = {
     "x"
 };
 
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-XFileImporter::XFileImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
-bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const {
+bool XFileImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
     static const uint32_t token[] = { AI_MAKE_MAGIC("xof ") };
-    return CheckMagicToken(pIOHandler,pFile,token,AI_COUNT_OF(token));
+    return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token));
 }
 
 // ------------------------------------------------------------------------------------------------
 // Get file extension list
-const aiImporterDesc* XFileImporter::GetInfo () const {
+const aiImporterDesc *XFileImporter::GetInfo() const {
     return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
-void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) {
+void XFileImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
     // read file into memory
-    std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
+    std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
     if (file == nullptr) {
-        throw DeadlyImportError( "Failed to open file ", pFile, "." );
+        throw DeadlyImportError("Failed to open file ", pFile, ".");
     }
 
     static const size_t MinSize = 16;
     size_t fileSize = file->FileSize();
-    if ( fileSize < MinSize ) {
-        throw DeadlyImportError( "XFile is too small." );
+    if (fileSize < MinSize) {
+        throw DeadlyImportError("XFile is too small.");
     }
 
     // in the hope that binary files will never start with a BOM ...
-    mBuffer.resize( fileSize + 1);
-    file->Read( &mBuffer.front(), 1, fileSize);
+    mBuffer.resize(fileSize + 1);
+    file->Read(&mBuffer.front(), 1, fileSize);
     ConvertToUTF8(mBuffer);
 
     // parse the file into a temporary representation
-    XFileParser parser( mBuffer);
+    XFileParser parser(mBuffer);
 
     // and create the proper return structures out of it
-    CreateDataRepresentationFromImport( pScene, parser.GetImportedData());
+    CreateDataRepresentationFromImport(pScene, parser.GetImportedData());
 
     // if nothing came from it, report it as error
-    if ( !pScene->mRootNode ) {
-        throw DeadlyImportError( "XFile is ill-formatted - no content imported." );
+    if (!pScene->mRootNode) {
+        throw DeadlyImportError("XFile is ill-formatted - no content imported.");
     }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Constructs the return data structure out of the imported data.
-void XFileImporter::CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData)
-{
+void XFileImporter::CreateDataRepresentationFromImport(aiScene *pScene, XFile::Scene *pData) {
     // Read the global materials first so that meshes referring to them can find them later
-    ConvertMaterials( pScene, pData->mGlobalMaterials);
+    ConvertMaterials(pScene, pData->mGlobalMaterials);
 
     // copy nodes, extracting meshes and materials on the way
-    pScene->mRootNode = CreateNodes( pScene, nullptr, pData->mRootNode);
+    pScene->mRootNode = CreateNodes(pScene, nullptr, pData->mRootNode);
 
     // extract animations
-    CreateAnimations( pScene, pData);
+    CreateAnimations(pScene, pData);
 
     // read the global meshes that were stored outside of any node
-    if( !pData->mGlobalMeshes.empty() )  {
+    if (!pData->mGlobalMeshes.empty()) {
         // create a root node to hold them if there isn't any, yet
-        if( pScene->mRootNode == nullptr ) {
+        if (pScene->mRootNode == nullptr) {
             pScene->mRootNode = new aiNode;
-            pScene->mRootNode->mName.Set( "$dummy_node");
+            pScene->mRootNode->mName.Set("$dummy_node");
         }
 
         // convert all global meshes and store them in the root node.
         // If there was one before, the global meshes now suddenly have its transformation matrix...
         // Don't know what to do there, I don't want to insert another node under the present root node
         // just to avoid this.
-        CreateMeshes( pScene, pScene->mRootNode, pData->mGlobalMeshes);
+        CreateMeshes(pScene, pScene->mRootNode, pData->mGlobalMeshes);
     }
 
     if (!pScene->mRootNode) {
-        throw DeadlyImportError( "No root node" );
+        throw DeadlyImportError("No root node");
     }
 
     // Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly
     MakeLeftHandedProcess convertProcess;
-    convertProcess.Execute( pScene);
+    convertProcess.Execute(pScene);
 
     FlipWindingOrderProcess flipper;
     flipper.Execute(pScene);
 
     // finally: create a dummy material if not material was imported
-    if( pScene->mNumMaterials == 0) {
+    if (pScene->mNumMaterials == 0) {
         pScene->mNumMaterials = 1;
         // create the Material
-        aiMaterial* mat = new aiMaterial;
-        int shadeMode = (int) aiShadingMode_Gouraud;
-        mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
+        aiMaterial *mat = new aiMaterial;
+        int shadeMode = (int)aiShadingMode_Gouraud;
+        mat->AddProperty<int>(&shadeMode, 1, AI_MATKEY_SHADING_MODEL);
         // material colours
         int specExp = 1;
 
-        aiColor3D clr = aiColor3D( 0, 0, 0);
-        mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_EMISSIVE);
-        mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_SPECULAR);
+        aiColor3D clr = aiColor3D(0, 0, 0);
+        mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_EMISSIVE);
+        mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
 
-        clr = aiColor3D( 0.5f, 0.5f, 0.5f);
-        mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_DIFFUSE);
-        mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS);
+        clr = aiColor3D(0.5f, 0.5f, 0.5f);
+        mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
+        mat->AddProperty(&specExp, 1, AI_MATKEY_SHININESS);
 
-        pScene->mMaterials = new aiMaterial*[1];
+        pScene->mMaterials = new aiMaterial *[1];
         pScene->mMaterials[0] = mat;
     }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Recursively creates scene nodes from the imported hierarchy.
-aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFile::Node* pNode) {
-    if ( !pNode ) {
+aiNode *XFileImporter::CreateNodes(aiScene *pScene, aiNode *pParent, const XFile::Node *pNode) {
+    if (!pNode) {
         return nullptr;
     }
 
     // create node
-    aiNode* node = new aiNode;
+    aiNode *node = new aiNode;
     node->mName.length = (ai_uint32)pNode->mName.length();
     node->mParent = pParent;
-    memcpy( node->mName.data, pNode->mName.c_str(), pNode->mName.length());
+    memcpy(node->mName.data, pNode->mName.c_str(), pNode->mName.length());
     node->mName.data[node->mName.length] = 0;
     node->mTransformation = pNode->mTrafoMatrix;
 
     // convert meshes from the source node
-    CreateMeshes( pScene, node, pNode->mMeshes);
+    CreateMeshes(pScene, node, pNode->mMeshes);
 
     // handle children
-    if( !pNode->mChildren.empty() ) {
+    if (!pNode->mChildren.empty()) {
         node->mNumChildren = (unsigned int)pNode->mChildren.size();
-        node->mChildren = new aiNode* [node->mNumChildren];
+        node->mChildren = new aiNode *[node->mNumChildren];
 
-        for ( unsigned int a = 0; a < pNode->mChildren.size(); ++a ) {
-            node->mChildren[ a ] = CreateNodes( pScene, node, pNode->mChildren[ a ] );
+        for (unsigned int a = 0; a < pNode->mChildren.size(); ++a) {
+            node->mChildren[a] = CreateNodes(pScene, node, pNode->mChildren[a]);
         }
     }
 
@@ -217,55 +213,55 @@ aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFil
 
 // ------------------------------------------------------------------------------------------------
 // Creates the meshes for the given node.
-void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector<XFile::Mesh*>& pMeshes) {
+void XFileImporter::CreateMeshes(aiScene *pScene, aiNode *pNode, const std::vector<XFile::Mesh *> &pMeshes) {
     if (pMeshes.empty()) {
         return;
     }
 
     // create a mesh for each mesh-material combination in the source node
-    std::vector<aiMesh*> meshes;
-    for( unsigned int a = 0; a < pMeshes.size(); ++a ) {
-        XFile::Mesh* sourceMesh = pMeshes[a];
-        if ( nullptr == sourceMesh ) {
+    std::vector<aiMesh *> meshes;
+    for (unsigned int a = 0; a < pMeshes.size(); ++a) {
+        XFile::Mesh *sourceMesh = pMeshes[a];
+        if (nullptr == sourceMesh) {
             continue;
         }
 
         // first convert its materials so that we can find them with their index afterwards
-        ConvertMaterials( pScene, sourceMesh->mMaterials);
+        ConvertMaterials(pScene, sourceMesh->mMaterials);
 
-        unsigned int numMaterials = std::max( (unsigned int)sourceMesh->mMaterials.size(), 1u);
-        for( unsigned int b = 0; b < numMaterials; ++b ) {
+        unsigned int numMaterials = std::max((unsigned int)sourceMesh->mMaterials.size(), 1u);
+        for (unsigned int b = 0; b < numMaterials; ++b) {
             // collect the faces belonging to this material
             std::vector<unsigned int> faces;
             unsigned int numVertices = 0;
-            if( !sourceMesh->mFaceMaterials.empty() ) {
+            if (!sourceMesh->mFaceMaterials.empty()) {
                 // if there is a per-face material defined, select the faces with the corresponding material
-                for( unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); ++c ) {
-                    if( sourceMesh->mFaceMaterials[c] == b) {
-                        faces.push_back( c);
+                for (unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); ++c) {
+                    if (sourceMesh->mFaceMaterials[c] == b) {
+                        faces.push_back(c);
                         numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size();
                     }
                 }
             } else {
                 // if there is no per-face material, place everything into one mesh
-                for( unsigned int c = 0; c < sourceMesh->mPosFaces.size(); ++c ) {
-                    faces.push_back( c);
+                for (unsigned int c = 0; c < sourceMesh->mPosFaces.size(); ++c) {
+                    faces.push_back(c);
                     numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size();
                 }
             }
 
             // no faces/vertices using this material? strange...
-            if ( numVertices == 0 ) {
+            if (numVertices == 0) {
                 continue;
             }
 
             // create a submesh using this material
-            aiMesh* mesh = new aiMesh;
-            meshes.push_back( mesh);
+            aiMesh *mesh = new aiMesh;
+            meshes.push_back(mesh);
 
             // find the material in the scene's material list. Either own material
             // or referenced material, it should already have a valid index
-            if( !sourceMesh->mFaceMaterials.empty() ) {
+            if (!sourceMesh->mFaceMaterials.empty()) {
                 mesh->mMaterialIndex = static_cast<unsigned int>(sourceMesh->mMaterials[b].sceneIndex);
             } else {
                 mesh->mMaterialIndex = 0;
@@ -282,41 +278,41 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
             mesh->mName.Set(sourceMesh->mName);
 
             // normals?
-            if ( sourceMesh->mNormals.size() > 0 ) {
-                mesh->mNormals = new aiVector3D[ numVertices ];
+            if (sourceMesh->mNormals.size() > 0) {
+                mesh->mNormals = new aiVector3D[numVertices];
             }
             // texture coords
-            for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c ) {
-                if ( !sourceMesh->mTexCoords[ c ].empty() ) {
-                    mesh->mTextureCoords[ c ] = new aiVector3D[ numVertices ];
+            for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) {
+                if (!sourceMesh->mTexCoords[c].empty()) {
+                    mesh->mTextureCoords[c] = new aiVector3D[numVertices];
                 }
             }
             // vertex colors
-            for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c ) {
-                if ( !sourceMesh->mColors[ c ].empty() ) {
-                    mesh->mColors[ c ] = new aiColor4D[ numVertices ];
+            for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) {
+                if (!sourceMesh->mColors[c].empty()) {
+                    mesh->mColors[c] = new aiColor4D[numVertices];
                 }
             }
 
             // now collect the vertex data of all data streams present in the imported mesh
-            unsigned int newIndex( 0 );
+            unsigned int newIndex(0);
             std::vector<unsigned int> orgPoints; // from which original point each new vertex stems
-            orgPoints.resize( numVertices, 0);
+            orgPoints.resize(numVertices, 0);
 
-            for( unsigned int c = 0; c < faces.size(); ++c ) {
+            for (unsigned int c = 0; c < faces.size(); ++c) {
                 unsigned int f = faces[c]; // index of the source face
-                const XFile::Face& pf = sourceMesh->mPosFaces[f]; // position source face
+                const XFile::Face &pf = sourceMesh->mPosFaces[f]; // position source face
 
                 // create face. either triangle or triangle fan depending on the index count
-                aiFace& df = mesh->mFaces[c]; // destination face
+                aiFace &df = mesh->mFaces[c]; // destination face
                 df.mNumIndices = (unsigned int)pf.mIndices.size();
-                df.mIndices = new unsigned int[ df.mNumIndices];
+                df.mIndices = new unsigned int[df.mNumIndices];
 
                 // collect vertex data for indices of this face
-                for( unsigned int d = 0; d < df.mNumIndices; ++d ) {
-                    df.mIndices[ d ] = newIndex;
-                    const unsigned int newIdx( pf.mIndices[ d ] );
-                    if ( newIdx > sourceMesh->mPositions.size() ) {
+                for (unsigned int d = 0; d < df.mNumIndices; ++d) {
+                    df.mIndices[d] = newIndex;
+                    const unsigned int newIdx = pf.mIndices[d];
+                    if (newIdx >= sourceMesh->mPositions.size()) {
                         continue;
                     }
 
@@ -325,24 +321,26 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
                     // Position
                     mesh->mVertices[newIndex] = sourceMesh->mPositions[pf.mIndices[d]];
                     // Normal, if present
-                    if ( mesh->HasNormals() ) {
-                        if ( sourceMesh->mNormFaces[ f ].mIndices.size() > d ) {
-                            const size_t idx( sourceMesh->mNormFaces[ f ].mIndices[ d ] );
-                            mesh->mNormals[ newIndex ] = sourceMesh->mNormals[ idx ];
+                    if (mesh->HasNormals()) {
+                        if (sourceMesh->mNormFaces[f].mIndices.size() > d) {
+                            const size_t idx(sourceMesh->mNormFaces[f].mIndices[d]);
+                            if (idx < sourceMesh->mNormals.size()) {
+                                mesh->mNormals[newIndex] = sourceMesh->mNormals[idx];
+                            }
                         }
                     }
 
                     // texture coord sets
-                    for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++e ) {
-                        if( mesh->HasTextureCoords( e)) {
+                    for (unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++e) {
+                        if (mesh->HasTextureCoords(e)) {
                             aiVector2D tex = sourceMesh->mTexCoords[e][pf.mIndices[d]];
-                            mesh->mTextureCoords[e][newIndex] = aiVector3D( tex.x, 1.0f - tex.y, 0.0f);
+                            mesh->mTextureCoords[e][newIndex] = aiVector3D(tex.x, 1.0f - tex.y, 0.0f);
                         }
                     }
                     // vertex color sets
-                    for ( unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; ++e ) {
-                        if ( mesh->HasVertexColors( e ) ) {
-                            mesh->mColors[ e ][ newIndex ] = sourceMesh->mColors[ e ][ pf.mIndices[ d ] ];
+                    for (unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; ++e) {
+                        if (mesh->HasVertexColors(e)) {
+                            mesh->mColors[e][newIndex] = sourceMesh->mColors[e][pf.mIndices[d]];
                         }
                     }
 
@@ -351,63 +349,66 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
             }
 
             // there should be as much new vertices as we calculated before
-            ai_assert( newIndex == numVertices);
+            ai_assert(newIndex == numVertices);
 
             // convert all bones of the source mesh which influence vertices in this newly created mesh
-            const std::vector<XFile::Bone>& bones = sourceMesh->mBones;
-            std::vector<aiBone*> newBones;
-            for( unsigned int c = 0; c < bones.size(); ++c ) {
-                const XFile::Bone& obone = bones[c];
+            const std::vector<XFile::Bone> &bones = sourceMesh->mBones;
+            std::vector<aiBone *> newBones;
+            for (unsigned int c = 0; c < bones.size(); ++c) {
+                const XFile::Bone &obone = bones[c];
                 // set up a vertex-linear array of the weights for quick searching if a bone influences a vertex
-                std::vector<ai_real> oldWeights( sourceMesh->mPositions.size(), 0.0);
-                for ( unsigned int d = 0; d < obone.mWeights.size(); ++d ) {
-                    oldWeights[ obone.mWeights[ d ].mVertex ] = obone.mWeights[ d ].mWeight;
+                std::vector<ai_real> oldWeights(sourceMesh->mPositions.size(), 0.0);
+                for (unsigned int d = 0; d < obone.mWeights.size(); ++d) {
+                    const unsigned int boneIdx = obone.mWeights[d].mVertex;
+                    if (boneIdx < obone.mWeights.size()) {
+                        oldWeights[obone.mWeights[d].mVertex] = obone.mWeights[d].mWeight;
+                    }
                 }
 
                 // collect all vertex weights that influence a vertex in the new mesh
                 std::vector<aiVertexWeight> newWeights;
-                newWeights.reserve( numVertices);
-                for( unsigned int d = 0; d < orgPoints.size(); ++d ) {
+                newWeights.reserve(numVertices);
+                for (unsigned int d = 0; d < orgPoints.size(); ++d) {
                     // does the new vertex stem from an old vertex which was influenced by this bone?
                     ai_real w = oldWeights[orgPoints[d]];
-                    if ( w > 0.0 ) {
-                        newWeights.emplace_back( d, w );
+                    if (w > 0.0) {
+                        newWeights.emplace_back(d, w);
                     }
                 }
 
                 // if the bone has no weights in the newly created mesh, ignore it
-                if ( newWeights.empty() ) {
+                if (newWeights.empty()) {
                     continue;
                 }
 
                 // create
-                aiBone* nbone = new aiBone;
-                newBones.push_back( nbone);
+                aiBone *nbone = new aiBone;
+                newBones.push_back(nbone);
                 // copy name and matrix
-                nbone->mName.Set( obone.mName);
+                nbone->mName.Set(obone.mName);
                 nbone->mOffsetMatrix = obone.mOffsetMatrix;
                 nbone->mNumWeights = (unsigned int)newWeights.size();
                 nbone->mWeights = new aiVertexWeight[nbone->mNumWeights];
-                for ( unsigned int d = 0; d < newWeights.size(); ++d ) {
-                    nbone->mWeights[ d ] = newWeights[ d ];
+                for (unsigned int d = 0; d < newWeights.size(); ++d) {
+                    nbone->mWeights[d] = newWeights[d];
                 }
             }
 
             // store the bones in the mesh
             mesh->mNumBones = (unsigned int)newBones.size();
-            if( !newBones.empty()) {
-                mesh->mBones = new aiBone*[mesh->mNumBones];
-                std::copy( newBones.begin(), newBones.end(), mesh->mBones);
+            if (!newBones.empty()) {
+                mesh->mBones = new aiBone *[mesh->mNumBones];
+                std::copy(newBones.begin(), newBones.end(), mesh->mBones);
             }
         }
     }
 
     // reallocate scene mesh array to be large enough
-    aiMesh** prevArray = pScene->mMeshes;
-    pScene->mMeshes = new aiMesh*[pScene->mNumMeshes + meshes.size()];
-    if( prevArray) {
-        memcpy( pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof( aiMesh*));
-        delete [] prevArray;
+    aiMesh **prevArray = pScene->mMeshes;
+    pScene->mMeshes = new aiMesh *[pScene->mNumMeshes + meshes.size()];
+    if (prevArray) {
+        memcpy(pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof(aiMesh *));
+        delete[] prevArray;
     }
 
     // allocate mesh index array in the node
@@ -415,7 +416,7 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
     pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
 
     // store all meshes in the mesh library of the scene and store their indices in the node
-    for( unsigned int a = 0; a < meshes.size(); a++) {
+    for (unsigned int a = 0; a < meshes.size(); a++) {
         pScene->mMeshes[pScene->mNumMeshes] = meshes[a];
         pNode->mMeshes[a] = pScene->mNumMeshes;
         pScene->mNumMeshes++;
@@ -424,35 +425,34 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
 
 // ------------------------------------------------------------------------------------------------
 // Converts the animations from the given imported data and creates them in the scene.
-void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData) {
-    std::vector<aiAnimation*> newAnims;
+void XFileImporter::CreateAnimations(aiScene *pScene, const XFile::Scene *pData) {
+    std::vector<aiAnimation *> newAnims;
 
-    for( unsigned int a = 0; a < pData->mAnims.size(); ++a ) {
-        const XFile::Animation* anim = pData->mAnims[a];
+    for (unsigned int a = 0; a < pData->mAnims.size(); ++a) {
+        const XFile::Animation *anim = pData->mAnims[a];
         // some exporters mock me with empty animation tags.
-        if ( anim->mAnims.empty() ) {
+        if (anim->mAnims.empty()) {
             continue;
         }
 
         // create a new animation to hold the data
-        aiAnimation* nanim = new aiAnimation;
-        newAnims.push_back( nanim);
-        nanim->mName.Set( anim->mName);
+        aiAnimation *nanim = new aiAnimation;
+        newAnims.push_back(nanim);
+        nanim->mName.Set(anim->mName);
         // duration will be determined by the maximum length
         nanim->mDuration = 0;
         nanim->mTicksPerSecond = pData->mAnimTicksPerSecond;
         nanim->mNumChannels = (unsigned int)anim->mAnims.size();
-        nanim->mChannels = new aiNodeAnim*[nanim->mNumChannels];
+        nanim->mChannels = new aiNodeAnim *[nanim->mNumChannels];
 
-        for( unsigned int b = 0; b < anim->mAnims.size(); ++b ) {
-            const XFile::AnimBone* bone = anim->mAnims[b];
-            aiNodeAnim* nbone = new aiNodeAnim;
-            nbone->mNodeName.Set( bone->mBoneName);
+        for (unsigned int b = 0; b < anim->mAnims.size(); ++b) {
+            const XFile::AnimBone *bone = anim->mAnims[b];
+            aiNodeAnim *nbone = new aiNodeAnim;
+            nbone->mNodeName.Set(bone->mBoneName);
             nanim->mChannels[b] = nbone;
 
             // key-frames are given as combined transformation matrix keys
-            if( !bone->mTrafoKeys.empty() )
-            {
+            if (!bone->mTrafoKeys.empty()) {
                 nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size();
                 nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys];
                 nbone->mNumRotationKeys = (unsigned int)bone->mTrafoKeys.size();
@@ -460,44 +460,44 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
                 nbone->mNumScalingKeys = (unsigned int)bone->mTrafoKeys.size();
                 nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys];
 
-                for( unsigned int c = 0; c < bone->mTrafoKeys.size(); ++c)  {
+                for (unsigned int c = 0; c < bone->mTrafoKeys.size(); ++c) {
                     // deconstruct each matrix into separate position, rotation and scaling
                     double time = bone->mTrafoKeys[c].mTime;
                     aiMatrix4x4 trafo = bone->mTrafoKeys[c].mMatrix;
 
                     // extract position
-                    aiVector3D pos( trafo.a4, trafo.b4, trafo.c4);
+                    aiVector3D pos(trafo.a4, trafo.b4, trafo.c4);
 
                     nbone->mPositionKeys[c].mTime = time;
                     nbone->mPositionKeys[c].mValue = pos;
 
                     // extract scaling
                     aiVector3D scale;
-                    scale.x = aiVector3D( trafo.a1, trafo.b1, trafo.c1).Length();
-                    scale.y = aiVector3D( trafo.a2, trafo.b2, trafo.c2).Length();
-                    scale.z = aiVector3D( trafo.a3, trafo.b3, trafo.c3).Length();
+                    scale.x = aiVector3D(trafo.a1, trafo.b1, trafo.c1).Length();
+                    scale.y = aiVector3D(trafo.a2, trafo.b2, trafo.c2).Length();
+                    scale.z = aiVector3D(trafo.a3, trafo.b3, trafo.c3).Length();
                     nbone->mScalingKeys[c].mTime = time;
                     nbone->mScalingKeys[c].mValue = scale;
 
                     // reconstruct rotation matrix without scaling
                     aiMatrix3x3 rotmat(
-                        trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z,
-                        trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z,
-                        trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z);
+                            trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z,
+                            trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z,
+                            trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z);
 
                     // and convert it into a quaternion
                     nbone->mRotationKeys[c].mTime = time;
-                    nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat);
+                    nbone->mRotationKeys[c].mValue = aiQuaternion(rotmat);
                 }
 
                 // longest lasting key sequence determines duration
-                nanim->mDuration = std::max( nanim->mDuration, bone->mTrafoKeys.back().mTime);
+                nanim->mDuration = std::max(nanim->mDuration, bone->mTrafoKeys.back().mTime);
             } else {
                 // separate key sequences for position, rotation, scaling
                 nbone->mNumPositionKeys = (unsigned int)bone->mPosKeys.size();
                 if (nbone->mNumPositionKeys != 0) {
                     nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys];
-                    for( unsigned int c = 0; c < nbone->mNumPositionKeys; ++c ) {
+                    for (unsigned int c = 0; c < nbone->mNumPositionKeys; ++c) {
                         aiVector3D pos = bone->mPosKeys[c].mValue;
 
                         nbone->mPositionKeys[c].mTime = bone->mPosKeys[c].mTime;
@@ -509,11 +509,11 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
                 nbone->mNumRotationKeys = (unsigned int)bone->mRotKeys.size();
                 if (nbone->mNumRotationKeys != 0) {
                     nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys];
-                    for( unsigned int c = 0; c < nbone->mNumRotationKeys; ++c ) {
+                    for (unsigned int c = 0; c < nbone->mNumRotationKeys; ++c) {
                         aiMatrix3x3 rotmat = bone->mRotKeys[c].mValue.GetMatrix();
 
                         nbone->mRotationKeys[c].mTime = bone->mRotKeys[c].mTime;
-                        nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat);
+                        nbone->mRotationKeys[c].mValue = aiQuaternion(rotmat);
                         nbone->mRotationKeys[c].mValue.w *= -1.0f; // needs quat inversion
                     }
                 }
@@ -522,153 +522,149 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
                 nbone->mNumScalingKeys = (unsigned int)bone->mScaleKeys.size();
                 if (nbone->mNumScalingKeys != 0) {
                     nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys];
-                    for( unsigned int c = 0; c < nbone->mNumScalingKeys; c++)
+                    for (unsigned int c = 0; c < nbone->mNumScalingKeys; c++)
                         nbone->mScalingKeys[c] = bone->mScaleKeys[c];
                 }
 
                 // longest lasting key sequence determines duration
-                if( bone->mPosKeys.size() > 0)
-                    nanim->mDuration = std::max( nanim->mDuration, bone->mPosKeys.back().mTime);
-                if( bone->mRotKeys.size() > 0)
-                    nanim->mDuration = std::max( nanim->mDuration, bone->mRotKeys.back().mTime);
-                if( bone->mScaleKeys.size() > 0)
-                    nanim->mDuration = std::max( nanim->mDuration, bone->mScaleKeys.back().mTime);
+                if (bone->mPosKeys.size() > 0)
+                    nanim->mDuration = std::max(nanim->mDuration, bone->mPosKeys.back().mTime);
+                if (bone->mRotKeys.size() > 0)
+                    nanim->mDuration = std::max(nanim->mDuration, bone->mRotKeys.back().mTime);
+                if (bone->mScaleKeys.size() > 0)
+                    nanim->mDuration = std::max(nanim->mDuration, bone->mScaleKeys.back().mTime);
             }
         }
     }
 
     // store all converted animations in the scene
-    if( newAnims.size() > 0)
-    {
+    if (newAnims.size() > 0) {
         pScene->mNumAnimations = (unsigned int)newAnims.size();
-        pScene->mAnimations = new aiAnimation* [pScene->mNumAnimations];
-        for( unsigned int a = 0; a < newAnims.size(); a++)
+        pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations];
+        for (unsigned int a = 0; a < newAnims.size(); a++)
             pScene->mAnimations[a] = newAnims[a];
     }
 }
 
 // ------------------------------------------------------------------------------------------------
 // Converts all materials in the given array and stores them in the scene's material list.
-void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Material>& pMaterials)
-{
+void XFileImporter::ConvertMaterials(aiScene *pScene, std::vector<XFile::Material> &pMaterials) {
     // count the non-referrer materials in the array
-    unsigned int numNewMaterials( 0 );
-    for ( unsigned int a = 0; a < pMaterials.size(); ++a ) {
-        if ( !pMaterials[ a ].mIsReference ) {
+    unsigned int numNewMaterials(0);
+    for (unsigned int a = 0; a < pMaterials.size(); ++a) {
+        if (!pMaterials[a].mIsReference) {
             ++numNewMaterials;
         }
     }
 
     // resize the scene's material list to offer enough space for the new materials
-    if( numNewMaterials > 0 ) {
-        aiMaterial** prevMats = pScene->mMaterials;
-        pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numNewMaterials];
-        if( nullptr != prevMats)  {
-            ::memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*));
-            delete [] prevMats;
+    if (numNewMaterials > 0) {
+        aiMaterial **prevMats = pScene->mMaterials;
+        pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials + numNewMaterials];
+        if (nullptr != prevMats) {
+            ::memcpy(pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof(aiMaterial *));
+            delete[] prevMats;
         }
     }
 
     // convert all the materials given in the array
-    for( unsigned int a = 0; a < pMaterials.size(); ++a ) {
-        XFile::Material& oldMat = pMaterials[a];
-        if( oldMat.mIsReference) {
+    for (unsigned int a = 0; a < pMaterials.size(); ++a) {
+        XFile::Material &oldMat = pMaterials[a];
+        if (oldMat.mIsReference) {
             // find the material it refers to by name, and store its index
-            for( size_t b = 0; b < pScene->mNumMaterials; ++b ) {
+            for (size_t b = 0; b < pScene->mNumMaterials; ++b) {
                 aiString name;
-                pScene->mMaterials[b]->Get( AI_MATKEY_NAME, name);
-                if( strcmp( name.C_Str(), oldMat.mName.data()) == 0 ) {
+                pScene->mMaterials[b]->Get(AI_MATKEY_NAME, name);
+                if (strcmp(name.C_Str(), oldMat.mName.data()) == 0) {
                     oldMat.sceneIndex = b;
                     break;
                 }
             }
 
-            if( oldMat.sceneIndex == SIZE_MAX ) {
-                ASSIMP_LOG_WARN( "Could not resolve global material reference \"", oldMat.mName, "\"" );
+            if (oldMat.sceneIndex == SIZE_MAX) {
+                ASSIMP_LOG_WARN("Could not resolve global material reference \"", oldMat.mName, "\"");
                 oldMat.sceneIndex = 0;
             }
 
             continue;
         }
 
-        aiMaterial* mat = new aiMaterial;
+        aiMaterial *mat = new aiMaterial;
         aiString name;
-        name.Set( oldMat.mName);
-        mat->AddProperty( &name, AI_MATKEY_NAME);
+        name.Set(oldMat.mName);
+        mat->AddProperty(&name, AI_MATKEY_NAME);
 
         // Shading model: hard-coded to PHONG, there is no such information in an XFile
         // FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix
         // for some models in the SDK (e.g. good old tiny.x)
-        int shadeMode = (int)oldMat.mSpecularExponent == 0.0f
-            ? aiShadingMode_Gouraud : aiShadingMode_Phong;
+        int shadeMode = (int)oldMat.mSpecularExponent == 0.0f ? aiShadingMode_Gouraud : aiShadingMode_Phong;
 
-        mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL);
+        mat->AddProperty<int>(&shadeMode, 1, AI_MATKEY_SHADING_MODEL);
         // material colours
         // Unclear: there's no ambient colour, but emissive. What to put for ambient?
         // Probably nothing at all, let the user select a suitable default.
-        mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
-        mat->AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
-        mat->AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
-        mat->AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
-
+        mat->AddProperty(&oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
+        mat->AddProperty(&oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+        mat->AddProperty(&oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
+        mat->AddProperty(&oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
 
         // texture, if there is one
-        if (1 == oldMat.mTextures.size() ) {
-            const XFile::TexEntry& otex = oldMat.mTextures.back();
+        if (1 == oldMat.mTextures.size()) {
+            const XFile::TexEntry &otex = oldMat.mTextures.back();
             if (otex.mName.length()) {
                 // if there is only one texture assume it contains the diffuse color
-                aiString tex( otex.mName);
-                if ( otex.mIsNormalMap ) {
-                    mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS( 0 ) );
+                aiString tex(otex.mName);
+                if (otex.mIsNormalMap) {
+                    mat->AddProperty(&tex, AI_MATKEY_TEXTURE_NORMALS(0));
                 } else {
-                    mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
+                    mat->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
                 }
             }
         } else {
             // Otherwise ... try to search for typical strings in the
             // texture's file name like 'bump' or 'diffuse'
-            unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0;
-            for( unsigned int b = 0; b < oldMat.mTextures.size(); ++b ) {
-                const XFile::TexEntry& otex = oldMat.mTextures[b];
+            unsigned int iHM = 0, iNM = 0, iDM = 0, iSM = 0, iAM = 0, iEM = 0;
+            for (unsigned int b = 0; b < oldMat.mTextures.size(); ++b) {
+                const XFile::TexEntry &otex = oldMat.mTextures[b];
                 std::string sz = otex.mName;
-                if ( !sz.length() ) {
+                if (!sz.length()) {
                     continue;
                 }
 
                 // find the file name
                 std::string::size_type s = sz.find_last_of("\\/");
-                if ( std::string::npos == s ) {
+                if (std::string::npos == s) {
                     s = 0;
                 }
 
                 // cut off the file extension
                 std::string::size_type sExt = sz.find_last_of('.');
-                if (std::string::npos != sExt){
+                if (std::string::npos != sExt) {
                     sz[sExt] = '\0';
                 }
 
                 // convert to lower case for easier comparison
-                for ( unsigned int c = 0; c < sz.length(); ++c ) {
-                    sz[ c ] = (char) tolower( (unsigned char) sz[ c ] );
+                for (unsigned int c = 0; c < sz.length(); ++c) {
+                    sz[c] = (char)tolower((unsigned char)sz[c]);
                 }
 
                 // Place texture filename property under the corresponding name
-                aiString tex( oldMat.mTextures[b].mName);
+                aiString tex(oldMat.mTextures[b].mName);
 
                 // bump map
                 if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s)) {
-                    mat->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++));
-                } else if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s)) {
-                    mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(iNM++));
-                } else if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s)) {
-                    mat->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++));
-                } else if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s)) {
-                    mat->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++));
-                } else if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s)) {
-                    mat->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++));
+                    mat->AddProperty(&tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++));
+                } else if (otex.mIsNormalMap || std::string::npos != sz.find("normal", s) || std::string::npos != sz.find("nm", s)) {
+                    mat->AddProperty(&tex, AI_MATKEY_TEXTURE_NORMALS(iNM++));
+                } else if (std::string::npos != sz.find("spec", s) || std::string::npos != sz.find("glanz", s)) {
+                    mat->AddProperty(&tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++));
+                } else if (std::string::npos != sz.find("ambi", s) || std::string::npos != sz.find("env", s)) {
+                    mat->AddProperty(&tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++));
+                } else if (std::string::npos != sz.find("emissive", s) || std::string::npos != sz.find("self", s)) {
+                    mat->AddProperty(&tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++));
                 } else {
                     // Assume it is a diffuse texture
-                    mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++));
+                    mat->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++));
                 }
             }
         }
@@ -679,4 +675,6 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Materi
     }
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_X_IMPORTER

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

@@ -68,7 +68,7 @@ namespace XFile {
  */
 class XFileImporter : public BaseImporter {
 public:
-    XFileImporter();
+    XFileImporter() = default;
     ~XFileImporter() override = default;
 
     // -------------------------------------------------------------------

+ 114 - 102
code/AssetLib/XGL/XGLLoader.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2023, assimp team
 
 All rights reserved.
 
@@ -56,64 +56,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <memory>
 #include <utility>
-//#include <cctype>
-//#include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 
-namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp
+static constexpr uint32_t ErrorId = ~0u;
 
 template <>
 const char *LogFunctions<XGLImporter>::Prefix() {
 	return "XGL: ";
 }
 
-} // namespace Assimp
-
-static const aiImporterDesc desc = {
-	"XGL Importer",
-	"",
-	"",
-	"",
-	aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour,
-	0,
-	0,
-	0,
-	0,
-	"xgl zgl"
-};
+static constexpr aiImporterDesc desc = {
+	"XGL Importer", "", "",  "",
+    aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour,
+	0,	0,	0,	0,	"xgl zgl"};
 
 // ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-XGLImporter::XGLImporter() :
-        mXmlParser(nullptr),
-        m_scene(nullptr) {
+XGLImporter::XGLImporter() : mXmlParser(nullptr), m_scene(nullptr) {
     // empty
 }
 
 // ------------------------------------------------------------------------------------------------
-// Destructor, private as well
 XGLImporter::~XGLImporter() {
-	delete mXmlParser;
+    clear();
 }
 
 // ------------------------------------------------------------------------------------------------
-// Returns whether the class can handle the format of the given file.
 bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
 	static const char *tokens[] = { "<world>", "<World>", "<WORLD>" };
 	return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
 }
 
 // ------------------------------------------------------------------------------------------------
-// Get a list of all file extensions which are handled by this class
 const aiImporterDesc *XGLImporter::GetInfo() const {
 	return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
-// Imports the given file into the given scene structure.
 void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
- #ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
+    clear();
+#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
 	std::vector<char> uncompressed;
 #endif
 
@@ -159,7 +141,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 
 	std::vector<aiMesh *> &meshes = scope.meshes_linear;
 	std::vector<aiMaterial *> &materials = scope.materials_linear;
-	if (!meshes.size() || !materials.size()) {
+	if (meshes.empty() || materials.empty()) {
 		ThrowException("failed to extract data from XGL file, no meshes loaded");
 	}
 
@@ -184,6 +166,13 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 	scope.dismiss();
 }
 
+// ------------------------------------------------------------------------------------------------
+void XGLImporter::clear() {
+    delete mXmlParser;
+    mXmlParser = nullptr;
+}
+
+
 // ------------------------------------------------------------------------------------------------
 void XGLImporter::ReadWorld(XmlNode &node, TempScope &scope) {
     for (XmlNode &currentNode : node.children()) {
@@ -199,9 +188,10 @@ void XGLImporter::ReadWorld(XmlNode &node, TempScope &scope) {
 	}
 
 	aiNode *const nd = ReadObject(node, scope);
-	if (!nd) {
+	if (nd == nullptr) {
 		ThrowException("failure reading <world>");
 	}
+
 	if (nd->mName.length == 0) {
 		nd->mName.Set("WORLD");
 	}
@@ -254,15 +244,17 @@ aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope) {
 			const std::string &s = ai_stdStrToLower(child.name());
 			if (s == "mesh") {
 				const size_t prev = scope.meshes_linear.size();
-                bool empty;
-				if (ReadMesh(child, scope, empty)) {
+				if (ReadMesh(child, scope)) {
 					const size_t newc = scope.meshes_linear.size();
 					for (size_t i = 0; i < newc - prev; ++i) {
 						meshes.push_back(static_cast<unsigned int>(i + prev));
 					}
-				}
+				} 
 			} else if (s == "mat") {
-				ReadMaterial(child, scope);
+				const uint32_t matId = ReadMaterial(child, scope);
+                if (matId == ErrorId) {
+                    ThrowException("Invalid material id detected.");
+                }
 			} else if (s == "object") {
 				children.push_back(ReadObject(child, scope));
 			} else if (s == "objectref") {
@@ -438,18 +430,25 @@ aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) {
     return mesh.release();
 }
 
+
 // ------------------------------------------------------------------------------------------------
-bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) {
-	TempMesh t;
+inline static unsigned int generateMeshId(unsigned int meshId, bool nor, bool uv) {
+    unsigned int currentMeshId = meshId | ((nor ? 1 : 0) << 31) | ((uv ? 1 : 0) << 30);
+    return currentMeshId;
+}
 
+// ------------------------------------------------------------------------------------------------
+bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
+	TempMesh t;
+    uint32_t matId = 99999;
+    bool mesh_created = false;
 	std::map<unsigned int, TempMaterialMesh> bymat;
     const unsigned int mesh_id = ReadIDAttr(node);
-    bool empty_mesh = true;
 	for (XmlNode &child : node.children()) {
         const std::string &s = ai_stdStrToLower(child.name());
 
 		if (s == "mat") {
-			ReadMaterial(child, scope);
+			matId = ReadMaterial(child, scope);
 		} else if (s == "p") {
 			pugi::xml_attribute attr = child.attribute("ID");
 			if (attr.empty()) {
@@ -477,66 +476,41 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) {
 		} else if (s == "f" || s == "l" || s == "p") {
 			const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1);
 
-			unsigned int mid = ~0u;
-			TempFace tf[3];
+			unsigned int meshId = ErrorId;
+            TempFace tempFace[3] = {};
 			bool has[3] = { false };
-			for (XmlNode &sub_child : child.children()) {
-                const std::string &scn = ai_stdStrToLower(sub_child.name());
-                if (scn == "fv1" || scn == "lv1" || scn == "pv1") {
-					ReadFaceVertex(sub_child, t, tf[0]);
-					has[0] = true;
-                } else if (scn == "fv2" || scn == "lv2") {
-					ReadFaceVertex(sub_child, t, tf[1]);
-					has[1] = true;
-                } else if (scn == "fv3") {
-					ReadFaceVertex(sub_child, t, tf[2]);
-					has[2] = true;
-                } else if (scn == "mat") {
-					if (mid != ~0u) {
-						LogWarn("only one material tag allowed per <f>");
-					}
-					mid = ResolveMaterialRef(sub_child, scope);
-                } else if (scn == "matref") {
-					if (mid != ~0u) {
-						LogWarn("only one material tag allowed per <f>");
-					}
-					mid = ResolveMaterialRef(sub_child, scope);
-				}
-			}
-            if (has[0] || has[1] || has[2]) {
-                empty_mesh = false;
-            }
-
-			if (mid == ~0u) {
+            meshId = ReadVertices(child, t, tempFace, has, meshId, scope);
+            if (meshId == ErrorId) {
 				ThrowException("missing material index");
 			}
 
-			bool nor = false;
-			bool uv = false;
+			bool nor = false, uv = false;
 			for (unsigned int i = 0; i < vcount; ++i) {
 				if (!has[i]) {
 					ThrowException("missing face vertex data");
 				}
 
-				nor = nor || tf[i].has_normal;
-				uv = uv || tf[i].has_uv;
+				nor = nor || tempFace[i].has_normal;
+				uv = uv || tempFace[i].has_uv;
 			}
 
-			if (mid >= (1 << 30)) {
+			if (meshId >= (1 << 30)) {
 				LogWarn("material indices exhausted, this may cause errors in the output");
 			}
-			unsigned int meshId = mid | ((nor ? 1 : 0) << 31) | ((uv ? 1 : 0) << 30);
+            const unsigned int currentMeshId = generateMeshId(meshId, nor, uv);
 
-			TempMaterialMesh &mesh = bymat[meshId];
-			mesh.matid = mid;
+            // Generate the temp mesh
+			TempMaterialMesh &mesh = bymat[currentMeshId];
+            mesh.matid = meshId;
+            mesh_created = true;
 
 			for (unsigned int i = 0; i < vcount; ++i) {
-				mesh.positions.push_back(tf[i].pos);
+				mesh.positions.push_back(tempFace[i].pos);
 				if (nor) {
-					mesh.normals.push_back(tf[i].normal);
+					mesh.normals.push_back(tempFace[i].normal);
 				}
 				if (uv) {
-					mesh.uvs.push_back(tf[i].uv);
+					mesh.uvs.push_back(tempFace[i].uv);
 				}
 
 				mesh.pflags |= 1 << (vcount - 1);
@@ -546,25 +520,59 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) {
 		}
 	}
 
-	// finally extract output meshes and add them to the scope
-	using pairt = std::pair<const unsigned int, TempMaterialMesh>;
-	for (const pairt &p : bymat) {
-		aiMesh *const m = ToOutputMesh(p.second);
-		scope.meshes_linear.push_back(m);
-
-		// if this is a definition, keep it on the stack
-		if (mesh_id != ~0u) {
-			scope.meshes.insert(std::pair<unsigned int, aiMesh *>(mesh_id, m));
-		}
-	}
-    if (empty_mesh) {
-        LogWarn("Mesh is empty, skipping.");
-        empty = empty_mesh;
-        return false;
+    if (!mesh_created) {
+        TempMaterialMesh &mesh = bymat[mesh_id];
+        mesh.matid = matId;
     }
 
+	// finally extract output meshes and add them to the scope
+    AppendOutputMeshes(bymat, scope, mesh_id);
+
 	// no id == not a reference, insert this mesh right *here*
-	return mesh_id == ~0u;
+    return mesh_id == ErrorId;
+}
+
+// ----------------------------------------------------------------------------------------------
+void XGLImporter::AppendOutputMeshes(std::map<unsigned int, TempMaterialMesh> bymat, TempScope &scope,
+        const unsigned int mesh_id) {
+    using pairt = std::pair<const unsigned int, TempMaterialMesh>;
+    for (const pairt &p : bymat) {
+        aiMesh *const m = ToOutputMesh(p.second);
+        scope.meshes_linear.push_back(m);
+
+        // if this is a definition, keep it on the stack
+        if (mesh_id != ErrorId) {
+            scope.meshes.insert(std::pair<unsigned int, aiMesh *>(mesh_id, m));
+        }
+    }
+}
+
+// ----------------------------------------------------------------------------------------------
+unsigned int XGLImporter::ReadVertices(XmlNode &child, TempMesh t, TempFace *tf, bool *has, unsigned int mid, TempScope &scope) {
+    for (XmlNode &sub_child : child.children()) {
+        const std::string &scn = ai_stdStrToLower(sub_child.name());
+        if (scn == "fv1" || scn == "lv1" || scn == "pv1") {
+            ReadFaceVertex(sub_child, t, tf[0]);
+            has[0] = true;
+        } else if (scn == "fv2" || scn == "lv2") {
+            ReadFaceVertex(sub_child, t, tf[1]);
+            has[1] = true;
+        } else if (scn == "fv3") {
+            ReadFaceVertex(sub_child, t, tf[2]);
+            has[2] = true;
+        } else if (scn == "mat") {
+            if (mid != ErrorId) {
+                LogWarn("only one material tag allowed per <f>");
+            }
+            mid = ResolveMaterialRef(sub_child, scope);
+        } else if (scn == "matref") {
+            if (mid != ErrorId) {
+                LogWarn("only one material tag allowed per <f>");
+            }
+            mid = ResolveMaterialRef(sub_child, scope);
+        }
+    }
+    return mid;
 }
 
 // ----------------------------------------------------------------------------------------------
@@ -598,10 +606,10 @@ unsigned int XGLImporter::ResolveMaterialRef(XmlNode &node, TempScope &scope) {
 }
 
 // ------------------------------------------------------------------------------------------------
-void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) {
+unsigned int XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) {
     const unsigned int mat_id = ReadIDAttr(node);
 
-	auto *mat(new aiMaterial);
+	auto *mat = new aiMaterial;
 	for (XmlNode &child : node.children()) {
         const std::string &s = ai_stdStrToLower(child.name());
 		if (s == "amb") {
@@ -627,6 +635,8 @@ void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) {
 
 	scope.materials[mat_id] = mat;
 	scope.materials_linear.push_back(mat);
+
+    return mat_id;
 }
 
 // ----------------------------------------------------------------------------------------------
@@ -683,7 +693,7 @@ unsigned int XGLImporter::ReadIDAttr(XmlNode &node) {
 		}
 	}
 
-	return ~0u;
+	return ErrorId;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -712,14 +722,14 @@ unsigned int XGLImporter::ReadIndexFromText(XmlNode &node) {
     const char *s = v.c_str();
 	if (!SkipSpaces(&s)) {
 		LogError("unexpected EOL, failed to parse index element");
-		return ~0u;
+        return ErrorId;
 	}
-	const char *se;
+	const char *se = nullptr;
 	const unsigned int t = strtoul10(s, &se);
 
 	if (se == s) {
 		LogError("failed to read index");
-		return ~0u;
+        return ErrorId;
 	}
 
 	return t;
@@ -786,4 +796,6 @@ aiColor3D XGLImporter::ReadCol3(XmlNode &node) {
 	return aiColor3D(v.x, v.y, v.z);
 }
 
+} // namespace Assimp
+
 #endif // ASSIMP_BUILD_NO_XGL_IMPORTER

+ 14 - 18
code/AssetLib/XGL/XGLLoader.h

@@ -69,16 +69,20 @@ namespace Assimp {
  */
 class XGLImporter : public BaseImporter, public LogFunctions<XGLImporter> {
 public:
+    /// @brief  The class constructor.
     XGLImporter();
+
+    /// @brief The class destructor.
     ~XGLImporter() override;
 
-    // -------------------------------------------------------------------
-    /** Returns whether the class can handle the format of the given file.
-     *  See BaseImporter::CanRead() for details.    */
+    /// @brief Returns whether the class can handle the format of the given file.
+    /// @see BaseImporter::CanRead() for details.    */
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
             bool checkSig) const override;
 
 protected:
+    void clear();
+
     // -------------------------------------------------------------------
     /** Return importer meta information.
      * See #BaseImporter::GetInfo for the details  */
@@ -92,10 +96,7 @@ protected:
 
 private:
     struct TempScope {
-        TempScope() :
-                light() {
-            // empty
-        }
+        TempScope() : light() {}
 
         ~TempScope() {
             for (aiMesh *m : meshes_linear) {
@@ -145,9 +146,7 @@ private:
     };
 
     struct TempMaterialMesh {
-        TempMaterialMesh() :
-                pflags(),
-                matid() {
+        TempMaterialMesh() : pflags(), matid() {
             // empty
         }
 
@@ -160,9 +159,7 @@ private:
     };
 
     struct TempFace {
-        TempFace() :
-                has_uv(),
-                has_normal() {
+        TempFace() : has_uv(), has_normal() {
             // empty
         }
 
@@ -175,26 +172,25 @@ private:
 
 private:
     void Cleanup();
-
     std::string GetElementName();
     bool ReadElement();
     bool ReadElementUpToClosing(const char *closetag);
     bool SkipToText();
     unsigned int ReadIDAttr(XmlNode &node);
-
     void ReadWorld(XmlNode &node, TempScope &scope);
     void ReadLighting(XmlNode &node, TempScope &scope);
     aiLight *ReadDirectionalLight(XmlNode &node);
     aiNode *ReadObject(XmlNode &node, TempScope &scope);
-    bool ReadMesh(XmlNode &node, TempScope &scope, bool &empty);
-    void ReadMaterial(XmlNode &node, TempScope &scope);
+    bool ReadMesh(XmlNode &node, TempScope &scope);
+    void AppendOutputMeshes(std::map<unsigned int, TempMaterialMesh> bymat, TempScope &scope, const unsigned int mesh_id);
+    unsigned int ReadVertices(XmlNode &child, TempMesh t, TempFace *tf, bool *has, unsigned int mid, TempScope &scope);
+    unsigned int ReadMaterial(XmlNode &node, TempScope &scope);
     aiVector2D ReadVec2(XmlNode &node);
     aiVector3D ReadVec3(XmlNode &node);
     aiColor3D ReadCol3(XmlNode &node);
     aiMatrix4x4 ReadTrafo(XmlNode &node);
     unsigned int ReadIndexFromText(XmlNode &node);
     float ReadFloat(XmlNode &node);
-
     aiMesh *ToOutputMesh(const TempMaterialMesh &m);
     void ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out);
     unsigned int ResolveMaterialRef(XmlNode &node, TempScope &scope);

+ 1 - 5
code/AssetLib/glTF/glTFImporter.cpp

@@ -62,11 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 using namespace glTF;
 
-//
-// glTFImporter
-//
-
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "glTF Importer",
     "",
     "",

+ 102 - 71
code/AssetLib/glTF2/glTF2Exporter.cpp

@@ -172,22 +172,6 @@ static void IdentityMatrix4(mat4 &o) {
     o[15] = 1;
 }
 
-static bool IsBoneWeightFitted(vec4 &weight) {
-    return weight[0] + weight[1] + weight[2] + weight[3] >= 1.f;
-}
-
-static int FitBoneWeight(vec4 &weight, float value) {
-    int i = 0;
-    for (; i < 4; ++i) {
-        if (weight[i] < value) {
-            weight[i] = value;
-            return i;
-        }
-    }
-
-    return -1;
-}
-
 template <typename T>
 void SetAccessorRange(Ref<Accessor> acc, void *data, size_t count,
         unsigned int numCompsIn, unsigned int numCompsOut) {
@@ -575,7 +559,11 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsi
     aiString tex;
 
     // Read texcoord (UV map index)
-    mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord);
+    // Note: must be an int to be successful.
+    int tmp = 0;
+    const auto ok = mat.Get(AI_MATKEY_UVWSRC(tt, slot), tmp);
+    if (ok == aiReturn_SUCCESS) texCoord = tmp;
+
 
     if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
         std::string path = tex.C_Str();
@@ -1009,23 +997,29 @@ Ref<Node> FindSkeletonRootJoint(Ref<Skin> &skinRef) {
     return parentNodeRef;
 }
 
+struct boneIndexWeightPair {
+    unsigned int indexJoint;
+    float weight;
+    bool operator()(boneIndexWeightPair &a, boneIndexWeightPair &b) {
+        return a.weight > b.weight;
+    }
+};
+
 void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buffer> &bufferRef, Ref<Skin> &skinRef,
-        std::vector<aiMatrix4x4> &inverseBindMatricesData) {
+        std::vector<aiMatrix4x4> &inverseBindMatricesData, bool unlimitedBonesPerVertex) {
     if (aimesh->mNumBones < 1) {
         return;
     }
 
     // Store the vertex joint and weight data.
     const size_t NumVerts(aimesh->mNumVertices);
-    vec4 *vertexJointData = new vec4[NumVerts];
-    vec4 *vertexWeightData = new vec4[NumVerts];
     int *jointsPerVertex = new int[NumVerts];
+    std::vector<std::vector<boneIndexWeightPair>> allVerticesPairs;
+    int maxJointsPerVertex = 0;
     for (size_t i = 0; i < NumVerts; ++i) {
         jointsPerVertex[i] = 0;
-        for (size_t j = 0; j < 4; ++j) {
-            vertexJointData[i][j] = 0;
-            vertexWeightData[i][j] = 0;
-        }
+        std::vector<boneIndexWeightPair> vertexPair;
+        allVerticesPairs.push_back(vertexPair);
     }
 
     for (unsigned int idx_bone = 0; idx_bone < aimesh->mNumBones; ++idx_bone) {
@@ -1055,61 +1049,88 @@ void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buf
             jointNamesIndex = static_cast<unsigned int>(inverseBindMatricesData.size() - 1);
         }
 
-        // aib->mWeights   =====>  vertexWeightData
-        for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights; ++idx_weights) {
+        // aib->mWeights   =====>  temp pairs data
+        for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights;
+              ++idx_weights) {
             unsigned int vertexId = aib->mWeights[idx_weights].mVertexId;
             float vertWeight = aib->mWeights[idx_weights].mWeight;
+            allVerticesPairs[vertexId].push_back({jointNamesIndex, vertWeight});
+            jointsPerVertex[vertexId] += 1;
+            maxJointsPerVertex =
+                    std::max(maxJointsPerVertex, jointsPerVertex[vertexId]);
+        }
+    } // End: for-loop mNumMeshes
 
-            // A vertex can only have at most four joint weights, which ideally sum up to 1
-            if (IsBoneWeightFitted(vertexWeightData[vertexId])) {
-                continue;
-            }
-            if (jointsPerVertex[vertexId] > 3) {
-                int boneIndexFitted = FitBoneWeight(vertexWeightData[vertexId], vertWeight);
-                if (boneIndexFitted != -1) {
-                    vertexJointData[vertexId][boneIndexFitted] = static_cast<float>(jointNamesIndex);
-                }
-            } else {
-                vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast<float>(jointNamesIndex);
-                vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight;
+    if (!unlimitedBonesPerVertex){
+        // skinning limited only for 4 bones per vertex, default
+        maxJointsPerVertex = 4;
+    }
 
-                jointsPerVertex[vertexId] += 1;
+    // temp pairs data  =====>  vertexWeightData
+    size_t numGroups = (maxJointsPerVertex - 1) / 4 + 1;
+    vec4 *vertexJointData = new vec4[NumVerts * numGroups];
+    vec4 *vertexWeightData = new vec4[NumVerts * numGroups];
+    for (size_t indexVertex = 0; indexVertex < NumVerts; ++indexVertex) {
+        // order pairs by weight for each vertex
+        std::sort(allVerticesPairs[indexVertex].begin(),
+                allVerticesPairs[indexVertex].end(),
+                boneIndexWeightPair());
+        for (size_t indexGroup = 0; indexGroup < numGroups; ++indexGroup) {
+            for (size_t indexJoint = 0; indexJoint < 4; ++indexJoint) {
+                size_t indexBone = indexGroup * 4 + indexJoint;
+                size_t indexData = indexVertex + NumVerts * indexGroup;
+                if (indexBone >= allVerticesPairs[indexVertex].size()) {
+                    vertexJointData[indexData][indexJoint] = 0.f;
+                    vertexWeightData[indexData][indexJoint] = 0.f;
+                } else {
+                    vertexJointData[indexData][indexJoint] =
+                    static_cast<float>(
+                            allVerticesPairs[indexVertex][indexBone].indexJoint);
+                    vertexWeightData[indexData][indexJoint] =
+                            allVerticesPairs[indexVertex][indexBone].weight;
+                }
             }
         }
+    }
 
-    } // End: for-loop mNumMeshes
+    for (size_t idx_group = 0; idx_group < numGroups; ++idx_group) {
+        Mesh::Primitive &p = meshRef->primitives.back();
+        Ref<Accessor> vertexJointAccessor = ExportData(
+            mAsset, skinRef->id, bufferRef, aimesh->mNumVertices,
+            vertexJointData + idx_group * NumVerts,
+            AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+        if (vertexJointAccessor) {
+            size_t offset = vertexJointAccessor->bufferView->byteOffset;
+            size_t bytesLen = vertexJointAccessor->bufferView->byteLength;
+            unsigned int s_bytesPerComp =
+                ComponentTypeSize(ComponentType_UNSIGNED_SHORT);
+            unsigned int bytesPerComp =
+                ComponentTypeSize(vertexJointAccessor->componentType);
+            size_t s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp;
+            Ref<Buffer> buf = vertexJointAccessor->bufferView->buffer;
+            uint8_t *arrys = new uint8_t[bytesLen];
+            unsigned int i = 0;
+            for (unsigned int j = 0; j < bytesLen; j += bytesPerComp) {
+                size_t len_p = offset + j;
+                float f_value = *(float *)&buf->GetPointer()[len_p];
+                unsigned short c = static_cast<unsigned short>(f_value);
+                memcpy(&arrys[i * s_bytesPerComp], &c, s_bytesPerComp);
+                ++i;
+            }
+            buf->ReplaceData_joint(offset, bytesLen, arrys, bytesLen);
+            vertexJointAccessor->componentType = ComponentType_UNSIGNED_SHORT;
+            vertexJointAccessor->bufferView->byteLength = s_bytesLen;
 
-    Mesh::Primitive &p = meshRef->primitives.back();
-    Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices,
-            vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
-    if (vertexJointAccessor) {
-        size_t offset = vertexJointAccessor->bufferView->byteOffset;
-        size_t bytesLen = vertexJointAccessor->bufferView->byteLength;
-        unsigned int s_bytesPerComp = ComponentTypeSize(ComponentType_UNSIGNED_SHORT);
-        unsigned int bytesPerComp = ComponentTypeSize(vertexJointAccessor->componentType);
-        size_t s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp;
-        Ref<Buffer> buf = vertexJointAccessor->bufferView->buffer;
-        uint8_t *arrys = new uint8_t[bytesLen];
-        unsigned int i = 0;
-        for (unsigned int j = 0; j < bytesLen; j += bytesPerComp) {
-            size_t len_p = offset + j;
-            float f_value = *(float *)&buf->GetPointer()[len_p];
-            unsigned short c = static_cast<unsigned short>(f_value);
-            memcpy(&arrys[i * s_bytesPerComp], &c, s_bytesPerComp);
-            ++i;
+            p.attributes.joint.push_back(vertexJointAccessor);
+            delete[] arrys;
+        }
+        Ref<Accessor> vertexWeightAccessor = ExportData(
+            mAsset, skinRef->id, bufferRef, aimesh->mNumVertices,
+            vertexWeightData + idx_group * NumVerts,
+            AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
+        if (vertexWeightAccessor) {
+            p.attributes.weight.push_back(vertexWeightAccessor);
         }
-        buf->ReplaceData_joint(offset, bytesLen, arrys, bytesLen);
-        vertexJointAccessor->componentType = ComponentType_UNSIGNED_SHORT;
-        vertexJointAccessor->bufferView->byteLength = s_bytesLen;
-
-        p.attributes.joint.push_back(vertexJointAccessor);
-        delete[] arrys;
-    }
-
-    Ref<Accessor> vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices,
-            vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
-    if (vertexWeightAccessor) {
-        p.attributes.weight.push_back(vertexWeightAccessor);
     }
     delete[] jointsPerVertex;
     delete[] vertexWeightData;
@@ -1247,9 +1268,19 @@ void glTF2Exporter::ExportMeshes() {
             break;
         }
 
+//        /*************** Skins ****************/
+//        if (aim->HasBones()) {
+//            ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData);
+//        }
         /*************** Skins ****************/
         if (aim->HasBones()) {
-            ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData);
+            bool unlimitedBonesPerVertex =
+                this->mProperties->HasPropertyBool(
+                        AI_CONFIG_EXPORT_GLTF_UNLIMITED_SKINNING_BONES_PER_VERTEX) &&
+                this->mProperties->GetPropertyBool(
+                        AI_CONFIG_EXPORT_GLTF_UNLIMITED_SKINNING_BONES_PER_VERTEX);
+            ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData,
+                    unlimitedBonesPerVertex);
         }
 
         /*************** Targets for blendshapes ****************/

+ 1 - 1
code/AssetLib/glTF2/glTF2Importer.cpp

@@ -82,7 +82,7 @@ struct Tangent {
 // glTF2Importer
 //
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "glTF2 Importer",
     "",
     "",

+ 7 - 2
code/CMakeLists.txt

@@ -923,7 +923,7 @@ IF(ASSIMP_HUNTER_ENABLED)
   hunter_add_package(utf8)
   find_package(utf8cpp CONFIG REQUIRED)
 ELSE()
-  # utf8 is header-only, so Assimp doesn't need to do anything.
+  INCLUDE_DIRECTORIES("../contrib/utf8cpp/source")
 ENDIF()
 
 # polyclipping
@@ -1380,7 +1380,12 @@ ENDIF()
 IF(NOT ASSIMP_HUNTER_ENABLED)
   if (UNZIP_FOUND)
     INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS})
-    TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
+    # TODO if cmake required version has been updated to >3.12.0, collapse this to the second case only
+    if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
+      TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
+    else()
+      TARGET_LINK_LIBRARIES(assimp ${UNZIP_LINK_LIBRARIES})
+    endif()
   else ()
     INCLUDE_DIRECTORIES("../")
   endif ()

+ 5 - 1
code/Common/Compression.cpp

@@ -66,6 +66,10 @@ Compression::Compression() :
 Compression::~Compression() {
     ai_assert(mImpl != nullptr);
 
+    if (mImpl->mOpen) {
+        close();
+    }
+
     delete mImpl;
 }
 
@@ -124,7 +128,7 @@ static int getFlushMode(Compression::FlushMode flush) {
     return z_flush;
 }
 
-constexpr size_t MYBLOCK = 32786;
+static constexpr size_t MYBLOCK = 32786;
 
 size_t Compression::decompress(const void *data, size_t in, std::vector<char> &uncompressed) {
     ai_assert(mImpl != nullptr);

+ 111 - 102
code/PostProcessing/ImproveCacheLocality.cpp

@@ -3,9 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
-
-
+Copyright (c) 2006-2023, assimp team
 
 All rights reserved.
 
@@ -59,31 +57,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <stdio.h>
 #include <stack>
 
-using namespace Assimp;
+namespace Assimp {
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
-ImproveCacheLocalityProcess::ImproveCacheLocalityProcess()
-: mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) {
+ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() :
+        mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) {
     // empty
 }
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the processing step is present in the given flag field.
-bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const {
+bool ImproveCacheLocalityProcess::IsActive(unsigned int pFlags) const {
     return (pFlags & aiProcess_ImproveCacheLocality) != 0;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Setup configuration
-void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp) {
+void ImproveCacheLocalityProcess::SetupProperties(const Importer *pImp) {
     // AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer
-    mConfigCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE,PP_ICL_PTCACHE_SIZE);
+    mConfigCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE, PP_ICL_PTCACHE_SIZE);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
-void ImproveCacheLocalityProcess::Execute( aiScene* pScene) {
+void ImproveCacheLocalityProcess::Execute(aiScene *pScene) {
     if (!pScene->mNumMeshes) {
         ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess skipped; there are no meshes");
         return;
@@ -93,11 +91,11 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene) {
 
     float out = 0.f;
     unsigned int numf = 0, numm = 0;
-    for( unsigned int a = 0; a < pScene->mNumMeshes; ++a ){
-        const float res = ProcessMesh( pScene->mMeshes[a],a);
+    for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
+        const float res = ProcessMesh(pScene->mMeshes[a], a);
         if (res) {
             numf += pScene->mMeshes[a]->mNumFaces;
-            out  += res;
+            out += res;
             ++numm;
         }
     }
@@ -109,9 +107,54 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene) {
     }
 }
 
+// ------------------------------------------------------------------------------------------------
+static ai_real calculateInputACMR(aiMesh *pMesh, const aiFace *const pcEnd,
+        unsigned int configCacheDepth, unsigned int meshNum) {
+    ai_real fACMR = 0.0f;
+    unsigned int *piFIFOStack = new unsigned int[configCacheDepth];
+    memset(piFIFOStack, 0xff, configCacheDepth * sizeof(unsigned int));
+    unsigned int *piCur = piFIFOStack;
+    const unsigned int *const piCurEnd = piFIFOStack + configCacheDepth;
+
+    // count the number of cache misses
+    unsigned int iCacheMisses = 0;
+    for (const aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) {
+        for (unsigned int qq = 0; qq < 3; ++qq) {
+            bool bInCache = false;
+            for (unsigned int *pp = piFIFOStack; pp < piCurEnd; ++pp) {
+                if (*pp == pcFace->mIndices[qq]) {
+                    // the vertex is in cache
+                    bInCache = true;
+                    break;
+                }
+            }
+            if (!bInCache) {
+                ++iCacheMisses;
+                if (piCurEnd == piCur) {
+                    piCur = piFIFOStack;
+                }
+                *piCur++ = pcFace->mIndices[qq];
+            }
+        }
+    }
+    delete[] piFIFOStack;
+    fACMR = (ai_real)iCacheMisses / pMesh->mNumFaces;
+    if (3.0 == fACMR) {
+        char szBuff[128]; // should be sufficiently large in every case
+
+        // the JoinIdenticalVertices process has not been executed on this
+        // mesh, otherwise this value would normally be at least minimally
+        // smaller than 3.0 ...
+        ai_snprintf(szBuff, 128, "Mesh %u: Not suitable for vcache optimization", meshNum);
+        ASSIMP_LOG_WARN(szBuff);
+        return static_cast<ai_real>(0.f);
+    }
+    return fACMR;
+}
+
 // ------------------------------------------------------------------------------------------------
 // Improves the cache coherency of a specific mesh
-ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshNum) {
+ai_real ImproveCacheLocalityProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshNum) {
     // TODO: rewrite this to use std::vector or boost::shared_array
     ai_assert(nullptr != pMesh);
 
@@ -126,91 +169,57 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
         return static_cast<ai_real>(0.f);
     }
 
-    if(pMesh->mNumVertices <= mConfigCacheDepth) {
+    if (pMesh->mNumVertices <= mConfigCacheDepth) {
         return static_cast<ai_real>(0.f);
     }
 
     ai_real fACMR = 3.f;
-    const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces;
+    const aiFace *const pcEnd = pMesh->mFaces + pMesh->mNumFaces;
 
     // Input ACMR is for logging purposes only
-    if (!DefaultLogger::isNullLogger())     {
-
-        unsigned int* piFIFOStack = new unsigned int[mConfigCacheDepth];
-        memset(piFIFOStack,0xff,mConfigCacheDepth*sizeof(unsigned int));
-        unsigned int* piCur = piFIFOStack;
-        const unsigned int* const piCurEnd = piFIFOStack + mConfigCacheDepth;
-
-        // count the number of cache misses
-        unsigned int iCacheMisses = 0;
-        for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace) {
-            for (unsigned int qq = 0; qq < 3;++qq) {
-                bool bInCache = false;
-                for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp) {
-                    if (*pp == pcFace->mIndices[qq])    {
-                        // the vertex is in cache
-                        bInCache = true;
-                        break;
-                    }
-                }
-                if (!bInCache)  {
-                    ++iCacheMisses;
-                    if (piCurEnd == piCur) {
-                        piCur = piFIFOStack;
-                    }
-                    *piCur++ = pcFace->mIndices[qq];
-                }
-            }
-        }
-        delete[] piFIFOStack;
-        fACMR = (ai_real) iCacheMisses / pMesh->mNumFaces;
-        if (3.0 == fACMR)   {
-            char szBuff[128]; // should be sufficiently large in every case
-
-            // the JoinIdenticalVertices process has not been executed on this
-            // mesh, otherwise this value would normally be at least minimally
-            // smaller than 3.0 ...
-            ai_snprintf(szBuff,128,"Mesh %u: Not suitable for vcache optimization",meshNum);
-            ASSIMP_LOG_WARN(szBuff);
-            return static_cast<ai_real>(0.f);
-        }
+    if (!DefaultLogger::isNullLogger()) {
+        fACMR = calculateInputACMR(pMesh, pcEnd, mConfigCacheDepth, meshNum);
     }
 
     // first we need to build a vertex-triangle adjacency list
-    VertexTriangleAdjacency adj(pMesh->mFaces,pMesh->mNumFaces, pMesh->mNumVertices,true);
+    VertexTriangleAdjacency adj(pMesh->mFaces, pMesh->mNumFaces, pMesh->mNumVertices, true);
 
     // build a list to store per-vertex caching time stamps
-    unsigned int* const piCachingStamps = new unsigned int[pMesh->mNumVertices];
-    memset(piCachingStamps,0x0,pMesh->mNumVertices*sizeof(unsigned int));
+    std::vector<unsigned int> piCachingStamps;
+    piCachingStamps.resize(pMesh->mNumVertices);
+    memset(&piCachingStamps[0], 0x0, pMesh->mNumVertices * sizeof(unsigned int));
 
     // allocate an empty output index buffer. We store the output indices in one large array.
     // Since the number of triangles won't change the input faces can be reused. This is how
     // we save thousands of redundant mini allocations for aiFace::mIndices
-    const unsigned int iIdxCnt = pMesh->mNumFaces*3;
-    unsigned int* const piIBOutput = new unsigned int[iIdxCnt];
-    unsigned int* piCSIter = piIBOutput;
+    const unsigned int iIdxCnt = pMesh->mNumFaces * 3;
+    std::vector<unsigned int> piIBOutput;
+    piIBOutput.resize(iIdxCnt);
+    std::vector<unsigned int>::iterator piCSIter = piIBOutput.begin();
 
     // allocate the flag array to hold the information
     // whether a face has already been emitted or not
-    std::vector<bool> abEmitted(pMesh->mNumFaces,false);
+    std::vector<bool> abEmitted(pMesh->mNumFaces, false);
 
     // dead-end vertex index stack
-    std::stack<unsigned int, std::vector<unsigned int> > sDeadEndVStack;
+    std::stack<unsigned int, std::vector<unsigned int>> sDeadEndVStack;
 
     // create a copy of the piNumTriPtr buffer
-    unsigned int* const piNumTriPtr = adj.mLiveTriangles;
+    unsigned int *const piNumTriPtr = adj.mLiveTriangles;
     const std::vector<unsigned int> piNumTriPtrNoModify(piNumTriPtr, piNumTriPtr + pMesh->mNumVertices);
 
     // get the largest number of referenced triangles and allocate the "candidate buffer"
-    unsigned int iMaxRefTris = 0; {
-        const unsigned int* piCur = adj.mLiveTriangles;
-        const unsigned int* const piCurEnd = adj.mLiveTriangles+pMesh->mNumVertices;
-        for (;piCur != piCurEnd;++piCur) {
-            iMaxRefTris = std::max(iMaxRefTris,*piCur);
+    unsigned int iMaxRefTris = 0;
+    {
+        const unsigned int *piCur = adj.mLiveTriangles;
+        const unsigned int *const piCurEnd = adj.mLiveTriangles + pMesh->mNumVertices;
+        for (; piCur != piCurEnd; ++piCur) {
+            iMaxRefTris = std::max(iMaxRefTris, *piCur);
         }
     }
     ai_assert(iMaxRefTris > 0);
-    unsigned int* piCandidates = new unsigned int[iMaxRefTris*3];
+    std::vector<unsigned int> piCandidates;
+    piCandidates.resize(iMaxRefTris * 3);
     unsigned int iCacheMisses = 0;
 
     // ...................................................................................
@@ -245,23 +254,23 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
 
     int ivdx = 0;
     int ics = 1;
-    int iStampCnt = mConfigCacheDepth+1;
-    while (ivdx >= 0)   {
+    int iStampCnt = mConfigCacheDepth + 1;
+    while (ivdx >= 0) {
 
         unsigned int icnt = piNumTriPtrNoModify[ivdx];
-        unsigned int* piList = adj.GetAdjacentTriangles(ivdx);
-        unsigned int* piCurCandidate = piCandidates;
+        unsigned int *piList = adj.GetAdjacentTriangles(ivdx);
+        std::vector<unsigned int>::iterator piCurCandidate = piCandidates.begin();
 
         // get all triangles in the neighborhood
-        for (unsigned int tri = 0; tri < icnt;++tri)    {
+        for (unsigned int tri = 0; tri < icnt; ++tri) {
 
             // if they have not yet been emitted, add them to the output IB
             const unsigned int fidx = *piList++;
-            if (!abEmitted[fidx])   {
+            if (!abEmitted[fidx]) {
 
                 // so iterate through all vertices of the current triangle
-                const aiFace* pcFace = &pMesh->mFaces[ fidx ];
-                unsigned nind = pcFace->mNumIndices;
+                const aiFace *pcFace = &pMesh->mFaces[fidx];
+                const unsigned nind = pcFace->mNumIndices;
                 for (unsigned ind = 0; ind < nind; ind++) {
                     unsigned dp = pcFace->mIndices[ind];
 
@@ -281,7 +290,7 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
                     *piCSIter++ = dp;
 
                     // if the vertex is not yet in cache, set its cache count
-                    if (iStampCnt-piCachingStamps[dp] > mConfigCacheDepth) {
+                    if (iStampCnt - piCachingStamps[dp] > mConfigCacheDepth) {
                         piCachingStamps[dp] = iStampCnt++;
                         ++iCacheMisses;
                     }
@@ -297,16 +306,16 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
         // get next fanning vertex
         ivdx = -1;
         int max_priority = -1;
-        for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur)    {
+        for (std::vector<unsigned int>::iterator piCur = piCandidates.begin(); piCur != piCurCandidate; ++piCur) {
             const unsigned int dp = *piCur;
 
             // must have live triangles
-            if (piNumTriPtr[dp] > 0)    {
+            if (piNumTriPtr[dp] > 0) {
                 int priority = 0;
 
                 // will the vertex be in cache, even after fanning occurs?
                 unsigned int tmp;
-                if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= mConfigCacheDepth) {
+                if ((tmp = iStampCnt - piCachingStamps[dp]) + 2 * piNumTriPtr[dp] <= mConfigCacheDepth) {
                     priority = tmp;
                 }
 
@@ -324,7 +333,7 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
             while (!sDeadEndVStack.empty()) {
                 unsigned int iCachedIdx = sDeadEndVStack.top();
                 sDeadEndVStack.pop();
-                if (piNumTriPtr[ iCachedIdx ] > 0)  {
+                if (piNumTriPtr[iCachedIdx] > 0) {
                     ivdx = iCachedIdx;
                     break;
                 }
@@ -333,9 +342,9 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
             if (-1 == ivdx) {
                 // well, there isn't such a vertex. Simply get the next vertex in input order and
                 // hope it is not too bad ...
-                while (ics < (int)pMesh->mNumVertices)  {
+                while (ics < (int)pMesh->mNumVertices) {
                     ++ics;
-                    if (piNumTriPtr[ics] > 0)   {
+                    if (piNumTriPtr[ics] > 0) {
                         ivdx = ics;
                         break;
                     }
@@ -345,29 +354,29 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
     }
     ai_real fACMR2 = 0.0f;
     if (!DefaultLogger::isNullLogger()) {
-        fACMR2 = (float)iCacheMisses / pMesh->mNumFaces;
-
+        fACMR2 = static_cast<ai_real>(iCacheMisses / pMesh->mNumFaces);
+        const ai_real averageACMR = ((fACMR - fACMR2) / fACMR) * 100.f;
         // very intense verbose logging ... prepare for much text if there are many meshes
-        if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
-            ASSIMP_LOG_VERBOSE_DEBUG("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f);
+        if (DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
+            ASSIMP_LOG_VERBOSE_DEBUG("Mesh ", meshNum, "| ACMR in: ", fACMR, " out: ", fACMR2, " | average ACMR ", averageACMR);
         }
-
         fACMR2 *= pMesh->mNumFaces;
     }
+
     // sort the output index buffer back to the input array
-    piCSIter = piIBOutput;
-    for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace)  {
+    piCSIter = piIBOutput.begin();
+    for (aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) {
         unsigned nind = pcFace->mNumIndices;
-        unsigned * ind = pcFace->mIndices;
-        if (nind > 0) ind[0] = *piCSIter++;
-        if (nind > 1) ind[1] = *piCSIter++;
-        if (nind > 2) ind[2] = *piCSIter++;
+        unsigned *ind = pcFace->mIndices;
+        if (nind > 0)
+            ind[0] = *piCSIter++;
+        if (nind > 1)
+            ind[1] = *piCSIter++;
+        if (nind > 2)
+            ind[2] = *piCSIter++;
     }
 
-    // delete temporary storage
-    delete[] piCachingStamps;
-    delete[] piIBOutput;
-    delete[] piCandidates;
-
     return fACMR2;
 }
+
+} // namespace Assimp

+ 4 - 7
code/PostProcessing/PretransformVertices.cpp

@@ -290,12 +290,6 @@ void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) {
 	}
 }
 
-static void normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, size_t numVectors) {
-	for (size_t i=0; i<numVectors; ++i) {
-		vectorArrayOut[i] = vectorArrayIn[i].Normalize();
-	}
-}
-
 // ------------------------------------------------------------------------------------------------
 // Apply the node transformation to a mesh
 void PretransformVertices::ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat) const {
@@ -322,8 +316,11 @@ void PretransformVertices::ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat)
 		const aiMatrix3x3 m = aiMatrix3x3(mat).Inverse().Transpose();
 
 		if (mesh->HasNormals()) {
-			normalizeVectorArray(mesh->mNormals, mesh->mNormals, mesh->mNumVertices);
+			for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
+                mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
+            }
 		}
+
 		if (mesh->HasTangentsAndBitangents()) {
 			for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
 				mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();

+ 16 - 3
contrib/zlib/zconf.h.included

@@ -40,6 +40,9 @@
 #  define crc32                 z_crc32
 #  define crc32_combine         z_crc32_combine
 #  define crc32_combine64       z_crc32_combine64
+#  define crc32_combine_gen     z_crc32_combine_gen
+#  define crc32_combine_gen64   z_crc32_combine_gen64
+#  define crc32_combine_op      z_crc32_combine_op
 #  define crc32_z               z_crc32_z
 #  define deflate               z_deflate
 #  define deflateBound          z_deflateBound
@@ -351,6 +354,9 @@
 #    ifdef FAR
 #      undef FAR
 #    endif
+#    ifndef WIN32_LEAN_AND_MEAN
+#      define WIN32_LEAN_AND_MEAN
+#    endif
 #    include <windows.h>
      /* No need for _export, use ZLIB.DEF instead. */
      /* For complete Windows compatibility, use WINAPI, not __stdcall. */
@@ -469,11 +475,18 @@ typedef uLong FAR uLongf;
 #  undef _LARGEFILE64_SOURCE
 #endif
 
-#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H)
-#  define Z_HAVE_UNISTD_H
+#ifndef Z_HAVE_UNISTD_H
+#  ifdef __WATCOMC__
+#    define Z_HAVE_UNISTD_H
+#  endif
+#endif
+#ifndef Z_HAVE_UNISTD_H
+#  if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
+#    define Z_HAVE_UNISTD_H
+#  endif
 #endif
 #ifndef Z_SOLO
-#  if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE)
+#  if defined(Z_HAVE_UNISTD_H)
 #    include <unistd.h>         /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
 #    ifdef VMS
 #      include <unixio.h>       /* for off_t */

+ 4 - 0
include/assimp/BaseImporter.h

@@ -63,6 +63,7 @@ struct aiImporterDesc;
 
 namespace Assimp {
 
+// Forward declarations
 class Importer;
 class IOSystem;
 class BaseProcess;
@@ -73,6 +74,9 @@ class IOStream;
 #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
                                           (string[1] << 16) + (string[2] << 8) + string[3]))
 
+using UByteBuffer = std::vector<uint8_t>;
+using ByteBuffer = std::vector<int8_t>;
+
 // ---------------------------------------------------------------------------
 /** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface
  *  for all importer worker classes.

+ 0 - 1
include/assimp/ParsingUtils.h

@@ -70,7 +70,6 @@ namespace Assimp {
 
 static const unsigned int BufferSize = 4096;
 
-
 // ---------------------------------------------------------------------------------
 template <class char_t>
 AI_FORCE_INLINE bool IsUpper(char_t in) {

+ 13 - 0
include/assimp/config.h.in

@@ -1085,6 +1085,19 @@ enum aiComponent
  */
 #define AI_CONFIG_USE_GLTF_PBR_SPECULAR_GLOSSINESS "USE_GLTF_PBR_SPECULAR_GLOSSINESS"
 
+/** @brief Specifies whether to apply a limit on the number of four bones per vertex in skinning
+ *
+ * When this flag is not defined, all bone weights and indices are limited to a
+ * maximum of four bones for each vertex (attributes JOINT_0 and WEIGHT_0 only).
+ * By enabling this flag, the number of bones per vertex is unlimited.
+ * In both cases, indices and bone weights are sorted by weight in descending order.
+ * In the case of the limit of up to four bones, a maximum of the four largest values are exported.
+ * Weights are not normalized.
+ * Property type: Bool. Default value: false.
+ */
+#define AI_CONFIG_EXPORT_GLTF_UNLIMITED_SKINNING_BONES_PER_VERTEX \
+        "USE_UNLIMITED_BONES_PER VERTEX"
+
 /**
  * @brief Specifies the blob name, assimp uses for exporting.
  * 

+ 7 - 1
include/assimp/mesh.h

@@ -59,6 +59,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/types.h>
 
 #ifdef __cplusplus
+#include <unordered_set>
+
 extern "C" {
 #endif
 
@@ -872,11 +874,15 @@ struct aiMesh {
 
         // DO NOT REMOVE THIS ADDITIONAL CHECK
         if (mNumBones && mBones) {
+            std::unordered_set<const aiBone *> bones;
             for (unsigned int a = 0; a < mNumBones; a++) {
                 if (mBones[a]) {
-                    delete mBones[a];
+                    bones.insert(mBones[a]);
                 }
             }
+            for (const aiBone *bone: bones) {
+                delete bone;
+            }
             delete[] mBones;
         }
 

+ 2 - 0
include/assimp/vector3.h

@@ -151,6 +151,8 @@ public:
 
 
 typedef aiVector3t<ai_real> aiVector3D;
+typedef aiVector3t<float> aiVector3f;
+typedef aiVector3t<double> aiVector3d;
 
 #else
 

+ 1 - 0
samples/SimpleTexturedDirectx11/CMakeLists.txt

@@ -19,6 +19,7 @@ INCLUDE_DIRECTORIES(
   ${Assimp_SOURCE_DIR}/include
   ${Assimp_SOURCE_DIR}/code
   ${SAMPLES_SHARED_CODE_DIR}
+  ${Assimp_SOURCE_DIR}/contrib/utf8cpp/source
 )
 
 LINK_DIRECTORIES(

+ 1 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp

@@ -23,6 +23,7 @@
 #include <dxgi1_2.h>
 #include <DirectXMath.h>
 #include <d3dcompiler.h>
+#include <utf8.h>
 
 #include "ModelLoader.h"
 #include "SafeRelease.hpp"

+ 1 - 0
samples/SimpleTexturedOpenGL/CMakeLists.txt

@@ -21,6 +21,7 @@ INCLUDE_DIRECTORIES(
   ${OPENGL_INCLUDE_DIR}
   ${GLUT_INCLUDE_DIR}
   ${SAMPLES_SHARED_CODE_DIR}
+  ${Assimp_SOURCE_DIR}/contrib/utf8cpp/source
 )
 
 LINK_DIRECTORIES(

+ 1 - 0
samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp

@@ -17,6 +17,7 @@
 #include <stdio.h>
 #include <GL/gl.h>
 #include <GL/glu.h>
+#include <utf8.h>
 
 #ifdef _MSC_VER
 #pragma warning(disable: 4100) // Disable warning 'unreferenced formal parameter'

BIN
test/models/glTF2/simple_skin/quad_skin.glb


+ 3 - 0
test/unit/utBlendImportAreaLight.cpp

@@ -48,6 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 class BlendImportAreaLight : public ::testing::Test {
 public:
+    BlendImportAreaLight() :
+            im(nullptr) {}
+    ~BlendImportAreaLight() override = default;
     void SetUp() override {
         im = new Assimp::Importer();
     }

+ 5 - 2
test/unit/utBlenderWork.cpp

@@ -48,11 +48,14 @@ using namespace ::Assimp;
 
 class BlenderWorkTest : public ::testing::Test {
 public:
-    virtual void SetUp() {
+    BlenderWorkTest() : im(nullptr) {}
+    ~BlenderWorkTest() override = default;
+
+    void SetUp() override {
         im = new Assimp::Importer();
     }
 
-    virtual void TearDown() {
+    void TearDown() override {
         delete im;
     }
 

Деякі файли не було показано, через те що забагато файлів було змінено