Explorar o código

Merge pull request #1338 from marauder2k9-torque/AssimpImporter-update

Assimp importer update
Brian Roberts hai 9 meses
pai
achega
70f546aafe
Modificáronse 100 ficheiros con 2228 adicións e 1716 borrados
  1. 3 2
      Engine/lib/CMakeLists.txt
  2. 47 48
      Engine/lib/assimp/Build.md
  3. 171 98
      Engine/lib/assimp/CMakeLists.txt
  4. 128 0
      Engine/lib/assimp/CODE_OF_CONDUCT.md
  5. 7 10
      Engine/lib/assimp/Dockerfile
  6. 41 47
      Engine/lib/assimp/Readme.md
  7. 0 29
      Engine/lib/assimp/cmake-modules/HunterGate.cmake
  8. 0 8
      Engine/lib/assimp/code/.editorconfig
  9. 17 9
      Engine/lib/assimp/code/AssetLib/3DS/3DSConverter.cpp
  10. 2 1
      Engine/lib/assimp/code/AssetLib/3DS/3DSExporter.cpp
  11. 3 5
      Engine/lib/assimp/code/AssetLib/3DS/3DSExporter.h
  12. 8 124
      Engine/lib/assimp/code/AssetLib/3DS/3DSHelper.h
  13. 13 8
      Engine/lib/assimp/code/AssetLib/3DS/3DSLoader.cpp
  14. 2 3
      Engine/lib/assimp/code/AssetLib/3DS/3DSLoader.h
  15. 22 8
      Engine/lib/assimp/code/AssetLib/3MF/3MFTypes.h
  16. 6 1
      Engine/lib/assimp/code/AssetLib/3MF/3MFXmlTags.h
  17. 6 6
      Engine/lib/assimp/code/AssetLib/3MF/D3MFExporter.cpp
  18. 1 1
      Engine/lib/assimp/code/AssetLib/3MF/D3MFExporter.h
  19. 10 9
      Engine/lib/assimp/code/AssetLib/3MF/D3MFImporter.cpp
  20. 3 3
      Engine/lib/assimp/code/AssetLib/3MF/D3MFImporter.h
  21. 9 12
      Engine/lib/assimp/code/AssetLib/3MF/D3MFOpcPackage.cpp
  22. 1 1
      Engine/lib/assimp/code/AssetLib/3MF/D3MFOpcPackage.h
  23. 142 34
      Engine/lib/assimp/code/AssetLib/3MF/XmlSerializer.cpp
  24. 4 1
      Engine/lib/assimp/code/AssetLib/3MF/XmlSerializer.h
  25. 121 120
      Engine/lib/assimp/code/AssetLib/AC/ACLoader.cpp
  26. 5 5
      Engine/lib/assimp/code/AssetLib/AC/ACLoader.h
  27. 14 37
      Engine/lib/assimp/code/AssetLib/AMF/AMFImporter.cpp
  28. 50 52
      Engine/lib/assimp/code/AssetLib/AMF/AMFImporter.hpp
  29. 4 4
      Engine/lib/assimp/code/AssetLib/AMF/AMFImporter_Geometry.cpp
  30. 7 8
      Engine/lib/assimp/code/AssetLib/AMF/AMFImporter_Material.cpp
  31. 5 22
      Engine/lib/assimp/code/AssetLib/AMF/AMFImporter_Node.hpp
  32. 6 4
      Engine/lib/assimp/code/AssetLib/AMF/AMFImporter_Postprocess.cpp
  33. 22 39
      Engine/lib/assimp/code/AssetLib/ASE/ASELoader.cpp
  34. 5 6
      Engine/lib/assimp/code/AssetLib/ASE/ASELoader.h
  35. 215 190
      Engine/lib/assimp/code/AssetLib/ASE/ASEParser.cpp
  36. 14 14
      Engine/lib/assimp/code/AssetLib/ASE/ASEParser.h
  37. 1 1
      Engine/lib/assimp/code/AssetLib/Assbin/AssbinExporter.cpp
  38. 2 2
      Engine/lib/assimp/code/AssetLib/Assbin/AssbinExporter.h
  39. 5 9
      Engine/lib/assimp/code/AssetLib/Assbin/AssbinFileWriter.cpp
  40. 1 1
      Engine/lib/assimp/code/AssetLib/Assbin/AssbinFileWriter.h
  41. 7 3
      Engine/lib/assimp/code/AssetLib/Assbin/AssbinLoader.cpp
  42. 1 1
      Engine/lib/assimp/code/AssetLib/Assbin/AssbinLoader.h
  43. 1 1
      Engine/lib/assimp/code/AssetLib/Assjson/cencode.c
  44. 67 54
      Engine/lib/assimp/code/AssetLib/Assjson/json_exporter.cpp
  45. 1 1
      Engine/lib/assimp/code/AssetLib/Assxml/AssxmlExporter.cpp
  46. 1 1
      Engine/lib/assimp/code/AssetLib/Assxml/AssxmlExporter.h
  47. 2 2
      Engine/lib/assimp/code/AssetLib/Assxml/AssxmlFileWriter.cpp
  48. 1 1
      Engine/lib/assimp/code/AssetLib/Assxml/AssxmlFileWriter.h
  49. 19 18
      Engine/lib/assimp/code/AssetLib/B3D/B3DImporter.cpp
  50. 1 1
      Engine/lib/assimp/code/AssetLib/B3D/B3DImporter.h
  51. 29 29
      Engine/lib/assimp/code/AssetLib/BVH/BVHLoader.cpp
  52. 1 1
      Engine/lib/assimp/code/AssetLib/BVH/BVHLoader.h
  53. 3 4
      Engine/lib/assimp/code/AssetLib/Blender/BlenderBMesh.cpp
  54. 2 2
      Engine/lib/assimp/code/AssetLib/Blender/BlenderBMesh.h
  55. 2 1
      Engine/lib/assimp/code/AssetLib/Blender/BlenderCustomData.cpp
  56. 2 2
      Engine/lib/assimp/code/AssetLib/Blender/BlenderDNA.cpp
  57. 13 4
      Engine/lib/assimp/code/AssetLib/Blender/BlenderDNA.h
  58. 1 1
      Engine/lib/assimp/code/AssetLib/Blender/BlenderDNA.inl
  59. 1 1
      Engine/lib/assimp/code/AssetLib/Blender/BlenderIntermediate.h
  60. 75 74
      Engine/lib/assimp/code/AssetLib/Blender/BlenderLoader.cpp
  61. 14 1
      Engine/lib/assimp/code/AssetLib/Blender/BlenderLoader.h
  62. 6 1
      Engine/lib/assimp/code/AssetLib/Blender/BlenderModifier.cpp
  63. 2 4
      Engine/lib/assimp/code/AssetLib/Blender/BlenderModifier.h
  64. 2 6
      Engine/lib/assimp/code/AssetLib/Blender/BlenderScene.cpp
  65. 8 19
      Engine/lib/assimp/code/AssetLib/Blender/BlenderScene.h
  66. 6 13
      Engine/lib/assimp/code/AssetLib/Blender/BlenderTessellator.cpp
  67. 2 7
      Engine/lib/assimp/code/AssetLib/Blender/BlenderTessellator.h
  68. 11 21
      Engine/lib/assimp/code/AssetLib/C4D/C4DImporter.cpp
  69. 2 0
      Engine/lib/assimp/code/AssetLib/C4D/C4DImporter.h
  70. 39 39
      Engine/lib/assimp/code/AssetLib/COB/COBLoader.cpp
  71. 10 10
      Engine/lib/assimp/code/AssetLib/COB/COBLoader.h
  72. 1 1
      Engine/lib/assimp/code/AssetLib/COB/COBScene.h
  73. 48 54
      Engine/lib/assimp/code/AssetLib/CSM/CSMLoader.cpp
  74. 4 5
      Engine/lib/assimp/code/AssetLib/CSM/CSMLoader.h
  75. 5 5
      Engine/lib/assimp/code/AssetLib/Collada/ColladaExporter.cpp
  76. 2 2
      Engine/lib/assimp/code/AssetLib/Collada/ColladaExporter.h
  77. 1 1
      Engine/lib/assimp/code/AssetLib/Collada/ColladaHelper.cpp
  78. 2 2
      Engine/lib/assimp/code/AssetLib/Collada/ColladaHelper.h
  79. 24 32
      Engine/lib/assimp/code/AssetLib/Collada/ColladaLoader.cpp
  80. 3 2
      Engine/lib/assimp/code/AssetLib/Collada/ColladaLoader.h
  81. 134 108
      Engine/lib/assimp/code/AssetLib/Collada/ColladaParser.cpp
  82. 1 1
      Engine/lib/assimp/code/AssetLib/Collada/ColladaParser.h
  83. 2 4
      Engine/lib/assimp/code/AssetLib/DXF/DXFHelper.h
  84. 292 54
      Engine/lib/assimp/code/AssetLib/DXF/DXFLoader.cpp
  85. 3 3
      Engine/lib/assimp/code/AssetLib/DXF/DXFLoader.h
  86. 1 1
      Engine/lib/assimp/code/AssetLib/FBX/FBXAnimation.cpp
  87. 7 7
      Engine/lib/assimp/code/AssetLib/FBX/FBXBinaryTokenizer.cpp
  88. 2 1
      Engine/lib/assimp/code/AssetLib/FBX/FBXCommon.h
  89. 1 1
      Engine/lib/assimp/code/AssetLib/FBX/FBXCompileConfig.h
  90. 142 57
      Engine/lib/assimp/code/AssetLib/FBX/FBXConverter.cpp
  91. 2 2
      Engine/lib/assimp/code/AssetLib/FBX/FBXConverter.h
  92. 10 6
      Engine/lib/assimp/code/AssetLib/FBX/FBXDeformer.cpp
  93. 34 16
      Engine/lib/assimp/code/AssetLib/FBX/FBXDocument.cpp
  94. 30 20
      Engine/lib/assimp/code/AssetLib/FBX/FBXDocument.h
  95. 1 1
      Engine/lib/assimp/code/AssetLib/FBX/FBXDocumentUtil.cpp
  96. 2 3
      Engine/lib/assimp/code/AssetLib/FBX/FBXDocumentUtil.h
  97. 2 2
      Engine/lib/assimp/code/AssetLib/FBX/FBXExportNode.cpp
  98. 15 18
      Engine/lib/assimp/code/AssetLib/FBX/FBXExportNode.h
  99. 1 1
      Engine/lib/assimp/code/AssetLib/FBX/FBXExportProperty.cpp
  100. 1 1
      Engine/lib/assimp/code/AssetLib/FBX/FBXExportProperty.h

+ 3 - 2
Engine/lib/CMakeLists.txt

@@ -6,6 +6,8 @@ set(ZLIB_ROOT "${ZLIB_ROOT}" CACHE STRING "ZLib root location" FORCE)
 mark_as_advanced(ZLIB_ROOT)
 # Png depends on zlib
 add_subdirectory(zlib ${TORQUE_LIB_TARG_DIRECTORY}/zlib EXCLUDE_FROM_ALL)
+set(ZLIB_FOUND 1)
+set(ZLIB_LIBRARIES zlib)
 
 if(APPLE)
     enable_language(OBJC)
