Parcourir la source

Merge branch 'master' into SmallAllocationFixInFBXLoader

Kim Kulling il y a 3 ans
Parent
commit
7b874983d0
100 fichiers modifiés avec 695 ajouts et 728 suppressions
  1. 6 0
      .github/dependabot.yml
  2. 6 6
      .github/workflows/ccpp.yml
  3. 2 2
      .github/workflows/sanitizer.yml
  4. 27 21
      Build.md
  5. 31 38
      CMakeLists.txt
  6. 1 1
      INSTALL
  7. 0 1
      README
  8. 3 0
      Readme.md
  9. 16 0
      SECURITY.md
  10. 1 1
      cmake-modules/FindDirectX.cmake
  11. 1 1
      cmake-modules/FindPkgMacros.cmake
  12. 1 0
      code/AssetLib/3DS/3DSConverter.cpp
  13. 1 3
      code/AssetLib/3DS/3DSExporter.cpp
  14. 6 7
      code/AssetLib/3DS/3DSLoader.cpp
  15. 2 0
      code/AssetLib/3MF/3MFXmlTags.h
  16. 2 7
      code/AssetLib/3MF/D3MFImporter.cpp
  17. 3 0
      code/AssetLib/3MF/D3MFOpcPackage.cpp
  18. 32 9
      code/AssetLib/3MF/XmlSerializer.cpp
  19. 7 9
      code/AssetLib/AC/ACLoader.cpp
  20. 5 6
      code/AssetLib/ASE/ASELoader.cpp
  21. 18 13
      code/AssetLib/ASE/ASEParser.cpp
  22. 1 1
      code/AssetLib/ASE/ASEParser.h
  23. 9 5
      code/AssetLib/Assbin/AssbinFileWriter.cpp
  24. 4 0
      code/AssetLib/Assbin/AssbinLoader.cpp
  25. 1 1
      code/AssetLib/Assjson/mesh_splitter.cpp
  26. 1 1
      code/AssetLib/Assxml/AssxmlFileWriter.cpp
  27. 5 7
      code/AssetLib/B3D/B3DImporter.cpp
  28. 2 2
      code/AssetLib/BVH/BVHLoader.cpp
  29. 4 4
      code/AssetLib/Blender/BlenderDNA.cpp
  30. 2 2
      code/AssetLib/Blender/BlenderDNA.h
  31. 1 2
      code/AssetLib/Blender/BlenderIntermediate.h
  32. 2 2
      code/AssetLib/Blender/BlenderLoader.cpp
  33. 1 1
      code/AssetLib/Blender/BlenderLoader.h
  34. 3 6
      code/AssetLib/Blender/BlenderModifier.cpp
  35. 12 6
      code/AssetLib/Blender/BlenderScene.cpp
  36. 12 8
      code/AssetLib/Blender/BlenderScene.h
  37. 1 3
      code/AssetLib/Blender/BlenderTessellator.cpp
  38. 1 1
      code/AssetLib/Blender/BlenderTessellator.h
  39. 7 11
      code/AssetLib/COB/COBLoader.cpp
  40. 1 1
      code/AssetLib/COB/COBScene.h
  41. 1 2
      code/AssetLib/CSM/CSMLoader.cpp
  42. 3 4
      code/AssetLib/Collada/ColladaExporter.cpp
  43. 1 1
      code/AssetLib/Collada/ColladaExporter.h
  44. 5 0
      code/AssetLib/Collada/ColladaHelper.h
  45. 7 6
      code/AssetLib/Collada/ColladaLoader.cpp
  46. 1 0
      code/AssetLib/Collada/ColladaLoader.h
  47. 10 9
      code/AssetLib/Collada/ColladaParser.cpp
  48. 8 11
      code/AssetLib/DXF/DXFLoader.cpp
  49. 0 21
      code/AssetLib/FBX/FBXAnimation.cpp
  50. 1 1
      code/AssetLib/FBX/FBXBinaryTokenizer.cpp
  51. 2 1
      code/AssetLib/FBX/FBXCommon.h
  52. 0 1
      code/AssetLib/FBX/FBXCompileConfig.h
  53. 117 66
      code/AssetLib/FBX/FBXConverter.cpp
  54. 29 16
      code/AssetLib/FBX/FBXConverter.h
  55. 7 27
      code/AssetLib/FBX/FBXDeformer.cpp
  56. 2 2
      code/AssetLib/FBX/FBXDocument.cpp
  57. 10 10
      code/AssetLib/FBX/FBXDocument.h
  58. 3 6
      code/AssetLib/FBX/FBXDocumentUtil.cpp
  59. 5 7
      code/AssetLib/FBX/FBXDocumentUtil.h
  60. 1 1
      code/AssetLib/FBX/FBXExporter.cpp
  61. 6 0
      code/AssetLib/FBX/FBXImportSettings.h
  62. 22 25
      code/AssetLib/FBX/FBXImporter.cpp
  63. 7 6
      code/AssetLib/FBX/FBXImporter.h
  64. 3 9
      code/AssetLib/FBX/FBXMaterial.cpp
  65. 6 26
      code/AssetLib/FBX/FBXMeshGeometry.cpp
  66. 12 9
      code/AssetLib/FBX/FBXMeshGeometry.h
  67. 29 78
      code/AssetLib/FBX/FBXNodeAttribute.cpp
  68. 10 13
      code/AssetLib/FBX/FBXParser.cpp
  69. 1 1
      code/AssetLib/FBX/FBXParser.h
  70. 13 19
      code/AssetLib/FBX/FBXProperties.cpp
  71. 1 3
      code/AssetLib/FBX/FBXTokenizer.cpp
  72. 1 1
      code/AssetLib/FBX/FBXTokenizer.h
  73. 2 6
      code/AssetLib/HMP/HMPLoader.cpp
  74. 3 3
      code/AssetLib/IFC/IFCBoolean.cpp
  75. 5 3
      code/AssetLib/IFC/IFCCurve.cpp
  76. 2 2
      code/AssetLib/IFC/IFCGeometry.cpp
  77. 2 3
      code/AssetLib/IFC/IFCLoader.cpp
  78. 36 36
      code/AssetLib/IFC/IFCOpenings.cpp
  79. 17 17
      code/AssetLib/IFC/IFCProfile.cpp
  80. 2 2
      code/AssetLib/IFC/IFCUtil.cpp
  81. 1 2
      code/AssetLib/IFC/IFCUtil.h
  82. 2 2
      code/AssetLib/IQM/IQMImporter.h
  83. 6 8
      code/AssetLib/Irr/IRRLoader.cpp
  84. 1 2
      code/AssetLib/Irr/IRRLoader.h
  85. 1 1
      code/AssetLib/Irr/IRRMeshLoader.cpp
  86. 1 1
      code/AssetLib/LWO/LWOBLoader.cpp
  87. 2 8
      code/AssetLib/LWO/LWOFileData.h
  88. 9 11
      code/AssetLib/LWO/LWOLoader.cpp
  89. 0 2
      code/AssetLib/LWO/LWOMaterial.cpp
  90. 10 13
      code/AssetLib/LWS/LWSLoader.cpp
  91. 1 1
      code/AssetLib/LWS/LWSLoader.h
  92. 1 3
      code/AssetLib/M3D/M3DWrapper.h
  93. 1 2
      code/AssetLib/MD2/MD2Loader.cpp
  94. 7 7
      code/AssetLib/MD3/MD3Loader.cpp
  95. 1 3
      code/AssetLib/MD5/MD5Loader.cpp
  96. 8 8
      code/AssetLib/MD5/MD5Parser.cpp
  97. 4 6
      code/AssetLib/MDC/MDCLoader.cpp
  98. 1 2
      code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp
  99. 1 3
      code/AssetLib/MDL/MDLLoader.cpp
  100. 3 0
      code/AssetLib/MDL/MDLMaterialLoader.cpp

+ 6 - 0
.github/dependabot.yml

@@ -0,0 +1,6 @@
+version: 2
+updates:
+  - package-ecosystem: "github-actions"
+    directory: "/"
+    schedule:
+      interval: "weekly"

+ 6 - 6
.github/workflows/ccpp.yml

@@ -43,7 +43,7 @@ jobs:
             toolchain: ninja-vs-win64-cxx17
             toolchain: ninja-vs-win64-cxx17
 
 
     steps:
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
     
     
     - uses: lukka/get-cmake@latest
     - uses: lukka/get-cmake@latest
     
     
@@ -64,21 +64,21 @@ jobs:
 
 
     - name: Checkout Hunter toolchains
     - name: Checkout Hunter toolchains
       if: endsWith(matrix.name, 'hunter')
       if: endsWith(matrix.name, 'hunter')
-      uses: actions/checkout@v2
+      uses: actions/checkout@v3
       with:
       with:
         repository: cpp-pm/polly
         repository: cpp-pm/polly
         path: cmake/polly
         path: cmake/polly
 
 
     - name: Remove contrib directory for Hunter builds
     - name: Remove contrib directory for Hunter builds
       if: contains(matrix.name, 'hunter')
       if: contains(matrix.name, 'hunter')
-      uses: JesseTG/[email protected].2
+      uses: JesseTG/[email protected].3
       with:
       with:
         path: contrib
         path: contrib
 
 
     - name: Cache DX SDK
     - name: Cache DX SDK
       id: dxcache
       id: dxcache
       if: contains(matrix.name, 'windows')
       if: contains(matrix.name, 'windows')
-      uses: actions/cache@v2
+      uses: actions/cache@v3
       with:
       with:
         path: '${{ github.workspace }}/DX_SDK'
         path: '${{ github.workspace }}/DX_SDK'
         key: ${{ runner.os }}-DX_SDK
         key: ${{ runner.os }}-DX_SDK
@@ -110,7 +110,7 @@ jobs:
         cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
         cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
         cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
         cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
         cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release ${{ steps.windows_extra_cmake_args.outputs.args }} ${{ steps.hunter_extra_cmake_args.outputs.args }}'
         cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release ${{ steps.windows_extra_cmake_args.outputs.args }} ${{ steps.hunter_extra_cmake_args.outputs.args }}'
-        buildWithCMakeArgs: '-- -v'
+        buildWithCMakeArgs: '-- -j 24 -v'
         buildDirectory: '${{ github.workspace }}/build/'
         buildDirectory: '${{ github.workspace }}/build/'
         
         
     - name: Exclude certain tests in Hunter specific builds
     - name: Exclude certain tests in Hunter specific builds
@@ -122,7 +122,7 @@ jobs:
       run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }}
       run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }}
       shell: bash
       shell: bash
 
 
-    - uses: actions/upload-artifact@v2
+    - uses: actions/upload-artifact@v3
       if: matrix.name == 'windows-msvc'
       if: matrix.name == 'windows-msvc'
       with:
       with:
         name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'
         name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'

+ 2 - 2
.github/workflows/sanitizer.yml

@@ -11,7 +11,7 @@ jobs:
     name: adress-sanitizer
     name: adress-sanitizer
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
     - uses: lukka/get-cmake@latest    
     - uses: lukka/get-cmake@latest    
     - uses: lukka/set-shell-env@v1
     - uses: lukka/set-shell-env@v1
       with:
       with:
@@ -35,7 +35,7 @@ jobs:
     name: undefined-behavior-sanitizer
     name: undefined-behavior-sanitizer
     runs-on: ubuntu-latest
     runs-on: ubuntu-latest
     steps:
     steps:
-    - uses: actions/checkout@v2
+    - uses: actions/checkout@v3
     - uses: lukka/get-cmake@latest    
     - uses: lukka/get-cmake@latest    
     - uses: lukka/set-shell-env@v1
     - uses: lukka/set-shell-env@v1
       with:
       with:

+ 27 - 21
Build.md

@@ -14,7 +14,8 @@ The assimp port in vcpkg is kept up to date by Microsoft team members and commun
 ## Install on Ubuntu
 ## Install on Ubuntu
 You can install the Asset-Importer-Lib via apt:
 You can install the Asset-Importer-Lib via apt:
 ```
 ```
-sudo apt-get install assimp
+sudo apt-get update
+sudo apt-get install libassimp-dev
 ```
 ```
 
 
 ## Install pyassimp
 ## Install pyassimp
@@ -84,23 +85,28 @@ Besides the toolchain, compilation should be the same as for Linux / Unix.
 
 
 ### CMake build options
 ### CMake build options
 The cmake-build-environment provides options to configure the build. The following options can be used:
 The cmake-build-environment provides options to configure the build. The following options can be used:
-- **BUILD_SHARED_LIBS ( default ON )**: Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib.
-- **BUILD_FRAMEWORK ( default OFF, MacOnly)**: Build package as Mac OS X Framework bundle
-- **ASSIMP_DOUBLE_PRECISION( default OFF )**: All data will be stored as double values.
-- **ASSIMP_OPT_BUILD_PACKAGES ( default OFF)**: Set to ON to generate CPack configuration files and packaging targets
-- **ASSIMP_ANDROID_JNIIOSYSTEM ( default OFF )**: Android JNI IOSystem support is active
-- **ASSIMP_NO_EXPORT ( default OFF )**: Disable Assimp's export functionality
-- **ASSIMP_BUILD_ZLIB ( default OFF )**: Build your own zlib
-- **ASSIMP_BUILD_ASSIMP_TOOLS ( default ON )**: If the supplementary tools for Assimp are built in addition to the library.
-- **ASSIMP_BUILD_SAMPLES ( default OFF )**: If the official samples are built as well (needs Glut).
-- **ASSIMP_BUILD_TESTS ( default ON )**: If the test suite for Assimp is built in addition to the library.
-- **ASSIMP_COVERALLS ( default OFF )**: Enable this to measure test coverage.
-- **ASSIMP_ERROR_MAX( default OFF)**: Enable all warnings.
-- **ASSIMP_WERROR( default OFF )**: Treat warnings as errors.
-- **ASSIMP_ASAN ( default OFF )**: Enable AddressSanitizer.
-- **ASSIMP_UBSAN ( default OFF )**: Enable Undefined Behavior sanitizer.
-- **SYSTEM_IRRXML ( default OFF )**: Use system installed Irrlicht/IrrXML library.
-- **BUILD_DOCS ( default OFF )**: Build documentation using Doxygen.
-- **INJECT_DEBUG_POSTFIX( default ON )**: Inject debug postfix in .a/.so lib names
-- **IGNORE_GIT_HASH ( default OFF )**: Don't call git to get the hash.
-- **ASSIMP_INSTALL_PDB ( default ON )**: Install MSVC debug files.
+- **ASSIMP_HUNTER_ENABLED (default OFF)**: Enable Hunter package manager support.
+- **BUILD_SHARED_LIBS (default ON)**: Generation of shared libs (dll for windows, so for Linux). Set this to OFF to get a static lib.
+- **ASSIMP_BUILD_FRAMEWORK (default OFF, MacOnly)**: Build package as Mac OS X Framework bundle.
+- **ASSIMP_DOUBLE_PRECISION (default OFF)**: All data will be stored as double values.
+- **ASSIMP_OPT_BUILD_PACKAGES (default OFF)**: Set to ON to generate CPack configuration files and packaging targets.
+- **ASSIMP_ANDROID_JNIIOSYSTEM (default OFF)**: Android JNI IOSystem support is active.
+- **ASSIMP_NO_EXPORT (default OFF)**: Disable Assimp's export functionality.
+- **ASSIMP_BUILD_ZLIB (default OFF)**: Build our own zlib.
+- **ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all exporter senabled.
+- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all importer senabled.
+- **ASSIMP_BUILD_ASSIMP_TOOLS (default ON)**: If the supplementary tools for Assimp are built in addition to the library.
+- **ASSIMP_BUILD_SAMPLES (default OFF)**: If the official samples are built as well (needs Glut).
+- **ASSIMP_BUILD_TESTS (default ON)**: If the test suite for Assimp is built in addition to the library.
+- **ASSIMP_COVERALLS (default OFF)**: Enable this to measure test coverage.
+- **ASSIMP_INSTALL (default ON)**: Install Assimp library. Disable this if you want to use Assimp as a submodule.
+- **ASSIMP_WARNINGS_AS_ERRORS (default ON)**: Treat all warnings as errors.
+- **ASSIMP_ASAN (default OFF)**: Enable AddressSanitizer.
+- **ASSIMP_UBSAN (default OFF)**: Enable Undefined Behavior sanitizer.
+- **ASSIMP_BUILD_DOCS (default OFF)**: Build documentation using Doxygen. OBSOLETE, see https://github.com/assimp/assimp-docs
+- **ASSIMP_INJECT_DEBUG_POSTFIX (default ON)**: Inject debug postfix in .a/.so/.lib/.dll lib names
+- **ASSIMP_IGNORE_GIT_HASH (default OFF)**: Don't call git to get the hash.
+- **ASSIMP_INSTALL_PDB (default ON)**: Install MSVC debug files.
+- **USE_STATIC_CRT (default OFF)**: Link against the static MSVC runtime libraries.
+- **ASSIMP_BUILD_DRACO (default OFF)**: Build Draco libraries. Primarily for glTF.
+- **ASSIMP_BUILD_ASSIMP_VIEW (default ON, if DirectX found, OFF otherwise)**: Build Assimp view tool (requires DirectX).

+ 31 - 38
CMakeLists.txt

@@ -56,7 +56,7 @@ IF(ASSIMP_HUNTER_ENABLED)
   add_definitions(-DASSIMP_USE_HUNTER)
   add_definitions(-DASSIMP_USE_HUNTER)
 ENDIF()
 ENDIF()
 
 
-PROJECT(Assimp VERSION 5.2.0)
+PROJECT(Assimp VERSION 5.2.4)
 
 
 # All supported options ###############################################
 # All supported options ###############################################
 
 
@@ -90,7 +90,7 @@ OPTION( ASSIMP_BUILD_ZLIB
 )
 )
 OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
 OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
   "If the supplementary tools for Assimp are built in addition to the library."
   "If the supplementary tools for Assimp are built in addition to the library."