@@ -116,8 +118,7 @@ add_subdirectory(convexMath ${TORQUE_LIB_TARG_DIRECTORY}/convexMath EXCLUDE_FROM
 
 # Assimp
 advanced_option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
-set(ASSIMP_BUILD_NO_OWN_ZLIB ON CACHE BOOL "" FORCE)
-mark_as_advanced(ASSIMP_BUILD_NO_OWN_ZLIB)
+advanced_option(ASSIMP_BUILD_NO_OWN_ZLIB "" ON)
 advanced_option(BUILD_SHARED_LIBS "Build package with shared libraries." OFF )
 advanced_option(ASSIMP_BUILD_FRAMEWORK "Build package as Mac OS X Framework bundle." OFF )
 advanced_option(ASSIMP_DOUBLE_PRECISION "Set to ON to enable double precision processing" OFF )

+ 47 - 48
Engine/lib/assimp/Build.md

@@ -1,36 +1,10 @@
 # Build / Install Instructions
 
-## Install on all platforms using vcpkg
-You can download and install assimp using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
-```bash
-    git clone https://github.com/Microsoft/vcpkg.git
-    cd vcpkg
-    ./bootstrap-vcpkg.sh
-    ./vcpkg integrate install
-    vcpkg install assimp
-```
-The assimp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
-
-## Install on Ubuntu
-You can install the Asset-Importer-Lib via apt:
-```
-sudo apt-get update
-sudo apt-get install libassimp-dev
-```
-
-## Install pyassimp
-You need to have pip installed:
-```
-pip install pyassimp
-```
-
 ## Manual build instructions
-
-### Install CMake
-Asset-Importer-Lib can be build for a lot of different platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ or for linux install it via
-```bash
-sudo apt-get install cmake
-```
+### Install prerequisites
+You need to install
+* cmake
+* Your compiler
 
 ### Get the source
 Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via:
@@ -38,35 +12,32 @@ Make sure you have a working git-installation. Open a command prompt and clone t
 git clone https://github.com/assimp/assimp.git
 ```
 ### Build from source:
+* For *assimp.lib* without any tools:
 ```bash
 cd assimp
-cmake CMakeLists.txt 
+cmake CMakeLists.txt
 cmake --build .
 ```
 
-### Build instructions for Windows with Visual-Studio
+* For assimp with the common tools like *assimp-cmd*
+```bash
+cd assimp
+cmake CMakeLists.txt -DASSIMP_BUILD_ASSIMP_TOOLS=ON
+cmake --build .
+```
+Note that by default this builds a shared library into the `bin` directory. If you want to build it as a static library see the build options at the bottom of this file.
 
-First you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/
+### Build instructions for Windows with Visual-Studio
+First, you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/
 To generate the build environment for your IDE open a command prompt, navigate to your repo and type:
 ```bash
 cmake CMakeLists.txt
 ```
-This will generate the project files for the visual studio. All dependencies used to build Asset-IMporter-Lib shall be part of the repo. If you want to use you own zlib.installation this is possible as well. Check the options for it.
+This will generate the project files for the visual studio. All dependencies used to build Asset-Importer-Lib shall be part of the repo. If you want to use you own zlib installation this is possible as well. Check the options for it.
 
 ### Build instructions for Windows with UWP
 See <https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app>
 
-### Build instructions for Linux / Unix
-Open a terminal and got to your repository. You can generate the makefiles and build the library via:
-
-```bash
-cmake CMakeLists.txt
-make -j4
-```
-The option -j descripes the number of parallel processes for the build. In this case make will try to use 4 cores for the build.
-
-If you want to use a IDE for linux you can try QTCreator for instance. 
-
 ### Build instructions for MinGW
  Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag 
 required to compile some of assimp's files, especially for debug builds.
@@ -93,9 +64,9 @@ The cmake-build-environment provides options to configure the build. The followi
 - **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_ALL_EXPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all exporters enabled.
+- **ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT (default ON)**: Build Assimp with all importers enabled.
+- **ASSIMP_BUILD_ASSIMP_TOOLS (default OFF)**: 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.
@@ -110,3 +81,31 @@ The cmake-build-environment provides options to configure the build. The followi
 - **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).
+
+### Install prebuild binaries
+## Install on all platforms using vcpkg
+You can download and install assimp using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
+```bash
+    git clone https://github.com/Microsoft/vcpkg.git
+    cd vcpkg
+    ./bootstrap-vcpkg.sh
+    ./vcpkg integrate install
+    ./vcpkg install assimp
+```
+The assimp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
+
+### Install on Ubuntu
+You can install the Asset-Importer-Lib via apt:
+```
+sudo apt-get update
+sudo apt-get install libassimp-dev
+```
+
+### Install pyassimp
+You need to have pip installed:
+```
+pip install pyassimp
+```
+
+### Get the SDK from itchi.io
+Just check [itchi.io](https://kimkulling.itch.io/the-asset-importer-lib)

+ 171 - 98
Engine/lib/assimp/CMakeLists.txt

@@ -1,6 +1,6 @@
 # Open Asset Import Library (assimp)
 # ----------------------------------------------------------------------
-# Copyright (c) 2006-2022, assimp team
+# Copyright (c) 2006-2024, assimp team
 #
 # All rights reserved.
 #
@@ -38,25 +38,50 @@ SET(CMAKE_POLICY_DEFAULT_CMP0012 NEW)
 SET(CMAKE_POLICY_DEFAULT_CMP0074 NEW)
 SET(CMAKE_POLICY_DEFAULT_CMP0092 NEW)
 
-CMAKE_MINIMUM_REQUIRED( VERSION 3.10 )
+CMAKE_MINIMUM_REQUIRED( VERSION 3.22 )
+
+# Experimental USD importer: disabled, need to opt-in
+# Note: assimp github PR automatic checks will fail the PR due to compiler warnings in
+# the external, 3rd party tinyusdz code which isn't technically part of the PR since it's
+# auto-cloned during build; so MUST disable the feature or the PR will be rejected
+option(ASSIMP_BUILD_USD_IMPORTER "Enable USD file import" off)
+option(ASSIMP_BUILD_USD_VERBOSE_LOGS "Enable verbose USD import debug logging" off)
+option(ASSIMP_BUILD_USE_CCACHE "Use ccache to speed up compilation." on)
+
+if(ASSIMP_BUILD_USE_CCACHE)
+  find_program(CCACHE_PATH ccache)
+  if (CCACHE_PATH)
+    set_property(GLOBAL PROPERTY RULE_LAUNCH_COMPILE ${CCACHE_PATH})
+    set_property(GLOBAL PROPERTY RULE_LAUNCH_LINK ${CCACHE_PATH})
+  endif()
+endif()
+
+# User may override these in their CMake script to provide M3D import/export support
+# (M3D importer/exporter was disabled for assimp release 5.1 or later)
+option(ASSIMP_BUILD_M3D_IMPORTER "Enable M3D file import" off)
+option(ASSIMP_BUILD_M3D_EXPORTER "Enable M3D file export" off)
+
+# Internal/private M3D logic
+if (NOT ASSIMP_BUILD_M3D_IMPORTER)
+    ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER)
+endif () # if (not ASSIMP_BUILD_M3D_IMPORTER)
+if (NOT ASSIMP_BUILD_M3D_EXPORTER)
+    ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_EXPORTER)
+endif () # if (not ASSIMP_BUILD_M3D_EXPORTER)
 
-# Disabled importers: m3d for 5.1
-ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_IMPORTER)
-ADD_DEFINITIONS( -DASSIMP_BUILD_NO_M3D_EXPORTER)
 # Toggles the use of the hunter package manager
 option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
 
 IF(ASSIMP_HUNTER_ENABLED)
   include("cmake-modules/HunterGate.cmake")
   HunterGate(
-    URL "https://github.com/cpp-pm/hunter/archive/v0.24.0.tar.gz"
-    SHA1 "a3d7f4372b1dcd52faa6ff4a3bd5358e1d0e5efd"
+    URL "https://github.com/cpp-pm/hunter/archive/v0.25.8.tar.gz"
+    SHA1 "26c79d587883ec910bce168e25f6ac4595f97033"
   )
-
   add_definitions(-DASSIMP_USE_HUNTER)
 ENDIF()
 
-PROJECT(Assimp VERSION 5.2.4)
+PROJECT(Assimp VERSION 5.4.3)
 
 # All supported options ###############################################
 
@@ -84,10 +109,6 @@ OPTION( ASSIMP_NO_EXPORT
   "Disable Assimp's export functionality."
   OFF
 )
-OPTION( ASSIMP_BUILD_ZLIB
-  "Build your own zlib"
-  OFF
-)
 OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
   "If the supplementary tools for Assimp are built in addition to the library."
   OFF
@@ -135,24 +156,36 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH
 )
 
 IF (WIN32)
-  # Use subset of Windows.h
+  OPTION( ASSIMP_BUILD_ZLIB
+    "Build your zlib"
+    ON
+  )
+ELSE()
+  OPTION( ASSIMP_BUILD_ZLIB
+    "Build your zlib"
+    OFF
+  )
+ENDIF()
+
+IF (WIN32)
+  # Use a subset of Windows.h
   ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
 
   IF(MSVC)
     OPTION( ASSIMP_INSTALL_PDB
-      "Install MSVC debug files."
+      "Create MSVC debug symbol files and add to Install target."
       ON )
     IF(NOT (MSVC_VERSION LESS 1900))
-      # Multibyte character set is deprecated since at least MSVC2015 (possibly earlier)
+      # Multibyte character set has been deprecated since at least MSVC2015 (possibly earlier)
       ADD_DEFINITIONS( -DUNICODE -D_UNICODE )
     ENDIF()
 
-    # Link statically against c/c++ lib to avoid missing redistriburable such as
+    # Link statically against c/c++ lib to avoid missing redistributable such as
     # "VCRUNTIME140.dll not found. Try reinstalling the app.", but give users
     # a choice to opt for the shared runtime if they want.
     option(USE_STATIC_CRT "Link against the static runtime libraries." OFF)
 
-    # The CMAKE_CXX_FLAGS vars can be overriden by some Visual Studio generators, so we use an alternative
+    # The CMAKE_CXX_FLAGS vars can be overridden by some Visual Studio generators, so we use an alternative
     # global method here:
     if (${USE_STATIC_CRT})
       add_compile_options(
@@ -193,12 +226,9 @@ SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VER
 SET (ASSIMP_SOVERSION 5)
 
 SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
-if(NOT ASSIMP_HUNTER_ENABLED)
-  # Enable C++17 support globally
-  set(CMAKE_CXX_STANDARD 17)
-  set(CMAKE_CXX_STANDARD_REQUIRED ON)
-  set(CMAKE_C_STANDARD 99)
-endif()
+set(CMAKE_CXX_STANDARD 17)
+set(CMAKE_CXX_STANDARD_REQUIRED ON)
+set(CMAKE_C_STANDARD 99)
 
 IF(NOT ASSIMP_IGNORE_GIT_HASH)
   # Get the current working branch
@@ -245,49 +275,60 @@ SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
 IF( UNIX )
   # Use GNUInstallDirs for Unix predefined directories
   INCLUDE(GNUInstallDirs)
-  # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux
-  IF( ${OPERATING_SYSTEM} MATCHES "Android")
-  ELSE()
-    IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
+  # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit Linux
+  IF(NOT ${OPERATING_SYSTEM} MATCHES "Android")
+    IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit Linux
       ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
     ENDIF()
   ENDIF()
 ENDIF()
 
 # Grouped compiler settings ########################################
-IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW)
+IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW AND NOT HAIKU)
   IF(NOT ASSIMP_HUNTER_ENABLED)
-    SET(CMAKE_CXX_STANDARD 17)
     SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
   ENDIF()
+
+  IF(CMAKE_CXX_COMPILER_VERSION GREATER_EQUAL 13 AND CMAKE_CXX_COMPILER_ID MATCHES "GNU")
+    MESSAGE(STATUS "GCC13 detected disabling \"-Wdangling-reference\" in Cpp files as it appears to be a false positive")
+    ADD_COMPILE_OPTIONS("$<$<COMPILE_LANGUAGE:CXX>:-Wno-dangling-reference>")
+  ENDIF()
   # hide all not-exported symbols
   IF(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "mips64" )
-	SET(CMAKE_CXX_FLAGS "-mxgot -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
-	SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
-	SET(LIBSTDC++_LIBRARIES -lstdc++)
+    SET(CMAKE_CXX_FLAGS "-mxgot -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
+    SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
+    SET(LIBSTDC++_LIBRARIES -lstdc++)
   ELSE()
-	SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
-	SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
-	SET(LIBSTDC++_LIBRARIES -lstdc++)
+    SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
+    SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
+    SET(LIBSTDC++_LIBRARIES -lstdc++)
   ENDIF()
 ELSEIF(MSVC)
   # enable multi-core compilation with MSVC
   IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
-    ADD_COMPILE_OPTIONS(/bigobj /W4 /WX )
+    ADD_COMPILE_OPTIONS(/bigobj)
   ELSE() # msvc
-    ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX)
+    ADD_COMPILE_OPTIONS(/MP /bigobj)
   ENDIF()
+
   # disable "elements of array '' will be default initialized" warning on MSVC2013
   IF(MSVC12)
-    ADD_COMPILE_OPTIONS(/wd4351)	
+    ADD_COMPILE_OPTIONS(/wd4351)
   ENDIF()
-  ADD_COMPILE_OPTIONS(/wd4244) #supress warning for double to float conversion if Double precission is activated
+  # supress warning for double to float conversion if Double precision is activated
+  ADD_COMPILE_OPTIONS(/wd4244)
   SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
-  SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
-  SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
+  # Allow user to disable PDBs
+  if(ASSIMP_INSTALL_PDB)
+    SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
+    SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
+  elseif((GENERATOR_IS_MULTI_CONFIG) OR (CMAKE_BUILD_TYPE MATCHES Release))
+    message("-- MSVC PDB generation disabled. Release binary will not be debuggable.")
+  endif()
+  # Source code is encoded in UTF-8
+  ADD_COMPILE_OPTIONS(/source-charset:utf-8)
 ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
   IF(NOT ASSIMP_HUNTER_ENABLED)
-    SET(CMAKE_CXX_STANDARD 17)
     SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
   ENDIF()
   SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
@@ -303,26 +344,26 @@ ELSEIF( MINGW )
     SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
   ENDIF()
     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}")
+      SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wno-dangling-reference -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}")
+      SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wno-dangling-reference -Wall -Wno-long-long -Wa,-mbig-obj -O3 ${CMAKE_CXX_FLAGS}")
     ENDIF()
     SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
 ENDIF()
 
 IF ( IOS AND NOT ASSIMP_HUNTER_ENABLED)
   IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
-    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og")
+    SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -fembed-bitcode -Og")
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -Og")
   ELSE()
-    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
+    SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
-    # Experimental for pdb generation
   ENDIF()
 ENDIF()
 
 IF (ASSIMP_COVERALLS)
   MESSAGE(STATUS "Coveralls enabled")
+
   INCLUDE(Coveralls)
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
   SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
@@ -330,14 +371,16 @@ ENDIF()
 
 IF (ASSIMP_ASAN)
   MESSAGE(STATUS "AddressSanitizer enabled")
+
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
-  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
+  SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -fsanitize=address")
 ENDIF()
 
 IF (ASSIMP_UBSAN)
   MESSAGE(STATUS "Undefined Behavior sanitizer enabled")
+
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin -fno-sanitize-recover=all")
-  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin -fno-sanitize-recover=all")
+  SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS} -fsanitize=undefined,shift,shift-exponent,integer-divide-by-zero,unreachable,vla-bound,null,return,signed-integer-overflow,bounds,float-divide-by-zero,float-cast-overflow,nonnull-attribute,returns-nonnull-attribute,bool,enum,vptr,pointer-overflow,builtin -fno-sanitize-recover=all")
 ENDIF()
 
 INCLUDE (FindPkgMacros)
@@ -388,13 +431,6 @@ IF (NOT TARGET uninstall AND ASSIMP_INSTALL)
   ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
 ENDIF()
 
-# cmake configuration files
-if(${BUILD_SHARED_LIBS})
-  set(BUILD_LIB_TYPE SHARED)
-else()
-  set(BUILD_LIB_TYPE STATIC)
-endif()
-
 IF( UNIX )
   # Use GNUInstallDirs for Unix predefined directories
   INCLUDE(GNUInstallDirs)
@@ -449,18 +485,20 @@ configure_package_config_file(
     INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}"
 )
 
-install(
-    FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
-    DESTINATION "${CONFIG_INSTALL_DIR}"
-    COMPONENT ${LIBASSIMP-DEV_COMPONENT}
-)
+if(ASSIMP_INSTALL)
+  install(
+      FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}"
+      DESTINATION "${CONFIG_INSTALL_DIR}"
+      COMPONENT ${LIBASSIMP-DEV_COMPONENT}
+  )
 
-install(
-    EXPORT "${TARGETS_EXPORT_NAME}"
-    NAMESPACE "${NAMESPACE}"
-    DESTINATION "${CONFIG_INSTALL_DIR}"
-    COMPONENT ${LIBASSIMP-DEV_COMPONENT}
-)
+  install(
+      EXPORT "${TARGETS_EXPORT_NAME}"
+      NAMESPACE "${NAMESPACE}"
+      DESTINATION "${CONFIG_INSTALL_DIR}"
+      COMPONENT ${LIBASSIMP-DEV_COMPONENT}
+  )
+endif()
 
 IF( ASSIMP_BUILD_DOCS )
   ADD_SUBDIRECTORY(doc)
@@ -478,7 +516,7 @@ IF(ASSIMP_HUNTER_ENABLED)
   set(ASSIMP_BUILD_MINIZIP TRUE)
 ELSE()
   # If the zlib is already found outside, add an export in case assimpTargets can't find it.
-  IF( ZLIB_FOUND )
+  IF( ZLIB_FOUND AND ASSIMP_INSTALL)
     INSTALL( TARGETS zlib zlibstatic
         EXPORT "${TARGETS_EXPORT_NAME}")
   ENDIF()
@@ -487,7 +525,11 @@ ELSE()
     FIND_PACKAGE(ZLIB)
   ENDIF()
 
-  IF( NOT ZLIB_FOUND )
+  IF ( NOT ZLIB_FOUND AND NOT ASSIMP_BUILD_ZLIB )
+    message( FATAL_ERROR
+      "Build configured with -DASSIMP_BUILD_ZLIB=OFF but unable to find zlib"
+    )
+  ELSEIF( NOT ZLIB_FOUND )
     MESSAGE(STATUS "compiling zlib from sources")
     INCLUDE(CheckIncludeFile)
     INCLUDE(CheckTypeSize)
@@ -556,11 +598,15 @@ SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
 )
 
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
-  IF ( MSVC )
-    SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
+  SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
 
+  IF (WIN32)
     # pick the correct prebuilt library
-    IF(MSVC15)
+    IF(MSVC143)
+      SET(C4D_LIB_POSTFIX "_2022")
+    ELSEIF(MSV142)
+      SET(C4D_LIB_POSTFIX "_2019")
+    ELSEIF(MSVC15)
       SET(C4D_LIB_POSTFIX "_2017")
     ELSEIF(MSVC14)
       SET(C4D_LIB_POSTFIX "_2015")
@@ -572,7 +618,7 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
       SET(C4D_LIB_POSTFIX "_2010")
     ELSE()
       MESSAGE( FATAL_ERROR
-        "C4D is currently only supported with MSVC 10, 11, 12, 14"
+        "C4D for Windows is currently only supported with MSVC 10, 11, 12, 14, 14.2, 14.3"
       )
     ENDIF()
 
@@ -590,15 +636,30 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
     # winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because
     # it can be used to communicate with a running Cinema 4D instance
     SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
+  ELSEIF (APPLE)
+    SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/libraries/osx")
+
+    SET(C4D_DEBUG_LIBRARIES
+      "${C4D_LIB_BASE_PATH}/debug/libcinewarelib.a"
+      "${C4D_LIB_BASE_PATH}/debug/libjpeglib.a"
+    )
+    SET(C4D_RELEASE_LIBRARIES
+      "${C4D_LIB_BASE_PATH}/release/libcinewarelib.a"
+      "${C4D_LIB_BASE_PATH}/release/libjpeglib.a"
+    )
   ELSE ()
     MESSAGE( FATAL_ERROR
-      "C4D is currently only available on Windows with Cineware SDK installed in contrib/Cineware"
+      "C4D is currently only available on Windows and macOS with Cineware SDK installed in contrib/Cineware"
     )
   ENDIF ()
 ELSE ()
   ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
 ENDIF ()
 
+if(ASSIMP_BUILD_DRACO_STATIC)
+  set(ASSIMP_BUILD_DRACO ON)
+endif()
+
 # Draco requires cmake 3.12
 IF (DEFINED CMAKE_VERSION AND "${CMAKE_VERSION}" VERSION_LESS "3.12")
   message(NOTICE "draco requires cmake 3.12 or newer, cmake is ${CMAKE_VERSION} . Draco is disabled")
@@ -608,7 +669,7 @@ ELSE()
   IF ( ASSIMP_BUILD_DRACO )
     # Primarily for glTF v2
     # Enable Draco glTF feature set
-    set(DRACO_GLTF ON CACHE BOOL "" FORCE)
+    set(DRACO_GLTF_BITSTREAM ON CACHE BOOL "" FORCE)
     # Disable unnecessary or omitted components
     set(DRACO_JS_GLUE OFF CACHE BOOL "" FORCE)
     set(DRACO_WASM OFF CACHE BOOL "" FORCE)
@@ -634,22 +695,29 @@ ELSE()
           "-Wno-sign-compare"
           "-Wno-unused-local-typedefs"
         )
-        # Draco 1.4.1 does not explicitly export any symbols under GCC/clang
-        list(APPEND DRACO_CXX_FLAGS
-          "-fvisibility=default"
-        )
+
+        if(NOT ASSIMP_BUILD_DRACO_STATIC)
+          # Draco 1.4.1 does not explicitly export any symbols under GCC/clang
+          list(APPEND DRACO_CXX_FLAGS
+            "-fvisibility=default"
+          )
+        endif()
       ENDIF()
 
       # Don't build or install all of Draco by default
       ADD_SUBDIRECTORY( "contrib/draco" EXCLUDE_FROM_ALL )
 
+      if(ASSIMP_BUILD_DRACO_STATIC)
+        set_property(DIRECTORY "contrib/draco" PROPERTY BUILD_SHARED_LIBS OFF)
+      endif()
+
       if(MSVC OR WIN32)
         set(draco_LIBRARIES "draco")
       else()
-        if(BUILD_SHARED_LIBS)
-          set(draco_LIBRARIES "draco_shared")
-        else()
+        if(ASSIMP_BUILD_DRACO_STATIC)
           set(draco_LIBRARIES "draco_static")
+        else()
+          set(draco_LIBRARIES "draco_shared")
         endif()
       endif()
 
@@ -657,13 +725,13 @@ ELSE()
       set_target_properties(draco_encoder draco_decoder PROPERTIES
         EXCLUDE_FROM_ALL TRUE
         EXCLUDE_FROM_DEFAULT_BUILD TRUE
-        )
+      )
 
       # Do build the draco shared library
       set_target_properties(${draco_LIBRARIES} PROPERTIES
         EXCLUDE_FROM_ALL FALSE
         EXCLUDE_FROM_DEFAULT_BUILD FALSE
-        )
+      )
 
       TARGET_USE_COMMON_OUTPUT_DIRECTORY(${draco_LIBRARIES})
       TARGET_USE_COMMON_OUTPUT_DIRECTORY(draco_encoder)
@@ -672,16 +740,17 @@ ELSE()
       set(draco_INCLUDE_DIRS "${CMAKE_CURRENT_SOURCE_DIR}/contrib/draco/src")
 
       # This is probably wrong
-      INSTALL( TARGETS ${draco_LIBRARIES}
-        EXPORT "${TARGETS_EXPORT_NAME}"
-        LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
-        ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
-        RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
-        FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
-        COMPONENT ${LIBASSIMP_COMPONENT}
-        INCLUDES DESTINATION include
-    )
-
+      if (ASSIMP_INSTALL)
+        INSTALL( TARGETS ${draco_LIBRARIES}
+          EXPORT "${TARGETS_EXPORT_NAME}"
+          LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+          ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+          RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
+          FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+          COMPONENT ${LIBASSIMP_COMPONENT}
+          INCLUDES DESTINATION include
+        )
+      endif()
     ENDIF()
   ENDIF()
 ENDIF()
@@ -725,8 +794,8 @@ IF ( ASSIMP_INSTALL )
 ENDIF()
 
 CONFIGURE_FILE(
-  ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
-  ${CMAKE_CURRENT_BINARY_DIR}/revision.h
+  ${CMAKE_CURRENT_LIST_DIR}/include/assimp/revision.h.in
+  ${CMAKE_CURRENT_BINARY_DIR}/include/assimp/revision.h
 )
 
 CONFIGURE_FILE(
@@ -767,7 +836,7 @@ IF ( ASSIMP_INSTALL )
     SET(CPACK_DEBIAN_PACKAGE_SECTION  "libs" )
     SET(CPACK_DEBIAN_PACKAGE_DEPENDS  "${CPACK_COMPONENTS_ALL}")
     SET(CPACK_DEBIAN_PACKAGE_SUGGESTS)
-    SET(cPACK_DEBIAN_PACKAGE_NAME     "assimp")
+    SET(CPACK_DEBIAN_PACKAGE_NAME     "assimp")
     SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/gtest contrib/zlib workspaces test doc obj samples packaging)
     SET(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force)
     SET(CPACK_DEBIAN_CHANGELOG)
@@ -804,6 +873,10 @@ if(WIN32)
       SET(ASSIMP_MSVC_VERSION "vc140")
     ELSEIF(MSVC15)
       SET(ASSIMP_MSVC_VERSION "vc141")
+    ELSEIF(MSV142)
+      SET(ASSIMP_MSVC_VERSION "vc142")
+    ELSEIF(MSVC143)
+      SET(ASSIMP_MSVC_VERSION "vc143")
     ENDIF()
   ENDIF()
 

+ 128 - 0
Engine/lib/assimp/CODE_OF_CONDUCT.md

@@ -0,0 +1,128 @@
+# Contributor Covenant Code of Conduct
+
+## Our Pledge
+
+We as members, contributors, and leaders pledge to make participation in our
+community a harassment-free experience for everyone, regardless of age, body
+size, visible or invisible disability, ethnicity, sex characteristics, gender
+identity and expression, level of experience, education, socio-economic status,
+nationality, personal appearance, race, religion, or sexual identity
+and orientation.
+
+We pledge to act and interact in ways that contribute to an open, welcoming,
+diverse, inclusive, and healthy community.
+
+## Our Standards
+
+Examples of behavior that contributes to a positive environment for our
+community include:
+
+* Demonstrating empathy and kindness toward other people
+* Being respectful of differing opinions, viewpoints, and experiences
+* Giving and gracefully accepting constructive feedback
+* Accepting responsibility and apologizing to those affected by our mistakes,
+  and learning from the experience
+* Focusing on what is best not just for us as individuals, but for the
+  overall community
+
+Examples of unacceptable behavior include:
+
+* The use of sexualized language or imagery, and sexual attention or
+  advances of any kind
+* Trolling, insulting or derogatory comments, and personal or political attacks
+* Public or private harassment
+* Publishing others' private information, such as a physical or email
+  address, without their explicit permission
+* Other conduct which could reasonably be considered inappropriate in a
+  professional setting
+
+## Enforcement Responsibilities
+
+Community leaders are responsible for clarifying and enforcing our standards of
+acceptable behavior and will take appropriate and fair corrective action in
+response to any behavior that they deem inappropriate, threatening, offensive,
+or harmful.
+
+Community leaders have the right and responsibility to remove, edit, or reject
+comments, commits, code, wiki edits, issues, and other contributions that are
+not aligned to this Code of Conduct, and will communicate reasons for moderation
+decisions when appropriate.
+
+## Scope
+
+This Code of Conduct applies within all community spaces, and also applies when
+an individual is officially representing the community in public spaces.
+Examples of representing our community include using an official e-mail address,
+posting via an official social media account, or acting as an appointed
+representative at an online or offline event.
+
+## Enforcement
+
+Instances of abusive, harassing, or otherwise unacceptable behavior may be
+reported to the community leaders responsible for enforcement at
+.
+All complaints will be reviewed and investigated promptly and fairly.
+
+All community leaders are obligated to respect the privacy and security of the
+reporter of any incident.
+
+## Enforcement Guidelines
+
+Community leaders will follow these Community Impact Guidelines in determining
+the consequences for any action they deem in violation of this Code of Conduct:
+
+### 1. Correction
+
+**Community Impact**: Use of inappropriate language or other behavior deemed
+unprofessional or unwelcome in the community.
+
+**Consequence**: A private, written warning from community leaders, providing
+clarity around the nature of the violation and an explanation of why the
+behavior was inappropriate. A public apology may be requested.
+
+### 2. Warning
+
+**Community Impact**: A violation through a single incident or series
+of actions.
+
+**Consequence**: A warning with consequences for continued behavior. No
+interaction with the people involved, including unsolicited interaction with
+those enforcing the Code of Conduct, for a specified period of time. This
+includes avoiding interactions in community spaces as well as external channels
+like social media. Violating these terms may lead to a temporary or
+permanent ban.
+
+### 3. Temporary Ban
+
+**Community Impact**: A serious violation of community standards, including
+sustained inappropriate behavior.
+
+**Consequence**: A temporary ban from any sort of interaction or public
+communication with the community for a specified period of time. No public or
+private interaction with the people involved, including unsolicited interaction
+with those enforcing the Code of Conduct, is allowed during this period.
+Violating these terms may lead to a permanent ban.
+
+### 4. Permanent Ban
+
+**Community Impact**: Demonstrating a pattern of violation of community
+standards, including sustained inappropriate behavior,  harassment of an
+individual, or aggression toward or disparagement of classes of individuals.
+
+**Consequence**: A permanent ban from any sort of public interaction within
+the community.
+
+## Attribution
+
+This Code of Conduct is adapted from the [Contributor Covenant][homepage],
+version 2.0, available at
+https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
+
+Community Impact Guidelines were inspired by [Mozilla's code of conduct
+enforcement ladder](https://github.com/mozilla/diversity).
+
+[homepage]: https://www.contributor-covenant.org
+
+For answers to common questions about this code of conduct, see the FAQ at
+https://www.contributor-covenant.org/faq. Translations are available at
+https://www.contributor-covenant.org/translations.

+ 7 - 10
Engine/lib/assimp/Dockerfile

@@ -1,16 +1,12 @@
-FROM ubuntu:14.04
+FROM ubuntu:22.04
 
-RUN apt-get update && apt-get install -y \
+RUN apt-get update && apt-get install --no-install-recommends -y ninja-build \
     git cmake build-essential software-properties-common
 
-RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update && apt-get install -y gcc-4.9 g++-4.9 && \
-    cd /usr/bin && \
-    rm gcc g++ cpp && \
-    ln -s gcc-4.9 gcc && \
-    ln -s g++-4.9 g++ && \
-    ln -s cpp-4.9 cpp
+RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update 
 
 WORKDIR /opt
+RUN apt install zlib1g-dev
 
 # Build Assimp
 RUN git clone https://github.com/assimp/assimp.git /opt/assimp
@@ -19,7 +15,8 @@ WORKDIR /opt/assimp
 
 RUN git checkout master \
     && mkdir build && cd build && \
-    cmake \
+    cmake -G 'Ninja' \
     -DCMAKE_BUILD_TYPE=Release \
+    -DASSIMP_BUILD_ASSIMP_TOOLS=ON \
     .. && \
-    make && make install
+    ninja -j4 && ninja install

+ 41 - 47
Engine/lib/assimp/Readme.md

@@ -1,42 +1,45 @@
 Open Asset Import Library (assimp)
 ==================================
-A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
-### Current project status ###
-[![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp) 
+
+Open Asset Import Library is a library that loads various 3D file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
+
+### Current project status ### 
 ![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
-<a href="https://scan.coverity.com/projects/5607">
-  <img alt="Coverity Scan Build Status"
-       src="https://scan.coverity.com/projects/5607/badge.svg"/>
-</a>
 [![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
-
-[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
-[![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=assimp_assimp&metric=alert_status)](https://sonarcloud.io/summary/new_code?id=assimp_assimp)
 [![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/)
+[![Gurubase](https://img.shields.io/badge/Gurubase-Ask%20assimp%20Guru-006BFF)](https://gurubase.io/g/assimp)
+[![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp)
 <br>
 
-APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
-Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
+APIs are provided for C and C++. Various bindings exist to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
+Additionally, assimp features various __mesh post-processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
 
-### Latest Doc's ###
-Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/). 
+## Project activity ##
+![Alt](https://repobeats.axiom.co/api/embed/997f84e5f9fcf772da1e687f3a4f3a8afdbf4cf0.svg "Repobeats analytics image")
 
-### Get involved ###
-This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
-<br>
-You find a bug in the docs? Use [Doc-Repo](https://github.com/assimp/assimp-docs).
-<br>
-Please check our Wiki as well: https://github.com/assimp/assimp/wiki
+### Documentation ###
+Read [our latest documentation](https://assimp-docs.readthedocs.io/en/latest/).
+
+### Pre-built binaries ###
+Download binaries from [our Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib).
 
-If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
+### Test data ###
+Clone [our model database](https://github.com/assimp/assimp-mdb).
+
+### Communities ###
+- Ask questions at [the Assimp Discussion Board](https://github.com/assimp/assimp/discussions).
+- Find us on [https://discord.gg/s9KJfaem](https://discord.gg/kKazXMXDy2)
+- Ask [the Assimp community on Reddit](https://www.reddit.com/r/Assimp/).
+- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). 
+- Nothing has worked? File a question or an issue report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues)
 
 #### Supported file formats ####
-You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md)
+See [the complete list of supported formats](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md).
 
 ### Building ###
-Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
+Start by reading [our build instructions](https://github.com/assimp/assimp/blob/master/Build.md). We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
 
 ### Ports ###
 * [Android](port/AndroidJNI/README.md)
@@ -47,46 +50,40 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file.
 * [Javascript/Node.js Interface](https://github.com/kovacsv/assimpjs)
 * [Unity 3d Plugin](https://ricardoreis.net/trilib-2/)
 * [Unreal Engine Plugin](https://github.com/irajsb/UE4_Assimp/)
-* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status))
+* [JVM](https://github.com/kotlin-graphics/assimp) Full JVM port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status))
 * [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port.
 * [Rust](https://github.com/jkvargas/russimp)
 
 ### Other tools ###
 [open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
+[Assimp-Viewer](https://github.com/assimp/assimp_view) is an experimental implementation for an Asset-Viewer based on ImGUI and Assimp (experimental).
 
 #### Repository structure ####
-Open Asset Import Library is implemented in C++. The directory structure looks like:
+Open Asset Import Library is implemented in C++. The directory structure looks like this:
 
 	/code		Source code
 	/contrib	Third-party libraries
-	/doc		Documentation (doxysource and pre-compiled docs)
-	/fuzz           Contains the test-code for the Google-Fuzzer project
+	/doc		Documentation (Doxygen source and pre-compiled docs)
+	/fuzz           Contains the test code for the Google Fuzzer project
 	/include	Public header C and C++ header files
-	/scripts 	Scripts used to generate the loading code for some formats
+	/scripts 	Scripts are used to generate the loading code for some formats
 	/port		Ports to other languages and scripts to maintain those.
 	/test		Unit- and regression tests, test suite of models
 	/tools		Tools (old assimp viewer, command line `assimp`)
-	/samples	A small number of samples to illustrate possible
-                        use cases for Assimp
+	/samples	A small number of samples to illustrate possible use cases for Assimp
 
 The source code is organized in the following way:
 
 	code/Common			The base implementation for importers and the infrastructure
+	code/CApi                       Special implementations which are only used for the C-API
+	code/Geometry                   A collection of geometry tools
+	code/Material                   The material system
+	code/PBR                        An exporter for physical-based models
 	code/PostProcessing		The post-processing steps
-	code/AssetLib/<FormatName>	Implementation for import and export for the format
-
-### Where to get help ###
-For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
-(CHMs for Windows are included in some release packages and should be located right here in the root folder).
-
-If the docs don't solve your problem, ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
-
-Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
-
-And we also have a Gitter-channel:Gitter [![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)<br>
+	code/AssetLib/<FormatName>	Implementation for import and export of the format
 
 ### Contributing ###
-Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
+I would greatly appreciate contributing to assimp. The easiest way to get involved is to submit
 a pull request with your changes against the main repository's `master` branch.
 
 ## Contributors
@@ -108,7 +105,7 @@ Become a financial contributor and help us sustain our community. [[Contribute](
 
 #### Organizations
 
-Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)]
+You can support the project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)]
 
 <a href="https://opencollective.com/assimp/organization/0/website"><img src="https://opencollective.com/assimp/organization/0/avatar.svg"></a>
 
@@ -118,6 +115,3 @@ Our license is based on the modified, __3-clause BSD__-License.
 An _informal_ summary is: do whatever you want, but include Assimp's license text with your product -
 and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp.
 For the legal details, see the `LICENSE` file.
-
-### Why this name ###
-Sorry, we're germans :-), no english native speakers ...

+ 0 - 29
Engine/lib/assimp/cmake-modules/HunterGate.cmake

@@ -22,38 +22,9 @@
 # OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-# This is a gate file to Hunter package manager.
-# Include this file using `include` command and add package you need, example:
-#
-#     cmake_minimum_required(VERSION 3.2)
-#
-#     include("cmake/HunterGate.cmake")
-#     HunterGate(
-#         URL "https://github.com/path/to/hunter/archive.tar.gz"
-#         SHA1 "798501e983f14b28b10cda16afa4de69eee1da1d"
-#     )
-#
-#     project(MyProject)
-#
-#     hunter_add_package(Foo)
-#     hunter_add_package(Boo COMPONENTS Bar Baz)
-#
-# Projects:
-#     * https://github.com/hunter-packages/gate/
-#     * https://github.com/ruslo/hunter
 
 option(HUNTER_ENABLED "Enable Hunter package manager support" ON)
 
-if(HUNTER_ENABLED)
-  if(CMAKE_VERSION VERSION_LESS "3.2")
-    message(
-        FATAL_ERROR
-        "At least CMake version 3.2 required for Hunter dependency management."
-        " Update CMake or set HUNTER_ENABLED to OFF."
-    )
-  endif()
-endif()
-
 include(CMakeParseArguments) # cmake_parse_arguments
 
 option(HUNTER_STATUS_PRINT "Print working status" ON)

+ 0 - 8
Engine/lib/assimp/code/.editorconfig

@@ -1,8 +0,0 @@
-# See <http://EditorConfig.org> for details
-
-[*.{h,hpp,c,cpp}]
-end_of_line = lf
-insert_final_newline = true
-trim_trailing_whitespace = true
-indent_size = 4
-indent_style = space

+ 17 - 9
Engine/lib/assimp/code/AssetLib/3DS/3DSConverter.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -52,9 +52,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <cctype>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const unsigned int NotSet = 0xcdcdcdcd;
+static constexpr unsigned int NotSet = 0xcdcdcdcd;
 
 // ------------------------------------------------------------------------------------------------
 // Setup final material indices, generae a default material if necessary
@@ -68,7 +68,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
     unsigned int idx(NotSet);
     for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) {
         std::string s = mScene->mMaterials[i].mName;
-        for (char & it : s) {
+        for (char &it : s) {
             it = static_cast<char>(::tolower(static_cast<unsigned char>(it)));
         }
 
@@ -262,7 +262,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
         unsigned int iWire = 1;
         mat.AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
     }
-    [[fallthrough]];
+        [[fallthrough]];
 
     case D3DS::Discreet3DS::Gouraud:
         eShading = aiShadingMode_Gouraud;
@@ -593,7 +593,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
 
         // Cameras or lights define their transformation in their parent node and in the
         // corresponding light or camera chunks. However, we read and process the latter
-        // to to be able to return valid cameras/lights even if no scenegraph is given.
+        // to be able to return valid cameras/lights even if no scenegraph is given.
         for (unsigned int n = 0; n < pcSOut->mNumCameras; ++n) {
             if (pcSOut->mCameras[n]->mName == pcOut->mName) {
                 pcSOut->mCameras[n]->mLookAt = aiVector3D(0.f, 0.f, 1.f);
@@ -643,11 +643,17 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
     }
 
     // Allocate storage for children
-    pcOut->mNumChildren = (unsigned int)pcIn->mChildren.size();
+    const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
+
+    pcOut->mNumChildren = size;
+    if (size == 0) {
+        return;
+    }
+
     pcOut->mChildren = new aiNode *[pcIn->mChildren.size()];
 
     // Recursively process all children
-    const unsigned int size = static_cast<unsigned int>(pcIn->mChildren.size());
+    
     for (unsigned int i = 0; i < size; ++i) {
         pcOut->mChildren[i] = new aiNode();
         pcOut->mChildren[i]->mParent = pcOut;
@@ -709,7 +715,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
             pcNode->mNumMeshes = 1;
 
             // Build a name for the node
-            pcNode->mName.length = ai_snprintf(pcNode->mName.data, MAXLEN, "3DSMesh_%u", i);
+            pcNode->mName.length = ai_snprintf(pcNode->mName.data, AI_MAXLEN, "3DSMesh_%u", i);
         }
 
         // Build dummy nodes for all cameras
@@ -805,4 +811,6 @@ void Discreet3DSImporter::ConvertScene(aiScene *pcOut) {
     }
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER

+ 2 - 1
Engine/lib/assimp/code/AssetLib/3DS/3DSExporter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/StringComparison.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/Exporter.hpp>
+#include <assimp/Exceptional.h>
 #include <assimp/IOSystem.hpp>
 
 #include <memory>

+ 3 - 5
Engine/lib/assimp/code/AssetLib/3DS/3DSExporter.h

@@ -2,8 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
-
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -57,8 +56,7 @@ struct aiNode;
 struct aiMaterial;
 struct aiMesh;
 
-namespace Assimp
-{
+namespace Assimp {
 
 // ------------------------------------------------------------------------------------------------
 /**
@@ -88,7 +86,7 @@ private:
 
     std::map<const aiNode*, aiMatrix4x4> trafos;
 
-    typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap;
+    using MeshesByNodeMap = std::multimap<const aiNode*, unsigned int>;
     MeshesByNodeMap meshes;
 
 };

+ 8 - 124
Engine/lib/assimp/code/AssetLib/3DS/3DSHelper.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -322,7 +322,6 @@ struct Texture {
     //! Default constructor
     Texture() AI_NO_EXCEPT
             : mTextureBlend(0.0f),
-              mMapName(),
               mOffsetU(0.0),
               mOffsetV(0.0),
               mScaleU(1.0),
@@ -334,51 +333,11 @@ struct Texture {
         mTextureBlend = get_qnan();
     }
 
-    Texture(const Texture &other) :
-            mTextureBlend(other.mTextureBlend),
-            mMapName(other.mMapName),
-            mOffsetU(other.mOffsetU),
-            mOffsetV(other.mOffsetV),
-            mScaleU(other.mScaleU),
-            mScaleV(other.mScaleV),
-            mRotation(other.mRotation),
-            mMapMode(other.mMapMode),
-            bPrivate(other.bPrivate),
-            iUVSrc(other.iUVSrc) {
-        // empty
-    }
-
-    Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(other.mTextureBlend),
-                                            mMapName(std::move(other.mMapName)),
-                                            mOffsetU(other.mOffsetU),
-                                            mOffsetV(other.mOffsetV),
-                                            mScaleU(other.mScaleU),
-                                            mScaleV(other.mScaleV),
-                                            mRotation(other.mRotation),
-                                            mMapMode(other.mMapMode),
-                                            bPrivate(other.bPrivate),
-                                            iUVSrc(other.iUVSrc) {
-        // empty
-    }
+    Texture(const Texture &other) = default;
 
-    Texture &operator=(Texture &&other) AI_NO_EXCEPT {
-        if (this == &other) {
-            return *this;
-        }
-
-        mTextureBlend = other.mTextureBlend;
-        mMapName = std::move(other.mMapName);
-        mOffsetU = other.mOffsetU;
-        mOffsetV = other.mOffsetV;
-        mScaleU = other.mScaleU;
-        mScaleV = other.mScaleV;
-        mRotation = other.mRotation;
-        mMapMode = other.mMapMode;
-        bPrivate = other.bPrivate;
-        iUVSrc = other.iUVSrc;
+    Texture(Texture &&other) AI_NO_EXCEPT = default;
 
-        return *this;
-    }
+    Texture &operator=(Texture &&other) AI_NO_EXCEPT = default;
 
     //! Specifies the blend factor for the texture
     ai_real mTextureBlend;
@@ -406,14 +365,13 @@ struct Texture {
 #ifdef _MSC_VER
 #pragma warning(pop)
 #endif // _MSC_VER
-
 // ---------------------------------------------------------------------------
 /** Helper structure representing a 3ds material */
 struct Material {
     //! Default constructor has been deleted
     Material() :
             mName(),
-            mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
+            mDiffuse(0.6f, 0.6f, 0.6f),
             mSpecularExponent(ai_real(0.0)),
             mShininessStrength(ai_real(1.0)),
             mShading(Discreet3DS::Gouraud),
@@ -426,7 +384,7 @@ struct Material {
     //! Constructor with explicit name
     explicit Material(const std::string &name) :
             mName(name),
-            mDiffuse(ai_real(0.6), ai_real(0.6), ai_real(0.6)),
+            mDiffuse(0.6f, 0.6f, 0.6f),
             mSpecularExponent(ai_real(0.0)),
             mShininessStrength(ai_real(1.0)),
             mShading(Discreet3DS::Gouraud),
@@ -436,83 +394,9 @@ struct Material {
         // empty
     }
 
-    Material(const Material &other) :
-            mName(other.mName),
-            mDiffuse(other.mDiffuse),
-            mSpecularExponent(other.mSpecularExponent),
-            mShininessStrength(other.mShininessStrength),
-            mSpecular(other.mSpecular),
-            mAmbient(other.mAmbient),
-            mShading(other.mShading),
-            mTransparency(other.mTransparency),
-            sTexDiffuse(other.sTexDiffuse),
-            sTexOpacity(other.sTexOpacity),
-            sTexSpecular(other.sTexSpecular),
-            sTexReflective(other.sTexReflective),
-            sTexBump(other.sTexBump),
-            sTexEmissive(other.sTexEmissive),
-            sTexShininess(other.sTexShininess),
-            mBumpHeight(other.mBumpHeight),
-            mEmissive(other.mEmissive),
-            sTexAmbient(other.sTexAmbient),
-            mTwoSided(other.mTwoSided) {
-        // empty
-    }
+    Material(const Material &other) = default;
 
-    //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
-    Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)),
-                                              mDiffuse(other.mDiffuse),
-                                              mSpecularExponent(other.mSpecularExponent),
-                                              mShininessStrength(other.mShininessStrength),
-                                              mSpecular(other.mSpecular),
-                                              mAmbient(other.mAmbient),
-                                              mShading(other.mShading),
-                                              mTransparency(other.mTransparency),
-                                              sTexDiffuse(std::move(other.sTexDiffuse)),
-                                              sTexOpacity(std::move(other.sTexOpacity)),
-                                              sTexSpecular(std::move(other.sTexSpecular)),
-                                              sTexReflective(std::move(other.sTexReflective)),
-                                              sTexBump(std::move(other.sTexBump)),
-                                              sTexEmissive(std::move(other.sTexEmissive)),
-                                              sTexShininess(std::move(other.sTexShininess)),
-                                              mBumpHeight(other.mBumpHeight),
-                                              mEmissive(other.mEmissive),
-                                              sTexAmbient(std::move(other.sTexAmbient)),
-                                              mTwoSided(other.mTwoSided) {
-        // empty
-    }
-
-    Material &operator=(Material &&other) AI_NO_EXCEPT {
-        if (this == &other) {
-            return *this;
-        }
-
-        mName = std::move(other.mName);
-        mDiffuse = other.mDiffuse;
-        mSpecularExponent = other.mSpecularExponent;
-        mShininessStrength = other.mShininessStrength,
-        mSpecular = other.mSpecular;
-        mAmbient = other.mAmbient;
-        mShading = other.mShading;
-        mTransparency = other.mTransparency;
-        sTexDiffuse = std::move(other.sTexDiffuse);
-        sTexOpacity = std::move(other.sTexOpacity);
-        sTexSpecular = std::move(other.sTexSpecular);
-        sTexReflective = std::move(other.sTexReflective);
-        sTexBump = std::move(other.sTexBump);
-        sTexEmissive = std::move(other.sTexEmissive);
-        sTexShininess = std::move(other.sTexShininess);
-        mBumpHeight = other.mBumpHeight;
-        mEmissive = other.mEmissive;
-        sTexAmbient = std::move(other.sTexAmbient);
-        mTwoSided = other.mTwoSided;
-
-        return *this;
-    }
-
-    virtual ~Material() {
-        // empty
-    }
+    virtual ~Material() = default;
 
     //! Name of the material
     std::string mName;

+ 13 - 8
Engine/lib/assimp/code/AssetLib/3DS/3DSLoader.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -54,9 +54,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Discreet 3DS Importer",
     "",
     "",
@@ -103,10 +103,6 @@ Discreet3DSImporter::Discreet3DSImporter() :
     // empty
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-Discreet3DSImporter::~Discreet3DSImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@@ -266,8 +262,15 @@ void Discreet3DSImporter::ParseMainChunk() {
     };
 
     ASSIMP_3DS_END_CHUNK();
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunreachable-code-return"
+#endif
     // recursively continue processing this hierarchy level
     return ParseMainChunk();
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -362,7 +365,7 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
     // IMPLEMENTATION NOTE;
     // Cameras or lights define their transformation in their parent node and in the
     // corresponding light or camera chunks. However, we read and process the latter
-    // to to be able to return valid cameras/lights even if no scenegraph is given.
+    // to be able to return valid cameras/lights even if no scenegraph is given.
 
     // get chunk type
     switch (chunk.Flag) {
@@ -1332,4 +1335,6 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
     (void)bGamma;
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER

+ 2 - 3
Engine/lib/assimp/code/AssetLib/3DS/3DSLoader.h

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -59,7 +59,6 @@ struct aiNode;
 
 namespace Assimp    {
 
-
 using namespace D3DS;
 
 // ---------------------------------------------------------------------------------
@@ -68,7 +67,7 @@ using namespace D3DS;
 class Discreet3DSImporter : public BaseImporter {
 public:
     Discreet3DSImporter();
-    ~Discreet3DSImporter();
+    ~Discreet3DSImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 22 - 8
Engine/lib/assimp/code/AssetLib/3MF/3MFTypes.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -57,6 +57,7 @@ enum class ResourceType {
     RT_BaseMaterials,
     RT_EmbeddedTexture2D,
     RT_Texture2DGroup,
+    RT_ColorGroup,
     RT_Unknown
 }; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
 
@@ -69,9 +70,7 @@ public:
         // empty
     }
 
-    virtual ~Resource() {
-        // empty
-    }
+    virtual ~Resource() = default;
 
     virtual ResourceType getType() const {
         return ResourceType::RT_Unknown;
@@ -95,7 +94,7 @@ public:
         // empty
     }
 
-    ~EmbeddedTexture() = default;
+    ~EmbeddedTexture() override = default;
 
     ResourceType getType() const override {
         return ResourceType::RT_EmbeddedTexture2D;
@@ -112,13 +111,28 @@ public:
         // empty
     }
 
-    ~Texture2DGroup() = default;
+    ~Texture2DGroup() override = default;
 
     ResourceType getType() const override {
         return ResourceType::RT_Texture2DGroup;
     }
 };
 
+class ColorGroup : public Resource {
+public:
+    std::vector<aiColor4D> mColors;
+    ColorGroup(int id) :
+            Resource(id){
+        // empty
+    }
+
+    ~ColorGroup() override = default;
+
+    ResourceType getType() const override {
+        return ResourceType::RT_ColorGroup;
+    }
+};
+
 class BaseMaterials : public Resource {
 public:
     std::vector<unsigned int> mMaterialIndex;
@@ -129,7 +143,7 @@ public:
         // empty
     }
 
-    ~BaseMaterials() = default;
+    ~BaseMaterials() override = default;
 
     ResourceType getType() const override {
         return ResourceType::RT_BaseMaterials;
@@ -154,7 +168,7 @@ public:
         // empty
     }
 
-    ~Object() = default;
+    ~Object() override = default;
 
     ResourceType getType() const override {
         return ResourceType::RT_Object;

+ 6 - 1
Engine/lib/assimp/code/AssetLib/3MF/3MFXmlTags.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -98,6 +98,11 @@ namespace XmlTag {
     const char *const texture_cuurd_u = "u";
     const char *const texture_cuurd_v = "v";
 
+    // vertex color definitions
+    const char *const colorgroup = "m:colorgroup";
+    const char *const color_item = "m:color";
+    const char *const color_vaule = "color";
+
     // Meta info tags
     const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
     const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";

+ 6 - 6
Engine/lib/assimp/code/AssetLib/3MF/D3MFExporter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -83,7 +83,7 @@ void ExportScene3MF(const char *pFile, IOSystem *pIOSystem, const aiScene *pScen
 namespace D3MF {
 
 D3MFExporter::D3MFExporter(const char *pFile, const aiScene *pScene) :
-        mArchiveName(pFile), m_zipArchive(nullptr), mScene(pScene), mModelOutput(), mRelOutput(), mContentOutput(), mBuildItems(), mRelations() {
+        mArchiveName(pFile), m_zipArchive(nullptr), mScene(pScene) {
     // empty
 }
 
@@ -249,10 +249,10 @@ void D3MFExporter::writeBaseMaterials() {
             if (color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1) {
 
                 hexDiffuseColor = ai_rgba2hex(
-                        (int)((ai_real)color.r) * 255,
-                        (int)((ai_real)color.g) * 255,
-                        (int)((ai_real)color.b) * 255,
-                        (int)((ai_real)color.a) * 255,
+                        (int)(((ai_real)color.r) * 255),
+                        (int)(((ai_real)color.g) * 255),
+                        (int)(((ai_real)color.b) * 255),
+                        (int)(((ai_real)color.a) * 255),
                         true);
 
             } else {

+ 1 - 1
Engine/lib/assimp/code/AssetLib/3MF/D3MFExporter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 10 - 9
Engine/lib/assimp/code/AssetLib/3MF/D3MFImporter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -68,7 +68,7 @@ namespace Assimp {
 
 using namespace D3MF;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "3mf Importer",
     "",
     "",
@@ -81,16 +81,17 @@ static const aiImporterDesc desc = {
     "3mf"
 };
 
-D3MFImporter::D3MFImporter() = default;
-
-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 ) const {
     if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
         return false;
     }
-    D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
-    return opcPackage.validate();
+    static const char *const ModelRef = "3D/3dmodel.model";
+    ZipArchiveIOSystem archive(pIOHandler, filename);
+    if (!archive.Exists(ModelRef)) {
+        return false;
+    }
+
+    return true;
 }
 
 void D3MFImporter::SetupProperties(const Importer*) {

+ 3 - 3
Engine/lib/assimp/code/AssetLib/3MF/D3MFImporter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -56,10 +56,10 @@ namespace Assimp {
 class D3MFImporter : public BaseImporter {
 public:
     /// @brief The default class constructor.
-    D3MFImporter();
+    D3MFImporter() = default;
 
     ///	@brief  The class destructor.
-    ~D3MFImporter() override;
+    ~D3MFImporter() override = default;
 
     /// @brief Performs the data format detection.
     /// @param pFile        The filename to check.

+ 9 - 12
Engine/lib/assimp/code/AssetLib/3MF/D3MFOpcPackage.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -68,7 +68,7 @@ using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
 class OpcPackageRelationshipReader {
 public:
     OpcPackageRelationshipReader(XmlParser &parser) :
-            m_relationShips() {
+            mRelations() {
         XmlNode root = parser.getRootNode();
         ParseRootNode(root);
     }
@@ -108,20 +108,20 @@ public:
                 relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string();
                 relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string();
                 if (validateRels(relPtr)) {
-                    m_relationShips.push_back(relPtr);
+                    mRelations.push_back(relPtr);
                 }
             }
         }
     }
 
-    std::vector<OpcPackageRelationshipPtr> m_relationShips;
+    std::vector<OpcPackageRelationshipPtr> mRelations;
 };
 
 static bool IsEmbeddedTexture( const std::string &filename ) {
     const std::string extension = BaseImporter::GetExtension(filename);
-    if (extension == "jpg" || extension == "png") {
+    if (extension == "jpg" || extension == "png" || extension == "jpeg") {
         std::string::size_type pos = filename.find("thumbnail");
-        if (pos == std::string::npos) {
+        if (pos != std::string::npos) {
             return false;
         }
         return true;
@@ -160,7 +160,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
                     // deal with zip-bug
                     rootFile = rootFile.substr(1);
                 }
-            } 
+            }
 
             ASSIMP_LOG_VERBOSE_DEBUG(rootFile);
 
@@ -186,9 +186,6 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
 D3MFOpcPackage::~D3MFOpcPackage() {
     mZipArchive->Close(mRootStream);
     delete mZipArchive;
-    for (auto tex : mEmbeddedTextures) {
-        delete tex;
-    }
 }
 
 IOStream *D3MFOpcPackage::RootStream() const {
@@ -217,11 +214,11 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
 
     OpcPackageRelationshipReader reader(xmlParser);
 
-    auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) {
+    auto itr = std::find_if(reader.mRelations.begin(), reader.mRelations.end(), [](const OpcPackageRelationshipPtr &rel) {
         return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
     });
 
-    if (itr == reader.m_relationShips.end()) {
+    if (itr == reader.mRelations.end()) {
         throw DeadlyImportError("Cannot find ", XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
     }
 

+ 1 - 1
Engine/lib/assimp/code/AssetLib/3MF/D3MFOpcPackage.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 142 - 34
Engine/lib/assimp/code/AssetLib/3MF/XmlSerializer.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -44,19 +44,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "3MFTypes.h"
 #include <assimp/scene.h>
 
+#include <utility>
+
 namespace Assimp {
 namespace D3MF {
 
-static const int IdNotSet = -1;
+static constexpr int IdNotSet = -1;
 
 namespace {
 
-static const size_t ColRGBA_Len = 9;
-static const size_t ColRGB_Len = 7;
+static constexpr size_t ColRGBA_Len = 9;
+static constexpr size_t ColRGB_Len = 7;
 
 // format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
-bool validateColorString(const char *color) {
-    const size_t len = strlen(color);
+bool validateColorString(const std::string color) {
+    const size_t len = color.size();
     if (ColRGBA_Len != len && ColRGB_Len != len) {
         return false;
     }
@@ -73,7 +75,7 @@ aiFace ReadTriangle(XmlNode &node, int &texId0, int &texId1, int &texId2) {
     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()));
 
-    texId0 = texId1 = texId2 = -1;
+    texId0 = texId1 = texId2 = IdNotSet;
     XmlParser::getIntAttribute(node, XmlTag::p1, texId0);
     XmlParser::getIntAttribute(node, XmlTag::p2, texId1);
     XmlParser::getIntAttribute(node, XmlTag::p3, texId2);
@@ -155,8 +157,8 @@ aiMatrix4x4 parseTransformMatrix(const std::string& matrixStr) {
     return transformMatrix;
 }
 
-bool parseColor(const char *color, aiColor4D &diffuse) {
-    if (nullptr == color) {
+bool parseColor(const std::string &color, aiColor4D &diffuse) {
+    if (color.empty()) {
         return false;
     }
 
@@ -176,7 +178,7 @@ bool parseColor(const char *color, aiColor4D &diffuse) {
 
     char b[3] = { color[5], color[6], '\0' };
     diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0);
-    const size_t len = strlen(color);
+    const size_t len = color.size();
     if (ColRGB_Len == len) {
         return true;
     }
@@ -214,7 +216,7 @@ void XmlSerializer::ImportXml(aiScene *scene) {
     if (nullptr == scene) {
         return;
     }
-    
+
     scene->mRootNode = new aiNode(XmlTag::RootTag);
     XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
     if (node.empty()) {
@@ -234,6 +236,8 @@ void XmlSerializer::ImportXml(aiScene *scene) {
             ReadBaseMaterials(currentNode);
         } else if (currentNodeName == XmlTag::meta) {
             ReadMetadata(currentNode);
+        } else if (currentNodeName == XmlTag::colorgroup) {
+            ReadColorGroup(currentNode);
         }
     }
     StoreMaterialsInScene(scene);
@@ -329,9 +333,49 @@ void XmlSerializer::ReadObject(XmlNode &node) {
 
             if (hasPid) {
                 auto it = mResourcesDictionnary.find(pid);
-                if (hasPindex && it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_BaseMaterials) {
-                    BaseMaterials *materials = static_cast<BaseMaterials *>(it->second);
-                    mesh->mMaterialIndex = materials->mMaterialIndex[pindex];
+                if (hasPindex && it != mResourcesDictionnary.end()) {
+                    if (it->second->getType() == ResourceType::RT_BaseMaterials) {
+                        BaseMaterials *materials = static_cast<BaseMaterials *>(it->second);
+                        mesh->mMaterialIndex = materials->mMaterialIndex[pindex];
+                    } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
+                        Texture2DGroup *group = static_cast<Texture2DGroup *>(it->second);
+                        if (mesh->mTextureCoords[0] == nullptr) {
+                            mesh->mNumUVComponents[0] = 2;
+                            for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+                                mesh->mNumUVComponents[i] = 0;
+                            }
+
+                            const std::string name = ai_to_string(group->mTexId);
+                            for (size_t i = 0; i < mMaterials.size(); ++i) {
+                                if (name == mMaterials[i]->GetName().C_Str()) {
+                                    mesh->mMaterialIndex = static_cast<unsigned int>(i);
+                                }
+                            }
+
+                            mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
+                            for (unsigned int vertex_idx = 0; vertex_idx < mesh->mNumVertices; vertex_idx++) {
+                                mesh->mTextureCoords[0][vertex_idx] =
+                                        aiVector3D(group->mTex2dCoords[pindex].x, group->mTex2dCoords[pindex].y, 0.0f);
+                            }
+                        } else {
+                            for (unsigned int vertex_idx = 0; vertex_idx < mesh->mNumVertices; vertex_idx++) {
+                                if (mesh->mTextureCoords[0][vertex_idx].z < 0) {
+                                    // use default
+                                    mesh->mTextureCoords[0][vertex_idx] =
+                                            aiVector3D(group->mTex2dCoords[pindex].x, group->mTex2dCoords[pindex].y, 0.0f);
+                                }
+                            }
+                        }
+                    }else if (it->second->getType() == ResourceType::RT_ColorGroup) {
+                        if (mesh->mColors[0] == nullptr) {
+                            mesh->mColors[0] = new aiColor4D[mesh->mNumVertices];
+
+                            ColorGroup *group = static_cast<ColorGroup *>(it->second);
+                            for (unsigned int vertex_idx = 0; vertex_idx < mesh->mNumVertices; vertex_idx++) {
+                                mesh->mColors[0][vertex_idx] = group->mColors[pindex];
+                            }
+                        }
+                    }
                 }
             }
 
@@ -413,27 +457,36 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
     for (XmlNode &currentNode : node.children()) {
         const std::string currentName = currentNode.name();
         if (currentName == XmlTag::triangle) {
-            int pid = IdNotSet, p1 = IdNotSet;
+            int pid = IdNotSet;
             bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
-            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) {
+            int pindex[3];
+            aiFace face = ReadTriangle(currentNode, pindex[0], pindex[1], pindex[2]);
+            if (hasPid && (pindex[0] != IdNotSet || pindex[1] != IdNotSet || pindex[2] != IdNotSet)) {
                 auto it = mResourcesDictionnary.find(pid);
                 if (it != mResourcesDictionnary.end()) {
                     if (it->second->getType() == ResourceType::RT_BaseMaterials) {
                         BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
-                        mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
+
+                        auto update_material = [&](int idx) {
+                            if (pindex[idx] != IdNotSet) {
+                                mesh->mMaterialIndex = baseMaterials->mMaterialIndex[pindex[idx]];
+                            }
+                        };
+
+                        update_material(0);
+                        update_material(1);
+                        update_material(2);
+
                     } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
+                        // Load texture coordinates into mesh, when any
+                        Texture2DGroup *group = static_cast<Texture2DGroup *>(it->second); // fix bug
                         if (mesh->mTextureCoords[0] == nullptr) {
                             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);
                             for (size_t i = 0; i < mMaterials.size(); ++i) {
                                 if (name == mMaterials[i]->GetName().C_Str()) {
@@ -441,19 +494,42 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
                                 }
                             }
                             mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
+                            for (unsigned int vertex_index = 0; vertex_index < mesh->mNumVertices; vertex_index++) {
+                                mesh->mTextureCoords[0][vertex_index].z = IdNotSet;//mark not set
+                            }
                         }
-                    } 
-                }
-            }
 
-            // 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);
+                        auto update_texture = [&](int idx) {
+                            if (pindex[idx] != IdNotSet) {
+                                size_t vertex_index = face.mIndices[idx];
+                                mesh->mTextureCoords[0][vertex_index] =
+                                        aiVector3D(group->mTex2dCoords[pindex[idx]].x, group->mTex2dCoords[pindex[idx]].y, 0.0f);
+                            }
+                        };
+
+                        update_texture(0);
+                        update_texture(1);
+                        update_texture(2);
+
+                    } else if (it->second->getType() == ResourceType::RT_ColorGroup) {
+                        // Load vertex color into mesh, when any
+                        ColorGroup *group = static_cast<ColorGroup *>(it->second);
+                        if (mesh->mColors[0] == nullptr) {
+                            mesh->mColors[0] = new aiColor4D[mesh->mNumVertices];
+                        }
+
+                        auto update_color = [&](int idx) {
+                            if (pindex[idx] != IdNotSet) {
+                                size_t vertex_index = face.mIndices[idx];
+                                mesh->mColors[0][vertex_index] = group->mColors[pindex[idx]];
+                            }
+                        };
+
+                        update_color(0);
+                        update_color(1);
+                        update_color(2);
+                    }
+                }
             }
 
             faces.push_back(face);
@@ -582,7 +658,7 @@ aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basemater
     stdMaterialName += strId;
     stdMaterialName += "_";
     if (hasName) {
-        stdMaterialName += std::string(name);
+        stdMaterialName += name;
     } else {
         stdMaterialName += "basemat_";
         stdMaterialName += ai_to_string(mMaterials.size());
@@ -596,6 +672,38 @@ aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basemater
     return material;
 }
 
+void XmlSerializer::ReadColor(XmlNode &node, ColorGroup *colorGroup) {
+    if (node.empty() || nullptr == colorGroup) {
+        return;
+    }
+
+    for (XmlNode currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == XmlTag::color_item) {
+            const char *color = currentNode.attribute(XmlTag::color_vaule).as_string();
+            aiColor4D color_value;
+            if (parseColor(color, color_value)) {
+                colorGroup->mColors.push_back(color_value);
+            }
+        }
+    }
+}
+
+void XmlSerializer::ReadColorGroup(XmlNode &node) {
+    if (node.empty()) {
+        return;
+    }
+
+    int id = IdNotSet;
+    if (!XmlParser::getIntAttribute(node, XmlTag::id, id)) {
+        return;
+    }
+
+    ColorGroup *group = new ColorGroup(id);
+    ReadColor(node, group);
+    mResourcesDictionnary.insert(std::make_pair(id, group));
+}
+
 void XmlSerializer::StoreMaterialsInScene(aiScene *scene) {
     if (nullptr == scene) {
         return;

+ 4 - 1
Engine/lib/assimp/code/AssetLib/3MF/XmlSerializer.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -57,6 +57,7 @@ class D3MFOpcPackage;
 class Object;
 class Texture2DGroup;
 class EmbeddedTexture;
+class ColorGroup;
 
 class XmlSerializer {
 public:
@@ -78,6 +79,8 @@ private:
     void ReadTextureGroup(XmlNode &node);
     aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId);
     void StoreMaterialsInScene(aiScene *scene);
+    void ReadColorGroup(XmlNode &node);
+    void ReadColor(XmlNode &node, ColorGroup *colorGroup);
 
 private:
     struct MetaEntry {

+ 121 - 120
Engine/lib/assimp/code/AssetLib/AC/ACLoader.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -60,9 +60,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/Importer.hpp>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "AC3D Importer",
     "",
     "",
@@ -77,8 +77,8 @@ static const aiImporterDesc desc = {
 
 // ------------------------------------------------------------------------------------------------
 // skip to the next token
-inline const char *AcSkipToNextToken(const char *buffer) {
-    if (!SkipSpaces(&buffer)) {
+inline const char *AcSkipToNextToken(const char *buffer, const char *end) {
+    if (!SkipSpaces(&buffer, end)) {
         ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL");
     }
     return buffer;
@@ -86,13 +86,13 @@ inline const char *AcSkipToNextToken(const char *buffer) {
 
 // ------------------------------------------------------------------------------------------------
 // read a string (may be enclosed in double quotation marks). buffer must point to "
-inline const char *AcGetString(const char *buffer, std::string &out) {
+inline const char *AcGetString(const char *buffer, const char *end, std::string &out) {
     if (*buffer == '\0') {
         throw DeadlyImportError("AC3D: Unexpected EOF in string");
     }
     ++buffer;
     const char *sz = buffer;
-    while ('\"' != *buffer) {
+    while ('\"' != *buffer && buffer != end) {
         if (IsLineEnd(*buffer)) {
             ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string");
             out = "ERROR";
@@ -112,8 +112,8 @@ inline const char *AcGetString(const char *buffer, std::string &out) {
 // ------------------------------------------------------------------------------------------------
 // read 1 to n floats prefixed with an optional predefined identifier
 template <class T>
-inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name, size_t name_length, size_t num, T *out) {
-    buffer = AcSkipToNextToken(buffer);
+inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *end, const char *name, size_t name_length, size_t num, T *out) {
+    buffer = AcSkipToNextToken(buffer, end);
     if (0 != name_length) {
         if (0 != strncmp(buffer, name, name_length) || !IsSpace(buffer[name_length])) {
             ASSIMP_LOG_ERROR("AC3D: Unexpected token. ", name, " was expected.");
@@ -122,7 +122,7 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name
         buffer += name_length + 1;
     }
     for (unsigned int _i = 0; _i < num; ++_i) {
-        buffer = AcSkipToNextToken(buffer);
+        buffer = AcSkipToNextToken(buffer, end);
         buffer = fast_atoreal_move<float>(buffer, ((float *)out)[_i]);
     }
 
@@ -132,7 +132,7 @@ inline const char *TAcCheckedLoadFloatArray(const char *buffer, const char *name
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 AC3DImporter::AC3DImporter() :
-        buffer(),
+        mBuffer(),
         configSplitBFCull(),
         configEvalSubdivision(),
         mNumMeshes(),
@@ -164,17 +164,17 @@ const aiImporterDesc *AC3DImporter::GetInfo() const {
 // ------------------------------------------------------------------------------------------------
 // Get a pointer to the next line from the file
 bool AC3DImporter::GetNextLine() {
-    SkipLine(&buffer);
-    return SkipSpaces(&buffer);
+    SkipLine(&mBuffer.data, mBuffer.end);
+    return SkipSpaces(&mBuffer.data, mBuffer.end);
 }
 
 // ------------------------------------------------------------------------------------------------
 // Parse an object section in an AC file
-void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
-    if (!TokenMatch(buffer, "OBJECT", 6))
-        return;
+bool AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
+    if (!TokenMatch(mBuffer.data, "OBJECT", 6))
+        return false;
 
-    SkipSpaces(&buffer);
+    SkipSpaces(&mBuffer.data, mBuffer.end);
 
     ++mNumMeshes;
 
@@ -182,7 +182,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
     Object &obj = objects.back();
 
     aiLight *light = nullptr;
-    if (!ASSIMP_strincmp(buffer, "light", 5)) {
+    if (!ASSIMP_strincmp(mBuffer.data, "light", 5)) {
         // This is a light source. Add it to the list
         mLights->push_back(light = new aiLight());
 
@@ -193,65 +193,71 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
 
         // Generate a default name for both the light source and the node
         // FIXME - what's the right way to print a size_t? Is 'zu' universally available? stick with the safe version.
-        light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1);
+        light->mName.length = ::ai_snprintf(light->mName.data, AI_MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1);
         obj.name = std::string(light->mName.data);
 
         ASSIMP_LOG_VERBOSE_DEBUG("AC3D: Light source encountered");
         obj.type = Object::Light;
-    } else if (!ASSIMP_strincmp(buffer, "group", 5)) {
+    } else if (!ASSIMP_strincmp(mBuffer.data, "group", 5)) {
         obj.type = Object::Group;
-    } else if (!ASSIMP_strincmp(buffer, "world", 5)) {
+    } else if (!ASSIMP_strincmp(mBuffer.data, "world", 5)) {
         obj.type = Object::World;
     } else
         obj.type = Object::Poly;
     while (GetNextLine()) {
-        if (TokenMatch(buffer, "kids", 4)) {
-            SkipSpaces(&buffer);
-            unsigned int num = strtoul10(buffer, &buffer);
+        if (TokenMatch(mBuffer.data, "kids", 4)) {
+            SkipSpaces(&mBuffer.data, mBuffer.end);
+            unsigned int num = strtoul10(mBuffer.data, &mBuffer.data);
             GetNextLine();
             if (num) {
                 // load the children of this object recursively
                 obj.children.reserve(num);
-                for (unsigned int i = 0; i < num; ++i)
-                    LoadObjectSection(obj.children);
+                for (unsigned int i = 0; i < num; ++i) {
+                    if (!LoadObjectSection(obj.children)) {
+                        ASSIMP_LOG_WARN("AC3D: wrong number of kids");
+                        break;
+                    }
+                }
             }
-            return;
-        } else if (TokenMatch(buffer, "name", 4)) {
-            SkipSpaces(&buffer);
-            buffer = AcGetString(buffer, obj.name);
+            return true;
+        } else if (TokenMatch(mBuffer.data, "name", 4)) {
+            SkipSpaces(&mBuffer.data, mBuffer.data);
+            mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, obj.name);
 
             // If this is a light source, we'll also need to store
             // the name of the node in it.
             if (light) {
                 light->mName.Set(obj.name);
             }
-        } else if (TokenMatch(buffer, "texture", 7)) {
-            SkipSpaces(&buffer);
-            buffer = AcGetString(buffer, obj.texture);
-        } else if (TokenMatch(buffer, "texrep", 6)) {
-            SkipSpaces(&buffer);
-            buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texRepeat);
+        } else if (TokenMatch(mBuffer.data, "texture", 7)) {
+            SkipSpaces(&mBuffer.data, mBuffer.end);
+            std::string texture;
+            mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, texture);
+            obj.textures.push_back(texture);
+        } else if (TokenMatch(mBuffer.data, "texrep", 6)) {
+            SkipSpaces(&mBuffer.data, mBuffer.end);
+            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &obj.texRepeat);
             if (!obj.texRepeat.x || !obj.texRepeat.y)
                 obj.texRepeat = aiVector2D(1.f, 1.f);
-        } else if (TokenMatch(buffer, "texoff", 6)) {
-            SkipSpaces(&buffer);
-            buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texOffset);
-        } else if (TokenMatch(buffer, "rot", 3)) {
-            SkipSpaces(&buffer);
-            buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 9, &obj.rotation);
-        } else if (TokenMatch(buffer, "loc", 3)) {
-            SkipSpaces(&buffer);
-            buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &obj.translation);
-        } else if (TokenMatch(buffer, "subdiv", 6)) {
-            SkipSpaces(&buffer);
-            obj.subDiv = strtoul10(buffer, &buffer);
-        } else if (TokenMatch(buffer, "crease", 6)) {
-            SkipSpaces(&buffer);
-            obj.crease = fast_atof(buffer);
-        } else if (TokenMatch(buffer, "numvert", 7)) {
-            SkipSpaces(&buffer);
-
-            unsigned int t = strtoul10(buffer, &buffer);
+        } else if (TokenMatch(mBuffer.data, "texoff", 6)) {
+            SkipSpaces(&mBuffer.data, mBuffer.end);
+            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &obj.texOffset);
+        } else if (TokenMatch(mBuffer.data, "rot", 3)) {
+            SkipSpaces(&mBuffer.data, mBuffer.end);
+            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 9, &obj.rotation);
+        } else if (TokenMatch(mBuffer.data, "loc", 3)) {
+            SkipSpaces(&mBuffer.data, mBuffer.end);
+            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 3, &obj.translation);
+        } else if (TokenMatch(mBuffer.data, "subdiv", 6)) {
+            SkipSpaces(&mBuffer.data, mBuffer.end);
+            obj.subDiv = strtoul10(mBuffer.data, &mBuffer.data);
+        } else if (TokenMatch(mBuffer.data, "crease", 6)) {
+            SkipSpaces(&mBuffer.data, mBuffer.end);
+            obj.crease = fast_atof(mBuffer.data);
+        } else if (TokenMatch(mBuffer.data, "numvert", 7)) {
+            SkipSpaces(&mBuffer.data, mBuffer.end);
+
+            unsigned int t = strtoul10(mBuffer.data, &mBuffer.data);
             if (t >= AI_MAX_ALLOC(aiVector3D)) {
                 throw DeadlyImportError("AC3D: Too many vertices, would run out of memory");
             }
@@ -260,59 +266,59 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
                 if (!GetNextLine()) {
                     ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: not all vertices have been parsed yet");
                     break;
-                } else if (!IsNumeric(*buffer)) {
+                } else if (!IsNumeric(*mBuffer.data)) {
                     ASSIMP_LOG_ERROR("AC3D: Unexpected token: not all vertices have been parsed yet");
-                    --buffer; // make sure the line is processed a second time
+                    --mBuffer.data; // make sure the line is processed a second time
                     break;
                 }
                 obj.vertices.emplace_back();
                 aiVector3D &v = obj.vertices.back();
-                buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 3, &v.x);
+                mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 3, &v.x);
             }
-        } else if (TokenMatch(buffer, "numsurf", 7)) {
-            SkipSpaces(&buffer);
+        } else if (TokenMatch(mBuffer.data, "numsurf", 7)) {
+            SkipSpaces(&mBuffer.data, mBuffer.end);
 
             bool Q3DWorkAround = false;
 
-            const unsigned int t = strtoul10(buffer, &buffer);
+            const unsigned int t = strtoul10(mBuffer.data, &mBuffer.data);
             obj.surfaces.reserve(t);
             for (unsigned int i = 0; i < t; ++i) {
                 GetNextLine();
-                if (!TokenMatch(buffer, "SURF", 4)) {
+                if (!TokenMatch(mBuffer.data, "SURF", 4)) {
                     // FIX: this can occur for some files - Quick 3D for
                     // example writes no surf chunks
                     if (!Q3DWorkAround) {
                         ASSIMP_LOG_WARN("AC3D: SURF token was expected");
                         ASSIMP_LOG_VERBOSE_DEBUG("Continuing with Quick3D Workaround enabled");
                     }
-                    --buffer; // make sure the line is processed a second time
+                    --mBuffer.data; // make sure the line is processed a second time
                     // break; --- see fix notes above
 
                     Q3DWorkAround = true;
                 }
-                SkipSpaces(&buffer);
+                SkipSpaces(&mBuffer.data, mBuffer.end);
                 obj.surfaces.emplace_back();
                 Surface &surf = obj.surfaces.back();
-                surf.flags = strtoul_cppstyle(buffer);
+                surf.flags = strtoul_cppstyle(mBuffer.data);
 
-                while (1) {
+                while (true) {
                     if (!GetNextLine()) {
                         throw DeadlyImportError("AC3D: Unexpected EOF: surface is incomplete");
                     }
-                    if (TokenMatch(buffer, "mat", 3)) {
-                        SkipSpaces(&buffer);
-                        surf.mat = strtoul10(buffer);
-                    } else if (TokenMatch(buffer, "refs", 4)) {
+                    if (TokenMatch(mBuffer.data, "mat", 3)) {
+                        SkipSpaces(&mBuffer.data, mBuffer.end);
+                        surf.mat = strtoul10(mBuffer.data);
+                    } else if (TokenMatch(mBuffer.data, "refs", 4)) {
                         // --- see fix notes above
                         if (Q3DWorkAround) {
                             if (!surf.entries.empty()) {
-                                buffer -= 6;
+                                mBuffer.data -= 6;
                                 break;
                             }
                         }
 
-                        SkipSpaces(&buffer);
-                        const unsigned int m = strtoul10(buffer);
+                        SkipSpaces(&mBuffer.data, mBuffer.end);
+                        const unsigned int m = strtoul10(mBuffer.data);
                         surf.entries.reserve(m);
 
                         obj.numRefs += m;
@@ -325,12 +331,12 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
                             surf.entries.emplace_back();
                             Surface::SurfaceEntry &entry = surf.entries.back();
 
-                            entry.first = strtoul10(buffer, &buffer);
-                            SkipSpaces(&buffer);
-                            buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &entry.second);
+                            entry.first = strtoul10(mBuffer.data, &mBuffer.data);
+                            SkipSpaces(&mBuffer.data, mBuffer.end);
+                            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "", 0, 2, &entry.second);
                         }
                     } else {
-                        --buffer; // make sure the line is processed a second time
+                        --mBuffer.data; // make sure the line is processed a second time
                         break;
                     }
                 }
@@ -338,6 +344,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
         }
     }
     ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: \'kids\' line was expected");
+    return false;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -351,8 +358,8 @@ void AC3DImporter::ConvertMaterial(const Object &object,
         s.Set(matSrc.name);
         matDest.AddProperty(&s, AI_MATKEY_NAME);
     }
-    if (object.texture.length()) {
-        s.Set(object.texture);
+    if (!object.textures.empty()) {
+        s.Set(object.textures[0]);
         matDest.AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
 
         // UV transformation
@@ -443,7 +450,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
                     idx = 0;
                 }
                 if ((*it).entries.empty()) {
-                    ASSIMP_LOG_WARN("AC3D: surface her zero vertex references");
+                    ASSIMP_LOG_WARN("AC3D: surface has zero vertex references");
                 }
 
                 // validate all vertex indices to make sure we won't crash here
@@ -461,16 +468,15 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
                 }
 
                 switch ((*it).GetType()) {
-                    // closed line
-                case Surface::ClosedLine:
-                    needMat[idx].first += (unsigned int)(*it).entries.size();
-                    needMat[idx].second += (unsigned int)(*it).entries.size() << 1u;
+                case Surface::ClosedLine: // closed line
+                    needMat[idx].first += static_cast<unsigned int>((*it).entries.size());
+                    needMat[idx].second += static_cast<unsigned int>((*it).entries.size() << 1u);
                     break;
 
                     // unclosed line
                 case Surface::OpenLine:
-                    needMat[idx].first += (unsigned int)(*it).entries.size() - 1;
-                    needMat[idx].second += ((unsigned int)(*it).entries.size() - 1) << 1u;
+                    needMat[idx].first += static_cast<unsigned int>((*it).entries.size() - 1);
+                    needMat[idx].second += static_cast<unsigned int>(((*it).entries.size() - 1) << 1u);
                     break;
 
                     // triangle strip
@@ -532,7 +538,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
                 // allocate UV coordinates, but only if the texture name for the
                 // surface is not empty
                 aiVector3D *uv = nullptr;
-                if (object.texture.length()) {
+                if (!object.textures.empty()) {
                     uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
                     mesh->mNumUVComponents[0] = 2;
                 }
@@ -572,15 +578,6 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
                                 const Surface::SurfaceEntry &entry2 = src.entries[i + 1];
                                 const Surface::SurfaceEntry &entry3 = src.entries[i + 2];
 
-                                // skip degenerate triangles
-                                if (object.vertices[entry1.first] == object.vertices[entry2.first] ||
-                                        object.vertices[entry1.first] == object.vertices[entry3.first] ||
-                                        object.vertices[entry2.first] == object.vertices[entry3.first]) {
-                                    mesh->mNumFaces--;
-                                    mesh->mNumVertices -= 3;
-                                    continue;
-                                }
-
                                 aiFace &face = *faces++;
                                 face.mNumIndices = 3;
                                 face.mIndices = new unsigned int[face.mNumIndices];
@@ -699,18 +696,18 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
         // generate a name depending on the type of the node
         switch (object.type) {
         case Object::Group:
-            node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACGroup_%i", mGroupsCounter++);
+            node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACGroup_%i", mGroupsCounter++);
             break;
         case Object::Poly:
-            node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACPoly_%i", mPolysCounter++);
+            node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACPoly_%i", mPolysCounter++);
             break;
         case Object::Light:
-            node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACLight_%i", mLightsCounter++);
+            node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACLight_%i", mLightsCounter++);
             break;
 
             // there shouldn't be more than one world, but we don't care
         case Object::World:
-            node->mName.length = ::ai_snprintf(node->mName.data, MAXLEN, "ACWorld_%i", mWorldsCounter++);
+            node->mName.length = ::ai_snprintf(node->mName.data, AI_MAXLEN, "ACWorld_%i", mWorldsCounter++);
             break;
         }
     }
@@ -750,7 +747,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
 
     // Check whether we can read from the file
-    if (file.get() == nullptr) {
+    if (file == nullptr) {
         throw DeadlyImportError("Failed to open AC3D file ", pFile, ".");
     }
 
@@ -758,17 +755,18 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
     std::vector<char> mBuffer2;
     TextFileToBuffer(file.get(), mBuffer2);
 
-    buffer = &mBuffer2[0];
+    mBuffer.data = &mBuffer2[0];
+    mBuffer.end = &mBuffer2[0] + mBuffer2.size();
     mNumMeshes = 0;
 
     mLightsCounter = mPolysCounter = mWorldsCounter = mGroupsCounter = 0;
 
-    if (::strncmp(buffer, "AC3D", 4)) {
+    if (::strncmp(mBuffer.data, "AC3D", 4)) {
         throw DeadlyImportError("AC3D: No valid AC3D file, magic sequence not found");
     }
 
     // print the file format version to the console
-    unsigned int version = HexDigitToDecimal(buffer[4]);
+    unsigned int version = HexDigitToDecimal(mBuffer.data[4]);
     char msg[3];
     ASSIMP_itoa10(msg, 3, version);
     ASSIMP_LOG_INFO("AC3D file format version: ", msg);
@@ -783,30 +781,31 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
     mLights = &lights;
 
     while (GetNextLine()) {
-        if (TokenMatch(buffer, "MATERIAL", 8)) {
+        if (TokenMatch(mBuffer.data, "MATERIAL", 8)) {
             materials.emplace_back();
             Material &mat = materials.back();
 
             // manually parse the material ... sscanf would use the buldin atof ...
             // Format: (name) rgb %f %f %f  amb %f %f %f  emis %f %f %f  spec %f %f %f  shi %d  trans %f
 
-            buffer = AcSkipToNextToken(buffer);
-            if ('\"' == *buffer) {
-                buffer = AcGetString(buffer, mat.name);
-                buffer = AcSkipToNextToken(buffer);
+            mBuffer.data = AcSkipToNextToken(mBuffer.data, mBuffer.end);
+            if ('\"' == *mBuffer.data) {
+                mBuffer.data = AcGetString(mBuffer.data, mBuffer.end, mat.name);
+                mBuffer.data = AcSkipToNextToken(mBuffer.data, mBuffer.end);
             }
 
-            buffer = TAcCheckedLoadFloatArray(buffer, "rgb", 3, 3, &mat.rgb);
-            buffer = TAcCheckedLoadFloatArray(buffer, "amb", 3, 3, &mat.amb);
-            buffer = TAcCheckedLoadFloatArray(buffer, "emis", 4, 3, &mat.emis);
-            buffer = TAcCheckedLoadFloatArray(buffer, "spec", 4, 3, &mat.spec);
-            buffer = TAcCheckedLoadFloatArray(buffer, "shi", 3, 1, &mat.shin);
-            buffer = TAcCheckedLoadFloatArray(buffer, "trans", 5, 1, &mat.trans);
+            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "rgb", 3, 3, &mat.rgb);
+            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "amb", 3, 3, &mat.amb);
+            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "emis", 4, 3, &mat.emis);
+            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "spec", 4, 3, &mat.spec);
+            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "shi", 3, 1, &mat.shin);
+            mBuffer.data = TAcCheckedLoadFloatArray(mBuffer.data, mBuffer.end, "trans", 5, 1, &mat.trans);
+        } else {
+            LoadObjectSection(rootObjects);
         }
-        LoadObjectSection(rootObjects);
     }
 
-    if (rootObjects.empty() || !mNumMeshes) {
+    if (rootObjects.empty() || mNumMeshes == 0u) {
         throw DeadlyImportError("AC3D: No meshes have been loaded");
     }
     if (materials.empty()) {
@@ -822,7 +821,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
     materials.reserve(mNumMeshes);
 
     // generate a dummy root if there are multiple objects on the top layer
-    Object *root;
+    Object *root = nullptr;
     if (1 == rootObjects.size())
         root = &rootObjects[0];
     else {
@@ -835,7 +834,7 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
         delete root;
     }
 
-    if (!::strncmp(pScene->mRootNode->mName.data, "Node", 4)) {
+    if (::strncmp(pScene->mRootNode->mName.data, "Node", 4) == 0) {
         pScene->mRootNode->mName.Set("<AC3DWorld>");
     }
 
@@ -854,10 +853,12 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
 
     // copy lights
     pScene->mNumLights = (unsigned int)lights.size();
-    if (lights.size()) {
+    if (!lights.empty()) {
         pScene->mLights = new aiLight *[lights.size()];
         ::memcpy(pScene->mLights, &lights[0], lights.size() * sizeof(void *));
     }
 }
 
+} // namespace Assimp
+
 #endif //!defined ASSIMP_BUILD_NO_AC_IMPORTER

+ 5 - 5
Engine/lib/assimp/code/AssetLib/AC/ACLoader.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -125,7 +125,6 @@ public:
                 type(World),
                 name(),
                 children(),
-                texture(),
                 texRepeat(1.f, 1.f),
                 texOffset(0.0f, 0.0f),
                 rotation(),
@@ -151,7 +150,8 @@ public:
         std::vector<Object> children;
 
         // texture to be assigned to all surfaces of the object
-        std::string texture;
+        // the .acc format supports up to 4 textures
+        std::vector<std::string> textures;
 
         // texture repat factors (scaling for all coordinates)
         aiVector2D texRepeat, texOffset;
@@ -216,7 +216,7 @@ private:
      *  load subobjects, the method returns after a 'kids 0' was
      *  encountered.
      *  @objects List of output objects*/
-    void LoadObjectSection(std::vector<Object> &objects);
+    bool LoadObjectSection(std::vector<Object> &objects);
 
     // -------------------------------------------------------------------
     /** Convert all objects into meshes and nodes.
@@ -242,7 +242,7 @@ private:
 
 private:
     // points to the next data line
-    const char *buffer;
+    aiBuffer mBuffer;
 
     // Configuration option: if enabled, up to two meshes
     // are generated per material: those faces who have

+ 14 - 37
Engine/lib/assimp/code/AssetLib/AMF/AMFImporter.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp {
 
-const aiImporterDesc AMFImporter::Description = {
+static constexpr aiImporterDesc Description = {
     "Additive manufacturing file format(AMF) Importer",
     "smalcom",
     "",
@@ -83,11 +83,7 @@ void AMFImporter::Clear() {
 
 AMFImporter::AMFImporter() AI_NO_EXCEPT :
         mNodeElement_Cur(nullptr),
-        mXmlParser(nullptr),
-        mUnit(),
-        mVersion(),
-        mMaterial_Converted(),
-        mTexture_Converted() {
+        mXmlParser(nullptr) {
     // empty
 }
 
@@ -182,28 +178,6 @@ bool AMFImporter::XML_SearchNode(const std::string &nodeName) {
     return nullptr != mXmlParser->findNode(nodeName);
 }
 
-void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString) {
-    size_t instr_len;
-
-    pOutString.clear();
-    instr_len = strlen(pInStr);
-    if (!instr_len) return;
-
-    pOutString.reserve(instr_len * 3 / 2);
-    // check and correct floats in format ".x". Must be "x.y".
-    if (pInStr[0] == '.') pOutString.push_back('0');
-
-    pOutString.push_back(pInStr[0]);
-    for (size_t ci = 1; ci < instr_len; ci++) {
-        if ((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t'))) {
-            pOutString.push_back('0');
-            pOutString.push_back('.');
-        } else {
-            pOutString.push_back(pInStr[ci]);
-        }
-    }
-}
-
 static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) {
     return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/'));
 }
@@ -217,7 +191,10 @@ void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std
     uint8_t arr4[4], arr3[3];
 
     // check input data
-    if (pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
+    if (pInputBase64.size() % 4) {
+        throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
+    }
+
     // prepare output place
     pOutputData.clear();
     pOutputData.reserve(pInputBase64.size() / 4 * 3);
@@ -261,7 +238,7 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
 
     // Check whether we can read from the file
-    if (file.get() == nullptr) {
+    if (file == nullptr) {
         throw DeadlyImportError("Failed to open AMF file ", pFile, ".");
     }
 
@@ -407,17 +384,17 @@ void AMFImporter::ParseNode_Instance(XmlNode &node) {
         for (auto &currentNode : node.children()) {
             const std::string &currentName = currentNode.name();
             if (currentName == "deltax") {
-                XmlParser::getValueAsFloat(currentNode, als.Delta.x);
+                XmlParser::getValueAsReal(currentNode, als.Delta.x);
             } else if (currentName == "deltay") {
-                XmlParser::getValueAsFloat(currentNode, als.Delta.y);
+                XmlParser::getValueAsReal(currentNode, als.Delta.y);
             } else if (currentName == "deltaz") {
-                XmlParser::getValueAsFloat(currentNode, als.Delta.z);
+                XmlParser::getValueAsReal(currentNode, als.Delta.z);
             } else if (currentName == "rx") {
-                XmlParser::getValueAsFloat(currentNode, als.Delta.x);
+                XmlParser::getValueAsReal(currentNode, als.Delta.x);
             } else if (currentName == "ry") {
-                XmlParser::getValueAsFloat(currentNode, als.Delta.y);
+                XmlParser::getValueAsReal(currentNode, als.Delta.y);
             } else if (currentName == "rz") {
-                XmlParser::getValueAsFloat(currentNode, als.Delta.z);
+                XmlParser::getValueAsReal(currentNode, als.Delta.z);
             }
         }
         ParseHelper_Node_Exit();

+ 50 - 52
Engine/lib/assimp/code/AssetLib/AMF/AMFImporter.hpp

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

+ 4 - 4
Engine/lib/assimp/code/AssetLib/AMF/AMFImporter_Geometry.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -167,11 +167,11 @@ void AMFImporter::ParseNode_Coordinates(XmlNode &node) {
             AMFCoordinates &als = *((AMFCoordinates *)ne); // alias for convenience
             const std::string &currentName = ai_tolower(currentNode.name());
             if (currentName == "x") {
-                XmlParser::getValueAsFloat(currentNode, als.Coordinate.x);
+                XmlParser::getValueAsReal(currentNode, als.Coordinate.x);
             } else if (currentName == "y") {
-                XmlParser::getValueAsFloat(currentNode, als.Coordinate.y);
+                XmlParser::getValueAsReal(currentNode, als.Coordinate.y);
             } else if (currentName == "z") {
-                XmlParser::getValueAsFloat(currentNode, als.Coordinate.z);
+                XmlParser::getValueAsReal(currentNode, als.Coordinate.z);
             }
         }
         ParseHelper_Node_Exit();

+ 7 - 8
Engine/lib/assimp/code/AssetLib/AMF/AMFImporter_Material.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -263,26 +263,25 @@ void AMFImporter::ParseNode_TexMap(XmlNode &node, const bool pUseOldName) {
             const std::string &name = currentNode.name();
             if (name == "utex1") {
 				read_flag[0] = true;
-                XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].x);
+                XmlParser::getValueAsReal(node, als.TextureCoordinate[0].x);
             } else if (name == "utex2") {
 				read_flag[1] = true;
-                XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].x);
+                XmlParser::getValueAsReal(node, als.TextureCoordinate[1].x);
             } else if (name == "utex3") {
 				read_flag[2] = true;
-                XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].x);
+                XmlParser::getValueAsReal(node, als.TextureCoordinate[2].x);
             } else if (name == "vtex1") {
 				read_flag[3] = true;
-                XmlParser::getValueAsFloat(node, als.TextureCoordinate[0].y);
+                XmlParser::getValueAsReal(node, als.TextureCoordinate[0].y);
             } else if (name == "vtex2") {
 				read_flag[4] = true;
-                XmlParser::getValueAsFloat(node, als.TextureCoordinate[1].y);
+                XmlParser::getValueAsReal(node, als.TextureCoordinate[1].y);
             } else if (name == "vtex3") {
 				read_flag[5] = true;
-                XmlParser::getValueAsFloat(node, als.TextureCoordinate[2].y);
+                XmlParser::getValueAsReal(node, als.TextureCoordinate[2].y);
 			}
 		}
         ParseHelper_Node_Exit();
-
 	} else {
 		for (pugi::xml_attribute &attr : node.attributes()) {
             const std::string name = attr.name();

+ 5 - 22
Engine/lib/assimp/code/AssetLib/AMF/AMFImporter_Node.hpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -56,7 +56,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <string>
 #include <vector>
 
-/// \class CAMFImporter_NodeElement
 /// Base class for elements of nodes.
 class AMFNodeElementBase {
 public:
@@ -88,9 +87,7 @@ public:
 	std::list<AMFNodeElementBase *> Child; ///< Child elements.
 
 public: /// Destructor, virtual..
-	virtual ~AMFNodeElementBase() {
-		// empty
-	}
+	virtual ~AMFNodeElementBase() = default;
 
 	/// Disabled copy constructor and co.
 	AMFNodeElementBase(const AMFNodeElementBase &pNodeElement) = delete;
@@ -103,12 +100,11 @@ protected:
 	/// \param [in] pType - element type.
 	/// \param [in] pParent - parent element.
 	AMFNodeElementBase(const EType pType, AMFNodeElementBase *pParent) :
-			Type(pType), ID(), Parent(pParent), Child() {
+			Type(pType), Parent(pParent) {
 		// empty
 	}
 }; // class IAMFImporter_NodeElement
 
-/// \struct CAMFImporter_NodeElement_Constellation
 /// A collection of objects or constellations with specific relative locations.
 struct AMFConstellation : public AMFNodeElementBase {
 	/// Constructor.
@@ -118,7 +114,6 @@ struct AMFConstellation : public AMFNodeElementBase {
 
 }; // struct CAMFImporter_NodeElement_Constellation
 
-/// \struct CAMFImporter_NodeElement_Instance
 /// Part of constellation.
 struct AMFInstance : public AMFNodeElementBase {
 
@@ -137,7 +132,6 @@ struct AMFInstance : public AMFNodeElementBase {
 			AMFNodeElementBase(ENET_Instance, pParent) {}
 };
 
-/// \struct CAMFImporter_NodeElement_Metadata
 /// Structure that define metadata node.
 struct AMFMetadata : public AMFNodeElementBase {
 
@@ -150,7 +144,6 @@ struct AMFMetadata : public AMFNodeElementBase {
 			AMFNodeElementBase(ENET_Metadata, pParent) {}
 };
 
-/// \struct CAMFImporter_NodeElement_Root
 /// Structure that define root node.
 struct AMFRoot : public AMFNodeElementBase {
 
@@ -163,7 +156,6 @@ struct AMFRoot : public AMFNodeElementBase {
 			AMFNodeElementBase(ENET_Root, pParent) {}
 };
 
-/// \struct CAMFImporter_NodeElement_Color
 /// Structure that define object node.
 struct AMFColor : public AMFNodeElementBase {
 	bool Composed; ///< Type of color stored: if true then look for formula in \ref Color_Composed[4], else - in \ref Color.
@@ -174,12 +166,11 @@ struct AMFColor : public AMFNodeElementBase {
 	/// @brief  Constructor.
 	/// @param [in] pParent - pointer to parent node.
 	AMFColor(AMFNodeElementBase *pParent) :
-			AMFNodeElementBase(ENET_Color, pParent), Composed(false), Color(), Profile() {
+			AMFNodeElementBase(ENET_Color, pParent), Composed(false), Color() {
 		// empty
 	}
 };
 
-/// \struct CAMFImporter_NodeElement_Material
 /// Structure that define material node.
 struct AMFMaterial : public AMFNodeElementBase {
 
@@ -189,7 +180,6 @@ struct AMFMaterial : public AMFNodeElementBase {
 			AMFNodeElementBase(ENET_Material, pParent) {}
 };
 
-/// \struct CAMFImporter_NodeElement_Object
 /// Structure that define object node.
 struct AMFObject : public AMFNodeElementBase {
 
@@ -208,7 +198,6 @@ struct AMFMesh : public AMFNodeElementBase {
 			AMFNodeElementBase(ENET_Mesh, pParent) {}
 };
 
-/// \struct CAMFImporter_NodeElement_Vertex
 /// Structure that define vertex node.
 struct AMFVertex : public AMFNodeElementBase {
 	/// Constructor.
@@ -217,7 +206,6 @@ struct AMFVertex : public AMFNodeElementBase {
 			AMFNodeElementBase(ENET_Vertex, pParent) {}
 };
 
-/// \struct CAMFImporter_NodeElement_Edge
 /// Structure that define edge node.
 struct AMFEdge : public AMFNodeElementBase {
 	/// Constructor.
@@ -226,7 +214,6 @@ struct AMFEdge : public AMFNodeElementBase {
 			AMFNodeElementBase(ENET_Edge, pParent) {}
 };
 
-/// \struct CAMFImporter_NodeElement_Vertices
 /// Structure that define vertices node.
 struct AMFVertices : public AMFNodeElementBase {
 	/// Constructor.
@@ -235,7 +222,6 @@ struct AMFVertices : public AMFNodeElementBase {
 			AMFNodeElementBase(ENET_Vertices, pParent) {}
 };
 
-/// \struct CAMFImporter_NodeElement_Volume
 /// Structure that define volume node.
 struct AMFVolume : public AMFNodeElementBase {
 	std::string MaterialID; ///< Which material to use.
@@ -247,7 +233,6 @@ struct AMFVolume : public AMFNodeElementBase {
 			AMFNodeElementBase(ENET_Volume, pParent) {}
 };
 
-/// \struct CAMFImporter_NodeElement_Coordinates
 /// Structure that define coordinates node.
 struct AMFCoordinates : public AMFNodeElementBase {
 	aiVector3D Coordinate; ///< Coordinate.
@@ -258,7 +243,6 @@ struct AMFCoordinates : public AMFNodeElementBase {
 			AMFNodeElementBase(ENET_Coordinates, pParent) {}
 };
 
-/// \struct CAMFImporter_NodeElement_TexMap
 /// Structure that define texture coordinates node.
 struct AMFTexMap : public AMFNodeElementBase {
 	aiVector3D TextureCoordinate[3]; ///< Texture coordinates.
@@ -270,12 +254,11 @@ struct AMFTexMap : public AMFNodeElementBase {
 	/// Constructor.
 	/// \param [in] pParent - pointer to parent node.
 	AMFTexMap(AMFNodeElementBase *pParent) :
-			AMFNodeElementBase(ENET_TexMap, pParent), TextureCoordinate{}, TextureID_R(), TextureID_G(), TextureID_B(), TextureID_A() {
+			AMFNodeElementBase(ENET_TexMap, pParent), TextureCoordinate{} {
 		// empty
 	}
 };
 
-/// \struct CAMFImporter_NodeElement_Triangle
 /// Structure that define triangle node.
 struct AMFTriangle : public AMFNodeElementBase {
 	size_t V[3]; ///< Triangle vertices.

+ 6 - 4
Engine/lib/assimp/code/AssetLib/AMF/AMFImporter_Postprocess.cpp

@@ -1,9 +1,9 @@
-/*
+/*
 ---------------------------------------------------------------------------
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -224,7 +224,8 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string &
     }
 
     // Create format hint.
-    strcpy(converted_texture.FormatHint, "rgba0000"); // copy initial string.
+    constexpr char templateColor[] = "rgba0000";
+    memcpy(converted_texture.FormatHint, templateColor, 8);
     if (!r.empty()) converted_texture.FormatHint[4] = '8';
     if (!g.empty()) converted_texture.FormatHint[5] = '8';
     if (!b.empty()) converted_texture.FormatHint[6] = '8';
@@ -815,6 +816,7 @@ nl_clean_loop:
             for (; next_it != nodeArray.end(); ++next_it) {
                 if ((*next_it)->FindNode((*nl_it)->mName) != nullptr) {
                     // if current top node(nl_it) found in another top node then erase it from node_list and restart search loop.
+                    // FIXME: this leaks memory on test models test8.amf and test9.amf
                     nodeArray.erase(nl_it);
 
                     goto nl_clean_loop;
@@ -866,7 +868,7 @@ nl_clean_loop:
             pScene->mTextures[idx]->mHeight = static_cast<unsigned int>(tex_convd.Height);
             pScene->mTextures[idx]->pcData = (aiTexel *)tex_convd.Data;
             // texture format description.
-            strcpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint);
+            strncpy(pScene->mTextures[idx]->achFormatHint, tex_convd.FormatHint, HINTMAXTEXTURELEN);
             idx++;
         } // for(const SPP_Texture& tex_convd: mTexture_Converted)
 

+ 22 - 39
Engine/lib/assimp/code/AssetLib/ASE/ASELoader.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
-
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 // internal headers
@@ -64,10 +63,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // utilities
 #include <assimp/fast_atof.h>
 
-using namespace Assimp;
+namespace Assimp {
 using namespace Assimp::ASE;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "ASE Importer",
     "",
     "",
@@ -87,10 +86,6 @@ ASEImporter::ASEImporter() :
     // empty
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-ASEImporter::~ASEImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool ASEImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@@ -122,14 +117,14 @@ void ASEImporter::InternReadFile(const std::string &pFile,
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
 
     // Check whether we can read from the file
-    if (file.get() == nullptr) {
+    if (file == nullptr) {
         throw DeadlyImportError("Failed to open ASE file ", pFile, ".");
     }
 
     // Allocate storage and copy the contents of the file to a memory buffer
     std::vector<char> mBuffer2;
     TextFileToBuffer(file.get(), mBuffer2);
-
+    const size_t fileSize = mBuffer2.size();
     this->mBuffer = &mBuffer2[0];
     this->pcScene = pScene;
 
@@ -151,7 +146,7 @@ void ASEImporter::InternReadFile(const std::string &pFile,
     };
 
     // Construct an ASE parser and parse the file
-    ASE::Parser parser(mBuffer, defaultFormat);
+    ASE::Parser parser(mBuffer, fileSize, defaultFormat);
     mParser = &parser;
     mParser->Parse();
 
@@ -326,21 +321,6 @@ void ASEImporter::BuildAnimations(const std::vector<BaseNode *> &nodes) {
                 aiNodeAnim *nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
                 nd->mNodeName.Set(me->mName + ".Target");
 
-                // If there is no input position channel we will need
-                // to supply the default position from the node's
-                // local transformation matrix.
-                /*TargetAnimationHelper helper;
-                if (me->mAnim.akeyPositions.empty())
-                {
-                    aiMatrix4x4& mat = (*i)->mTransform;
-                    helper.SetFixedMainAnimationChannel(aiVector3D(
-                        mat.a4, mat.b4, mat.c4));
-                }
-                else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions);
-                helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions);
-
-                helper.Process(&me->mTargetAnim.akeyPositions);*/
-
                 // Allocate the key array and fill it
                 nd->mNumPositionKeys = (unsigned int)me->mTargetAnim.akeyPositions.size();
                 nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
@@ -466,10 +446,9 @@ void ASEImporter::BuildLights() {
 }
 
 // ------------------------------------------------------------------------------------------------
-void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
-        aiNode *pcParent, const char *szName) {
+void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParent, const std::string &name) {
     aiMatrix4x4 m;
-    AddNodes(nodes, pcParent, szName, m);
+    AddNodes(nodes, pcParent, name, m);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -526,10 +505,9 @@ void ASEImporter::AddMeshes(const ASE::BaseNode *snode, aiNode *node) {
 
 // ------------------------------------------------------------------------------------------------
 // Add child nodes to a given parent node
-void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
-        aiNode *pcParent, const char *szName,
+void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes, aiNode *pcParent, const std::string &name,
         const aiMatrix4x4 &mat) {
-    const size_t len = szName ? ::strlen(szName) : 0;
+    const size_t len = name.size();
     ai_assert(4 <= AI_MAX_NUMBER_OF_COLOR_SETS);
 
     // Receives child nodes for the pcParent node
@@ -539,16 +517,18 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
     // which has *us* as parent.
     for (std::vector<BaseNode *>::const_iterator it = nodes.begin(), end = nodes.end(); it != end; ++it) {
         const BaseNode *snode = *it;
-        if (szName) {
-            if (len != snode->mParent.length() || ::strcmp(szName, snode->mParent.c_str()))
+        if (!name.empty()) {
+            if (len != snode->mParent.length() || name != snode->mParent.c_str()) {
                 continue;
-        } else if (snode->mParent.length())
+            }
+        } else if (snode->mParent.length()) {
             continue;
+        }
 
         (*it)->mProcessed = true;
 
         // Allocate a new node and add it to the output data structure
-        apcNodes.push_back(new aiNode());
+        apcNodes.push_back(new aiNode);
         aiNode *node = apcNodes.back();
 
         node->mName.Set((snode->mName.length() ? snode->mName.c_str() : "Unnamed_Node"));
@@ -561,7 +541,7 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
 
         // Add sub nodes - prevent stack overflow due to recursive parenting
         if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName) {
-            AddNodes(nodes, node, node->mName.data, snode->mTransform);
+            AddNodes(nodes, node, node->mName.C_Str(), snode->mTransform);
         }
 
         // Further processing depends on the type of the node
@@ -639,7 +619,8 @@ void ASEImporter::BuildNodes(std::vector<BaseNode *> &nodes) {
     }
 
     // add all nodes
-    AddNodes(nodes, ch, nullptr);
+    static const std::string none = "";
+    AddNodes(nodes, ch, none);
 
     // now iterate through al nodes and find those that have not yet
     // been added to the nodegraph (= their parent could not be recognized)
@@ -924,7 +905,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh &mesh, std::vector<aiMesh *> &avOutMes
         ASSIMP_LOG_WARN("Material index is out of range");
     }
 
-    // If the material the mesh is assigned to is consisting of submeshes, split it
+    // If the material the mesh is assigned to consists of submeshes, split it
     if (!mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials.empty()) {
         std::vector<ASE::Material> vSubMaterials = mParser->m_vMaterials[mesh.iMaterialIndex].avSubMaterials;
 
@@ -1282,6 +1263,8 @@ bool ASEImporter::GenerateNormals(ASE::Mesh &mesh) {
     return false;
 }
 
+}
+
 #endif // ASSIMP_BUILD_NO_3DS_IMPORTER
 
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

+ 5 - 6
Engine/lib/assimp/code/AssetLib/ASE/ASELoader.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -62,7 +62,7 @@ namespace Assimp {
 class ASEImporter : public BaseImporter {
 public:
     ASEImporter();
-    ~ASEImporter() override;
+    ~ASEImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.
@@ -153,13 +153,13 @@ private:
      *  \param matrix Current transform
      */
     void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
-        aiNode* pcParent,const char* szName);
+        aiNode* pcParent, const std::string &name);
 
     void AddNodes(const std::vector<ASE::BaseNode*>& nodes,
-        aiNode* pcParent,const char* szName,
+        aiNode* pcParent, const std::string &name,
         const aiMatrix4x4& matrix);
 
-    void AddMeshes(const ASE::BaseNode* snode,aiNode* node);
+    void AddMeshes(const ASE::BaseNode* snode, aiNode* node);
 
     // -------------------------------------------------------------------
     /** Generate a default material and add it to the parser's list
@@ -188,5 +188,4 @@ protected:
 
 } // end of namespace Assimp
 
-
 #endif // AI_3DSIMPORTER_H_INC

A diferenza do arquivo foi suprimida porque é demasiado grande
+ 215 - 190
Engine/lib/assimp/code/AssetLib/ASE/ASEParser.cpp


+ 14 - 14
Engine/lib/assimp/code/AssetLib/ASE/ASEParser.h

@@ -2,8 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
-
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -385,20 +384,18 @@ struct Dummy : public BaseNode {
 /** \brief Class to parse ASE files
  */
 class Parser {
-private:
-    Parser() AI_NO_EXCEPT {
-        // empty
-    }
-
 public:
+    /// @brief No default constructor.
+    Parser() = delete;
+
     // -------------------------------------------------------------------
     //! Construct a parser from a given input file which is
     //! guaranteed to be terminated with zero.
-    //! @param szFile Input file
+    //! @param file              The name of the input file.
     //! @param fileFormatDefault Assumed file format version. If the
     //!   file format is specified in the file the new value replaces
     //!   the default value.
-    Parser(const char *szFile, unsigned int fileFormatDefault);
+    Parser(const char *file, size_t fileLen, unsigned int fileFormatDefault);
 
     // -------------------------------------------------------------------
     //! Parses the file into the parsers internal representation
@@ -556,13 +553,15 @@ private:
     //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
     //! \param apOut Output buffer (3 floats)
     //! \param rIndexOut Output index
-    void ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut);
+    void ParseLV4MeshRealTriple(ai_real *apOut, unsigned int &rIndexOut);
+    void ParseLV4MeshFloatTriple(float *apOut, unsigned int &rIndexOut);
 
     // -------------------------------------------------------------------
     //! Parse a *MESH_VERT block in a file
     //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
     //! \param apOut Output buffer (3 floats)
-    void ParseLV4MeshFloatTriple(ai_real *apOut);
+    void ParseLV4MeshRealTriple(ai_real *apOut);
+    void ParseLV4MeshFloatTriple(float *apOut);
 
     // -------------------------------------------------------------------
     //! Parse a *MESH_TFACE block in a file
@@ -580,7 +579,8 @@ private:
     // -------------------------------------------------------------------
     //! Parse a single float element
     //! \param fOut Output float
-    void ParseLV4MeshFloat(ai_real &fOut);
+    void ParseLV4MeshReal(ai_real &fOut);
+    void ParseLV4MeshFloat(float &fOut);
 
     // -------------------------------------------------------------------
     //! Parse a single int element
@@ -620,8 +620,8 @@ private:
     bool ParseString(std::string &out, const char *szName);
 
 public:
-    //! Pointer to current data
-    const char *filePtr;
+    const char *mFilePtr; ////< Pointer to current data
+    const char *mEnd;     ///< The end pointer of the file data
 
     //! background color to be passed to the viewer
     //! QNAN if none was found

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Assbin/AssbinExporter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 2 - 2
Engine/lib/assimp/code/AssetLib/Assbin/AssbinExporter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -56,5 +56,5 @@ namespace Assimp {
 void ASSIMP_API ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/);
 
 }
-#endif 
+#endif
 #endif // AI_ASSBINEXPORTER_H_INC

+ 5 - 9
Engine/lib/assimp/code/AssetLib/Assbin/AssbinFileWriter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -50,11 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/version.h>
 #include <assimp/IOStream.hpp>
 
-#ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-#include <zlib.h>
-#else
-#include "../contrib/zlib/zlib.h"
-#endif
+#include "zlib.h"
 
 #include <ctime>
 
@@ -291,15 +287,15 @@ public:
     size_t Read(void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override {
         return 0;
     }
-    
+
     aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) override {
         return aiReturn_FAILURE;
     }
-    
+
     size_t Tell() const override {
         return cursor;
     }
-    
+
     void Flush() override {
         // not implemented
     }

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Assbin/AssbinFileWriter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 7 - 3
Engine/lib/assimp/code/AssetLib/Assbin/AssbinLoader.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Assimp Binary Importer",
     "Gargaj / Conspiracy",
     "",
@@ -91,9 +91,13 @@ bool AssbinImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, boo
     }
 
     char s[32];
-    in->Read(s, sizeof(char), 32);
+    const size_t read = in->Read(s, sizeof(char), 32);
 
     pIOHandler->Close(in);
+    
+    if (read < 19) {
+      return false;
+    }
 
     return strncmp(s, "ASSIMP.binary-dump.", 19) == 0;
 }

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Assbin/AssbinLoader.h

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Assjson/cencode.c

@@ -7,7 +7,7 @@ For details, see http://sourceforge.net/projects/libb64
 
 #include "cencode.h" // changed from <B64/cencode.h>
 
-const int CHARS_PER_LINE = 72;
+static const int CHARS_PER_LINE = 72;
 
 #ifdef _MSC_VER
 #pragma warning(push)

+ 67 - 54
Engine/lib/assimp/code/AssetLib/Assjson/json_exporter.cpp

@@ -10,6 +10,7 @@ Licensed under a 3-clause BSD license. See the LICENSE file for more information
 #ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
 
 #include <assimp/scene.h>
+#include <assimp/ai_assert.h>
 #include <assimp/Exporter.hpp>
 #include <assimp/IOStream.hpp>
 #include <assimp/IOSystem.hpp>
@@ -23,16 +24,15 @@ Licensed under a 3-clause BSD license. See the LICENSE file for more information
 
 #define CURRENT_FORMAT_VERSION 100
 
-// grab scoped_ptr from assimp to avoid a dependency on boost.
-//#include <assimp/../../code/BoostWorkaround/boost/scoped_ptr.hpp>
-
 #include "mesh_splitter.h"
 
 extern "C" {
-#include "cencode.h"
+#   include "cencode.h"
 }
+
 namespace Assimp {
 
+// Forward declarations
 void ExportAssimp2Json(const char *, Assimp::IOSystem *, const aiScene *, const Assimp::ExportProperties *);
 
 // small utility class to simplify serializing the aiScene to Json
@@ -43,7 +43,7 @@ public:
         Flag_WriteSpecialFloats = 0x2,
         Flag_SkipWhitespaces = 0x4
     };
-    
+
     JSONWriter(Assimp::IOStream &out, unsigned int flags = 0u) :
             out(out), indent (""), newline("\n"), space(" "), buff (), first(false), flags(flags) {
         // make sure that all formatting happens using the standard, C locale and not the user's current locale
@@ -179,7 +179,6 @@ private:
         // escape backslashes and single quotes, both would render the JSON invalid if left as is
         t.reserve(s.length);
         for (size_t i = 0; i < s.length; ++i) {
-
             if (s.data[i] == '\\' || s.data[i] == '\'' || s.data[i] == '\"') {
                 t.push_back('\\');
             }
@@ -241,7 +240,7 @@ private:
     unsigned int flags;
 };
 
-void Write(JSONWriter &out, const aiVector3D &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiVector3D &ai, bool is_elem = true) {
     out.StartArray(is_elem);
     out.Element(ai.x);
     out.Element(ai.y);
@@ -249,7 +248,7 @@ void Write(JSONWriter &out, const aiVector3D &ai, bool is_elem = true) {
     out.EndArray();
 }
 
-void Write(JSONWriter &out, const aiQuaternion &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiQuaternion &ai, bool is_elem = true) {
     out.StartArray(is_elem);
     out.Element(ai.w);
     out.Element(ai.x);
@@ -258,7 +257,7 @@ void Write(JSONWriter &out, const aiQuaternion &ai, bool is_elem = true) {
     out.EndArray();
 }
 
-void Write(JSONWriter &out, const aiColor3D &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiColor3D &ai, bool is_elem = true) {
     out.StartArray(is_elem);
     out.Element(ai.r);
     out.Element(ai.g);
@@ -266,7 +265,7 @@ void Write(JSONWriter &out, const aiColor3D &ai, bool is_elem = true) {
     out.EndArray();
 }
 
-void Write(JSONWriter &out, const aiMatrix4x4 &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiMatrix4x4 &ai, bool is_elem = true) {
     out.StartArray(is_elem);
     for (unsigned int x = 0; x < 4; ++x) {
         for (unsigned int y = 0; y < 4; ++y) {
@@ -276,7 +275,7 @@ void Write(JSONWriter &out, const aiMatrix4x4 &ai, bool is_elem = true) {
     out.EndArray();
 }
 
-void Write(JSONWriter &out, const aiBone &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiBone &ai, bool is_elem = true) {
     out.StartObj(is_elem);
 
     out.Key("name");
@@ -297,7 +296,7 @@ void Write(JSONWriter &out, const aiBone &ai, bool is_elem = true) {
     out.EndObj();
 }
 
-void Write(JSONWriter &out, const aiFace &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiFace &ai, bool is_elem = true) {
     out.StartArray(is_elem);
     for (unsigned int i = 0; i < ai.mNumIndices; ++i) {
         out.Element(ai.mIndices[i]);
@@ -305,7 +304,7 @@ void Write(JSONWriter &out, const aiFace &ai, bool is_elem = true) {
     out.EndArray();
 }
 
-void Write(JSONWriter &out, const aiMesh &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiMesh &ai, bool is_elem = true) {
     out.StartObj(is_elem);
 
     out.Key("name");
@@ -416,7 +415,7 @@ void Write(JSONWriter &out, const aiMesh &ai, bool is_elem = true) {
     out.EndObj();
 }
 
-void Write(JSONWriter &out, const aiNode &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiNode &ai, bool is_elem = true) {
     out.StartObj(is_elem);
 
     out.Key("name");
@@ -446,7 +445,7 @@ void Write(JSONWriter &out, const aiNode &ai, bool is_elem = true) {
     out.EndObj();
 }
 
-void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
     out.StartObj(is_elem);
 
     out.Key("properties");
@@ -466,41 +465,55 @@ void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
 
         out.Key("value");
         switch (prop->mType) {
-        case aiPTI_Float:
-            if (prop->mDataLength / sizeof(float) > 1) {
-                out.StartArray();
-                for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(float); ++ii) {
-                    out.Element(reinterpret_cast<float *>(prop->mData)[ii]);
+            case aiPTI_Float:
+                if (prop->mDataLength / sizeof(float) > 1) {
+                    out.StartArray();
+                    for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(float); ++ii) {
+                        out.Element(reinterpret_cast<float *>(prop->mData)[ii]);
+                    }
+                    out.EndArray();
+                } else {
+                    out.SimpleValue(*reinterpret_cast<float *>(prop->mData));
                 }
-                out.EndArray();
-            } else {
-                out.SimpleValue(*reinterpret_cast<float *>(prop->mData));
-            }
-            break;
-
-        case aiPTI_Integer:
-            if (prop->mDataLength / sizeof(int) > 1) {
-                out.StartArray();
-                for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(int); ++ii) {
-                    out.Element(reinterpret_cast<int *>(prop->mData)[ii]);
+                break;
+            case aiPTI_Double:
+                if (prop->mDataLength / sizeof(double) > 1) {
+                    out.StartArray();
+                    for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(double); ++ii) {
+                        out.Element(reinterpret_cast<double*>(prop->mData)[ii]);
+                    }
+                    out.EndArray();
+                } else {
+                    out.SimpleValue(*reinterpret_cast<double*>(prop->mData));
                 }
-                out.EndArray();
-            } else {
-                out.SimpleValue(*reinterpret_cast<int *>(prop->mData));
-            }
-            break;
+                break;
+            case aiPTI_Integer:
+                if (prop->mDataLength / sizeof(int) > 1) {
+                    out.StartArray();
+                    for (unsigned int ii = 0; ii < prop->mDataLength / sizeof(int); ++ii) {
+                        out.Element(reinterpret_cast<int *>(prop->mData)[ii]);
+                    }
+                    out.EndArray();
+                } else {
+                    out.SimpleValue(*reinterpret_cast<int *>(prop->mData));
+                }
+                break;
 
-        case aiPTI_String: {
-            aiString s;
-            aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
-            out.SimpleValue(s);
-        } break;
-        case aiPTI_Buffer: {
-            // binary data is written as series of hex-encoded octets
-            out.SimpleValue(prop->mData, prop->mDataLength);
-        } break;
-        default:
-            assert(false);
+            case aiPTI_String:
+                {
+                    aiString s;
+                    aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
+                    out.SimpleValue(s);
+                }
+                break;
+            case aiPTI_Buffer:
+                {
+                    // binary data is written as series of hex-encoded octets
+                    out.SimpleValue(prop->mData, prop->mDataLength);
+                }
+                break;
+            default:
+                ai_assert(false);
         }
 
         out.EndObj();
@@ -510,7 +523,7 @@ void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
     out.EndObj();
 }
 
-void Write(JSONWriter &out, const aiTexture &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiTexture &ai, bool is_elem = true) {
     out.StartObj(is_elem);
 
     out.Key("width");
@@ -546,7 +559,7 @@ void Write(JSONWriter &out, const aiTexture &ai, bool is_elem = true) {
     out.EndObj();
 }
 
-void Write(JSONWriter &out, const aiLight &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiLight &ai, bool is_elem = true) {
     out.StartObj(is_elem);
 
     out.Key("name");
@@ -594,7 +607,7 @@ void Write(JSONWriter &out, const aiLight &ai, bool is_elem = true) {
     out.EndObj();
 }
 
-void Write(JSONWriter &out, const aiNodeAnim &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiNodeAnim &ai, bool is_elem = true) {
     out.StartObj(is_elem);
 
     out.Key("name");
@@ -647,7 +660,7 @@ void Write(JSONWriter &out, const aiNodeAnim &ai, bool is_elem = true) {
     out.EndObj();
 }
 
-void Write(JSONWriter &out, const aiAnimation &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiAnimation &ai, bool is_elem = true) {
     out.StartObj(is_elem);
 
     out.Key("name");
@@ -668,7 +681,7 @@ void Write(JSONWriter &out, const aiAnimation &ai, bool is_elem = true) {
     out.EndObj();
 }
 
-void Write(JSONWriter &out, const aiCamera &ai, bool is_elem = true) {
+static void Write(JSONWriter &out, const aiCamera &ai, bool is_elem = true) {
     out.StartObj(is_elem);
 
     out.Key("name");
@@ -695,7 +708,7 @@ void Write(JSONWriter &out, const aiCamera &ai, bool is_elem = true) {
     out.EndObj();
 }
 
-void WriteFormatInfo(JSONWriter &out) {
+static void WriteFormatInfo(JSONWriter &out) {
     out.StartObj();
     out.Key("format");
     out.SimpleValue("\"assimp2json\"");
@@ -704,7 +717,7 @@ void WriteFormatInfo(JSONWriter &out) {
     out.EndObj();
 }
 
-void Write(JSONWriter &out, const aiScene &ai) {
+static void Write(JSONWriter &out, const aiScene &ai) {
     out.StartObj();
 
     out.Key("__metadata__");

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Assxml/AssxmlExporter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Assxml/AssxmlExporter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.

+ 2 - 2
Engine/lib/assimp/code/AssetLib/Assxml/AssxmlFileWriter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -652,7 +652,7 @@ void DumpSceneToAssxml(
         const char *pFile, const char *cmd, IOSystem *pIOSystem,
         const aiScene *pScene, bool shortened) {
     std::unique_ptr<IOStream> file(pIOSystem->Open(pFile, "wt"));
-    if (!file.get()) {
+    if (!file) {
         throw std::runtime_error("Unable to open output file " + std::string(pFile) + '\n');
     }
 

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Assxml/AssxmlFileWriter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 19 - 18
Engine/lib/assimp/code/AssetLib/B3D/B3DImporter.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -59,10 +59,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 using namespace std;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "BlitzBasic 3D Importer",
     "",
     "",
@@ -79,9 +79,9 @@ static const aiImporterDesc desc = {
 #pragma warning(disable : 4018)
 #endif
 
-//#define DEBUG_B3D
+// #define DEBUG_B3D
 
-template<typename T>
+template <typename T>
 void DeleteAllBarePointers(std::vector<T> &x) {
     for (auto p : x) {
         delete p;
@@ -116,7 +116,7 @@ void B3DImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
 
     // Check whether we can read from the file
-    if (file.get() == nullptr) {
+    if (file == nullptr) {
         throw DeadlyImportError("Failed to open B3D file ", pFile, ".");
     }
 
@@ -150,7 +150,7 @@ AI_WONT_RETURN void B3DImporter::Fail(const string &str) {
 
 // ------------------------------------------------------------------------------------------------
 int B3DImporter::ReadByte() {
-    if (_pos > _buf.size()) {
+    if (_pos >= _buf.size()) {
         Fail("EOF");
     }
 
@@ -253,7 +253,7 @@ size_t B3DImporter::ChunkSize() {
 template <class T>
 T *B3DImporter::to_array(const vector<T> &v) {
     if (v.empty()) {
-        return 0;
+        return nullptr;
     }
     T *p = new T[v.size()];
     for (size_t i = 0; i < v.size(); ++i) {
@@ -266,7 +266,7 @@ T *B3DImporter::to_array(const vector<T> &v) {
 template <class T>
 T **unique_to_array(vector<std::unique_ptr<T>> &v) {
     if (v.empty()) {
-        return 0;
+        return nullptr;
     }
     T **p = new T *[v.size()];
     for (size_t i = 0; i < v.size(); ++i) {
@@ -329,7 +329,7 @@ void B3DImporter::ReadBRUS() {
             mat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED);
         }
 
-        //Textures
+        // Textures
         for (int i = 0; i < n_texs; ++i) {
             int texid = ReadInt();
             if (texid < -1 || (texid >= 0 && texid >= static_cast<int>(_textures.size()))) {
@@ -372,7 +372,7 @@ void B3DImporter::ReadVRTS() {
         }
 
         if (_vflags & 2) {
-            ReadQuat(); //skip v 4bytes...
+            ReadQuat(); // skip v 4bytes...
         }
 
         for (int j = 0; j < _tcsets; ++j) {
@@ -418,7 +418,6 @@ void B3DImporter::ReadTRIS(int v0) {
             ASSIMP_LOG_ERROR("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2);
 #endif
             Fail("Bad triangle index");
-            continue;
         }
         face->mNumIndices = 3;
         face->mIndices = new unsigned[3];
@@ -617,7 +616,7 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
             } else if (chunk == "BRUS") {
                 ReadBRUS();
             } else if (chunk == "NODE") {
-                ReadNODE(0);
+                ReadNODE(nullptr);
             }
             ExitChunk();
         }
@@ -642,7 +641,7 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
             int n_tris = mesh->mNumFaces;
             int n_verts = mesh->mNumVertices = n_tris * 3;
 
-            aiVector3D *mv = mesh->mVertices = new aiVector3D[n_verts], *mn = 0, *mc = 0;
+            aiVector3D *mv = mesh->mVertices = new aiVector3D[n_verts], *mn = nullptr, *mc = nullptr;
             if (_vflags & 1) {
                 mn = mesh->mNormals = new aiVector3D[n_verts];
             }
@@ -705,22 +704,22 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
         }
     }
 
-    //nodes
+    // nodes
     scene->mRootNode = _nodes[0];
     _nodes.clear(); // node ownership now belongs to scene
 
-    //material
+    // material
     if (!_materials.size()) {
         _materials.emplace_back(std::unique_ptr<aiMaterial>(new aiMaterial));
     }
     scene->mNumMaterials = static_cast<unsigned int>(_materials.size());
     scene->mMaterials = unique_to_array(_materials);
 
-    //meshes
+    // meshes
     scene->mNumMeshes = static_cast<unsigned int>(_meshes.size());
     scene->mMeshes = unique_to_array(_meshes);
 
-    //animations
+    // animations
     if (_animations.size() == 1 && _nodeAnims.size()) {
 
         aiAnimation *anim = _animations.back().get();
@@ -739,4 +738,6 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
     flip.Execute(scene);
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER

+ 1 - 1
Engine/lib/assimp/code/AssetLib/B3D/B3DImporter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 29 - 29
Engine/lib/assimp/code/AssetLib/BVH/BVHLoader.cpp

@@ -4,7 +4,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 
@@ -55,10 +55,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <map>
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
+
 using namespace Assimp::Formatter;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "BVH Importer (MoCap)",
     "",
     "",
@@ -73,8 +74,8 @@ static const aiImporterDesc desc = {
 
 // ------------------------------------------------------------------------------------------------
 // Aborts the file reading with an exception
-template<typename... T>
-AI_WONT_RETURN void BVHLoader::ThrowException(T&&... args) {
+template <typename... T>
+AI_WONT_RETURN void BVHLoader::ThrowException(T &&...args) {
     throw DeadlyImportError(mFileName, ":", mLine, " - ", args...);
 }
 
@@ -115,7 +116,7 @@ void BVHLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IOSyst
 
     // read file into memory
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
-    if (file.get() == nullptr) {
+    if (file == nullptr) {
         throw DeadlyImportError("Failed to open file ", pFile, ".");
     }
 
@@ -191,7 +192,7 @@ aiNode *BVHLoader::ReadNode() {
 
     // now read the node's contents
     std::string siteToken;
-    while (1) {
+    while (true) {
         std::string token = GetNextToken();
 
         // node offset to parent node
@@ -247,7 +248,7 @@ aiNode *BVHLoader::ReadEndSite(const std::string &pParentName) {
 
     // now read the node's contents. Only possible entry is "OFFSET"
     std::string token;
-    while (1) {
+    while (true) {
         token.clear();
         token = GetNextToken();
 
@@ -426,7 +427,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
         nodeAnim->mNodeName.Set(nodeName);
         std::map<BVHLoader::ChannelType, int> channelMap;
 
-        //Build map of channels
+        // Build map of channels
         for (unsigned int channel = 0; channel < node.mChannels.size(); ++channel) {
             channelMap[node.mChannels[channel]] = channel;
         }
@@ -441,7 +442,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
 
                 // Now compute all translations
                 for (BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel + 1)) {
-                    //Find channel in node
+                    // Find channel in node
                     std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
 
                     if (mapIter == channelMap.end())
@@ -485,30 +486,27 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
             for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) {
                 aiMatrix4x4 temp;
                 aiMatrix3x3 rotMatrix;
-				for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++ channelIdx) {
-					switch (node.mChannels[channelIdx]) {
-                    case Channel_RotationX:
-                        {
+                for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++channelIdx) {
+                    switch (node.mChannels[channelIdx]) {
+                    case Channel_RotationX: {
                         const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
-                        aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp);
-                        }
-                        break;
-                    case Channel_RotationY:
-                        {
+                        aiMatrix4x4::RotationX(angle, temp);
+                        rotMatrix *= aiMatrix3x3(temp);
+                    } break;
+                    case Channel_RotationY: {
                         const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
-                        aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp);
-                        }
-                        break;
-                    case Channel_RotationZ:
-                        {
+                        aiMatrix4x4::RotationY(angle, temp);
+                        rotMatrix *= aiMatrix3x3(temp);
+                    } break;
+                    case Channel_RotationZ: {
                         const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
-                        aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp);
-                        }
-                        break;
+                        aiMatrix4x4::RotationZ(angle, temp);
+                        rotMatrix *= aiMatrix3x3(temp);
+                    } break;
                     default:
                         break;
-					}
-				}
+                    }
+                }
                 rotkey->mTime = double(fr);
                 rotkey->mValue = aiQuaternion(rotMatrix);
                 ++rotkey;
@@ -525,4 +523,6 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
     }
 }
 
+} // namespace Assimp
+
 #endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER

+ 1 - 1
Engine/lib/assimp/code/AssetLib/BVH/BVHLoader.h

@@ -4,7 +4,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.

+ 3 - 4
Engine/lib/assimp/code/AssetLib/Blender/BlenderBMesh.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -52,8 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 template <>
 const char *LogFunctions<BlenderBMeshConverter>::Prefix() {
-    static auto prefix = "BLEND_BMESH: ";
-    return prefix;
+    return "BLEND_BMESH: ";
 }
 } // namespace Assimp
 
@@ -140,7 +139,7 @@ void BlenderBMeshConverter::ConvertPolyToFaces(const MPoly &poly) {
                 ThrowException("BMesh uv loop array has incorrect size");
             }
             const MLoopUV *loopUV = &BMesh->mloopuv[poly.loopstart];
-            AddTFace(loopUV[0].uv, loopUV[1].uv, loopUV[2].uv, poly.totloop == 4 ? loopUV[3].uv : 0);
+            AddTFace(loopUV[0].uv, loopUV[1].uv, loopUV[2].uv, poly.totloop == 4 ? loopUV[3].uv : nullptr);
         }
     } else if (poly.totloop > 4) {
 #if ASSIMP_BLEND_WITH_GLU_TESSELLATE

+ 2 - 2
Engine/lib/assimp/code/AssetLib/Blender/BlenderBMesh.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -80,7 +80,7 @@ namespace Assimp
         void DestroyTriMesh( );
         void ConvertPolyToFaces( const Blender::MPoly& poly );
         void AddFace( int v1, int v2, int v3, int v4 = 0 );
-        void AddTFace( const float* uv1, const float* uv2, const float *uv3, const float* uv4 = 0 );
+        void AddTFace(const float *uv1, const float *uv2, const float *uv3, const float *uv4 = nullptr);
 
         const Blender::Mesh* BMesh;
         Blender::Mesh* triMesh;

+ 2 - 1
Engine/lib/assimp/code/AssetLib/Blender/BlenderCustomData.cpp

@@ -96,7 +96,8 @@ struct CustomDataTypeDescription {
         *           other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
         *           use a special readfunction for that cases
         */
-std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { { DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
+static std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
+        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
         DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
         DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
         DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),

+ 2 - 2
Engine/lib/assimp/code/AssetLib/Blender/BlenderDNA.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -72,7 +72,7 @@ struct Type {
 
 // ------------------------------------------------------------------------------------------------
 void DNAParser::Parse() {
-    StreamReaderAny &stream = *db.reader.get();
+    StreamReaderAny &stream = *db.reader;
     DNA &dna = db.dna;
 
     if (!match4(stream, "SDNA")) {

+ 13 - 4
Engine/lib/assimp/code/AssetLib/Blender/BlenderDNA.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -106,9 +106,7 @@ struct ElemBase {
         // empty
     }
 
-    virtual ~ElemBase() {
-        // empty
-    }
+    virtual ~ElemBase() = default;
 
     /** Type name of the element. The type
      * string points is the `c_str` of the `name` attribute of the
@@ -431,6 +429,17 @@ inline bool Structure ::ResolvePointer<std::shared_ptr, ElemBase>(std::shared_pt
         const Field &f,
         bool) const;
 
+template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(
+    std::shared_ptr<ElemBase>& out, const Pointer & ptrval,
+    const FileDatabase& db, const Field&, bool) const;
+template <> inline void Structure :: Convert<int>    (int& dest,const FileDatabase& db) const;
+template<> inline void Structure :: Convert<short>  (short& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<char>   (char& dest,const FileDatabase& db) const;
+template <> inline void Structure::Convert<unsigned char>(unsigned char& dest, const FileDatabase& db) const;
+template <> inline void Structure :: Convert<float>  (float& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<double> (double& dest,const FileDatabase& db) const;
+template <> inline void Structure :: Convert<Pointer> (Pointer& dest,const FileDatabase& db) const;
+
 // -------------------------------------------------------------------------------
 /** Represents the full data structure information for a single BLEND file.
  *  This data is extracted from the DNA1 chunk in the file.

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Blender/BlenderDNA.inl

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Blender/BlenderIntermediate.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.

+ 75 - 74
Engine/lib/assimp/code/AssetLib/Blender/BlenderLoader.cpp

@@ -1,10 +1,8 @@
-
 /*
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
-
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -63,23 +61,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/StringComparison.h>
 
 #include <cctype>
+#include <memory>
+#include <utility>
 
 // zlib is needed for compressed blend files
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
 #include "Common/Compression.h"
-/* #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
-#    include <zlib.h>
-#  else
-#    include "../contrib/zlib/zlib.h"
-#  endif*/
 #endif
 
 namespace Assimp {
 
 template <>
 const char *LogFunctions<BlenderImporter>::Prefix() {
-    static auto prefix = "BLEND: ";
-    return prefix;
+    return "BLEND: ";
 }
 
 } // namespace Assimp
@@ -88,7 +82,7 @@ using namespace Assimp;
 using namespace Assimp::Blender;
 using namespace Assimp::Formatter;
 
-static const aiImporterDesc blenderDesc = {
+static constexpr aiImporterDesc blenderDesc = {
     "Blender 3D Importer (http://www.blender3d.org)",
     "",
     "",
@@ -114,15 +108,12 @@ BlenderImporter::~BlenderImporter() {
     delete modifier_cache;
 }
 
-static const char * const Tokens[] = { "BLENDER" };
+static const char Token[] = "BLENDER";
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
-    // note: this won't catch compressed files
-    static const char *tokens[] = { "<BLENDER", "blender" };
-
-    return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
+    return ParseMagicToken(pFile, pIOHandler).error.empty();
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -141,67 +132,25 @@ void BlenderImporter::SetupProperties(const Importer * /*pImp*/) {
 // Imports the given file into the given scene structure.
 void BlenderImporter::InternReadFile(const std::string &pFile,
         aiScene *pScene, IOSystem *pIOHandler) {
-#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
-    std::vector<char> uncompressed;
-#endif
-
     FileDatabase file;
-    std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
-    if (!stream) {
-        ThrowException("Could not open file for reading");
-    }
-
-    char magic[8] = { 0 };
-    stream->Read(magic, 7, 1);
-    if (strcmp(magic, Tokens[0])) {
-        // Check for presence of the gzip header. If yes, assume it is a
-        // compressed blend file and try uncompressing it, else fail. This is to
-        // avoid uncompressing random files which our loader might end up with.
-#ifdef ASSIMP_BUILD_NO_COMPRESSED_BLEND
-        ThrowException("BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?");
-#else
-        if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) {
-            ThrowException("BLENDER magic bytes are missing, couldn't find GZIP header either");
-        }
-
-        LogDebug("Found no BLENDER magic word but a GZIP header, might be a compressed file");
-        if (magic[2] != 8) {
-            ThrowException("Unsupported GZIP compression method");
-        }
-
-        // http://www.gzip.org/zlib/rfc-gzip.html#header-trailer
-        stream->Seek(0L, aiOrigin_SET);
-        std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
-
-        size_t total = 0;
-        Compression compression;
-        if (compression.open(Compression::Format::Binary, Compression::FlushMode::NoFlush, 16 + Compression::MaxWBits)) {
-            total = compression.decompress((unsigned char *)reader->GetPtr(), reader->GetRemainingSize(), uncompressed);
-            compression.close();
-        }
-
-        // replace the input stream with a memory stream
-        stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t *>(uncompressed.data()), total));
-
-        // .. and retry
-        stream->Read(magic, 7, 1);
-        if (strcmp(magic, "BLENDER")) {
-            ThrowException("Found no BLENDER magic word in decompressed GZIP file");
-        }
-#endif
+    StreamOrError streamOrError = ParseMagicToken(pFile, pIOHandler);
+    if (!streamOrError.error.empty()) {
+        ThrowException(streamOrError.error);
     }
+    std::shared_ptr<IOStream> stream = std::move(streamOrError.stream);
 
-    file.i64bit = (stream->Read(magic, 1, 1), magic[0] == '-');
-    file.little = (stream->Read(magic, 1, 1), magic[0] == 'v');
+    char version[4] = { 0 };
+    file.i64bit = (stream->Read(version, 1, 1), version[0] == '-');
+    file.little = (stream->Read(version, 1, 1), version[0] == 'v');
 
-    stream->Read(magic, 3, 1);
-    magic[3] = '\0';
+    stream->Read(version, 3, 1);
+    version[3] = '\0';
 
-    LogInfo("Blender version is ", magic[0], ".", magic + 1,
+    LogInfo("Blender version is ", version[0], ".", version + 1,
             " (64bit: ", file.i64bit ? "true" : "false",
             ", little endian: ", file.little ? "true" : "false", ")");
 
-    ParseBlendFile(file, stream);
+    ParseBlendFile(file, std::move(stream));
 
     Scene scene;
     ExtractScene(scene, file);
@@ -218,7 +167,7 @@ void BlenderImporter::ParseBlendFile(FileDatabase &out, std::shared_ptr<IOStream
 
     out.entries.reserve(128);
     { // even small BLEND files tend to consist of many file blocks
-        SectionParser parser(*out.reader.get(), out.i64bit);
+        SectionParser parser(*out.reader, out.i64bit);
 
         // first parse the file in search for the DNA and insert all other sections into the database
         while ((parser.Next(), 1)) {
@@ -408,7 +357,7 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M
     // check if the file contents are bundled with the BLEND file
     if (img->packedfile) {
         name.data[0] = '*';
-        name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(MAXLEN - 1), static_cast<int32_t>(conv_data.textures->size()));
+        name.length = 1 + ASSIMP_itoa10(name.data + 1, static_cast<unsigned int>(AI_MAXLEN - 1), static_cast<int32_t>(conv_data.textures->size()));
 
         conv_data.textures->push_back(new aiTexture());
         aiTexture *curTex = conv_data.textures->back();
@@ -482,7 +431,7 @@ void BlenderImporter::AddSentinelTexture(aiMaterial *out, const Material *mat, c
     (void)conv_data;
 
     aiString name;
-    name.length = ai_snprintf(name.data, MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++,
+    name.length = ai_snprintf(name.data, AI_MAXLEN, "Procedural,num=%i,type=%s", conv_data.sentinel_cnt++,
             GetTextureTypeDisplayString(tex->tex->type));
     out->AddProperty(&name, AI_MATKEY_TEXTURE_DIFFUSE(
                                     conv_data.next_texture[aiTextureType_DIFFUSE]++));
@@ -544,8 +493,9 @@ void BlenderImporter::BuildDefaultMaterial(Blender::ConversionData &conv_data) {
             if (index == static_cast<unsigned int>(-1)) {
                 // Setup a default material.
                 std::shared_ptr<Material> p(new Material());
-                ai_assert(::strlen(AI_DEFAULT_MATERIAL_NAME) < sizeof(p->id.name) - 2);
-                strcpy(p->id.name + 2, AI_DEFAULT_MATERIAL_NAME);
+                const size_t len = ::strlen(AI_DEFAULT_MATERIAL_NAME);
+                ai_assert(len < sizeof(p->id.name) - 2);
+                memcpy(p->id.name + 2, AI_DEFAULT_MATERIAL_NAME, len);
 
                 // Note: MSVC11 does not zero-initialize Material here, although it should.
                 // Thus all relevant fields should be explicitly initialized. We cannot add
@@ -1337,4 +1287,55 @@ aiNode *BlenderImporter::ConvertNode(const Scene &in, const Object *obj, Convers
     return node.release();
 }
 
+BlenderImporter::StreamOrError BlenderImporter::ParseMagicToken(const std::string &pFile, IOSystem *pIOHandler) const {
+    std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
+    if (stream == nullptr) {
+        return {{}, {}, "Could not open file for reading"};
+    }
+
+    char magic[8] = { 0 };
+    stream->Read(magic, 7, 1);
+    if (strcmp(magic, Token) == 0) {
+        return {stream, {}, {}};
+    }
+
+    // Check for presence of the gzip header. If yes, assume it is a
+    // compressed blend file and try uncompressing it, else fail. This is to
+    // avoid uncompressing random files which our loader might end up with.
+#ifdef ASSIMP_BUILD_NO_COMPRESSED_BLEND
+    return {{}, {}, "BLENDER magic bytes are missing, is this file compressed (Assimp was built without decompression support)?"};
+#else
+    if (magic[0] != 0x1f || static_cast<uint8_t>(magic[1]) != 0x8b) {
+        return {{}, {}, "BLENDER magic bytes are missing, couldn't find GZIP header either"};
+    }
+
+    LogDebug("Found no BLENDER magic word but a GZIP header, might be a compressed file");
+    if (magic[2] != 8) {
+        return {{}, {}, "Unsupported GZIP compression method"};
+    }
+
+    // http://www.gzip.org/zlib/rfc-gzip.html#header-trailer
+    stream->Seek(0L, aiOrigin_SET);
+    std::shared_ptr<StreamReaderLE> reader = std::shared_ptr<StreamReaderLE>(new StreamReaderLE(stream));
+
+    size_t total = 0;
+    Compression compression;
+    auto uncompressed = std::make_shared<std::vector<char>>();
+    if (compression.open(Compression::Format::Binary, Compression::FlushMode::NoFlush, 16 + Compression::MaxWBits)) {
+        total = compression.decompress((unsigned char *)reader->GetPtr(), reader->GetRemainingSize(), *uncompressed);
+        compression.close();
+    }
+
+    // replace the input stream with a memory stream
+    stream = std::make_shared<MemoryIOStream>(reinterpret_cast<uint8_t *>(uncompressed->data()), total);
+
+    // .. and retry
+    stream->Read(magic, 7, 1);
+    if (strcmp(magic, Token) == 0) {
+        return {stream, uncompressed, {}};
+    }
+    return {{}, {}, "Found no BLENDER magic word in decompressed GZIP file"};
+#endif
+}
+
 #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

+ 14 - 1
Engine/lib/assimp/code/AssetLib/Blender/BlenderLoader.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -180,6 +180,19 @@ private:
             const Blender::MTex *tex,
             Blender::ConversionData &conv_data);
 
+    // TODO: Move to a std::variant, once c++17 is supported.
+    struct StreamOrError {
+        std::shared_ptr<IOStream> stream;
+        std::shared_ptr<std::vector<char>> input;
+        std::string error;
+    };
+
+    // Returns either a stream (and optional input data for the stream) or
+    // an error if it can't parse the magic token.
+    StreamOrError ParseMagicToken(
+            const std::string &pFile,
+            IOSystem *pIOHandler) const;
+
 private: // static stuff, mostly logging and error reporting.
     // --------------------
     static void CheckActualType(const Blender::ElemBase *dt,

+ 6 - 1
Engine/lib/assimp/code/AssetLib/Blender/BlenderModifier.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -283,6 +283,11 @@ void BlenderModifier_Subdivision ::DoIt(aiNode &out, ConversionData &conv_data,
     if (conv_data.meshes->empty()) {
         return;
     }
+    const size_t meshIndex = conv_data.meshes->size() - out.mNumMeshes;
+    if (meshIndex >= conv_data.meshes->size()) {
+        ASSIMP_LOG_ERROR("Invalid index detected.");
+        return;
+    }
     aiMesh **const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
     std::unique_ptr<aiMesh *[]> tempmeshes(new aiMesh *[out.mNumMeshes]());
 

+ 2 - 4
Engine/lib/assimp/code/AssetLib/Blender/BlenderModifier.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -62,9 +62,7 @@ public:
     /**
      *  The class destructor, virtual.
      */
-    virtual ~BlenderModifier() {
-        // empty
-    }
+    virtual ~BlenderModifier() = default;
 
     // --------------------
     /**

+ 2 - 6
Engine/lib/assimp/code/AssetLib/Blender/BlenderScene.cpp

@@ -102,10 +102,6 @@ void Structure::Convert<CollectionObject>(
 
     ReadFieldPtr<ErrorPolicy_Fail>(dest.next, "*next", db);
     {
-        //std::shared_ptr<CollectionObject> prev;
-        //ReadFieldPtr<ErrorPolicy_Fail>(prev, "*prev", db);
-        //dest.prev = prev.get();
-
         std::shared_ptr<Object> ob;
         ReadFieldPtr<ErrorPolicy_Igno>(ob, "*ob", db);
         dest.ob = ob.get();
@@ -301,7 +297,7 @@ void Structure ::Convert<Base>(
         const FileDatabase &db) const {
     // note: as per https://github.com/assimp/assimp/issues/128,
     // reading the Object linked list recursively is prone to stack overflow.
-    // This structure converter is therefore an hand-written exception that
+    // This structure converter is therefore a hand-written exception that
     // does it iteratively.
 
     const int initial_pos = db.reader->GetCurrentPos();
@@ -569,7 +565,7 @@ void Structure ::Convert<MVert>(
         const FileDatabase &db) const {
 
     ReadFieldArray<ErrorPolicy_Fail>(dest.co, "co", db);
-    ReadFieldArray<ErrorPolicy_Fail>(dest.no, "no", db);
+    ReadFieldArray<ErrorPolicy_Warn>(dest.no, "no", db);
     ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
     //ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
     ReadField<ErrorPolicy_Igno>(dest.bweight, "bweight", db);

+ 8 - 19
Engine/lib/assimp/code/AssetLib/Blender/BlenderScene.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -182,7 +182,7 @@ struct MVert : ElemBase {
     int bweight;
 
     MVert() :
-            ElemBase(), flag(0), mat_nr(0), bweight(0) {}
+            flag(0), mat_nr(0), bweight(0) {}
 };
 
 // -------------------------------------------------------------------------------
@@ -417,7 +417,6 @@ struct CustomDataLayer : ElemBase {
     std::shared_ptr<ElemBase> data; // must be converted to real type according type member
 
     CustomDataLayer() :
-            ElemBase(),
             type(0),
             offset(0),
             flag(0),
@@ -729,7 +728,7 @@ struct Object : ElemBase {
     ListBase modifiers;
 
     Object() :
-            ElemBase(), type(Type_EMPTY), parent(nullptr), track(), proxy(), proxy_from(), data() {
+            type(Type_EMPTY), parent(nullptr) {
         // empty
     }
 };
@@ -741,8 +740,7 @@ struct Base : ElemBase {
     std::shared_ptr<Object> object WARN;
 
     Base() :
-            ElemBase(), prev(nullptr), next(), object() {
-        // empty
+            prev(nullptr) {
         // empty
     }
 };
@@ -758,10 +756,7 @@ struct Scene : ElemBase {
 
     ListBase base;
 
-    Scene() :
-            ElemBase(), camera(), world(), basact(), master_collection() {
-        // empty
-    }
+    Scene() = default;
 };
 
 // -------------------------------------------------------------------------------
@@ -791,10 +786,7 @@ struct Image : ElemBase {
 
     short gen_x, gen_y, gen_type;
 
-    Image() :
-            ElemBase() {
-        // empty
-    }
+    Image() = default;
 };
 
 // -------------------------------------------------------------------------------
@@ -884,7 +876,7 @@ struct Tex : ElemBase {
     //char use_nodes;
 
     Tex() :
-            ElemBase(), imaflag(ImageFlags_INTERPOL), type(Type_CLOUDS), ima() {
+            imaflag(ImageFlags_INTERPOL), type(Type_CLOUDS) {
         // empty
     }
 };
@@ -976,10 +968,7 @@ struct MTex : ElemBase {
     //float shadowfac;
     //float zenupfac, zendownfac, blendfac;
 
-    MTex() :
-            ElemBase() {
-        // empty
-    }
+    MTex() = default;
 };
 
 } // namespace Blender

+ 6 - 13
Engine/lib/assimp/code/AssetLib/Blender/BlenderTessellator.cpp

@@ -2,8 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
-
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -40,10 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
-/** @file  BlenderTessellator.cpp
- *  @brief A simple tessellation wrapper
- */
-
+/// @file  BlenderTessellator.cpp
+/// @brief A simple tessellation wrapper
 
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 
@@ -62,8 +59,7 @@ namspace Assimp
 {
     template< > const char* LogFunctions< BlenderTessellatorGL >::Prefix()
     {
-        static auto prefix = "BLEND_TESS_GL: ";
-        return prefix;
+        return "BLEND_TESS_GL: ";
     }
 }
 
@@ -81,9 +77,7 @@ BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ):
 }
 
 // ------------------------------------------------------------------------------------------------
-BlenderTessellatorGL::~BlenderTessellatorGL( )
-{
-}
+BlenderTessellatorGL::~BlenderTessellatorGL() = default;
 
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
@@ -259,8 +253,7 @@ namespace Assimp
 {
     template< > const char* LogFunctions< BlenderTessellatorP2T >::Prefix()
     {
-        static auto prefix = "BLEND_TESS_P2T: ";
-        return prefix;
+        return "BLEND_TESS_P2T: ";
     }
 }
 

+ 2 - 7
Engine/lib/assimp/code/AssetLib/Blender/BlenderTessellator.h

@@ -2,8 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
-
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -144,11 +143,7 @@ namespace Assimp
 
 #if ASSIMP_BLEND_WITH_POLY_2_TRI
 
-#ifdef ASSIMP_USE_HUNTER
-#  include <poly2tri/poly2tri.h>
-#else
-#  include "../contrib/poly2tri/poly2tri/poly2tri.h"
-#endif
+#include "contrib/poly2tri/poly2tri/poly2tri.h"
 
 namespace Assimp
 {

+ 11 - 21
Engine/lib/assimp/code/AssetLib/C4D/C4DImporter.cpp

@@ -46,10 +46,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // no #ifdefing here, Cinema4D support is carried out in a branch of assimp
 // where it is turned on in the CMake settings.
 
-#ifndef _MSC_VER
-#   error C4D support is currently MSVC only
-#endif
-
 #include "C4DImporter.h"
 #include <memory>
 #include <assimp/IOSystem.hpp>
@@ -86,8 +82,7 @@ void GetWriterInfo(int &id, String &appname) {
 
 namespace Assimp {
     template<> const char* LogFunctions<C4DImporter>::Prefix() {
-        static auto prefix = "C4D: ";
-        return prefix;
+        return "C4D: ";
     }
 }
 
@@ -106,25 +101,20 @@ static const aiImporterDesc desc = {
 
 
 // ------------------------------------------------------------------------------------------------
-C4DImporter::C4DImporter()
-: BaseImporter() {
-    // empty
-}
+C4DImporter::C4DImporter() = default;
 
 // ------------------------------------------------------------------------------------------------
-C4DImporter::~C4DImporter() {
-    // empty
-}
+C4DImporter::~C4DImporter() = default;
 
 // ------------------------------------------------------------------------------------------------
-bool C4DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const {
+bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
     const std::string& extension = GetExtension(pFile);
     if (extension == "c4d") {
         return true;
     } else if ((!extension.length() || checkSig) && pIOHandler)   {
         // TODO
     }
-    
+
     return false;
 }
 
@@ -311,7 +301,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
 
     // based on Cineware sample code
     while (object) {
-        const LONG type = object->GetType();
+        const Int32 type = object->GetType();
         const Matrix& ml = object->GetMl();
 
         aiNode* const nd = new aiNode();
@@ -374,8 +364,8 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
     PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
     ai_assert(polyObject != nullptr);
 
-    const LONG pointCount = polyObject->GetPointCount();
-    const LONG polyCount = polyObject->GetPolygonCount();
+    const Int32 pointCount = polyObject->GetPointCount();
+    const Int32 polyCount = polyObject->GetPolygonCount();
     if(!polyObject || !pointCount) {
         LogWarn("ignoring mesh with zero vertices or faces");
         return nullptr;
@@ -397,7 +387,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
     unsigned int vcount = 0;
 
     // first count vertices
-    for (LONG i = 0; i < polyCount; i++)
+    for (Int32 i = 0; i < polyCount; i++)
     {
         vcount += 3;
 
@@ -440,7 +430,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
     }
 
     // copy vertices and extra channels over and populate faces
-    for (LONG i = 0; i < polyCount; ++i, ++face) {
+    for (Int32 i = 0; i < polyCount; ++i, ++face) {
         ai_assert(polys[i].a < pointCount && polys[i].a >= 0);
         const Vector& pointA = points[polys[i].a];
         verts->x = pointA.x;
@@ -517,7 +507,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
         if (tangents_src) {
 
             for(unsigned int k = 0; k < face->mNumIndices; ++k) {
-                LONG l;
+                Int32 l;
                 switch(k) {
                 case 0:
                     l = polys[i].a;

+ 2 - 0
Engine/lib/assimp/code/AssetLib/C4D/C4DImporter.h

@@ -78,6 +78,8 @@ namespace Assimp  {
 // -------------------------------------------------------------------------------------------
 class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
 public:
+    C4DImporter();
+    ~C4DImporter() override;
     bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override;
 
 protected:

+ 39 - 39
Engine/lib/assimp/code/AssetLib/COB/COBLoader.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -61,11 +61,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <memory>
 
-using namespace Assimp;
+namespace Assimp {
 using namespace Assimp::COB;
 using namespace Assimp::Formatter;
 
-static const float units[] = {
+static constexpr float units[] = {
     1000.f,
     100.f,
     1.f,
@@ -76,7 +76,7 @@ static const float units[] = {
     1.f / 1609.344f
 };
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "TrueSpace Object Importer",
     "",
     "",
@@ -89,14 +89,6 @@ static const aiImporterDesc desc = {
     "cob scn"
 };
 
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-COBImporter::COBImporter() = default;
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-COBImporter::~COBImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool COBImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@@ -158,7 +150,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
     // sort faces by material indices
     for (std::shared_ptr<Node> &n : scene.nodes) {
         if (n->type == Node::TYPE_MESH) {
-            Mesh &mesh = (Mesh &)(*n.get());
+            Mesh &mesh = (Mesh &)(*n);
             for (Face &f : mesh.faces) {
                 mesh.temp_map[f.material].push_back(&f);
             }
@@ -168,7 +160,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
     // count meshes
     for (std::shared_ptr<Node> &n : scene.nodes) {
         if (n->type == Node::TYPE_MESH) {
-            Mesh &mesh = (Mesh &)(*n.get());
+            Mesh &mesh = (Mesh &)(*n);
             if (mesh.vertex_positions.size() && mesh.texture_coords.size()) {
                 pScene->mNumMeshes += static_cast<unsigned int>(mesh.temp_map.size());
             }
@@ -211,7 +203,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
         }
     }
 
-    pScene->mRootNode = BuildNodes(*root.get(), scene, pScene);
+    pScene->mRootNode = BuildNodes(*root, scene, pScene);
     //flip normals after import
     FlipWindingOrderProcess flip;
     flip.Execute(pScene);
@@ -380,9 +372,11 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
     }
 
     // add children recursively
-    nd->mChildren = new aiNode *[root.temp_children.size()]();
-    for (const Node *n : root.temp_children) {
-        (nd->mChildren[nd->mNumChildren++] = BuildNodes(*n, scin, fill))->mParent = nd;
+    if (!root.temp_children.empty()) {
+        nd->mChildren = new aiNode *[root.temp_children.size()]();
+        for (const Node *n : root.temp_children) {
+            (nd->mChildren[nd->mNumChildren++] = BuildNodes(*n, scin, fill))->mParent = nd;
+        }
     }
 
     return nd;
@@ -481,8 +475,9 @@ void COBImporter::ReadBasicNodeInfo_Ascii(Node &msh, LineSplitter &splitter, con
         } else if (splitter.match_start("Transform")) {
             for (unsigned int y = 0; y < 4 && ++splitter; ++y) {
                 const char *s = splitter->c_str();
+                const char *end = s + splitter->size();
                 for (unsigned int x = 0; x < 4; ++x) {
-                    SkipSpaces(&s);
+                    SkipSpaces(&s, end);
                     msh.transform[y][x] = fast_atof(&s);
                 }
             }
@@ -494,12 +489,12 @@ void COBImporter::ReadBasicNodeInfo_Ascii(Node &msh, LineSplitter &splitter, con
 
 // ------------------------------------------------------------------------------------------------
 template <typename T>
-void COBImporter::ReadFloat3Tuple_Ascii(T &fill, const char **in) {
+void COBImporter::ReadFloat3Tuple_Ascii(T &fill, const char **in, const char *end) {
     const char *rgb = *in;
     for (unsigned int i = 0; i < 3; ++i) {
-        SkipSpaces(&rgb);
+        SkipSpaces(&rgb, end);
         if (*rgb == ',') ++rgb;
-        SkipSpaces(&rgb);
+        SkipSpaces(&rgb, end);
 
         fill[i] = fast_atof(&rgb);
     }
@@ -546,7 +541,7 @@ void COBImporter::ReadMat1_Ascii(Scene &out, LineSplitter &splitter, const Chunk
     }
 
     const char *rgb = splitter[1];
-    ReadFloat3Tuple_Ascii(mat.rgb, &rgb);
+    ReadFloat3Tuple_Ascii(mat.rgb, &rgb, splitter.getEnd());
 
     ++splitter;
     if (!splitter.match_start("alpha ")) {
@@ -625,20 +620,21 @@ void COBImporter::ReadLght_Ascii(Scene &out, LineSplitter &splitter, const Chunk
     }
 
     const char *rgb = splitter[1];
-    ReadFloat3Tuple_Ascii(msh.color, &rgb);
+    const char *end = splitter.getEnd();
+    ReadFloat3Tuple_Ascii(msh.color, &rgb, end);
 
-    SkipSpaces(&rgb);
+    SkipSpaces(&rgb, end);
     if (strncmp(rgb, "cone angle", 10) != 0) {
         ASSIMP_LOG_WARN("Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id);
     }
-    SkipSpaces(rgb + 10, &rgb);
+    SkipSpaces(rgb + 10, &rgb, end);
     msh.angle = fast_atof(&rgb);
 
-    SkipSpaces(&rgb);
+    SkipSpaces(&rgb, end);
     if (strncmp(rgb, "inner angle", 11) != 0) {
         ASSIMP_LOG_WARN("Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
     }
-    SkipSpaces(rgb + 11, &rgb);
+    SkipSpaces(rgb + 11, &rgb, end);
     msh.inner_angle = fast_atof(&rgb);
 
     // skip the rest for we can't handle this kind of physically-based lighting information.
@@ -711,14 +707,14 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk
 
             for (unsigned int cur = 0; cur < cnt && ++splitter; ++cur) {
                 const char *s = splitter->c_str();
-
+                const char *end = splitter.getEnd();
                 aiVector3D &v = msh.vertex_positions[cur];
 
-                SkipSpaces(&s);
+                SkipSpaces(&s, end);
                 v.x = fast_atof(&s);
-                SkipSpaces(&s);
+                SkipSpaces(&s, end);
                 v.y = fast_atof(&s);
-                SkipSpaces(&s);
+                SkipSpaces(&s, end);
                 v.z = fast_atof(&s);
             }
         } else if (splitter.match_start("Texture Vertices")) {
@@ -727,12 +723,13 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk
 
             for (unsigned int cur = 0; cur < cnt && ++splitter; ++cur) {
                 const char *s = splitter->c_str();
+                const char *end = splitter.getEnd();
 
                 aiVector2D &v = msh.texture_coords[cur];
 
-                SkipSpaces(&s);
+                SkipSpaces(&s, end);
                 v.x = fast_atof(&s);
-                SkipSpaces(&s);
+                SkipSpaces(&s, end);
                 v.y = fast_atof(&s);
             }
         } else if (splitter.match_start("Faces")) {
@@ -757,8 +754,9 @@ void COBImporter::ReadPolH_Ascii(Scene &out, LineSplitter &splitter, const Chunk
                 face.material = strtoul10(splitter[6]);
 
                 const char *s = (++splitter)->c_str();
+                const char *end = splitter.getEnd();
                 for (size_t i = 0; i < face.indices.size(); ++i) {
-                    if (!SkipSpaces(&s)) {
+                    if (!SkipSpaces(&s, end)) {
                         ThrowException("Expected EOL token in Face entry");
                     }
                     if ('<' != *s++) {
@@ -868,7 +866,7 @@ void COBImporter::ReadBinaryFile(Scene &out, StreamReaderLE *reader) {
         return;
     }
 
-    while (1) {
+    while (true) {
         std::string type;
         type += reader->GetI1();
         type += reader->GetI1();
@@ -1054,7 +1052,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
     id[0] = reader.GetI1(), id[1] = reader.GetI1();
 
     if (id[0] == 'e' && id[1] == ':') {
-        mat.tex_env.reset(new Texture());
+        mat.tex_env = std::make_shared<Texture>();
 
         reader.GetI1();
         ReadString_Binary(mat.tex_env->path, reader);
@@ -1064,7 +1062,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
     }
 
     if (id[0] == 't' && id[1] == ':') {
-        mat.tex_color.reset(new Texture());
+        mat.tex_color = std::make_shared<Texture>();
 
         reader.GetI1();
         ReadString_Binary(mat.tex_color->path, reader);
@@ -1080,7 +1078,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const
     }
 
     if (id[0] == 'b' && id[1] == ':') {
-        mat.tex_bump.reset(new Texture());
+        mat.tex_bump = std::make_shared<Texture>();
 
         reader.GetI1();
         ReadString_Binary(mat.tex_bump->path, reader);
@@ -1172,4 +1170,6 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
     ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
 }
 
+}
+
 #endif // ASSIMP_BUILD_NO_COB_IMPORTER

+ 10 - 10
Engine/lib/assimp/code/AssetLib/COB/COBLoader.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -56,16 +56,16 @@ class LineSplitter;
 
 // TinyFormatter.h
 namespace Formatter {
-template <typename T, typename TR, typename A>
-class basic_formatter;
-typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format;
+    template <typename T, typename TR, typename A>
+    class basic_formatter;
+    typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format;
 } // namespace Formatter
 
 // COBScene.h
 namespace COB {
-struct ChunkInfo;
-struct Node;
-struct Scene;
+    struct ChunkInfo;
+    struct Node;
+    struct Scene;
 } // namespace COB
 
 // -------------------------------------------------------------------------------------------
@@ -75,8 +75,8 @@ struct Scene;
 // -------------------------------------------------------------------------------------------
 class COBImporter : public BaseImporter {
 public:
-    COBImporter();
-    ~COBImporter() override;
+    COBImporter() = default;
+    ~COBImporter() override = default;
 
     // --------------------
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
@@ -120,7 +120,7 @@ private:
     void ReadChunkInfo_Ascii(COB::ChunkInfo &out, const LineSplitter &splitter);
     void ReadBasicNodeInfo_Ascii(COB::Node &msh, LineSplitter &splitter, const COB::ChunkInfo &nfo);
     template <typename T>
-    void ReadFloat3Tuple_Ascii(T &fill, const char **in);
+    void ReadFloat3Tuple_Ascii(T &fill, const char **in, const char *end);
 
     void ReadPolH_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
     void ReadBitM_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);

+ 1 - 1
Engine/lib/assimp/code/AssetLib/COB/COBScene.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 48 - 54
Engine/lib/assimp/code/AssetLib/CSM/CSMLoader.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 
@@ -44,9 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  CSMLoader.cpp
  *  Implementation of the CSM importer class.
  */
-
-
-
 #ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
 
 #include "CSMLoader.h"
@@ -63,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "CharacterStudio Motion Importer (MoCap)",
     "",
     "",
@@ -79,33 +76,26 @@ static const aiImporterDesc desc = {
 
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
-CSMImporter::CSMImporter()
-: noSkeletonMesh()
-{}
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-CSMImporter::~CSMImporter() = default;
+CSMImporter::CSMImporter() : noSkeletonMesh(){
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
-bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const
-{
+bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const {
     static const char* tokens[] = {"$Filename"};
     return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens));
 }
 
 // ------------------------------------------------------------------------------------------------
 // Build a string of all file extensions supported
-const aiImporterDesc* CSMImporter::GetInfo () const
-{
+const aiImporterDesc* CSMImporter::GetInfo () const {
     return &desc;
 }
 
 // ------------------------------------------------------------------------------------------------
 // Setup configuration properties for the loader
-void CSMImporter::SetupProperties(const Importer* pImp)
-{
+void CSMImporter::SetupProperties(const Importer* pImp) {
     noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
 }
 
@@ -117,7 +107,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
     std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
 
     // Check whether we can read from the file
-    if( file.get() == nullptr) {
+    if (file == nullptr) {
         throw DeadlyImportError( "Failed to open CSM file ", pFile, ".");
     }
 
@@ -125,38 +115,38 @@ void CSMImporter::InternReadFile( const std::string& pFile,
     std::vector<char> mBuffer2;
     TextFileToBuffer(file.get(),mBuffer2);
     const char* buffer = &mBuffer2[0];
-
+    const char *end = &mBuffer2[mBuffer2.size() - 1] + 1;
     std::unique_ptr<aiAnimation> anim(new aiAnimation());
     int first = 0, last = 0x00ffffff;
 
     // now process the file and look out for '$' sections
-    while (1)   {
-        SkipSpaces(&buffer);
+    while (true) {
+        SkipSpaces(&buffer, end);
         if ('\0' == *buffer)
             break;
 
         if ('$'  == *buffer)    {
             ++buffer;
             if (TokenMatchI(buffer,"firstframe",10))    {
-                SkipSpaces(&buffer);
+                SkipSpaces(&buffer, end);
                 first = strtol10(buffer,&buffer);
             }
             else if (TokenMatchI(buffer,"lastframe",9))     {
-                SkipSpaces(&buffer);
+                SkipSpaces(&buffer, end);
                 last = strtol10(buffer,&buffer);
             }
             else if (TokenMatchI(buffer,"rate",4))  {
-                SkipSpaces(&buffer);
-                float d;
+                SkipSpaces(&buffer, end);
+                float d = { 0.0f };
                 buffer = fast_atoreal_move<float>(buffer,d);
                 anim->mTicksPerSecond = d;
             }
             else if (TokenMatchI(buffer,"order",5)) {
                 std::vector< aiNodeAnim* > anims_temp;
                 anims_temp.reserve(30);
-                while (1)   {
-                    SkipSpaces(&buffer);
-                    if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer) && *buffer == '$')
+                while (true) {
+                    SkipSpaces(&buffer, end);
+                    if (IsLineEnd(*buffer) && SkipSpacesAndLineEnd(&buffer, end) && *buffer == '$')
                         break; // next section
 
                     // Construct a new node animation channel and setup its name
@@ -164,41 +154,43 @@ void CSMImporter::InternReadFile( const std::string& pFile,
                     aiNodeAnim* nda = anims_temp.back();
 
                     char* ot = nda->mNodeName.data;
-                    while (!IsSpaceOrNewLine(*buffer))
+                    while (!IsSpaceOrNewLine(*buffer)) {
                         *ot++ = *buffer++;
+                    }
 
                     *ot = '\0';
                     nda->mNodeName.length = static_cast<ai_uint32>(ot-nda->mNodeName.data);
                 }
 
                 anim->mNumChannels = static_cast<unsigned int>(anims_temp.size());
-                if (!anim->mNumChannels)
+                if (!anim->mNumChannels) {
                     throw DeadlyImportError("CSM: Empty $order section");
+                }
 
                 // copy over to the output animation
                 anim->mChannels = new aiNodeAnim*[anim->mNumChannels];
                 ::memcpy(anim->mChannels,&anims_temp[0],sizeof(aiNodeAnim*)*anim->mNumChannels);
-            }
-            else if (TokenMatchI(buffer,"points",6))    {
-                if (!anim->mNumChannels)
+            } else if (TokenMatchI(buffer,"points",6)) {
+                if (!anim->mNumChannels) {
                     throw DeadlyImportError("CSM: \'$order\' section is required to appear prior to \'$points\'");
+                }
 
                 // If we know how many frames we'll read, we can preallocate some storage
                 unsigned int alloc = 100;
-                if (last != 0x00ffffff)
-                {
+                if (last != 0x00ffffff) {
                     alloc = last-first;
                     alloc += alloc>>2u; // + 25%
-                    for (unsigned int i = 0; i < anim->mNumChannels;++i)
+                    for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
                         anim->mChannels[i]->mPositionKeys = new aiVectorKey[alloc];
+                    }
                 }
 
                 unsigned int filled = 0;
 
                 // Now read all point data.
-                while (1)   {
-                    SkipSpaces(&buffer);
-                    if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer) || *buffer == '$'))   {
+                while (true) {
+                    SkipSpaces(&buffer, end);
+                    if (IsLineEnd(*buffer) && (!SkipSpacesAndLineEnd(&buffer, end) || *buffer == '$'))   {
                         break; // next section
                     }
 
@@ -209,8 +201,8 @@ void CSMImporter::InternReadFile( const std::string& pFile,
                     for (unsigned int i = 0; i < anim->mNumChannels;++i)    {
 
                         aiNodeAnim* s = anim->mChannels[i];
-                        if (s->mNumPositionKeys == alloc)   { /* need to reallocate? */
-
+                        if (s->mNumPositionKeys == alloc)   {
+                            // need to reallocate?
                             aiVectorKey* old = s->mPositionKeys;
                             s->mPositionKeys = new aiVectorKey[s->mNumPositionKeys = alloc*2];
                             ::memcpy(s->mPositionKeys,old,sizeof(aiVectorKey)*alloc);
@@ -218,24 +210,26 @@ void CSMImporter::InternReadFile( const std::string& pFile,
                         }
 
                         // read x,y,z
-                        if(!SkipSpacesAndLineEnd(&buffer))
+                        if (!SkipSpacesAndLineEnd(&buffer, end)) {
                             throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample x coord");
+                        }
 
                         if (TokenMatchI(buffer, "DROPOUT", 7))  {
                             // seems this is invalid marker data; at least the doc says it's possible
                             ASSIMP_LOG_WARN("CSM: Encountered invalid marker data (DROPOUT)");
-                        }
-                        else    {
+                        } else {
                             aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
                             sub->mTime = (double)frame;
                             buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.x);
 
-                            if(!SkipSpacesAndLineEnd(&buffer))
+                            if (!SkipSpacesAndLineEnd(&buffer, end)) {
                                 throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample y coord");
+                            }
                             buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.y);
 
-                            if(!SkipSpacesAndLineEnd(&buffer))
+                            if (!SkipSpacesAndLineEnd(&buffer, end)) {
                                 throw DeadlyImportError("CSM: Unexpected EOF occurred reading sample z coord");
+                            }
                             buffer = fast_atoreal_move<float>(buffer, (float&)sub->mValue.z);
 
                             ++s->mNumPositionKeys;
@@ -243,22 +237,22 @@ void CSMImporter::InternReadFile( const std::string& pFile,
                     }
 
                     // update allocation granularity
-                    if (filled == alloc)
+                    if (filled == alloc) {
                         alloc *= 2;
+                    }
 
                     ++filled;
                 }
                 // all channels must be complete in order to continue safely.
                 for (unsigned int i = 0; i < anim->mNumChannels;++i)    {
-
-                    if (!anim->mChannels[i]->mNumPositionKeys)
+                    if (!anim->mChannels[i]->mNumPositionKeys) {
                         throw DeadlyImportError("CSM: Invalid marker track");
+                    }
                 }
             }
-        }
-        else    {
+        } else {
             // advance to the next line
-            SkipLine(&buffer);
+            SkipLine(&buffer, end);
         }
     }
 
@@ -272,7 +266,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
     pScene->mRootNode->mNumChildren = anim->mNumChannels;
     pScene->mRootNode->mChildren = new aiNode* [anim->mNumChannels];
 
-    for (unsigned int i = 0; i < anim->mNumChannels;++i)    {
+    for (unsigned int i = 0; i < anim->mNumChannels;++i) {
         aiNodeAnim* na = anim->mChannels[i];
 
         aiNode* nd  = pScene->mRootNode->mChildren[i] = new aiNode();

+ 4 - 5
Engine/lib/assimp/code/AssetLib/CSM/CSMLoader.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -61,7 +61,7 @@ namespace Assimp {
 class CSMImporter : public BaseImporter {
 public:
     CSMImporter();
-    ~CSMImporter() override;
+    ~CSMImporter() override = default;
 
     // -------------------------------------------------------------------
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
@@ -81,9 +81,8 @@ protected:
 private:
     bool noSkeletonMesh;
 
-}; // end of class CSMImporter
+};
 
-} // end of namespace Assimp
+} // namespace Assimp
 
 #endif // AI_AC3DIMPORTER_H_INC
-

+ 5 - 5
Engine/lib/assimp/code/AssetLib/Collada/ColladaExporter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -91,7 +91,7 @@ void ExportSceneCollada(const char *pFile, IOSystem *pIOSystem, const aiScene *p
 // Encodes a string into a valid XML ID using the xsd:ID schema qualifications.
 static const std::string XMLIDEncode(const std::string &name) {
     const char XML_ID_CHARS[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_-.";
-    const unsigned int XML_ID_CHARS_COUNT = sizeof(XML_ID_CHARS) / sizeof(char);
+    const unsigned int XML_ID_CHARS_COUNT = sizeof(XML_ID_CHARS) / sizeof(char) - 1;
 
     if (name.length() == 0) {
         return name;
@@ -246,7 +246,7 @@ void ColladaExporter::WriteHeader() {
     }
 
     // Assimp root nodes can have meshes, Collada Scenes cannot
-    if (mScene->mRootNode->mNumChildren == 0 || mScene->mRootNode->mMeshes != 0) {
+    if (mScene->mRootNode->mNumChildren == 0 || mScene->mRootNode->mMeshes != nullptr) {
         mAdd_root_node = true;
     }
 
@@ -448,7 +448,7 @@ void ColladaExporter::WriteLight(size_t pIndex) {
     PushTag();
     switch (light->mType) {
     case aiLightSource_AMBIENT:
-        WriteAmbienttLight(light);
+        WriteAmbientLight(light);
         break;
     case aiLightSource_DIRECTIONAL:
         WriteDirectionalLight(light);
@@ -543,7 +543,7 @@ void ColladaExporter::WriteSpotLight(const aiLight *const light) {
     mOutput << startstr << "</spot>" << endstr;
 }
 
-void ColladaExporter::WriteAmbienttLight(const aiLight *const light) {
+void ColladaExporter::WriteAmbientLight(const aiLight *const light) {
 
     const aiColor3D &color = light->mColorAmbient;
     mOutput << startstr << "<ambient>" << endstr;

+ 2 - 2
Engine/lib/assimp/code/AssetLib/Collada/ColladaExporter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -101,7 +101,7 @@ protected:
     void WritePointLight(const aiLight *const light);
     void WriteDirectionalLight(const aiLight *const light);
     void WriteSpotLight(const aiLight *const light);
-    void WriteAmbienttLight(const aiLight *const light);
+    void WriteAmbientLight(const aiLight *const light);
 
     /// Writes the controller library
     void WriteControllerLibrary();

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Collada/ColladaHelper.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 2 - 2
Engine/lib/assimp/code/AssetLib/Collada/ColladaHelper.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -666,7 +666,7 @@ struct ChannelEntry {
     const Collada::Accessor *mTimeAccessor; ///> Collada accessor to the time values
     const Collada::Data *mTimeData; ///> Source data array for the time values
     const Collada::Accessor *mValueAccessor; ///> Collada accessor to the key value values
-    const Collada::Data *mValueData; ///> Source datat array for the key value values
+    const Collada::Data *mValueData; ///> Source data array for the key value values
 
     ChannelEntry() :
             mChannel(),

+ 24 - 32
Engine/lib/assimp/code/AssetLib/Collada/ColladaLoader.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -64,7 +64,7 @@ namespace Assimp {
 using namespace Assimp::Formatter;
 using namespace Assimp::Collada;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Collada Importer",
     "",
     "",
@@ -92,27 +92,15 @@ inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 ColladaLoader::ColladaLoader() :
-        mFileName(),
-        mMeshIndexByID(),
-        mMaterialIndexByName(),
-        mMeshes(),
-        newMats(),
-        mCameras(),
-        mLights(),
-        mTextures(),
-        mAnims(),
         noSkeletonMesh(false),
         removeEmptyBones(false),
         ignoreUpDirection(false),
+        ignoreUnitSize(false),
         useColladaName(false),
         mNodeNameCounter(0) {
     // empty
 }
 
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-ColladaLoader::~ColladaLoader() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@@ -131,6 +119,7 @@ void ColladaLoader::SetupProperties(const Importer *pImp) {
     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;
+    ignoreUnitSize = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UNIT_SIZE, 0) != 0;
     useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 0) != 0;
 }
 
@@ -179,12 +168,15 @@ void ColladaLoader::InternReadFile(const std::string &pFile, aiScene *pScene, IO
     // ... then fill the materials with the now adjusted settings
     FillMaterials(parser, pScene);
 
-    // Apply unit-size scale calculation
-
-    pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0, 0, 0,
-            0, parser.mUnitSize, 0, 0,
-            0, 0, parser.mUnitSize, 0,
-            0, 0, 0, 1);
+    if (!ignoreUnitSize) {
+        // Apply unit-size scale calculation
+        pScene->mRootNode->mTransformation *= aiMatrix4x4(
+                parser.mUnitSize, 0, 0, 0,
+                0, parser.mUnitSize, 0, 0,
+                0, 0, parser.mUnitSize, 0,
+                0, 0, 0, 1);
+    }
+    
     if (!ignoreUpDirection) {
         // Convert to Y_UP, if different orientation
         if (parser.mUpDirection == ColladaParser::UP_X) {
@@ -255,7 +247,9 @@ aiNode *ColladaLoader::BuildHierarchy(const ColladaParser &pParser, const Collad
 
     // add children. first the *real* ones
     node->mNumChildren = static_cast<unsigned int>(pNode->mChildren.size() + instances.size());
-    node->mChildren = new aiNode *[node->mNumChildren];
+    if (node->mNumChildren != 0) {
+        node->mChildren = new aiNode * [node->mNumChildren];
+    }
 
     for (size_t a = 0; a < pNode->mChildren.size(); ++a) {
         node->mChildren[a] = BuildHierarchy(pParser, pNode->mChildren[a]);
@@ -631,16 +625,14 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
     }
 
     // same for texture coords, as many as we have
-    // empty slots are not allowed, need to pack and adjust UV indexes accordingly
-    for (size_t a = 0, real = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
+    for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
         if (pSrcMesh->mTexCoords[a].size() >= pStartVertex + numVertices) {
-            dstMesh->mTextureCoords[real] = new aiVector3D[numVertices];
+            dstMesh->mTextureCoords[a] = new aiVector3D[numVertices];
             for (size_t b = 0; b < numVertices; ++b) {
-                dstMesh->mTextureCoords[real][b] = pSrcMesh->mTexCoords[a][pStartVertex + b];
+                dstMesh->mTextureCoords[a][b] = pSrcMesh->mTexCoords[a][pStartVertex + b];
             }
 
-            dstMesh->mNumUVComponents[real] = pSrcMesh->mNumUVComponents[a];
-            ++real;
+            dstMesh->mNumUVComponents[a] = pSrcMesh->mNumUVComponents[a];
         }
     }
 
@@ -1264,12 +1256,12 @@ void ColladaLoader::CreateAnimation(aiScene *pScene, const ColladaParser &pParse
             // now for every unique point in time, find or interpolate the key values for that time
             // and apply them to the transform chain. Then the node's present transformation can be calculated.
             ai_real time = startTime;
-            while (1) {
+            while (true) {
                 for (ChannelEntry & e : entries) {
                     // find the keyframe behind the current point in time
                     size_t pos = 0;
                     ai_real postTime = 0.0;
-                    while (1) {
+                    while (true) {
                         if (pos >= e.mTimeAccessor->mCount) {
                             break;
                         }
@@ -1523,7 +1515,7 @@ void ColladaLoader::AddTexture(aiMaterial &mat,
         map = -1;
         for (std::string::const_iterator it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
             if (IsNumeric(*it)) {
-                map = strtoul10(&(*it));        
+                map = strtoul10(&(*it));
                 break;
             }
         }
@@ -1680,7 +1672,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture(const ColladaParser &pParse
 
     // recurse through the param references until we end up at an image
     std::string name = pName;
-    while (1) {
+    while (true) {
         // the given string is a param entry. Find it
         Effect::ParamLibrary::const_iterator it = pEffect.mParams.find(name);
         // if not found, we're at the end of the recursion. The resulting string should be the image ID

+ 3 - 2
Engine/lib/assimp/code/AssetLib/Collada/ColladaLoader.h

@@ -4,7 +4,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -86,7 +86,7 @@ public:
     ColladaLoader();
 
     /// The class destructor.
-    ~ColladaLoader() override;
+    ~ColladaLoader() override = default;
 
     /// Returns whether the class can handle the format of the given file.
     /// @see BaseImporter::CanRead() for more details.
@@ -239,6 +239,7 @@ protected:
     bool noSkeletonMesh;
     bool removeEmptyBones;
     bool ignoreUpDirection;
+    bool ignoreUnitSize;
     bool useColladaName;
 
     /** Used by FindNameForNode() to generate unique node names */

+ 134 - 108
Engine/lib/assimp/code/AssetLib/Collada/ColladaParser.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
 #include <memory>
+#include <utility>
 
 using namespace Assimp;
 using namespace Assimp::Collada;
@@ -67,7 +68,7 @@ static void ReportWarning(const char *msg, ...) {
     va_start(args, msg);
 
     char szBuffer[3000];
-    const int iLen = vsprintf(szBuffer, msg, args);
+    const int iLen = vsnprintf(szBuffer, sizeof(szBuffer), msg, args);
     ai_assert(iLen > 0);
 
     va_end(args);
@@ -144,7 +145,7 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
     } else {
         // attempt to open the file directly
         daefile.reset(pIOHandler->Open(pFile));
-        if (daefile.get() == nullptr) {
+        if (daefile == nullptr) {
             throw DeadlyImportError("Failed to open file '", pFile, "'.");
         }
     }
@@ -634,7 +635,8 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
         const std::string &currentName = currentNode.name();
         if (currentName == "morph") {
             controller.mType = Morph;
-            controller.mMeshId = currentNode.attribute("source").as_string();
+            std::string id = currentNode.attribute("source").as_string();
+            controller.mMeshId = id.substr(1, id.size() - 1);
             int methodIndex = currentNode.attribute("method").as_int();
             if (methodIndex > 0) {
                 std::string method;
@@ -653,12 +655,13 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
             std::string v;
             XmlParser::getValueAsString(currentNode, v);
             const char *content = v.c_str();
+            const char *end = content + v.size();
             for (unsigned int a = 0; a < 16; a++) {
-                SkipSpacesAndLineEnd(&content);
+                SkipSpacesAndLineEnd(&content, end);
                 // read a number
                 content = fast_atoreal_move<ai_real>(content, controller.mBindShapeMatrix[a]);
                 // skip whitespace after it
-                SkipSpacesAndLineEnd(&content);
+                SkipSpacesAndLineEnd(&content, end);
             }
         } else if (currentName == "source") {
             ReadSource(currentNode);
@@ -739,7 +742,9 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
                 throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <vertex_weights> data <input> element");
             }
         } else if (currentName == "vcount" && vertexCount > 0) {
-            const char *text = currentNode.text().as_string();
+            const std::string stdText = currentNode.text().as_string();
+            const char *text = stdText.c_str();
+            const char *end = text + stdText.size();
             size_t numWeights = 0;
             for (std::vector<size_t>::iterator it = pController.mWeightCounts.begin(); it != pController.mWeightCounts.end(); ++it) {
                 if (*text == 0) {
@@ -748,7 +753,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
 
                 *it = strtoul10(text, &text);
                 numWeights += *it;
-                SkipSpacesAndLineEnd(&text);
+                SkipSpacesAndLineEnd(&text, end);
             }
             // reserve weight count
             pController.mWeights.resize(numWeights);
@@ -757,17 +762,19 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
             std::string stdText;
             XmlParser::getValueAsString(currentNode, stdText);
             const char *text = stdText.c_str();
+            const char *end = text + stdText.size();
             for (std::vector<std::pair<size_t, size_t>>::iterator it = pController.mWeights.begin(); it != pController.mWeights.end(); ++it) {
-                if (text == 0) {
+                if (text == nullptr) {
                     throw DeadlyImportError("Out of data while reading <vertex_weights>");
                 }
+                SkipSpacesAndLineEnd(&text, end);
                 it->first = strtoul10(text, &text);
-                SkipSpacesAndLineEnd(&text);
+                SkipSpacesAndLineEnd(&text, end);
                 if (*text == 0) {
                     throw DeadlyImportError("Out of data while reading <vertex_weights>");
                 }
                 it->second = strtoul10(text, &text);
-                SkipSpacesAndLineEnd(&text);
+                SkipSpacesAndLineEnd(&text, end);
             }
         }
     }
@@ -812,38 +819,38 @@ void ColladaParser::ReadImage(XmlNode &node, Collada::Image &pImage) {
                 if (!pImage.mFileName.length()) {
                     pImage.mFileName = "unknown_texture";
                 }
-            }
-        } else if (mFormat == FV_1_5_n) {
-            std::string value;
-            XmlNode refChild = currentNode.child("ref");
-            XmlNode hexChild = currentNode.child("hex");
-            if (refChild) {
-                // element content is filename - hopefully
-                if (XmlParser::getValueAsString(refChild, value)) {
-                    aiString filepath(value);
-                    UriDecodePath(filepath);
-                    pImage.mFileName = filepath.C_Str();
-                }
-            } else if (hexChild && !pImage.mFileName.length()) {
-                // embedded image. get format
-                pImage.mEmbeddedFormat = hexChild.attribute("format").as_string();
-                if (pImage.mEmbeddedFormat.empty()) {
-                    ASSIMP_LOG_WARN("Collada: Unknown image file format");
-                }
+            } else if (mFormat == FV_1_5_n) {
+                std::string value;
+                XmlNode refChild = currentNode.child("ref");
+                XmlNode hexChild = currentNode.child("hex");
+                if (refChild) {
+                    // element content is filename - hopefully
+                    if (XmlParser::getValueAsString(refChild, value)) {
+                        aiString filepath(value);
+                        UriDecodePath(filepath);
+                        pImage.mFileName = filepath.C_Str();
+                    }
+                } else if (hexChild && !pImage.mFileName.length()) {
+                    // embedded image. get format
+                    pImage.mEmbeddedFormat = hexChild.attribute("format").as_string();
+                    if (pImage.mEmbeddedFormat.empty()) {
+                        ASSIMP_LOG_WARN("Collada: Unknown image file format");
+                    }
 
-                XmlParser::getValueAsString(hexChild, value);
-                const char *data = value.c_str();
-                // hexadecimal-encoded binary octets. First of all, find the
-                // required buffer size to reserve enough storage.
-                const char *cur = data;
-                while (!IsSpaceOrNewLine(*cur)) {
-                    ++cur;
-                }
+                    XmlParser::getValueAsString(hexChild, value);
+                    const char *data = value.c_str();
+                    // hexadecimal-encoded binary octets. First of all, find the
+                    // required buffer size to reserve enough storage.
+                    const char *cur = data;
+                    while (!IsSpaceOrNewLine(*cur)) {
+                        ++cur;
+                    }
 
-                const unsigned int size = (unsigned int)(cur - data) * 2;
-                pImage.mImageData.resize(size);
-                for (unsigned int i = 0; i < size; ++i) {
-                    pImage.mImageData[i] = HexOctetToDecimal(data + (i << 1));
+                    const unsigned int size = (unsigned int)(cur - data) * 2;
+                    pImage.mImageData.resize(size);
+                    for (unsigned int i = 0; i < size; ++i) {
+                        pImage.mImageData[i] = HexOctetToDecimal(data + (i << 1));
+                    }
                 }
             }
         }
@@ -950,44 +957,45 @@ void ColladaParser::ReadLight(XmlNode &node, Collada::Light &pLight) {
             std::string v;
             XmlParser::getValueAsString(currentNode, v);
             const char *content = v.c_str();
+            const char *end = content + v.size();
 
             content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.r);
-            SkipSpacesAndLineEnd(&content);
+            SkipSpacesAndLineEnd(&content, end);
 
             content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.g);
-            SkipSpacesAndLineEnd(&content);
+            SkipSpacesAndLineEnd(&content, end);
 
             content = fast_atoreal_move<ai_real>(content, (ai_real &)pLight.mColor.b);
-            SkipSpacesAndLineEnd(&content);
+            SkipSpacesAndLineEnd(&content, end);
         } else if (currentName == "constant_attenuation") {
-            XmlParser::getValueAsFloat(currentNode, pLight.mAttConstant);
+            XmlParser::getValueAsReal(currentNode, pLight.mAttConstant);
         } else if (currentName == "linear_attenuation") {
-            XmlParser::getValueAsFloat(currentNode, pLight.mAttLinear);
+            XmlParser::getValueAsReal(currentNode, pLight.mAttLinear);
         } else if (currentName == "quadratic_attenuation") {
-            XmlParser::getValueAsFloat(currentNode, pLight.mAttQuadratic);
+            XmlParser::getValueAsReal(currentNode, pLight.mAttQuadratic);
         } else if (currentName == "falloff_angle") {
-            XmlParser::getValueAsFloat(currentNode, pLight.mFalloffAngle);
+            XmlParser::getValueAsReal(currentNode, pLight.mFalloffAngle);
         } else if (currentName == "falloff_exponent") {
-            XmlParser::getValueAsFloat(currentNode, pLight.mFalloffExponent);
+            XmlParser::getValueAsReal(currentNode, pLight.mFalloffExponent);
         }
         // FCOLLADA extensions
         // -------------------------------------------------------
         else if (currentName == "outer_cone") {
-            XmlParser::getValueAsFloat(currentNode, pLight.mOuterAngle);
+            XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle);
         } else if (currentName == "penumbra_angle") { // this one is deprecated, now calculated using outer_cone
-            XmlParser::getValueAsFloat(currentNode, pLight.mPenumbraAngle);
+            XmlParser::getValueAsReal(currentNode, pLight.mPenumbraAngle);
         } else if (currentName == "intensity") {
-            XmlParser::getValueAsFloat(currentNode, pLight.mIntensity);
+            XmlParser::getValueAsReal(currentNode, pLight.mIntensity);
         }
         else if (currentName == "falloff") {
-            XmlParser::getValueAsFloat(currentNode, pLight.mOuterAngle);
+            XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle);
         } else if (currentName == "hotspot_beam") {
-            XmlParser::getValueAsFloat(currentNode, pLight.mFalloffAngle);
+            XmlParser::getValueAsReal(currentNode, pLight.mFalloffAngle);
         }
         // OpenCOLLADA extensions
         // -------------------------------------------------------
         else if (currentName == "decay_falloff") {
-            XmlParser::getValueAsFloat(currentNode, pLight.mOuterAngle);
+            XmlParser::getValueAsReal(currentNode, pLight.mOuterAngle);
         }
     }
 }
@@ -1002,15 +1010,15 @@ void ColladaParser::ReadCamera(XmlNode &node, Collada::Camera &camera) {
         if (currentName == "orthographic") {
             camera.mOrtho = true;
         } else if (currentName == "xfov" || currentName == "xmag") {
-            XmlParser::getValueAsFloat(currentNode, camera.mHorFov);
+            XmlParser::getValueAsReal(currentNode, camera.mHorFov);
         } else if (currentName == "yfov" || currentName == "ymag") {
-            XmlParser::getValueAsFloat(currentNode, camera.mVerFov);
+            XmlParser::getValueAsReal(currentNode, camera.mVerFov);
         } else if (currentName == "aspect_ratio") {
-            XmlParser::getValueAsFloat(currentNode, camera.mAspect);
+            XmlParser::getValueAsReal(currentNode, camera.mAspect);
         } else if (currentName == "znear") {
-            XmlParser::getValueAsFloat(currentNode, camera.mZNear);
+            XmlParser::getValueAsReal(currentNode, camera.mZNear);
         } else if (currentName == "zfar") {
-            XmlParser::getValueAsFloat(currentNode, camera.mZFar);
+            XmlParser::getValueAsReal(currentNode, camera.mZFar);
         }
     }
 }
@@ -1162,15 +1170,15 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) {
         } else if (currentName == "mirrorV") {
             XmlParser::getValueAsBool(currentNode, out.mMirrorV);
         } else if (currentName == "repeatU") {
-            XmlParser::getValueAsFloat(currentNode, out.mTransform.mScaling.x);
+            XmlParser::getValueAsReal(currentNode, out.mTransform.mScaling.x);
         } else if (currentName == "repeatV") {
-            XmlParser::getValueAsFloat(currentNode, out.mTransform.mScaling.y);
+            XmlParser::getValueAsReal(currentNode, out.mTransform.mScaling.y);
         } else if (currentName == "offsetU") {
-            XmlParser::getValueAsFloat(currentNode, out.mTransform.mTranslation.x);
+            XmlParser::getValueAsReal(currentNode, out.mTransform.mTranslation.x);
         } else if (currentName == "offsetV") {
-            XmlParser::getValueAsFloat(currentNode, out.mTransform.mTranslation.y);
+            XmlParser::getValueAsReal(currentNode, out.mTransform.mTranslation.y);
         } else if (currentName == "rotateUV") {
-            XmlParser::getValueAsFloat(currentNode, out.mTransform.mRotation);
+            XmlParser::getValueAsReal(currentNode, out.mTransform.mRotation);
         } else if (currentName == "blend_mode") {
             std::string v;
             XmlParser::getValueAsString(currentNode, v);
@@ -1190,14 +1198,14 @@ void ColladaParser::ReadSamplerProperties(XmlNode &node, Sampler &out) {
         // OKINO extensions
         // -------------------------------------------------------
         else if (currentName == "weighting") {
-            XmlParser::getValueAsFloat(currentNode, out.mWeighting);
+            XmlParser::getValueAsReal(currentNode, out.mWeighting);
         } else if (currentName == "mix_with_previous_layer") {
-            XmlParser::getValueAsFloat(currentNode, out.mMixWithPrevious);
+            XmlParser::getValueAsReal(currentNode, out.mMixWithPrevious);
         }
         // MAX3D extensions
         // -------------------------------------------------------
         else if (currentName == "amount") {
-            XmlParser::getValueAsFloat(currentNode, out.mWeighting);
+            XmlParser::getValueAsReal(currentNode, out.mWeighting);
         }
     }
 }
@@ -1218,18 +1226,19 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
             std::string v;
             XmlParser::getValueAsString(currentNode, v);
             const char *content = v.c_str();
+            const char *end = v.c_str() + v.size() + 1; 
 
             content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.r);
-            SkipSpacesAndLineEnd(&content);
+            SkipSpacesAndLineEnd(&content, end);
 
             content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.g);
-            SkipSpacesAndLineEnd(&content);
+            SkipSpacesAndLineEnd(&content, end);
 
             content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.b);
-            SkipSpacesAndLineEnd(&content);
+            SkipSpacesAndLineEnd(&content, end);
 
             content = fast_atoreal_move<ai_real>(content, (ai_real &)pColor.a);
-            SkipSpacesAndLineEnd(&content);
+            SkipSpacesAndLineEnd(&content, end);
         } else if (currentName == "texture") {
             // get name of source texture/sampler
             XmlParser::getStdStrAttribute(currentNode, "texture", pSampler.mName);
@@ -1256,13 +1265,13 @@ void ColladaParser::ReadEffectColor(XmlNode &node, aiColor4D &pColor, Sampler &p
 
 // ------------------------------------------------------------------------------------------------
 // Reads an effect entry containing a float
-void ColladaParser::ReadEffectFloat(XmlNode &node, ai_real &pFloat) {
-    pFloat = 0.f;
+void ColladaParser::ReadEffectFloat(XmlNode &node, ai_real &pReal) {
+    pReal = 0.f;
     XmlNode floatNode = node.child("float");
     if (floatNode.empty()) {
         return;
     }
-    XmlParser::getValueAsFloat(floatNode, pFloat);
+    XmlParser::getValueAsReal(floatNode, pReal);
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -1272,9 +1281,7 @@ void ColladaParser::ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam)
         return;
     }
 
-    XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
-    XmlNode currentNode;
-    while (xmlIt.getNext(currentNode)) {
+    for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "surface") {
             // image ID given inside <init_from> tags
@@ -1287,22 +1294,24 @@ void ColladaParser::ReadEffectParam(XmlNode &node, Collada::EffectParam &pParam)
             }
         } else if (currentName == "sampler2D" && (FV_1_4_n == mFormat || FV_1_3_n == mFormat)) {
             // surface ID is given inside <source> tags
-            const char *content = currentNode.value();
-            pParam.mType = Param_Sampler;
-            pParam.mReference = content;
+            XmlNode source = currentNode.child("source");
+            if (source) {
+                std::string v;
+                XmlParser::getValueAsString(source, v);
+                pParam.mType = Param_Sampler;
+                pParam.mReference = v.c_str();
+            }
         } else if (currentName == "sampler2D") {
             // surface ID is given inside <instance_image> tags
-            std::string url;
-            XmlParser::getStdStrAttribute(currentNode, "url", url);
-            if (url[0] != '#') {
-                throw DeadlyImportError("Unsupported URL format in instance_image");
-            }
-            pParam.mType = Param_Sampler;
-            pParam.mReference = url.c_str() + 1;
-        } else if (currentName == "source") {
-            const char *source = currentNode.child_value();
-            if (nullptr != source) {
-                pParam.mReference = source;
+            XmlNode instance_image = currentNode.child("instance_image");
+            if (instance_image) {
+                std::string url;
+                XmlParser::getStdStrAttribute(instance_image, "url", url);
+                if (url[0] != '#') {
+                    throw DeadlyImportError("Unsupported URL format in instance_image");
+                }
+                pParam.mType = Param_Sampler;
+                pParam.mReference = url.c_str() + 1;
             }
         }
     }
@@ -1343,6 +1352,7 @@ void ColladaParser::ReadGeometry(XmlNode &node, Collada::Mesh &pMesh) {
     if (node.empty()) {
         return;
     }
+    
     for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "mesh") {
@@ -1413,6 +1423,7 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
     XmlParser::getValueAsString(node, v);
     v = ai_trim(v);
     const char *content = v.c_str();
+    const char *end = content + v.size();
 
     // read values and store inside an array in the data library
     mDataLibrary[id] = Data();
@@ -1431,11 +1442,13 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
                 }
 
                 s.clear();
-                while (!IsSpaceOrNewLine(*content))
-                    s += *content++;
+                while (!IsSpaceOrNewLine(*content)) {
+                    s += *content;
+                    content++;
+                }
                 data.mStrings.push_back(s);
 
-                SkipSpacesAndLineEnd(&content);
+                SkipSpacesAndLineEnd(&content, end);
             }
         } else {
             data.mValues.reserve(count);
@@ -1450,7 +1463,7 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
                 content = fast_atoreal_move<ai_real>(content, value);
                 data.mValues.push_back(value);
                 // skip whitespace after it
-                SkipSpacesAndLineEnd(&content);
+                SkipSpacesAndLineEnd(&content, end);
             }
         }
     }
@@ -1615,8 +1628,10 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
                     std::string v;
                     XmlParser::getValueAsString(currentNode, v);
                     const char *content = v.c_str();
+                    const char *end = content + v.size();
+
                     vcount.reserve(numPrimitives);
-                    SkipSpacesAndLineEnd(&content);
+                    SkipSpacesAndLineEnd(&content, end);
                     for (unsigned int a = 0; a < numPrimitives; a++) {
                         if (*content == 0) {
                             throw DeadlyImportError("Expected more values while reading <vcount> contents.");
@@ -1624,7 +1639,7 @@ void ColladaParser::ReadIndexData(XmlNode &node, Mesh &pMesh) {
                         // read a number
                         vcount.push_back((size_t)strtoul10(content, &content));
                         // skip whitespace after it
-                        SkipSpacesAndLineEnd(&content);
+                        SkipSpacesAndLineEnd(&content, end);
                     }
                 }
             }
@@ -1733,14 +1748,16 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
         std::string v;
         XmlParser::getValueAsString(node, v);
         const char *content = v.c_str();
-        SkipSpacesAndLineEnd(&content);
+        const char *end = content + v.size();
+
+        SkipSpacesAndLineEnd(&content, end);
         while (*content != 0) {
             // read a value.
             // Hack: (thom) Some exporters put negative indices sometimes. We just try to carry on anyways.
             int value = std::max(0, strtol10(content, &content));
             indices.push_back(size_t(value));
             // skip whitespace after it
-            SkipSpacesAndLineEnd(&content);
+            SkipSpacesAndLineEnd(&content, end);
         }
     }
 
@@ -1770,6 +1787,10 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
         const Accessor *acc = input.mResolved;
         if (!acc->mData) {
             acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource);
+            const size_t dataSize = acc->mOffset + acc->mCount * acc->mStride;
+            if (dataSize > acc->mData->mValues.size()) {
+                throw DeadlyImportError("Not enough data for accessor");
+            }
         }
     }
     // and the same for the per-index channels
@@ -1794,13 +1815,19 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
         const Accessor *acc = input.mResolved;
         if (!acc->mData) {
             acc->mData = &ResolveLibraryReference(mDataLibrary, acc->mSource);
+            const size_t dataSize = acc->mOffset + acc->mCount * acc->mStride;
+            if (dataSize > acc->mData->mValues.size()) {
+                throw DeadlyImportError("Not enough data for accessor");
+            }
         }
     }
 
     // For continued primitives, the given count does not come all in one <p>, but only one primitive per <p>
     size_t numPrimitives = pNumPrimitives;
-    if (pPrimType == Prim_TriFans || pPrimType == Prim_Polygon)
+    if (pPrimType == Prim_TriFans || pPrimType == Prim_Polygon) {
         numPrimitives = 1;
+    }
+
     // For continued primitives, the given count is actually the number of <p>'s inside the parent tag
     if (pPrimType == Prim_TriStrips) {
         size_t numberOfVertices = indices.size() / numOffsets;
@@ -1853,7 +1880,6 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
         default:
             // LineStrip is not supported due to expected index unmangling
             throw DeadlyImportError("Unsupported primitive type.");
-            break;
         }
 
         // store the face size to later reconstruct the face from
@@ -1866,7 +1892,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
 
 ///@note This function won't work correctly if both PerIndex and PerVertex channels have same channels.
 ///For example if TEXCOORD present in both <vertices> and <polylist> tags this function will create wrong uv coordinates.
-///It's not clear from COLLADA documentation is this allowed or not. For now only exporter fixed to avoid such behavior
+///It's not clear from COLLADA documentation whether this is allowed or not. For now only exporter fixed to avoid such behavior
 void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh &pMesh,
         std::vector<InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices) {
     // calculate the base offset of the vertex whose attributes we ant to copy
@@ -2165,15 +2191,15 @@ void ColladaParser::ReadNodeTransformation(XmlNode &node, Node *pNode, Transform
     }
 
     // how many parameters to read per transformation type
-    static const unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 };
+    static constexpr unsigned int sNumParameters[] = { 9, 4, 3, 3, 7, 16 };
     std::string value;
     XmlParser::getValueAsString(node, value);
     const char *content = value.c_str();
-
+    const char *end = value.c_str() + value.size();
     // read as many parameters and store in the transformation
     for (unsigned int a = 0; a < sNumParameters[pType]; a++) {
         // skip whitespace before the number
-        SkipSpacesAndLineEnd(&content);
+        SkipSpacesAndLineEnd(&content, end);
         // read a number
         content = fast_atoreal_move<ai_real>(content, tf.f[a]);
     }
@@ -2267,9 +2293,9 @@ void ColladaParser::ReadNodeGeometry(XmlNode &node, Node *pNode) {
                             urlMat++;
 
                         s.mMatName = urlMat;
+                        ReadMaterialVertexInputBinding(instanceMatNode, s);
                         // store the association
                         instance.mMaterials[group] = s;
-                        ReadMaterialVertexInputBinding(instanceMatNode, s);
                     }
                 }
             }
@@ -2305,7 +2331,7 @@ void ColladaParser::ReadScene(XmlNode &node) {
             // find the referred scene, skip the leading #
             NodeLibrary::const_iterator sit = mNodeLibrary.find(url.c_str() + 1);
             if (sit == mNodeLibrary.end()) {
-                throw DeadlyImportError("Unable to resolve visual_scene reference \"", std::string(url), "\" in <instance_visual_scene> element.");
+                throw DeadlyImportError("Unable to resolve visual_scene reference \"", std::string(std::move(url)), "\" in <instance_visual_scene> element.");
             }
             mRootNode = sit->second;
         }

+ 1 - 1
Engine/lib/assimp/code/AssetLib/Collada/ColladaParser.h

@@ -2,7 +2,7 @@
  Open Asset Import Library (assimp)
  ----------------------------------------------------------------------
 
- Copyright (c) 2006-2022, assimp team
+ Copyright (c) 2006-2024, assimp team
 
  All rights reserved.
 

+ 2 - 4
Engine/lib/assimp/code/AssetLib/DXF/DXFHelper.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -65,7 +65,6 @@ public:
     LineReader(StreamReaderLE& reader)
     : splitter(reader,false,true)
     , groupcode( 0 )
-    , value()
     , end() {
         // empty
     }
@@ -186,8 +185,7 @@ struct InsertBlock {
     InsertBlock()
     : pos()
     , scale(1.f,1.f,1.f)
-    , angle()
-    , name() {
+    , angle() {
         // empty
     }
 

+ 292 - 54
Engine/lib/assimp/code/AssetLib/DXF/DXFLoader.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the DXF importer class
  */
 
-
 #ifndef ASSIMP_BUILD_NO_DXF_IMPORTER
 
 #include "AssetLib/DXF/DXFLoader.h"
@@ -57,6 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/importerdesc.h>
 
 #include <numeric>
+#include <utility>
 
 using namespace Assimp;
 
@@ -67,26 +67,269 @@ static constexpr size_t AI_DXF_BINARY_IDENT_LEN = sizeof AI_DXF_BINARY_IDENT;
 // default vertex color that all uncolored vertices will receive
 static const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f));
 
-// color indices for DXF - 16 are supported, the table is
-// taken directly from the DXF spec.
-static aiColor4D g_aclrDxfIndexColors[] = {
-    aiColor4D (0.6f, 0.6f, 0.6f, 1.0f),
-    aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red
-    aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green
-    aiColor4D (0.0f, 0.0f, 1.0f, 1.0f), // blue
-    aiColor4D (0.3f, 1.0f, 0.3f, 1.0f), // light green
-    aiColor4D (0.3f, 0.3f, 1.0f, 1.0f), // light blue
-    aiColor4D (1.0f, 0.3f, 0.3f, 1.0f), // light red
-    aiColor4D (1.0f, 0.0f, 1.0f, 1.0f), // pink
-    aiColor4D (1.0f, 0.6f, 0.0f, 1.0f), // orange
-    aiColor4D (0.6f, 0.3f, 0.0f, 1.0f), // dark orange
-    aiColor4D (1.0f, 1.0f, 0.0f, 1.0f), // yellow
-    aiColor4D (0.3f, 0.3f, 0.3f, 1.0f), // dark gray
-    aiColor4D (0.8f, 0.8f, 0.8f, 1.0f), // light gray
-    aiColor4D (0.0f, 00.f, 0.0f, 1.0f), // black
-    aiColor4D (1.0f, 1.0f, 1.0f, 1.0f), // white
-    aiColor4D (0.6f, 0.0f, 1.0f, 1.0f)  // violet
+// color indices for DXF - 256 are supported, the table is
+// taken directly from the AutoCad Index (ACI) table
+// https://gohtx.com/acadcolors.php
+//STH 2024-0126
+static const aiColor4D g_aclrDxfIndexColors[256] = {
+    aiColor4D (0.0f, 0.0f ,0.0f, 1.0f), //dxf color code 0
+    aiColor4D (1.0f, 0.0f ,0.0f, 1.0f), //dxf color code 1
+    aiColor4D (1.0f, 1.0f ,0.0f, 1.0f), //dxf color code 2
+    aiColor4D (0.0f, 1.0f ,0.0f, 1.0f), //dxf color code 3
+    aiColor4D (0.0f, 1.0f ,1.0f, 1.0f), //dxf color code 4
+    aiColor4D (0.0f, 0.0f ,1.0f, 1.0f), //dxf color code 5
+    aiColor4D (1.0f, 0.0f ,1.0f, 1.0f), //dxf color code 6
+    aiColor4D (1.0f, 1.0f ,1.0f, 1.0f), //dxf color code 7
+    aiColor4D (0.3f, 0.3f ,0.3f, 1.0f), //dxf color code 8
+    aiColor4D (0.5f, 0.5f ,0.5f, 1.0f), //dxf color code 9
+    aiColor4D (1.0f, 0.0f ,0.0f, 1.0f), //dxf color code 10
+    aiColor4D (1.0f, 0.7f ,0.7f, 1.0f), //dxf color code 11
+    aiColor4D (0.7f, 0.0f ,0.0f, 1.0f), //dxf color code 12
+    aiColor4D (0.7f, 0.5f ,0.5f, 1.0f), //dxf color code 13
+    aiColor4D (0.5f, 0.0f ,0.0f, 1.0f), //dxf color code 14
+    aiColor4D (0.5f, 0.3f ,0.3f, 1.0f), //dxf color code 15
+    aiColor4D (0.4f, 0.0f ,0.0f, 1.0f), //dxf color code 16
+    aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 17
+    aiColor4D (0.3f, 0.0f ,0.0f, 1.0f), //dxf color code 18
+    aiColor4D (0.3f, 0.2f ,0.2f, 1.0f), //dxf color code 19
+    aiColor4D (1.0f, 0.2f ,0.0f, 1.0f), //dxf color code 20
+    aiColor4D (1.0f, 0.7f ,0.7f, 1.0f), //dxf color code 21
+    aiColor4D (0.7f, 0.2f ,0.0f, 1.0f), //dxf color code 22
+    aiColor4D (0.7f, 0.6f ,0.5f, 1.0f), //dxf color code 23
+    aiColor4D (0.5f, 0.1f ,0.0f, 1.0f), //dxf color code 24
+    aiColor4D (0.5f, 0.4f ,0.3f, 1.0f), //dxf color code 25
+    aiColor4D (0.4f, 0.1f ,0.0f, 1.0f), //dxf color code 26
+    aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 27
+    aiColor4D (0.3f, 0.1f ,0.0f, 1.0f), //dxf color code 28
+    aiColor4D (0.3f, 0.2f ,0.2f, 1.0f), //dxf color code 29
+    aiColor4D (1.0f, 0.5f ,0.0f, 1.0f), //dxf color code 30
+    aiColor4D (1.0f, 0.8f ,0.7f, 1.0f), //dxf color code 31
+    aiColor4D (0.7f, 0.4f ,0.0f, 1.0f), //dxf color code 32
+    aiColor4D (0.7f, 0.6f ,0.5f, 1.0f), //dxf color code 33
+    aiColor4D (0.5f, 0.3f ,0.0f, 1.0f), //dxf color code 34
+    aiColor4D (0.5f, 0.4f ,0.3f, 1.0f), //dxf color code 35
+    aiColor4D (0.4f, 0.2f ,0.0f, 1.0f), //dxf color code 36
+    aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 37
+    aiColor4D (0.3f, 0.2f ,0.0f, 1.0f), //dxf color code 38
+    aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 39
+    aiColor4D (1.0f, 0.7f ,0.0f, 1.0f), //dxf color code 40
+    aiColor4D (1.0f, 0.9f ,0.7f, 1.0f), //dxf color code 41
+    aiColor4D (0.7f, 0.6f ,0.0f, 1.0f), //dxf color code 42
+    aiColor4D (0.7f, 0.7f ,0.5f, 1.0f), //dxf color code 43
+    aiColor4D (0.5f, 0.4f ,0.0f, 1.0f), //dxf color code 44
+    aiColor4D (0.5f, 0.5f ,0.3f, 1.0f), //dxf color code 45
+    aiColor4D (0.4f, 0.3f ,0.0f, 1.0f), //dxf color code 46
+    aiColor4D (0.4f, 0.4f ,0.3f, 1.0f), //dxf color code 47
+    aiColor4D (0.3f, 0.2f ,0.0f, 1.0f), //dxf color code 48
+    aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 49
+    aiColor4D (1.0f, 1.0f ,0.0f, 1.0f), //dxf color code 50
+    aiColor4D (1.0f, 1.0f ,0.7f, 1.0f), //dxf color code 51
+    aiColor4D (0.7f, 0.7f ,0.0f, 1.0f), //dxf color code 52
+    aiColor4D (0.7f, 0.7f ,0.5f, 1.0f), //dxf color code 53
+    aiColor4D (0.5f, 0.5f ,0.0f, 1.0f), //dxf color code 54
+    aiColor4D (0.5f, 0.5f ,0.3f, 1.0f), //dxf color code 55
+    aiColor4D (0.4f, 0.4f ,0.0f, 1.0f), //dxf color code 56
+    aiColor4D (0.4f, 0.4f ,0.3f, 1.0f), //dxf color code 57
+    aiColor4D (0.3f, 0.3f ,0.0f, 1.0f), //dxf color code 58
+    aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 59
+    aiColor4D (0.7f, 1.0f ,0.0f, 1.0f), //dxf color code 60
+    aiColor4D (0.9f, 1.0f ,0.7f, 1.0f), //dxf color code 61
+    aiColor4D (0.6f, 0.7f ,0.0f, 1.0f), //dxf color code 62
+    aiColor4D (0.7f, 0.7f ,0.5f, 1.0f), //dxf color code 63
+    aiColor4D (0.4f, 0.5f ,0.0f, 1.0f), //dxf color code 64
+    aiColor4D (0.5f, 0.5f ,0.3f, 1.0f), //dxf color code 65
+    aiColor4D (0.3f, 0.4f ,0.0f, 1.0f), //dxf color code 66
+    aiColor4D (0.4f, 0.4f ,0.3f, 1.0f), //dxf color code 67
+    aiColor4D (0.2f, 0.3f ,0.0f, 1.0f), //dxf color code 68
+    aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 69
+    aiColor4D (0.5f, 1.0f ,0.0f, 1.0f), //dxf color code 70
+    aiColor4D (0.8f, 1.0f ,0.7f, 1.0f), //dxf color code 71
+    aiColor4D (0.4f, 0.7f ,0.0f, 1.0f), //dxf color code 72
+    aiColor4D (0.6f, 0.7f ,0.5f, 1.0f), //dxf color code 73
+    aiColor4D (0.3f, 0.5f ,0.0f, 1.0f), //dxf color code 74
+    aiColor4D (0.4f, 0.5f ,0.3f, 1.0f), //dxf color code 75
+    aiColor4D (0.2f, 0.4f ,0.0f, 1.0f), //dxf color code 76
+    aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 77
+    aiColor4D (0.2f, 0.3f ,0.0f, 1.0f), //dxf color code 78
+    aiColor4D (0.3f, 0.3f ,0.2f, 1.0f), //dxf color code 79
+    aiColor4D (0.2f, 1.0f ,0.0f, 1.0f), //dxf color code 80
+    aiColor4D (0.7f, 1.0f ,0.7f, 1.0f), //dxf color code 81
+    aiColor4D (0.2f, 0.7f ,0.0f, 1.0f), //dxf color code 82
+    aiColor4D (0.6f, 0.7f ,0.5f, 1.0f), //dxf color code 83
+    aiColor4D (0.1f, 0.5f ,0.0f, 1.0f), //dxf color code 84
+    aiColor4D (0.4f, 0.5f ,0.3f, 1.0f), //dxf color code 85
+    aiColor4D (0.1f, 0.4f ,0.0f, 1.0f), //dxf color code 86
+    aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 87
+    aiColor4D (0.1f, 0.3f ,0.0f, 1.0f), //dxf color code 88
+    aiColor4D (0.2f, 0.3f ,0.2f, 1.0f), //dxf color code 89
+    aiColor4D (0.0f, 1.0f ,0.0f, 1.0f), //dxf color code 90
+    aiColor4D (0.7f, 1.0f ,0.7f, 1.0f), //dxf color code 91
+    aiColor4D (0.0f, 0.7f ,0.0f, 1.0f), //dxf color code 92
+    aiColor4D (0.5f, 0.7f ,0.5f, 1.0f), //dxf color code 93
+    aiColor4D (0.0f, 0.5f ,0.0f, 1.0f), //dxf color code 94
+    aiColor4D (0.3f, 0.5f ,0.3f, 1.0f), //dxf color code 95
+    aiColor4D (0.0f, 0.4f ,0.0f, 1.0f), //dxf color code 96
+    aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 97
+    aiColor4D (0.0f, 0.3f ,0.0f, 1.0f), //dxf color code 98
+    aiColor4D (0.2f, 0.3f ,0.2f, 1.0f), //dxf color code 99
+    aiColor4D (0.0f, 1.0f ,0.2f, 1.0f), //dxf color code 100
+    aiColor4D (0.7f, 1.0f ,0.7f, 1.0f), //dxf color code 101
+    aiColor4D (0.0f, 0.7f ,0.2f, 1.0f), //dxf color code 102
+    aiColor4D (0.5f, 0.7f ,0.6f, 1.0f), //dxf color code 103
+    aiColor4D (0.0f, 0.5f ,0.1f, 1.0f), //dxf color code 104
+    aiColor4D (0.3f, 0.5f ,0.4f, 1.0f), //dxf color code 105
+    aiColor4D (0.0f, 0.4f ,0.1f, 1.0f), //dxf color code 106
+    aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 107
+    aiColor4D (0.0f, 0.3f ,0.1f, 1.0f), //dxf color code 108
+    aiColor4D (0.2f, 0.3f ,0.2f, 1.0f), //dxf color code 109
+    aiColor4D (0.0f, 1.0f ,0.5f, 1.0f), //dxf color code 110
+    aiColor4D (0.7f, 1.0f ,0.8f, 1.0f), //dxf color code 111
+    aiColor4D (0.0f, 0.7f ,0.4f, 1.0f), //dxf color code 112
+    aiColor4D (0.5f, 0.7f ,0.6f, 1.0f), //dxf color code 113
+    aiColor4D (0.0f, 0.5f ,0.3f, 1.0f), //dxf color code 114
+    aiColor4D (0.3f, 0.5f ,0.4f, 1.0f), //dxf color code 115
+    aiColor4D (0.0f, 0.4f ,0.2f, 1.0f), //dxf color code 116
+    aiColor4D (0.3f, 0.4f ,0.3f, 1.0f), //dxf color code 117
+    aiColor4D (0.0f, 0.3f ,0.2f, 1.0f), //dxf color code 118
+    aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 119
+    aiColor4D (0.0f, 1.0f ,0.7f, 1.0f), //dxf color code 120
+    aiColor4D (0.7f, 1.0f ,0.9f, 1.0f), //dxf color code 121
+    aiColor4D (0.0f, 0.7f ,0.6f, 1.0f), //dxf color code 122
+    aiColor4D (0.5f, 0.7f ,0.7f, 1.0f), //dxf color code 123
+    aiColor4D (0.0f, 0.5f ,0.4f, 1.0f), //dxf color code 124
+    aiColor4D (0.3f, 0.5f ,0.5f, 1.0f), //dxf color code 125
+    aiColor4D (0.0f, 0.4f ,0.3f, 1.0f), //dxf color code 126
+    aiColor4D (0.3f, 0.4f ,0.4f, 1.0f), //dxf color code 127
+    aiColor4D (0.0f, 0.3f ,0.2f, 1.0f), //dxf color code 128
+    aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 129
+    aiColor4D (0.0f, 1.0f ,1.0f, 1.0f), //dxf color code 130
+    aiColor4D (0.7f, 1.0f ,1.0f, 1.0f), //dxf color code 131
+    aiColor4D (0.0f, 0.7f ,0.7f, 1.0f), //dxf color code 132
+    aiColor4D (0.5f, 0.7f ,0.7f, 1.0f), //dxf color code 133
+    aiColor4D (0.0f, 0.5f ,0.5f, 1.0f), //dxf color code 134
+    aiColor4D (0.3f, 0.5f ,0.5f, 1.0f), //dxf color code 135
+    aiColor4D (0.0f, 0.4f ,0.4f, 1.0f), //dxf color code 136
+    aiColor4D (0.3f, 0.4f ,0.4f, 1.0f), //dxf color code 137
+    aiColor4D (0.0f, 0.3f ,0.3f, 1.0f), //dxf color code 138
+    aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 139
+    aiColor4D (0.0f, 0.7f ,1.0f, 1.0f), //dxf color code 140
+    aiColor4D (0.7f, 0.9f ,1.0f, 1.0f), //dxf color code 141
+    aiColor4D (0.0f, 0.6f ,0.7f, 1.0f), //dxf color code 142
+    aiColor4D (0.5f, 0.7f ,0.7f, 1.0f), //dxf color code 143
+    aiColor4D (0.0f, 0.4f ,0.5f, 1.0f), //dxf color code 144
+    aiColor4D (0.3f, 0.5f ,0.5f, 1.0f), //dxf color code 145
+    aiColor4D (0.0f, 0.3f ,0.4f, 1.0f), //dxf color code 146
+    aiColor4D (0.3f, 0.4f ,0.4f, 1.0f), //dxf color code 147
+    aiColor4D (0.0f, 0.2f ,0.3f, 1.0f), //dxf color code 148
+    aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 149
+    aiColor4D (0.0f, 0.5f ,1.0f, 1.0f), //dxf color code 150
+    aiColor4D (0.7f, 0.8f ,1.0f, 1.0f), //dxf color code 151
+    aiColor4D (0.0f, 0.4f ,0.7f, 1.0f), //dxf color code 152
+    aiColor4D (0.5f, 0.6f ,0.7f, 1.0f), //dxf color code 153
+    aiColor4D (0.0f, 0.3f ,0.5f, 1.0f), //dxf color code 154
+    aiColor4D (0.3f, 0.4f ,0.5f, 1.0f), //dxf color code 155
+    aiColor4D (0.0f, 0.2f ,0.4f, 1.0f), //dxf color code 156
+    aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 157
+    aiColor4D (0.0f, 0.2f ,0.3f, 1.0f), //dxf color code 158
+    aiColor4D (0.2f, 0.3f ,0.3f, 1.0f), //dxf color code 159
+    aiColor4D (0.0f, 0.2f ,1.0f, 1.0f), //dxf color code 160
+    aiColor4D (0.7f, 0.7f ,1.0f, 1.0f), //dxf color code 161
+    aiColor4D (0.0f, 0.2f ,0.7f, 1.0f), //dxf color code 162
+    aiColor4D (0.5f, 0.6f ,0.7f, 1.0f), //dxf color code 163
+    aiColor4D (0.0f, 0.1f ,0.5f, 1.0f), //dxf color code 164
+    aiColor4D (0.3f, 0.4f ,0.5f, 1.0f), //dxf color code 165
+    aiColor4D (0.0f, 0.1f ,0.4f, 1.0f), //dxf color code 166
+    aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 167
+    aiColor4D (0.0f, 0.1f ,0.3f, 1.0f), //dxf color code 168
+    aiColor4D (0.2f, 0.2f ,0.3f, 1.0f), //dxf color code 169
+    aiColor4D (0.0f, 0.0f ,1.0f, 1.0f), //dxf color code 170
+    aiColor4D (0.7f, 0.7f ,1.0f, 1.0f), //dxf color code 171
+    aiColor4D (0.0f, 0.0f ,0.7f, 1.0f), //dxf color code 172
+    aiColor4D (0.5f, 0.5f ,0.7f, 1.0f), //dxf color code 173
+    aiColor4D (0.0f, 0.0f ,0.5f, 1.0f), //dxf color code 174
+    aiColor4D (0.3f, 0.3f ,0.5f, 1.0f), //dxf color code 175
+    aiColor4D (0.0f, 0.0f ,0.4f, 1.0f), //dxf color code 176
+    aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 177
+    aiColor4D (0.0f, 0.0f ,0.3f, 1.0f), //dxf color code 178
+    aiColor4D (0.2f, 0.2f ,0.3f, 1.0f), //dxf color code 179
+    aiColor4D (0.2f, 0.0f ,1.0f, 1.0f), //dxf color code 180
+    aiColor4D (0.7f, 0.7f ,1.0f, 1.0f), //dxf color code 181
+    aiColor4D (0.2f, 0.0f ,0.7f, 1.0f), //dxf color code 182
+    aiColor4D (0.6f, 0.5f ,0.7f, 1.0f), //dxf color code 183
+    aiColor4D (0.1f, 0.0f ,0.5f, 1.0f), //dxf color code 184
+    aiColor4D (0.4f, 0.3f ,0.5f, 1.0f), //dxf color code 185
+    aiColor4D (0.1f, 0.0f ,0.4f, 1.0f), //dxf color code 186
+    aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 187
+    aiColor4D (0.1f, 0.0f ,0.3f, 1.0f), //dxf color code 188
+    aiColor4D (0.2f, 0.2f ,0.3f, 1.0f), //dxf color code 189
+    aiColor4D (0.5f, 0.0f ,1.0f, 1.0f), //dxf color code 190
+    aiColor4D (0.8f, 0.7f ,1.0f, 1.0f), //dxf color code 191
+    aiColor4D (0.4f, 0.0f ,0.7f, 1.0f), //dxf color code 192
+    aiColor4D (0.6f, 0.5f ,0.7f, 1.0f), //dxf color code 193
+    aiColor4D (0.3f, 0.0f ,0.5f, 1.0f), //dxf color code 194
+    aiColor4D (0.4f, 0.3f ,0.5f, 1.0f), //dxf color code 195
+    aiColor4D (0.2f, 0.0f ,0.4f, 1.0f), //dxf color code 196
+    aiColor4D (0.3f, 0.3f ,0.4f, 1.0f), //dxf color code 197
+    aiColor4D (0.2f, 0.0f ,0.3f, 1.0f), //dxf color code 198
+    aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 199
+    aiColor4D (0.7f, 0.0f ,1.0f, 1.0f), //dxf color code 200
+    aiColor4D (0.9f, 0.7f ,1.0f, 1.0f), //dxf color code 201
+    aiColor4D (0.6f, 0.0f ,0.7f, 1.0f), //dxf color code 202
+    aiColor4D (0.7f, 0.5f ,0.7f, 1.0f), //dxf color code 203
+    aiColor4D (0.4f, 0.0f ,0.5f, 1.0f), //dxf color code 204
+    aiColor4D (0.5f, 0.3f ,0.5f, 1.0f), //dxf color code 205
+    aiColor4D (0.3f, 0.0f ,0.4f, 1.0f), //dxf color code 206
+    aiColor4D (0.4f, 0.3f ,0.4f, 1.0f), //dxf color code 207
+    aiColor4D (0.2f, 0.0f ,0.3f, 1.0f), //dxf color code 208
+    aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 209
+    aiColor4D (1.0f, 0.0f ,1.0f, 1.0f), //dxf color code 210
+    aiColor4D (1.0f, 0.7f ,1.0f, 1.0f), //dxf color code 211
+    aiColor4D (0.7f, 0.0f ,0.7f, 1.0f), //dxf color code 212
+    aiColor4D (0.7f, 0.5f ,0.7f, 1.0f), //dxf color code 213
+    aiColor4D (0.5f, 0.0f ,0.5f, 1.0f), //dxf color code 214
+    aiColor4D (0.5f, 0.3f ,0.5f, 1.0f), //dxf color code 215
+    aiColor4D (0.4f, 0.0f ,0.4f, 1.0f), //dxf color code 216
+    aiColor4D (0.4f, 0.3f ,0.4f, 1.0f), //dxf color code 217
+    aiColor4D (0.3f, 0.0f ,0.3f, 1.0f), //dxf color code 218
+    aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 219
+    aiColor4D (1.0f, 0.0f ,0.7f, 1.0f), //dxf color code 220
+    aiColor4D (1.0f, 0.7f ,0.9f, 1.0f), //dxf color code 221
+    aiColor4D (0.7f, 0.0f ,0.6f, 1.0f), //dxf color code 222
+    aiColor4D (0.7f, 0.5f ,0.7f, 1.0f), //dxf color code 223
+    aiColor4D (0.5f, 0.0f ,0.4f, 1.0f), //dxf color code 224
+    aiColor4D (0.5f, 0.3f ,0.5f, 1.0f), //dxf color code 225
+    aiColor4D (0.4f, 0.0f ,0.3f, 1.0f), //dxf color code 226
+    aiColor4D (0.4f, 0.3f ,0.4f, 1.0f), //dxf color code 227
+    aiColor4D (0.3f, 0.0f ,0.2f, 1.0f), //dxf color code 228
+    aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 229
+    aiColor4D (1.0f, 0.0f ,0.5f, 1.0f), //dxf color code 230
+    aiColor4D (1.0f, 0.7f ,0.8f, 1.0f), //dxf color code 231
+    aiColor4D (0.7f, 0.0f ,0.4f, 1.0f), //dxf color code 232
+    aiColor4D (0.7f, 0.5f ,0.6f, 1.0f), //dxf color code 233
+    aiColor4D (0.5f, 0.0f ,0.3f, 1.0f), //dxf color code 234
+    aiColor4D (0.5f, 0.3f ,0.4f, 1.0f), //dxf color code 235
+    aiColor4D (0.4f, 0.0f ,0.2f, 1.0f), //dxf color code 236
+    aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 237
+    aiColor4D (0.3f, 0.0f ,0.2f, 1.0f), //dxf color code 238
+    aiColor4D (0.3f, 0.2f ,0.3f, 1.0f), //dxf color code 239
+    aiColor4D (1.0f, 0.0f ,0.2f, 1.0f), //dxf color code 240
+    aiColor4D (1.0f, 0.7f ,0.7f, 1.0f), //dxf color code 241
+    aiColor4D (0.7f, 0.0f ,0.2f, 1.0f), //dxf color code 242
+    aiColor4D (0.7f, 0.5f ,0.6f, 1.0f), //dxf color code 243
+    aiColor4D (0.5f, 0.0f ,0.1f, 1.0f), //dxf color code 244
+    aiColor4D (0.5f, 0.3f ,0.4f, 1.0f), //dxf color code 245
+    aiColor4D (0.4f, 0.0f ,0.1f, 1.0f), //dxf color code 246
+    aiColor4D (0.4f, 0.3f ,0.3f, 1.0f), //dxf color code 247
+    aiColor4D (0.3f, 0.0f ,0.1f, 1.0f), //dxf color code 248
+    aiColor4D (0.3f, 0.2f ,0.2f, 1.0f), //dxf color code 249
+    aiColor4D (0.2f, 0.2f ,0.2f, 1.0f), //dxf color code 250
+    aiColor4D (0.3f, 0.3f ,0.3f, 1.0f), //dxf color code 251
+    aiColor4D (0.4f, 0.4f ,0.4f, 1.0f), //dxf color code 252
+    aiColor4D (0.5f, 0.5f ,0.5f, 1.0f), //dxf color code 253
+    aiColor4D (0.7f, 0.7f ,0.7f, 1.0f), //dxf color code 254
+    aiColor4D (1.0f, 1.0f ,1.0f, 1.0f) //dxf color code 255
 };
+
 #define AI_DXF_NUM_INDEX_COLORS (sizeof(g_aclrDxfIndexColors)/sizeof(g_aclrDxfIndexColors[0]))
 #define AI_DXF_ENTITIES_MAGIC_BLOCK "$ASSIMP_ENTITIES_MAGIC"
 
@@ -95,7 +338,7 @@ static const int GroupCode_XComp = 10;
 static const int GroupCode_YComp = 20;
 static const int GroupCode_ZComp = 30;
 
-static const aiImporterDesc desc = {
+static constexpr aiImporterDesc desc = {
     "Drawing Interchange Format (DXF) Importer",
     "",
     "",
@@ -108,14 +351,6 @@ static const aiImporterDesc desc = {
     "dxf"
 };
 
-// ------------------------------------------------------------------------------------------------
-// Constructor to be privately used by Importer
-DXFImporter::DXFImporter() = default;
-
-// ------------------------------------------------------------------------------------------------
-// Destructor, private as well
-DXFImporter::~DXFImporter() = default;
-
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 bool DXFImporter::CanRead( const std::string& filename, IOSystem* pIOHandler, bool /*checkSig*/ ) const {
@@ -135,7 +370,7 @@ void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene,
     std::shared_ptr<IOStream> file = std::shared_ptr<IOStream>( pIOHandler->Open( filename) );
 
     // Check whether we can read the file
-    if( file.get() == nullptr ) {
+    if (file == nullptr) {
         throw DeadlyImportError( "Failed to open DXF file ", filename, "");
     }
 
@@ -150,7 +385,7 @@ void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene,
     // DXF files can grow very large, so read them via the StreamReader,
     // which will choose a suitable strategy.
     file->Seek(0,aiOrigin_SET);
-    StreamReaderLE stream( file );
+    StreamReaderLE stream( std::move(file) );
 
     DXF::LineReader reader (stream);
     DXF::FileData output;
@@ -228,7 +463,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) {
         ASSIMP_LOG_VERBOSE_DEBUG("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount);
     }
 
-    if (! output.blocks.size()  ) {
+    if (output.blocks.empty()) {
         throw DeadlyImportError("DXF: no data blocks loaded");
     }
 
@@ -370,7 +605,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
                 ASSIMP_LOG_ERROR("DXF: PolyLine instance is nullptr, skipping.");
                 continue;
             }
-            
+
             std::shared_ptr<DXF::PolyLine> pl_out = std::shared_ptr<DXF::PolyLine>(new DXF::PolyLine(*pl_in));
 
             if (bl_src.base.Length() || insert.scale.x!=1.f || insert.scale.y!=1.f || insert.scale.z!=1.f || insert.angle || insert.pos.Length()) {
@@ -378,8 +613,12 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
                 // XXX order
                 aiMatrix4x4 trafo, tmp;
                 aiMatrix4x4::Translation(-bl_src.base,trafo);
-                trafo *= aiMatrix4x4::Scaling(insert.scale,tmp);
+                //Need to translate position before scaling the insert
+                //otherwise the position ends up being the position*scaling
+                //STH 2024.01.17
                 trafo *= aiMatrix4x4::Translation(insert.pos,tmp);
+                trafo *= aiMatrix4x4::Scaling(insert.scale,tmp);
+                //trafo *= aiMatrix4x4::Translation(insert.pos,tmp);
 
                 // XXX rotation currently ignored - I didn't find an appropriate sample model.
                 if (insert.angle != 0.f) {
@@ -586,10 +825,11 @@ void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output)
     }
 }
 
-#define DXF_POLYLINE_FLAG_CLOSED        0x1
-#define DXF_POLYLINE_FLAG_3D_POLYLINE   0x8
-#define DXF_POLYLINE_FLAG_3D_POLYMESH   0x10
-#define DXF_POLYLINE_FLAG_POLYFACEMESH  0x40
+static constexpr unsigned int DXF_POLYLINE_FLAG_CLOSED = 0x1;
+// Currently unused
+//static constexpr unsigned int DXF_POLYLINE_FLAG_3D_POLYLINE = 0x8;
+//static constexpr unsigned int DXF_POLYLINE_FLAG_3D_POLYMESH = 0x10;
+static constexpr unsigned int DXF_POLYLINE_FLAG_POLYFACEMESH = 0x40;
 
 // ------------------------------------------------------------------------------------------------
 void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) {
@@ -638,12 +878,6 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
         reader++;
     }
 
-    //if (!(line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH))   {
-    //  DefaultLogger::get()->warn((Formatter::format("DXF: polyline not currently supported: "),line.flags));
-    //  output.blocks.back().lines.pop_back();
-    //  return;
-    //}
-
     if (vguess && line.positions.size() != vguess) {
         ASSIMP_LOG_WARN("DXF: unexpected vertex count in polymesh: ",
             line.positions.size(),", expected ", vguess );
@@ -733,12 +967,18 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li
         case 71:
         case 72:
         case 73:
-        case 74:
-            if (cnti == 4) {
-                ASSIMP_LOG_WARN("DXF: more than 4 indices per face not supported; ignoring");
-                break;
+        case 74: {
+                if (cnti == 4) {
+                    ASSIMP_LOG_WARN("DXF: more than 4 indices per face not supported; ignoring");
+                    break;
+                }
+                const int index = reader.ValueAsSignedInt();
+                if (index >= 0) {
+                    indices[cnti++] = static_cast<unsigned int>(index);
+                } else {
+                    indices[cnti++] = static_cast<unsigned int>(-index);
+                }
             }
-            indices[cnti++] = reader.ValueAsUnsignedInt();
             break;
 
         // color
@@ -776,8 +1016,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li
 }
 
 // ------------------------------------------------------------------------------------------------
-void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output)
-{
+void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output) {
     // (note) this is also used for for parsing line entities, so we
     // must handle the vertex_count == 2 case as well.
 
@@ -794,8 +1033,7 @@ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output)
         if (reader.GroupCode() == 0) {
             break;
         }
-        switch (reader.GroupCode())
-        {
+        switch (reader.GroupCode()) {
 
         // 8 specifies the layer
         case 8:

+ 3 - 3
Engine/lib/assimp/code/AssetLib/DXF/DXFLoader.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -68,8 +68,8 @@ namespace DXF {
  */
 class DXFImporter : public BaseImporter {
 public:
-    DXFImporter();
-    ~DXFImporter() override;
+    DXFImporter() = default;
+    ~DXFImporter() override = default;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.

+ 1 - 1
Engine/lib/assimp/code/AssetLib/FBX/FBXAnimation.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 7 - 7
Engine/lib/assimp/code/AssetLib/FBX/FBXBinaryTokenizer.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "FBXUtil.h"
 #include <assimp/defs.h>
 #include <stdint.h>
+#include <cstdint>
 #include <assimp/Exceptional.h>
 #include <assimp/ByteSwapper.h>
 #include <assimp/DefaultLogger.hpp>
@@ -139,6 +140,7 @@ size_t Offset(const char* begin, const char* cursor) {
 }
 
 // ------------------------------------------------------------------------------------------------
+AI_WONT_RETURN void TokenizeError(const std::string& message, const char* begin, const char* cursor) AI_WONT_RETURN_SUFFIX;
 void TokenizeError(const std::string& message, const char* begin, const char* cursor) {
     TokenizeError(message, Offset(begin, cursor));
 }
@@ -341,8 +343,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
 
 
 // ------------------------------------------------------------------------------------------------
-bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, bool const is64bits)
-{
+bool ReadScope(TokenList &output_tokens, StackAllocator &token_allocator, const char *input, const char *&cursor, const char *end, bool const is64bits) {
     // the first word contains the offset at which this block ends
 	const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
 
@@ -408,7 +409,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
 
         // XXX this is vulnerable to stack overflowing ..
         while(Offset(input, cursor) < end_offset - sentinel_block_length) {
-			ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits);
+            ReadScope(output_tokens, token_allocator, input, cursor, input + end_offset - sentinel_block_length, is64bits);
         }
         output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
 
@@ -431,8 +432,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
 
 // ------------------------------------------------------------------------------------------------
 // TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
-void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
-{
+void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length, StackAllocator &token_allocator) {
 	ai_assert(input);
 	ASSIMP_LOG_DEBUG("Tokenizing binary FBX file");
 
@@ -465,7 +465,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
     try
     {
         while (cursor < end ) {
-		    if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
+            if (!ReadScope(output_tokens, token_allocator, input, cursor, input + length, is64bits)) {
                 break;
             }
         }

+ 2 - 1
Engine/lib/assimp/code/AssetLib/FBX/FBXCommon.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -55,6 +55,7 @@ const char NULL_RECORD[NumNullRecords] = { // 25 null bytes in 64-bit and 13 nul
     '\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?)
+static std::string NULL_RECORD_STRING(NumNullRecords, '\0');
 const std::string SEPARATOR = { '\x00', '\x01' }; // for use inside strings
 const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
 const int64_t SECOND = 46186158000; // FBX's kTime unit

+ 1 - 1
Engine/lib/assimp/code/AssetLib/FBX/FBXCompileConfig.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 142 - 57
Engine/lib/assimp/code/AssetLib/FBX/FBXConverter.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -55,9 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/MathFunctions.h>
 #include <assimp/StringComparison.h>
-
 #include <assimp/scene.h>
-
 #include <assimp/CreateAnimMesh.h>
 #include <assimp/StringUtils.h>
 #include <assimp/commonMetaData.h>
@@ -78,6 +76,53 @@ using namespace Util;
 
 #define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000LL
 
+static void correctRootTransform(const aiScene *scene) {
+    if (scene == nullptr) {
+        return;
+    }
+
+    if (scene->mMetaData == nullptr) {
+        return;
+    }
+
+    int32_t UpAxis = 1, UpAxisSign = 1, FrontAxis = 2, FrontAxisSign = 1, CoordAxis = 0, CoordAxisSign = 1;
+    double UnitScaleFactor = 1.0;
+    for (unsigned MetadataIndex = 0; MetadataIndex < scene->mMetaData->mNumProperties; ++MetadataIndex) {
+        if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UpAxis") == 0) {
+            scene->mMetaData->Get<int32_t>(MetadataIndex, UpAxis);
+        }
+        if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UpAxisSign") == 0) {
+            scene->mMetaData->Get<int32_t>(MetadataIndex, UpAxisSign);
+        }
+        if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "FrontAxis") == 0) {
+            scene->mMetaData->Get<int32_t>(MetadataIndex, FrontAxis);
+        }
+        if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "FrontAxisSign") == 0) {
+            scene->mMetaData->Get<int32_t>(MetadataIndex, FrontAxisSign);
+        }
+        if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "CoordAxis") == 0) {
+            scene->mMetaData->Get<int32_t>(MetadataIndex, CoordAxis);
+        }
+        if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "CoordAxisSign") == 0) {
+            scene->mMetaData->Get<int32_t>(MetadataIndex, CoordAxisSign);
+        }
+        if (strcmp(scene->mMetaData->mKeys[MetadataIndex].C_Str(), "UnitScaleFactor") == 0) {
+            scene->mMetaData->Get<double>(MetadataIndex, UnitScaleFactor);
+        }
+    }
+
+    aiVector3D upVec, forwardVec, rightVec;
+    upVec[UpAxis] = UpAxisSign * static_cast<float>(UnitScaleFactor);
+    forwardVec[FrontAxis] = FrontAxisSign * static_cast<float>(UnitScaleFactor);
+    rightVec[CoordAxis] = CoordAxisSign * (float)UnitScaleFactor;
+
+    aiMatrix4x4 mat(rightVec.x, rightVec.y, rightVec.z, 0.0f,
+                    upVec.x, upVec.y, upVec.z, 0.0f,
+                    forwardVec.x, forwardVec.y, forwardVec.z, 0.0f,
+                    0.0f, 0.0f, 0.0f, 1.0f);
+    scene->mRootNode->mTransformation *= mat;
+}
+
 FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBones) :
         defaultMaterialIndex(),
         mMeshes(),
@@ -93,6 +138,8 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
         mSceneOut(out),
         doc(doc),
         mRemoveEmptyBones(removeEmptyBones) {
+
+
     // animations need to be converted first since this will
     // populate the node_anim_chain_bits map, which is needed
     // to determine which nodes need to be generated.
@@ -119,7 +166,7 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
             if (mat) {
 
                 if (materials_converted.find(mat) == materials_converted.end()) {
-                    ConvertMaterial(*mat, 0);
+                    ConvertMaterial(*mat, nullptr);
                 }
             }
         }
@@ -133,6 +180,10 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
     // need not contain geometry (i.e. camera animations, raw armatures).
     if (out->mNumMeshes == 0) {
         out->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+    } else {
+        // Apply the FBX axis metadata unless requested not to
+        if (!doc.Settings().ignoreUpDirection)
+            correctRootTransform(mSceneOut);
     }
 }
 
@@ -196,7 +247,7 @@ struct FBXConverter::PotentialNode {
 /// todo: get bone from stack
 /// todo: make map of aiBone* to aiNode*
 /// then update convert clusters to the new format
-void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node) {
+void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node, const aiMatrix4x4& parent_transform) {
     const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(id, "Model");
 
     std::vector<PotentialNode> nodes;
@@ -227,7 +278,7 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
         if (nullptr != model) {
             nodes_chain.clear();
             post_nodes_chain.clear();
-            aiMatrix4x4 new_abs_transform = parent->mTransformation;
+            aiMatrix4x4 new_abs_transform = parent_transform;
             std::string node_name = FixNodeName(model->Name());
             // even though there is only a single input node, the design of
             // assimp (or rather: the complicated transformation chain that
@@ -261,6 +312,8 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
 
                 child->mParent = last_parent;
                 last_parent = child.mNode;
+
+                new_abs_transform *= child->mTransformation;
             }
 
             // attach geometry
@@ -283,6 +336,8 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
 
                     postnode->mParent = last_parent;
                     last_parent = postnode.mNode;
+
+                    new_abs_transform *= postnode->mTransformation;
                 }
             } else {
                 // free the nodes we allocated as we don't need them
@@ -290,7 +345,7 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
             }
 
             // recursion call - child nodes
-            ConvertNodes(model->ID(), last_parent, root_node);
+            ConvertNodes(model->ID(), last_parent, root_node, new_abs_transform);
 
             if (doc.Settings().readLights) {
                 ConvertLights(*model, node_name);
@@ -305,18 +360,15 @@ void FBXConverter::ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node)
         }
     }
 
-    if (nodes.size()) {
+    if (nodes.empty()) {
+        parent->mNumChildren = 0;
+        parent->mChildren = nullptr;
+    } else {
         parent->mChildren = new aiNode *[nodes.size()]();
         parent->mNumChildren = static_cast<unsigned int>(nodes.size());
-
-        for (unsigned int i = 0; i < nodes.size(); ++i)
-        {
+        for (unsigned int i = 0; i < nodes.size(); ++i) {
             parent->mChildren[i] = nodes[i].mOwnership.release();
         }
-        nodes.clear();
-    } else {
-        parent->mNumChildren = 0;
-        parent->mChildren = nullptr;
     }
 }
 
@@ -424,16 +476,32 @@ void FBXConverter::ConvertCamera(const Camera &cam, const std::string &orig_name
 
     out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
 
+    // NOTE: Camera mPosition, mLookAt and mUp must be set to default here.
+    // All transformations to the camera will be handled by its node in the scenegraph.
     out_camera->mPosition = aiVector3D(0.0f);
     out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
     out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
 
-    out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
-
-    out_camera->mClipPlaneNear = cam.NearPlane();
-    out_camera->mClipPlaneFar = cam.FarPlane();
+    // NOTE: Some software (maya) does not put FieldOfView in FBX, so we compute
+    // mHorizontalFOV from FocalLength and FilmWidth with unit conversion.
+
+    // TODO: This is not a complete solution for how FBX cameras can be stored.
+    // TODO: Incorporate non-square pixel aspect ratio.
+    // TODO: FBX aperture mode might be storing vertical FOV in need of conversion with aspect ratio.
+
+    float fov_deg = cam.FieldOfView();
+    // If FOV not specified in file, compute using FilmWidth and FocalLength.
+    if (fov_deg == kFovUnknown) {
+        float film_width_inches = cam.FilmWidth();
+        float focal_length_mm = cam.FocalLength();
+        ASSIMP_LOG_VERBOSE_DEBUG("FBX FOV unspecified. Computing from FilmWidth (", film_width_inches, "inches) and FocalLength (", focal_length_mm, "mm).");
+        double half_fov_rad = std::atan2(film_width_inches * 25.4 * 0.5, focal_length_mm);
+        out_camera->mHorizontalFOV = static_cast<float>(half_fov_rad);
+    } else {
+        // FBX fov is full-view degrees. We want half-view radians.
+        out_camera->mHorizontalFOV = AI_DEG_TO_RAD(fov_deg) * 0.5f;
+    }
 
-    out_camera->mHorizontalFOV = AI_DEG_TO_RAD(cam.FieldOfView());
     out_camera->mClipPlaneNear = cam.NearPlane();
     out_camera->mClipPlaneFar = cam.FarPlane();
 }
@@ -562,16 +630,17 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
     bool is_id[3] = { true, true, true };
 
     aiMatrix4x4 temp[3];
-    if (std::fabs(rotation.z) > angle_epsilon) {
-        aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]);
+    const auto rot = AI_DEG_TO_RAD(rotation);
+    if (std::fabs(rot.z) > angle_epsilon) {
+        aiMatrix4x4::RotationZ(rot.z, temp[2]);
         is_id[2] = false;
     }
-    if (std::fabs(rotation.y) > angle_epsilon) {
-        aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]);
+    if (std::fabs(rot.y) > angle_epsilon) {
+        aiMatrix4x4::RotationY(rot.y, temp[1]);
         is_id[1] = false;
     }
-    if (std::fabs(rotation.x) > angle_epsilon) {
-        aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]);
+    if (std::fabs(rot.x) > angle_epsilon) {
+        aiMatrix4x4::RotationX(rot.x, temp[0]);
         is_id[0] = false;
     }
 
@@ -643,13 +712,12 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
 bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
     const PropertyTable &props = model.Props();
 
-    const auto zero_epsilon = ai_epsilon;
+    const auto zero_epsilon = Math::getEpsilon<ai_real>();
     const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
     for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
         const TransformationComp comp = static_cast<TransformationComp>(i);
 
-        if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation ||
-            comp == TransformationComp_PreRotation || comp == TransformationComp_PostRotation) {
+        if (comp == TransformationComp_Rotation || comp == TransformationComp_Scaling || comp == TransformationComp_Translation) {
             continue;
         }
 
@@ -876,8 +944,12 @@ void FBXConverter::SetupNodeMetadata(const Model &model, aiNode &nd) {
             data->Set(index++, prop.first, interpretedBool->Value());
         } else if (const TypedProperty<int> *interpretedInt = prop.second->As<TypedProperty<int>>()) {
             data->Set(index++, prop.first, interpretedInt->Value());
+        } else if (const TypedProperty<uint32_t> *interpretedUInt = prop.second->As<TypedProperty<uint32_t>>()) {
+            data->Set(index++, prop.first, interpretedUInt->Value());
         } else if (const TypedProperty<uint64_t> *interpretedUint64 = prop.second->As<TypedProperty<uint64_t>>()) {
             data->Set(index++, prop.first, interpretedUint64->Value());
+        } else if (const TypedProperty<int64_t> *interpretedint64 = prop.second->As<TypedProperty<int64_t>>()) {
+            data->Set(index++, prop.first, interpretedint64->Value());
         } else if (const TypedProperty<float> *interpretedFloat = prop.second->As<TypedProperty<float>>()) {
             data->Set(index++, prop.first, interpretedFloat->Value());
         } else if (const TypedProperty<std::string> *interpretedString = prop.second->As<TypedProperty<std::string>>()) {
@@ -1179,19 +1251,27 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
     std::vector<aiAnimMesh *> animMeshes;
     for (const BlendShape *blendShape : mesh.GetBlendShapes()) {
         for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) {
-            const std::vector<const ShapeGeometry *> &shapeGeometries = blendShapeChannel->GetShapeGeometries();
-            for (size_t i = 0; i < shapeGeometries.size(); i++) {
-                aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
-                const ShapeGeometry *shapeGeometry = shapeGeometries.at(i);
-                const std::vector<aiVector3D> &curVertices = shapeGeometry->GetVertices();
-                const std::vector<aiVector3D> &curNormals = shapeGeometry->GetNormals();
-                const std::vector<unsigned int> &curIndices = shapeGeometry->GetIndices();
+            const auto& shapeGeometries = blendShapeChannel->GetShapeGeometries();
+            for (const ShapeGeometry *shapeGeometry : shapeGeometries) {
+                const auto &curNormals = shapeGeometry->GetNormals();
+                aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh, true, !curNormals.empty());
+                const auto &curVertices = shapeGeometry->GetVertices();
+                const auto &curIndices = shapeGeometry->GetIndices();
                 //losing channel name if using shapeGeometry->Name()
-                animMesh->mName.Set(FixAnimMeshName(blendShapeChannel->Name()));
+                // if blendShapeChannel Name is empty or doesn't have a ".", add geoMetryName;
+                auto aniName = FixAnimMeshName(blendShapeChannel->Name());
+                auto geoMetryName = FixAnimMeshName(shapeGeometry->Name());
+                if (aniName.empty()) {
+                    aniName = geoMetryName;
+                }
+                else if (aniName.find('.') == aniName.npos) {
+                    aniName += "." + geoMetryName;
+                }
+                animMesh->mName.Set(aniName);
                 for (size_t j = 0; j < curIndices.size(); j++) {
                     const unsigned int curIndex = curIndices.at(j);
                     aiVector3D vertex = curVertices.at(j);
-                    aiVector3D normal = curNormals.at(j);
+                    aiVector3D normal = curNormals.empty() ? aiVector3D() : curNormals.at(j);
                     unsigned int count = 0;
                     const unsigned int *outIndices = mesh.ToOutputVertexIndex(curIndex, count);
                     for (unsigned int k = 0; k < count; k++) {
@@ -1409,18 +1489,17 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
     std::vector<aiAnimMesh *> animMeshes;
     for (const BlendShape *blendShape : mesh.GetBlendShapes()) {
         for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) {
-            const std::vector<const ShapeGeometry *> &shapeGeometries = blendShapeChannel->GetShapeGeometries();
-            for (size_t i = 0; i < shapeGeometries.size(); i++) {
-                aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
-                const ShapeGeometry *shapeGeometry = shapeGeometries.at(i);
-                const std::vector<aiVector3D> &curVertices = shapeGeometry->GetVertices();
-                const std::vector<aiVector3D> &curNormals = shapeGeometry->GetNormals();
-                const std::vector<unsigned int> &curIndices = shapeGeometry->GetIndices();
+            const auto& shapeGeometries = blendShapeChannel->GetShapeGeometries();
+            for (const ShapeGeometry *shapeGeometry : shapeGeometries) {
+                const auto& curNormals = shapeGeometry->GetNormals();
+                aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh, true, !curNormals.empty());
+                const auto& curVertices = shapeGeometry->GetVertices();
+                const auto& curIndices = shapeGeometry->GetIndices();
                 animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name()));
                 for (size_t j = 0; j < curIndices.size(); j++) {
                     unsigned int curIndex = curIndices.at(j);
                     aiVector3D vertex = curVertices.at(j);
-                    aiVector3D normal = curNormals.at(j);
+                    aiVector3D normal = curNormals.empty() ? aiVector3D() : curNormals.at(j);
                     unsigned int count = 0;
                     const unsigned int *outIndices = mesh.ToOutputVertexIndex(curIndex, count);
                     for (unsigned int k = 0; k < count; k++) {
@@ -1458,7 +1537,9 @@ static void copyBoneToSkeletonBone(aiMesh *mesh, aiBone *bone, aiSkeletonBone *s
     skeletonBone->mWeights = bone->mWeights;
     skeletonBone->mOffsetMatrix = bone->mOffsetMatrix;
     skeletonBone->mMeshId = mesh;
+#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
     skeletonBone->mNode = bone->mNode;
+#endif
     skeletonBone->mParent = -1;
 }
 
@@ -1566,7 +1647,7 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
         out->mBones = nullptr;
         out->mNumBones = 0;
         return;
-    } 
+    }
 
     out->mBones = new aiBone *[bones.size()]();
     out->mNumBones = static_cast<unsigned int>(bones.size());
@@ -1575,7 +1656,7 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
 
 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> &count_out_indices, const aiMatrix4x4 & /* absolute_transform*/,
+        std::vector<size_t> &count_out_indices, const aiMatrix4x4 &absolute_transform,
         aiNode *) {
     ai_assert(cluster != nullptr); // make sure cluster valid
 
@@ -1592,16 +1673,16 @@ void FBXConverter::ConvertCluster(std::vector<aiBone*> &local_mesh_bones, const
         bone = new aiBone();
         bone->mName = bone_name;
 
-        bone->mOffsetMatrix = cluster->Transform();
+        //bone->mOffsetMatrix = cluster->Transform();
         // store local transform link for post processing
-        /*
+
         bone->mOffsetMatrix = cluster->TransformLink();
         bone->mOffsetMatrix.Inverse();
 
-        aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
+        const aiMatrix4x4 matrix = (aiMatrix4x4)absolute_transform;
 
         bone->mOffsetMatrix = bone->mOffsetMatrix * matrix; // * mesh_offset
-        */
+
         //
         // Now calculate the aiVertexWeights
         //
@@ -1784,7 +1865,7 @@ aiString FBXConverter::GetTexturePath(const Texture *tex) {
                 // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
                 // This may occur on this case too, it has to be studied
                 path.data[0] = '*';
-                path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
+                path.length = 1 + ASSIMP_itoa10(path.data + 1, AI_MAXLEN - 1, index);
             }
         }
     }
@@ -2052,6 +2133,10 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_
     TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor", aiTextureType_EMISSION_COLOR, mesh);
     TrySetTextureProperties(out_mat, _textures, "Maya|metalness", aiTextureType_METALNESS, mesh);
     TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|base", aiTextureType_MAYA_BASE, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|specular", aiTextureType_MAYA_SPECULAR, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|specularColor", aiTextureType_MAYA_SPECULAR_COLOR, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|specularRoughness", aiTextureType_MAYA_SPECULAR_ROUGHNESS, mesh);
 
     // Maya stingray
     TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map", aiTextureType_BASE_COLOR, mesh);
@@ -2364,7 +2449,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
 
                 // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
                 path.data[0] = '*';
-                path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
+                path.length = 1 + ASSIMP_itoa10(path.data + 1, AI_MAXLEN - 1, index);
             }
 
             out_mat->AddProperty(&path, (name + "|file").c_str(), aiTextureType_UNKNOWN, 0);
@@ -2730,7 +2815,7 @@ void FBXConverter::ProcessMorphAnimDatas(std::map<std::string, morphAnimData *>
                                 auto geoIt = std::find(model->GetGeometry().begin(), model->GetGeometry().end(), geo);
                                 auto geoIndex = static_cast<unsigned int>(std::distance(model->GetGeometry().begin(), geoIt));
                                 auto name = aiString(FixNodeName(model->Name() + "*"));
-                                name.length = 1 + ASSIMP_itoa10(name.data + name.length, MAXLEN - 1, geoIndex);
+                                name.length = 1 + ASSIMP_itoa10(name.data + name.length, AI_MAXLEN - 1, geoIndex);
                                 morphAnimData *animData;
                                 auto animIt = morphAnimDatas->find(name.C_Str());
                                 if (animIt == morphAnimDatas->end()) {
@@ -3197,7 +3282,6 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
     aiVector3D defTranslate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f));
     aiVector3D defRotation = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f));
     aiVector3D defScale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f));
-    aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder);
 
     aiVectorKey* outTranslations = new aiVectorKey[keyCount];
     aiQuatKey* outRotations = new aiQuatKey[keyCount];
@@ -3215,6 +3299,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
     if (keyframeLists[TransformationComp_Rotation].size() > 0) {
         InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder);
     } else {
+        aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder);
         for (size_t i = 0; i < keyCount; ++i) {
             outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
             outRotations[i].mValue = defQuat;
@@ -3231,7 +3316,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
     }
 
     bool ok = false;
-    
+
     const auto zero_epsilon = ai_epsilon;
 
     const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);

+ 2 - 2
Engine/lib/assimp/code/AssetLib/FBX/FBXConverter.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.
@@ -134,7 +134,7 @@ private:
 
     // ------------------------------------------------------------------------------------------------
     // collect and assign child nodes
-    void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node);
+    void ConvertNodes(uint64_t id, aiNode *parent, aiNode *root_node, const aiMatrix4x4& parent_transform = aiMatrix4x4());
 
     // ------------------------------------------------------------------------------------------------
     void ConvertLights(const Model& model, const std::string &orig_name );

+ 10 - 6
Engine/lib/assimp/code/AssetLib/FBX/FBXDeformer.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -84,7 +84,7 @@ Cluster::Cluster(uint64_t id, const Element& element, const Document& doc, const
     transform = ReadMatrix(Transform);
     transformLink = ReadMatrix(TransformLink);
 
-    // it is actually possible that there be Deformer's with no weights
+    // it is actually possible that there are Deformer's with no weights
     if (!!Indexes != !!Weights) {
         DOMError("either Indexes or Weights are missing from Cluster",&element);
     }
@@ -154,8 +154,10 @@ BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc,
     for (const Connection* con : conns) {
         const BlendShapeChannel* const bspc = ProcessSimpleConnection<BlendShapeChannel>(*con, false, "BlendShapeChannel -> BlendShape", element);
         if (bspc) {
-            blendShapeChannels.push_back(bspc);
-            continue;
+            auto pr = blendShapeChannels.insert(bspc);
+            if (!pr.second) {
+                FBXImporter::LogWarn("there is the same blendShapeChannel id ", bspc->ID());
+            }
         }
     }
 }
@@ -179,8 +181,10 @@ BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const
     for (const Connection* con : conns) {
         const ShapeGeometry* const sg = ProcessSimpleConnection<ShapeGeometry>(*con, false, "Shape -> BlendShapeChannel", element);
         if (sg) {
-            shapeGeometries.push_back(sg);
-            continue;
+            auto pr = shapeGeometries.insert(sg);
+            if (!pr.second) {
+                FBXImporter::LogWarn("there is the same shapeGeometrie id ", sg->ID());
+            }
         }
     }
 }

+ 34 - 16
Engine/lib/assimp/code/AssetLib/FBX/FBXDocument.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -78,7 +78,7 @@ const Object* LazyObject::Get(bool dieOnError) {
         return nullptr;
     }
 
-    if (object.get()) {
+    if (object) {
         return object.get();
     }
 
@@ -199,6 +199,14 @@ const Object* LazyObject::Get(bool dieOnError) {
             object.reset(new AnimationCurveNode(id,element,name,doc));
         }
     }
+    catch (std::bad_alloc&) {
+        // out-of-memory is unrecoverable and should always lead to a failure
+
+        flags &= ~BEING_CONSTRUCTED;
+        flags |= FAILED_TO_CONSTRUCT;
+
+        throw;
+    }
     catch(std::exception& ex) {
         flags &= ~BEING_CONSTRUCTED;
         flags |= FAILED_TO_CONSTRUCT;
@@ -214,7 +222,7 @@ const Object* LazyObject::Get(bool dieOnError) {
         return nullptr;
     }
 
-    if (!object.get()) {
+    if (!object) {
         //DOMError("failed to convert element to DOM object, class: " + classtag + ", name: " + name,&element);
     }
 
@@ -235,7 +243,7 @@ FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr<cons
 }
 
 // ------------------------------------------------------------------------------------------------
-Document::Document(const Parser& parser, const ImportSettings& settings) :
+Document::Document(Parser& parser, const ImportSettings& settings) :
      settings(settings), parser(parser) {
 	ASSIMP_LOG_DEBUG("Creating FBX Document");
 
@@ -257,13 +265,17 @@ Document::Document(const Parser& parser, const ImportSettings& settings) :
 }
 
 // ------------------------------------------------------------------------------------------------
-Document::~Document() {
-    for(ObjectMap::value_type& v : objects) {
-        delete v.second;
+Document::~Document()
+{
+	// The document does not own the memory for the following objects, but we need to call their d'tor
+	// so they can properly free memory like string members:
+	
+    for (ObjectMap::value_type &v : objects) {
+        delete_LazyObject(v.second);
     }
 
-    for(ConnectionMap::value_type& v : src_connections) {
-        delete v.second;
+    for (ConnectionMap::value_type &v : src_connections) {
+        delete_Connection(v.second);
     }
     // |dest_connections| contain the same Connection objects as the |src_connections|
 }
@@ -336,7 +348,7 @@ void Document::ReadGlobalSettings() {
         DOMError("GlobalSettings dictionary contains no property table");
     }
 
-    globals.reset(new FileGlobalSettings(*this, props));
+    globals.reset(new FileGlobalSettings(*this, std::move(props)));
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -348,9 +360,11 @@ void Document::ReadObjects() {
         DOMError("no Objects dictionary found");
     }
 
+    StackAllocator &allocator = parser.GetAllocator();
+
     // add a dummy entry to represent the Model::RootNode object (id 0),
     // which is only indirectly defined in the input file
-    objects[0] = new LazyObject(0L, *eobjects, *this);
+    objects[0] = new_LazyObject(0L, *eobjects, *this);
 
     const Scope& sobjects = *eobjects->Compound();
     for(const ElementMap::value_type& el : sobjects.Elements()) {
@@ -373,11 +387,13 @@ void Document::ReadObjects() {
             DOMError("encountered object with implicitly defined id 0",el.second);
         }
 
-        if(objects.find(id) != objects.end()) {
+        const auto foundObject = objects.find(id);
+        if(foundObject != objects.end()) {
             DOMWarning("encountered duplicate object id, ignoring first occurrence",el.second);
+            delete_LazyObject(foundObject->second);
         }
 
-        objects[id] = new LazyObject(id, *el.second, *this);
+        objects[id] = new_LazyObject(id, *el.second, *this);
 
         // grab all animation stacks upfront since there is no listing of them
         if(!strcmp(el.first.c_str(),"AnimationStack")) {
@@ -444,8 +460,10 @@ void Document::ReadPropertyTemplates() {
 }
 
 // ------------------------------------------------------------------------------------------------
-void Document::ReadConnections() {
-    const Scope& sc = parser.GetRootScope();
+void Document::ReadConnections()
+{
+    StackAllocator &allocator = parser.GetAllocator();
+    const Scope &sc = parser.GetRootScope();
     // read property templates from "Definitions" section
     const Element* const econns = sc["Connections"];
     if(!econns || !econns->Compound()) {
@@ -484,7 +502,7 @@ void Document::ReadConnections() {
         }
 
         // add new connection
-        const Connection* const c = new Connection(insertionOrder++,src,dest,prop,*this);
+        const Connection* const c = new_Connection(insertionOrder++,src,dest,prop,*this);
         src_connections.insert(ConnectionMap::value_type(src,c));
         dest_connections.insert(ConnectionMap::value_type(dest,c));
     }

+ 30 - 20
Engine/lib/assimp/code/AssetLib/FBX/FBXDocument.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_FBX_DOCUMENT_H
 
 #include <numeric>
+#include <unordered_set>
 #include <stdint.h>
 #include <assimp/mesh.h>
 #include "FBXProperties.h"
@@ -54,9 +55,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define _AI_CONCAT(a,b)  a ## b
 #define  AI_CONCAT(a,b)  _AI_CONCAT(a,b)
 
+
 namespace Assimp {
 namespace FBX {
 
+// Use an 'illegal' default FOV value to detect if the FBX camera has set the FOV.
+static const float kFovUnknown = -1.0f;
+
+
 class Parser;
 class Object;
 struct ImportSettings;
@@ -80,6 +86,10 @@ class BlendShape;
 class Skin;
 class Cluster;
 
+#define new_LazyObject new (allocator.Allocate(sizeof(LazyObject))) LazyObject
+#define new_Connection new (allocator.Allocate(sizeof(Connection))) Connection
+#define delete_LazyObject(_p) (_p)->~LazyObject()
+#define delete_Connection(_p) (_p)->~Connection()
 
 /** Represents a delay-parsed FBX objects. Many objects in the scene
  *  are not needed by assimp, so it makes no sense to parse them
@@ -168,7 +178,7 @@ public:
 
     const PropertyTable& Props() const {
         ai_assert(props.get());
-        return *props.get();
+        return *props;
     }
 
 private:
@@ -242,7 +252,7 @@ public:
     fbx_simple_property(FilmAspectRatio, float, 1.0f)
     fbx_simple_property(ApertureMode, int, 0)
 
-    fbx_simple_property(FieldOfView, float, 1.0f)
+    fbx_simple_property(FieldOfView, float, kFovUnknown)
     fbx_simple_property(FocalLength, float, 1.0f)
 };
 
@@ -432,7 +442,7 @@ public:
 
     const PropertyTable& Props() const {
         ai_assert(props.get());
-        return *props.get();
+        return *props;
     }
 
     /** Get material links */
@@ -503,7 +513,7 @@ public:
 
     const PropertyTable& Props() const {
         ai_assert(props.get());
-        return *props.get();
+        return *props;
     }
 
     // return a 4-tuple
@@ -618,7 +628,7 @@ public:
 
     const PropertyTable& Props() const {
         ai_assert(props.get());
-        return *props.get();
+        return *props;
     }
 
     const uint8_t* Content() const {
@@ -632,7 +642,7 @@ public:
 
     uint8_t* RelinquishContent() {
         uint8_t* ptr = content;
-        content = 0;
+        content = nullptr;
         return ptr;
     }
 
@@ -663,7 +673,7 @@ public:
 
     const PropertyTable& Props() const {
         ai_assert(props.get());
-        return *props.get();
+        return *props;
     }
 
     const TextureMap& Textures() const {
@@ -735,7 +745,7 @@ public:
 
     const PropertyTable& Props() const {
         ai_assert(props.get());
-        return *props.get();
+        return *props;
     }
 
 
@@ -780,7 +790,7 @@ public:
 
     const PropertyTable& Props() const {
         ai_assert(props.get());
-        return *props.get();
+        return *props;
     }
 
     /* the optional white list specifies a list of property names for which the caller
@@ -808,7 +818,7 @@ public:
 
     const PropertyTable& Props() const {
         ai_assert(props.get());
-        return *props.get();
+        return *props;
     }
 
     const AnimationLayerList& Layers() const {
@@ -829,7 +839,7 @@ public:
 
     const PropertyTable& Props() const {
         ai_assert(props.get());
-        return *props.get();
+        return *props;
     }
 
 private:
@@ -855,14 +865,14 @@ public:
         return fullWeights;
     }
 
-    const std::vector<const ShapeGeometry*>& GetShapeGeometries() const {
+    const std::unordered_set<const ShapeGeometry*>& GetShapeGeometries() const {
         return shapeGeometries;
     }
 
 private:
     float percent;
     WeightArray fullWeights;
-    std::vector<const ShapeGeometry*> shapeGeometries;
+    std::unordered_set<const ShapeGeometry*> shapeGeometries;
 };
 
 /** DOM class for BlendShape deformers */
@@ -872,12 +882,12 @@ public:
 
     virtual ~BlendShape();
 
-    const std::vector<const BlendShapeChannel*>& BlendShapeChannels() const {
+    const std::unordered_set<const BlendShapeChannel*>& BlendShapeChannels() const {
         return blendShapeChannels;
     }
 
 private:
-    std::vector<const BlendShapeChannel*> blendShapeChannels;
+    std::unordered_set<const BlendShapeChannel*> blendShapeChannels;
 };
 
 /** DOM class for skin deformer clusters (aka sub-deformers) */
@@ -1018,7 +1028,7 @@ public:
 
     const PropertyTable& Props() const {
         ai_assert(props.get());
-        return *props.get();
+        return *props;
     }
 
     const Document& GetDocument() const {
@@ -1072,7 +1082,7 @@ private:
 /** DOM root for a FBX file */
 class Document {
 public:
-    Document(const Parser& parser, const ImportSettings& settings);
+    Document(Parser& parser, const ImportSettings& settings);
 
     ~Document();
 
@@ -1097,7 +1107,7 @@ public:
 
     const FileGlobalSettings& GlobalSettings() const {
         ai_assert(globals.get());
-        return *globals.get();
+        return *globals;
     }
 
     const PropertyTemplateMap& Templates() const {
@@ -1156,7 +1166,7 @@ private:
     const ImportSettings& settings;
 
     ObjectMap objects;
-    const Parser& parser;
+    Parser& parser;
 
     PropertyTemplateMap templates;
     ConnectionMap src_connections;

+ 1 - 1
Engine/lib/assimp/code/AssetLib/FBX/FBXDocumentUtil.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 
 All rights reserved.

+ 2 - 3
Engine/lib/assimp/code/AssetLib/FBX/FBXDocumentUtil.h

@@ -58,12 +58,11 @@ namespace Util {
 
 /* DOM/Parse error reporting - does not return */
 AI_WONT_RETURN void DOMError(const std::string& message, const Token& token) AI_WONT_RETURN_SUFFIX;
-AI_WONT_RETURN void DOMError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
+AI_WONT_RETURN void DOMError(const std::string &message, const Element *element = nullptr) AI_WONT_RETURN_SUFFIX;
 
 // does return
 void DOMWarning(const std::string& message, const Token& token);
-void DOMWarning(const std::string& message, const Element* element = NULL);
-
+void DOMWarning(const std::string &message, const Element *element = nullptr);
 
 // fetch a property table and the corresponding property template
 std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,

+ 2 - 2
Engine/lib/assimp/code/AssetLib/FBX/FBXExportNode.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -360,7 +360,7 @@ void FBX::Node::EndBinary(
     bool has_children
 ) {
     // if there were children, add a null record
-    if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD); }
+    if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD_STRING); }
 
     // now go back and write initial pos
     this->end_pos = s.Tell();

+ 15 - 18
Engine/lib/assimp/code/AssetLib/FBX/FBXExportNode.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 
@@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/StreamWriter.h> // StreamWriterLE
 
 #include <string>
+#include <utility>
 #include <vector>
 
 namespace Assimp {
@@ -76,34 +77,30 @@ public: // constructors
     /// The class constructor with the name.
     Node(const std::string& n)
     : name(n)
-    , properties()
-    , children()
     , force_has_children( false ) {
         // empty
     }
 
     // convenience template to construct with properties directly
     template <typename... More>
-    Node(const std::string& n, const More... more)
+    Node(const std::string& n, More&&... more)
     : name(n)
-    , properties()
-    , children()
     , force_has_children(false) {
-        AddProperties(more...);
+        AddProperties(std::forward<More>(more)...);
     }
 
 public: // functions to add properties or children
     // add a single property to the node
     template <typename T>
-    void AddProperty(T value) {
-        properties.emplace_back(value);
+    void AddProperty(T&& value) {
+        properties.emplace_back(std::forward<T>(value));
     }
 
     // convenience function to add multiple properties at once
     template <typename T, typename... More>
-    void AddProperties(T value, More... more) {
-        properties.emplace_back(value);
-        AddProperties(more...);
+    void AddProperties(T&& value, More&&... more) {
+        properties.emplace_back(std::forward<T>(value));
+        AddProperties(std::forward<More>(more)...);
     }
     void AddProperties() {}
 
@@ -114,11 +111,11 @@ public: // functions to add properties or children
     template <typename... More>
     void AddChild(
         const std::string& name,
-        More... more
+        More&&... more
     ) {
         FBX::Node c(name);
-        c.AddProperties(more...);
-        children.push_back(c);
+        c.AddProperties(std::forward<More>(more)...);
+        children.push_back(std::move(c));
     }
 
 public: // support specifically for dealing with Properties70 nodes
@@ -146,10 +143,10 @@ public: // support specifically for dealing with Properties70 nodes
         const std::string& type,
         const std::string& type2,
         const std::string& flags,
-        More... more
+        More&&... more
     ) {
         Node n("P");
-        n.AddProperties(name, type, type2, flags, more...);
+        n.AddProperties(name, type, type2, flags, std::forward<More>(more)...);
         AddChild(n);
     }
 
@@ -214,7 +211,7 @@ public: // static member functions
         bool binary, int indent
     ) {
         FBX::FBXExportProperty p(value);
-        FBX::Node node(name, p);
+        FBX::Node node(name, std::move(p));
         node.Dump(s, binary, indent);
     }
 

+ 1 - 1
Engine/lib/assimp/code/AssetLib/FBX/FBXExportProperty.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

+ 1 - 1
Engine/lib/assimp/code/AssetLib/FBX/FBXExportProperty.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
+Copyright (c) 2006-2024, assimp team
 
 All rights reserved.
 

Algúns arquivos non se mostraron porque demasiados arquivos cambiaron neste cambio