-  ON
+  OFF
 )
 )
 OPTION ( ASSIMP_BUILD_SAMPLES
 OPTION ( ASSIMP_BUILD_SAMPLES
   "If the official samples are built as well (needs Glut)."
   "If the official samples are built as well (needs Glut)."
@@ -108,9 +108,9 @@ OPTION( ASSIMP_INSTALL
   "Disable this if you want to use assimp as a submodule."
   "Disable this if you want to use assimp as a submodule."
   ON
   ON
 )
 )
-OPTION ( ASSIMP_ERROR_MAX
-  "Enable all warnings."
-  OFF
+OPTION ( ASSIMP_WARNINGS_AS_ERRORS
+  "Treat all warnings as errors."
+  ON
 )
 )
 OPTION ( ASSIMP_ASAN
 OPTION ( ASSIMP_ASAN
   "Enable AddressSanitizer."
   "Enable AddressSanitizer."
@@ -139,10 +139,6 @@ IF (WIN32)
   ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
   ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
 
 
   IF(MSVC)
   IF(MSVC)
-    OPTION (ASSIMP_BUILD_ASSIMP_VIEW
-      "If the Assimp view tool is built. (requires DirectX)"
-      OFF )
-
     OPTION( ASSIMP_INSTALL_PDB
     OPTION( ASSIMP_INSTALL_PDB
       "Install MSVC debug files."
       "Install MSVC debug files."
       ON )
       ON )
@@ -184,6 +180,7 @@ ENDIF()
 IF(NOT BUILD_SHARED_LIBS)
 IF(NOT BUILD_SHARED_LIBS)
   MESSAGE(STATUS "Shared libraries disabled")
   MESSAGE(STATUS "Shared libraries disabled")
   SET(LINK_SEARCH_START_STATIC TRUE)
   SET(LINK_SEARCH_START_STATIC TRUE)
+  SET(CMAKE_FIND_LIBRARY_SUFFIXES ${CMAKE_STATIC_LIBRARY_SUFFIX} ${CMAKE_FIND_LIBRARY_SUFFIXES})
 ELSE()
 ELSE()
   MESSAGE(STATUS "Shared libraries enabled")
   MESSAGE(STATUS "Shared libraries enabled")
 ENDIF()
 ENDIF()
@@ -197,8 +194,8 @@ SET (ASSIMP_SOVERSION 5)
 
 
 SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
 SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
 if(NOT ASSIMP_HUNTER_ENABLED)
 if(NOT ASSIMP_HUNTER_ENABLED)
-  # Enable C++11 support globally
-  set(CMAKE_CXX_STANDARD 11)
+  # Enable C++17 support globally
+  set(CMAKE_CXX_STANDARD 17)
   set(CMAKE_CXX_STANDARD_REQUIRED ON)
   set(CMAKE_CXX_STANDARD_REQUIRED ON)
   set(CMAKE_C_STANDARD 99)
   set(CMAKE_C_STANDARD 99)
 endif()
 endif()
@@ -231,16 +228,6 @@ IF(ASSIMP_DOUBLE_PRECISION)
   ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
   ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
 ENDIF()
 ENDIF()
 
 
-CONFIGURE_FILE(
-  ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
-  ${CMAKE_CURRENT_BINARY_DIR}/revision.h
-)
-
-CONFIGURE_FILE(
-  ${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h.in
-  ${CMAKE_CURRENT_BINARY_DIR}/include/assimp/config.h
-)
-
 INCLUDE_DIRECTORIES( BEFORE
 INCLUDE_DIRECTORIES( BEFORE
   ./
   ./
   code/
   code/
@@ -270,7 +257,7 @@ ENDIF()
 # Grouped compiler settings ########################################
 # Grouped compiler settings ########################################
 IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW)
 IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW)
   IF(NOT ASSIMP_HUNTER_ENABLED)
   IF(NOT ASSIMP_HUNTER_ENABLED)
-    SET(CMAKE_CXX_STANDARD 11)
+    SET(CMAKE_CXX_STANDARD 17)
     SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
     SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
   ENDIF()
   ENDIF()
   # hide all not-exported symbols
   # hide all not-exported symbols
@@ -300,7 +287,7 @@ ELSEIF(MSVC)
   SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
   SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
 ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
 ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
   IF(NOT ASSIMP_HUNTER_ENABLED)
   IF(NOT ASSIMP_HUNTER_ENABLED)
-    SET(CMAKE_CXX_STANDARD 11)
+    SET(CMAKE_CXX_STANDARD 17)
     SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
     SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
   ENDIF()
   ENDIF()
   SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
   SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
@@ -312,11 +299,15 @@ ELSEIF( MINGW )
     message(WARNING "MinGW is old, if you experience errors, update MinGW.")
     message(WARNING "MinGW is old, if you experience errors, update MinGW.")
   ENDIF()
   ENDIF()
   IF(NOT ASSIMP_HUNTER_ENABLED)
   IF(NOT ASSIMP_HUNTER_ENABLED)
-    SET(CMAKE_CXX_FLAGS "-std=gnu++11 ${CMAKE_CXX_FLAGS}")
+    SET(CMAKE_CXX_FLAGS "-std=gnu++17 ${CMAKE_CXX_FLAGS}")
     SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
     SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
   ENDIF()
   ENDIF()
-  SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj -O3 ${CMAKE_CXX_FLAGS}")
-  SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
+    IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
+      SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj -g ${CMAKE_CXX_FLAGS}")
+    ELSE()
+      SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj -O3 ${CMAKE_CXX_FLAGS}")
+    ENDIF()
+    SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
 ENDIF()
 ENDIF()
 
 
 IF ( IOS AND NOT ASSIMP_HUNTER_ENABLED)
 IF ( IOS AND NOT ASSIMP_HUNTER_ENABLED)
@@ -337,16 +328,6 @@ IF (ASSIMP_COVERALLS)
   SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
   SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
 ENDIF()
 ENDIF()
 
 
-IF (ASSIMP_ERROR_MAX)
-  MESSAGE(STATUS "Turning on all warnings")
-  IF (MSVC)
-    ADD_COMPILE_OPTIONS(/W4) # NB: there is a /Wall option, pedantic mode
-  ELSE()
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall")
-    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall")
-  ENDIF()
-ENDIF()
-
 IF (ASSIMP_ASAN)
 IF (ASSIMP_ASAN)
   MESSAGE(STATUS "AddressSanitizer enabled")
   MESSAGE(STATUS "AddressSanitizer enabled")
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
@@ -707,10 +688,12 @@ ENDIF()
 
 
 # Main assimp code
 # Main assimp code
 ADD_SUBDIRECTORY( code/ )
 ADD_SUBDIRECTORY( code/ )
+
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
   # The viewer for windows only
   # The viewer for windows only
   IF (WIN32)
   IF (WIN32)
-    OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" OFF )
+    FIND_PACKAGE(DirectX)
+    OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
     IF ( ASSIMP_BUILD_ASSIMP_VIEW )
     IF ( ASSIMP_BUILD_ASSIMP_VIEW )
       ADD_SUBDIRECTORY( tools/assimp_view/ )
       ADD_SUBDIRECTORY( tools/assimp_view/ )
     ENDIF ()
     ENDIF ()
@@ -735,12 +718,22 @@ IF ( ASSIMP_BUILD_TESTS )
   ADD_SUBDIRECTORY( test/ )
   ADD_SUBDIRECTORY( test/ )
 ENDIF ()
 ENDIF ()
 
 
-# Generate a pkg-config .pc for the Assimp library.
+# Generate a pkg-config .pc, revision.h, and config.h for the Assimp library.
 CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
 CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
 IF ( ASSIMP_INSTALL )
 IF ( ASSIMP_INSTALL )
   INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
   INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
 ENDIF()
 ENDIF()
 
 
+CONFIGURE_FILE(
+  ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
+  ${CMAKE_CURRENT_BINARY_DIR}/revision.h
+)
+
+CONFIGURE_FILE(
+  ${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h.in
+  ${CMAKE_CURRENT_BINARY_DIR}/include/assimp/config.h
+)
+
 IF ( ASSIMP_INSTALL )
 IF ( ASSIMP_INSTALL )
   IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
   IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
     # Packing information
     # Packing information

+ 1 - 1
INSTALL

@@ -14,4 +14,4 @@ https://assimp-docs.readthedocs.io/en/latest/
 Building Assimp 
 Building Assimp 
 ------------------------------
 ------------------------------
 
 
-Just check the build-instaructions which you can find here: https://github.com/assimp/assimp/blob/master/Build.md
+Just check the build-instructions which you can find here: https://github.com/assimp/assimp/blob/master/Build.md

+ 0 - 1
README

@@ -1 +0,0 @@
-See Readme.md

+ 3 - 0
Readme.md

@@ -9,9 +9,11 @@ A library to import and export various 3d-model-formats including scene-post-pro
        src="https://scan.coverity.com/projects/5607/badge.svg"/>
        src="https://scan.coverity.com/projects/5607/badge.svg"/>
 </a>
 </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)
 [![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)
 [![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)
 [![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")
 [![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")
 [![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
 [![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
 <br>
 <br>
 
 
@@ -58,6 +60,7 @@ Open Asset Import Library is implemented in C++. The directory structure looks l
 	/code		Source code
 	/code		Source code
 	/contrib	Third-party libraries
 	/contrib	Third-party libraries
 	/doc		Documentation (doxysource and pre-compiled docs)
 	/doc		Documentation (doxysource and pre-compiled docs)
+	/fuzz           Contains the test-code for the Google-Fuzzer project
 	/include	Public header C and C++ header files
 	/include	Public header C and C++ header files
 	/scripts 	Scripts used to generate the loading code for some formats
 	/scripts 	Scripts used to generate the loading code for some formats
 	/port		Ports to other languages and scripts to maintain those.
 	/port		Ports to other languages and scripts to maintain those.

+ 16 - 0
SECURITY.md

@@ -0,0 +1,16 @@
+# Security Policy
+
+## Supported Versions
+
+Use this section to tell people about which versions of your project are
+currently being supported with security updates.
+
+| Version | Supported          |
+| ------- | ------------------ |
+| 5.2.4   | :white_check_mark: |
+
+## Reporting a Vulnerability
+
+If you have found any security vulnerability you can contact us via 
[email protected]
+

+ 1 - 1
cmake-modules/FindDirectX.cmake

@@ -55,7 +55,7 @@ if(WIN32) # The only platform it makes sense to check for DirectX SDK
   endif(CMAKE_CL_64)
   endif(CMAKE_CL_64)
   find_library(DirectX_LIBRARY NAMES d3d9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
   find_library(DirectX_LIBRARY NAMES d3d9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
   find_library(DirectX_D3DX9_LIBRARY NAMES d3dx9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
   find_library(DirectX_D3DX9_LIBRARY NAMES d3dx9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
-  find_library(DirectX_DXERR_LIBRARY NAMES DxErr HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
+  find_library(DirectX_DXERR_LIBRARY NAMES DxErr DxErr9 HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
   find_library(DirectX_DXGUID_LIBRARY NAMES dxguid HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
   find_library(DirectX_DXGUID_LIBRARY NAMES dxguid HINTS ${DirectX_LIB_SEARCH_PATH} PATH_SUFFIXES ${DirectX_LIBPATH_SUFFIX})
 
 
 
 

+ 1 - 1
cmake-modules/FindPkgMacros.cmake

@@ -54,7 +54,7 @@ macro(clear_if_changed TESTVAR)
       set(${var} "NOTFOUND" CACHE STRING "x" FORCE)
       set(${var} "NOTFOUND" CACHE STRING "x" FORCE)
     endforeach(var)
     endforeach(var)
   endif ()
   endif ()
-  set(${TESTVAR}_INT_CHECK ${${TESTVAR}} CACHE INTERNAL "x" FORCE)
+  set(${TESTVAR}_INT_CHECK "${${TESTVAR}}" CACHE INTERNAL "x" FORCE)
 endmacro(clear_if_changed)
 endmacro(clear_if_changed)
 
 
 # Try to get some hints from pkg-config, if available
 # Try to get some hints from pkg-config, if available

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

@@ -262,6 +262,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
         unsigned int iWire = 1;
         unsigned int iWire = 1;
         mat.AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
         mat.AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
     }
     }
+    [[fallthrough]];
 
 
     case D3DS::Discreet3DS::Gouraud:
     case D3DS::Discreet3DS::Gouraud:
         eShading = aiShadingMode_Gouraud;
         eShading = aiShadingMode_Gouraud;

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

@@ -209,9 +209,7 @@ Discreet3DSExporter::Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, con
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Discreet3DSExporter::~Discreet3DSExporter() {
-    // empty
-}
+Discreet3DSExporter::~Discreet3DSExporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 int Discreet3DSExporter::WriteHierarchy(const aiNode &node, int seq, int sibling_level) {
 int Discreet3DSExporter::WriteHierarchy(const aiNode &node, int seq, int sibling_level) {

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

@@ -105,9 +105,7 @@ Discreet3DSImporter::Discreet3DSImporter() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-Discreet3DSImporter::~Discreet3DSImporter() {
-    // empty
-}
+Discreet3DSImporter::~Discreet3DSImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -319,7 +317,7 @@ void Discreet3DSImporter::ParseObjectChunk() {
     case Discreet3DS::CHUNK_MAT_MATERIAL:
     case Discreet3DS::CHUNK_MAT_MATERIAL:
 
 
         // Add a new material to the list
         // Add a new material to the list
-        mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + ai_to_string(mScene->mMaterials.size()))));
+        mScene->mMaterials.emplace_back(std::string("UNNAMED_" + ai_to_string(mScene->mMaterials.size())));
         ParseMaterialChunk();
         ParseMaterialChunk();
         break;
         break;
 
 
@@ -370,7 +368,7 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
     switch (chunk.Flag) {
     switch (chunk.Flag) {
     case Discreet3DS::CHUNK_TRIMESH: {
     case Discreet3DS::CHUNK_TRIMESH: {
         // this starts a new triangle mesh
         // this starts a new triangle mesh
-        mScene->mMeshes.push_back(D3DS::Mesh(std::string(name, num)));
+        mScene->mMeshes.emplace_back(std::string(name, num));
 
 
         // Read mesh chunks
         // Read mesh chunks
         ParseMeshChunk();
         ParseMeshChunk();
@@ -999,7 +997,7 @@ void Discreet3DSImporter::ParseMeshChunk() {
         mMesh.mFaces.reserve(num);
         mMesh.mFaces.reserve(num);
         while (num-- > 0) {
         while (num-- > 0) {
             // 3DS faces are ALWAYS triangles
             // 3DS faces are ALWAYS triangles
-            mMesh.mFaces.push_back(D3DS::Face());
+            mMesh.mFaces.emplace_back();
             D3DS::Face &sFace = mMesh.mFaces.back();
             D3DS::Face &sFace = mMesh.mFaces.back();
 
 
             sFace.mIndices[0] = (uint16_t)stream->GetI2();
             sFace.mIndices[0] = (uint16_t)stream->GetI2();
@@ -1284,7 +1282,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
     switch (chunk.Flag) {
     switch (chunk.Flag) {
     case Discreet3DS::CHUNK_LINRGBF:
     case Discreet3DS::CHUNK_LINRGBF:
         bGamma = true;
         bGamma = true;
-
+    // fallthrough
     case Discreet3DS::CHUNK_RGBF:
     case Discreet3DS::CHUNK_RGBF:
         if (sizeof(float) * 3 > diff) {
         if (sizeof(float) * 3 > diff) {
             *out = clrError;
             *out = clrError;
@@ -1297,6 +1295,7 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
 
 
     case Discreet3DS::CHUNK_LINRGBB:
     case Discreet3DS::CHUNK_LINRGBB:
         bGamma = true;
         bGamma = true;
+            // fallthrough
     case Discreet3DS::CHUNK_RGBB: {
     case Discreet3DS::CHUNK_RGBB: {
         if (sizeof(char) * 3 > diff) {
         if (sizeof(char) * 3 > diff) {
             *out = clrError;
             *out = clrError;

+ 2 - 0
code/AssetLib/3MF/3MFXmlTags.h

@@ -74,6 +74,8 @@ namespace XmlTag {
     const char* const pid = "pid";
     const char* const pid = "pid";
     const char* const pindex = "pindex";
     const char* const pindex = "pindex";
     const char* const p1 = "p1";
     const char* const p1 = "p1";
+    const char *const p2 = "p2";
+    const char *const p3 = "p3";
     const char* const name = "name";
     const char* const name = "name";
     const char* const type = "type";
     const char* const type = "type";
     const char* const build = "build";
     const char* const build = "build";

+ 2 - 7
code/AssetLib/3MF/D3MFImporter.cpp

@@ -81,14 +81,9 @@ static const aiImporterDesc desc = {
     "3mf"
     "3mf"
 };
 };
 
 
-D3MFImporter::D3MFImporter() :
-        BaseImporter() {
-    // empty
-}
+D3MFImporter::D3MFImporter() = default;
 
 
-D3MFImporter::~D3MFImporter() {
-    // empty
-}
+D3MFImporter::~D3MFImporter() = default;
 
 
 bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const {
 bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const {
     if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
     if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {

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

@@ -186,6 +186,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
 D3MFOpcPackage::~D3MFOpcPackage() {
 D3MFOpcPackage::~D3MFOpcPackage() {
     mZipArchive->Close(mRootStream);
     mZipArchive->Close(mRootStream);
     delete mZipArchive;
     delete mZipArchive;
+    for (auto tex : mEmbeddedTextures) {
+        delete tex;
+    }
 }
 }
 
 
 IOStream *D3MFOpcPackage::RootStream() const {
 IOStream *D3MFOpcPackage::RootStream() const {

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

@@ -64,7 +64,7 @@ bool validateColorString(const char *color) {
     return true;
     return true;
 }
 }
 
 
-aiFace ReadTriangle(XmlNode &node) {
+aiFace ReadTriangle(XmlNode &node, int &texId0, int &texId1, int &texId2) {
     aiFace face;
     aiFace face;
 
 
     face.mNumIndices = 3;
     face.mNumIndices = 3;
@@ -73,6 +73,11 @@ aiFace ReadTriangle(XmlNode &node) {
     face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
     face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
     face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
     face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
 
 
+    texId0 = texId1 = texId2 = -1;
+    XmlParser::getIntAttribute(node, XmlTag::p1, texId0);
+    XmlParser::getIntAttribute(node, XmlTag::p2, texId1);
+    XmlParser::getIntAttribute(node, XmlTag::p3, texId2);
+
     return face;
     return face;
 }
 }
 
 
@@ -106,7 +111,7 @@ bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &va
     return false;
     return false;
 }
 }
 
 
-aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
+aiMatrix4x4 parseTransformMatrix(const std::string& matrixStr) {
     // split the string
     // split the string
     std::vector<float> numbers;
     std::vector<float> numbers;
     std::string currentNumber;
     std::string currentNumber;
@@ -412,6 +417,9 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
             bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
             bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
             bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
             bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
 
 
+            int texId[3];
+            Texture2DGroup *group = nullptr;
+            aiFace face = ReadTriangle(currentNode, texId[0], texId[1], texId[2]);
             if (hasPid && hasP1) {
             if (hasPid && hasP1) {
                 auto it = mResourcesDictionnary.find(pid);
                 auto it = mResourcesDictionnary.find(pid);
                 if (it != mResourcesDictionnary.end()) {
                 if (it != mResourcesDictionnary.end()) {
@@ -420,23 +428,34 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
                         mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
                         mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
                     } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
                     } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
                         if (mesh->mTextureCoords[0] == nullptr) {
                         if (mesh->mTextureCoords[0] == nullptr) {
-                            Texture2DGroup *group = static_cast<Texture2DGroup *>(it->second);
+                            mesh->mNumUVComponents[0] = 2;
+                            for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+                                mesh->mNumUVComponents[i] = 0;
+                            }
+
+                            group = static_cast<Texture2DGroup *>(it->second);
                             const std::string name = ai_to_string(group->mTexId);
                             const std::string name = ai_to_string(group->mTexId);
                             for (size_t i = 0; i < mMaterials.size(); ++i) {
                             for (size_t i = 0; i < mMaterials.size(); ++i) {
                                 if (name == mMaterials[i]->GetName().C_Str()) {
                                 if (name == mMaterials[i]->GetName().C_Str()) {
                                     mesh->mMaterialIndex = static_cast<unsigned int>(i);
                                     mesh->mMaterialIndex = static_cast<unsigned int>(i);
                                 }
                                 }
                             }
                             }
-                            mesh->mTextureCoords[0] = new aiVector3D[group->mTex2dCoords.size()];
-                            for (unsigned int i = 0; i < group->mTex2dCoords.size(); ++i) {
-                                mesh->mTextureCoords[0][i] = aiVector3D(group->mTex2dCoords[i].x, group->mTex2dCoords[i].y, 0);
-                            }
+                            mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
                         }
                         }
                     } 
                     } 
                 }
                 }
             }
             }
 
 
-            aiFace face = ReadTriangle(currentNode);
+            // Load texture coordinates into mesh, when any
+            if (group != nullptr) {
+                size_t i0 = face.mIndices[0];
+                size_t i1 = face.mIndices[1];
+                size_t i2 = face.mIndices[2];
+                mesh->mTextureCoords[0][i0] = aiVector3D(group->mTex2dCoords[texId[0]].x, group->mTex2dCoords[texId[0]].y, 0.0f);
+                mesh->mTextureCoords[0][i1] = aiVector3D(group->mTex2dCoords[texId[1]].x, group->mTex2dCoords[texId[1]].y, 0.0f);
+                mesh->mTextureCoords[0][i2] = aiVector3D(group->mTex2dCoords[texId[2]].x, group->mTex2dCoords[texId[2]].y, 0.0f);
+            }
+
             faces.push_back(face);
             faces.push_back(face);
         }
         }
     }
     }
@@ -578,11 +597,15 @@ aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basemater
 }
 }
 
 
 void XmlSerializer::StoreMaterialsInScene(aiScene *scene) {
 void XmlSerializer::StoreMaterialsInScene(aiScene *scene) {
-    if (nullptr == scene || mMaterials.empty()) {
+    if (nullptr == scene) {
         return;
         return;
     }
     }
 
 
     scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size());
     scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size());
+    if (scene->mNumMaterials == 0) {
+        return;
+    }
+
     scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
     scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
     for (size_t i = 0; i < mMaterials.size(); ++i) {
     for (size_t i = 0; i < mMaterials.size(); ++i) {
         scene->mMaterials[i] = mMaterials[i];
         scene->mMaterials[i] = mMaterials[i];

+ 7 - 9
code/AssetLib/AC/ACLoader.cpp

@@ -146,9 +146,7 @@ AC3DImporter::AC3DImporter() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-AC3DImporter::~AC3DImporter() {
-    // nothing to be done here
-}
+AC3DImporter::~AC3DImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -180,7 +178,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
 
 
     ++mNumMeshes;
     ++mNumMeshes;
 
 
-    objects.push_back(Object());
+    objects.emplace_back();
     Object &obj = objects.back();
     Object &obj = objects.back();
 
 
     aiLight *light = nullptr;
     aiLight *light = nullptr;
@@ -267,7 +265,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
                     --buffer; // make sure the line is processed a second time
                     --buffer; // make sure the line is processed a second time
                     break;
                     break;
                 }
                 }
-                obj.vertices.push_back(aiVector3D());
+                obj.vertices.emplace_back();
                 aiVector3D &v = obj.vertices.back();
                 aiVector3D &v = obj.vertices.back();
                 buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &v.x);
                 buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &v.x);
             }
             }
@@ -293,7 +291,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
                     Q3DWorkAround = true;
                     Q3DWorkAround = true;
                 }
                 }
                 SkipSpaces(&buffer);
                 SkipSpaces(&buffer);
-                obj.surfaces.push_back(Surface());
+                obj.surfaces.emplace_back();
                 Surface &surf = obj.surfaces.back();
                 Surface &surf = obj.surfaces.back();
                 surf.flags = strtoul_cppstyle(buffer);
                 surf.flags = strtoul_cppstyle(buffer);
 
 
@@ -324,7 +322,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
                                 ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: surface references are incomplete");
                                 ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: surface references are incomplete");
                                 break;
                                 break;
                             }
                             }
-                            surf.entries.push_back(Surface::SurfaceEntry());
+                            surf.entries.emplace_back();
                             Surface::SurfaceEntry &entry = surf.entries.back();
                             Surface::SurfaceEntry &entry = surf.entries.back();
 
 
                             entry.first = strtoul10(buffer, &buffer);
                             entry.first = strtoul10(buffer, &buffer);
@@ -786,7 +784,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
 
 
     while (GetNextLine()) {
     while (GetNextLine()) {
         if (TokenMatch(buffer, "MATERIAL", 8)) {
         if (TokenMatch(buffer, "MATERIAL", 8)) {
-            materials.push_back(Material());
+            materials.emplace_back();
             Material &mat = materials.back();
             Material &mat = materials.back();
 
 
             // manually parse the material ... sscanf would use the buldin atof ...
             // manually parse the material ... sscanf would use the buldin atof ...
@@ -813,7 +811,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
     }
     }
     if (materials.empty()) {
     if (materials.empty()) {
         ASSIMP_LOG_WARN("AC3D: No material has been found");
         ASSIMP_LOG_WARN("AC3D: No material has been found");
-        materials.push_back(Material());
+        materials.emplace_back();
     }
     }
 
 
     mNumMeshes += (mNumMeshes >> 2u) + 1;
     mNumMeshes += (mNumMeshes >> 2u) + 1;

+ 5 - 6
code/AssetLib/ASE/ASELoader.cpp

@@ -89,9 +89,7 @@ ASEImporter::ASEImporter() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-ASEImporter::~ASEImporter() {
-    // empty
-}
+ASEImporter::~ASEImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -265,7 +263,7 @@ void ASEImporter::GenerateDefaultMaterial() {
     }
     }
     if (bHas || mParser->m_vMaterials.empty()) {
     if (bHas || mParser->m_vMaterials.empty()) {
         // add a simple material without submaterials to the parser's list
         // add a simple material without submaterials to the parser's list
-        mParser->m_vMaterials.push_back(ASE::Material(AI_DEFAULT_MATERIAL_NAME));
+        mParser->m_vMaterials.emplace_back(AI_DEFAULT_MATERIAL_NAME);
         ASE::Material &mat = mParser->m_vMaterials.back();
         ASE::Material &mat = mParser->m_vMaterials.back();
 
 
         mat.mDiffuse = aiColor3D(0.6f, 0.6f, 0.6f);
         mat.mDiffuse = aiColor3D(0.6f, 0.6f, 0.6f);
@@ -870,6 +868,7 @@ void ASEImporter::ConvertMaterial(ASE::Material &mat) {
         unsigned int iWire = 1;
         unsigned int iWire = 1;
         mat.pcInstance->AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
         mat.pcInstance->AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
     }
     }
+    // fallthrough
     case D3DS::Discreet3DS::Gouraud:
     case D3DS::Discreet3DS::Gouraud:
         eShading = aiShadingMode_Gouraud;
         eShading = aiShadingMode_Gouraud;
         break;
         break;
@@ -1004,8 +1003,8 @@ void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, std::vector<aiMesh *> &avOutMes
                                             blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end(); ++blubb) {
                                             blubb != mesh.mBoneVertices[iIndex2].mBoneWeights.end(); ++blubb) {
 
 
                                         // NOTE: illegal cases have already been filtered out
                                         // NOTE: illegal cases have already been filtered out
-                                        avOutputBones[(*blubb).first].push_back(std::pair<unsigned int, float>(
-                                                iBase, (*blubb).second));
+                                        avOutputBones[(*blubb).first].emplace_back(
+                                                iBase, (*blubb).second);
                                     }
                                     }
                                 }
                                 }
                             }
                             }

+ 18 - 13
code/AssetLib/ASE/ASEParser.cpp

@@ -74,7 +74,7 @@ using namespace Assimp::ASE;
             return;                                \
             return;                                \
         }                                          \
         }                                          \
     }                                              \
     }                                              \
-    else if ('\0' == *filePtr) {                   \
+    if ('\0' == *filePtr) {                        \
         return;                                    \
         return;                                    \
     }                                              \
     }                                              \
     if (IsLineEnd(*filePtr) && !bLastWasEndLine) { \
     if (IsLineEnd(*filePtr) && !bLastWasEndLine) { \
@@ -264,7 +264,7 @@ void Parser::Parse() {
             if (TokenMatch(filePtr, "GEOMOBJECT", 10))
             if (TokenMatch(filePtr, "GEOMOBJECT", 10))
 
 
             {
             {
-                m_vMeshes.push_back(Mesh("UNNAMED"));
+                m_vMeshes.emplace_back("UNNAMED");
                 ParseLV1ObjectBlock(m_vMeshes.back());
                 ParseLV1ObjectBlock(m_vMeshes.back());
                 continue;
                 continue;
             }
             }
@@ -272,7 +272,7 @@ void Parser::Parse() {
             if (TokenMatch(filePtr, "HELPEROBJECT", 12))
             if (TokenMatch(filePtr, "HELPEROBJECT", 12))
 
 
             {
             {
-                m_vDummies.push_back(Dummy());
+                m_vDummies.emplace_back();
                 ParseLV1ObjectBlock(m_vDummies.back());
                 ParseLV1ObjectBlock(m_vDummies.back());
                 continue;
                 continue;
             }
             }
@@ -280,13 +280,13 @@ void Parser::Parse() {
             if (TokenMatch(filePtr, "LIGHTOBJECT", 11))
             if (TokenMatch(filePtr, "LIGHTOBJECT", 11))
 
 
             {
             {
-                m_vLights.push_back(Light("UNNAMED"));
+                m_vLights.emplace_back("UNNAMED");
                 ParseLV1ObjectBlock(m_vLights.back());
                 ParseLV1ObjectBlock(m_vLights.back());
                 continue;
                 continue;
             }
             }
             // camera object
             // camera object
             if (TokenMatch(filePtr, "CAMERAOBJECT", 12)) {
             if (TokenMatch(filePtr, "CAMERAOBJECT", 12)) {
-                m_vCameras.push_back(Camera("UNNAMED"));
+                m_vCameras.emplace_back("UNNAMED");
                 ParseLV1ObjectBlock(m_vCameras.back());
                 ParseLV1ObjectBlock(m_vCameras.back());
                 continue;
                 continue;
             }
             }
@@ -385,7 +385,7 @@ void Parser::ParseLV1SoftSkinBlock() {
                         unsigned int numWeights;
                         unsigned int numWeights;
                         ParseLV4MeshLong(numWeights);
                         ParseLV4MeshLong(numWeights);
 
 
-                        curMesh->mBoneVertices.push_back(ASE::BoneVertex());
+                        curMesh->mBoneVertices.emplace_back();
                         ASE::BoneVertex &vert = curMesh->mBoneVertices.back();
                         ASE::BoneVertex &vert = curMesh->mBoneVertices.back();
 
 
                         // Reserve enough storage
                         // Reserve enough storage
@@ -409,7 +409,7 @@ void Parser::ParseLV1SoftSkinBlock() {
                             if (-1 == me.first) {
                             if (-1 == me.first) {
                                 // We don't have this bone yet, so add it to the list
                                 // We don't have this bone yet, so add it to the list
                                 me.first = static_cast<int>(curMesh->mBones.size());
                                 me.first = static_cast<int>(curMesh->mBones.size());
-                                curMesh->mBones.push_back(ASE::Bone(bone));
+                                curMesh->mBones.emplace_back(bone);
                             }
                             }
                             ParseLV4MeshFloat(me.second);
                             ParseLV4MeshFloat(me.second);
 
 
@@ -420,6 +420,8 @@ void Parser::ParseLV1SoftSkinBlock() {
                 }
                 }
             }
             }
         }
         }
+        if (*filePtr == '\0')
+            return;
         ++filePtr;
         ++filePtr;
         SkipSpacesAndLineEnd(&filePtr);
         SkipSpacesAndLineEnd(&filePtr);
     }
     }
@@ -646,10 +648,13 @@ void Parser::ParseLV2MaterialBlock(ASE::Material &mat) {
                 }
                 }
 
 
                 // get a reference to the material
                 // get a reference to the material
-                Material &sMat = mat.avSubMaterials[iIndex];
+                if (iIndex < mat.avSubMaterials.size()) {
+                    Material &sMat = mat.avSubMaterials[iIndex];
+
+                    // parse the material block
+                    ParseLV2MaterialBlock(sMat);
+                }
 
 
-                // parse the material block
-                ParseLV2MaterialBlock(sMat);
                 continue;
                 continue;
             }
             }
         }
         }
@@ -1006,7 +1011,7 @@ void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation &anim) {
                 anim.mScalingType = ASE::Animation::TCB;
                 anim.mScalingType = ASE::Animation::TCB;
             }
             }
             if (b) {
             if (b) {
-                anim.akeyScaling.push_back(aiVectorKey());
+                anim.akeyScaling.emplace_back();
                 aiVectorKey &key = anim.akeyScaling.back();
                 aiVectorKey &key = anim.akeyScaling.back();
                 ParseLV4MeshFloatTriple(&key.mValue.x, iIndex);
                 ParseLV4MeshFloatTriple(&key.mValue.x, iIndex);
                 key.mTime = (double)iIndex;
                 key.mTime = (double)iIndex;
@@ -1045,7 +1050,7 @@ void Parser::ParseLV3PosAnimationBlock(ASE::Animation &anim) {
                 anim.mPositionType = ASE::Animation::TCB;
                 anim.mPositionType = ASE::Animation::TCB;
             }
             }
             if (b) {
             if (b) {
-                anim.akeyPositions.push_back(aiVectorKey());
+                anim.akeyPositions.emplace_back();
                 aiVectorKey &key = anim.akeyPositions.back();
                 aiVectorKey &key = anim.akeyPositions.back();
                 ParseLV4MeshFloatTriple(&key.mValue.x, iIndex);
                 ParseLV4MeshFloatTriple(&key.mValue.x, iIndex);
                 key.mTime = (double)iIndex;
                 key.mTime = (double)iIndex;
@@ -1084,7 +1089,7 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation &anim) {
                 anim.mRotationType = ASE::Animation::TCB;
                 anim.mRotationType = ASE::Animation::TCB;
             }
             }
             if (b) {
             if (b) {
-                anim.akeyRotations.push_back(aiQuatKey());
+                anim.akeyRotations.emplace_back();
                 aiQuatKey &key = anim.akeyRotations.back();
                 aiQuatKey &key = anim.akeyRotations.back();
                 aiVector3D v;
                 aiVector3D v;
                 ai_real f;
                 ai_real f;

+ 1 - 1
code/AssetLib/ASE/ASEParser.h

@@ -116,7 +116,7 @@ struct Material : public D3DS::Material {
         return *this;
         return *this;
     }
     }
 
 
-    ~Material() {}
+    ~Material() = default;
 
 
     //! Contains all sub materials of this material
     //! Contains all sub materials of this material
     std::vector<Material> avSubMaterials;
     std::vector<Material> avSubMaterials;

+ 9 - 5
code/AssetLib/Assbin/AssbinFileWriter.cpp

@@ -130,7 +130,7 @@ inline size_t Write<double>(IOStream *stream, const double &f) {
 // Serialize a vec3
 // Serialize a vec3
 template <>
 template <>
 inline size_t Write<aiVector3D>(IOStream *stream, const aiVector3D &v) {
 inline size_t Write<aiVector3D>(IOStream *stream, const aiVector3D &v) {
-    size_t t = Write<float>(stream, v.x);
+    size_t t = Write<ai_real>(stream, v.x);
     t += Write<float>(stream, v.y);
     t += Write<float>(stream, v.y);
     t += Write<float>(stream, v.z);
     t += Write<float>(stream, v.z);
 
 
@@ -141,7 +141,7 @@ inline size_t Write<aiVector3D>(IOStream *stream, const aiVector3D &v) {
 // Serialize a color value
 // Serialize a color value
 template <>
 template <>
 inline size_t Write<aiColor3D>(IOStream *stream, const aiColor3D &v) {
 inline size_t Write<aiColor3D>(IOStream *stream, const aiColor3D &v) {
-    size_t t = Write<float>(stream, v.r);
+    size_t t = Write<ai_real>(stream, v.r);
     t += Write<float>(stream, v.g);
     t += Write<float>(stream, v.g);
     t += Write<float>(stream, v.b);
     t += Write<float>(stream, v.b);
 
 
@@ -152,7 +152,7 @@ inline size_t Write<aiColor3D>(IOStream *stream, const aiColor3D &v) {
 // Serialize a color value
 // Serialize a color value
 template <>
 template <>
 inline size_t Write<aiColor4D>(IOStream *stream, const aiColor4D &v) {
 inline size_t Write<aiColor4D>(IOStream *stream, const aiColor4D &v) {
-    size_t t = Write<float>(stream, v.r);
+    size_t t = Write<ai_real>(stream, v.r);
     t += Write<float>(stream, v.g);
     t += Write<float>(stream, v.g);
     t += Write<float>(stream, v.b);
     t += Write<float>(stream, v.b);
     t += Write<float>(stream, v.a);
     t += Write<float>(stream, v.a);
@@ -164,7 +164,7 @@ inline size_t Write<aiColor4D>(IOStream *stream, const aiColor4D &v) {
 // Serialize a quaternion
 // Serialize a quaternion
 template <>
 template <>
 inline size_t Write<aiQuaternion>(IOStream *stream, const aiQuaternion &v) {
 inline size_t Write<aiQuaternion>(IOStream *stream, const aiQuaternion &v) {
-    size_t t = Write<float>(stream, v.w);
+    size_t t = Write<ai_real>(stream, v.w);
     t += Write<float>(stream, v.x);
     t += Write<float>(stream, v.x);
     t += Write<float>(stream, v.y);
     t += Write<float>(stream, v.y);
     t += Write<float>(stream, v.z);
     t += Write<float>(stream, v.z);
@@ -190,7 +190,7 @@ template <>
 inline size_t Write<aiMatrix4x4>(IOStream *stream, const aiMatrix4x4 &m) {
 inline size_t Write<aiMatrix4x4>(IOStream *stream, const aiMatrix4x4 &m) {
     for (unsigned int i = 0; i < 4; ++i) {
     for (unsigned int i = 0; i < 4; ++i) {
         for (unsigned int i2 = 0; i2 < 4; ++i2) {
         for (unsigned int i2 = 0; i2 < 4; ++i2) {
-            Write<float>(stream, m[i][i2]);
+            Write<ai_real>(stream, m[i][i2]);
         }
         }
     }
     }
 
 
@@ -642,6 +642,10 @@ protected:
         Write<aiString>(&chunk, l->mName);
         Write<aiString>(&chunk, l->mName);
         Write<unsigned int>(&chunk, l->mType);
         Write<unsigned int>(&chunk, l->mType);
 
 
+        Write<aiVector3D>(&chunk, l->mPosition);
+        Write<aiVector3D>(&chunk, l->mDirection);
+        Write<aiVector3D>(&chunk, l->mUp);
+
         if (l->mType != aiLightSource_DIRECTIONAL) {
         if (l->mType != aiLightSource_DIRECTIONAL) {
             Write<float>(&chunk, l->mAttenuationConstant);
             Write<float>(&chunk, l->mAttenuationConstant);
             Write<float>(&chunk, l->mAttenuationLinear);
             Write<float>(&chunk, l->mAttenuationLinear);

+ 4 - 0
code/AssetLib/Assbin/AssbinLoader.cpp

@@ -556,6 +556,10 @@ void AssbinImporter::ReadBinaryLight(IOStream *stream, aiLight *l) {
     l->mName = Read<aiString>(stream);
     l->mName = Read<aiString>(stream);
     l->mType = (aiLightSourceType)Read<unsigned int>(stream);
     l->mType = (aiLightSourceType)Read<unsigned int>(stream);
 
 
+    l->mPosition = Read<aiVector3D>(stream);
+    l->mDirection = Read<aiVector3D>(stream);
+    l->mUp = Read<aiVector3D>(stream);
+
     if (l->mType != aiLightSource_DIRECTIONAL) {
     if (l->mType != aiLightSource_DIRECTIONAL) {
         l->mAttenuationConstant = Read<float>(stream);
         l->mAttenuationConstant = Read<float>(stream);
         l->mAttenuationLinear = Read<float>(stream);
         l->mAttenuationLinear = Read<float>(stream);

+ 1 - 1
code/AssetLib/Assjson/mesh_splitter.cpp

@@ -304,7 +304,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std:
 		}
 		}
 
 
 		// add the newly created mesh to the list
 		// add the newly created mesh to the list
-		source_mesh_map.push_back(std::make_pair(out_mesh,a));
+		source_mesh_map.emplace_back(out_mesh,a);
 
 
 		if (base == in_mesh->mNumFaces) {
 		if (base == in_mesh->mNumFaces) {
 			break;
 			break;

+ 1 - 1
code/AssetLib/Assxml/AssxmlFileWriter.cpp

@@ -365,7 +365,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
 
 
                 ioprintf(io, "\t\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%u\"",
                 ioprintf(io, "\t\t\t<MatProperty key=\"%s\" \n\t\t\ttype=\"%s\" tex_usage=\"%s\" tex_index=\"%u\"",
                         prop->mKey.data, sz,
                         prop->mKey.data, sz,
-                        ::TextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex);
+                        ::aiTextureTypeToString((aiTextureType)prop->mSemantic), prop->mIndex);
 
 
                 if (prop->mType == aiPTI_Float) {
                 if (prop->mType == aiPTI_Float) {
                     ioprintf(io, " size=\"%i\">\n\t\t\t\t",
                     ioprintf(io, " size=\"%i\">\n\t\t\t\t",

+ 5 - 7
code/AssetLib/B3D/B3DImporter.cpp

@@ -88,9 +88,7 @@ void DeleteAllBarePointers(std::vector<T> &x) {
     }
     }
 }
 }
 
 
-B3DImporter::~B3DImporter() {
-    // empty
-}
+B3DImporter::~B3DImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 bool B3DImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
 bool B3DImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
@@ -479,13 +477,13 @@ void B3DImporter::ReadKEYS(aiNodeAnim *nodeAnim) {
     while (ChunkSize()) {
     while (ChunkSize()) {
         int frame = ReadInt();
         int frame = ReadInt();
         if (flags & 1) {
         if (flags & 1) {
-            trans.push_back(aiVectorKey(frame, ReadVec3()));
+            trans.emplace_back(frame, ReadVec3());
         }
         }
         if (flags & 2) {
         if (flags & 2) {
-            scale.push_back(aiVectorKey(frame, ReadVec3()));
+            scale.emplace_back(frame, ReadVec3());
         }
         }
         if (flags & 4) {
         if (flags & 4) {
-            rot.push_back(aiQuatKey(frame, ReadQuat()));
+            rot.emplace_back(frame, ReadQuat());
         }
         }
     }
     }
 
 
@@ -673,7 +671,7 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
                         int bone = v.bones[k];
                         int bone = v.bones[k];
                         float weight = v.weights[k];
                         float weight = v.weights[k];
 
 
-                        vweights[bone].push_back(aiVertexWeight(vertIdx + faceIndex, weight));
+                        vweights[bone].emplace_back(vertIdx + faceIndex, weight);
                     }
                     }
                 }
                 }
                 ++face;
                 ++face;

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

@@ -88,7 +88,7 @@ BVHLoader::BVHLoader() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-BVHLoader::~BVHLoader() {}
+BVHLoader::~BVHLoader() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -186,7 +186,7 @@ aiNode *BVHLoader::ReadNode() {
     std::vector<aiNode *> childNodes;
     std::vector<aiNode *> childNodes;
 
 
     // and create an bone entry for it
     // and create an bone entry for it
-    mNodes.push_back(Node(node));
+    mNodes.emplace_back(node);
     Node &internNode = mNodes.back();
     Node &internNode = mNodes.back();
 
 
     // now read the node's contents
     // now read the node's contents

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

@@ -325,10 +325,10 @@ void SectionParser ::Next() {
     stream.SetCurrentPos(current.start + current.size);
     stream.SetCurrentPos(current.start + current.size);
 
 
     const char tmp[] = {
     const char tmp[] = {
-        (const char)stream.GetI1(),
-        (const char)stream.GetI1(),
-        (const char)stream.GetI1(),
-        (const char)stream.GetI1()
+        (char)stream.GetI1(),
+        (char)stream.GetI1(),
+        (char)stream.GetI1(),
+        (char)stream.GetI1()
     };
     };
     current.id = std::string(tmp, tmp[3] ? 4 : tmp[2] ? 3 : tmp[1] ? 2 : 1);
     current.id = std::string(tmp, tmp[3] ? 4 : tmp[2] ? 3 : tmp[1] ? 2 : 1);
 
 

+ 2 - 2
code/AssetLib/Blender/BlenderDNA.h

@@ -416,10 +416,10 @@ template <>
 struct Structure::_defaultInitializer<ErrorPolicy_Fail> {
 struct Structure::_defaultInitializer<ErrorPolicy_Fail> {
 
 
     template <typename T>
     template <typename T>
-    void operator()(T & /*out*/, const char * = "") {
+    void operator()(T & /*out*/, const char *message = "") {
         // obviously, it is crucial that _DefaultInitializer is used
         // obviously, it is crucial that _DefaultInitializer is used
         // only from within a catch clause.
         // only from within a catch clause.
-        throw DeadlyImportError("Constructing BlenderDNA Structure encountered an error");
+        throw DeadlyImportError("Constructing BlenderDNA Structure encountered an error: ", message);
     }
     }
 };
 };
 
 

+ 1 - 2
code/AssetLib/Blender/BlenderIntermediate.h

@@ -65,8 +65,7 @@ namespace Blender {
     struct TempArray    {
     struct TempArray    {
         typedef TCLASS< T*,std::allocator<T*> > mywrap;
         typedef TCLASS< T*,std::allocator<T*> > mywrap;
 
 
-        TempArray() {
-        }
+        TempArray() = default;
 
 
         ~TempArray () {
         ~TempArray () {
             for(T* elem : arr) {
             for(T* elem : arr) {

+ 2 - 2
code/AssetLib/Blender/BlenderLoader.cpp

@@ -281,7 +281,7 @@ void BlenderImporter::ExtractScene(Scene &out, const FileDatabase &file) {
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void BlenderImporter::ParseSubCollection(const Blender::Scene &in, aiNode *root, std::shared_ptr<Collection> collection, ConversionData &conv_data) {
+void BlenderImporter::ParseSubCollection(const Blender::Scene &in, aiNode *root, const std::shared_ptr<Collection>& collection, ConversionData &conv_data) {
 
 
     std::deque<Object *> root_objects;
     std::deque<Object *> root_objects;
     // Count number of objects
     // Count number of objects
@@ -986,7 +986,7 @@ void BlenderImporter::ConvertMesh(const Scene & /*in*/, const Object * /*obj*/,
     // key is material number, value is the TextureUVMapping for the material
     // key is material number, value is the TextureUVMapping for the material
     typedef std::map<uint32_t, TextureUVMapping> MaterialTextureUVMappings;
     typedef std::map<uint32_t, TextureUVMapping> MaterialTextureUVMappings;
     MaterialTextureUVMappings matTexUvMappings;
     MaterialTextureUVMappings matTexUvMappings;
-    const uint32_t maxMat = static_cast<const uint32_t>(mesh->mat.size());
+    const uint32_t maxMat = static_cast<uint32_t>(mesh->mat.size());
     for (uint32_t m = 0; m < maxMat; ++m) {
     for (uint32_t m = 0; m < maxMat; ++m) {
         // get material by index
         // get material by index
         const std::shared_ptr<Material> pMat = mesh->mat[m];
         const std::shared_ptr<Material> pMat = mesh->mat[m];

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

@@ -117,7 +117,7 @@ protected:
     void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
     void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
     void ParseBlendFile(Blender::FileDatabase &out, std::shared_ptr<IOStream> stream);
     void ParseBlendFile(Blender::FileDatabase &out, std::shared_ptr<IOStream> stream);
     void ExtractScene(Blender::Scene &out, const Blender::FileDatabase &file);
     void ExtractScene(Blender::Scene &out, const Blender::FileDatabase &file);
-    void ParseSubCollection(const Blender::Scene &in, aiNode *root, std::shared_ptr<Blender::Collection> collection, Blender::ConversionData &conv_data);
+    void ParseSubCollection(const Blender::Scene &in, aiNode *root, const std::shared_ptr<Blender::Collection>& collection, Blender::ConversionData &conv_data);
     void ConvertBlendFile(aiScene *out, const Blender::Scene &in, const Blender::FileDatabase &file);
     void ConvertBlendFile(aiScene *out, const Blender::Scene &in, const Blender::FileDatabase &file);
 
 
 private:
 private:

+ 3 - 6
code/AssetLib/Blender/BlenderModifier.cpp

@@ -71,10 +71,6 @@ static const fpCreateModifier creators[] = {
     nullptr // sentinel
     nullptr // sentinel
 };
 };
 
 
-// ------------------------------------------------------------------------------------------------
-struct SharedModifierData : ElemBase {
-    ModifierData modifier;
-};
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_data, const Scene &in, const Object &orig_object) {
 void BlenderModifierShowcase::ApplyModifiers(aiNode &out, ConversionData &conv_data, const Scene &in, const Object &orig_object) {
@@ -157,6 +153,7 @@ void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const
     // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
     // hijacking the ABI, see the big note in BlenderModifierShowcase::ApplyModifiers()
     const MirrorModifierData &mir = static_cast<const MirrorModifierData &>(orig_modifier);
     const MirrorModifierData &mir = static_cast<const MirrorModifierData &>(orig_modifier);
     ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
     ai_assert(mir.modifier.type == ModifierData::eModifierType_Mirror);
+    std::shared_ptr<Object> mirror_ob = mir.mirror_ob.lock();
 
 
     conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
     conv_data.meshes->reserve(conv_data.meshes->size() + out.mNumMeshes);
 
 
@@ -171,8 +168,8 @@ void BlenderModifier_Mirror ::DoIt(aiNode &out, ConversionData &conv_data, const
         const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
         const float ys = mir.flag & MirrorModifierData::Flags_AXIS_Y ? -1.f : 1.f;
         const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
         const float zs = mir.flag & MirrorModifierData::Flags_AXIS_Z ? -1.f : 1.f;
 
 
-        if (mir.mirror_ob) {
-            const aiVector3D center(mir.mirror_ob->obmat[3][0], mir.mirror_ob->obmat[3][1], mir.mirror_ob->obmat[3][2]);
+        if (mirror_ob) {
+            const aiVector3D center(mirror_ob->obmat[3][0], mirror_ob->obmat[3][1], mirror_ob->obmat[3][2]);
             for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
             for (unsigned int j = 0; j < mesh->mNumVertices; ++j) {
                 aiVector3D &v = mesh->mVertices[j];
                 aiVector3D &v = mesh->mVertices[j];
 
 

+ 12 - 6
code/AssetLib/Blender/BlenderScene.cpp

@@ -624,7 +624,9 @@ void Structure ::Convert<ListBase>(
         const FileDatabase &db) const {
         const FileDatabase &db) const {
 
 
     ReadFieldPtr<ErrorPolicy_Igno>(dest.first, "*first", db);
     ReadFieldPtr<ErrorPolicy_Igno>(dest.first, "*first", db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.last, "*last", db);
+    std::shared_ptr<ElemBase> last;
+    ReadFieldPtr<ErrorPolicy_Igno>(last, "*last", db);
+    dest.last = last;
 
 
     db.reader->IncPtr(size);
     db.reader->IncPtr(size);
 }
 }
@@ -648,7 +650,9 @@ void Structure ::Convert<ModifierData>(
         const FileDatabase &db) const {
         const FileDatabase &db) const {
 
 
     ReadFieldPtr<ErrorPolicy_Warn>(dest.next, "*next", db);
     ReadFieldPtr<ErrorPolicy_Warn>(dest.next, "*next", db);
-    ReadFieldPtr<ErrorPolicy_Warn>(dest.prev, "*prev", db);
+    std::shared_ptr<ElemBase> prev;
+    ReadFieldPtr<ErrorPolicy_Warn>(prev, "*prev", db);
+    dest.prev = prev;
     ReadField<ErrorPolicy_Igno>(dest.type, "type", db);
     ReadField<ErrorPolicy_Igno>(dest.type, "type", db);
     ReadField<ErrorPolicy_Igno>(dest.mode, "mode", db);
     ReadField<ErrorPolicy_Igno>(dest.mode, "mode", db);
     ReadFieldArray<ErrorPolicy_Igno>(dest.name, "name", db);
     ReadFieldArray<ErrorPolicy_Igno>(dest.name, "name", db);
@@ -772,7 +776,9 @@ void Structure ::Convert<MirrorModifierData>(
     ReadField<ErrorPolicy_Igno>(dest.axis, "axis", db);
     ReadField<ErrorPolicy_Igno>(dest.axis, "axis", db);
     ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
     ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
     ReadField<ErrorPolicy_Igno>(dest.tolerance, "tolerance", db);
     ReadField<ErrorPolicy_Igno>(dest.tolerance, "tolerance", db);
-    ReadFieldPtr<ErrorPolicy_Igno>(dest.mirror_ob, "*mirror_ob", db);
+    std::shared_ptr<Object> mirror_ob;
+    ReadFieldPtr<ErrorPolicy_Igno>(mirror_ob, "*mirror_ob", db);
+    dest.mirror_ob = mirror_ob;
 
 
     db.reader->IncPtr(size);
     db.reader->IncPtr(size);
 }
 }
@@ -833,9 +839,9 @@ void Structure::Convert<CustomDataLayer>(
     ReadField<ErrorPolicy_Fail>(dest.flag, "flag", db);
     ReadField<ErrorPolicy_Fail>(dest.flag, "flag", db);
     ReadField<ErrorPolicy_Fail>(dest.active, "active", db);
     ReadField<ErrorPolicy_Fail>(dest.active, "active", db);
     ReadField<ErrorPolicy_Fail>(dest.active_rnd, "active_rnd", db);
     ReadField<ErrorPolicy_Fail>(dest.active_rnd, "active_rnd", db);
-    ReadField<ErrorPolicy_Fail>(dest.active_clone, "active_clone", db);
-    ReadField<ErrorPolicy_Fail>(dest.active_mask, "active_mask", db);
-    ReadField<ErrorPolicy_Fail>(dest.uid, "uid", db);
+    ReadField<ErrorPolicy_Warn>(dest.active_clone, "active_clone", db);
+    ReadField<ErrorPolicy_Warn>(dest.active_mask, "active_mask", db);
+    ReadField<ErrorPolicy_Warn>(dest.uid, "uid", db);
     ReadFieldArray<ErrorPolicy_Warn>(dest.name, "name", db);
     ReadFieldArray<ErrorPolicy_Warn>(dest.name, "name", db);
     ReadCustomDataPtr<ErrorPolicy_Fail>(dest.data, dest.type, "*data", db);
     ReadCustomDataPtr<ErrorPolicy_Fail>(dest.data, dest.type, "*data", db);
 
 

+ 12 - 8
code/AssetLib/Blender/BlenderScene.h

@@ -124,7 +124,7 @@ struct ID : ElemBase {
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 struct ListBase : ElemBase {
 struct ListBase : ElemBase {
     std::shared_ptr<ElemBase> first;
     std::shared_ptr<ElemBase> first;
-    std::shared_ptr<ElemBase> last;
+    std::weak_ptr<ElemBase> last;
 };
 };
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
@@ -642,14 +642,21 @@ struct ModifierData : ElemBase {
     };
     };
 
 
     std::shared_ptr<ElemBase> next WARN;
     std::shared_ptr<ElemBase> next WARN;
-    std::shared_ptr<ElemBase> prev WARN;
+    std::weak_ptr<ElemBase> prev WARN;
 
 
     int type, mode;
     int type, mode;
     char name[32];
     char name[32];
 };
 };
 
 
+
+// ------------------------------------------------------------------------------------------------
+struct SharedModifierData : ElemBase {
+    ModifierData modifier;
+};
+
+
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
-struct SubsurfModifierData : ElemBase {
+struct SubsurfModifierData : SharedModifierData {
 
 
     enum Type {
     enum Type {
 
 
@@ -662,7 +669,6 @@ struct SubsurfModifierData : ElemBase {
         FLAGS_SubsurfUV = 1 << 3
         FLAGS_SubsurfUV = 1 << 3
     };
     };
 
 
-    ModifierData modifier FAIL;
     short subdivType WARN;
     short subdivType WARN;
     short levels FAIL;
     short levels FAIL;
     short renderLevels;
     short renderLevels;
@@ -670,7 +676,7 @@ struct SubsurfModifierData : ElemBase {
 };
 };
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
-struct MirrorModifierData : ElemBase {
+struct MirrorModifierData : SharedModifierData {
 
 
     enum Flags {
     enum Flags {
         Flags_CLIPPING = 1 << 0,
         Flags_CLIPPING = 1 << 0,
@@ -682,11 +688,9 @@ struct MirrorModifierData : ElemBase {
         Flags_VGROUP = 1 << 6
         Flags_VGROUP = 1 << 6
     };
     };
 
 
-    ModifierData modifier FAIL;
-
     short axis, flag;
     short axis, flag;
     float tolerance;
     float tolerance;
-    std::shared_ptr<Object> mirror_ob;
+    std::weak_ptr<Object> mirror_ob;
 };
 };
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------

+ 1 - 3
code/AssetLib/Blender/BlenderTessellator.cpp

@@ -274,9 +274,7 @@ BlenderTessellatorP2T::BlenderTessellatorP2T( BlenderBMeshConverter& converter )
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-BlenderTessellatorP2T::~BlenderTessellatorP2T( )
-{
-}
+
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
 void BlenderTessellatorP2T::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )

+ 1 - 1
code/AssetLib/Blender/BlenderTessellator.h

@@ -186,7 +186,7 @@ namespace Assimp
     {
     {
     public:
     public:
         BlenderTessellatorP2T( BlenderBMeshConverter& converter );
         BlenderTessellatorP2T( BlenderBMeshConverter& converter );
-        ~BlenderTessellatorP2T( );
+        ~BlenderTessellatorP2T( ) = default;
 
 
         void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
         void Tessellate( const Blender::MLoop* polyLoop, int vertexCount, const std::vector< Blender::MVert >& vertices );
 
 

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

@@ -91,15 +91,11 @@ static const aiImporterDesc desc = {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
-COBImporter::COBImporter() {
-    // empty
-}
+COBImporter::COBImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-COBImporter::~COBImporter() {
-    // empty
-}
+COBImporter::~COBImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -522,7 +518,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
         return;
         return;
     }
     }
 
 
-    out.materials.push_back(Material());
+    out.materials.emplace_back();
     Material &mat = out.materials.back();
     Material &mat = out.materials.back();
     mat = nfo;
     mat = nfo;
 
 
@@ -753,7 +749,7 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk
                     ThrowException("Expected Face line");
                     ThrowException("Expected Face line");
                 }
                 }
 
 
-                msh.faces.push_back(Face());
+                msh.faces.emplace_back();
                 Face &face = msh.faces.back();
                 Face &face = msh.faces.back();
 
 
                 face.indices.resize(strtoul10(splitter[2]));
                 face.indices.resize(strtoul10(splitter[2]));
@@ -956,7 +952,7 @@ void COBImporter::ReadPolH_Binary(COB::Scene &out, StreamReaderLE &reader, const
                 ThrowException(format("A hole is the first entity in the `PolH` chunk with id ") << nfo.id);
                 ThrowException(format("A hole is the first entity in the `PolH` chunk with id ") << nfo.id);
             }
             }
         } else
         } else
-            msh.faces.push_back(Face());
+            msh.faces.emplace_back();
         Face &f = msh.faces.back();
         Face &f = msh.faces.back();
 
 
         const size_t num = reader.GetI2();
         const size_t num = reader.GetI2();
@@ -968,7 +964,7 @@ void COBImporter::ReadPolH_Binary(COB::Scene &out, StreamReaderLE &reader, const
         }
         }
 
 
         for (size_t x = 0; x < num; ++x) {
         for (size_t x = 0; x < num; ++x) {
-            f.indices.push_back(VertexIndex());
+            f.indices.emplace_back();
 
 
             VertexIndex &v = f.indices.back();
             VertexIndex &v = f.indices.back();
             v.pos_idx = reader.GetI4();
             v.pos_idx = reader.GetI4();
@@ -1008,7 +1004,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
 
 
     const chunk_guard cn(nfo, reader);
     const chunk_guard cn(nfo, reader);
 
 
-    out.materials.push_back(Material());
+    out.materials.emplace_back();
     Material &mat = out.materials.back();
     Material &mat = out.materials.back();
     mat = nfo;
     mat = nfo;
 
 

+ 1 - 1
code/AssetLib/COB/COBScene.h

@@ -107,7 +107,7 @@ struct Node : public ChunkInfo
         TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE
         TYPE_MESH,TYPE_GROUP,TYPE_LIGHT,TYPE_CAMERA,TYPE_BONE
     };
     };
 
 
-    virtual ~Node() {}
+    virtual ~Node() = default;
     Node(Type type) : type(type), unit_scale(1.f){}
     Node(Type type) : type(type), unit_scale(1.f){}
 
 
     Type type;
     Type type;

+ 1 - 2
code/AssetLib/CSM/CSMLoader.cpp

@@ -85,8 +85,7 @@ CSMImporter::CSMImporter()
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-CSMImporter::~CSMImporter()
-{}
+CSMImporter::~CSMImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.

+ 3 - 4
code/AssetLib/Collada/ColladaExporter.cpp

@@ -154,8 +154,7 @@ ColladaExporter::ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, con
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor
 // Destructor
-ColladaExporter::~ColladaExporter() {
-}
+ColladaExporter::~ColladaExporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Starts writing the contents
 // Starts writing the contents
@@ -1330,9 +1329,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) {
             std::vector<std::string> names;
             std::vector<std::string> names;
             for (size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
             for (size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
                 if (nodeAnim->mPreState == aiAnimBehaviour_DEFAULT || nodeAnim->mPreState == aiAnimBehaviour_LINEAR || nodeAnim->mPreState == aiAnimBehaviour_REPEAT) {
                 if (nodeAnim->mPreState == aiAnimBehaviour_DEFAULT || nodeAnim->mPreState == aiAnimBehaviour_LINEAR || nodeAnim->mPreState == aiAnimBehaviour_REPEAT) {
-                    names.push_back("LINEAR");
+                    names.emplace_back("LINEAR");
                 } else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) {
                 } else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) {
-                    names.push_back("STEP");
+                    names.emplace_back("STEP");
                 }
                 }
             }
             }
 
 

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

@@ -233,7 +233,7 @@ public:
         Surface ambient, diffuse, specular, emissive, reflective, transparent, normal;
         Surface ambient, diffuse, specular, emissive, reflective, transparent, normal;
         Property shininess, transparency, index_refraction;
         Property shininess, transparency, index_refraction;
 
 
-        Material() {}
+        Material() = default;
     };
     };
 
 
     std::map<unsigned int, std::string> textures;
     std::map<unsigned int, std::string> textures;

+ 5 - 0
code/AssetLib/Collada/ColladaHelper.h

@@ -621,6 +621,11 @@ struct Animation {
 
 
         for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
         for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
             Animation *anim = *it;
             Animation *anim = *it;
+            // Assign the first animation name to the parent if empty.
+            // This prevents the animation name from being lost when animations are combined
+            if (mName.empty()) {
+              mName = anim->mName;
+            }
             CombineSingleChannelAnimationsRecursively(anim);
             CombineSingleChannelAnimationsRecursively(anim);
 
 
             if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 &&
             if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 &&

+ 7 - 6
code/AssetLib/Collada/ColladaLoader.cpp

@@ -102,6 +102,7 @@ ColladaLoader::ColladaLoader() :
         mTextures(),
         mTextures(),
         mAnims(),
         mAnims(),
         noSkeletonMesh(false),
         noSkeletonMesh(false),
+        removeEmptyBones(false),
         ignoreUpDirection(false),
         ignoreUpDirection(false),
         useColladaName(false),
         useColladaName(false),
         mNodeNameCounter(0) {
         mNodeNameCounter(0) {
@@ -110,9 +111,7 @@ ColladaLoader::ColladaLoader() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-ColladaLoader::~ColladaLoader() {
-    // empty
-}
+ColladaLoader::~ColladaLoader() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -130,6 +129,7 @@ bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void ColladaLoader::SetupProperties(const Importer *pImp) {
 void ColladaLoader::SetupProperties(const Importer *pImp) {
     noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0;
     noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0;
+    removeEmptyBones = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true) != 0;
     ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION, 0) != 0;
     ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION, 0) != 0;
     useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 0) != 0;
     useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 0) != 0;
 }
 }
@@ -798,9 +798,10 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
         // count the number of bones which influence vertices of the current submesh
         // count the number of bones which influence vertices of the current submesh
         size_t numRemainingBones = 0;
         size_t numRemainingBones = 0;
         for (const auto & dstBone : dstBones) {
         for (const auto & dstBone : dstBones) {
-            if (!dstBone.empty()) {
-                ++numRemainingBones;
+            if (dstBone.empty() && removeEmptyBones) {
+                continue;
             }
             }
+            ++numRemainingBones;
         }
         }
 
 
         // create bone array and copy bone weights one by one
         // create bone array and copy bone weights one by one
@@ -809,7 +810,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
         size_t boneCount = 0;
         size_t boneCount = 0;
         for (size_t a = 0; a < numBones; ++a) {
         for (size_t a = 0; a < numBones; ++a) {
             // omit bones without weights
             // omit bones without weights
-            if (dstBones[a].empty()) {
+            if (dstBones[a].empty() && removeEmptyBones) {
                 continue;
                 continue;
             }
             }
 
 

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

@@ -237,6 +237,7 @@ protected:
     std::vector<aiAnimation *> mAnims;
     std::vector<aiAnimation *> mAnims;
 
 
     bool noSkeletonMesh;
     bool noSkeletonMesh;
+    bool removeEmptyBones;
     bool ignoreUpDirection;
     bool ignoreUpDirection;
     bool useColladaName;
     bool useColladaName;
 
 

+ 10 - 9
code/AssetLib/Collada/ColladaParser.cpp

@@ -1616,6 +1616,7 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
                     XmlParser::getValueAsString(currentNode, v);
                     XmlParser::getValueAsString(currentNode, v);
                     const char *content = v.c_str();
                     const char *content = v.c_str();
                     vcount.reserve(numPrimitives);
                     vcount.reserve(numPrimitives);
+                    SkipSpacesAndLineEnd(&content);
                     for (unsigned int a = 0; a < numPrimitives; a++) {
                     for (unsigned int a = 0; a < numPrimitives; a++) {
                         if (*content == 0) {
                         if (*content == 0) {
                             throw DeadlyImportError("Expected more values while reading <vcount> contents.");
                             throw DeadlyImportError("Expected more values while reading <vcount> contents.");
@@ -1928,7 +1929,7 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
     switch (pInput.mType) {
     switch (pInput.mType) {
     case IT_Position: // ignore all position streams except 0 - there can be only one position
     case IT_Position: // ignore all position streams except 0 - there can be only one position
         if (pInput.mIndex == 0) {
         if (pInput.mIndex == 0) {
-            pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+            pMesh.mPositions.emplace_back(obj[0], obj[1], obj[2]);
         } else {
         } else {
             ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
             ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
         }
         }
@@ -1940,7 +1941,7 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
 
 
         // ignore all normal streams except 0 - there can be only one normal
         // ignore all normal streams except 0 - there can be only one normal
         if (pInput.mIndex == 0) {
         if (pInput.mIndex == 0) {
-            pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+            pMesh.mNormals.emplace_back(obj[0], obj[1], obj[2]);
         } else {
         } else {
             ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
             ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
         }
         }
@@ -1952,7 +1953,7 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
 
 
         // ignore all tangent streams except 0 - there can be only one tangent
         // ignore all tangent streams except 0 - there can be only one tangent
         if (pInput.mIndex == 0) {
         if (pInput.mIndex == 0) {
-            pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+            pMesh.mTangents.emplace_back(obj[0], obj[1], obj[2]);
         } else {
         } else {
             ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
             ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
         }
         }
@@ -1965,7 +1966,7 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
 
 
         // ignore all bitangent streams except 0 - there can be only one bitangent
         // ignore all bitangent streams except 0 - there can be only one bitangent
         if (pInput.mIndex == 0) {
         if (pInput.mIndex == 0) {
-            pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+            pMesh.mBitangents.emplace_back(obj[0], obj[1], obj[2]);
         } else {
         } else {
             ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
             ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
         }
         }
@@ -1978,7 +1979,7 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
                 pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
                 pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
                         pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
                         pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
 
 
-            pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
+            pMesh.mTexCoords[pInput.mIndex].emplace_back(obj[0], obj[1], obj[2]);
             if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
             if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
                 pMesh.mNumUVComponents[pInput.mIndex] = 3;
                 pMesh.mNumUVComponents[pInput.mIndex] = 3;
             }
             }
@@ -2057,7 +2058,7 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
                 XmlParser::getStdStrAttribute(currentNode, "id", child->mID);
                 XmlParser::getStdStrAttribute(currentNode, "id", child->mID);
             }
             }
             if (XmlParser::hasAttribute(currentNode, "sid")) {
             if (XmlParser::hasAttribute(currentNode, "sid")) {
-                XmlParser::getStdStrAttribute(currentNode, "id", child->mSID);
+                XmlParser::getStdStrAttribute(currentNode, "sid", child->mSID);
             }
             }
             if (XmlParser::hasAttribute(currentNode, "name")) {
             if (XmlParser::hasAttribute(currentNode, "name")) {
                 XmlParser::getStdStrAttribute(currentNode, "name", child->mName);
                 XmlParser::getStdStrAttribute(currentNode, "name", child->mName);
@@ -2112,7 +2113,7 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
                 if (s[0] != '#') {
                 if (s[0] != '#') {
                     ASSIMP_LOG_ERROR("Collada: Unresolved reference format of node");
                     ASSIMP_LOG_ERROR("Collada: Unresolved reference format of node");
                 } else {
                 } else {
-                    pNode->mNodeInstances.push_back(NodeInstance());
+                    pNode->mNodeInstances.emplace_back();
                     pNode->mNodeInstances.back().mNode = s.c_str() + 1;
                     pNode->mNodeInstances.back().mNode = s.c_str() + 1;
                 }
                 }
             }
             }
@@ -2128,7 +2129,7 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
                     throw DeadlyImportError("Unknown reference format in <instance_light> element");
                     throw DeadlyImportError("Unknown reference format in <instance_light> element");
                 }
                 }
 
 
-                pNode->mLights.push_back(LightInstance());
+                pNode->mLights.emplace_back();
                 pNode->mLights.back().mLight = url.c_str() + 1;
                 pNode->mLights.back().mLight = url.c_str() + 1;
             }
             }
         } else if (currentName == "instance_camera") {
         } else if (currentName == "instance_camera") {
@@ -2139,7 +2140,7 @@ void ColladaParser::ReadSceneNode(XmlNode &node, Node *pNode) {
                 if (url[0] != '#') {
                 if (url[0] != '#') {
                     throw DeadlyImportError("Unknown reference format in <instance_camera> element");
                     throw DeadlyImportError("Unknown reference format in <instance_camera> element");
                 }
                 }
-                pNode->mCameras.push_back(CameraInstance());
+                pNode->mCameras.emplace_back();
                 pNode->mCameras.back().mCamera = url.c_str() + 1;
                 pNode->mCameras.back().mCamera = url.c_str() + 1;
             }
             }
         }
         }

+ 8 - 11
code/AssetLib/DXF/DXFLoader.cpp

@@ -110,16 +110,11 @@ static const aiImporterDesc desc = {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
-DXFImporter::DXFImporter()
-: BaseImporter() {
-    // empty
-}
+DXFImporter::DXFImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-DXFImporter::~DXFImporter() {
-    // empty
-}
+DXFImporter::~DXFImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -368,7 +363,9 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
         // XXX this would be the place to implement recursive expansion if needed.
         // XXX this would be the place to implement recursive expansion if needed.
         const DXF::Block& bl_src = *(*it).second;
         const DXF::Block& bl_src = *(*it).second;
 
 
-        for (std::shared_ptr<const DXF::PolyLine> pl_in : bl_src.lines) {
+        const size_t size = bl_src.lines.size(); // the size may increase in the loop
+        for (size_t i = 0; i < size; ++i) {
+            std::shared_ptr<const DXF::PolyLine> pl_in = bl_src.lines[i];
             if (!pl_in) {
             if (!pl_in) {
                 ASSIMP_LOG_ERROR("DXF: PolyLine instance is nullptr, skipping.");
                 ASSIMP_LOG_ERROR("DXF: PolyLine instance is nullptr, skipping.");
                 continue;
                 continue;
@@ -473,7 +470,7 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) {
 void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) {
     // push a new block onto the stack.
     // push a new block onto the stack.
-    output.blocks.push_back( DXF::Block() );
+    output.blocks.emplace_back();
     DXF::Block& block = output.blocks.back();
     DXF::Block& block = output.blocks.back();
 
 
     while( !reader.End() && !reader.Is(0,"ENDBLK")) {
     while( !reader.End() && !reader.Is(0,"ENDBLK")) {
@@ -518,7 +515,7 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) {
 void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output) {
     // Push a new block onto the stack.
     // Push a new block onto the stack.
-    output.blocks.push_back( DXF::Block() );
+    output.blocks.emplace_back();
     DXF::Block& block = output.blocks.back();
     DXF::Block& block = output.blocks.back();
 
 
     block.name = AI_DXF_ENTITIES_MAGIC_BLOCK;
     block.name = AI_DXF_ENTITIES_MAGIC_BLOCK;
@@ -548,7 +545,7 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
 }
 }
 
 
 void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output) {
 void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output) {
-    output.blocks.back().insertions.push_back( DXF::InsertBlock() );
+    output.blocks.back().insertions.emplace_back();
     DXF::InsertBlock& bl = output.blocks.back().insertions.back();
     DXF::InsertBlock& bl = output.blocks.back().insertions.back();
 
 
     while( !reader.End() && !reader.Is(0)) {
     while( !reader.End() && !reader.Is(0)) {

+ 0 - 21
code/AssetLib/FBX/FBXAnimation.cpp

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2022, assimp team
 Copyright (c) 2006-2022, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -87,11 +86,6 @@ AnimationCurve::AnimationCurve(uint64_t id, const Element &element, const std::s
     }
     }
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-AnimationCurve::~AnimationCurve() {
-    // empty
-}
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, const std::string &name,
 AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, const std::string &name,
         const Document &doc, const char *const *target_prop_whitelist /*= nullptr*/,
         const Document &doc, const char *const *target_prop_whitelist /*= nullptr*/,
@@ -147,11 +141,6 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, cons
     props = GetPropertyTable(doc, "AnimationCurveNode.FbxAnimCurveNode", element, sc, false);
     props = GetPropertyTable(doc, "AnimationCurveNode.FbxAnimCurveNode", element, sc, false);
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-AnimationCurveNode::~AnimationCurveNode() {
-    // empty
-}
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 const AnimationCurveMap &AnimationCurveNode::Curves() const {
 const AnimationCurveMap &AnimationCurveNode::Curves() const {
     if (curves.empty()) {
     if (curves.empty()) {
@@ -193,11 +182,6 @@ AnimationLayer::AnimationLayer(uint64_t id, const Element &element, const std::s
     props = GetPropertyTable(doc, "AnimationLayer.FbxAnimLayer", element, sc, true);
     props = GetPropertyTable(doc, "AnimationLayer.FbxAnimLayer", element, sc, true);
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-AnimationLayer::~AnimationLayer() {
-    // empty
-}
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 AnimationCurveNodeList AnimationLayer::Nodes(const char *const *target_prop_whitelist /*= nullptr*/,
 AnimationCurveNodeList AnimationLayer::Nodes(const char *const *target_prop_whitelist /*= nullptr*/,
         size_t whitelist_size /*= 0*/) const {
         size_t whitelist_size /*= 0*/) const {
@@ -279,11 +263,6 @@ AnimationStack::AnimationStack(uint64_t id, const Element &element, const std::s
     }
     }
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-AnimationStack::~AnimationStack() {
-    // empty
-}
-
 } // namespace FBX
 } // namespace FBX
 } // namespace Assimp
 } // namespace Assimp
 
 

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

@@ -470,7 +470,7 @@ void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length,
     }
     }
     catch (const DeadlyImportError& e)
     catch (const DeadlyImportError& e)
     {
     {
-        if (!is64bits && (length > std::numeric_limits<std::uint32_t>::max())) {
+        if (!is64bits && (length > std::numeric_limits<uint32_t>::max())) {
             throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", ai_to_string(version), ") of the FBX format. (", e.what(), ")");
             throw DeadlyImportError("The FBX file is invalid. This may be because the content is too big for this older version (", ai_to_string(version), ") of the FBX format. (", e.what(), ")");
         }
         }
         throw;
         throw;

+ 2 - 1
code/AssetLib/FBX/FBXCommon.h

@@ -50,7 +50,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace Assimp {
 namespace FBX {
 namespace FBX {
 
 
-const std::string NULL_RECORD = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
+static constexpr size_t NumNullRecords = 25;
+const char NULL_RECORD[NumNullRecords] = { // 25 null bytes in 64-bit and 13 null bytes in 32-bit
     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
 }; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
 }; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)

+ 0 - 1
code/AssetLib/FBX/FBXCompileConfig.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2022, assimp team
 Copyright (c) 2006-2022, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,

+ 117 - 66
code/AssetLib/FBX/FBXConverter.cpp

@@ -65,12 +65,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <stdlib.h>
 #include <stdlib.h>
 #include <cstdint>
 #include <cstdint>
 #include <iomanip>
 #include <iomanip>
-#include <iostream>
 #include <iterator>
 #include <iterator>
 #include <memory>
 #include <memory>
 #include <sstream>
 #include <sstream>
-#include <tuple>
-#include <vector>
 
 
 namespace Assimp {
 namespace Assimp {
 namespace FBX {
 namespace FBX {
@@ -187,8 +184,7 @@ std::string FBXConverter::MakeUniqueNodeName(const Model *const model, const aiN
 
 
 /// This struct manages nodes which may or may not end up in the node hierarchy.
 /// This struct manages nodes which may or may not end up in the node hierarchy.
 /// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released.
 /// When a node becomes a child of another node, that node becomes its owner and mOwnership should be released.
-struct FBXConverter::PotentialNode
-{
+struct FBXConverter::PotentialNode {
     PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {}
     PotentialNode() : mOwnership(new aiNode), mNode(mOwnership.get()) {}
     PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {}
     PotentialNode(const std::string& name) : mOwnership(new aiNode(name)), mNode(mOwnership.get()) {}
     aiNode* operator->() { return mNode; }
     aiNode* operator->() { return mNode; }
@@ -231,7 +227,6 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
         if (nullptr != model) {
         if (nullptr != model) {
             nodes_chain.clear();
             nodes_chain.clear();
             post_nodes_chain.clear();
             post_nodes_chain.clear();
-
             aiMatrix4x4 new_abs_transform = parent->mTransformation;
             aiMatrix4x4 new_abs_transform = parent->mTransformation;
             std::string node_name = FixNodeName(model->Name());
             std::string node_name = FixNodeName(model->Name());
             // even though there is only a single input node, the design of
             // even though there is only a single input node, the design of
@@ -247,7 +242,7 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
             ai_assert(nodes_chain.size());
             ai_assert(nodes_chain.size());
 
 
             if (need_additional_node) {
             if (need_additional_node) {
-                nodes_chain.emplace_back(PotentialNode(node_name));
+                nodes_chain.emplace_back(node_name);
             }
             }
 
 
             //setup metadata on newest node
             //setup metadata on newest node
@@ -266,8 +261,6 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
 
 
                 child->mParent = last_parent;
                 child->mParent = last_parent;
                 last_parent = child.mNode;
                 last_parent = child.mNode;
-
-                new_abs_transform *= child->mTransformation;
             }
             }
 
 
             // attach geometry
             // attach geometry
@@ -290,8 +283,6 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
 
 
                     postnode->mParent = last_parent;
                     postnode->mParent = last_parent;
                     last_parent = postnode.mNode;
                     last_parent = postnode.mNode;
-
-                    new_abs_transform *= postnode->mTransformation;
                 }
                 }
             } else {
             } else {
                 // free the nodes we allocated as we don't need them
                 // free the nodes we allocated as we don't need them
@@ -452,7 +443,7 @@ void FBXConverter::GetUniqueName(const std::string &name, std::string &uniqueNam
     auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count
     auto it_pair = mNodeNames.insert({ name, 0 }); // duplicate node name instance count
     unsigned int &i = it_pair.first->second;
     unsigned int &i = it_pair.first->second;
     while (!it_pair.second) {
     while (!it_pair.second) {
-        i++;
+        ++i;
         std::ostringstream ext;
         std::ostringstream ext;
         ext << name << std::setfill('0') << std::setw(3) << i;
         ext << name << std::setfill('0') << std::setw(3) << i;
         uniqueName = ext.str();
         uniqueName = ext.str();
@@ -651,9 +642,8 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
 
 
 bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
 bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
     const PropertyTable &props = model.Props();
     const PropertyTable &props = model.Props();
-    bool ok;
 
 
-    const float zero_epsilon = ai_epsilon;
+    const auto zero_epsilon = ai_epsilon;
     const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
     const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
     for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
     for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
         const TransformationComp comp = static_cast<TransformationComp>(i);
         const TransformationComp comp = static_cast<TransformationComp>(i);
@@ -665,6 +655,7 @@ bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
 
 
         bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling);
         bool scale_compare = (comp == TransformationComp_GeometricScaling || comp == TransformationComp_Scaling);
 
 
+        bool ok = true;
         const aiVector3D &v = PropertyGet<aiVector3D>(props, NameTransformationCompProperty(comp), ok);
         const aiVector3D &v = PropertyGet<aiVector3D>(props, NameTransformationCompProperty(comp), ok);
         if (ok && scale_compare) {
         if (ok && scale_compare) {
             if ((v - all_ones).SquareLength() > zero_epsilon) {
             if ((v - all_ones).SquareLength() > zero_epsilon) {
@@ -899,20 +890,17 @@ void FBXConverter::SetupNodeMetadata(const Model &model, aiNode &nd) {
     }
     }
 }
 }
 
 
-void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node,
-        const aiMatrix4x4 &absolute_transform) {
+void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform) {
     const std::vector<const Geometry *> &geos = model.GetGeometry();
     const std::vector<const Geometry *> &geos = model.GetGeometry();
 
 
     std::vector<unsigned int> meshes;
     std::vector<unsigned int> meshes;
     meshes.reserve(geos.size());
     meshes.reserve(geos.size());
 
 
     for (const Geometry *geo : geos) {
     for (const Geometry *geo : geos) {
-
         const MeshGeometry *const mesh = dynamic_cast<const MeshGeometry *>(geo);
         const MeshGeometry *const mesh = dynamic_cast<const MeshGeometry *>(geo);
         const LineGeometry *const line = dynamic_cast<const LineGeometry *>(geo);
         const LineGeometry *const line = dynamic_cast<const LineGeometry *>(geo);
         if (mesh) {
         if (mesh) {
-            const std::vector<unsigned int> &indices = ConvertMesh(*mesh, model, parent, root_node,
-                    absolute_transform);
+            const std::vector<unsigned int> &indices = ConvertMesh(*mesh, model, parent, root_node, absolute_transform);
             std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
             std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
         } else if (line) {
         } else if (line) {
             const std::vector<unsigned int> &indices = ConvertLine(*line, root_node);
             const std::vector<unsigned int> &indices = ConvertLine(*line, root_node);
@@ -933,8 +921,7 @@ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root
 }
 }
 
 
 std::vector<unsigned int>
 std::vector<unsigned int>
-FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
-        const aiMatrix4x4 &absolute_transform) {
+FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform) {
     std::vector<unsigned int> temp;
     std::vector<unsigned int> temp;
 
 
     MeshMap::const_iterator it = meshes_converted.find(&mesh);
     MeshMap::const_iterator it = meshes_converted.find(&mesh);
@@ -957,7 +944,7 @@ FBXConverter::ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *
         const MatIndexArray::value_type base = mindices[0];
         const MatIndexArray::value_type base = mindices[0];
         for (MatIndexArray::value_type index : mindices) {
         for (MatIndexArray::value_type index : mindices) {
             if (index != base) {
             if (index != base) {
-                return ConvertMeshMultiMaterial(mesh, model, parent, root_node, absolute_transform);
+                return ConvertMeshMultiMaterial(mesh, model, absolute_transform, parent, root_node);
             }
             }
         }
         }
     }
     }
@@ -1031,9 +1018,36 @@ aiMesh *FBXConverter::SetupEmptyMesh(const Geometry &mesh, aiNode *parent) {
     return out_mesh;
     return out_mesh;
 }
 }
 
 
-unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
-        const aiMatrix4x4 &absolute_transform, aiNode *parent,
-        aiNode *) {
+static aiSkeleton *createAiSkeleton(SkeletonBoneContainer &sbc) {
+    if (sbc.MeshArray.empty() || sbc.SkeletonBoneToMeshLookup.empty()) {
+        return nullptr;
+    }
+
+    aiSkeleton *skeleton = new aiSkeleton;
+    for (auto *mesh : sbc.MeshArray) {
+        auto it = sbc.SkeletonBoneToMeshLookup.find(mesh);
+        if (it == sbc.SkeletonBoneToMeshLookup.end()) {
+            continue;
+        }
+        SkeletonBoneArray *ba = it->second;
+        if (ba == nullptr) {
+            continue;
+        }
+
+        skeleton->mNumBones = static_cast<unsigned int>(ba->size());
+        skeleton->mBones = new aiSkeletonBone*[skeleton->mNumBones];
+        size_t index = 0;
+        for (auto bone : (* ba)) {
+            skeleton->mBones[index] = bone;
+            ++index;
+        }
+    }
+
+    return skeleton;
+}
+
+unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
+        aiNode *parent, aiNode *) {
     const MatIndexArray &mindices = mesh.GetMaterialIndices();
     const MatIndexArray &mindices = mesh.GetMaterialIndices();
     aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
     aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
 
 
@@ -1151,8 +1165,15 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
         ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]);
         ConvertMaterialForMesh(out_mesh, model, mesh, mindices[0]);
     }
     }
 
 
-    if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr) {
+    if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr && !doc.Settings().useSkeleton) {
         ConvertWeights(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr);
         ConvertWeights(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr);
+    } else if (doc.Settings().readWeights && mesh.DeformerSkin() != nullptr && doc.Settings().useSkeleton) {
+        SkeletonBoneContainer sbc;
+        ConvertWeightsToSkeleton(out_mesh, mesh, absolute_transform, parent, NO_MATERIAL_SEPARATION, nullptr, sbc);
+        aiSkeleton *skeleton = createAiSkeleton(sbc);
+        if (skeleton != nullptr) {
+            mSkeletons.emplace_back(skeleton);
+        }
     }
     }
 
 
     std::vector<aiAnimMesh *> animMeshes;
     std::vector<aiAnimMesh *> animMeshes;
@@ -1199,9 +1220,8 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
 }
 }
 
 
 std::vector<unsigned int>
 std::vector<unsigned int>
-FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent,
-        aiNode *root_node,
-        const aiMatrix4x4 &absolute_transform) {
+FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, aiNode *parent,
+        aiNode *root_node) {
     const MatIndexArray &mindices = mesh.GetMaterialIndices();
     const MatIndexArray &mindices = mesh.GetMaterialIndices();
     ai_assert(mindices.size());
     ai_assert(mindices.size());
 
 
@@ -1211,7 +1231,7 @@ FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &mo
     for (MatIndexArray::value_type index : mindices) {
     for (MatIndexArray::value_type index : mindices) {
         if (had.find(index) == had.end()) {
         if (had.find(index) == had.end()) {
 
 
-            indices.push_back(ConvertMeshMultiMaterial(mesh, model, index, parent, root_node, absolute_transform));
+            indices.push_back(ConvertMeshMultiMaterial(mesh, model, absolute_transform, index, parent, root_node));
             had.insert(index);
             had.insert(index);
         }
         }
     }
     }
@@ -1219,10 +1239,8 @@ FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &mo
     return indices;
     return indices;
 }
 }
 
 
-unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model,
-        MatIndexArray::value_type index,
-        aiNode *parent, aiNode *,
-        const aiMatrix4x4 &absolute_transform) {
+unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
+        MatIndexArray::value_type index, aiNode *parent, aiNode *) {
     aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
     aiMesh *const out_mesh = SetupEmptyMesh(mesh, parent);
 
 
     const MatIndexArray &mindices = mesh.GetMaterialIndices();
     const MatIndexArray &mindices = mesh.GetMaterialIndices();
@@ -1435,20 +1453,47 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
     return static_cast<unsigned int>(mMeshes.size() - 1);
     return static_cast<unsigned int>(mMeshes.size() - 1);
 }
 }
 
 
-void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo,
-        const aiMatrix4x4 &absolute_transform,
+static void copyBoneToSkeletonBone(aiMesh *mesh, aiBone *bone, aiSkeletonBone *skeletonBone ) {
+    skeletonBone->mNumnWeights = bone->mNumWeights;
+    skeletonBone->mWeights = bone->mWeights;
+    skeletonBone->mOffsetMatrix = bone->mOffsetMatrix;
+    skeletonBone->mMeshId = mesh;
+    skeletonBone->mNode = bone->mNode;
+    skeletonBone->mParent = -1;
+}
+
+void FBXConverter::ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent, unsigned int materialIndex,
+        std::vector<unsigned int> *outputVertStartIndices, SkeletonBoneContainer &skeletonContainer) {
+
+    if (skeletonContainer.SkeletonBoneToMeshLookup.find(out) != skeletonContainer.SkeletonBoneToMeshLookup.end()) {
+        return;
+    }
+
+    ConvertWeights(out, geo, absolute_transform, parent, materialIndex, outputVertStartIndices);
+    skeletonContainer.MeshArray.emplace_back(out);
+    SkeletonBoneArray *ba = new SkeletonBoneArray;
+    for (size_t i = 0; i < out->mNumBones; ++i) {
+        aiBone *bone = out->mBones[i];
+        if (bone == nullptr) {
+            continue;
+        }
+        aiSkeletonBone *skeletonBone = new aiSkeletonBone;
+        copyBoneToSkeletonBone(out, bone, skeletonBone);
+        ba->emplace_back(skeletonBone);
+    }
+    skeletonContainer.SkeletonBoneToMeshLookup[out] = ba;
+}
+
+void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
         aiNode *parent, unsigned int materialIndex,
         aiNode *parent, unsigned int materialIndex,
         std::vector<unsigned int> *outputVertStartIndices) {
         std::vector<unsigned int> *outputVertStartIndices) {
     ai_assert(geo.DeformerSkin());
     ai_assert(geo.DeformerSkin());
 
 
-    std::vector<size_t> out_indices;
-    std::vector<size_t> index_out_indices;
-    std::vector<size_t> count_out_indices;
+    std::vector<size_t> out_indices, index_out_indices, count_out_indices;
 
 
     const Skin &sk = *geo.DeformerSkin();
     const Skin &sk = *geo.DeformerSkin();
 
 
-    std::vector<aiBone *> bones;
-
+    std::vector<aiBone*> bones;
     const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
     const bool no_mat_check = materialIndex == NO_MATERIAL_SEPARATION;
     ai_assert(no_mat_check || outputVertStartIndices);
     ai_assert(no_mat_check || outputVertStartIndices);
 
 
@@ -1521,26 +1566,20 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo,
         out->mBones = nullptr;
         out->mBones = nullptr;
         out->mNumBones = 0;
         out->mNumBones = 0;
         return;
         return;
-    } else {
-        out->mBones = new aiBone *[bones.size()]();
-        out->mNumBones = static_cast<unsigned int>(bones.size());
+    } 
 
 
-        std::swap_ranges(bones.begin(), bones.end(), out->mBones);
-    }
+    out->mBones = new aiBone *[bones.size()]();
+    out->mNumBones = static_cast<unsigned int>(bones.size());
+    std::swap_ranges(bones.begin(), bones.end(), out->mBones);
 }
 }
 
 
-const aiNode *GetNodeByName(aiNode *current_node) {
-    aiNode *iter = current_node;
-    //printf("Child count: %d", iter->mNumChildren);
-    return iter;
-}
-
-void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
+void FBXConverter::ConvertCluster(std::vector<aiBone*> &local_mesh_bones, const Cluster *cluster,
         std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
         std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
-        std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
+        std::vector<size_t> &count_out_indices, const aiMatrix4x4 & /* absolute_transform*/,
         aiNode *) {
         aiNode *) {
-    ai_assert(cl); // make sure cluster valid
-    std::string deformer_name = cl->TargetNode()->Name();
+    ai_assert(cluster != nullptr); // make sure cluster valid
+
+    std::string deformer_name = cluster->TargetNode()->Name();
     aiString bone_name = aiString(FixNodeName(deformer_name));
     aiString bone_name = aiString(FixNodeName(deformer_name));
 
 
     aiBone *bone = nullptr;
     aiBone *bone = nullptr;
@@ -1553,14 +1592,16 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
         bone = new aiBone();
         bone = new aiBone();
         bone->mName = bone_name;
         bone->mName = bone_name;
 
 
+        bone->mOffsetMatrix = cluster->Transform();
         // store local transform link for post processing
         // store local transform link for post processing
-        bone->mOffsetMatrix = cl->TransformLink();
+        /*
+        bone->mOffsetMatrix = cluster->TransformLink();
         bone->mOffsetMatrix.Inverse();
         bone->mOffsetMatrix.Inverse();
 
 
         aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
         aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
 
 
         bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset
         bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset
-
+        */
         //
         //
         // Now calculate the aiVertexWeights
         // Now calculate the aiVertexWeights
         //
         //
@@ -1571,7 +1612,7 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
         cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];
         cursor = bone->mWeights = new aiVertexWeight[out_indices.size()];
 
 
         const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
         const size_t no_index_sentinel = std::numeric_limits<size_t>::max();
-        const WeightArray &weights = cl->GetWeights();
+        const WeightArray &weights = cluster->GetWeights();
 
 
         const size_t c = index_out_indices.size();
         const size_t c = index_out_indices.size();
         for (size_t i = 0; i < c; ++i) {
         for (size_t i = 0; i < c; ++i) {
@@ -2162,7 +2203,7 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert
     if (ok) {
     if (ok) {
         out_mat->AddProperty(&ShininessExponent, 1, AI_MATKEY_SHININESS);
         out_mat->AddProperty(&ShininessExponent, 1, AI_MATKEY_SHININESS);
          // Match Blender behavior to extract roughness when only shininess is present
          // Match Blender behavior to extract roughness when only shininess is present
-        const float roughness = 1.0 - (sqrt(ShininessExponent) / 10.0);
+        const float roughness = 1.0f - (sqrt(ShininessExponent) / 10.0f);
         out_mat->AddProperty(&roughness, 1, AI_MATKEY_ROUGHNESS_FACTOR);
         out_mat->AddProperty(&roughness, 1, AI_MATKEY_ROUGHNESS_FACTOR);
     }
     }
 
 
@@ -2616,7 +2657,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
                 meshMorphAnim->mNumKeys = numKeys;
                 meshMorphAnim->mNumKeys = numKeys;
                 meshMorphAnim->mKeys = new aiMeshMorphKey[numKeys];
                 meshMorphAnim->mKeys = new aiMeshMorphKey[numKeys];
                 unsigned int j = 0;
                 unsigned int j = 0;
-                for (auto animIt : *animData) {
+                for (auto &animIt : *animData) {
                     morphKeyData *keyData = animIt.second;
                     morphKeyData *keyData = animIt.second;
                     unsigned int numValuesAndWeights = static_cast<unsigned int>(keyData->values.size());
                     unsigned int numValuesAndWeights = static_cast<unsigned int>(keyData->values.size());
                     meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
                     meshMorphAnim->mKeys[j].mNumValuesAndWeights = numValuesAndWeights;
@@ -3191,7 +3232,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
 
 
     bool ok = false;
     bool ok = false;
     
     
-    const float zero_epsilon = ai_epsilon;
+    const auto zero_epsilon = ai_epsilon;
 
 
     const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
     const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
     if (ok && preRotation.SquareLength() > zero_epsilon) {
     if (ok && preRotation.SquareLength() > zero_epsilon) {
@@ -3278,7 +3319,7 @@ FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList(const std::vector<c
                 }
                 }
             }
             }
 
 
-            inputs.push_back(std::make_tuple(Keys, Values, mapto));
+            inputs.emplace_back(Keys, Values, mapto);
         }
         }
     }
     }
     return inputs; // pray for NRVO :-)
     return inputs; // pray for NRVO :-)
@@ -3329,13 +3370,17 @@ FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std::
                 float vc = curve->GetValues().at(1);
                 float vc = curve->GetValues().at(1);
                 for (size_t n = 1; n < count; n++) {
                 for (size_t n = 1; n < count; n++) {
                     while (std::abs(vc - vp) >= 180.0f) {
                     while (std::abs(vc - vp) >= 180.0f) {
-                        float step = std::floor(float(tc - tp) / (vc - vp) * 179.0f);
+                        double step = std::floor(double(tc - tp) / std::abs(vc - vp) * 179.0f);
                         int64_t tnew = tp + int64_t(step);
                         int64_t tnew = tp + int64_t(step);
-                        float vnew = vp + (vc - vp) * step / float(tc - tp);
+                        float vnew = vp + (vc - vp) * float(step / (tc - tp));
                         if (tnew >= adj_start && tnew <= adj_stop) {
                         if (tnew >= adj_start && tnew <= adj_stop) {
                             Keys->push_back(tnew);
                             Keys->push_back(tnew);
                             Values->push_back(vnew);
                             Values->push_back(vnew);
                         }
                         }
+                        else {
+                            // Something broke
+                            break;
+                        }
                         tp = tnew;
                         tp = tnew;
                         vp = vnew;
                         vp = vnew;
                     }
                     }
@@ -3351,7 +3396,7 @@ FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std::
                     }
                     }
                 }
                 }
             }
             }
-            inputs.push_back(std::make_tuple(Keys, Values, mapto));
+            inputs.emplace_back(Keys, Values, mapto);
         }
         }
     }
     }
     return inputs;
     return inputs;
@@ -3636,6 +3681,12 @@ void FBXConverter::TransferDataToScene() {
 
 
         std::swap_ranges(textures.begin(), textures.end(), mSceneOut->mTextures);
         std::swap_ranges(textures.begin(), textures.end(), mSceneOut->mTextures);
     }
     }
+
+    if (!mSkeletons.empty()) {
+        mSceneOut->mSkeletons = new aiSkeleton *[mSkeletons.size()];
+        mSceneOut->mNumSkeletons = static_cast<unsigned int>(mSkeletons.size());
+        std::swap_ranges(mSkeletons.begin(), mSkeletons.end(), mSceneOut->mSkeletons);
+    }
 }
 }
 
 
 void FBXConverter::ConvertOrphanedEmbeddedTextures() {
 void FBXConverter::ConvertOrphanedEmbeddedTextures() {

+ 29 - 16
code/AssetLib/FBX/FBXConverter.h

@@ -75,7 +75,18 @@ typedef std::map<int64_t, morphKeyData*> morphAnimData;
 namespace Assimp {
 namespace Assimp {
 namespace FBX {
 namespace FBX {
 
 
+class MeshGeometry;
+
+using SkeletonBoneArray = std::vector<aiSkeletonBone *>;
+using SkeletonBoneToMesh = std::map<aiMesh*, SkeletonBoneArray*>;
+
+struct SkeletonBoneContainer {
+    std::vector<aiMesh *> MeshArray;
+    SkeletonBoneToMesh SkeletonBoneToMeshLookup;
+};
+
 class Document;
 class Document;
+
 /**
 /**
  *  Convert a FBX #Document to #aiScene
  *  Convert a FBX #Document to #aiScene
  *  @param out Empty scene to be populated
  *  @param out Empty scene to be populated
@@ -180,14 +191,12 @@ private:
     void SetupNodeMetadata(const Model& model, aiNode& nd);
     void SetupNodeMetadata(const Model& model, aiNode& nd);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
-    void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node,
-                      const aiMatrix4x4 &absolute_transform);
+    void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
     // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
     // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
     std::vector<unsigned int>
     std::vector<unsigned int>
-    ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
-                const aiMatrix4x4 &absolute_transform);
+    ConvertMesh(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
     std::vector<unsigned int> ConvertLine(const LineGeometry& line, aiNode *root_node);
     std::vector<unsigned int> ConvertLine(const LineGeometry& line, aiNode *root_node);
@@ -196,18 +205,16 @@ private:
     aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent);
     aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode *parent);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
-    unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model,
-                                           const aiMatrix4x4 &absolute_transform, aiNode *parent,
-                                           aiNode *root_node);
+    unsigned int ConvertMeshSingleMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform,
+                                           aiNode *parent, aiNode *root_node);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
     std::vector<unsigned int>
     std::vector<unsigned int>
-    ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, aiNode *parent, aiNode *root_node,
-                             const aiMatrix4x4 &absolute_transform);
+    ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, aiNode *parent, aiNode *root_node);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
-    unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, MatIndexArray::value_type index,
-                                          aiNode *parent, aiNode *root_node, const aiMatrix4x4 &absolute_transform);
+    unsigned int ConvertMeshMultiMaterial(const MeshGeometry &mesh, const Model &model, const aiMatrix4x4 &absolute_transform, MatIndexArray::value_type index,
+                                          aiNode *parent, aiNode *root_node);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
     static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
     static const unsigned int NO_MATERIAL_SEPARATION = /* std::numeric_limits<unsigned int>::max() */
@@ -220,15 +227,19 @@ private:
     *  - outputVertStartIndices is only used when a material index is specified, it gives for
     *  - outputVertStartIndices is only used when a material index is specified, it gives for
     *    each output vertex the DOM index it maps to.
     *    each output vertex the DOM index it maps to.
     */
     */
-    void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
-            aiNode *parent = nullptr, unsigned int materialIndex = NO_MATERIAL_SEPARATION,
+    void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform, aiNode *parent = nullptr,
+            unsigned int materialIndex = NO_MATERIAL_SEPARATION,
             std::vector<unsigned int> *outputVertStartIndices = nullptr);
             std::vector<unsigned int> *outputVertStartIndices = nullptr);
 
 
+    // ------------------------------------------------------------------------------------------------
+    void ConvertWeightsToSkeleton(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
+            aiNode *parent, unsigned int materialIndex, std::vector<unsigned int> *outputVertStartIndices,
+            SkeletonBoneContainer &skeletonContainer);
+
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
     void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
     void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
                         std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
                         std::vector<size_t> &out_indices, std::vector<size_t> &index_out_indices,
-                        std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
-                        aiNode *parent );
+            std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform, aiNode *parent);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
     void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
     void ConvertMaterialForMesh(aiMesh* out, const Model& model, const MeshGeometry& geo,
@@ -301,7 +312,8 @@ private:
     void ConvertAnimationStack(const AnimationStack& st);
     void ConvertAnimationStack(const AnimationStack& st);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
-    void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas, const BlendShapeChannel* bsc, const AnimationCurveNode* node);
+    void ProcessMorphAnimDatas(std::map<std::string, morphAnimData*>* morphAnimDatas,
+        const BlendShapeChannel* bsc, const AnimationCurveNode* node);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
     void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
     void GenerateNodeAnimations(std::vector<aiNodeAnim*>& node_anims,
@@ -450,6 +462,7 @@ private:
 
 
     double anim_fps;
     double anim_fps;
 
 
+    std::vector<aiSkeleton *> mSkeletons;
     aiScene* const mSceneOut;
     aiScene* const mSceneOut;
     const FBX::Document& doc;
     const FBX::Document& doc;
     bool mRemoveEmptyBones;
     bool mRemoveEmptyBones;

+ 7 - 27
code/AssetLib/FBX/FBXDeformer.cpp

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2022, assimp team
 Copyright (c) 2006-2022, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -58,22 +57,16 @@ namespace FBX {
 using namespace Util;
 using namespace Util;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-    : Object(id,element,name)
-{
+Deformer::Deformer(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
+        Object(id,element,name) {
     const Scope& sc = GetRequiredScope(element);
     const Scope& sc = GetRequiredScope(element);
 
 
     const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
     const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
     props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
     props = GetPropertyTable(doc,"Deformer.Fbx" + classname,element,sc,true);
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Deformer::~Deformer()
-{
-
-}
-
+Deformer::~Deformer() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const std::string& name)
@@ -122,11 +115,7 @@ Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Cluster::~Cluster()
-{
-
-}
-
+Cluster::~Cluster() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 Skin::Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 Skin::Skin(uint64_t id, const Element& element, const Document& doc, const std::string& name)
@@ -155,10 +144,7 @@ Skin::Skin(uint64_t id, const Element& element, const Document& doc, const std::
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Skin::~Skin()
-{
-
-}
+Skin::~Skin() = default;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc, const std::string& name)
     : Deformer(id, element, doc, name)
     : Deformer(id, element, doc, name)
@@ -174,10 +160,7 @@ BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc,
     }
     }
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-BlendShape::~BlendShape()
-{
-
-}
+BlendShape::~BlendShape() = default;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name)
 BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const Document& doc, const std::string& name)
     : Deformer(id, element, doc, name)
     : Deformer(id, element, doc, name)
@@ -202,10 +185,7 @@ BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const
     }
     }
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-BlendShapeChannel::~BlendShapeChannel()
-{
-
-}
+BlendShapeChannel::~BlendShapeChannel() = default;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 }
 }
 }
 }

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

@@ -67,7 +67,7 @@ namespace FBX {
 using namespace Util;
 using namespace Util;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) : 
+LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) :
         doc(doc), element(element), id(id), flags() {
         doc(doc), element(element), id(id), flags() {
     // empty
     // empty
 }
 }
@@ -552,7 +552,7 @@ std::vector<const Connection*> Document::GetConnectionsSequenced(uint64_t id, bo
     ai_assert( count != 0 );
     ai_assert( count != 0 );
     ai_assert( count <= MAX_CLASSNAMES);
     ai_assert( count <= MAX_CLASSNAMES);
 
 
-    size_t lengths[MAX_CLASSNAMES];
+    size_t lengths[MAX_CLASSNAMES] = {};
 
 
     const size_t c = count;
     const size_t c = count;
     for (size_t i = 0; i < c; ++i) {
     for (size_t i = 0; i < c; ++i) {

+ 10 - 10
code/AssetLib/FBX/FBXDocument.h

@@ -168,7 +168,7 @@ class NodeAttribute : public Object {
 public:
 public:
     NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
     NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name);
 
 
-    virtual ~NodeAttribute();
+    virtual ~NodeAttribute() = default;
 
 
     const PropertyTable& Props() const {
     const PropertyTable& Props() const {
         ai_assert(props.get());
         ai_assert(props.get());
@@ -184,7 +184,7 @@ class CameraSwitcher : public NodeAttribute {
 public:
 public:
     CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
     CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name);
 
 
-    virtual ~CameraSwitcher();
+    virtual ~CameraSwitcher() = default;
 
 
     int CameraID() const {
     int CameraID() const {
         return cameraId;
         return cameraId;
@@ -229,7 +229,7 @@ class Camera : public NodeAttribute {
 public:
 public:
     Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
     Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name);
 
 
-    virtual  ~Camera();
+    virtual  ~Camera() = default;
 
 
     fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
     fbx_simple_property(Position, aiVector3D, aiVector3D(0,0,0))
     fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
     fbx_simple_property(UpVector, aiVector3D, aiVector3D(0,1,0))
@@ -254,21 +254,21 @@ public:
 class Null : public NodeAttribute {
 class Null : public NodeAttribute {
 public:
 public:
     Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
     Null(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-    virtual ~Null();
+    virtual ~Null() = default;
 };
 };
 
 
 /** DOM base class for FBX limb node markers attached to a node */
 /** DOM base class for FBX limb node markers attached to a node */
 class LimbNode : public NodeAttribute {
 class LimbNode : public NodeAttribute {
 public:
 public:
     LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
     LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-    virtual ~LimbNode();
+    virtual ~LimbNode() = default;
 };
 };
 
 
 /** DOM base class for FBX lights attached to a node */
 /** DOM base class for FBX lights attached to a node */
 class Light : public NodeAttribute {
 class Light : public NodeAttribute {
 public:
 public:
     Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
     Light(uint64_t id, const Element& element, const Document& doc, const std::string& name);
-    virtual ~Light();
+    virtual ~Light() = default;
 
 
     enum Type {
     enum Type {
         Type_Point,
         Type_Point,
@@ -694,7 +694,7 @@ using KeyValueList = std::vector<float>;
 class AnimationCurve : public Object {
 class AnimationCurve : public Object {
 public:
 public:
     AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
     AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);
-    virtual ~AnimationCurve();
+    virtual ~AnimationCurve() = default;
 
 
     /** get list of keyframe positions (time).
     /** get list of keyframe positions (time).
      *  Invariant: |GetKeys()| > 0 */
      *  Invariant: |GetKeys()| > 0 */
@@ -735,7 +735,7 @@ public:
     AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
     AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
             const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
             const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
 
 
-    virtual ~AnimationCurveNode();
+    virtual ~AnimationCurveNode() = default;
 
 
     const PropertyTable& Props() const {
     const PropertyTable& Props() const {
         ai_assert(props.get());
         ai_assert(props.get());
@@ -780,7 +780,7 @@ using AnimationCurveNodeList = std::vector<const AnimationCurveNode*>;
 class AnimationLayer : public Object {
 class AnimationLayer : public Object {
 public:
 public:
     AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
     AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc);
-    virtual ~AnimationLayer();
+    virtual ~AnimationLayer() = default;
 
 
     const PropertyTable& Props() const {
     const PropertyTable& Props() const {
         ai_assert(props.get());
         ai_assert(props.get());
@@ -803,7 +803,7 @@ using AnimationLayerList = std::vector<const AnimationLayer*>;
 class AnimationStack : public Object {
 class AnimationStack : public Object {
 public:
 public:
     AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
     AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc);
-    virtual ~AnimationStack();
+    virtual ~AnimationStack() = default;
 
 
     fbx_simple_property(LocalStart, int64_t, 0L)
     fbx_simple_property(LocalStart, int64_t, 0L)
     fbx_simple_property(LocalStop, int64_t, 0L)
     fbx_simple_property(LocalStop, int64_t, 0L)

+ 3 - 6
code/AssetLib/FBX/FBXDocumentUtil.cpp

@@ -59,14 +59,12 @@ namespace Util {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError.
 // signal DOM construction error, this is always unrecoverable. Throws DeadlyImportError.
-void DOMError(const std::string& message, const Token& token)
-{
+void DOMError(const std::string& message, const Token& token) {
     throw DeadlyImportError("FBX-DOM", Util::GetTokenText(&token), message);
     throw DeadlyImportError("FBX-DOM", Util::GetTokenText(&token), message);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void DOMError(const std::string& message, const Element* element /*= nullptr*/)
-{
+void DOMError(const std::string& message, const Element* element /*= nullptr*/) {
     if(element) {
     if(element) {
         DOMError(message,element->KeyToken());
         DOMError(message,element->KeyToken());
     }
     }
@@ -76,8 +74,7 @@ void DOMError(const std::string& message, const Element* element /*= nullptr*/)
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // print warning, do return
 // print warning, do return
-void DOMWarning(const std::string& message, const Token& token)
-{
+void DOMWarning(const std::string& message, const Token& token) {
     if(DefaultLogger::get()) {
     if(DefaultLogger::get()) {
         ASSIMP_LOG_WARN("FBX-DOM", Util::GetTokenText(&token), message);
         ASSIMP_LOG_WARN("FBX-DOM", Util::GetTokenText(&token), message);
     }
     }

+ 5 - 7
code/AssetLib/FBX/FBXDocumentUtil.h

@@ -74,13 +74,11 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename T>
 template <typename T>
-inline
-const T* ProcessSimpleConnection(const Connection& con,
-    bool is_object_property_conn,
-    const char* name,
-    const Element& element,
-    const char** propNameOut = nullptr)
-{
+inline const T* ProcessSimpleConnection(const Connection& con,
+        bool is_object_property_conn,
+        const char* name,
+        const Element& element,
+        const char** propNameOut = nullptr) {
     if (is_object_property_conn && !con.PropertyName().length()) {
     if (is_object_property_conn && !con.PropertyName().length()) {
         DOMWarning("expected incoming " + std::string(name) +
         DOMWarning("expected incoming " + std::string(name) +
             " link to be an object-object connection, ignoring",
             " link to be an object-object connection, ignoring",

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

@@ -255,7 +255,7 @@ void FBXExporter::WriteBinaryHeader()
 
 
 void FBXExporter::WriteBinaryFooter()
 void FBXExporter::WriteBinaryFooter()
 {
 {
-    outfile->Write(NULL_RECORD.c_str(), NULL_RECORD.size(), 1);
+    outfile->Write(NULL_RECORD, NumNullRecords, 1);
 
 
     outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1);
     outfile->Write(GENERIC_FOOTID.c_str(), GENERIC_FOOTID.size(), 1);
 
 

+ 6 - 0
code/AssetLib/FBX/FBXImportSettings.h

@@ -60,6 +60,7 @@ struct ImportSettings {
             readLights(true),
             readLights(true),
             readAnimations(true),
             readAnimations(true),
             readWeights(true),
             readWeights(true),
+            useSkeleton(false),
             preservePivots(true),
             preservePivots(true),
             optimizeEmptyAnimationCurves(true),
             optimizeEmptyAnimationCurves(true),
             useLegacyEmbeddedTextureNaming(false),
             useLegacyEmbeddedTextureNaming(false),
@@ -112,6 +113,11 @@ struct ImportSettings {
      *  Default value is true. */
      *  Default value is true. */
     bool readWeights;
     bool readWeights;
 
 
+    /** will convert all animation data into a skeleton (experimental)
+     *  Default value is false.
+     */
+    bool useSkeleton;
+
     /** preserve transformation pivots and offsets. Since these can
     /** preserve transformation pivots and offsets. Since these can
      *  not directly be represented in assimp, additional dummy
      *  not directly be represented in assimp, additional dummy
      *  nodes will be generated. Note that settings this to false
      *  nodes will be generated. Note that settings this to false

+ 22 - 25
code/AssetLib/FBX/FBXImporter.cpp

@@ -90,12 +90,9 @@ static const aiImporterDesc desc = {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by #Importer
 // Constructor to be privately used by #Importer
-FBXImporter::FBXImporter() {
-}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-FBXImporter::~FBXImporter() {
+FBXImporter::FBXImporter() :
+        mSettings() {
+    // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -115,20 +112,21 @@ const aiImporterDesc *FBXImporter::GetInfo() const {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Setup configuration properties for the loader
 // Setup configuration properties for the loader
 void FBXImporter::SetupProperties(const Importer *pImp) {
 void FBXImporter::SetupProperties(const Importer *pImp) {
-	settings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
-	settings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
-	settings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
-	settings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
-	settings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
-	settings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
-	settings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
-	settings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
-	settings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
-	settings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
-	settings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
-	settings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
-	settings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
-	settings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
+    mSettings.readAllLayers = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_GEOMETRY_LAYERS, true);
+    mSettings.readAllMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ALL_MATERIALS, false);
+    mSettings.readMaterials = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_MATERIALS, true);
+    mSettings.readTextures = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_TEXTURES, true);
+    mSettings.readCameras = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_CAMERAS, true);
+    mSettings.readLights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_LIGHTS, true);
+    mSettings.readAnimations = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_ANIMATIONS, true);
+    mSettings.readWeights = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_READ_WEIGHTS, true);
+    mSettings.strictMode = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_STRICT_MODE, false);
+    mSettings.preservePivots = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, true);
+    mSettings.optimizeEmptyAnimationCurves = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, true);
+    mSettings.useLegacyEmbeddedTextureNaming = pImp->GetPropertyBool(AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING, false);
+    mSettings.removeEmptyBones = pImp->GetPropertyBool(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true);
+    mSettings.convertToMeters = pImp->GetPropertyBool(AI_CONFIG_FBX_CONVERT_TO_M, false);
+    mSettings.useSkeleton = pImp->GetPropertyBool(AI_CONFIG_FBX_USE_SKELETON_BONE_CONTAINER, false);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -155,7 +153,7 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 	contents[contents.size() - 1] = 0;
 	contents[contents.size() - 1] = 0;
 	const char *const begin = &*contents.begin();
 	const char *const begin = &*contents.begin();
 
 
-	// broadphase tokenizing pass in which we identify the core
+	// broad-phase tokenized pass in which we identify the core
 	// syntax elements of FBX (brackets, commas, key:value mappings)
 	// syntax elements of FBX (brackets, commas, key:value mappings)
 	TokenList tokens;
 	TokenList tokens;
     Assimp::StackAllocator tempAllocator;
     Assimp::StackAllocator tempAllocator;
@@ -173,15 +171,14 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
         Parser parser(tokens, tempAllocator, is_binary);
         Parser parser(tokens, tempAllocator, is_binary);
 
 
 		// take the raw parse-tree and convert it to a FBX DOM
 		// take the raw parse-tree and convert it to a FBX DOM
-		Document doc(parser, settings);
+		Document doc(parser, mSettings);
 
 
 		// convert the FBX DOM to aiScene
 		// convert the FBX DOM to aiScene
-		ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
+		ConvertToAssimpScene(pScene, doc, mSettings.removeEmptyBones);
 
 
 		// size relative to cm
 		// size relative to cm
 		float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
 		float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
-        if (size_relative_to_cm == 0.0)
-        {
+        if (size_relative_to_cm == 0.0) {
 			// BaseImporter later asserts that fileScale is non-zero.
 			// BaseImporter later asserts that fileScale is non-zero.
 			ThrowException("The UnitScaleFactor must be non-zero");
 			ThrowException("The UnitScaleFactor must be non-zero");
         }
         }

+ 7 - 6
code/AssetLib/FBX/FBXImporter.h

@@ -69,13 +69,14 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
 // -------------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------------
 class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
 class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
 public:
 public:
+    /// @brief The class constructor.
     FBXImporter();
     FBXImporter();
-    ~FBXImporter() override;
 
 
-    // --------------------
-    bool CanRead(const std::string &pFile,
-            IOSystem *pIOHandler,
-            bool checkSig) const override;
+    ///	@brief The class destructor, default implementation.
+    ~FBXImporter() override = default;
+
+    /// @brief Will check the file for readability.
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
 
 
 protected:
 protected:
     // --------------------
     // --------------------
@@ -90,7 +91,7 @@ protected:
             IOSystem *pIOHandler) override;
             IOSystem *pIOHandler) override;
 
 
 private:
 private:
-    FBX::ImportSettings settings;
+    FBX::ImportSettings mSettings;
 }; // !class FBXImporter
 }; // !class FBXImporter
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp

+ 3 - 9
code/AssetLib/FBX/FBXMaterial.cpp

@@ -136,9 +136,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Material::~Material() {
-    // empty
-}
+Material::~Material() = default;
 
 
     aiVector2D uvTrans;
     aiVector2D uvTrans;
     aiVector2D uvScaling;
     aiVector2D uvScaling;
@@ -255,9 +253,7 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
 }
 }
 
 
 
 
-Texture::~Texture() {
-    // empty
-}
+Texture::~Texture() = default;
 
 
 LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name) :
 LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Document& /*doc*/, const std::string& name) :
         Object(id,element,name),
         Object(id,element,name),
@@ -276,9 +272,7 @@ LayeredTexture::LayeredTexture(uint64_t id, const Element& element, const Docume
     }
     }
 }
 }
 
 
-LayeredTexture::~LayeredTexture() {
-    // empty
-}
+LayeredTexture::~LayeredTexture() = default;
 
 
 void LayeredTexture::fillTexture(const Document& doc) {
 void LayeredTexture::fillTexture(const Document& doc) {
     const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
     const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());

+ 6 - 26
code/AssetLib/FBX/FBXMeshGeometry.cpp

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2022, assimp team
 Copyright (c) 2006-2022, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -54,18 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "FBXImportSettings.h"
 #include "FBXImportSettings.h"
 #include "FBXDocumentUtil.h"
 #include "FBXDocumentUtil.h"
 
 
-
 namespace Assimp {
 namespace Assimp {
 namespace FBX {
 namespace FBX {
 
 
 using namespace Util;
 using namespace Util;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
-    : Object(id, element, name)
-    , skin()
-{
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
+Geometry::Geometry(uint64_t id, const Element& element, const std::string& name, const Document& doc) :
+        Object(id, element, name), skin() {
+    const std::vector<const Connection*> &conns = doc.GetConnectionsByDestinationSequenced(ID(),"Deformer");
     for(const Connection* con : conns) {
     for(const Connection* con : conns) {
         const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
         const Skin* const sk = ProcessSimpleConnection<Skin>(*con, false, "Skin -> Geometry", element);
         if(sk) {
         if(sk) {
@@ -78,12 +74,6 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
     }
     }
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-Geometry::~Geometry()
-{
-    // empty
-}
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
 const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
     return blendShapes;
     return blendShapes;
@@ -183,18 +173,12 @@ MeshGeometry::MeshGeometry(uint64_t id, const Element& element, const std::strin
         if(doc.Settings().readAllLayers || index == 0) {
         if(doc.Settings().readAllLayers || index == 0) {
             const Scope& layer = GetRequiredScope(*(*it).second);
             const Scope& layer = GetRequiredScope(*(*it).second);
             ReadLayer(layer);
             ReadLayer(layer);
-        }
-        else {
+        } else {
             FBXImporter::LogWarn("ignoring additional geometry layers");
             FBXImporter::LogWarn("ignoring additional geometry layers");
         }
         }
     }
     }
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-MeshGeometry::~MeshGeometry() {
-    // empty
-}
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
 const std::vector<aiVector3D>& MeshGeometry::GetVertices() const {
     return m_vertices;
     return m_vertices;
@@ -681,9 +665,7 @@ ShapeGeometry::ShapeGeometry(uint64_t id, const Element& element, const std::str
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-ShapeGeometry::~ShapeGeometry() {
-    // empty
-}
+ShapeGeometry::~ShapeGeometry() = default;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 const std::vector<aiVector3D>& ShapeGeometry::GetVertices() const {
 const std::vector<aiVector3D>& ShapeGeometry::GetVertices() const {
     return m_vertices;
     return m_vertices;
@@ -711,9 +693,7 @@ LineGeometry::LineGeometry(uint64_t id, const Element& element, const std::strin
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-LineGeometry::~LineGeometry() {
-    // empty
-}
+LineGeometry::~LineGeometry() = default;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 const std::vector<aiVector3D>& LineGeometry::GetVertices() const {
 const std::vector<aiVector3D>& LineGeometry::GetVertices() const {
     return m_vertices;
     return m_vertices;

+ 12 - 9
code/AssetLib/FBX/FBXMeshGeometry.h

@@ -55,22 +55,25 @@ namespace FBX {
 /**
 /**
  *  DOM base class for all kinds of FBX geometry
  *  DOM base class for all kinds of FBX geometry
  */
  */
-class Geometry : public Object
-{
+class Geometry : public Object {
 public:
 public:
+    /// @brief The class constructor with all parameters.
+    /// @param id       The id.
+    /// @param element  
+    /// @param name 
+    /// @param doc 
     Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
     Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
-    virtual ~Geometry();
+    virtual ~Geometry() = default;
 
 
-    /** Get the Skin attached to this geometry or nullptr */
+    /// Get the Skin attached to this geometry or nullptr
     const Skin* DeformerSkin() const;
     const Skin* DeformerSkin() const;
 
 
-    /** Get the BlendShape attached to this geometry or nullptr */
+    /// Get the BlendShape attached to this geometry or nullptr
     const std::vector<const BlendShape*>& GetBlendShapes() const;
     const std::vector<const BlendShape*>& GetBlendShapes() const;
 
 
 private:
 private:
     const Skin* skin;
     const Skin* skin;
     std::vector<const BlendShape*> blendShapes;
     std::vector<const BlendShape*> blendShapes;
-
 };
 };
 
 
 typedef std::vector<int> MatIndexArray;
 typedef std::vector<int> MatIndexArray;
@@ -79,14 +82,13 @@ typedef std::vector<int> MatIndexArray;
 /**
 /**
  *  DOM class for FBX geometry of type "Mesh"
  *  DOM class for FBX geometry of type "Mesh"
  */
  */
-class MeshGeometry : public Geometry
-{
+class MeshGeometry : public Geometry {
 public:
 public:
     /** The class constructor */
     /** The class constructor */
     MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
     MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
 
 
     /** The class destructor */
     /** The class destructor */
-    virtual ~MeshGeometry();
+    virtual ~MeshGeometry() = default;
 
 
     /** Get a list of all vertex points, non-unique*/
     /** Get a list of all vertex points, non-unique*/
     const std::vector<aiVector3D>& GetVertices() const;
     const std::vector<aiVector3D>& GetVertices() const;
@@ -130,6 +132,7 @@ public:
     /** Determine the face to which a particular output vertex index belongs.
     /** Determine the face to which a particular output vertex index belongs.
     *  This mapping is always unique. */
     *  This mapping is always unique. */
     unsigned int FaceForVertexIndex( unsigned int in_index ) const;
     unsigned int FaceForVertexIndex( unsigned int in_index ) const;
+
 private:
 private:
     void ReadLayer( const Scope& layer );
     void ReadLayer( const Scope& layer );
     void ReadLayerElement( const Scope& layerElement );
     void ReadLayerElement( const Scope& layerElement );

+ 29 - 78
code/AssetLib/FBX/FBXNodeAttribute.cpp

@@ -57,114 +57,65 @@ namespace FBX {
 using namespace Util;
 using namespace Util;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-NodeAttribute::NodeAttribute(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: Object(id,element,name)
-, props()
-{
-    const Scope& sc = GetRequiredScope(element);
+NodeAttribute::NodeAttribute(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
+        Object(id, element, name), props() {
+    const Scope &sc = GetRequiredScope(element);
 
 
-    const std::string& classname = ParseTokenAsString(GetRequiredToken(element,2));
+    const std::string &classname = ParseTokenAsString(GetRequiredToken(element, 2));
 
 
     // hack on the deriving type but Null/LimbNode attributes are the only case in which
     // hack on the deriving type but Null/LimbNode attributes are the only case in which
     // the property table is by design absent and no warning should be generated
     // the property table is by design absent and no warning should be generated
     // for it.
     // for it.
     const bool is_null_or_limb = !strcmp(classname.c_str(), "Null") || !strcmp(classname.c_str(), "LimbNode");
     const bool is_null_or_limb = !strcmp(classname.c_str(), "Null") || !strcmp(classname.c_str(), "LimbNode");
-    props = GetPropertyTable(doc,"NodeAttribute.Fbx" + classname,element,sc, is_null_or_limb);
+    props = GetPropertyTable(doc, "NodeAttribute.Fbx" + classname, element, sc, is_null_or_limb);
 }
 }
 
 
-
-// ------------------------------------------------------------------------------------------------
-NodeAttribute::~NodeAttribute()
-{
-    // empty
-}
-
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-CameraSwitcher::CameraSwitcher(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-    : NodeAttribute(id,element,doc,name)
-{
-    const Scope& sc = GetRequiredScope(element);
-    const Element* const CameraId = sc["CameraId"];
-    const Element* const CameraName = sc["CameraName"];
-    const Element* const CameraIndexName = sc["CameraIndexName"];
-
-    if(CameraId) {
-        cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId,0));
+CameraSwitcher::CameraSwitcher(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
+        NodeAttribute(id, element, doc, name) {
+    const Scope &sc = GetRequiredScope(element);
+    const Element *const CameraId = sc["CameraId"];
+    const Element *const CameraName = sc["CameraName"];
+    const Element *const CameraIndexName = sc["CameraIndexName"];
+
+    if (CameraId) {
+        cameraId = ParseTokenAsInt(GetRequiredToken(*CameraId, 0));
     }
     }
 
 
-    if(CameraName) {
-        cameraName = GetRequiredToken(*CameraName,0).StringContents();
+    if (CameraName) {
+        cameraName = GetRequiredToken(*CameraName, 0).StringContents();
     }
     }
 
 
-    if(CameraIndexName && CameraIndexName->Tokens().size()) {
-        cameraIndexName = GetRequiredToken(*CameraIndexName,0).StringContents();
+    if (CameraIndexName && CameraIndexName->Tokens().size()) {
+        cameraIndexName = GetRequiredToken(*CameraIndexName, 0).StringContents();
     }
     }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-CameraSwitcher::~CameraSwitcher()
-{
+Camera::Camera(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
+        NodeAttribute(id, element, doc, name) {
     // empty
     // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Camera::Camera(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: NodeAttribute(id,element,doc,name)
-{
+Light::Light(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
+        NodeAttribute(id, element, doc, name) {
     // empty
     // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Camera::~Camera()
-{
+Null::Null(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
+        NodeAttribute(id, element, doc, name) {
     // empty
     // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Light::Light(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: NodeAttribute(id,element,doc,name)
-{
+LimbNode::LimbNode(uint64_t id, const Element &element, const Document &doc, const std::string &name) :
+        NodeAttribute(id, element, doc, name) {
     // empty
     // empty
 }
 }
 
 
+} // namespace FBX
+} // namespace Assimp
 
 
-// ------------------------------------------------------------------------------------------------
-Light::~Light()
-{
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Null::Null(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: NodeAttribute(id,element,doc,name)
-{
-
-}
-
-
-// ------------------------------------------------------------------------------------------------
-Null::~Null()
-{
-
-}
-
-
-// ------------------------------------------------------------------------------------------------
-LimbNode::LimbNode(uint64_t id, const Element& element, const Document& doc, const std::string& name)
-: NodeAttribute(id,element,doc,name)
-{
-
-}
-
-
-// ------------------------------------------------------------------------------------------------
-LimbNode::~LimbNode()
-{
-
-}
-
-}
-}
-
-#endif
+#endif // ASSIMP_BUILD_NO_FBX_IMPORTER

+ 10 - 13
code/AssetLib/FBX/FBXParser.cpp

@@ -175,7 +175,6 @@ Element::~Element()
      // no need to delete tokens, they are owned by the parser
      // no need to delete tokens, they are owned by the parser
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
 Scope::Scope(Parser& parser,bool topLevel)
 Scope::Scope(Parser& parser,bool topLevel)
 {
 {
     if(!topLevel) {
     if(!topLevel) {
@@ -638,9 +637,9 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
         if (type == 'd') {
         if (type == 'd') {
             const double* d = reinterpret_cast<const double*>(&buff[0]);
             const double* d = reinterpret_cast<const double*>(&buff[0]);
             for (unsigned int i = 0; i < count3; ++i, d += 3) {
             for (unsigned int i = 0; i < count3; ++i, d += 3) {
-                out.push_back(aiVector3D(static_cast<ai_real>(d[0]),
+                out.emplace_back(static_cast<ai_real>(d[0]),
                     static_cast<ai_real>(d[1]),
                     static_cast<ai_real>(d[1]),
-                    static_cast<ai_real>(d[2])));
+                    static_cast<ai_real>(d[2]));
             }
             }
             // for debugging
             // for debugging
             /*for ( size_t i = 0; i < out.size(); i++ ) {
             /*for ( size_t i = 0; i < out.size(); i++ ) {
@@ -653,7 +652,7 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
         else if (type == 'f') {
         else if (type == 'f') {
             const float* f = reinterpret_cast<const float*>(&buff[0]);
             const float* f = reinterpret_cast<const float*>(&buff[0]);
             for (unsigned int i = 0; i < count3; ++i, f += 3) {
             for (unsigned int i = 0; i < count3; ++i, f += 3) {
-                out.push_back(aiVector3D(f[0],f[1],f[2]));
+                out.emplace_back(f[0],f[1],f[2]);
             }
             }
         }
         }
 
 
@@ -727,16 +726,16 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
         if (type == 'd') {
         if (type == 'd') {
             const double* d = reinterpret_cast<const double*>(&buff[0]);
             const double* d = reinterpret_cast<const double*>(&buff[0]);
             for (unsigned int i = 0; i < count4; ++i, d += 4) {
             for (unsigned int i = 0; i < count4; ++i, d += 4) {
-                out.push_back(aiColor4D(static_cast<float>(d[0]),
+                out.emplace_back(static_cast<float>(d[0]),
                     static_cast<float>(d[1]),
                     static_cast<float>(d[1]),
                     static_cast<float>(d[2]),
                     static_cast<float>(d[2]),
-                    static_cast<float>(d[3])));
+                    static_cast<float>(d[3]));
             }
             }
         }
         }
         else if (type == 'f') {
         else if (type == 'f') {
             const float* f = reinterpret_cast<const float*>(&buff[0]);
             const float* f = reinterpret_cast<const float*>(&buff[0]);
             for (unsigned int i = 0; i < count4; ++i, f += 4) {
             for (unsigned int i = 0; i < count4; ++i, f += 4) {
-                out.push_back(aiColor4D(f[0],f[1],f[2],f[3]));
+                out.emplace_back(f[0],f[1],f[2],f[3]);
             }
             }
         }
         }
         return;
         return;
@@ -808,13 +807,13 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el) {
         if (type == 'd') {
         if (type == 'd') {
             const double* d = reinterpret_cast<const double*>(&buff[0]);
             const double* d = reinterpret_cast<const double*>(&buff[0]);
             for (unsigned int i = 0; i < count2; ++i, d += 2) {
             for (unsigned int i = 0; i < count2; ++i, d += 2) {
-                out.push_back(aiVector2D(static_cast<float>(d[0]),
-                    static_cast<float>(d[1])));
+                out.emplace_back(static_cast<float>(d[0]),
+                    static_cast<float>(d[1]));
             }
             }
         } else if (type == 'f') {
         } else if (type == 'f') {
             const float* f = reinterpret_cast<const float*>(&buff[0]);
             const float* f = reinterpret_cast<const float*>(&buff[0]);
             for (unsigned int i = 0; i < count2; ++i, f += 2) {
             for (unsigned int i = 0; i < count2; ++i, f += 2) {
-                out.push_back(aiVector2D(f[0],f[1]));
+                out.emplace_back(f[0],f[1]);
             }
             }
         }
         }
 
 
@@ -968,8 +967,7 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // read an array of uints
 // read an array of uints
-void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
-{
+void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el) {
     out.resize( 0 );
     out.resize( 0 );
     const TokenList& tok = el.Tokens();
     const TokenList& tok = el.Tokens();
     if(tok.empty()) {
     if(tok.empty()) {
@@ -1193,7 +1191,6 @@ aiMatrix4x4 ReadMatrix(const Element& element)
     return result;
     return result;
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // wrapper around ParseTokenAsString() with ParseError handling
 // wrapper around ParseTokenAsString() with ParseError handling
 std::string ParseTokenAsString(const Token& t)
 std::string ParseTokenAsString(const Token& t)

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

@@ -89,7 +89,7 @@ class Element
 {
 {
 public:
 public:
     Element(const Token& key_token, Parser& parser);
     Element(const Token& key_token, Parser& parser);
-    ~Element();
+    ~Element() = default;
 
 
     const Scope* Compound() const {
     const Scope* Compound() const {
         return compound;
         return compound;

+ 13 - 19
code/AssetLib/FBX/FBXProperties.cpp

@@ -60,29 +60,23 @@ namespace FBX {
     using namespace Util;
     using namespace Util;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Property::Property()
-{
-}
+    Property::Property() = default;
 
 
-// ------------------------------------------------------------------------------------------------
-Property::~Property()
-{
-}
+    // ------------------------------------------------------------------------------------------------
+    Property::~Property() = default;
 
 
-namespace {
+    namespace {
 
 
-void checkTokenCount(const TokenList& tok, unsigned int expectedCount)
-{
-    ai_assert(expectedCount >= 2);
-    if (tok.size() < expectedCount) {
-        const std::string& s = ParseTokenAsString(*tok[1]);
-        if (tok[1]->IsBinary()) {
-            throw DeadlyImportError("Not enough tokens for property of type ", s, " at offset ", tok[1]->Offset());
-        }
-        else {
-            throw DeadlyImportError("Not enough tokens for property of type ", s, " at line ", tok[1]->Line());
+    void checkTokenCount(const TokenList &tok, unsigned int expectedCount) {
+        ai_assert(expectedCount >= 2);
+        if (tok.size() < expectedCount) {
+            const std::string &s = ParseTokenAsString(*tok[1]);
+            if (tok[1]->IsBinary()) {
+                throw DeadlyImportError("Not enough tokens for property of type ", s, " at offset ", tok[1]->Offset());
+            } else {
+                throw DeadlyImportError("Not enough tokens for property of type ", s, " at line ", tok[1]->Line());
+            }
         }
         }
-    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 1 - 3
code/AssetLib/FBX/FBXTokenizer.cpp

@@ -79,9 +79,7 @@ Token::Token(const char* sbegin, const char* send, TokenType type, unsigned int
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Token::~Token()
-{
-}
+
 
 
 namespace {
 namespace {
 
 

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

@@ -97,7 +97,7 @@ public:
     /** construct a binary token */
     /** construct a binary token */
     Token(const char* sbegin, const char* send, TokenType type, size_t offset);
     Token(const char* sbegin, const char* send, TokenType type, size_t offset);
 
 
-    ~Token();
+    ~Token() = default;
 
 
 public:
 public:
     std::string StringContents() const {
     std::string StringContents() const {

+ 2 - 6
code/AssetLib/HMP/HMPLoader.cpp

@@ -72,15 +72,11 @@ static const aiImporterDesc desc = {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
-HMPImporter::HMPImporter() {
-    // nothing to do here
-}
+HMPImporter::HMPImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-HMPImporter::~HMPImporter() {
-    // nothing to do here
-}
+HMPImporter::~HMPImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.

+ 3 - 3
code/AssetLib/IFC/IFCBoolean.cpp

@@ -310,7 +310,7 @@ bool IntersectsBoundaryProfile(const IfcVector3 &e0, const IfcVector3 &e1, const
                 if (IfcVector2(diff.x, diff.y).SquareLength() < 1e-10)
                 if (IfcVector2(diff.x, diff.y).SquareLength() < 1e-10)
                     continue;
                     continue;
             }
             }
-            intersect_results.push_back(std::make_pair(i, e0));
+            intersect_results.emplace_back(i, e0);
             continue;
             continue;
         }
         }
 
 
@@ -324,7 +324,7 @@ bool IntersectsBoundaryProfile(const IfcVector3 &e0, const IfcVector3 &e1, const
                 if (IfcVector2(diff.x, diff.y).SquareLength() < 1e-10)
                 if (IfcVector2(diff.x, diff.y).SquareLength() < 1e-10)
                     continue;
                     continue;
             }
             }
-            intersect_results.push_back(std::make_pair(i, p));
+            intersect_results.emplace_back(i, p);
         }
         }
     }
     }
 
 
@@ -504,7 +504,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly
                 }
                 }
                 // now add them to the list of intersections
                 // now add them to the list of intersections
                 for (size_t b = 0; b < intersected_boundary.size(); ++b)
                 for (size_t b = 0; b < intersected_boundary.size(); ++b)
-                    intersections.push_back(std::make_tuple(a, proj_inv * intersected_boundary[b].second, intersected_boundary[b].first));
+                    intersections.emplace_back(a, proj_inv * intersected_boundary[b].second, intersected_boundary[b].first);
 
 
                 // and calculate our new inside/outside state
                 // and calculate our new inside/outside state
                 if (intersected_boundary.size() & 1)
                 if (intersected_boundary.size() & 1)

+ 5 - 3
code/AssetLib/IFC/IFCCurve.cpp

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2022, assimp team
 Copyright (c) 2006-2022, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -51,7 +50,6 @@ namespace Assimp {
 namespace IFC {
 namespace IFC {
 namespace {
 namespace {
 
 
-
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 // Conic is the base class for Circle and Ellipse
 // Conic is the base class for Circle and Ellipse
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
@@ -226,7 +224,7 @@ public:
                 IFCImporter::LogVerboseDebug("ignoring transition code on composite curve segment, only continuous transitions are supported");
                 IFCImporter::LogVerboseDebug("ignoring transition code on composite curve segment, only continuous transitions are supported");
             }
             }
 
 
-            curves.push_back( CurveEntry(bc,IsTrue(curveSegment.SameSense)) );
+            curves.emplace_back(bc,IsTrue(curveSegment.SameSense) );
             total += bc->GetParametricRangeDelta();
             total += bc->GetParametricRangeDelta();
         }
         }
 
 
@@ -546,8 +544,10 @@ IfcFloat RecursiveSearch(const Curve* cv, const IfcVector3& val, IfcFloat a, Ifc
         }
         }
     }
     }
 
 
+#ifndef __INTEL_LLVM_COMPILER
     ai_assert( min_diff[ 0 ] != inf );
     ai_assert( min_diff[ 0 ] != inf );
     ai_assert( min_diff[ 1 ] != inf );
     ai_assert( min_diff[ 1 ] != inf );
+#endif // __INTEL_LLVM_COMPILER
     if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
     if ( std::fabs(a-min_point[0]) < threshold || recurse >= max_recurse) {
         return min_point[0];
         return min_point[0];
     }
     }
@@ -606,8 +606,10 @@ bool BoundedCurve::IsClosed() const {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void BoundedCurve::SampleDiscrete(TempMesh& out) const {
 void BoundedCurve::SampleDiscrete(TempMesh& out) const {
     const ParamRange& range = GetParametricRange();
     const ParamRange& range = GetParametricRange();
+#ifndef __INTEL_LLVM_COMPILER
     ai_assert( range.first != std::numeric_limits<IfcFloat>::infinity() );
     ai_assert( range.first != std::numeric_limits<IfcFloat>::infinity() );
     ai_assert( range.second != std::numeric_limits<IfcFloat>::infinity() );
     ai_assert( range.second != std::numeric_limits<IfcFloat>::infinity() );
+#endif // __INTEL_LLVM_COMPILER
 
 
     return SampleDiscrete(out,range.first,range.second);
     return SampleDiscrete(out,range.first,range.second);
 }
 }

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

@@ -170,7 +170,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
             continue;
             continue;
         }
         }
 
 
-        fake_openings.push_back(TempOpening());
+        fake_openings.emplace_back();
         TempOpening& opening = fake_openings.back();
         TempOpening& opening = fake_openings.back();
 
 
         opening.extrusionDir = master_normal;
         opening.extrusionDir = master_normal;
@@ -612,7 +612,7 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
             TempMesh& bounds = *t.profileMesh.get();
             TempMesh& bounds = *t.profileMesh.get();
 
 
             if( bounds.mVerts.size() <= 2 ) {
             if( bounds.mVerts.size() <= 2 ) {
-                nors.push_back(IfcVector3());
+                nors.emplace_back();
                 continue;
                 continue;
             }
             }
             auto nor = ((bounds.mVerts[2] - bounds.mVerts[0]) ^ (bounds.mVerts[1] - bounds.mVerts[0])).Normalize();
             auto nor = ((bounds.mVerts[2] - bounds.mVerts[0]) ^ (bounds.mVerts[1] - bounds.mVerts[0])).Normalize();

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

@@ -120,12 +120,11 @@ static const aiImporterDesc desc = {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
-IFCImporter::IFCImporter() {}
+IFCImporter::IFCImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-IFCImporter::~IFCImporter() {
-}
+IFCImporter::~IFCImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.

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

@@ -114,9 +114,9 @@ void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField&
     if (!found) {
     if (!found) {
         // the rectangle [pmin,pend] is opaque, fill it
         // the rectangle [pmin,pend] is opaque, fill it
         out.push_back(pmin);
         out.push_back(pmin);
-        out.push_back(IfcVector2(pmin.x,pmax.y));
+        out.emplace_back(pmin.x,pmax.y);
         out.push_back(pmax);
         out.push_back(pmax);
-        out.push_back(IfcVector2(pmax.x,pmin.y));
+        out.emplace_back(pmax.x,pmin.y);
         return;
         return;
     }
     }
 
 
@@ -126,9 +126,9 @@ void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField&
     // see if there's an offset to fill at the top of our quad
     // see if there's an offset to fill at the top of our quad
     if (xs - pmin.x) {
     if (xs - pmin.x) {
         out.push_back(pmin);
         out.push_back(pmin);
-        out.push_back(IfcVector2(pmin.x,pmax.y));
-        out.push_back(IfcVector2(xs,pmax.y));
-        out.push_back(IfcVector2(xs,pmin.y));
+        out.emplace_back(pmin.x,pmax.y);
+        out.emplace_back(xs,pmax.y);
+        out.emplace_back(xs,pmin.y);
     }
     }
 
 
     // search along the y-axis for all openings that overlap xs and our quad
     // search along the y-axis for all openings that overlap xs and our quad
@@ -159,10 +159,10 @@ void QuadrifyPart(const IfcVector2& pmin, const IfcVector2& pmax, XYSortedField&
     }
     }
     if (!found) {
     if (!found) {
         // the rectangle [pmin,pend] is opaque, fill it
         // the rectangle [pmin,pend] is opaque, fill it
-        out.push_back(IfcVector2(xs,pmin.y));
-        out.push_back(IfcVector2(xs,pmax.y));
-        out.push_back(IfcVector2(xe,pmax.y));
-        out.push_back(IfcVector2(xe,pmin.y));
+        out.emplace_back(xs,pmin.y);
+        out.emplace_back(xs,pmax.y);
+        out.emplace_back(xe,pmax.y);
+        out.emplace_back(xe,pmin.y);
         return;
         return;
     }
     }
     if (ylast < pmax.y) {
     if (ylast < pmax.y) {
@@ -342,7 +342,7 @@ void InsertWindowContours(const ContourVector& contours,
                         if ((contour[a] - edge).SquareLength() > diag*diag*0.7) {
                         if ((contour[a] - edge).SquareLength() > diag*diag*0.7) {
                             continue;
                             continue;
                         }
                         }
-                        curmesh.mVerts.push_back(IfcVector3(contour[a].x, contour[a].y, 0.0f));
+                        curmesh.mVerts.emplace_back(contour[a].x, contour[a].y, 0.0f);
                     }
                     }
 
 
                     if (edge != contour[last_hit]) {
                     if (edge != contour[last_hit]) {
@@ -363,7 +363,7 @@ void InsertWindowContours(const ContourVector& contours,
                             corner.y = bb.second.y;
                             corner.y = bb.second.y;
                         }
                         }
 
 
-                        curmesh.mVerts.push_back(IfcVector3(corner.x, corner.y, 0.0f));
+                        curmesh.mVerts.emplace_back(corner.x, corner.y, 0.0f);
                     }
                     }
                     else if (cnt == 1) {
                     else if (cnt == 1) {
                         // avoid degenerate polygons (also known as lines or points)
                         // avoid degenerate polygons (also known as lines or points)
@@ -399,7 +399,7 @@ void MergeWindowContours (const std::vector<IfcVector2>& a,
     ClipperLib::Polygon clip;
     ClipperLib::Polygon clip;
 
 
     for(const IfcVector2& pip : a) {
     for(const IfcVector2& pip : a) {
-        clip.push_back(ClipperLib::IntPoint(  to_int64(pip.x), to_int64(pip.y) ));
+        clip.emplace_back(to_int64(pip.x), to_int64(pip.y));
     }
     }
 
 
     if (ClipperLib::Orientation(clip)) {
     if (ClipperLib::Orientation(clip)) {
@@ -410,7 +410,7 @@ void MergeWindowContours (const std::vector<IfcVector2>& a,
     clip.clear();
     clip.clear();
 
 
     for(const IfcVector2& pip : b) {
     for(const IfcVector2& pip : b) {
-        clip.push_back(ClipperLib::IntPoint(  to_int64(pip.x), to_int64(pip.y) ));
+        clip.emplace_back(to_int64(pip.x), to_int64(pip.y));
     }
     }
 
 
     if (ClipperLib::Orientation(clip)) {
     if (ClipperLib::Orientation(clip)) {
@@ -433,7 +433,7 @@ void MakeDisjunctWindowContours (const std::vector<IfcVector2>& a,
     ClipperLib::Polygon clip;
     ClipperLib::Polygon clip;
 
 
     for(const IfcVector2& pip : a) {
     for(const IfcVector2& pip : a) {
-        clip.push_back(ClipperLib::IntPoint(  to_int64(pip.x), to_int64(pip.y) ));
+        clip.emplace_back(to_int64(pip.x), to_int64(pip.y));
     }
     }
 
 
     if (ClipperLib::Orientation(clip)) {
     if (ClipperLib::Orientation(clip)) {
@@ -444,7 +444,7 @@ void MakeDisjunctWindowContours (const std::vector<IfcVector2>& a,
     clip.clear();
     clip.clear();
 
 
     for(const IfcVector2& pip : b) {
     for(const IfcVector2& pip : b) {
-        clip.push_back(ClipperLib::IntPoint(  to_int64(pip.x), to_int64(pip.y) ));
+        clip.emplace_back(to_int64(pip.x), to_int64(pip.y));
     }
     }
 
 
     if (ClipperLib::Orientation(clip)) {
     if (ClipperLib::Orientation(clip)) {
@@ -466,7 +466,7 @@ void CleanupWindowContour(ProjectedWindowContour& window)
     ClipperLib::ExPolygons clipped;
     ClipperLib::ExPolygons clipped;
 
 
     for(const IfcVector2& pip : contour) {
     for(const IfcVector2& pip : contour) {
-        subject.push_back(ClipperLib::IntPoint(  to_int64(pip.x), to_int64(pip.y) ));
+        subject.emplace_back(to_int64(pip.x), to_int64(pip.y));
     }
     }
 
 
     clipper.AddPolygon(subject,ClipperLib::ptSubject);
     clipper.AddPolygon(subject,ClipperLib::ptSubject);
@@ -524,7 +524,7 @@ void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh&
         ClipperLib::Polygon clip;
         ClipperLib::Polygon clip;
         clip.reserve(contour_flat.size());
         clip.reserve(contour_flat.size());
         for(const IfcVector2& pip : contour_flat) {
         for(const IfcVector2& pip : contour_flat) {
-            clip.push_back(ClipperLib::IntPoint(  to_int64(pip.x), to_int64(pip.y) ));
+            clip.emplace_back(to_int64(pip.x), to_int64(pip.y));
         }
         }
 
 
         if (!ClipperLib::Orientation(clip)) {
         if (!ClipperLib::Orientation(clip)) {
@@ -544,7 +544,7 @@ void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh&
                     continue;
                     continue;
                 }
                 }
             }
             }
-            subject.push_back(ClipperLib::IntPoint(  to_int64(pip.x), to_int64(pip.y) ));
+            subject.emplace_back(to_int64(pip.x), to_int64(pip.y));
             if (--countdown == 0) {
             if (--countdown == 0) {
                 if (!ClipperLib::Orientation(subject)) {
                 if (!ClipperLib::Orientation(subject)) {
                     std::reverse(subject.begin(), subject.end());
                     std::reverse(subject.begin(), subject.end());
@@ -558,10 +558,10 @@ void CleanupOuterContour(const std::vector<IfcVector2>& contour_flat, TempMesh&
                 for(const ClipperLib::ExPolygon& ex : clipped) {
                 for(const ClipperLib::ExPolygon& ex : clipped) {
                     iold.push_back(static_cast<unsigned int>(ex.outer.size()));
                     iold.push_back(static_cast<unsigned int>(ex.outer.size()));
                     for(const ClipperLib::IntPoint& point : ex.outer) {
                     for(const ClipperLib::IntPoint& point : ex.outer) {
-                        vold.push_back(IfcVector3(
+                        vold.emplace_back(
                             from_int64(point.X),
                             from_int64(point.X),
                             from_int64(point.Y),
                             from_int64(point.Y),
-                            0.0f));
+                            0.0f);
                     }
                     }
                 }
                 }
 
 
@@ -1039,7 +1039,7 @@ void Quadrify(const std::vector< BoundingBox >& bbs, TempMesh& curmesh)
     curmesh.mVertcnt.resize(quads.size()/4,4);
     curmesh.mVertcnt.resize(quads.size()/4,4);
     curmesh.mVerts.reserve(quads.size());
     curmesh.mVerts.reserve(quads.size());
     for(const IfcVector2& v2 : quads) {
     for(const IfcVector2& v2 : quads) {
-        curmesh.mVerts.push_back(IfcVector3(v2.x, v2.y, static_cast<IfcFloat>(0.0)));
+        curmesh.mVerts.emplace_back(v2.x, v2.y, static_cast<IfcFloat>(0.0));
     }
     }
 }
 }
 
 
@@ -1095,7 +1095,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
         vmin = std::min(vv, vmin);
         vmin = std::min(vv, vmin);
         vmax = std::max(vv, vmax);
         vmax = std::max(vv, vmax);
 
 
-        out_contour.push_back(IfcVector2(vv.x,vv.y));
+        out_contour.emplace_back(vv.x,vv.y);
     }
     }
 
 
     zcoord /= in_verts.size();
     zcoord /= in_verts.size();
@@ -1128,7 +1128,7 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
     for(const IfcVector3& x : in_verts) {
     for(const IfcVector3& x : in_verts) {
         const IfcVector3& vv = m * x;
         const IfcVector3& vv = m * x;
 
 
-        out_contour2.push_back(IfcVector2(vv.x,vv.y));
+        out_contour2.emplace_back(vv.x,vv.y);
         ai_assert(std::fabs(vv.z) < vmax.z + 1e-8);
         ai_assert(std::fabs(vv.z) < vmax.z + 1e-8);
     }
     }
 
 
@@ -1378,12 +1378,12 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
 
 
         if(!temp_contour.empty()) {
         if(!temp_contour.empty()) {
             if (generate_connection_geometry) {
             if (generate_connection_geometry) {
-                contours_to_openings.push_back(std::vector<TempOpening*>(
-                    joined_openings.begin(),
-                    joined_openings.end()));
+                contours_to_openings.emplace_back(
+                        joined_openings.begin(),
+                        joined_openings.end());
             }
             }
 
 
-            contours.push_back(ProjectedWindowContour(temp_contour, bb, is_rectangle));
+            contours.emplace_back(temp_contour, bb, is_rectangle);
         }
         }
     }
     }
 
 
@@ -1428,7 +1428,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
     return true;
     return true;
 }
 }
 
 
-std::vector<IfcVector2> GetContourInPlane2D(std::shared_ptr<TempMesh> mesh,IfcMatrix3 planeSpace,
+std::vector<IfcVector2> GetContourInPlane2D(const std::shared_ptr<TempMesh>& mesh,IfcMatrix3 planeSpace,
     IfcVector3 planeNor,IfcFloat planeOffset,
     IfcVector3 planeNor,IfcFloat planeOffset,
     IfcVector3 extrusionDir,IfcVector3& wall_extrusion,bool& first,bool& ok) {
     IfcVector3 extrusionDir,IfcVector3& wall_extrusion,bool& first,bool& ok) {
     std::vector<IfcVector2> contour;
     std::vector<IfcVector2> contour;
@@ -1469,7 +1469,7 @@ std::vector<IfcVector2> GetContourInPlane2D(std::shared_ptr<TempMesh> mesh,IfcMa
 
 
         // XXX should not be necessary - but it is. Why? For precision reasons?
         // XXX should not be necessary - but it is. Why? For precision reasons?
         vv = is_extruded_side ? vv_extr : vv;
         vv = is_extruded_side ? vv_extr : vv;
-        contour.push_back(IfcVector2(vv.x,vv.y));
+        contour.emplace_back(vv.x,vv.y);
     }
     }
     ok = true;
     ok = true;
 
 
@@ -1491,7 +1491,7 @@ static void logSegment(std::pair<IfcVector2,IfcVector2> segment) {
     IFCImporter::LogInfo(msg2.str().c_str());
     IFCImporter::LogInfo(msg2.str().c_str());
 }
 }
 
 
-std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(std::shared_ptr<TempMesh> mesh,IfcMatrix3 planeSpace,
+std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(const std::shared_ptr<TempMesh>& mesh,IfcMatrix3 planeSpace,
     IfcFloat planeOffset) {
     IfcFloat planeOffset) {
 
 
         {
         {
@@ -1676,7 +1676,7 @@ std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(std::shared_ptr<TempMe
             std::stringstream msg;
             std::stringstream msg;
             msg << "GetContoursInPlane3D: found " << contours.size() << " contours:\n";
             msg << "GetContoursInPlane3D: found " << contours.size() << " contours:\n";
 
 
-            for(auto c : contours) {
+            for(const auto& c : contours) {
                 msg << " Contour: \n";
                 msg << " Contour: \n";
                 for(auto p : c) {
                 for(auto p : c) {
                     msg << "   " << p.x << " " << p.y << " \n";
                     msg << "   " << p.x << " " << p.y << " \n";
@@ -1690,7 +1690,7 @@ std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(std::shared_ptr<TempMe
         return contours;
         return contours;
 }
 }
 
 
-std::vector<std::vector<IfcVector2>> GetContoursInPlane(std::shared_ptr<TempMesh> mesh,IfcMatrix3 planeSpace,
+std::vector<std::vector<IfcVector2>> GetContoursInPlane(const std::shared_ptr<TempMesh>& mesh,IfcMatrix3 planeSpace,
     IfcVector3 planeNor,IfcFloat planeOffset,
     IfcVector3 planeNor,IfcFloat planeOffset,
     IfcVector3 extrusionDir,IfcVector3& wall_extrusion,bool& first) {
     IfcVector3 extrusionDir,IfcVector3& wall_extrusion,bool& first) {
 
 
@@ -1758,7 +1758,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
         vmin = std::min(IfcVector2(vv.x, vv.y), vmin);
         vmin = std::min(IfcVector2(vv.x, vv.y), vmin);
         vmax = std::max(IfcVector2(vv.x, vv.y), vmax);
         vmax = std::max(IfcVector2(vv.x, vv.y), vmax);
 
 
-        contour_flat.push_back(IfcVector2(vv.x,vv.y));
+        contour_flat.emplace_back(vv.x,vv.y);
     }
     }
 
 
     // With the current code in DerivePlaneCoordinateSpace,
     // With the current code in DerivePlaneCoordinateSpace,
@@ -1791,7 +1791,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
                     pip.x = (pip.x - vmin.x) / vmax.x;
                     pip.x = (pip.x - vmin.x) / vmax.x;
                     pip.y = (pip.y - vmin.y) / vmax.y;
                     pip.y = (pip.y - vmin.y) / vmax.y;
 
 
-                    hole.push_back(ClipperLib::IntPoint(to_int64(pip.x),to_int64(pip.y)));
+                    hole.emplace_back(to_int64(pip.x), to_int64(pip.y));
                 }
                 }
 
 
                 if(!ClipperLib::Orientation(hole)) {
                 if(!ClipperLib::Orientation(hole)) {
@@ -1833,7 +1833,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
                 pip.x  = (pip.x - vmin.x) / vmax.x;
                 pip.x  = (pip.x - vmin.x) / vmax.x;
                 pip.y  = (pip.y - vmin.y) / vmax.y;
                 pip.y  = (pip.y - vmin.y) / vmax.y;
 
 
-                poly.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
+                poly.emplace_back(to_int64(pip.x), to_int64(pip.y));
             }
             }
 
 
             if (ClipperLib::Orientation(poly)) {
             if (ClipperLib::Orientation(poly)) {
@@ -1891,7 +1891,7 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
         // Build the poly2tri inner contours for all holes we got from ClipperLib
         // Build the poly2tri inner contours for all holes we got from ClipperLib
         for(ClipperLib::Polygon& opening : clip.holes) {
         for(ClipperLib::Polygon& opening : clip.holes) {
 
 
-            contours.push_back(std::vector<p2t::Point*>());
+            contours.emplace_back();
             std::vector<p2t::Point*>& contour = contours.back();
             std::vector<p2t::Point*>& contour = contours.back();
 
 
             for(ClipperLib::IntPoint& point : opening) {
             for(ClipperLib::IntPoint& point : opening) {

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

@@ -108,10 +108,10 @@ void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& de
         const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
         const IfcFloat x = cprofile->XDim*0.5f, y = cprofile->YDim*0.5f;
 
 
         meshout.mVerts.reserve(meshout.mVerts.size()+4);
         meshout.mVerts.reserve(meshout.mVerts.size()+4);
-        meshout.mVerts.push_back( IfcVector3( x, y, 0.f ));
-        meshout.mVerts.push_back( IfcVector3(-x, y, 0.f ));
-        meshout.mVerts.push_back( IfcVector3(-x,-y, 0.f ));
-        meshout.mVerts.push_back( IfcVector3( x,-y, 0.f ));
+        meshout.mVerts.emplace_back( x, y, 0.f );
+        meshout.mVerts.emplace_back(-x, y, 0.f );
+        meshout.mVerts.emplace_back(-x,-y, 0.f );
+        meshout.mVerts.emplace_back( x,-y, 0.f );
         meshout.mVertcnt.push_back(4);
         meshout.mVertcnt.push_back(4);
     }
     }
     else if( const Schema_2x3::IfcCircleProfileDef* const circle = def.ToPtr<Schema_2x3::IfcCircleProfileDef>()) {
     else if( const Schema_2x3::IfcCircleProfileDef* const circle = def.ToPtr<Schema_2x3::IfcCircleProfileDef>()) {
@@ -125,7 +125,7 @@ void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& de
 
 
         IfcFloat angle = 0.f;
         IfcFloat angle = 0.f;
         for(size_t i = 0; i < segments; ++i, angle += delta) {
         for(size_t i = 0; i < segments; ++i, angle += delta) {
-            meshout.mVerts.push_back( IfcVector3( std::cos(angle)*radius, std::sin(angle)*radius, 0.f ));
+            meshout.mVerts.emplace_back( std::cos(angle)*radius, std::sin(angle)*radius, 0.f );
         }
         }
 
 
         meshout.mVertcnt.push_back(static_cast<unsigned int>(segments));
         meshout.mVertcnt.push_back(static_cast<unsigned int>(segments));
@@ -136,18 +136,18 @@ void ProcessParametrizedProfile(const Schema_2x3::IfcParameterizedProfileDef& de
         const IfcFloat inner_height = ishape->OverallDepth - ishape->FlangeThickness * 2;
         const IfcFloat inner_height = ishape->OverallDepth - ishape->FlangeThickness * 2;
 
 
         meshout.mVerts.reserve(12);
         meshout.mVerts.reserve(12);
-        meshout.mVerts.push_back(IfcVector3(0,0,0));
-        meshout.mVerts.push_back(IfcVector3(0,ishape->FlangeThickness,0));
-        meshout.mVerts.push_back(IfcVector3(offset,ishape->FlangeThickness,0));
-        meshout.mVerts.push_back(IfcVector3(offset,ishape->FlangeThickness + inner_height,0));
-        meshout.mVerts.push_back(IfcVector3(0,ishape->FlangeThickness + inner_height,0));
-        meshout.mVerts.push_back(IfcVector3(0,ishape->OverallDepth,0));
-        meshout.mVerts.push_back(IfcVector3(ishape->OverallWidth,ishape->OverallDepth,0));
-        meshout.mVerts.push_back(IfcVector3(ishape->OverallWidth,ishape->FlangeThickness + inner_height,0));
-        meshout.mVerts.push_back(IfcVector3(offset+ishape->WebThickness,ishape->FlangeThickness + inner_height,0));
-        meshout.mVerts.push_back(IfcVector3(offset+ishape->WebThickness,ishape->FlangeThickness,0));
-        meshout.mVerts.push_back(IfcVector3(ishape->OverallWidth,ishape->FlangeThickness,0));
-        meshout.mVerts.push_back(IfcVector3(ishape->OverallWidth,0,0));
+        meshout.mVerts.emplace_back(0,0,0);
+        meshout.mVerts.emplace_back(0,ishape->FlangeThickness,0);
+        meshout.mVerts.emplace_back(offset,ishape->FlangeThickness,0);
+        meshout.mVerts.emplace_back(offset,ishape->FlangeThickness + inner_height,0);
+        meshout.mVerts.emplace_back(0,ishape->FlangeThickness + inner_height,0);
+        meshout.mVerts.emplace_back(0,ishape->OverallDepth,0);
+        meshout.mVerts.emplace_back(ishape->OverallWidth,ishape->OverallDepth,0);
+        meshout.mVerts.emplace_back(ishape->OverallWidth,ishape->FlangeThickness + inner_height,0);
+        meshout.mVerts.emplace_back(offset+ishape->WebThickness,ishape->FlangeThickness + inner_height,0);
+        meshout.mVerts.emplace_back(offset+ishape->WebThickness,ishape->FlangeThickness,0);
+        meshout.mVerts.emplace_back(ishape->OverallWidth,ishape->FlangeThickness,0);
+        meshout.mVerts.emplace_back(ishape->OverallWidth,0,0);
 
 
         meshout.mVertcnt.push_back(12);
         meshout.mVertcnt.push_back(12);
     }
     }

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

@@ -201,7 +201,7 @@ void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
     size_t vidx = std::accumulate(mVertcnt.begin(),begin,0);
     size_t vidx = std::accumulate(mVertcnt.begin(),begin,0);
     for(iit = begin; iit != end; vidx += *iit++) {
     for(iit = begin; iit != end; vidx += *iit++) {
         if (!*iit) {
         if (!*iit) {
-            normals.push_back(IfcVector3());
+            normals.emplace_back();
             continue;
             continue;
         }
         }
         for(size_t vofs = 0, cnt = 0; vofs < *iit; ++vofs) {
         for(size_t vofs = 0, cnt = 0; vofs < *iit; ++vofs) {
@@ -215,7 +215,7 @@ void TempMesh::ComputePolygonNormals(std::vector<IfcVector3>& normals,
             ++cnt;
             ++cnt;
         }
         }
 
 
-        normals.push_back(IfcVector3());
+        normals.emplace_back();
         NewellNormal<4,4,4>(normals.back(),*iit,&temp[0],&temp[1],&temp[2]);
         NewellNormal<4,4,4>(normals.back(),*iit,&temp[0],&temp[1],&temp[2]);
     }
     }
 
 

+ 1 - 2
code/AssetLib/IFC/IFCUtil.h

@@ -344,8 +344,7 @@ protected:
 public:
 public:
     typedef std::pair<IfcFloat, IfcFloat> ParamRange;
     typedef std::pair<IfcFloat, IfcFloat> ParamRange;
 
 
-    virtual ~Curve() {}
-
+    virtual ~Curve() = default;
 
 
     // check if a curve is closed
     // check if a curve is closed
     virtual bool IsClosed() const = 0;
     virtual bool IsClosed() const = 0;

+ 2 - 2
code/AssetLib/IQM/IQMImporter.h

@@ -56,9 +56,9 @@ class IQMImporter : public BaseImporter {
 public:
 public:
 	/// \brief  Default constructor
 	/// \brief  Default constructor
 	IQMImporter();
 	IQMImporter();
-    ~IQMImporter() override {}
+    ~IQMImporter() override = default;
 
 
-	/// \brief  Returns whether the class can handle the format of the given file.
+    /// \brief  Returns whether the class can handle the format of the given file.
 	/// \remark See BaseImporter::CanRead() for details.
 	/// \remark See BaseImporter::CanRead() for details.
 	bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
 	bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
 
 

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

@@ -88,9 +88,7 @@ IRRImporter::IRRImporter() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-IRRImporter::~IRRImporter() {
-	// empty
-}
+IRRImporter::~IRRImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -628,7 +626,7 @@ void IRRImporter::GenerateGraph(Node *root, aiNode *rootOut, aiScene *scene,
 				ASSIMP_LOG_ERROR("IRR: Unable to load external file: ", root->meshPath);
 				ASSIMP_LOG_ERROR("IRR: Unable to load external file: ", root->meshPath);
 				break;
 				break;
 			}
 			}
-			attach.push_back(AttachmentInfo(localScene, rootOut));
+			attach.emplace_back(localScene, rootOut);
 
 
 			// Now combine the material we've loaded for this mesh
 			// Now combine the material we've loaded for this mesh
 			// with the real materials we got from the file. As we
 			// with the real materials we got from the file. As we
@@ -874,7 +872,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 
 
 	// Batch loader used to load external models
 	// Batch loader used to load external models
 	BatchLoader batch(pIOHandler);
 	BatchLoader batch(pIOHandler);
-	//  batch.SetBasePath(pFile);
+	//batch.SetBasePath(pFile);
 
 
 	cameras.reserve(5);
 	cameras.reserve(5);
 	lights.reserve(5);
 	lights.reserve(5);
@@ -979,7 +977,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 					// Materials can occur for nearly any type of node
 					// Materials can occur for nearly any type of node
 					if (inMaterials && curNode->type != Node::DUMMY) {
 					if (inMaterials && curNode->type != Node::DUMMY) {
 						//  This is a material description - parse it!
 						//  This is a material description - parse it!
-						curNode->materials.push_back(std::pair<aiMaterial *, unsigned int>());
+						curNode->materials.emplace_back();
 						std::pair<aiMaterial *, unsigned int> &p = curNode->materials.back();
 						std::pair<aiMaterial *, unsigned int> &p = curNode->materials.back();
 
 
 						p.first = ParseMaterial(p.second);
 						p.first = ParseMaterial(p.second);
@@ -988,7 +986,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 					} else if (inAnimator) {
 					} else if (inAnimator) {
 						//  This is an animation path - add a new animator
 						//  This is an animation path - add a new animator
 						//  to the list.
 						//  to the list.
-						curNode->animators.push_back(Animator());
+						curNode->animators.emplace_back();
 						curAnim = &curNode->animators.back();
 						curAnim = &curNode->animators.back();
 
 
 						++guessedAnimCnt;
 						++guessedAnimCnt;
@@ -1015,7 +1013,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 										// here N is the ONE-based index of the point
 										// here N is the ONE-based index of the point
 										if (prop.name.length() >= 6 && prop.name.substr(0, 5) == "Point") {
 										if (prop.name.length() >= 6 && prop.name.substr(0, 5) == "Point") {
 											// Add a new key to the list
 											// Add a new key to the list
-											curAnim->splineKeys.push_back(aiVectorKey());
+											curAnim->splineKeys.emplace_back();
 											aiVectorKey &key = curAnim->splineKeys.back();
 											aiVectorKey &key = curAnim->splineKeys.back();
 
 
 											// and parse its properties
 											// and parse its properties

+ 1 - 2
code/AssetLib/Irr/IRRLoader.h

@@ -206,8 +206,7 @@ private:
      */
      */
     struct SkyboxVertex
     struct SkyboxVertex
     {
     {
-        SkyboxVertex()
-        {}
+        SkyboxVertex() = default;
 
 
         //! Construction from single vertex components
         //! Construction from single vertex components
         SkyboxVertex(ai_real px, ai_real py, ai_real pz,
         SkyboxVertex(ai_real px, ai_real py, ai_real pz,

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

@@ -79,7 +79,7 @@ IRRMeshImporter::IRRMeshImporter() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-IRRMeshImporter::~IRRMeshImporter() {}
+IRRMeshImporter::~IRRMeshImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.

+ 1 - 1
code/AssetLib/LWO/LWOBLoader.cpp

@@ -218,7 +218,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.push_back(LWO::Texture());
+    list.emplace_back();
     LWO::Texture* tex = &list.back();
     LWO::Texture* tex = &list.back();
 
 
     std::string type;
     std::string type;

+ 2 - 8
code/AssetLib/LWO/LWOFileData.h

@@ -338,13 +338,7 @@ struct Face : public aiFace {
     uint32_t type;
     uint32_t type;
 
 
     //! Assignment operator
     //! Assignment operator
-    Face &operator=(const LWO::Face &f) {
-        aiFace::operator=(f);
-        surfaceIndex = f.surfaceIndex;
-        smoothGroup = f.smoothGroup;
-        type = f.type;
-        return *this;
-    }
+    Face &operator=(const LWO::Face &f) = default;
 };
 };
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -354,7 +348,7 @@ struct VMapEntry {
     explicit VMapEntry(unsigned int _dims) :
     explicit VMapEntry(unsigned int _dims) :
             dims(_dims) {}
             dims(_dims) {}
 
 
-    virtual ~VMapEntry() {}
+    virtual ~VMapEntry() = default;
 
 
     //! allocates memory for the vertex map
     //! allocates memory for the vertex map
     virtual void Allocate(unsigned int num) {
     virtual void Allocate(unsigned int num) {

+ 9 - 11
code/AssetLib/LWO/LWOLoader.cpp

@@ -100,9 +100,7 @@ LWOImporter::LWOImporter() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-LWOImporter::~LWOImporter() {
-    // empty
-}
+LWOImporter::~LWOImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -287,7 +285,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
             if (UINT_MAX == iDefaultSurface) {
             if (UINT_MAX == iDefaultSurface) {
                 pSorted.erase(pSorted.end() - 1);
                 pSorted.erase(pSorted.end() - 1);
             }
             }
-            for (unsigned int p = 0, j = 0; j < mSurfaces->size(); ++j) {
+            for (unsigned int j = 0; j < mSurfaces->size(); ++j) {
                 SortedRep &sorted = pSorted[j];
                 SortedRep &sorted = pSorted[j];
                 if (sorted.empty())
                 if (sorted.empty())
                     continue;
                     continue;
@@ -425,7 +423,6 @@ void LWOImporter::InternReadFile(const std::string &pFile,
                 } else {
                 } else {
                     ASSIMP_LOG_VERBOSE_DEBUG("LWO2: No need to compute normals, they're already there");
                     ASSIMP_LOG_VERBOSE_DEBUG("LWO2: No need to compute normals, they're already there");
                 }
                 }
-                ++p;
             }
             }
         }
         }
 
 
@@ -1098,7 +1095,7 @@ void LWOImporter::LoadLWO2VertexMap(unsigned int length, bool perPoly) {
 void LWOImporter::LoadLWO2Clip(unsigned int length) {
 void LWOImporter::LoadLWO2Clip(unsigned int length) {
     AI_LWO_VALIDATE_CHUNK_LENGTH(length, CLIP, 10);
     AI_LWO_VALIDATE_CHUNK_LENGTH(length, CLIP, 10);
 
 
-    mClips.push_back(LWO::Clip());
+    mClips.emplace_back();
     LWO::Clip &clip = mClips.back();
     LWO::Clip &clip = mClips.back();
 
 
     // first - get the index of the clip
     // first - get the index of the clip
@@ -1168,7 +1165,7 @@ void LWOImporter::LoadLWO2Clip(unsigned int length) {
 void LWOImporter::LoadLWO3Clip(unsigned int length) {
 void LWOImporter::LoadLWO3Clip(unsigned int length) {
     AI_LWO_VALIDATE_CHUNK_LENGTH(length, CLIP, 12);
     AI_LWO_VALIDATE_CHUNK_LENGTH(length, CLIP, 12);
 
 
-    mClips.push_back(LWO::Clip());
+    mClips.emplace_back();
     LWO::Clip &clip = mClips.back();
     LWO::Clip &clip = mClips.back();
 
 
     // first - get the index of the clip
     // first - get the index of the clip
@@ -1241,7 +1238,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) {
     LE_NCONST uint8_t *const end = mFileBuffer + length;
     LE_NCONST uint8_t *const end = mFileBuffer + length;
     AI_LWO_VALIDATE_CHUNK_LENGTH(length, ENVL, 4);
     AI_LWO_VALIDATE_CHUNK_LENGTH(length, ENVL, 4);
 
 
-    mEnvelopes.push_back(LWO::Envelope());
+    mEnvelopes.emplace_back();
     LWO::Envelope &envelope = mEnvelopes.back();
     LWO::Envelope &envelope = mEnvelopes.back();
 
 
     // Get the index of the envelope
     // Get the index of the envelope
@@ -1293,7 +1290,7 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) {
             case AI_LWO_KEY: {
             case AI_LWO_KEY: {
                 AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, KEY, 8);
                 AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, KEY, 8);
 
 
-                envelope.keys.push_back(LWO::Key());
+                envelope.keys.emplace_back();
                 LWO::Key &key = envelope.keys.back();
                 LWO::Key &key = envelope.keys.back();
 
 
                 key.time = GetF4();
                 key.time = GetF4();
@@ -1349,7 +1346,7 @@ void LWOImporter::LoadLWO3Envelope(unsigned int length) {
     LE_NCONST uint8_t *const end = mFileBuffer + length;
     LE_NCONST uint8_t *const end = mFileBuffer + length;
     AI_LWO_VALIDATE_CHUNK_LENGTH(length, ENVL, 4);
     AI_LWO_VALIDATE_CHUNK_LENGTH(length, ENVL, 4);
 
 
-    mEnvelopes.push_back(LWO::Envelope());
+    mEnvelopes.emplace_back();
     LWO::Envelope &envelope = mEnvelopes.back();
     LWO::Envelope &envelope = mEnvelopes.back();
 
 
     // Get the index of the envelope
     // Get the index of the envelope
@@ -1391,7 +1388,7 @@ void LWOImporter::LoadLWO3Envelope(unsigned int length) {
             case AI_LWO_KEY: {
             case AI_LWO_KEY: {
                 AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, KEY, 10);
                 AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, KEY, 10);
 
 
-                envelope.keys.push_back(LWO::Key());
+                envelope.keys.emplace_back();
                 LWO::Key &key = envelope.keys.back();
                 LWO::Key &key = envelope.keys.back();
 
 
                 key.time = GetF4();
                 key.time = GetF4();
@@ -1541,6 +1538,7 @@ void LWOImporter::LoadLWO2File() {
                     break;
                     break;
                 }
                 }
                 // --- intentionally no break here
                 // --- intentionally no break here
+                // fallthrough
             case AI_LWO_VMAP: {
             case AI_LWO_VMAP: {
                 if (skip)
                 if (skip)
                     break;
                     break;

+ 0 - 2
code/AssetLib/LWO/LWOMaterial.cpp

@@ -707,12 +707,10 @@ void LWOImporter::LoadNodalBlocks(unsigned int size) {
         if (mFileBuffer + head.length > end) {
         if (mFileBuffer + head.length > end) {
             throw DeadlyImportError("LWO3: cannot read length; LoadNodalBlocks");
             throw DeadlyImportError("LWO3: cannot read length; LoadNodalBlocks");
         }
         }
-        int node_idx = 0;
         uint8_t *const next = mFileBuffer + head.length;
         uint8_t *const next = mFileBuffer + head.length;
         mFileBuffer += bufOffset;
         mFileBuffer += bufOffset;
         switch (head.type) {
         switch (head.type) {
         case AI_LWO_NNDS:
         case AI_LWO_NNDS:
-            node_idx++;
             LoadNodes(head.length);
             LoadNodes(head.length);
             break;
             break;
         }
         }

+ 10 - 13
code/AssetLib/LWS/LWSLoader.cpp

@@ -90,7 +90,7 @@ void LWS::Element::Parse(const char *&buffer) {
         } else if (*buffer == '}')
         } else if (*buffer == '}')
             return;
             return;
 
 
-        children.push_back(Element());
+        children.emplace_back();
 
 
         // copy data line - read token per token
         // copy data line - read token per token
 
 
@@ -141,9 +141,7 @@ LWSImporter::LWSImporter() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-LWSImporter::~LWSImporter() {
-    // nothing to do here
-}
+LWSImporter::~LWSImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -199,7 +197,7 @@ void LWSImporter::ReadEnvelope(const LWS::Element &dad, LWO::Envelope &fill) {
         const char *c = (*it).tokens[1].c_str();
         const char *c = (*it).tokens[1].c_str();
 
 
         if ((*it).tokens[0] == "Key") {
         if ((*it).tokens[0] == "Key") {
-            fill.keys.push_back(LWO::Key());
+            fill.keys.emplace_back();
             LWO::Key &key = fill.keys.back();
             LWO::Key &key = fill.keys.back();
 
 
             float f;
             float f;
@@ -262,7 +260,7 @@ void LWSImporter::ReadEnvelope_Old(
     num = strtoul10((*it).tokens[0].c_str());
     num = strtoul10((*it).tokens[0].c_str());
     for (unsigned int i = 0; i < num; ++i) {
     for (unsigned int i = 0; i < num; ++i) {
 
 
-        nodes.channels.push_back(LWO::Envelope());
+        nodes.channels.emplace_back();
         LWO::Envelope &envl = nodes.channels.back();
         LWO::Envelope &envl = nodes.channels.back();
 
 
         envl.index = i;
         envl.index = i;
@@ -313,6 +311,9 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
             std::string::size_type t = src.path.substr(s).find_last_of('.');
             std::string::size_type t = src.path.substr(s).find_last_of('.');
 
 
             nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
             nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
+            if (nd->mName.length > MAXLEN) {
+                nd->mName.length = MAXLEN;
+            }
             return;
             return;
         }
         }
     }
     }
@@ -381,7 +382,7 @@ void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vector<Attachm
 
 
         //Push attachment, if the object came from an external file
         //Push attachment, if the object came from an external file
         if (obj) {
         if (obj) {
-            attach.push_back(AttachmentInfo(obj, nd));
+            attach.emplace_back(obj, nd);
         }
         }
     }
     }
 
 
@@ -513,7 +514,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
     std::list<LWS::NodeDesc> nodes;
     std::list<LWS::NodeDesc> nodes;
 
 
     unsigned int cur_light = 0, cur_camera = 0, cur_object = 0;
     unsigned int cur_light = 0, cur_camera = 0, cur_object = 0;
-    unsigned int num_light = 0, num_camera = 0, num_object = 0;
+    unsigned int num_light = 0, num_camera = 0;
 
 
     // check magic identifier, 'LWSC'
     // check magic identifier, 'LWSC'
     bool motion_file = false;
     bool motion_file = false;
@@ -583,7 +584,6 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
             d.id = batch.AddLoadRequest(path, 0, &props);
             d.id = batch.AddLoadRequest(path, 0, &props);
 
 
             nodes.push_back(d);
             nodes.push_back(d);
-            ++num_object;
         } else if ((*it).tokens[0] == "LoadObject") { // 'LoadObject': load a LWO file into the scene-graph
         } else if ((*it).tokens[0] == "LoadObject") { // 'LoadObject': load a LWO file into the scene-graph
 
 
             // add node to list
             // add node to list
@@ -601,7 +601,6 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 
 
             d.path = path;
             d.path = path;
             nodes.push_back(d);
             nodes.push_back(d);
-            ++num_object;
         } else if ((*it).tokens[0] == "AddNullObject") { // 'AddNullObject': add a dummy node to the hierarchy
         } else if ((*it).tokens[0] == "AddNullObject") { // 'AddNullObject': add a dummy node to the hierarchy
 
 
             // add node to list
             // add node to list
@@ -615,8 +614,6 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
             }
             }
             d.name = c;
             d.name = c;
             nodes.push_back(d);
             nodes.push_back(d);
-
-            num_object++;
         }
         }
         // 'NumChannels': Number of envelope channels assigned to last layer
         // 'NumChannels': Number of envelope channels assigned to last layer
         else if ((*it).tokens[0] == "NumChannels") {
         else if ((*it).tokens[0] == "NumChannels") {
@@ -638,7 +635,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
             }
             }
 
 
             // important: index of channel
             // important: index of channel
-            nodes.back().channels.push_back(LWO::Envelope());
+            nodes.back().channels.emplace_back();
             LWO::Envelope &env = nodes.back().channels.back();
             LWO::Envelope &env = nodes.back().channels.back();
 
 
             env.index = strtoul10(c);
             env.index = strtoul10(c);

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

@@ -69,7 +69,7 @@ namespace LWS {
  */
  */
 class Element {
 class Element {
 public:
 public:
-    Element() {}
+    Element() = default;
 
 
     // first: name, second: rest
     // first: name, second: rest
     std::string tokens[2];
     std::string tokens[2];

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

@@ -57,9 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // Assimp specific M3D configuration. Comment out these defines to remove functionality
 // Assimp specific M3D configuration. Comment out these defines to remove functionality
 //#define ASSIMP_USE_M3D_READFILECB
 //#define ASSIMP_USE_M3D_READFILECB
 
 
-// Share stb_image's PNG loader with other importers/exporters instead of bringing our own copy.
-#define STBI_ONLY_PNG
-#include <stb/stb_image.h>
+#include "Common/StbCommon.h"
 
 
 #include "m3d.h"
 #include "m3d.h"
 
 

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

@@ -102,8 +102,7 @@ MD2Importer::MD2Importer()
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-MD2Importer::~MD2Importer()
-{}
+MD2Importer::~MD2Importer() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.

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

@@ -144,7 +144,7 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem *
                 if (*buff == '{') {
                 if (*buff == '{') {
                     ++buff;
                     ++buff;
                     // add new map section
                     // add new map section
-                    curData->maps.push_back(Q3Shader::ShaderMapBlock());
+                    curData->maps.emplace_back();
                     curMap = &curData->maps.back();
                     curMap = &curData->maps.back();
 
 
                     for (; SkipSpacesAndLineEnd(&buff); SkipLine(&buff)) {
                     for (; SkipSpacesAndLineEnd(&buff); SkipLine(&buff)) {
@@ -209,7 +209,7 @@ bool Q3Shader::LoadShader(ShaderData &fill, const std::string &pFile, IOSystem *
             }
             }
         } else {
         } else {
             // add new section
             // add new section
-            fill.blocks.push_back(Q3Shader::ShaderDataBlock());
+            fill.blocks.emplace_back();
             curData = &fill.blocks.back();
             curData = &fill.blocks.back();
 
 
             // get the name of this section
             // get the name of this section
@@ -249,7 +249,7 @@ bool Q3Shader::LoadSkin(SkinData &fill, const std::string &pFile, IOSystem *io)
         if (!::strncmp(&ss[0], "tag_", std::min((size_t)4, ss.length())))
         if (!::strncmp(&ss[0], "tag_", std::min((size_t)4, ss.length())))
             continue;
             continue;
 
 
-        fill.textures.push_back(SkinData::TextureEntry());
+        fill.textures.emplace_back();
         SkinData::TextureEntry &entry = fill.textures.back();
         SkinData::TextureEntry &entry = fill.textures.back();
 
 
         entry.first = ss;
         entry.first = ss;
@@ -345,7 +345,7 @@ MD3Importer::MD3Importer() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-MD3Importer::~MD3Importer() {}
+MD3Importer::~MD3Importer() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -584,7 +584,7 @@ bool MD3Importer::ReadMultipartFile() {
 
 
         // original root
         // original root
         scene_lower->mRootNode->mName.Set("lower");
         scene_lower->mRootNode->mName.Set("lower");
-        attach.push_back(AttachmentInfo(scene_lower, nd));
+        attach.emplace_back(scene_lower, nd);
 
 
         // tag_torso
         // tag_torso
         tag_torso = scene_lower->mRootNode->FindNode("tag_torso");
         tag_torso = scene_lower->mRootNode->FindNode("tag_torso");
@@ -593,7 +593,7 @@ bool MD3Importer::ReadMultipartFile() {
             goto error_cleanup;
             goto error_cleanup;
         }
         }
         scene_upper->mRootNode->mName.Set("upper");
         scene_upper->mRootNode->mName.Set("upper");
-        attach.push_back(AttachmentInfo(scene_upper, tag_torso));
+        attach.emplace_back(scene_upper, tag_torso);
 
 
         // tag_head
         // tag_head
         tag_head = scene_upper->mRootNode->FindNode("tag_head");
         tag_head = scene_upper->mRootNode->FindNode("tag_head");
@@ -602,7 +602,7 @@ bool MD3Importer::ReadMultipartFile() {
             goto error_cleanup;
             goto error_cleanup;
         }
         }
         scene_head->mRootNode->mName.Set("head");
         scene_head->mRootNode->mName.Set("head");
-        attach.push_back(AttachmentInfo(scene_head, tag_head));
+        attach.emplace_back(scene_head, tag_head);
 
 
         // Remove tag_head and tag_torso from all other model parts ...
         // Remove tag_head and tag_torso from all other model parts ...
         // this ensures (together with AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY)
         // this ensures (together with AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY)

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

@@ -94,9 +94,7 @@ MD5Importer::MD5Importer() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-MD5Importer::~MD5Importer() {
-    // empty
-}
+MD5Importer::~MD5Importer() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.

+ 8 - 8
code/AssetLib/MD5/MD5Parser.cpp

@@ -76,7 +76,7 @@ MD5Parser::MD5Parser(char *_buffer, unsigned int _fileSize) {
     // and read all sections until we're finished
     // and read all sections until we're finished
     bool running = true;
     bool running = true;
     while (running) {
     while (running) {
-        mSections.push_back(Section());
+        mSections.emplace_back();
         Section &sec = mSections.back();
         Section &sec = mSections.back();
         if (!ParseSection(sec)) {
         if (!ParseSection(sec)) {
             break;
             break;
@@ -158,7 +158,7 @@ bool MD5Parser::ParseSection(Section &out) {
                     break;
                     break;
                 }
                 }
 
 
-                out.mElements.push_back(Element());
+                out.mElements.emplace_back();
                 Element &elem = out.mElements.back();
                 Element &elem = out.mElements.back();
 
 
                 elem.iLineNumber = lineNumber;
                 elem.iLineNumber = lineNumber;
@@ -253,7 +253,7 @@ MD5MeshParser::MD5MeshParser(SectionList &mSections) {
         } else if ((*iter).mName == "joints") {
         } else if ((*iter).mName == "joints") {
             // "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 )
             // "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 )
             for (const auto &elem : (*iter).mElements) {
             for (const auto &elem : (*iter).mElements) {
-                mJoints.push_back(BoneDesc());
+                mJoints.emplace_back();
                 BoneDesc &desc = mJoints.back();
                 BoneDesc &desc = mJoints.back();
 
 
                 const char *sz = elem.szStart;
                 const char *sz = elem.szStart;
@@ -267,7 +267,7 @@ MD5MeshParser::MD5MeshParser(SectionList &mSections) {
                 AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there
                 AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there
             }
             }
         } else if ((*iter).mName == "mesh") {
         } else if ((*iter).mName == "mesh") {
-            mMeshes.push_back(MeshDesc());
+            mMeshes.emplace_back();
             MeshDesc &desc = mMeshes.back();
             MeshDesc &desc = mMeshes.back();
 
 
             for (const auto &elem : (*iter).mElements) {
             for (const auto &elem : (*iter).mElements) {
@@ -364,7 +364,7 @@ MD5AnimParser::MD5AnimParser(SectionList &mSections) {
         if ((*iter).mName == "hierarchy") {
         if ((*iter).mName == "hierarchy") {
             // "sheath" 0 63 6
             // "sheath" 0 63 6
             for (const auto &elem : (*iter).mElements) {
             for (const auto &elem : (*iter).mElements) {
-                mAnimatedBones.push_back(AnimBoneDesc());
+                mAnimatedBones.emplace_back();
                 AnimBoneDesc &desc = mAnimatedBones.back();
                 AnimBoneDesc &desc = mAnimatedBones.back();
 
 
                 const char *sz = elem.szStart;
                 const char *sz = elem.szStart;
@@ -389,7 +389,7 @@ MD5AnimParser::MD5AnimParser(SectionList &mSections) {
             for (const auto &elem : (*iter).mElements) {
             for (const auto &elem : (*iter).mElements) {
                 const char *sz = elem.szStart;
                 const char *sz = elem.szStart;
 
 
-                mBaseFrames.push_back(BaseFrameDesc());
+                mBaseFrames.emplace_back();
                 BaseFrameDesc &desc = mBaseFrames.back();
                 BaseFrameDesc &desc = mBaseFrames.back();
 
 
                 AI_MD5_READ_TRIPLE(desc.vPositionXYZ);
                 AI_MD5_READ_TRIPLE(desc.vPositionXYZ);
@@ -401,7 +401,7 @@ MD5AnimParser::MD5AnimParser(SectionList &mSections) {
                 continue;
                 continue;
             }
             }
 
 
-            mFrames.push_back(FrameDesc());
+            mFrames.emplace_back();
             FrameDesc &desc = mFrames.back();
             FrameDesc &desc = mFrames.back();
             desc.iIndex = strtoul10((*iter).mGlobalValue.c_str());
             desc.iIndex = strtoul10((*iter).mGlobalValue.c_str());
 
 
@@ -459,7 +459,7 @@ MD5CameraParser::MD5CameraParser(SectionList &mSections) {
             for (const auto &elem : (*iter).mElements) {
             for (const auto &elem : (*iter).mElements) {
                 const char *sz = elem.szStart;
                 const char *sz = elem.szStart;
 
 
-                frames.push_back(CameraAnimFrameDesc());
+                frames.emplace_back();
                 CameraAnimFrameDesc &cur = frames.back();
                 CameraAnimFrameDesc &cur = frames.back();
                 AI_MD5_READ_TRIPLE(cur.vPositionXYZ);
                 AI_MD5_READ_TRIPLE(cur.vPositionXYZ);
                 AI_MD5_READ_TRIPLE(cur.vRotationQuat);
                 AI_MD5_READ_TRIPLE(cur.vRotationQuat);

+ 4 - 6
code/AssetLib/MDC/MDCLoader.cpp

@@ -105,9 +105,7 @@ MDCImporter::MDCImporter() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-MDCImporter::~MDCImporter() {
-    // empty
-}
+MDCImporter::~MDCImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -271,13 +269,13 @@ void MDCImporter::InternReadFile(
             pcMesh->mMaterialIndex = (unsigned int)aszShaders.size();
             pcMesh->mMaterialIndex = (unsigned int)aszShaders.size();
 
 
             // create a new shader
             // create a new shader
-            aszShaders.push_back(std::string(pcShader->ucName,
-                    ::strnlen(pcShader->ucName, sizeof(pcShader->ucName))));
+            aszShaders.emplace_back(pcShader->ucName,
+                    ::strnlen(pcShader->ucName, sizeof(pcShader->ucName)));
         }
         }
         // need to create a default material
         // need to create a default material
         else if (UINT_MAX == iDefaultMatIndex) {
         else if (UINT_MAX == iDefaultMatIndex) {
             pcMesh->mMaterialIndex = iDefaultMatIndex = (unsigned int)aszShaders.size();
             pcMesh->mMaterialIndex = iDefaultMatIndex = (unsigned int)aszShaders.size();
-            aszShaders.push_back(std::string());
+            aszShaders.emplace_back();
         }
         }
         // otherwise assign a reference to the default material
         // otherwise assign a reference to the default material
         else
         else

+ 1 - 2
code/AssetLib/MDL/HalfLife/UniqueNameGenerator.cpp

@@ -68,8 +68,7 @@ UniqueNameGenerator::UniqueNameGenerator(const char *template_name, const char *
     separator_(separator) {
     separator_(separator) {
 }
 }
 
 
-UniqueNameGenerator::~UniqueNameGenerator() {
-}
+UniqueNameGenerator::~UniqueNameGenerator() = default;
 
 
 void UniqueNameGenerator::make_unique(std::vector<std::string> &names) {
 void UniqueNameGenerator::make_unique(std::vector<std::string> &names) {
     struct DuplicateInfo {
     struct DuplicateInfo {

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

@@ -98,9 +98,7 @@ MDLImporter::MDLImporter() :
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-MDLImporter::~MDLImporter() {
-    // empty
-}
+MDLImporter::~MDLImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.

+ 3 - 0
code/AssetLib/MDL/MDLMaterialLoader.cpp

@@ -449,6 +449,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
         unsigned int iWidth,
         unsigned int iWidth,
         unsigned int iHeight) {
         unsigned int iHeight) {
     std::unique_ptr<aiTexture> pcNew;
     std::unique_ptr<aiTexture> pcNew;
+    if (szCurrent == nullptr) {
+        return;
+    }
 
 
     // get the type of the skin
     // get the type of the skin
     unsigned int iMasked = (unsigned int)(iType & 0xF);
     unsigned int iMasked = (unsigned int)(iType & 0xF);

Certains fichiers n'ont pas été affichés car il y a eu trop de fichiers modifiés dans ce diff