Explorar el Código

Merge branch 'master' into jdumas/ziplib

Jérémie Dumas hace 4 años
padre
commit
57d22e4dbf
Se han modificado 100 ficheros con 2160 adiciones y 1750 borrados
  1. 1 0
      .github/FUNDING.yml
  2. 3 9
      .github/ISSUE_TEMPLATE/bug_report.md
  3. 1 1
      .github/ISSUE_TEMPLATE/feature_request.md
  4. 25 0
      .github/ISSUE_TEMPLATE/tech_debt.md
  5. 3 2
      .gitignore
  6. 17 14
      CMakeLists.txt
  7. 3 1
      Readme.md
  8. 0 17
      cmake-modules/FindIrrXML.cmake
  9. 0 0
      cmake-modules/HunterGate.cmake
  10. 19 0
      cmake-modules/assimp-hunter-config.cmake.in
  11. 0 0
      cmake-modules/assimp-plain-config.cmake.in
  12. 0 18
      cmake/assimp-hunter-config.cmake.in
  13. 3 8
      code/AssetLib/3DS/3DSConverter.cpp
  14. 12 6
      code/AssetLib/3DS/3DSExporter.cpp
  15. 1 1
      code/AssetLib/3DS/3DSExporter.h
  16. 40 40
      code/AssetLib/3DS/3DSHelper.h
  17. 1 1
      code/AssetLib/3DS/3DSLoader.cpp
  18. 14 5
      code/AssetLib/3DS/3DSLoader.h
  19. 165 0
      code/AssetLib/3MF/3MFTypes.h
  20. 10 2
      code/AssetLib/3MF/3MFXmlTags.h
  21. 7 4
      code/AssetLib/3MF/D3MFExporter.h
  22. 15 507
      code/AssetLib/3MF/D3MFImporter.cpp
  23. 32 6
      code/AssetLib/3MF/D3MFImporter.h
  24. 59 13
      code/AssetLib/3MF/D3MFOpcPackage.cpp
  25. 11 5
      code/AssetLib/3MF/D3MFOpcPackage.h
  26. 593 0
      code/AssetLib/3MF/XmlSerializer.cpp
  27. 52 14
      code/AssetLib/3MF/XmlSerializer.h
  28. 5 5
      code/AssetLib/AC/ACLoader.h
  29. 2 2
      code/AssetLib/AMF/AMFImporter.cpp
  30. 4 4
      code/AssetLib/AMF/AMFImporter.hpp
  31. 3 3
      code/AssetLib/AMF/AMFImporter_Geometry.cpp
  32. 4 5
      code/AssetLib/AMF/AMFImporter_Node.hpp
  33. 4 4
      code/AssetLib/AMF/AMFImporter_Postprocess.cpp
  34. 2 4
      code/AssetLib/ASE/ASELoader.cpp
  35. 5 20
      code/AssetLib/ASE/ASELoader.h
  36. 0 2
      code/AssetLib/ASE/ASEParser.cpp
  37. 4 4
      code/AssetLib/ASE/ASEParser.h
  38. 4 2
      code/AssetLib/Assbin/AssbinExporter.h
  39. 12 13
      code/AssetLib/Assbin/AssbinFileWriter.cpp
  40. 1 1
      code/AssetLib/Assbin/AssbinLoader.cpp
  41. 5 12
      code/AssetLib/Assbin/AssbinLoader.h
  42. 27 15
      code/AssetLib/Assjson/json_exporter.cpp
  43. 10 11
      code/AssetLib/Assjson/mesh_splitter.cpp
  44. 14 23
      code/AssetLib/Assjson/mesh_splitter.h
  45. 1 1
      code/AssetLib/Assxml/AssxmlExporter.cpp
  46. 1 0
      code/AssetLib/Assxml/AssxmlExporter.h
  47. 2 2
      code/AssetLib/Assxml/AssxmlFileWriter.cpp
  48. 1 2
      code/AssetLib/Assxml/AssxmlFileWriter.h
  49. 1 1
      code/AssetLib/B3D/B3DImporter.cpp
  50. 9 11
      code/AssetLib/B3D/B3DImporter.h
  51. 2 2
      code/AssetLib/BVH/BVHLoader.cpp
  52. 1 1
      code/AssetLib/BVH/BVHLoader.h
  53. 1 1
      code/AssetLib/Blender/BlenderDNA.h
  54. 3 3
      code/AssetLib/Blender/BlenderLoader.cpp
  55. 94 104
      code/AssetLib/Blender/BlenderLoader.h
  56. 9 9
      code/AssetLib/Blender/BlenderModifier.h
  57. 6 0
      code/AssetLib/C4D/C4DImporter.cpp
  58. 6 6
      code/AssetLib/COB/COBLoader.cpp
  59. 55 59
      code/AssetLib/COB/COBLoader.h
  60. 4 5
      code/AssetLib/COB/COBScene.h
  61. 1 1
      code/AssetLib/CSM/CSMLoader.cpp
  62. 11 15
      code/AssetLib/CSM/CSMLoader.h
  63. 15 11
      code/AssetLib/Collada/ColladaLoader.cpp
  64. 114 125
      code/AssetLib/Collada/ColladaParser.cpp
  65. 1 0
      code/AssetLib/Collada/ColladaParser.h
  66. 8 10
      code/AssetLib/DXF/DXFLoader.cpp
  67. 7 10
      code/AssetLib/DXF/DXFLoader.h
  68. 13 8
      code/AssetLib/FBX/FBXConverter.cpp
  69. 2 2
      code/AssetLib/FBX/FBXConverter.h
  70. 5 6
      code/AssetLib/FBX/FBXDocument.cpp
  71. 6 1
      code/AssetLib/FBX/FBXDocument.h
  72. 2 3
      code/AssetLib/FBX/FBXExportNode.cpp
  73. 3 4
      code/AssetLib/FBX/FBXExportNode.h
  74. 113 38
      code/AssetLib/FBX/FBXExporter.cpp
  75. 10 11
      code/AssetLib/FBX/FBXExporter.h
  76. 1 1
      code/AssetLib/FBX/FBXImporter.cpp
  77. 6 5
      code/AssetLib/FBX/FBXImporter.h
  78. 9 4
      code/AssetLib/FBX/FBXMaterial.cpp
  79. 4 4
      code/AssetLib/FBX/FBXMeshGeometry.cpp
  80. 4 4
      code/AssetLib/FBX/FBXMeshGeometry.h
  81. 12 16
      code/AssetLib/FBX/FBXParser.cpp
  82. 4 5
      code/AssetLib/FBX/FBXProperties.cpp
  83. 3 3
      code/AssetLib/FBX/FBXProperties.h
  84. 1 1
      code/AssetLib/FBX/FBXUtil.cpp
  85. 3 2
      code/AssetLib/HMP/HMPLoader.cpp
  86. 20 33
      code/AssetLib/HMP/HMPLoader.h
  87. 1 2
      code/AssetLib/IFC/IFCBoolean.cpp
  88. 1 1
      code/AssetLib/IFC/IFCCurve.cpp
  89. 1 1
      code/AssetLib/IFC/IFCGeometry.cpp
  90. 2 3
      code/AssetLib/IFC/IFCLoader.cpp
  91. 34 52
      code/AssetLib/IFC/IFCLoader.h
  92. 3 3
      code/AssetLib/IFC/IFCMaterial.cpp
  93. 4 4
      code/AssetLib/IFC/IFCOpenings.cpp
  94. 116 116
      code/AssetLib/IFC/IFCReaderGen1_2x3.cpp
  95. 81 81
      code/AssetLib/IFC/IFCReaderGen2_2x3.cpp
  96. 129 129
      code/AssetLib/IFC/IFCReaderGen_4.cpp
  97. 13 13
      code/AssetLib/IFC/IFCReaderGen_4.h
  98. 0 1
      code/AssetLib/IFC/IFCUtil.cpp
  99. 6 8
      code/AssetLib/IFC/IFCUtil.h
  100. 2 2
      code/AssetLib/Irr/IRRLoader.cpp

+ 1 - 0
.github/FUNDING.yml

@@ -1 +1,2 @@
 open_collective: assimp
+patreon: assimp

+ 3 - 9
.github/ISSUE_TEMPLATE/bug_report.md

@@ -1,8 +1,8 @@
 ---
 name: Bug report
 about: Create a report to help us improve
-title: ''
-labels: ''
+title: 'Bug:'
+labels: 'Bug'
 assignees: ''
 
 ---
@@ -23,16 +23,10 @@ A clear and concise description of what you expected to happen.
 **Screenshots**
 If applicable, add screenshots to help explain your problem.
 
-**Desktop (please complete the following information):**
+**Platform (please complete the following information):**
  - OS: [e.g. iOS]
  - Browser [e.g. chrome, safari]
  - Version [e.g. 22]
 
-**Smartphone (please complete the following information):**
- - Device: [e.g. iPhone6]
- - OS: [e.g. iOS8.1]
- - Browser [e.g. stock browser, safari]
- - Version [e.g. 22]
-
 **Additional context**
 Add any other context about the problem here.

+ 1 - 1
.github/ISSUE_TEMPLATE/feature_request.md

@@ -2,7 +2,7 @@
 name: Feature request
 about: Suggest an idea for this project
 title: ''
-labels: ''
+labels: 'Feature-Request'
 assignees: ''
 
 ---

+ 25 - 0
.github/ISSUE_TEMPLATE/tech_debt.md

@@ -0,0 +1,25 @@
+---
+name: Technical debt
+about: Create a report to help us to fix and detect tech debts
+title: ''
+labels: 'Techdebt'
+assignees: ''
+
+---
+
+**Describe the technical debt**
+A clear and concise description of what the tech debt is about.
+
+**Better solution**
+A clear and concise description of what you would expect.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. iOS]
+ - Browser [e.g. chrome, safari]
+ - Version [e.g. 22]
+
+**Additional context**
+Add any other context about the problem here.

+ 3 - 2
.gitignore

@@ -25,7 +25,7 @@ CMakeSettings.json
 # Output
 bin/
 lib/
-
+x64/
 # QtCreator
 CMakeLists.txt.user
 
@@ -94,6 +94,7 @@ test/gtest/src/gtest-stamp/gtest-gitinfo.txt
 test/gtest/src/gtest-stamp/gtest-gitclone-lastrun.txt
 Assimp.opensdf
 contrib/zlib/CTestTestfile.cmake
+contrib/zlib/Debug/zlibstaticd.pdb
 ipch/assimp_viewer-44bbbcd1/assimp_viewerd-ccc45335.ipch
 bin64/assimp-vc140-mt.dll
 bin64/assimp-vc140-mtd.dll
@@ -118,4 +119,4 @@ tools/assimp_qt_viewer/moc_mainwindow.cpp_parameters
 tools/assimp_qt_viewer/ui_mainwindow.h
 
 #Generated directory
-generated/*
+generated/*

+ 17 - 14
CMakeLists.txt

@@ -44,16 +44,16 @@ CMAKE_MINIMUM_REQUIRED( VERSION 3.10 )
 option(ASSIMP_HUNTER_ENABLED "Enable Hunter package manager support" OFF)
 
 IF(ASSIMP_HUNTER_ENABLED)
-  include("cmake/HunterGate.cmake")
+  include("cmake-modules/HunterGate.cmake")
   HunterGate(
-    URL "https://github.com/cpp-pm/hunter/archive/v0.23.293.tar.gz"
-    SHA1 "e8e5470652db77149d9b38656db2a6c0b7642693"
+    URL "https://github.com/cpp-pm/hunter/archive/v0.23.311.tar.gz"
+    SHA1 "1a82b9b73055879181cb1466b2ab5d48ee8ae410"
   )
 
   add_definitions(-DASSIMP_USE_HUNTER)
 ENDIF()
 
-PROJECT( Assimp VERSION 5.0.1 )
+PROJECT(Assimp VERSION 5.1.0)
 
 # All supported options ###############################################
 
@@ -135,11 +135,11 @@ IF ( WIN32 )
   # Use subset of Windows.h
   ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
 
-  OPTION ( ASSIMP_BUILD_ASSIMP_VIEW
-    "If the Assimp view tool is built. (requires DirectX)"
-    OFF )
-
   IF(MSVC)
+    OPTION ( ASSIMP_BUILD_ASSIMP_VIEW
+      "If the Assimp view tool is built. (requires DirectX)"
+      OFF )
+
     OPTION( ASSIMP_INSTALL_PDB
       "Install MSVC debug files."
       ON )
@@ -265,9 +265,12 @@ ELSEIF(MSVC)
   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
   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")
 ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
   IF(NOT ASSIMP_HUNTER_ENABLED)
     SET(CMAKE_CXX_STANDARD 11)
@@ -334,9 +337,9 @@ INCLUDE (FindPkgMacros)
 INCLUDE (PrecompiledHeader)
 
 # Set Assimp project output directory variables.
-SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
-SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
-SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib")
+SET(ASSIMP_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for runtime output files")
+SET(ASSIMP_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin" CACHE STRING "Path for library output files")
+SET(ASSIMP_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib" CACHE STRING "Path for archive output files")
 
 # Macro used to set the output directories of a target to the
 # respective Assimp output directories.
@@ -395,14 +398,14 @@ set(GENERATED_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
 
 IF(ASSIMP_HUNTER_ENABLED)
   set(CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_NAME}")
-  set(CMAKE_CONFIG_TEMPLATE_FILE "cmake/assimp-hunter-config.cmake.in")
+  set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-hunter-config.cmake.in")
   set(NAMESPACE "${PROJECT_NAME}::")
   set(TARGETS_EXPORT_NAME "${PROJECT_NAME}Targets")
   set(VERSION_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}ConfigVersion.cmake")
   set(PROJECT_CONFIG "${GENERATED_DIR}/${PROJECT_NAME}Config.cmake")
 ELSE()
   set(CONFIG_INSTALL_DIR "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
-  set(CMAKE_CONFIG_TEMPLATE_FILE "cmake/assimp-plain-config.cmake.in")
+  set(CMAKE_CONFIG_TEMPLATE_FILE "cmake-modules/assimp-plain-config.cmake.in")
   string(TOLOWER ${PROJECT_NAME} PROJECT_NAME_LOWERCASE)
   set(NAMESPACE "${PROJECT_NAME_LOWERCASE}::")
   set(TARGETS_EXPORT_NAME "${PROJECT_NAME_LOWERCASE}Targets")

+ 3 - 1
Readme.md

@@ -42,7 +42,9 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file.
 * [.NET](https://bitbucket.org/Starnick/assimpnet/src/master/)
 * [Pascal](port/AssimpPascal/Readme.md)
 * [Javascript (Alpha)](https://github.com/makc/assimp2json)
-* [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777)
+* [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))
 * [HAXE-Port](https://github.com/longde123/assimp-haxe) The Assimp-HAXE-port.
 * [Rust](https://github.com/jkvargas/russimp)

+ 0 - 17
cmake-modules/FindIrrXML.cmake

@@ -1,17 +0,0 @@
-# Find IrrXMl from irrlicht project
-#
-# Find LibIrrXML headers and library
-#
-#   IRRXML_FOUND          - IrrXML found
-#   IRRXML_INCLUDE_DIR    - Headers location
-#   IRRXML_LIBRARY        - IrrXML main library
-
-find_path(IRRXML_INCLUDE_DIR irrXML.h
-    PATH_SUFFIXES include/irrlicht include/irrxml)
-find_library(IRRXML_LIBRARY IrrXML)
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(IrrXML REQUIRED_VARS IRRXML_INCLUDE_DIR IRRXML_LIBRARY)
-
-
-mark_as_advanced(IRRXML_INCLUDE_DIR IRRXML_LIBRARY)

+ 0 - 0
cmake/HunterGate.cmake → cmake-modules/HunterGate.cmake


+ 19 - 0
cmake-modules/assimp-hunter-config.cmake.in

@@ -0,0 +1,19 @@
+@PACKAGE_INIT@
+
+find_package(RapidJSON     CONFIG REQUIRED)
+find_package(ZLIB          CONFIG REQUIRED)
+find_package(utf8cpp       CONFIG REQUIRED)
+find_package(minizip       CONFIG REQUIRED)
+find_package(openddlparser CONFIG REQUIRED)
+find_package(poly2tri      CONFIG REQUIRED)
+find_package(polyclipping  CONFIG REQUIRED)
+find_package(zip           CONFIG REQUIRED)
+find_package(pugixml       CONFIG REQUIRED)
+find_package(stb           CONFIG REQUIRED)
+
+if(@ASSIMP_BUILD_DRACO@)
+  find_package(draco CONFIG REQUIRED)
+endif()
+
+include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")
+check_required_components("@PROJECT_NAME@")

+ 0 - 0
cmake/assimp-plain-config.cmake.in → cmake-modules/assimp-plain-config.cmake.in


+ 0 - 18
cmake/assimp-hunter-config.cmake.in

@@ -1,18 +0,0 @@
-@PACKAGE_INIT@
-
-find_package(RapidJSON CONFIG REQUIRED)
-find_package(ZLIB CONFIG REQUIRED)
-find_package(utf8cpp CONFIG REQUIRED)
-find_package(minizip CONFIG REQUIRED)
-find_package(openddlparser CONFIG REQUIRED)
-find_package(poly2tri CONFIG REQUIRED)
-find_package(polyclipping CONFIG REQUIRED)
-find_package(zip CONFIG REQUIRED)
-find_package(pugixml CONFIG REQUIRED)
-
-if(@ASSIMP_BUILD_DRACO@)
-  find_package(draco CONFIG REQUIRED)
-endif()
-
-include("${CMAKE_CURRENT_LIST_DIR}/@[email protected]")
-check_required_components("@PROJECT_NAME@")

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

@@ -68,8 +68,8 @@ 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 (std::string::iterator it = s.begin(); it != s.end(); ++it) {
-            *it = static_cast<char>(::tolower(static_cast<unsigned char>(*it)));
+        for (char & it : s) {
+            it = static_cast<char>(::tolower(static_cast<unsigned char>(it)));
         }
 
         if (std::string::npos == s.find("default")) continue;
@@ -79,12 +79,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
                 mScene->mMaterials[i].mDiffuse.r !=
                         mScene->mMaterials[i].mDiffuse.b) continue;
 
-        if (mScene->mMaterials[i].sTexDiffuse.mMapName.length() != 0 ||
-                mScene->mMaterials[i].sTexBump.mMapName.length() != 0 ||
-                mScene->mMaterials[i].sTexOpacity.mMapName.length() != 0 ||
-                mScene->mMaterials[i].sTexEmissive.mMapName.length() != 0 ||
-                mScene->mMaterials[i].sTexSpecular.mMapName.length() != 0 ||
-                mScene->mMaterials[i].sTexShininess.mMapName.length() != 0) {
+        if (ContainsTextures(i)) {
             continue;
         }
         idx = i;

+ 12 - 6
code/AssetLib/3DS/3DSExporter.cpp

@@ -56,8 +56,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <memory>
 
-using namespace Assimp;
 namespace Assimp {
+
 using namespace D3DS;
 
 namespace {
@@ -291,7 +291,7 @@ void Discreet3DSExporter::WriteMaterials() {
             ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_SPECULAR);
             WriteColor(color);
         }
-                
+
         if (mat.Get(AI_MATKEY_COLOR_AMBIENT, color) == AI_SUCCESS) {
             ChunkWriter curChunk(writer, Discreet3DS::CHUNK_MAT_AMBIENT);
             WriteColor(color);
@@ -330,6 +330,7 @@ void Discreet3DSExporter::WriteMaterials() {
             case aiShadingMode_Blinn:
             case aiShadingMode_CookTorrance:
             case aiShadingMode_Fresnel:
+            case aiShadingMode_PBR_BRDF: // Possibly should be Discreet3DS::Metal in some cases but this is undocumented
                 shading_mode_out = Discreet3DS::Phong;
                 break;
 
@@ -356,7 +357,10 @@ void Discreet3DSExporter::WriteMaterials() {
             writer.PutI2(1);
         }
 
-        WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE);
+        // Fallback to BASE_COLOR if no DIFFUSE
+        if (!WriteTexture(mat, aiTextureType_DIFFUSE, Discreet3DS::CHUNK_MAT_TEXTURE))
+            WriteTexture(mat, aiTextureType_BASE_COLOR, Discreet3DS::CHUNK_MAT_TEXTURE);
+
         WriteTexture(mat, aiTextureType_HEIGHT, Discreet3DS::CHUNK_MAT_BUMPMAP);
         WriteTexture(mat, aiTextureType_OPACITY, Discreet3DS::CHUNK_MAT_OPACMAP);
         WriteTexture(mat, aiTextureType_SHININESS, Discreet3DS::CHUNK_MAT_MAT_SHINMAP);
@@ -367,20 +371,21 @@ void Discreet3DSExporter::WriteMaterials() {
 }
 
 // ------------------------------------------------------------------------------------------------
-void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type, uint16_t chunk_flags) {
+// returns true if the texture existed
+bool Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type, uint16_t chunk_flags) {
     aiString path;
     aiTextureMapMode map_mode[2] = {
         aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
     };
     ai_real blend = 1.0;
     if (mat.GetTexture(type, 0, &path, nullptr, nullptr, &blend, nullptr, map_mode) != AI_SUCCESS || !path.length) {
-        return;
+        return false;
     }
 
     // TODO: handle embedded textures properly
     if (path.data[0] == '*') {
         ASSIMP_LOG_ERROR("Ignoring embedded texture for export: ", path.C_Str());
-        return;
+        return false;
     }
 
     ChunkWriter chunk(writer, chunk_flags);
@@ -402,6 +407,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type
         writer.PutU2(val);
     }
     // TODO: export texture transformation (i.e. UV offset, scale, rotation)
+    return true;
 }
 
 // ------------------------------------------------------------------------------------------------

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

@@ -73,7 +73,7 @@ public:
 private:
     void WriteMeshes();
     void WriteMaterials();
-    void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
+    bool WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
     void WriteFaceMaterialChunk(const aiMesh& mesh);
     int WriteHierarchy(const aiNode& node, int level, int sibling_level);
     void WriteString(const std::string& s);

+ 40 - 40
code/AssetLib/3DS/3DSHelper.h

@@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/light.h>
 #include <assimp/material.h>
 #include <assimp/qnan.h>
-#include <stdio.h> //sprintf
+#include <cstdio> //sprintf
 
 namespace Assimp {
 namespace D3DS {
@@ -259,7 +259,7 @@ namespace Discreet3DS {
         // Specifies the file name of a texture
         CHUNK_MAPFILE = 0xA300,
 
-        // Specifies whether a materail requires two-sided rendering
+        // Specifies whether a material requires two-sided rendering
         CHUNK_MAT_TWO_SIDE = 0xA081,
         // ********************************************************************
 
@@ -348,16 +348,16 @@ struct Texture {
         // empty
     }
 
-    Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(std::move(other.mTextureBlend)),
+    Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(other.mTextureBlend),
                                             mMapName(std::move(other.mMapName)),
-                                            mOffsetU(std::move(other.mOffsetU)),
-                                            mOffsetV(std::move(other.mOffsetV)),
-                                            mScaleU(std::move(other.mScaleU)),
-                                            mScaleV(std::move(other.mScaleV)),
-                                            mRotation(std::move(other.mRotation)),
-                                            mMapMode(std::move(other.mMapMode)),
-                                            bPrivate(std::move(other.bPrivate)),
-                                            iUVSrc(std::move(other.iUVSrc)) {
+                                            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
     }
 
@@ -366,16 +366,16 @@ struct Texture {
             return *this;
         }
 
-        mTextureBlend = std::move(other.mTextureBlend);
+        mTextureBlend = other.mTextureBlend;
         mMapName = std::move(other.mMapName);
-        mOffsetU = std::move(other.mOffsetU);
-        mOffsetV = std::move(other.mOffsetV);
-        mScaleU = std::move(other.mScaleU);
-        mScaleV = std::move(other.mScaleV);
-        mRotation = std::move(other.mRotation);
-        mMapMode = std::move(other.mMapMode);
-        bPrivate = std::move(other.bPrivate);
-        iUVSrc = std::move(other.iUVSrc);
+        mOffsetU = other.mOffsetU;
+        mOffsetV = other.mOffsetV;
+        mScaleU = other.mScaleU;
+        mScaleV = other.mScaleV;
+        mRotation = other.mRotation;
+        mMapMode = other.mMapMode;
+        bPrivate = other.bPrivate;
+        iUVSrc = other.iUVSrc;
 
         return *this;
     }
@@ -461,13 +461,13 @@ struct Material {
 
     //! 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(std::move(other.mDiffuse)),
-                                              mSpecularExponent(std::move(other.mSpecularExponent)),
-                                              mShininessStrength(std::move(other.mShininessStrength)),
-                                              mSpecular(std::move(other.mSpecular)),
-                                              mAmbient(std::move(other.mAmbient)),
-                                              mShading(std::move(other.mShading)),
-                                              mTransparency(std::move(other.mTransparency)),
+                                              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)),
@@ -475,10 +475,10 @@ struct Material {
                                               sTexBump(std::move(other.sTexBump)),
                                               sTexEmissive(std::move(other.sTexEmissive)),
                                               sTexShininess(std::move(other.sTexShininess)),
-                                              mBumpHeight(std::move(other.mBumpHeight)),
-                                              mEmissive(std::move(other.mEmissive)),
+                                              mBumpHeight(other.mBumpHeight),
+                                              mEmissive(other.mEmissive),
                                               sTexAmbient(std::move(other.sTexAmbient)),
-                                              mTwoSided(std::move(other.mTwoSided)) {
+                                              mTwoSided(other.mTwoSided) {
         // empty
     }
 
@@ -488,13 +488,13 @@ struct Material {
         }
 
         mName = std::move(other.mName);
-        mDiffuse = std::move(other.mDiffuse);
-        mSpecularExponent = std::move(other.mSpecularExponent);
-        mShininessStrength = std::move(other.mShininessStrength),
-        mSpecular = std::move(other.mSpecular);
-        mAmbient = std::move(other.mAmbient);
-        mShading = std::move(other.mShading);
-        mTransparency = std::move(other.mTransparency);
+        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);
@@ -502,10 +502,10 @@ struct Material {
         sTexBump = std::move(other.sTexBump);
         sTexEmissive = std::move(other.sTexEmissive);
         sTexShininess = std::move(other.sTexShininess);
-        mBumpHeight = std::move(other.mBumpHeight);
-        mEmissive = std::move(other.mEmissive);
+        mBumpHeight = other.mBumpHeight;
+        mEmissive = other.mEmissive;
         sTexAmbient = std::move(other.sTexAmbient);
-        mTwoSided = std::move(other.mTwoSided);
+        mTwoSided = other.mTwoSided;
 
         return *this;
     }

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

@@ -449,7 +449,7 @@ void Discreet3DSImporter::ParseChunk(const char *name, unsigned int num) {
         // Read the lense angle
         camera->mHorizontalFOV = AI_DEG_TO_RAD(stream->GetF4());
         if (camera->mHorizontalFOV < 0.001f) {
-            camera->mHorizontalFOV = AI_DEG_TO_RAD(45.f);
+            camera->mHorizontalFOV = float(AI_DEG_TO_RAD(45.f));
         }
 
         // Now check for further subchunks

+ 14 - 5
code/AssetLib/3DS/3DSLoader.h

@@ -46,11 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 #ifndef AI_3DSIMPORTER_H_INC
 #define AI_3DSIMPORTER_H_INC
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 #include <assimp/BaseImporter.h>
 #include <assimp/types.h>
 
-#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 #include "3DSHelper.h"
 #include <assimp/StreamReader.h>
@@ -75,14 +75,14 @@ public:
      * See BaseImporter::CanRead() for details.
      */
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+        bool checkSig) const override;
 
     // -------------------------------------------------------------------
     /** Called prior to ReadFile().
      * The function is a request to the importer to update its configuration
      * basing on the Importer's configuration property list.
      */
-    void SetupProperties(const Importer* pImp);
+    void SetupProperties(const Importer* pImp) override;
 
 protected:
 
@@ -90,14 +90,14 @@ protected:
     /** Return importer meta information.
      * See #BaseImporter::GetInfo for the details
      */
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc* GetInfo () const override;
 
     // -------------------------------------------------------------------
     /** Imports the given file into the given scene structure.
      * See BaseImporter::InternReadFile() for details
      */
     void InternReadFile( const std::string& pFile, aiScene* pScene,
-        IOSystem* pIOHandler);
+        IOSystem* pIOHandler) override;
 
     // -------------------------------------------------------------------
     /** Converts a temporary material to the outer representation
@@ -208,6 +208,15 @@ protected:
     */
     void ReplaceDefaultMaterial();
 
+    bool ContainsTextures(unsigned int i) const {
+        return !mScene->mMaterials[i].sTexDiffuse.mMapName.empty() ||
+               !mScene->mMaterials[i].sTexBump.mMapName.empty() ||
+               !mScene->mMaterials[i].sTexOpacity.mMapName.empty() ||
+               !mScene->mMaterials[i].sTexEmissive.mMapName.empty() ||
+               !mScene->mMaterials[i].sTexSpecular.mMapName.empty() ||
+               !mScene->mMaterials[i].sTexShininess.mMapName.empty() ;
+    }
+
     // -------------------------------------------------------------------
     /** Convert the whole scene
     */

+ 165 - 0
code/AssetLib/3MF/3MFTypes.h

@@ -0,0 +1,165 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2021, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 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.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include <assimp/vector3.h>
+#include <assimp/matrix4x4.h>
+#include <assimp/ParsingUtils.h>
+#include <vector>
+#include <string>
+
+struct aiMaterial;
+struct aiMesh;
+
+namespace Assimp {
+namespace D3MF {
+
+enum class ResourceType {
+    RT_Object,
+    RT_BaseMaterials,
+    RT_EmbeddedTexture2D,
+    RT_Texture2DGroup,
+    RT_Unknown
+}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
+
+class Resource {
+public:
+    int mId;
+
+    Resource(int id) :
+            mId(id) {
+        // empty
+    }
+
+    virtual ~Resource() {
+        // empty
+    }
+
+    virtual ResourceType getType() const {
+        return ResourceType::RT_Unknown;
+    }
+};
+
+class EmbeddedTexture : public Resource {
+public:
+    std::string mPath;
+    std::string mContentType;
+    std::string mTilestyleU;
+    std::string mTilestyleV;
+    std::vector<char> mBuffer;
+
+    EmbeddedTexture(int id) :
+            Resource(id),
+            mPath(),
+            mContentType(),
+            mTilestyleU(),
+            mTilestyleV() {
+        // empty
+    }
+
+    ~EmbeddedTexture() = default;
+
+    ResourceType getType() const override {
+        return ResourceType::RT_EmbeddedTexture2D;
+    }
+};
+
+class Texture2DGroup : public Resource {
+public:
+    std::vector<aiVector2D> mTex2dCoords;
+    int mTexId;
+    Texture2DGroup(int id) :
+            Resource(id),
+            mTexId(-1) {
+        // empty
+    }
+
+    ~Texture2DGroup() = default;
+
+    ResourceType getType() const override {
+        return ResourceType::RT_Texture2DGroup;
+    }
+};
+
+class BaseMaterials : public Resource {
+public:
+    std::vector<unsigned int> mMaterialIndex;
+
+    BaseMaterials(int id) :
+            Resource(id),
+            mMaterialIndex() {
+        // empty
+    }
+
+    ~BaseMaterials() = default;
+
+    ResourceType getType() const override {
+        return ResourceType::RT_BaseMaterials;
+    }
+};
+
+struct Component {
+    int mObjectId;
+    aiMatrix4x4 mTransformation;
+};
+
+class Object : public Resource {
+public:
+    std::vector<aiMesh *> mMeshes;
+    std::vector<unsigned int> mMeshIndex;
+    std::vector<Component> mComponents;
+    std::string mName;
+
+    Object(int id) :
+            Resource(id),
+            mName(std::string("Object_") + ai_to_string(id)) {
+        // empty
+    }
+
+    ~Object() = default;
+
+    ResourceType getType() const override {
+        return ResourceType::RT_Object;
+    }
+};
+
+} // namespace D3MF
+} // namespace Assimp

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

@@ -80,13 +80,21 @@ namespace XmlTag {
     const char* const item = "item";
     const char* const objectid = "objectid";
     const char* const transform = "transform";
+    const char *const path = "path";
 
     // Material definitions
     const char* const basematerials = "basematerials";
-    const char* const basematerials_id = "id";
     const char* const basematerials_base = "base";
     const char* const basematerials_name = "name";
     const char* const basematerials_displaycolor = "displaycolor";
+    const char* const texture_2d = "m:texture2d";
+    const char *const texture_group = "m:texture2dgroup";
+    const char *const texture_content_type = "contenttype";
+    const char *const texture_tilestyleu = "tilestyleu";
+    const char *const texture_tilestylev = "tilestylev";
+    const char *const texture_2d_coord = "m:tex2coord";
+    const char *const texture_cuurd_u = "u";
+    const char *const texture_cuurd_v = "v";
 
     // Meta info tags
     const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
@@ -103,7 +111,7 @@ namespace XmlTag {
     const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
     const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
     const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
-    }
+}
 
 } // Namespace D3MF
 } // Namespace Assimp

+ 7 - 4
code/AssetLib/3MF/D3MFExporter.h

@@ -40,6 +40,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 #pragma once
 
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
+
 #include <memory>
 #include <sstream>
 #include <vector>
@@ -58,8 +61,6 @@ class IOStream;
 
 namespace D3MF {
 
-#ifndef ASSIMP_BUILD_NO_EXPORT
-#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
 
 struct OpcPackageRelationship;
 
@@ -100,9 +101,11 @@ private:
     std::vector<OpcPackageRelationship*> mRelations;
 };
 
-#endif // ASSIMP_BUILD_NO_3MF_EXPORTER
-#endif // ASSIMP_BUILD_NO_EXPORT
 
 } // Namespace D3MF
 } // Namespace Assimp
 
+#endif // ASSIMP_BUILD_NO_3MF_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
+
+

+ 15 - 507
code/AssetLib/3MF/D3MFImporter.cpp

@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "D3MFImporter.h"
 #include "3MFXmlTags.h"
 #include "D3MFOpcPackage.h"
+#include "XmlSerializer.h"
 
 #include <assimp/StringComparison.h>
 #include <assimp/StringUtils.h>
@@ -61,513 +62,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <string>
 #include <vector>
 #include <iomanip>
-#include <string.h>
+#include <cstring>
 
 namespace Assimp {
-namespace D3MF {
-
-enum class ResourceType {
-    RT_Object,
-    RT_BaseMaterials,
-    RT_Unknown
-}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
-
-class Resource {
-public:
-    int mId;
-
-    Resource(int id) :
-            mId(id) {
-        // empty
-    }
-
-    virtual ~Resource() {
-        // empty
-    }
-
-    virtual ResourceType getType() const {
-        return ResourceType::RT_Unknown;
-    }
-};
-
-class BaseMaterials : public Resource {
-public:
-    std::vector<aiMaterial *> mMaterials;
-    std::vector<unsigned int> mMaterialIndex;
-
-    BaseMaterials(int id) :
-            Resource(id),
-            mMaterials(),
-            mMaterialIndex() {
-        // empty
-    }
-
-    ~BaseMaterials() = default;
-
-    ResourceType getType() const override {
-        return ResourceType::RT_BaseMaterials;
-    }
-};
-
-struct Component {
-    int mObjectId;
-    aiMatrix4x4 mTransformation;
-};
-
-class Object : public Resource {
-public:
-    std::vector<aiMesh *> mMeshes;
-    std::vector<unsigned int> mMeshIndex;
-    std::vector<Component> mComponents;
-    std::string mName;
-
-    Object(int id) :
-            Resource(id),
-            mName(std::string("Object_") + ai_to_string(id)) {
-        // empty
-    }
-
-    ~Object() = default;
-
-    ResourceType getType() const override {
-        return ResourceType::RT_Object;
-    }
-};
-
-class XmlSerializer {
-public:
-    XmlSerializer(XmlParser *xmlParser) :
-            mResourcesDictionnary(),
-            mMaterialCount(0),
-            mMeshCount(0),
-            mXmlParser(xmlParser) {
-        // empty
-    }
-
-    ~XmlSerializer() {
-        for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it ) {
-            delete it->second;
-        }
-    }
-
-    void ImportXml(aiScene *scene) {
-        if (nullptr == scene) {
-            return;
-        }
-
-        scene->mRootNode = new aiNode(XmlTag::RootTag);
-
-        XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
-        if (node.empty()) {
-            return;
-        }
-        XmlNode resNode = node.child(XmlTag::resources);
-        for (auto &currentNode : resNode.children()) {
-            const std::string currentNodeName = currentNode.name();
-            if (currentNodeName == XmlTag::object) {
-                ReadObject(currentNode);
-            } else if (currentNodeName == XmlTag::basematerials) {
-                ReadBaseMaterials(currentNode);
-            } else if (currentNodeName == XmlTag::meta) {
-                ReadMetadata(currentNode);
-            }
-        }
-
-        XmlNode buildNode = node.child(XmlTag::build);
-        for (auto &currentNode : buildNode.children()) {
-            const std::string currentNodeName = currentNode.name();
-            if (currentNodeName == XmlTag::item) {
-                int objectId = -1;
-                std::string transformationMatrixStr;
-                aiMatrix4x4 transformationMatrix;
-                getNodeAttribute(currentNode, D3MF::XmlTag::objectid, objectId);
-                bool hasTransform = getNodeAttribute(currentNode, D3MF::XmlTag::transform, transformationMatrixStr);
-
-                auto it = mResourcesDictionnary.find(objectId);
-                if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
-                    Object *obj = static_cast<Object *>(it->second);
-                    if (hasTransform) {
-                        transformationMatrix = parseTransformMatrix(transformationMatrixStr);
-                    }
-
-                    addObjectToNode(scene->mRootNode, obj, transformationMatrix);
-                }
-            }
-        }
-
-        // import the metadata
-        if (!mMetaData.empty()) {
-            const size_t numMeta = mMetaData.size();
-            scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
-            for (size_t i = 0; i < numMeta; ++i) {
-                aiString val(mMetaData[i].value);
-                scene->mMetaData->Set(static_cast<unsigned int>(i), mMetaData[i].name, val);
-            }
-        }
-
-        // import the meshes
-        scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
-        if (scene->mNumMeshes != 0) {
-            scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
-            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
-                if (it->second->getType() == ResourceType::RT_Object) {
-                    Object *obj = static_cast<Object *>(it->second);
-                    ai_assert(nullptr != obj);
-                    for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
-                        scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
-                    }
-                }
-            }
-        }
-
-        // import the materials
-        scene->mNumMaterials = mMaterialCount;
-        if (scene->mNumMaterials != 0) {
-            scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
-            for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
-                if (it->second->getType() == ResourceType::RT_BaseMaterials) {
-                    BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
-                    for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) {
-                        scene->mMaterials[baseMaterials->mMaterialIndex[i]] = baseMaterials->mMaterials[i];
-                    }
-                }
-            }
-        }
-    }
-
-private:
-    void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
-        ai_assert(nullptr != obj);
-
-        aiNode *sceneNode = new aiNode(obj->mName);
-        sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
-        sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
-        std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
-
-        sceneNode->mTransformation = nodeTransform;
-        if (nullptr != parent) {
-            parent->addChildren(1, &sceneNode);
-        }
-
-        for (size_t i = 0; i < obj->mComponents.size(); ++i) {
-            Component c = obj->mComponents[i];
-            auto it = mResourcesDictionnary.find(c.mObjectId);
-            if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
-                addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
-            }
-        }
-    }
-
-    bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
-        pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
-        if (!objectAttribute.empty()) {
-            value = objectAttribute.as_string();
-            return true;
-        }
-
-        return false;
-    }
-
-    bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
-        std::string strValue;
-        bool ret = getNodeAttribute(node, attribute, strValue);
-        if (ret) {
-            value = std::atoi(strValue.c_str());
-            return true;
-        } 
-
-        return false;
-    }
-
-    aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
-        // split the string
-        std::vector<float> numbers;
-        std::string currentNumber;
-        for (size_t i = 0; i < matrixStr.size(); ++i) {
-            const char c = matrixStr[i];
-            if (c == ' ') {
-                if (currentNumber.size() > 0) {
-                    float f = std::stof(currentNumber);
-                    numbers.push_back(f);
-                    currentNumber.clear();
-                }
-            } else {
-                currentNumber.push_back(c);
-            }
-        }
-        if (currentNumber.size() > 0) {
-            const float f = std::stof(currentNumber);
-            numbers.push_back(f);
-        }
-
-        aiMatrix4x4 transformMatrix;
-        transformMatrix.a1 = numbers[0];
-        transformMatrix.b1 = numbers[1];
-        transformMatrix.c1 = numbers[2];
-        transformMatrix.d1 = 0;
-
-        transformMatrix.a2 = numbers[3];
-        transformMatrix.b2 = numbers[4];
-        transformMatrix.c2 = numbers[5];
-        transformMatrix.d2 = 0;
-
-        transformMatrix.a3 = numbers[6];
-        transformMatrix.b3 = numbers[7];
-        transformMatrix.c3 = numbers[8];
-        transformMatrix.d3 = 0;
-
-        transformMatrix.a4 = numbers[9];
-        transformMatrix.b4 = numbers[10];
-        transformMatrix.c4 = numbers[11];
-        transformMatrix.d4 = 1;
-
-        return transformMatrix;
-    }
-
-    void ReadObject(XmlNode &node) {
-        int id = -1, pid = -1, pindex = -1;
-        bool hasId = getNodeAttribute(node, XmlTag::id, id);
-        bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
-        bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
-        if (!hasId) {
-            return;
-        }
-
-        Object *obj = new Object(id);
-
-        for (XmlNode &currentNode : node.children()) {
-            const std::string &currentName = currentNode.name();
-            if (currentName == D3MF::XmlTag::mesh) {
-                auto mesh = ReadMesh(currentNode);
-                mesh->mName.Set(ai_to_string(id));
-
-                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];
-                    }
-                }
-
-                obj->mMeshes.push_back(mesh);
-                obj->mMeshIndex.push_back(mMeshCount);
-                mMeshCount++;
-            } else if (currentName == D3MF::XmlTag::components) {
-                for (XmlNode &currentSubNode : currentNode.children()) {
-                    const std::string subNodeName = currentSubNode.name();
-                    if (subNodeName == D3MF::XmlTag::component) {
-                        int objectId = -1;
-                        std::string componentTransformStr;
-                        aiMatrix4x4 componentTransform;
-                        if (getNodeAttribute(currentSubNode, D3MF::XmlTag::transform, componentTransformStr)) {
-                            componentTransform = parseTransformMatrix(componentTransformStr);
-                        }
-
-                        if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
-                            obj->mComponents.push_back({ objectId, componentTransform });
-                        }
-                    }
-                }
-            }
-        }
-
-        mResourcesDictionnary.insert(std::make_pair(id, obj));
-    }
-
-    aiMesh *ReadMesh(XmlNode &node) {
-        aiMesh *mesh = new aiMesh();
-
-        for (XmlNode &currentNode : node.children()) {
-            const std::string currentName = currentNode.name();
-            if (currentName == XmlTag::vertices) {
-                ImportVertices(currentNode, mesh);
-            } else if (currentName == XmlTag::triangles) {
-                ImportTriangles(currentNode, mesh);
-            }
-        }
-
-        return mesh;
-    }
-
-    void ReadMetadata(XmlNode &node) {
-        pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
-        const std::string name = attribute.as_string();
-        const std::string value = node.value();
-        if (name.empty()) {
-            return;
-        }
-
-        MetaEntry entry;
-        entry.name = name;
-        entry.value = value;
-        mMetaData.push_back(entry);
-    }
-
-    void ImportVertices(XmlNode &node, aiMesh *mesh) {
-        std::vector<aiVector3D> vertices;
-        for (XmlNode &currentNode : node.children()) {
-            const std::string currentName = currentNode.name();
-            if (currentName == XmlTag::vertex) {
-                vertices.push_back(ReadVertex(currentNode));
-            }
-        }
-
-        mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
-        mesh->mVertices = new aiVector3D[mesh->mNumVertices];
-        std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
-    }
-
-    aiVector3D ReadVertex(XmlNode &node) {
-        aiVector3D vertex;
-        vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
-        vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
-        vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
-
-        return vertex;
-    }
-
-    void ImportTriangles(XmlNode &node, aiMesh *mesh) {
-        std::vector<aiFace> faces;
-        for (XmlNode &currentNode : node.children()) {
-            const std::string currentName = currentNode.name();
-            if (currentName == XmlTag::triangle) {
-                aiFace face = ReadTriangle(currentNode);
-                faces.push_back(face);
-
-                int pid = 0, p1 = 0;
-                bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
-                bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
-
-                if (hasPid && hasP1) {
-                    auto it = mResourcesDictionnary.find(pid);
-                    if (it != mResourcesDictionnary.end()) {
-                        if (it->second->getType() == ResourceType::RT_BaseMaterials) {
-                            BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
-                            mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
-                        }
-                        // TODO: manage the separation into several meshes if the triangles of the mesh do not all refer to the same material
-                    }
-                }
-            }
-        }
-
-        mesh->mNumFaces = static_cast<unsigned int>(faces.size());
-        mesh->mFaces = new aiFace[mesh->mNumFaces];
-        mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
-
-        std::copy(faces.begin(), faces.end(), mesh->mFaces);
-    }
-
-    aiFace ReadTriangle(XmlNode &node) {
-        aiFace face;
-
-        face.mNumIndices = 3;
-        face.mIndices = new unsigned int[face.mNumIndices];
-        face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
-        face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
-        face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
-
-        return face;
-    }
-
-    void ReadBaseMaterials(XmlNode &node) {
-        int id = -1;
-        if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) {
-            BaseMaterials *baseMaterials = new BaseMaterials(id);
-
-            for (XmlNode &currentNode : node.children()) {
-                const std::string currentName = currentNode.name();
-                if (currentName == XmlTag::basematerials_base) {
-                    baseMaterials->mMaterialIndex.push_back(mMaterialCount);
-                    baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id));
-                    ++mMaterialCount;
-                }
-            }
-
-            mResourcesDictionnary.insert(std::make_pair(id, baseMaterials));
-        }
-    }
-
-    bool parseColor(const char *color, aiColor4D &diffuse) {
-        if (nullptr == color) {
-            return false;
-        }
-
-        //format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
-        const size_t len = strlen(color);
-        if (9 != len && 7 != len) {
-            return false;
-        }
-
-        const char *buf(color);
-        if ('#' != buf[0]) {
-            return false;
-        }
-
-        char r[3] = { buf[1], buf[2], '\0' };
-        diffuse.r = static_cast<ai_real>(strtol(r, nullptr, 16)) / ai_real(255.0);
-
-        char g[3] = { buf[3], buf[4], '\0' };
-        diffuse.g = static_cast<ai_real>(strtol(g, nullptr, 16)) / ai_real(255.0);
-
-        char b[3] = { buf[5], buf[6], '\0' };
-        diffuse.b = static_cast<ai_real>(strtol(b, nullptr, 16)) / ai_real(255.0);
-
-        if (7 == len)
-            return true;
-
-        char a[3] = { buf[7], buf[8], '\0' };
-        diffuse.a = static_cast<ai_real>(strtol(a, nullptr, 16)) / ai_real(255.0);
-
-        return true;
-    }
-
-    void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
-        const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
-        aiColor4D diffuse;
-        if (parseColor(color, diffuse)) {
-            mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
-        }
-    }
-
-    aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId) {
-        aiMaterial *material = new aiMaterial();
-        material->mNumProperties = 0;
-        std::string name;
-        bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
-
-        std::string stdMaterialName;
-        const std::string strId(ai_to_string(basematerialsId));
-        stdMaterialName += "id";
-        stdMaterialName += strId;
-        stdMaterialName += "_";
-        if (hasName) {
-            stdMaterialName += std::string(name);
-        } else {
-            stdMaterialName += "basemat_";
-            stdMaterialName += ai_to_string(mMaterialCount - basematerialsId);
-        }
-
-        aiString assimpMaterialName(stdMaterialName);
-        material->AddProperty(&assimpMaterialName, AI_MATKEY_NAME);
-
-        assignDiffuseColor(node, material);
-
-        return material;
-    }
-
-private:
-    struct MetaEntry {
-        std::string name;
-        std::string value;
-    };
-    std::vector<MetaEntry> mMetaData;
-    std::map<unsigned int, Resource *> mResourcesDictionnary;
-    unsigned int mMaterialCount, mMeshCount;
-    XmlParser *mXmlParser;
-};
-
-} //namespace D3MF
 
 using namespace D3MF;
 
@@ -597,7 +94,9 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
     const std::string extension(GetExtension(filename));
     if (extension == desc.mFileExtensions) {
         return true;
-    } else if (!extension.length() || checkSig) {
+    } 
+
+    if (!extension.length() || checkSig) {
         if (nullptr == pIOHandler) {
             return false;
         }
@@ -611,7 +110,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
     return false;
 }
 
-void D3MFImporter::SetupProperties(const Importer * /*pImp*/) {
+void D3MFImporter::SetupProperties(const Importer*) {
     // empty
 }
 
@@ -626,6 +125,15 @@ void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene,
     if (xmlParser.parse(opcPackage.RootStream())) {
         XmlSerializer xmlSerializer(&xmlParser);
         xmlSerializer.ImportXml(pScene);
+
+        const std::vector<aiTexture*> &tex =  opcPackage.GetEmbeddedTextures();
+        if (!tex.empty()) {
+            pScene->mNumTextures = static_cast<unsigned int>(tex.size());
+            pScene->mTextures = new aiTexture *[pScene->mNumTextures];
+            for (unsigned int i = 0; i < pScene->mNumTextures; ++i) {
+                pScene->mTextures[i] = tex[i];
+            }
+        }
     }
 }
 

+ 32 - 6
code/AssetLib/3MF/D3MFImporter.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,23 +42,50 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_D3MFLOADER_H_INCLUDED
 #define AI_D3MFLOADER_H_INCLUDED
 
+#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
+
 #include <assimp/BaseImporter.h>
 
 namespace Assimp {
 
+// ---------------------------------------------------------------------------
 /// @brief  The 3MF-importer class.
+///
+/// Implements the basic topology import and embedded textures.
+// ---------------------------------------------------------------------------
 class D3MFImporter : public BaseImporter {
 public:
+    /// @brief The default class constructor.
     D3MFImporter();
-    ~D3MFImporter();
-    bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
-    void SetupProperties(const Importer *pImp);
-    const aiImporterDesc *GetInfo() const;
+
+    ///	@brief  The class destructor.
+    ~D3MFImporter() override;
+
+    /// @brief Performs the data format detection.
+    /// @param pFile        The filename to check.
+    /// @param pIOHandler   The used IO-System.
+    /// @param checkSig     true for signature checking.
+    /// @return true for can be loaded, false for not.
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
+
+    /// @brief  Not used
+    /// @param pImp Not used
+    void SetupProperties(const Importer *pImp) override;
+
+    /// @brief The importer description getter.
+    /// @return The info
+    const aiImporterDesc *GetInfo() const override;
 
 protected:
-    void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
+    /// @brief Internal read function, performs the file parsing.
+    /// @param pFile        The filename
+    /// @param pScene       The scene to load in.
+    /// @param pIOHandler   The io-system
+    void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
 };
 
 } // Namespace Assimp
 
+#endif // #ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
+
 #endif // AI_D3MFLOADER_H_INCLUDED

+ 59 - 13
code/AssetLib/3MF/D3MFOpcPackage.cpp

@@ -43,20 +43,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "D3MFOpcPackage.h"
 #include <assimp/Exceptional.h>
-
 #include <assimp/XmlParser.h>
 #include <assimp/ZipArchiveIOSystem.h>
 #include <assimp/ai_assert.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOStream.hpp>
 #include <assimp/IOSystem.hpp>
-
+#include <assimp/texture.h>
 #include "3MFXmlTags.h"
+
 #include <algorithm>
 #include <cassert>
 #include <cstdlib>
 #include <map>
-#include <memory>
 #include <vector>
 
 namespace Assimp {
@@ -64,11 +63,12 @@ namespace Assimp {
 namespace D3MF {
 // ------------------------------------------------------------------------------------------------
 
-typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
+using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
 
 class OpcPackageRelationshipReader {
 public:
-    OpcPackageRelationshipReader(XmlParser &parser) {
+    OpcPackageRelationshipReader(XmlParser &parser) :
+            m_relationShips() {
         XmlNode root = parser.getRootNode();
         ParseRootNode(root);
     }
@@ -91,6 +91,7 @@ public:
         if (relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty()) {
             return false;
         }
+
         return true;
     }
 
@@ -100,7 +101,7 @@ public:
         }
 
         for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) {
-            std::string name = currentNode.name();
+            const std::string name = currentNode.name();
             if (name == "Relationship") {
                 OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
                 relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID).as_string();
@@ -116,11 +117,23 @@ public:
     std::vector<OpcPackageRelationshipPtr> m_relationShips;
 };
 
+static bool IsEmbeddedTexture( const std::string &filename ) {
+    const std::string extension = BaseImporter::GetExtension(filename);
+    if (extension == "jpg" || extension == "png") {
+        std::string::size_type pos = filename.find("thumbnail");
+        if (pos == std::string::npos) {
+            return false;
+        }
+        return true;
+    }
+
+    return false;
+}
 // ------------------------------------------------------------------------------------------------
 D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
         mRootStream(nullptr),
         mZipArchive() {
-    mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile));
+    mZipArchive = new ZipArchiveIOSystem(pIOHandler, rFile);
     if (!mZipArchive->isOpen()) {
         throw DeadlyImportError("Failed to open file ", rFile, ".");
     }
@@ -136,18 +149,18 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
 
             IOStream *fileStream = mZipArchive->Open(file.c_str());
             if (nullptr == fileStream) {
-                ai_assert(fileStream != nullptr);
+                ASSIMP_LOG_ERROR("Filestream is nullptr.");
                 continue;
             }
 
             std::string rootFile = ReadPackageRootRelationship(fileStream);
-            if (rootFile.size() > 0 && rootFile[0] == '/') {
+            if (!rootFile.empty() && rootFile[0] == '/') {
                 rootFile = rootFile.substr(1);
                 if (rootFile[0] == '/') {
                     // deal with zip-bug
                     rootFile = rootFile.substr(1);
                 }
-            }
+            } 
 
             ASSIMP_LOG_VERBOSE_DEBUG(rootFile);
 
@@ -158,9 +171,12 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
             if (nullptr == mRootStream) {
                 throw DeadlyImportError("Cannot open root-file in archive : " + rootFile);
             }
-
         } else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
             ASSIMP_LOG_WARN("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file);
+        } else if (IsEmbeddedTexture(file)) {
+            IOStream *fileStream = mZipArchive->Open(file.c_str());
+            LoadEmbeddedTextures(fileStream, file);
+            mZipArchive->Close(fileStream);
         } else {
             ASSIMP_LOG_WARN("Ignored file of unknown type: ", file);
         }
@@ -169,20 +185,25 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
 
 D3MFOpcPackage::~D3MFOpcPackage() {
     mZipArchive->Close(mRootStream);
+    delete mZipArchive;
 }
 
 IOStream *D3MFOpcPackage::RootStream() const {
     return mRootStream;
 }
 
-static const std::string ModelRef = "3D/3dmodel.model";
+const std::vector<aiTexture *> &D3MFOpcPackage::GetEmbeddedTextures() const {
+    return mEmbeddedTextures;
+}
+
+static const char *const ModelRef = "3D/3dmodel.model";
 
 bool D3MFOpcPackage::validate() {
     if (nullptr == mRootStream || nullptr == mZipArchive) {
         return false;
     }
 
-    return mZipArchive->Exists(ModelRef.c_str());
+    return mZipArchive->Exists(ModelRef);
 }
 
 std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
@@ -204,6 +225,31 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
     return (*itr)->target;
 }
 
+void D3MFOpcPackage::LoadEmbeddedTextures(IOStream *fileStream, const std::string &filename) {
+    if (nullptr == fileStream) {
+        return;
+    }
+
+    const size_t size = fileStream->FileSize();
+    if (0 == size) {
+        return;
+    }
+
+    unsigned char *data = new unsigned char[size];
+    fileStream->Read(data, 1, size);
+    aiTexture *texture = new aiTexture;
+    std::string embName = "*" + filename;
+    texture->mFilename.Set(embName.c_str());
+    texture->mWidth = static_cast<unsigned int>(size);
+    texture->mHeight = 0;
+    texture->achFormatHint[0] = 'p';
+    texture->achFormatHint[1] = 'n';
+    texture->achFormatHint[2] = 'g';
+    texture->achFormatHint[3] = '\0';
+    texture->pcData = (aiTexel*) data;
+    mEmbeddedTextures.emplace_back(texture);
+}
+
 } // Namespace D3MF
 } // Namespace Assimp
 

+ 11 - 5
code/AssetLib/3MF/D3MFOpcPackage.h

@@ -42,12 +42,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef D3MFOPCPACKAGE_H
 #define D3MFOPCPACKAGE_H
 
+#include <assimp/IOSystem.hpp>
 #include <memory>
 #include <string>
-#include <assimp/IOSystem.hpp>
+
+struct aiTexture;
 
 namespace Assimp {
-    class ZipArchiveIOSystem;
+
+class ZipArchiveIOSystem;
 
 namespace D3MF {
 
@@ -63,16 +66,19 @@ public:
     ~D3MFOpcPackage();
     IOStream* RootStream() const;
     bool validate();
+    const std::vector<aiTexture*> &GetEmbeddedTextures() const;
 
 protected:
     std::string ReadPackageRootRelationship(IOStream* stream);
+    void LoadEmbeddedTextures(IOStream *fileStream, const std::string &filename);
 
 private:
     IOStream* mRootStream;
-    std::unique_ptr<ZipArchiveIOSystem> mZipArchive;
+    ZipArchiveIOSystem *mZipArchive;
+    std::vector<aiTexture *> mEmbeddedTextures;
 };
 
-} // Namespace D3MF
-} // Namespace Assimp
+} // namespace D3MF
+} // namespace Assimp
 
 #endif // D3MFOPCPACKAGE_H

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

@@ -0,0 +1,593 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2021, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 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.
+
+----------------------------------------------------------------------
+*/
+#include "XmlSerializer.h"
+#include "D3MFOpcPackage.h"
+#include "3MFXmlTags.h"
+#include "3MFTypes.h"
+#include <assimp/scene.h>
+
+namespace Assimp {
+namespace D3MF {
+
+static const int IdNotSet = -1;
+
+namespace {
+
+static const size_t ColRGBA_Len = 9;
+static const 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);
+    if (ColRGBA_Len != len && ColRGB_Len != len) {
+        return false;
+    }
+
+    return true;
+}
+
+aiFace ReadTriangle(XmlNode &node) {
+    aiFace face;
+
+    face.mNumIndices = 3;
+    face.mIndices = new unsigned int[face.mNumIndices];
+    face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
+    face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
+    face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
+
+    return face;
+}
+
+aiVector3D ReadVertex(XmlNode &node) {
+    aiVector3D vertex;
+    vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
+    vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
+    vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
+
+    return vertex;
+}
+
+bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
+    pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
+    if (!objectAttribute.empty()) {
+        value = objectAttribute.as_string();
+        return true;
+    }
+
+    return false;
+}
+
+bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
+    std::string strValue;
+    const bool ret = getNodeAttribute(node, attribute, strValue);
+    if (ret) {
+        value = std::atoi(strValue.c_str());
+        return true;
+    }
+
+    return false;
+}
+
+aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
+    // split the string
+    std::vector<float> numbers;
+    std::string currentNumber;
+    for (char c : matrixStr) {
+        if (c == ' ') {
+            if (!currentNumber.empty()) {
+                float f = std::stof(currentNumber);
+                numbers.push_back(f);
+                currentNumber.clear();
+            }
+        } else {
+            currentNumber.push_back(c);
+        }
+    }
+    if (!currentNumber.empty()) {
+        const float f = std::stof(currentNumber);
+        numbers.push_back(f);
+    }
+
+    aiMatrix4x4 transformMatrix;
+    transformMatrix.a1 = numbers[0];
+    transformMatrix.b1 = numbers[1];
+    transformMatrix.c1 = numbers[2];
+    transformMatrix.d1 = 0;
+
+    transformMatrix.a2 = numbers[3];
+    transformMatrix.b2 = numbers[4];
+    transformMatrix.c2 = numbers[5];
+    transformMatrix.d2 = 0;
+
+    transformMatrix.a3 = numbers[6];
+    transformMatrix.b3 = numbers[7];
+    transformMatrix.c3 = numbers[8];
+    transformMatrix.d3 = 0;
+
+    transformMatrix.a4 = numbers[9];
+    transformMatrix.b4 = numbers[10];
+    transformMatrix.c4 = numbers[11];
+    transformMatrix.d4 = 1;
+
+    return transformMatrix;
+}
+
+bool parseColor(const char *color, aiColor4D &diffuse) {
+    if (nullptr == color) {
+        return false;
+    }
+
+    if (!validateColorString(color)) {
+        return false;
+    }
+
+    if ('#' != color[0]) {
+        return false;
+    }
+
+    char r[3] = { color[1], color[2], '\0' };
+    diffuse.r = static_cast<ai_real>(strtol(r, nullptr, 16)) / ai_real(255.0);
+
+    char g[3] = { color[3], color[4], '\0' };
+    diffuse.g = static_cast<ai_real>(strtol(g, nullptr, 16)) / ai_real(255.0);
+
+    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);
+    if (ColRGB_Len == len) {
+        return true;
+    }
+
+    char a[3] = { color[7], color[8], '\0' };
+    diffuse.a = static_cast<ai_real>(strtol(a, nullptr, 16)) / ai_real(255.0);
+
+    return true;
+}
+
+void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
+    const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
+    aiColor4D diffuse;
+    if (parseColor(color, diffuse)) {
+        mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
+    }
+}
+
+} // namespace
+
+XmlSerializer::XmlSerializer(XmlParser *xmlParser) :
+        mResourcesDictionnary(),
+        mMeshCount(0),
+        mXmlParser(xmlParser) {
+    ai_assert(nullptr != xmlParser);
+}
+
+XmlSerializer::~XmlSerializer() {
+    for (auto &it : mResourcesDictionnary) {
+        delete it.second;
+    }
+}
+
+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()) {
+        return;
+    }
+
+    XmlNode resNode = node.child(XmlTag::resources);
+    for (auto &currentNode : resNode.children()) {
+        const std::string currentNodeName = currentNode.name();
+        if (currentNodeName == XmlTag::texture_2d) {
+            ReadEmbeddecTexture(currentNode);
+        } else if (currentNodeName == XmlTag::texture_group) {
+            ReadTextureGroup(currentNode);
+        } else if (currentNodeName == XmlTag::object) {
+            ReadObject(currentNode);
+        } else if (currentNodeName == XmlTag::basematerials) {
+            ReadBaseMaterials(currentNode);
+        } else if (currentNodeName == XmlTag::meta) {
+            ReadMetadata(currentNode);
+        }
+    }
+    StoreMaterialsInScene(scene);
+    XmlNode buildNode = node.child(XmlTag::build);
+    if (buildNode.empty()) {
+        return;
+    }
+
+    for (auto &currentNode : buildNode.children()) {
+        const std::string currentNodeName = currentNode.name();
+        if (currentNodeName == XmlTag::item) {
+            int objectId = IdNotSet;
+            std::string transformationMatrixStr;
+            aiMatrix4x4 transformationMatrix;
+            getNodeAttribute(currentNode, D3MF::XmlTag::objectid, objectId);
+            bool hasTransform = getNodeAttribute(currentNode, D3MF::XmlTag::transform, transformationMatrixStr);
+
+            auto it = mResourcesDictionnary.find(objectId);
+            if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
+                Object *obj = static_cast<Object *>(it->second);
+                if (hasTransform) {
+                    transformationMatrix = parseTransformMatrix(transformationMatrixStr);
+                }
+
+                addObjectToNode(scene->mRootNode, obj, transformationMatrix);
+            }
+        }
+    }
+
+    // import the metadata
+    if (!mMetaData.empty()) {
+        const size_t numMeta = mMetaData.size();
+        scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
+        for (size_t i = 0; i < numMeta; ++i) {
+            aiString val(mMetaData[i].value);
+            scene->mMetaData->Set(static_cast<unsigned int>(i), mMetaData[i].name, val);
+        }
+    }
+
+    // import the meshes, materials are already stored
+    scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
+    if (scene->mNumMeshes != 0) {
+        scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
+        for (auto &it : mResourcesDictionnary) {
+            if (it.second->getType() == ResourceType::RT_Object) {
+                Object *obj = static_cast<Object *>(it.second);
+                ai_assert(nullptr != obj);
+                for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
+                    scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
+                }
+            }
+        }
+    }
+}
+
+void XmlSerializer::addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
+    ai_assert(nullptr != obj);
+
+    aiNode *sceneNode = new aiNode(obj->mName);
+    sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
+    sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
+    std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
+
+    sceneNode->mTransformation = nodeTransform;
+    if (nullptr != parent) {
+        parent->addChildren(1, &sceneNode);
+    }
+
+    for (Assimp::D3MF::Component c : obj->mComponents) {
+        auto it = mResourcesDictionnary.find(c.mObjectId);
+        if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
+            addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
+        }
+    }
+}
+
+void XmlSerializer::ReadObject(XmlNode &node) {
+    int id = IdNotSet, pid = IdNotSet, pindex = IdNotSet;
+    bool hasId = getNodeAttribute(node, XmlTag::id, id);
+    if (!hasId) {
+        return;
+    }
+
+    bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
+    bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
+
+    Object *obj = new Object(id);
+    for (XmlNode &currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == D3MF::XmlTag::mesh) {
+            auto mesh = ReadMesh(currentNode);
+            mesh->mName.Set(ai_to_string(id));
+
+            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];
+                }
+            }
+
+            obj->mMeshes.push_back(mesh);
+            obj->mMeshIndex.push_back(mMeshCount);
+            mMeshCount++;
+        } else if (currentName == D3MF::XmlTag::components) {
+            for (XmlNode &currentSubNode : currentNode.children()) {
+                const std::string subNodeName = currentSubNode.name();
+                if (subNodeName == D3MF::XmlTag::component) {
+                    int objectId = IdNotSet;
+                    std::string componentTransformStr;
+                    aiMatrix4x4 componentTransform;
+                    if (getNodeAttribute(currentSubNode, D3MF::XmlTag::transform, componentTransformStr)) {
+                        componentTransform = parseTransformMatrix(componentTransformStr);
+                    }
+
+                    if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
+                        obj->mComponents.push_back({ objectId, componentTransform });
+                    }
+                }
+            }
+        }
+    }
+
+    mResourcesDictionnary.insert(std::make_pair(id, obj));
+}
+
+aiMesh *XmlSerializer::ReadMesh(XmlNode &node) {
+    if (node.empty()) {
+        return nullptr;
+    }
+
+    aiMesh *mesh = new aiMesh();
+    for (XmlNode &currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == XmlTag::vertices) {
+            ImportVertices(currentNode, mesh);
+        } else if (currentName == XmlTag::triangles) {
+            ImportTriangles(currentNode, mesh);
+        }
+    }
+
+    return mesh;
+}
+
+void XmlSerializer::ReadMetadata(XmlNode &node) {
+    pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
+    const std::string name = attribute.as_string();
+    const std::string value = node.value();
+    if (name.empty()) {
+        return;
+    }
+
+    MetaEntry entry;
+    entry.name = name;
+    entry.value = value;
+    mMetaData.push_back(entry);
+}
+
+void XmlSerializer::ImportVertices(XmlNode &node, aiMesh *mesh) {
+    ai_assert(nullptr != mesh);
+
+    std::vector<aiVector3D> vertices;
+    for (XmlNode &currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == XmlTag::vertex) {
+            vertices.push_back(ReadVertex(currentNode));
+        }
+    }
+
+    mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
+    mesh->mVertices = new aiVector3D[mesh->mNumVertices];
+    std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
+}
+
+void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
+    std::vector<aiFace> faces;
+    for (XmlNode &currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        if (currentName == XmlTag::triangle) {
+            int pid = IdNotSet, p1 = IdNotSet;
+            bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
+            bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
+
+            if (hasPid && hasP1) {
+                auto it = mResourcesDictionnary.find(pid);
+                if (it != mResourcesDictionnary.end()) {
+                    if (it->second->getType() == ResourceType::RT_BaseMaterials) {
+                        BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
+                        mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
+                    } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
+                        if (mesh->mTextureCoords[0] == nullptr) {
+                            Texture2DGroup *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()) {
+                                    mesh->mMaterialIndex = static_cast<unsigned int>(i);
+                                }
+                            }
+                            mesh->mTextureCoords[0] = new aiVector3D[group->mTex2dCoords.size()];
+                            for (unsigned int i = 0; i < group->mTex2dCoords.size(); ++i) {
+                                mesh->mTextureCoords[0][i] = aiVector3D(group->mTex2dCoords[i].x, group->mTex2dCoords[i].y, 0);
+                            }
+                        }
+                    } 
+                }
+            }
+
+            aiFace face = ReadTriangle(currentNode);
+            faces.push_back(face);
+        }
+    }
+
+    mesh->mNumFaces = static_cast<unsigned int>(faces.size());
+    mesh->mFaces = new aiFace[mesh->mNumFaces];
+    mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
+
+    std::copy(faces.begin(), faces.end(), mesh->mFaces);
+}
+
+void XmlSerializer::ReadBaseMaterials(XmlNode &node) {
+    int id = IdNotSet;
+    if (getNodeAttribute(node, D3MF::XmlTag::id, id)) {
+        BaseMaterials *baseMaterials = new BaseMaterials(id);
+
+        for (XmlNode &currentNode : node.children()) {
+            const std::string currentName = currentNode.name();
+            if (currentName == XmlTag::basematerials_base) {
+                baseMaterials->mMaterialIndex.push_back(static_cast<unsigned int>(mMaterials.size()));
+                mMaterials.push_back(readMaterialDef(currentNode, id));
+            }
+        }
+
+        mResourcesDictionnary.insert(std::make_pair(id, baseMaterials));
+    }
+}
+
+void XmlSerializer::ReadEmbeddecTexture(XmlNode &node) {
+    if (node.empty()) {
+        return;
+    }
+
+    std::string value;
+    EmbeddedTexture *tex2D = nullptr;
+    if (XmlParser::getStdStrAttribute(node, XmlTag::id, value)) {
+        tex2D = new EmbeddedTexture(atoi(value.c_str()));
+    }
+    if (nullptr == tex2D) {
+        return;
+    }
+
+    if (XmlParser::getStdStrAttribute(node, XmlTag::path, value)) {
+        tex2D->mPath = value;
+    }
+    if (XmlParser::getStdStrAttribute(node, XmlTag::texture_content_type, value)) {
+        tex2D->mContentType = value;
+    }
+    if (XmlParser::getStdStrAttribute(node, XmlTag::texture_tilestyleu, value)) {
+        tex2D->mTilestyleU = value;
+    }
+    if (XmlParser::getStdStrAttribute(node, XmlTag::texture_tilestylev, value)) {
+        tex2D->mTilestyleV = value;
+    }
+    mEmbeddedTextures.emplace_back(tex2D);
+    StoreEmbeddedTexture(tex2D);
+}
+
+void XmlSerializer::StoreEmbeddedTexture(EmbeddedTexture *tex) {
+    aiMaterial *mat = new aiMaterial;
+    aiString s;
+    s.Set(ai_to_string(tex->mId).c_str());
+    mat->AddProperty(&s, AI_MATKEY_NAME);
+    const std::string name = "*" + tex->mPath;
+    s.Set(name);
+    mat->AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
+
+    aiColor3D col;
+    mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_DIFFUSE);
+    mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_AMBIENT);
+    mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_EMISSIVE);
+    mat->AddProperty<aiColor3D>(&col, 1, AI_MATKEY_COLOR_SPECULAR);
+    mMaterials.emplace_back(mat);
+}
+
+void XmlSerializer::ReadTextureCoords2D(XmlNode &node, Texture2DGroup *tex2DGroup) {
+    if (node.empty() || nullptr == tex2DGroup) {
+        return;
+    }
+
+    int id = IdNotSet;
+    if (XmlParser::getIntAttribute(node, "texid", id)) {
+        tex2DGroup->mTexId = id;
+    }
+
+    double value = 0.0;
+    for (XmlNode currentNode : node.children()) {
+        const std::string currentName = currentNode.name();
+        aiVector2D texCoord;
+        if (currentName == XmlTag::texture_2d_coord) {
+            XmlParser::getDoubleAttribute(currentNode, XmlTag::texture_cuurd_u, value);
+            texCoord.x = (ai_real)value;
+            XmlParser::getDoubleAttribute(currentNode, XmlTag::texture_cuurd_v, value);
+            texCoord.y = (ai_real)value;
+            tex2DGroup->mTex2dCoords.push_back(texCoord);
+        }
+    }
+}
+
+void XmlSerializer::ReadTextureGroup(XmlNode &node) {
+    if (node.empty()) {
+        return;
+    }
+
+    int id = IdNotSet;
+    if (!XmlParser::getIntAttribute(node, XmlTag::id, id)) {
+        return;
+    }
+
+    Texture2DGroup *group = new Texture2DGroup(id);
+    ReadTextureCoords2D(node, group);
+    mResourcesDictionnary.insert(std::make_pair(id, group));
+}
+
+aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basematerialsId) {
+    aiMaterial *material = new aiMaterial();
+    material->mNumProperties = 0;
+    std::string name;
+    bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
+
+    std::string stdMaterialName;
+    const std::string strId(ai_to_string(basematerialsId));
+    stdMaterialName += "id";
+    stdMaterialName += strId;
+    stdMaterialName += "_";
+    if (hasName) {
+        stdMaterialName += std::string(name);
+    } else {
+        stdMaterialName += "basemat_";
+        stdMaterialName += ai_to_string(mMaterials.size());
+    }
+
+    aiString assimpMaterialName(stdMaterialName);
+    material->AddProperty(&assimpMaterialName, AI_MATKEY_NAME);
+
+    assignDiffuseColor(node, material);
+
+    return material;
+}
+
+void XmlSerializer::StoreMaterialsInScene(aiScene *scene) {
+    if (nullptr == scene || mMaterials.empty()) {
+        return;
+    }
+
+    scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size());
+    scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
+    for (size_t i = 0; i < mMaterials.size(); ++i) {
+        scene->mMaterials[i] = mMaterials[i];
+    }
+}
+
+} // namespace D3MF
+} // namespace Assimp

+ 52 - 14
include/assimp/Defines.h → code/AssetLib/3MF/XmlSerializer.h

@@ -3,6 +3,7 @@ Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
 Copyright (c) 2006-2021, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -37,22 +38,59 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 ----------------------------------------------------------------------
 */
-
 #pragma once
-#ifndef AI_DEFINES_H_INC
-#define AI_DEFINES_H_INC
 
-#ifdef __GNUC__
-#   pragma GCC system_header
-#endif
+#include <assimp/XmlParser.h>
+#include <assimp/mesh.h>
+#include <vector>
+#include <map>
+
+struct aiNode;
+struct aiMesh;
+struct aiMaterial;
+
+namespace Assimp {
+namespace D3MF {
+
+class Resource;
+class D3MFOpcPackage;
+class Object;
+class Texture2DGroup;
+class EmbeddedTexture;
+
+class XmlSerializer {
+public:
+    XmlSerializer(XmlParser *xmlParser);
+    ~XmlSerializer();
+    void ImportXml(aiScene *scene);
 
-// We need those constants, workaround for any platforms where nobody defined them yet
-#if (!defined SIZE_MAX)
-#   define SIZE_MAX (~((size_t)0))
-#endif
+private:
+    void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform);
+    void ReadObject(XmlNode &node);
+    aiMesh *ReadMesh(XmlNode &node);
+    void ReadMetadata(XmlNode &node);
+    void ImportVertices(XmlNode &node, aiMesh *mesh);
+    void ImportTriangles(XmlNode &node, aiMesh *mesh);
+    void ReadBaseMaterials(XmlNode &node);
+    void ReadEmbeddecTexture(XmlNode &node);
+    void StoreEmbeddedTexture(EmbeddedTexture *tex);
+    void ReadTextureCoords2D(XmlNode &node, Texture2DGroup *tex2DGroup);
+    void ReadTextureGroup(XmlNode &node);
+    aiMaterial *readMaterialDef(XmlNode &node, unsigned int basematerialsId);
+    void StoreMaterialsInScene(aiScene *scene);
 
-#if (!defined UINT_MAX)
-#   define UINT_MAX (~((unsigned int)0))
-#endif
+private:
+    struct MetaEntry {
+        std::string name;
+        std::string value;
+    };
+    std::vector<MetaEntry> mMetaData;
+    std::vector<EmbeddedTexture *> mEmbeddedTextures;
+    std::vector<aiMaterial *> mMaterials;
+    std::map<unsigned int, Resource *> mResourcesDictionnary;
+    unsigned int mMeshCount;
+    XmlParser *mXmlParser;
+};
 
-#endif // AI_DEINES_H_INC
+} // namespace D3MF
+} // namespace Assimp

+ 5 - 5
code/AssetLib/AC/ACLoader.h

@@ -63,7 +63,7 @@ namespace Assimp {
 class AC3DImporter : public BaseImporter {
 public:
     AC3DImporter();
-    ~AC3DImporter();
+    ~AC3DImporter() override;
 
     // Represents an AC3D material
     struct Material {
@@ -185,25 +185,25 @@ public:
      * See BaseImporter::CanRead() for details.
      */
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
-            bool checkSig) const;
+            bool checkSig) const override;
 
 protected:
     // -------------------------------------------------------------------
     /** Return importer meta information.
      * See #BaseImporter::GetInfo for the details */
-    const aiImporterDesc *GetInfo() const;
+    const aiImporterDesc *GetInfo() const override;
 
     // -------------------------------------------------------------------
     /** Imports the given file into the given scene structure.
      * See BaseImporter::InternReadFile() for details*/
     void InternReadFile(const std::string &pFile, aiScene *pScene,
-            IOSystem *pIOHandler);
+            IOSystem *pIOHandler) override;
 
     // -------------------------------------------------------------------
     /** Called prior to ReadFile().
     * The function is a request to the importer to update its configuration
     * basing on the Importer's configuration property list.*/
-    void SetupProperties(const Importer *pImp);
+    void SetupProperties(const Importer *pImp) override;
 
 private:
     // -------------------------------------------------------------------

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

@@ -303,7 +303,7 @@ void AMFImporter::ParseNode_Root() {
     }
     XmlNode node = *root;
     mUnit = ai_tolower(std::string(node.attribute("unit").as_string()));
-    
+
     mVersion = node.attribute("version").as_string();
 
     // Read attributes for node <amf>.
@@ -511,7 +511,7 @@ bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool p
     }
 
     if (extension.empty() || pCheckSig) {
-        const char *tokens[] = { "<amf" };
+        static const char * const tokens[] = { "<amf" };
         return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
     }
 

+ 4 - 4
code/AssetLib/AMF/AMFImporter.hpp

@@ -267,7 +267,7 @@ public:
     AMFImporter() AI_NO_EXCEPT;
 
     /// Default destructor.
-    ~AMFImporter();
+    ~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.
@@ -276,9 +276,9 @@ public:
     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;
-    void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
-    const aiImporterDesc *GetInfo() const;
+    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;

+ 3 - 3
code/AssetLib/AMF/AMFImporter_Geometry.cpp

@@ -75,7 +75,7 @@ void AMFImporter::ParseNode_Mesh(XmlNode &node) {
             found_volumes = true;
         }
         ParseHelper_Node_Exit();
-    } 
+    }
 
     if (!found_verts && !found_volumes) {
         mNodeElement_Cur->Child.push_back(ne);
@@ -199,9 +199,9 @@ void AMFImporter::ParseNode_Volume(XmlNode &node) {
 
     // Read attributes for node <color>.
     // and assign read data
-   
+
     ((AMFVolume *)ne)->MaterialID = node.attribute("materialid").as_string();
-     
+
     ((AMFVolume *)ne)->Type = type;
     // Check for child nodes
     bool col_read = false;

+ 4 - 5
code/AssetLib/AMF/AMFImporter_Node.hpp

@@ -48,15 +48,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef INCLUDED_AI_AMF_IMPORTER_NODE_H
 #define INCLUDED_AI_AMF_IMPORTER_NODE_H
 
-// Header files, stdlib.
+// Header files, Assimp.
+#include <assimp/scene.h>
+#include <assimp/types.h>
+
 #include <list>
 #include <string>
 #include <vector>
 
-// Header files, Assimp.
-#include "assimp/scene.h"
-#include "assimp/types.h"
-
 /// \class CAMFImporter_NodeElement
 /// Base class for elements of nodes.
 class AMFNodeElementBase {

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

@@ -69,7 +69,7 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
     }
 
     tcol = Color->Color;
-    
+
     // Check if default color must be used
     if ((tcol.r == 0) && (tcol.g == 0) && (tcol.b == 0) && (tcol.a == 0)) {
         tcol.r = 0.5f;
@@ -99,10 +99,10 @@ void AMFImporter::PostprocessHelper_CreateMeshDataArray(const AMFMesh &nodeEleme
     }
 
     // all coordinates stored as child and we need to reserve space for future push_back's.
-    vertexCoordinateArray.reserve(vn->Child.size()); 
+    vertexCoordinateArray.reserve(vn->Child.size());
 
     // colors count equal vertices count.
-    pVertexColorArray.resize(vn->Child.size()); 
+    pVertexColorArray.resize(vn->Child.size());
     col_idx = 0;
 
     // Inside vertices collect all data and place to arrays
@@ -690,7 +690,7 @@ void AMFImporter::Postprocess_BuildConstellation(AMFConstellation &pConstellatio
         if (ne->Type == AMFNodeElementBase::ENET_Metadata) continue;
         if (ne->Type != AMFNodeElementBase::ENET_Instance) throw DeadlyImportError("Only <instance> nodes can be in <constellation>.");
 
-        // create alias for conveniance
+        // create alias for convenience
         AMFInstance &als = *((AMFInstance *)ne);
         // find referenced object
         if (!Find_ConvertedNode(als.ObjectID, nodeArray, &found_node)) Throw_ID_NotFound(als.ObjectID);

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

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -106,7 +104,7 @@ bool ASEImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
     }
 
     if ((!extension.length() || cs) && pIOHandler) {
-        const char *tokens[] = { "*3dsmax_asciiexport" };
+        static const char * const tokens[] = { "*3dsmax_asciiexport" };
         return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
     }
     return false;
@@ -683,7 +681,7 @@ void ASEImporter::BuildNodes(std::vector<BaseNode *> &nodes) {
         }
     }
 
-    // Are there ane orphaned nodes?
+    // Are there any orphaned nodes?
     if (!aiList.empty()) {
         std::vector<aiNode *> apcNodes;
         apcNodes.reserve(aiList.size() + pcScene->mRootNode->mNumChildren);

+ 5 - 20
code/AssetLib/ASE/ASELoader.h

@@ -62,42 +62,37 @@ namespace Assimp {
 class ASEImporter : public BaseImporter {
 public:
     ASEImporter();
-    ~ASEImporter();
+    ~ASEImporter() override;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.
      * See BaseImporter::CanRead() for details.
      */
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+        bool checkSig) const override;
 
 protected:
-
     // -------------------------------------------------------------------
     /** Return importer meta information.
      * See #BaseImporter::GetInfo for the details
      */
-    const aiImporterDesc* GetInfo () const;
-
+    const aiImporterDesc* GetInfo () const override;
 
     // -------------------------------------------------------------------
     /** Imports the given file into the given scene structure.
     * See BaseImporter::InternReadFile() for details
     */
     void InternReadFile( const std::string& pFile, aiScene* pScene,
-        IOSystem* pIOHandler);
-
+        IOSystem* pIOHandler) override;
 
     // -------------------------------------------------------------------
     /** Called prior to ReadFile().
     * The function is a request to the importer to update its configuration
     * basing on the Importer's configuration property list.
     */
-    void SetupProperties(const Importer* pImp);
-
+    void SetupProperties(const Importer* pImp) override;
 
 private:
-
     // -------------------------------------------------------------------
     /** Generate normal vectors basing on smoothing groups
      * (in some cases the normal are already contained in the file)
@@ -106,7 +101,6 @@ private:
      */
     bool GenerateNormals(ASE::Mesh& mesh);
 
-
     // -------------------------------------------------------------------
     /** Create valid vertex/normal/UV/color/face lists.
      *  All elements are unique, faces have only one set of indices
@@ -115,51 +109,43 @@ private:
      */
     void BuildUniqueRepresentation(ASE::Mesh& mesh);
 
-
     /** Create one-material-per-mesh meshes ;-)
      * \param mesh Mesh to work with
      *  \param Receives the list of all created meshes
      */
     void ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOut);
 
-
     // -------------------------------------------------------------------
     /** Convert a material to a aiMaterial object
      * \param mat Input material
      */
     void ConvertMaterial(ASE::Material& mat);
 
-
     // -------------------------------------------------------------------
     /** Setup the final material indices for each mesh
      */
     void BuildMaterialIndices();
 
-
     // -------------------------------------------------------------------
     /** Build the node graph
      */
     void BuildNodes(std::vector<ASE::BaseNode*>& nodes);
 
-
     // -------------------------------------------------------------------
     /** Build output cameras
      */
     void BuildCameras();
 
-
     // -------------------------------------------------------------------
     /** Build output lights
      */
     void BuildLights();
 
-
     // -------------------------------------------------------------------
     /** Build output animations
      */
     void BuildAnimations(const std::vector<ASE::BaseNode*>& nodes);
 
-
     // -------------------------------------------------------------------
     /** Add sub nodes to a node
      *  \param pcParent parent node to be filled
@@ -183,7 +169,6 @@ private:
     void GenerateDefaultMaterial();
 
 protected:
-
     /** Parser instance */
     ASE::Parser* mParser;
 

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

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

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

@@ -95,8 +95,8 @@ struct Material : public D3DS::Material {
     Material(Material &&other) AI_NO_EXCEPT
             : D3DS::Material(std::move(other)),
               avSubMaterials(std::move(other.avSubMaterials)),
-              pcInstance(std::move(other.pcInstance)),
-              bNeed(std::move(other.bNeed)) {
+              pcInstance(other.pcInstance),
+              bNeed(other.bNeed) {
         other.pcInstance = nullptr;
     }
 
@@ -108,8 +108,8 @@ struct Material : public D3DS::Material {
         //D3DS::Material::operator=(std::move(other));
 
         avSubMaterials = std::move(other.avSubMaterials);
-        pcInstance = std::move(other.pcInstance);
-        bNeed = std::move(other.bNeed);
+        pcInstance = other.pcInstance;
+        bNeed = other.bNeed;
 
         other.pcInstance = nullptr;
 

+ 4 - 2
code/AssetLib/Assbin/AssbinExporter.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,16 +42,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file AssbinExporter.h
  * ASSBIN Exporter Main Header
  */
+#pragma once
 #ifndef AI_ASSBINEXPORTER_H_INC
 #define AI_ASSBINEXPORTER_H_INC
 
 #include <assimp/defs.h>
 
+#ifndef ASSIMP_BUILD_NO_EXPORT
+
 // nothing really needed here - reserved for future use like properties
 namespace Assimp {
 
 void ASSIMP_API ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/);
 
 }
-
+#endif 
 #endif // AI_ASSBINEXPORTER_H_INC

+ 12 - 13
code/AssetLib/Assbin/AssbinFileWriter.cpp

@@ -43,13 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
 #include "AssbinFileWriter.h"
-
 #include "Common/assbin_chunks.h"
 #include "PostProcessing/ProcessHelper.h"
 
 #include <assimp/Exceptional.h>
 #include <assimp/version.h>
-#include <assimp/Exporter.hpp>
 #include <assimp/IOStream.hpp>
 
 #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
@@ -58,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "../contrib/zlib/zlib.h"
 #endif
 
-#include <time.h>
+#include <ctime>
 
 #if _MSC_VER
 #pragma warning(push)
@@ -172,7 +170,7 @@ inline size_t Write<aiQuaternion>(IOStream *stream, const aiQuaternion &v) {
     t += Write<float>(stream, v.z);
     ai_assert(t == 16);
 
-    return 16;
+    return t;
 }
 
 // -----------------------------------------------------------------------------------
@@ -277,7 +275,7 @@ public:
         // empty
     }
 
-    virtual ~AssbinChunkWriter() {
+    ~AssbinChunkWriter() override {
         if (container) {
             container->Write(&magic, sizeof(uint32_t), 1);
             container->Write(&cursor, sizeof(uint32_t), 1);
@@ -288,26 +286,27 @@ public:
 
     void *GetBufferPointer() { return buffer; }
 
-    // -------------------------------------------------------------------
-    virtual size_t Read(void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) {
+    size_t Read(void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override {
         return 0;
     }
-    virtual aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) {
+    
+    aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) override {
         return aiReturn_FAILURE;
     }
-    virtual size_t Tell() const {
+    
+    size_t Tell() const override {
         return cursor;
     }
-    virtual void Flush() {
+    
+    void Flush() override {
         // not implemented
     }
 
-    virtual size_t FileSize() const {
+    size_t FileSize() const override {
         return cursor;
     }
 
-    // -------------------------------------------------------------------
-    virtual size_t Write(const void *pvBuffer, size_t pSize, size_t pCount) {
+    size_t Write(const void *pvBuffer, size_t pSize, size_t pCount) override {
         pSize *= pCount;
         if (cursor + pSize > cur_size) {
             Grow(cursor + pSize);

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

@@ -406,7 +406,7 @@ void AssbinImporter::ReadBinaryMesh(IOStream *stream, aiMesh *mesh) {
             f.mIndices = new unsigned int[f.mNumIndices];
 
             for (unsigned int a = 0; a < f.mNumIndices; ++a) {
-                // Check if unsigned  short ( 16 bit  ) are big enought for the indices
+                // Check if unsigned  short ( 16 bit  ) are big enough for the indices
                 if (fitsIntoUI16(mesh->mNumVertices)) {
                     f.mIndices[a] = Read<uint16_t>(stream);
                 } else {

+ 5 - 12
code/AssetLib/Assbin/AssbinLoader.h

@@ -5,7 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -74,17 +73,11 @@ private:
     bool compressed;
 
 public:
-    virtual bool CanRead(
-        const std::string& pFile,
-        IOSystem* pIOHandler,
-        bool checkSig
-    ) const;
-    virtual const aiImporterDesc* GetInfo() const;
-    virtual void InternReadFile(
-    const std::string& pFile,
-        aiScene* pScene,
-        IOSystem* pIOHandler
-    );
+    bool CanRead(const std::string& pFile,
+        IOSystem* pIOHandler, bool checkSig) const override;
+    const aiImporterDesc* GetInfo() const override;
+    void InternReadFile(
+    const std::string& pFile,aiScene* pScene,IOSystem* pIOHandler) override;
     void ReadHeader();
     void ReadBinaryScene( IOStream * stream, aiScene* pScene );
     void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent );

+ 27 - 15
code/AssetLib/Assjson/json_exporter.cpp

@@ -41,12 +41,17 @@ public:
     enum {
         Flag_DoNotIndent = 0x1,
         Flag_WriteSpecialFloats = 0x2,
+        Flag_SkipWhitespaces = 0x4
     };
-
+    
     JSONWriter(Assimp::IOStream &out, unsigned int flags = 0u) :
-            out(out), first(), flags(flags) {
+            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
         buff.imbue(std::locale("C"));
+        if (flags & Flag_SkipWhitespaces) {
+            newline = "";
+            space = "";
+        }
     }
 
     ~JSONWriter() {
@@ -70,7 +75,7 @@ public:
     void Key(const std::string &name) {
         AddIndentation();
         Delimit();
-        buff << '\"' + name + "\": ";
+        buff << '\"' + name + "\":" << space;
     }
 
     template <typename Literal>
@@ -78,12 +83,12 @@ public:
         AddIndentation();
         Delimit();
 
-        LiteralToString(buff, name) << '\n';
+        LiteralToString(buff, name) << newline;
     }
 
     template <typename Literal>
     void SimpleValue(const Literal &s) {
-        LiteralToString(buff, s) << '\n';
+        LiteralToString(buff, s) << newline;
     }
 
     void SimpleValue(const void *buffer, size_t len) {
@@ -102,7 +107,7 @@ public:
             }
         }
 
-        buff << '\"' << cur_out << "\"\n";
+        buff << '\"' << cur_out << "\"" << newline;
         delete[] cur_out;
     }
 
@@ -115,7 +120,7 @@ public:
             }
         }
         first = true;
-        buff << "{\n";
+        buff << "{" << newline;
         PushIndent();
     }
 
@@ -123,7 +128,7 @@ public:
         PopIndent();
         AddIndentation();
         first = false;
-        buff << "}\n";
+        buff << "}" << newline;
     }
 
     void StartArray(bool is_element = false) {
@@ -135,19 +140,19 @@ public:
             }
         }
         first = true;
-        buff << "[\n";
+        buff << "[" << newline;
         PushIndent();
     }
 
     void EndArray() {
         PopIndent();
         AddIndentation();
-        buff << "]\n";
+        buff << "]" << newline;
         first = false;
     }
 
     void AddIndentation() {
-        if (!(flags & Flag_DoNotIndent)) {
+        if (!(flags & Flag_DoNotIndent) && !(flags & Flag_SkipWhitespaces)) {
             buff << indent;
         }
     }
@@ -156,7 +161,7 @@ public:
         if (!first) {
             buff << ',';
         } else {
-            buff << ' ';
+            buff << space;
             first = false;
         }
     }
@@ -227,7 +232,9 @@ private:
 
 private:
     Assimp::IOStream &out;
-    std::string indent, newline;
+    std::string indent;
+    std::string newline;
+    std::string space;
     std::stringstream buff;
     bool first;
 
@@ -765,7 +772,7 @@ void Write(JSONWriter &out, const aiScene &ai) {
     out.EndObj();
 }
 
-void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *scene, const Assimp::ExportProperties *) {
+void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *scene, const Assimp::ExportProperties *pProperties) {
     std::unique_ptr<Assimp::IOStream> str(io->Open(file, "wt"));
     if (!str) {
         throw DeadlyExportError("could not open output file");
@@ -782,7 +789,12 @@ void ExportAssimp2Json(const char *file, Assimp::IOSystem *io, const aiScene *sc
         splitter.Execute(scenecopy_tmp);
 
         // XXX Flag_WriteSpecialFloats is turned on by default, right now we don't have a configuration interface for exporters
-        JSONWriter s(*str, JSONWriter::Flag_WriteSpecialFloats);
+
+        unsigned int flags = JSONWriter::Flag_WriteSpecialFloats;
+        if (pProperties->GetPropertyBool("JSON_SKIP_WHITESPACES", false)) {
+            flags |= JSONWriter::Flag_SkipWhitespaces;
+        }
+        JSONWriter s(*str, flags);
         Write(s, *scenecopy_tmp);
 
     } catch (...) {

+ 10 - 11
code/AssetLib/Assjson/mesh_splitter.cpp

@@ -69,13 +69,12 @@ void MeshSplitter::UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh
 	for (unsigned int i = 0, end = pcNode->mNumChildren; i < end;++i)	{
 		UpdateNode ( pcNode->mChildren[i], source_mesh_map );
 	}
-	return;
 }
 
-#define WAS_NOT_COPIED 0xffffffff
+static const unsigned int WAS_NOT_COPIED = 0xffffffff;
 
-typedef std::pair <unsigned int,float> PerVertexWeight;
-typedef std::vector	<PerVertexWeight> VertexWeightTable;
+using PerVertexWeight = std::pair <unsigned int,float>;
+using VertexWeightTable = std::vector	<PerVertexWeight>;
 
 // ------------------------------------------------------------------------------------------------
 VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) {
@@ -89,7 +88,7 @@ VertexWeightTable* ComputeVertexBoneWeightTable(const aiMesh* pMesh) {
 		aiBone* bone = pMesh->mBones[i];
 		for (unsigned int a = 0; a < bone->mNumWeights;++a)	{
 			const aiVertexWeight& weight = bone->mWeights[a];
-			avPerVertexWeights[weight.mVertexId].push_back( std::make_pair(i,weight.mWeight) );
+			avPerVertexWeights[weight.mVertexId].emplace_back(i,weight.mWeight);
 		}
 	}
 	return avPerVertexWeights;
@@ -100,7 +99,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std:
 	// TODO: should better use std::(multi)set for source_mesh_map.
 
 	if (in_mesh->mNumVertices <= LIMIT)	{
-		source_mesh_map.push_back(std::make_pair(in_mesh,a));
+		source_mesh_map.emplace_back(in_mesh,a);
 		return;
 	}
 
@@ -110,7 +109,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std:
 	// we need to split this mesh into sub meshes. Estimate submesh size
 	const unsigned int sub_meshes = (in_mesh->mNumVertices / LIMIT) + 1;
 
-	// create a std::vector<unsigned int> to remember which vertices have already 
+	// create a std::vector<unsigned int> to remember which vertices have already
 	// been copied and to which position (i.e. output index)
 	std::vector<unsigned int> was_copied_to;
 	was_copied_to.resize(in_mesh->mNumVertices,WAS_NOT_COPIED);
@@ -125,7 +124,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std:
 	while (true) {
 		const unsigned int out_vertex_index = LIMIT;
 
-		aiMesh* out_mesh = new aiMesh();			
+		aiMesh* out_mesh = new aiMesh();
 		out_mesh->mNumVertices = 0;
 		out_mesh->mMaterialIndex = in_mesh->mMaterialIndex;
 
@@ -179,7 +178,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std:
 
 				// check whether we do already have this vertex
 				if (WAS_NOT_COPIED == was_copied_to[index])	{
-					iNeed++; 
+					iNeed++;
 				}
 			}
 			if (out_mesh->mNumVertices + iNeed > out_vertex_index)	{
@@ -187,7 +186,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std:
 				break;
 			}
 
-			vFaces.push_back(aiFace());
+			vFaces.emplace_back();
 			aiFace& rFace = vFaces.back();
 
 			// setup face type and number of indices
@@ -240,7 +239,7 @@ void MeshSplitter :: SplitMesh(unsigned int a, aiMesh* in_mesh, std::vector<std:
 						out_mesh->mTextureCoords[c][out_mesh->mNumVertices] = in_mesh->mTextureCoords[c][index];
 					}
 				}
-				// vertex colors 
+				// vertex colors
 				for (unsigned int c = 0;  c < AI_MAX_NUMBER_OF_COLOR_SETS;++c) {
 					if (in_mesh->HasVertexColors( c)) {
 						out_mesh->mColors[c][out_mesh->mNumVertices] = in_mesh->mColors[c][index];

+ 14 - 23
code/AssetLib/Assjson/mesh_splitter.h

@@ -22,40 +22,31 @@ struct aiNode;
 
 // ---------------------------------------------------------------------------
 /** Splits meshes of unique vertices into meshes with no more vertices than
- *  a given, configurable threshold value. 
+ *  a given, configurable threshold value.
  */
-class MeshSplitter 
-{
-
+class MeshSplitter {
 public:
-	
-	void SetLimit(unsigned int l) {
-		LIMIT = l;
-	}
+    unsigned int LIMIT;
 
-	unsigned int GetLimit() const {
-		return LIMIT;
-	}
+    void SetLimit(unsigned int l) {
+        LIMIT = l;
+    }
 
-public:
+    unsigned int GetLimit() const {
+        return LIMIT;
+    }
 
-	// -------------------------------------------------------------------
-	/** Executes the post processing step on the given imported data.
+    // -------------------------------------------------------------------
+    /** Executes the post processing step on the given imported data.
 	 * At the moment a process is not supposed to fail.
 	 * @param pScene The imported data to work at.
 	 */
-	void Execute( aiScene* pScene);
-
+    void Execute(aiScene *pScene);
 
 private:
+    void UpdateNode(aiNode *pcNode, const std::vector<std::pair<aiMesh *, unsigned int>> &source_mesh_map);
+    void SplitMesh(unsigned int index, aiMesh *mesh, std::vector<std::pair<aiMesh *, unsigned int>> &source_mesh_map);
 
-	void UpdateNode(aiNode* pcNode, const std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map);
-	void SplitMesh (unsigned int index, aiMesh* mesh, std::vector<std::pair<aiMesh*, unsigned int> >& source_mesh_map);
-
-public:
-
-	unsigned int LIMIT;
 };
 
 #endif // INCLUDED_MESH_SPLITTER
-

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

@@ -50,7 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 #include <assimp/Exporter.hpp>
 
-namespace Assimp   { 
+namespace Assimp   {
 
 void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
 {

+ 1 - 0
code/AssetLib/Assxml/AssxmlExporter.h

@@ -43,6 +43,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file AssxmlExporter.h
  * ASSXML Exporter Main Header
  */
+#pragma once
 #ifndef AI_ASSXMLEXPORTER_H_INC
 #define AI_ASSXMLEXPORTER_H_INC
 

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

@@ -168,7 +168,7 @@ static void WriteNode(const aiNode *node, IOStream *io, unsigned int depth) {
 }
 
 // -----------------------------------------------------------------------------------
-// Some chuncks of text will need to be encoded for XML
+// Some chunks of text will need to be encoded for XML
 // http://stackoverflow.com/questions/5665231/most-efficient-way-to-escape-xml-html-in-c-string#5665377
 static std::string encodeXML(const std::string &data) {
     std::string buffer;
@@ -601,7 +601,7 @@ static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene,
                 ioprintf(io, "\t\t<TextureCoords num=\"%u\" set=\"%u\" name=\"%s\" num_components=\"%u\"> \n",
                          mesh->mNumVertices,
                          a,
-                         mesh->mTextureCoordsNames[a].C_Str(),
+                         (mesh->HasTextureCoordsName(a) ? mesh->GetTextureCoordsName(a)->C_Str() : ""),
                          mesh->mNumUVComponents[a]);
 
                 if (!shortened) {

+ 1 - 2
code/AssetLib/Assxml/AssxmlFileWriter.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file AssxmlFileWriter.h
  *  @brief Declaration of Assxml file writer.
  */
-
+#pragma once
 #ifndef AI_ASSXMLFILEWRITER_H_INC
 #define AI_ASSXMLFILEWRITER_H_INC
 

+ 1 - 1
code/AssetLib/B3D/B3DImporter.cpp

@@ -143,7 +143,7 @@ AI_WONT_RETURN void B3DImporter::Oops() {
 }
 
 // ------------------------------------------------------------------------------------------------
-AI_WONT_RETURN void B3DImporter::Fail(string str) {
+AI_WONT_RETURN void B3DImporter::Fail(const string &str) {
 #ifdef DEBUG_B3D
     ASSIMP_LOG_ERROR("Error in B3D file data: ", str);
 #endif

+ 9 - 11
code/AssetLib/B3D/B3DImporter.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -40,8 +39,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
-/** @file Definition of the .b3d importer class. */
-
+/**
+ *  @file Definition of the .b3d importer class.
+ */
+#pragma once
 #ifndef AI_B3DIMPORTER_H_INC
 #define AI_B3DIMPORTER_H_INC
 
@@ -62,14 +63,12 @@ namespace Assimp{
 class B3DImporter : public BaseImporter{
 public:
     B3DImporter() = default;
-    virtual ~B3DImporter();
-
-    virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
+    ~B3DImporter() override;
+    bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override;
 
 protected:
-
-    virtual const aiImporterDesc* GetInfo () const;
-    virtual void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
+    const aiImporterDesc* GetInfo () const override;
+    void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
 
 private:
 
@@ -96,7 +95,7 @@ private:
     };
 
     AI_WONT_RETURN void Oops() AI_WONT_RETURN_SUFFIX;
-    AI_WONT_RETURN void Fail( std::string str ) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void Fail(const std::string &str) AI_WONT_RETURN_SUFFIX;
 
     void ReadTEXS();
     void ReadBRUS();
@@ -113,7 +112,6 @@ private:
     void ReadBB3D( aiScene *scene );
 
     size_t _pos;
-//  unsigned _size;
     std::vector<unsigned char> _buf;
     std::vector<size_t> _stack;
 

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

@@ -100,7 +100,7 @@ bool BVHLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs)
         return true;
 
     if ((!extension.length() || cs) && pIOHandler) {
-        const char *tokens[] = { "HIERARCHY" };
+        static const char * const tokens[] = { "HIERARCHY" };
         return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
     }
     return false;
@@ -178,7 +178,7 @@ void BVHLoader::ReadHierarchy(aiScene *pScene) {
 }
 
 // ------------------------------------------------------------------------------------------------
-// Reads a node and recursively its childs and returns the created node;
+// Reads a node and recursively its children and returns the created node;
 aiNode *BVHLoader::ReadNode() {
     // first token is name
     std::string nodeName = GetNextToken();

+ 1 - 1
code/AssetLib/BVH/BVHLoader.h

@@ -112,7 +112,7 @@ protected:
     /** Reads the hierarchy */
     void ReadHierarchy(aiScene *pScene);
 
-    /** Reads a node and recursively its childs and returns the created node. */
+    /** Reads a node and recursively its children and returns the created node. */
     aiNode *ReadNode();
 
     /** Reads an end node and returns the created node. */

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

@@ -476,7 +476,7 @@ public:
      *  in BlenderScene.cpp and is machine-generated.
      *  Converters are used to quickly handle objects whose
      *  exact data type is a runtime-property and not yet
-     *  known at compile time (consier Object::data).*/
+     *  known at compile time (consider Object::data).*/
     void RegisterConverters();
 
     // --------------------------------------------------------

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

@@ -113,8 +113,8 @@ BlenderImporter::~BlenderImporter() {
     delete modifier_cache;
 }
 
-static const char *Tokens[] = { "BLENDER" };
-static const char *TokensForSearch[] = { "blender" };
+static const char * const Tokens[] = { "BLENDER" };
+static const char * const TokensForSearch[] = { "blender" };
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
@@ -679,7 +679,7 @@ void BlenderImporter::BuildMaterials(ConversionData &conv_data) {
 
     BuildDefaultMaterial(conv_data);
 
-    for (std::shared_ptr<Material> mat : conv_data.materials_raw) {
+    for (const std::shared_ptr<Material> &mat : conv_data.materials_raw) {
 
         // reset per material global counters
         for (size_t i = 0; i < sizeof(conv_data.next_texture) / sizeof(conv_data.next_texture[0]); ++i) {

+ 94 - 104
code/AssetLib/Blender/BlenderLoader.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  BlenderLoader.h
  *  @brief Declaration of the Blender 3D (*.blend) importer class.
  */
+#pragma once
 #ifndef INCLUDED_AI_BLEND_LOADER_H
 #define INCLUDED_AI_BLEND_LOADER_H
 
@@ -56,149 +56,139 @@ struct aiLight;
 struct aiCamera;
 struct aiMaterial;
 
-namespace Assimp    {
-
-    // 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;
-    }
-
-    // BlenderDNA.h
-    namespace Blender {
-        class  FileDatabase;
-        struct ElemBase;
-    }
-
-    // BlenderScene.h
-    namespace Blender {
-        struct Scene;
-        struct Object;
-        struct Mesh;
-        struct Camera;
-        struct Lamp;
-        struct MTex;
-        struct Image;
-        struct Material;
-    }
-
-    // BlenderIntermediate.h
-    namespace Blender {
-        struct ConversionData;
-        template <template <typename,typename> class TCLASS, typename T> struct TempArray;
-    }
-
-    // BlenderModifier.h
-    namespace Blender {
-        class BlenderModifierShowcase;
-        class BlenderModifier;
-    }
-
-
+namespace Assimp {
+
+// 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;
+
+} // namespace Formatter
+
+// BlenderDNA.h
+namespace Blender {
+class FileDatabase;
+struct ElemBase;
+} // namespace Blender
+
+// BlenderScene.h
+namespace Blender {
+struct Scene;
+struct Object;
+struct Mesh;
+struct Camera;
+struct Lamp;
+struct MTex;
+struct Image;
+struct Material;
+} // namespace Blender
+
+// BlenderIntermediate.h
+namespace Blender {
+struct ConversionData;
+template <template <typename, typename> class TCLASS, typename T>
+struct TempArray;
+} // namespace Blender
+
+// BlenderModifier.h
+namespace Blender {
+class BlenderModifierShowcase;
+class BlenderModifier;
+} // namespace Blender
 
 // -------------------------------------------------------------------------------------------
 /** Load blenders official binary format. The actual file structure (the `DNA` how they
  *  call it is outsourced to BlenderDNA.cpp/BlenderDNA.h. This class only performs the
  *  conversion from intermediate format to aiScene. */
 // -------------------------------------------------------------------------------------------
-class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter>
-{
+class BlenderImporter : public BaseImporter, public LogFunctions<BlenderImporter> {
 public:
     BlenderImporter();
-    ~BlenderImporter();
-    bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
+    ~BlenderImporter() override;
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
 
 protected:
-    const aiImporterDesc* GetInfo () const;
-    void SetupProperties(const Importer* pImp);
-    void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
-    void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream);
-    void ExtractScene(Blender::Scene& out, const Blender::FileDatabase& file);
-    void ConvertBlendFile(aiScene* out, const Blender::Scene& in, const Blender::FileDatabase& file);
+    const aiImporterDesc *GetInfo() const override;
+    void SetupProperties(const Importer *pImp) override;
+    void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
+    void ParseBlendFile(Blender::FileDatabase &out, std::shared_ptr<IOStream> stream);
+    void ExtractScene(Blender::Scene &out, const Blender::FileDatabase &file);
+    void ConvertBlendFile(aiScene *out, const Blender::Scene &in, const Blender::FileDatabase &file);
 
 private:
-    aiNode* ConvertNode(const Blender::Scene& in,
-        const Blender::Object* obj,
-        Blender::ConversionData& conv_info,
-        const aiMatrix4x4& parentTransform
-    );
+    aiNode *ConvertNode(const Blender::Scene &in,
+            const Blender::Object *obj,
+            Blender::ConversionData &conv_info,
+            const aiMatrix4x4 &parentTransform);
 
     // --------------------
-    void ConvertMesh(const Blender::Scene& in,
-        const Blender::Object* obj,
-        const Blender::Mesh* mesh,
-        Blender::ConversionData& conv_data,
-        Blender::TempArray<std::vector,aiMesh>& temp
-    );
+    void ConvertMesh(const Blender::Scene &in,
+            const Blender::Object *obj,
+            const Blender::Mesh *mesh,
+            Blender::ConversionData &conv_data,
+            Blender::TempArray<std::vector, aiMesh> &temp);
 
     // --------------------
-    aiLight* ConvertLight(const Blender::Scene& in,
-        const Blender::Object* obj,
-        const Blender::Lamp* mesh,
-        Blender::ConversionData& conv_data
-    );
+    aiLight *ConvertLight(const Blender::Scene &in,
+            const Blender::Object *obj,
+            const Blender::Lamp *mesh,
+            Blender::ConversionData &conv_data);
 
     // --------------------
-    aiCamera* ConvertCamera(const Blender::Scene& in,
-        const Blender::Object* obj,
-        const Blender::Camera* mesh,
-        Blender::ConversionData& conv_data
-    );
+    aiCamera *ConvertCamera(const Blender::Scene &in,
+            const Blender::Object *obj,
+            const Blender::Camera *mesh,
+            Blender::ConversionData &conv_data);
 
     // --------------------
     void BuildDefaultMaterial(
-        Blender::ConversionData& conv_data
-    );
+            Blender::ConversionData &conv_data);
 
+    // --------------------
     void AddBlendParams(
-        aiMaterial* result,
-        const Blender::Material* source
-    );
+            aiMaterial *result,
+            const Blender::Material *source);
 
+    // --------------------
     void BuildMaterials(
-        Blender::ConversionData& conv_data
-    );
+            Blender::ConversionData &conv_data);
 
     // --------------------
     void ResolveTexture(
-        aiMaterial* out,
-        const Blender::Material* mat,
-        const Blender::MTex* tex,
-        Blender::ConversionData& conv_data
-    );
+            aiMaterial *out,
+            const Blender::Material *mat,
+            const Blender::MTex *tex,
+            Blender::ConversionData &conv_data);
 
     // --------------------
     void ResolveImage(
-        aiMaterial* out,
-        const Blender::Material* mat,
-        const Blender::MTex* tex,
-        const Blender::Image* img,
-        Blender::ConversionData& conv_data
-    );
+            aiMaterial *out,
+            const Blender::Material *mat,
+            const Blender::MTex *tex,
+            const Blender::Image *img,
+            Blender::ConversionData &conv_data);
 
+    // --------------------
     void AddSentinelTexture(
-        aiMaterial* out,
-        const Blender::Material* mat,
-        const Blender::MTex* tex,
-        Blender::ConversionData& conv_data
-    );
+            aiMaterial *out,
+            const Blender::Material *mat,
+            const Blender::MTex *tex,
+            Blender::ConversionData &conv_data);
 
 private: // static stuff, mostly logging and error reporting.
-
     // --------------------
-    static void CheckActualType(const Blender::ElemBase* dt,
-        const char* check
-    );
+    static void CheckActualType(const Blender::ElemBase *dt,
+            const char *check);
 
     // --------------------
-    static void NotSupportedObjectType(const Blender::Object* obj,
-        const char* type
-    );
-
+    static void NotSupportedObjectType(const Blender::Object *obj,
+            const char *type);
 
 private:
-
-    Blender::BlenderModifierShowcase* modifier_cache;
+    Blender::BlenderModifierShowcase *modifier_cache;
 
 }; // !class BlenderImporter
 

+ 9 - 9
code/AssetLib/Blender/BlenderModifier.h

@@ -52,9 +52,9 @@ namespace Assimp {
 namespace Blender {
 
 // -------------------------------------------------------------------------------------------
-/** 
+/**
  *  Dummy base class for all blender modifiers. Modifiers are reused between imports, so
- *  they should be stateless and not try to cache model data. 
+ *  they should be stateless and not try to cache model data.
  */
 // -------------------------------------------------------------------------------------------
 class BlenderModifier {
@@ -67,7 +67,7 @@ public:
     }
 
     // --------------------
-    /** 
+    /**
      *  Check if *this* modifier is active, given a ModifierData& block.
      */
     virtual bool IsActive( const ModifierData& /*modin*/) {
@@ -75,10 +75,10 @@ public:
     }
 
     // --------------------
-    /** 
+    /**
      *  Apply the modifier to a given output node. The original data used
      *  to construct the node is given as well. Not called unless IsActive()
-     *  was called and gave positive response. 
+     *  was called and gave positive response.
      */
     virtual void DoIt(aiNode& /*out*/,
         ConversionData& /*conv_data*/,
@@ -92,8 +92,8 @@ public:
 };
 
 // -------------------------------------------------------------------------------------------
-/** 
- *  Manage all known modifiers and instance and apply them if necessary 
+/**
+ *  Manage all known modifiers and instance and apply them if necessary
  */
 // -------------------------------------------------------------------------------------------
 class BlenderModifierShowcase {
@@ -113,8 +113,8 @@ private:
 // MODIFIERS /////////////////////////////////////////////////////////////////////////////////
 
 // -------------------------------------------------------------------------------------------
-/** 
- *  Mirror modifier. Status: implemented. 
+/**
+ *  Mirror modifier. Status: implemented.
  */
 // -------------------------------------------------------------------------------------------
 class BlenderModifier_Mirror : public BlenderModifier {

+ 6 - 0
code/AssetLib/C4D/C4DImporter.cpp

@@ -146,8 +146,14 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
         ThrowException("failed to read document " + pFile);
     }
 
+    // Generate the root-node
     pScene->mRootNode = new aiNode("<C4DRoot>");
 
+    // convert left-handed to right-handed
+    pScene->mRootNode->mTransformation.a1 = 0.01f;
+    pScene->mRootNode->mTransformation.b2 = 0.01f;
+    pScene->mRootNode->mTransformation.c3 = -0.01f;
+
     // first convert all materials
     ReadMaterials(doc->GetFirstMaterial());
 

+ 6 - 6
code/AssetLib/COB/COBLoader.cpp

@@ -110,7 +110,7 @@ bool COBImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
     }
 
     else if ((!extension.length() || checkSig) && pIOHandler) {
-        const char *tokens[] = { "Caligary" };
+        static const char * const tokens[] = { "Caligary" };
         return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
     }
     return false;
@@ -230,7 +230,7 @@ void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 }
 
 // ------------------------------------------------------------------------------------------------
-void ConvertTexture(std::shared_ptr<Texture> tex, aiMaterial *out, aiTextureType type) {
+void ConvertTexture(const std::shared_ptr<Texture> &tex, aiMaterial *out, aiTextureType type) {
     const aiString path(tex->path);
     out->AddProperty(&path, AI_MATKEY_TEXTURE(type, 0));
     out->AddProperty(&tex->transform, 1, AI_MATKEY_UVTRANSFORM(type, 0));
@@ -586,7 +586,7 @@ void COBImporter::ReadUnit_Ascii(Scene &out, LineSplitter &splitter, const Chunk
         return;
     }
 
-    // parent chunks preceede their childs, so we should have the
+    // parent chunks preceede their children, so we should have the
     // corresponding chunk already.
     for (std::shared_ptr<Node> &nd : out.nodes) {
         if (nd->id == nfo.parent_id) {
@@ -668,7 +668,7 @@ void COBImporter::ReadCame_Ascii(Scene &out, LineSplitter &splitter, const Chunk
 
     ReadBasicNodeInfo_Ascii(msh, ++splitter, nfo);
 
-    // skip the next line, we don't know this differenciation between a
+    // skip the next line, we don't know this differentiation between a
     // standard camera and a panoramic camera.
     ++splitter;
 }
@@ -884,7 +884,7 @@ void COBImporter::ReadBinaryFile(Scene &out, StreamReaderLE *reader) {
         std::string type;
         type += reader->GetI1();
         type += reader->GetI1();
-        type += reader->GetI1(); 
+        type += reader->GetI1();
         type += reader->GetI1();
 
         ChunkInfo nfo;
@@ -1169,7 +1169,7 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
 
     const chunk_guard cn(nfo, reader);
 
-    // parent chunks preceede their childs, so we should have the
+    // parent chunks preceede their children, so we should have the
     // corresponding chunk already.
     for (std::shared_ptr<Node> &nd : out.nodes) {
         if (nd->id == nfo.parent_id) {

+ 55 - 59
code/AssetLib/COB/COBLoader.h

@@ -51,104 +51,100 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 struct aiNode;
 
-namespace Assimp    {
-    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;
-    }
-
-    // COBScene.h
-    namespace COB {
-        struct ChunkInfo;
-        struct Node;
-        struct Scene;
-    }
+namespace Assimp {
+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;
+} // namespace Formatter
+
+// COBScene.h
+namespace COB {
+struct ChunkInfo;
+struct Node;
+struct Scene;
+} // namespace COB
 
 // -------------------------------------------------------------------------------------------
 /** Importer class to load TrueSpace files (cob,scn) up to v6.
  *
  *  Currently relatively limited, loads only ASCII files and needs more test coverage. */
 // -------------------------------------------------------------------------------------------
-class COBImporter : public BaseImporter
-{
+class COBImporter : public BaseImporter {
 public:
     COBImporter();
-    ~COBImporter();
-    
+    ~COBImporter() override;
+
     // --------------------
-    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
+            bool checkSig) const override;
 
 protected:
-
     // --------------------
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc *GetInfo() const override;
 
     // --------------------
-    void SetupProperties(const Importer* pImp);
+    void SetupProperties(const Importer *pImp) override;
 
     // --------------------
-    void InternReadFile( const std::string& pFile, aiScene* pScene,
-        IOSystem* pIOHandler);
+    void InternReadFile(const std::string &pFile, aiScene *pScene,
+            IOSystem *pIOHandler) override;
 
 private:
-
     // -------------------------------------------------------------------
     /** Prepend 'COB: ' and throw msg.*/
-    AI_WONT_RETURN static void ThrowException(const std::string& msg) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN static void ThrowException(const std::string &msg) AI_WONT_RETURN_SUFFIX;
 
     // -------------------------------------------------------------------
     /** @brief Read from an ascii scene/object file
      *  @param out Receives output data.
      *  @param stream Stream to read from. */
-    void ReadAsciiFile(COB::Scene& out, StreamReaderLE* stream);
+    void ReadAsciiFile(COB::Scene &out, StreamReaderLE *stream);
 
     // -------------------------------------------------------------------
     /** @brief Read from a binary scene/object file
      *  @param out Receives output data.
      *  @param stream Stream to read from.  */
-    void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream);
+    void ReadBinaryFile(COB::Scene &out, StreamReaderLE *stream);
 
     // Conversion to Assimp output format
-
-    aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill);
+    aiNode *BuildNodes(const COB::Node &root, const COB::Scene &scin, aiScene *fill);
 
 private:
     // ASCII file support
 
-    void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name);
-    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 ReadPolH_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-    void ReadBitM_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-    void ReadMat1_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-    void ReadGrou_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-    void ReadBone_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-    void ReadCame_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-    void ReadLght_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-    void ReadUnit_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-    void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
-
+    void UnsupportedChunk_Ascii(LineSplitter &splitter, const COB::ChunkInfo &nfo, const char *name);
+    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 ReadPolH_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
+    void ReadBitM_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
+    void ReadMat1_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
+    void ReadGrou_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
+    void ReadBone_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
+    void ReadCame_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
+    void ReadLght_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
+    void ReadUnit_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
+    void ReadChan_Ascii(COB::Scene &out, LineSplitter &splitter, const COB::ChunkInfo &nfo);
 
     // Binary file support
 
-    void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name);
-    void ReadString_Binary(std::string& out, StreamReaderLE& reader);
-    void ReadBasicNodeInfo_Binary(COB::Node& msh, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-
-    void ReadPolH_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-    void ReadBitM_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-    void ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-    void ReadCame_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-    void ReadLght_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-    void ReadGrou_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-    void ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const COB::ChunkInfo& nfo);
-
+    void UnsupportedChunk_Binary(StreamReaderLE &reader, const COB::ChunkInfo &nfo, const char *name);
+    void ReadString_Binary(std::string &out, StreamReaderLE &reader);
+    void ReadBasicNodeInfo_Binary(COB::Node &msh, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
+
+    void ReadPolH_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
+    void ReadBitM_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
+    void ReadMat1_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
+    void ReadCame_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
+    void ReadLght_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
+    void ReadGrou_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
+    void ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const COB::ChunkInfo &nfo);
 
 }; // !class COBImporter
 

+ 4 - 5
code/AssetLib/COB/COBScene.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,16 +42,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  COBScene.h
 *  @brief Utilities for the COB importer.
 */
+#pragma once
 #ifndef INCLUDED_AI_COB_SCENE_H
 #define INCLUDED_AI_COB_SCENE_H
 
-#include <memory>
-#include <deque>
-#include <map>
-
 #include <assimp/BaseImporter.h>
 #include <assimp/material.h>
 
+#include <deque>
+#include <map>
+
 namespace Assimp {
 namespace COB {
 

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

@@ -99,7 +99,7 @@ bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
         return true;
 
     if ((checkSig || !extension.length()) && pIOHandler) {
-        const char* tokens[] = {"$Filename"};
+        static const char * const tokens[] = {"$Filename"};
         return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
     }
     return false;

+ 11 - 15
code/AssetLib/CSM/CSMLoader.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -48,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/BaseImporter.h>
 
-namespace Assimp    {
+namespace Assimp {
 
 // ---------------------------------------------------------------------------
 /** Importer class to load MOCAPs in CharacterStudio Motion format.
@@ -59,35 +58,32 @@ namespace Assimp    {
  *  Link to file format specification:
  *  <max_8_dvd>\samples\Motion\Docs\CSM.rtf
 */
-class CSMImporter : public BaseImporter
-{
+class CSMImporter : public BaseImporter {
 public:
     CSMImporter();
-    ~CSMImporter();
-
+    ~CSMImporter() override;
 
-public:
     // -------------------------------------------------------------------
-    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
+            bool checkSig) const override;
 
 protected:
-
     // -------------------------------------------------------------------
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc *GetInfo() const override;
 
     // -------------------------------------------------------------------
-    void SetupProperties(const Importer* pImp);
+    void SetupProperties(const Importer *pImp) override;
 
     // -------------------------------------------------------------------
-    void InternReadFile( const std::string& pFile, aiScene* pScene,
-        IOSystem* pIOHandler);
+    void InternReadFile(const std::string &pFile, aiScene *pScene,
+            IOSystem *pIOHandler) override;
 
 private:
-
     bool noSkeletonMesh;
 
 }; // end of class CSMImporter
+
 } // end of namespace Assimp
+
 #endif // AI_AC3DIMPORTER_H_INC
 

+ 15 - 11
code/AssetLib/Collada/ColladaLoader.cpp

@@ -47,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "ColladaParser.h"
 #include <assimp/ColladaMetaData.h>
 #include <assimp/CreateAnimMesh.h>
-#include <assimp/Defines.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/SkeletonMeshBuilder.h>
 #include <assimp/ZipArchiveIOSystem.h>
@@ -135,14 +134,15 @@ bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
 
     // XML - too generic, we need to open the file and search for typical keywords
     if (extension == "xml" || !extension.length() || checkSig) {
-        /*  If CanRead() is called in order to check whether we
-         *  support a specific file extension in general pIOHandler
-         *  might be nullptr and it's our duty to return true here.
-         */
-        if (!pIOHandler) {
+        //  If CanRead() is called in order to check whether we
+        //  support a specific file extension in general pIOHandler
+        //  might be nullptr and it's our duty to return true here.
+        if (nullptr == pIOHandler) {
             return true;
         }
-        static const char *tokens[] = { "<collada" };
+        static const char * const tokens[] = {
+            "<collada"
+        };
         return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
     }
 
@@ -573,7 +573,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser &pParser, const Node
 
     // now place all mesh references we gathered in the target node
     pTarget->mNumMeshes = static_cast<unsigned int>(newMeshRefs.size());
-    if (newMeshRefs.size()) {
+    if (!newMeshRefs.empty()) {
         struct UIntTypeConverter {
             unsigned int operator()(const size_t &v) const {
                 return static_cast<unsigned int>(v);
@@ -619,6 +619,10 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
         dstMesh->mName = pSrcMesh->mId;
     }
 
+    if (pSrcMesh->mPositions.empty()) {
+        return dstMesh.release();
+    }
+
     // count the vertices addressed by its faces
     const size_t numVertices = std::accumulate(pSrcMesh->mFaceSize.begin() + pStartFace,
             pSrcMesh->mFaceSize.begin() + pStartFace + pSubMesh.mNumFaces, size_t(0));
@@ -1540,7 +1544,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;
             }
         }
@@ -1671,7 +1675,7 @@ void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/)
         const Material &material = matIt->second;
         // a material is only a reference to an effect
         ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find(material.mEffect);
-        if (effIt == pParser.mEffectLibrary.end())  
+        if (effIt == pParser.mEffectLibrary.end())
             continue;
         Effect &effect = effIt->second;
 
@@ -1682,7 +1686,7 @@ void ColladaLoader::BuildMaterials(ColladaParser &pParser, aiScene * /*pScene*/)
 
         // store the material
         mMaterialIndexByName[matIt->first] = newMats.size();
-        newMats.push_back(std::pair<Effect *, aiMaterial *>(&effect, mat));
+        newMats.emplace_back(&effect, mat);
     }
     // ScenePreprocessor generates a default material automatically if none is there.
     // All further code here in this loader works well without a valid material so

+ 114 - 125
code/AssetLib/Collada/ColladaParser.cpp

@@ -170,10 +170,10 @@ ColladaParser::ColladaParser(IOSystem *pIOHandler, const std::string &pFile) :
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 ColladaParser::~ColladaParser() {
-    for (auto & it : mNodeLibrary) {
+    for (auto &it : mNodeLibrary) {
         delete it.second;
     }
-    for (auto & it : mMeshLibrary) {
+    for (auto &it : mMeshLibrary) {
         delete it.second;
     }
 }
@@ -231,11 +231,7 @@ void ColladaParser::UriDecodePath(aiString &ss) {
 
     // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
     // I need to filter it without destroying linux paths starting with "/somewhere"
-#if defined(_MSC_VER)
     if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
-#else
-    if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
-#endif
         --ss.length;
         ::memmove(ss.data, ss.data + 1, ss.length);
         ss.data[ss.length] = 0;
@@ -396,7 +392,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
 
     std::string animName;
     if (!XmlParser::getStdStrAttribute(node, "name", animName)) {
-        if (!XmlParser::getStdStrAttribute( node, "id", animName )) {
+        if (!XmlParser::getStdStrAttribute(node, "id", animName)) {
             animName = std::string("animation_") + ai_to_string(mAnimationClipLibrary.size());
         }
     }
@@ -420,7 +416,7 @@ void ColladaParser::ReadAnimationClipLibrary(XmlNode &node) {
 
 void ColladaParser::PostProcessControllers() {
     std::string meshId;
-    for (auto & it : mControllerLibrary) {
+    for (auto &it : mControllerLibrary) {
         meshId = it.second.mMeshId;
         if (meshId.empty()) {
             continue;
@@ -445,7 +441,7 @@ void ColladaParser::PostProcessRootAnimations() {
     }
 
     Animation temp;
-    for (auto & it : mAnimationClipLibrary) {
+    for (auto &it : mAnimationClipLibrary) {
         std::string clipName = it.first;
 
         Animation *clip = new Animation();
@@ -453,7 +449,7 @@ void ColladaParser::PostProcessRootAnimations() {
 
         temp.mSubAnims.push_back(clip);
 
-        for (std::string animationID : it.second) {
+        for (const std::string &animationID : it.second) {
             AnimationLibrary::iterator animation = mAnimationLibrary.find(animationID);
 
             if (animation != mAnimationLibrary.end()) {
@@ -529,7 +525,7 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
                 // have it read into a channel
                 ChannelMap::iterator newChannel = channels.insert(std::make_pair(id, AnimationChannel())).first;
                 ReadAnimationSampler(currentNode, newChannel->second);
-            } 
+            }
         } else if (currentName == "channel") {
             std::string source_name, target;
             XmlParser::getStdStrAttribute(currentNode, "source", source_name);
@@ -552,7 +548,7 @@ void ColladaParser::ReadAnimation(XmlNode &node, Collada::Animation *pParent) {
             pParent->mSubAnims.push_back(anim);
         }
 
-        for (const auto & channel : channels) {
+        for (const auto &channel : channels) {
             anim->mChannels.push_back(channel.second);
         }
 
@@ -626,8 +622,6 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
     XmlNodeIterator xmlIt(node, XmlNodeIterator::PreOrderMode);
     XmlNode currentNode;
     while (xmlIt.getNext(currentNode)) {
-
-    //for (XmlNode &currentNode : node.children()) {
         const std::string &currentName = currentNode.name();
         if (currentName == "morph") {
             controller.mType = Morph;
@@ -644,7 +638,7 @@ void ColladaParser::ReadController(XmlNode &node, Collada::Controller &controlle
         } else if (currentName == "skin") {
             std::string id;
             if (XmlParser::getStdStrAttribute(currentNode, "source", id)) {
-                controller.mMeshId = id.substr(1, id.size()-1);
+                controller.mMeshId = id.substr(1, id.size() - 1);
             }
         } else if (currentName == "bind_shape_matrix") {
             std::string v;
@@ -698,7 +692,7 @@ void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pCo
             } else if (strcmp(attrSemantic, "INV_BIND_MATRIX") == 0) {
                 pController.mJointOffsetMatrixSource = attrSource;
             } else {
-                throw DeadlyImportError("Unknown semantic \"" , attrSemantic , "\" in <joints> data <input> element");
+                throw DeadlyImportError("Unknown semantic \"", attrSemantic, "\" in <joints> data <input> element");
             }
         }
     }
@@ -708,7 +702,7 @@ void ColladaParser::ReadControllerJoints(XmlNode &node, Collada::Controller &pCo
 // Reads the joint weights for the given controller
 void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pController) {
     // Read vertex count from attributes and resize the array accordingly
-    int vertexCount=0;
+    int vertexCount = 0;
     XmlParser::getIntAttribute(node, "count", vertexCount);
     pController.mWeightCounts.resize(vertexCount);
 
@@ -723,7 +717,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
 
             // local URLS always start with a '#'. We don't support global URLs
             if (attrSource[0] != '#') {
-                throw DeadlyImportError( "Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element");
+                throw DeadlyImportError("Unsupported URL format in \"", attrSource, "\" in source attribute of <vertex_weights> data <input> element");
             }
             channel.mAccessor = attrSource + 1;
 
@@ -777,7 +771,7 @@ void ColladaParser::ReadImageLibrary(XmlNode &node) {
         const std::string &currentName = currentNode.name();
         if (currentName == "image") {
             std::string id;
-            if (XmlParser::getStdStrAttribute( currentNode, "id", id )) {
+            if (XmlParser::getStdStrAttribute(currentNode, "id", id)) {
                 mImageLibrary[id] = Image();
                 // read on from there
                 ReadImage(currentNode, mImageLibrary[id]);
@@ -907,7 +901,7 @@ void ColladaParser::ReadCameraLibrary(XmlNode &node) {
             if (!name.empty()) {
                 cam.mName = name;
             }
-            ReadCamera(currentNode, cam);            
+            ReadCamera(currentNode, cam);
         }
     }
 }
@@ -920,7 +914,7 @@ void ColladaParser::ReadMaterial(XmlNode &node, Collada::Material &pMaterial) {
         if (currentName == "instance_effect") {
             std::string url;
             readUrlAttribute(currentNode, url);
-            pMaterial.mEffect = url.c_str();
+            pMaterial.mEffect = url;
         }
     }
 }
@@ -1361,8 +1355,8 @@ void ColladaParser::ReadMesh(XmlNode &node, Mesh &pMesh) {
         } else if (currentName == "vertices") {
             ReadVertexData(currentNode, pMesh);
         } else if (currentName == "triangles" || currentName == "lines" || currentName == "linestrips" ||
-                currentName == "polygons" || currentName == "polylist" || currentName == "trifans" ||
-                currentName == "tristrips") {
+                   currentName == "polygons" || currentName == "polylist" || currentName == "trifans" ||
+                   currentName == "tristrips") {
             ReadIndexData(currentNode, pMesh);
         }
     }
@@ -1439,9 +1433,8 @@ void ColladaParser::ReadDataArray(XmlNode &node) {
                     throw DeadlyImportError("Expected more values while reading float_array contents.");
                 }
 
-                ai_real value;
                 // read a number
-                //SkipSpacesAndLineEnd(&content);
+                ai_real value;
                 content = fast_atoreal_move<ai_real>(content, value);
                 data.mValues.push_back(value);
                 // skip whitespace after it
@@ -1489,11 +1482,10 @@ void ColladaParser::ReadAccessor(XmlNode &node, const std::string &pID) {
             std::string name;
             if (XmlParser::hasAttribute(currentNode, "name")) {
                 XmlParser::getStdStrAttribute(currentNode, "name", name);
-                //name = mReader->getAttributeValue(attrName);
 
                 // analyse for common type components and store it's sub-offset in the corresponding field
 
-                /* Cartesian coordinates */
+                // Cartesian coordinates
                 if (name == "X")
                     acc.mSubOffset[0] = acc.mParams.size();
                 else if (name == "Y")
@@ -1674,12 +1666,9 @@ void ColladaParser::ReadInputChannel(XmlNode &node, std::vector<InputChannel> &p
 
     // read set if texture coordinates
     if (channel.mType == IT_Texcoord || channel.mType == IT_Color) {
-        int attrSet = -1;
-        if (XmlParser::hasAttribute(node, "set")) {
-            XmlParser::getIntAttribute(node, "set", attrSet);
-        }
-
-        channel.mIndex = attrSet;
+        unsigned int attrSet = 0;
+        if (XmlParser::getUIntAttribute(node, "set", attrSet))
+            channel.mIndex = attrSet;
     }
 
     // store, if valid type
@@ -1704,20 +1693,20 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
     // determine the expected number of indices
     size_t expectedPointCount = 0;
     switch (pPrimType) {
-        case Prim_Polylist: {
-            for (size_t i : pVCount)
-                expectedPointCount += i;
-            break;
-        }
-        case Prim_Lines:
-            expectedPointCount = 2 * pNumPrimitives;
-            break;
-        case Prim_Triangles:
-            expectedPointCount = 3 * pNumPrimitives;
-            break;
-        default:
-            // other primitive types don't state the index count upfront... we need to guess
-            break;
+    case Prim_Polylist: {
+        for (size_t i : pVCount)
+            expectedPointCount += i;
+        break;
+    }
+    case Prim_Lines:
+        expectedPointCount = 2 * pNumPrimitives;
+        break;
+    case Prim_Triangles:
+        expectedPointCount = 3 * pNumPrimitives;
+        break;
+    default:
+        // other primitive types don't state the index count upfront... we need to guess
+        break;
     }
 
     // and read all indices into a temporary array
@@ -1727,7 +1716,7 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
     }
 
     // It is possible to not contain any indices
-    if (pNumPrimitives > 0)  {
+    if (pNumPrimitives > 0) {
         std::string v;
         XmlParser::getValueAsString(node, v);
         const char *content = v.c_str();
@@ -1925,87 +1914,87 @@ void ColladaParser::ExtractDataObjectFromChannel(const InputChannel &pInput, siz
 
     // now we reinterpret it according to the type we're reading here
     switch (pInput.mType) {
-        case IT_Position: // ignore all position streams except 0 - there can be only one position
-            if (pInput.mIndex == 0) {
-                pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2]));
-            } else {
-                ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
-            }
-            break;
-        case IT_Normal:
-            // pad to current vertex count if necessary
-            if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1)
-                pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0));
+    case IT_Position: // ignore all position streams except 0 - there can be only one position
+        if (pInput.mIndex == 0) {
+            pMesh.mPositions.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+        } else {
+            ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
+        }
+        break;
+    case IT_Normal:
+        // pad to current vertex count if necessary
+        if (pMesh.mNormals.size() < pMesh.mPositions.size() - 1)
+            pMesh.mNormals.insert(pMesh.mNormals.end(), pMesh.mPositions.size() - pMesh.mNormals.size() - 1, aiVector3D(0, 1, 0));
 
-            // ignore all normal streams except 0 - there can be only one normal
-            if (pInput.mIndex == 0) {
-                pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
-            } else {
-                ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
-            }
-            break;
-        case IT_Tangent:
+        // ignore all normal streams except 0 - there can be only one normal
+        if (pInput.mIndex == 0) {
+            pMesh.mNormals.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+        } else {
+            ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
+        }
+        break;
+    case IT_Tangent:
+        // pad to current vertex count if necessary
+        if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1)
+            pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0));
+
+        // ignore all tangent streams except 0 - there can be only one tangent
+        if (pInput.mIndex == 0) {
+            pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+        } else {
+            ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
+        }
+        break;
+    case IT_Bitangent:
+        // pad to current vertex count if necessary
+        if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) {
+            pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1));
+        }
+
+        // ignore all bitangent streams except 0 - there can be only one bitangent
+        if (pInput.mIndex == 0) {
+            pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
+        } else {
+            ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
+        }
+        break;
+    case IT_Texcoord:
+        // up to 4 texture coord sets are fine, ignore the others
+        if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
             // pad to current vertex count if necessary
-            if (pMesh.mTangents.size() < pMesh.mPositions.size() - 1)
-                pMesh.mTangents.insert(pMesh.mTangents.end(), pMesh.mPositions.size() - pMesh.mTangents.size() - 1, aiVector3D(1, 0, 0));
+            if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
+                pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
+                        pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
 
-            // ignore all tangent streams except 0 - there can be only one tangent
-            if (pInput.mIndex == 0) {
-                pMesh.mTangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
-            } else {
-                ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
+            pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
+            if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
+                pMesh.mNumUVComponents[pInput.mIndex] = 3;
             }
-            break;
-        case IT_Bitangent:
+        } else {
+            ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
+        }
+        break;
+    case IT_Color:
+        // up to 4 color sets are fine, ignore the others
+        if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) {
             // pad to current vertex count if necessary
-            if (pMesh.mBitangents.size() < pMesh.mPositions.size() - 1) {
-                pMesh.mBitangents.insert(pMesh.mBitangents.end(), pMesh.mPositions.size() - pMesh.mBitangents.size() - 1, aiVector3D(0, 0, 1));
-            }
+            if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
+                pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(),
+                        pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1));
 
-            // ignore all bitangent streams except 0 - there can be only one bitangent
-            if (pInput.mIndex == 0) {
-                pMesh.mBitangents.push_back(aiVector3D(obj[0], obj[1], obj[2]));
-            } else {
-                ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
-            }
-            break;
-        case IT_Texcoord:
-            // up to 4 texture coord sets are fine, ignore the others
-            if (pInput.mIndex < AI_MAX_NUMBER_OF_TEXTURECOORDS) {
-                // pad to current vertex count if necessary
-                if (pMesh.mTexCoords[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
-                    pMesh.mTexCoords[pInput.mIndex].insert(pMesh.mTexCoords[pInput.mIndex].end(),
-                            pMesh.mPositions.size() - pMesh.mTexCoords[pInput.mIndex].size() - 1, aiVector3D(0, 0, 0));
-
-                pMesh.mTexCoords[pInput.mIndex].push_back(aiVector3D(obj[0], obj[1], obj[2]));
-                if (0 != acc.mSubOffset[2] || 0 != acc.mSubOffset[3]) {
-                    pMesh.mNumUVComponents[pInput.mIndex] = 3;
-                }
-            } else {
-                ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
-            }
-            break;
-        case IT_Color:
-            // up to 4 color sets are fine, ignore the others
-            if (pInput.mIndex < AI_MAX_NUMBER_OF_COLOR_SETS) {
-                // pad to current vertex count if necessary
-                if (pMesh.mColors[pInput.mIndex].size() < pMesh.mPositions.size() - 1)
-                    pMesh.mColors[pInput.mIndex].insert(pMesh.mColors[pInput.mIndex].end(),
-                            pMesh.mPositions.size() - pMesh.mColors[pInput.mIndex].size() - 1, aiColor4D(0, 0, 0, 1));
-
-                aiColor4D result(0, 0, 0, 1);
-                for (size_t i = 0; i < pInput.mResolved->mSize; ++i) {
-                    result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
-                }
-                pMesh.mColors[pInput.mIndex].push_back(result);
-            } else {
-                ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
+            aiColor4D result(0, 0, 0, 1);
+            for (size_t i = 0; i < pInput.mResolved->mSize; ++i) {
+                result[static_cast<unsigned int>(i)] = obj[pInput.mResolved->mSubOffset[i]];
             }
+            pMesh.mColors[pInput.mIndex].push_back(result);
+        } else {
+            ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
+        }
 
-            break;
-        default:
-            // IT_Invalid and IT_Vertex
-            ai_assert(false && "shouldn't ever get here");
+        break;
+    default:
+        // IT_Invalid and IT_Vertex
+        ai_assert(false && "shouldn't ever get here");
     }
 }
 
@@ -2170,10 +2159,10 @@ void ColladaParser::ReadNodeTransformation(XmlNode &node, Node *pNode, Transform
 
     // 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);
         // read a number
         content = fast_atoreal_move<ai_real>(content, tf.f[a]);
-        // skip whitespace after it
-        SkipSpacesAndLineEnd(&content);
     }
 
     // place the transformation at the queue of the node
@@ -2215,8 +2204,8 @@ void ColladaParser::ReadMaterialVertexInputBinding(XmlNode &node, Collada::Seman
 
 void ColladaParser::ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive) {
     // Attempt to load any undefined Collada::Image in ImageLibrary
-    for (ImageLibrary::iterator it = mImageLibrary.begin(); it != mImageLibrary.end(); ++it) {
-        Collada::Image &image = (*it).second;
+    for (auto & it : mImageLibrary) {
+        Collada::Image &image = it.second;
 
         if (image.mImageData.empty()) {
             std::unique_ptr<IOStream> image_file(zip_archive.Open(image.mFileName.c_str()));

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

@@ -43,6 +43,7 @@
  *  @brief Defines the parser helper class for the collada loader
  */
 
+#pragma once
 #ifndef AI_COLLADAPARSER_H_INC
 #define AI_COLLADAPARSER_H_INC
 

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

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -63,11 +61,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 
 // AutoCAD Binary DXF<CR><LF><SUB><NULL>
-const std::string AI_DXF_BINARY_IDENT = std::string("AutoCAD Binary DXF\r\n\x1a\0");
-const size_t AI_DXF_BINARY_IDENT_LEN = 24u;
+static constexpr char AI_DXF_BINARY_IDENT[] = "AutoCAD Binary DXF\r\n\x1a";
+static constexpr size_t AI_DXF_BINARY_IDENT_LEN = sizeof AI_DXF_BINARY_IDENT;
 
 // default vertex color that all uncolored vertices will receive
-const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f));
+static const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f));
 
 // color indices for DXF - 16 are supported, the table is
 // taken directly from the DXF spec.
@@ -132,8 +130,8 @@ bool DXFImporter::CanRead( const std::string& filename, IOSystem* pIOHandler, bo
     }
 
     if ( extension.empty() || checkSig ) {
-        const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" };
-        return BaseImporter::SearchFileHeaderForToken(pIOHandler, filename, pTokens, 4, 32 );
+        static const char * const pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" };
+        return SearchFileHeaderForToken(pIOHandler, filename, pTokens, 4, 32 );
     }
 
     return false;
@@ -156,10 +154,10 @@ void DXFImporter::InternReadFile( const std::string& filename, aiScene* pScene,
     }
 
     // Check whether this is a binary DXF file - we can't read binary DXF files :-(
-    char buff[AI_DXF_BINARY_IDENT_LEN+1] = {0};
+    char buff[AI_DXF_BINARY_IDENT_LEN] = {0};
     file->Read(buff,AI_DXF_BINARY_IDENT_LEN,1);
 
-    if (0 == strncmp(AI_DXF_BINARY_IDENT.c_str(),buff,AI_DXF_BINARY_IDENT_LEN)) {
+    if (0 == memcmp(AI_DXF_BINARY_IDENT,buff,AI_DXF_BINARY_IDENT_LEN)) {
         throw DeadlyImportError("DXF: Binary files are not supported at the moment");
     }
 
@@ -549,7 +547,7 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
         ++reader;
     }
 
-    ASSIMP_LOG_VERBOSE_DEBUG( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), 
+    ASSIMP_LOG_VERBOSE_DEBUG( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(),
         " inserted blocks in ENTITIES" );
 }
 

+ 7 - 10
code/AssetLib/DXF/DXFLoader.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  DXFLoader.h
  *  @brief Declaration of the .dxf importer class.
  */
+#pragma once
 #ifndef AI_DXFLOADER_H_INCLUDED
 #define AI_DXFLOADER_H_INCLUDED
 
@@ -59,39 +59,36 @@ namespace DXF {
     struct Block;
     struct InsertBlock;
 
-    typedef std::map<std::string, const DXF::Block*> BlockMap;
+    using BlockMap = std::map<std::string, const DXF::Block*>;
 }
 
 // ---------------------------------------------------------------------------
-/** 
+/**
  *  @brief  DXF importer implementation.
  */
 class DXFImporter : public BaseImporter {
 public:
     DXFImporter();
-    ~DXFImporter();
+    ~DXFImporter() override;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.
     * See BaseImporter::CanRead() for details.  */
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+        bool checkSig) const override;
 
 protected:
     // -------------------------------------------------------------------
     /** Return importer meta information.
      * See #BaseImporter::GetInfo for the details*/
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc* GetInfo () const override;
 
     // -------------------------------------------------------------------
     /** Imports the given file into the given scene structure.
      * See BaseImporter::InternReadFile() for details */
-    void InternReadFile( const std::string& pFile,
-        aiScene* pScene,
-        IOSystem* pIOHandler);
+    void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
 
 private:
-
     // -----------------------------------------------------
     void SkipSection(DXF::LineReader& reader);
 

+ 13 - 8
code/AssetLib/FBX/FBXConverter.cpp

@@ -862,7 +862,7 @@ bool FBXConverter::GenerateTransformationNodeChain(const Model &model, const std
     output_nodes.push_back(std::move(nd));
     return false;
 }
-  
+
 void FBXConverter::SetupNodeMetadata(const Model &model, aiNode &nd) {
     const PropertyTable &props = model.Props();
     DirectPropertyMap unparsedProperties = props.GetUnparsedProperties();
@@ -917,8 +917,10 @@ void FBXConverter::ConvertModel(const Model &model, aiNode *parent, aiNode *root
         } else if (line) {
             const std::vector<unsigned int> &indices = ConvertLine(*line, root_node);
             std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
-        } else {
+        } else if (geo) {
             FBXImporter::LogWarn("ignoring unrecognized geometry: ", geo->Name());
+        } else {
+            FBXImporter::LogWarn("skipping null geometry");
         }
     }
 
@@ -1126,7 +1128,7 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
             *out_uv++ = aiVector3D(v.x, v.y, 0.0f);
         }
 
-        out_mesh->mTextureCoordsNames[i] = mesh.GetTextureCoordChannelName(i);
+        out_mesh->SetTextureCoordsName(i, aiString(mesh.GetTextureCoordChannelName(i)));
 
         out_mesh->mNumUVComponents[i] = 2;
     }
@@ -1593,7 +1595,7 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
         bone_map.insert(std::pair<const std::string, aiBone *>(deformer_name, bone));
     }
 
-    ASSIMP_LOG_DEBUG("bone research: Indicies size: ", out_indices.size());
+    ASSIMP_LOG_DEBUG("bone research: Indices size: ", out_indices.size());
 
     // lookup must be populated in case something goes wrong
     // this also allocates bones to mesh instance outside
@@ -1766,6 +1768,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const TextureMap
         // XXX handle all kinds of UV transformations
         uvTrafo.mScaling = tex->UVScaling();
         uvTrafo.mTranslation = tex->UVTranslation();
+        uvTrafo.mRotation = tex->UVRotation();
         out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, 0);
 
         const PropertyTable &props = tex->Props();
@@ -1885,6 +1888,7 @@ void FBXConverter::TrySetTextureProperties(aiMaterial *out_mat, const LayeredTex
         // XXX handle all kinds of UV transformations
         uvTrafo.mScaling = tex->UVScaling();
         uvTrafo.mTranslation = tex->UVTranslation();
+        uvTrafo.mRotation = tex->UVRotation();
         out_mat->AddProperty(&uvTrafo, 1, _AI_MATKEY_UVTRANSFORM_BASE, target, texIndex);
 
         const PropertyTable &props = tex->Props();
@@ -2129,7 +2133,7 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert
     if (ok) {
         out_mat->AddProperty(&Emissive, 1, AI_MATKEY_COLOR_EMISSIVE);
     } else {
-        const aiColor3D &emissiveColor = GetColorPropertyFromMaterial(props, "Maya|emissive", ok);
+        const aiColor3D &emissiveColor = GetColorProperty(props, "Maya|emissive", ok);
         if (ok) {
             out_mat->AddProperty(&emissiveColor, 1, AI_MATKEY_COLOR_EMISSIVE);
         }
@@ -2216,7 +2220,7 @@ void FBXConverter::SetShadingPropertiesCommon(aiMaterial *out_mat, const Propert
     }
 
     // PBR material information
-    const aiColor3D &baseColor = GetColorPropertyFromMaterial(props, "Maya|base_color", ok);
+    const aiColor3D &baseColor = GetColorProperty(props, "Maya|base_color", ok);
     if (ok) {
         out_mat->AddProperty(&baseColor, 1, AI_MATKEY_BASE_COLOR);
     }
@@ -2324,6 +2328,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial *out_mat, const PropertyTa
             // XXX handle all kinds of UV transformations
             uvTrafo.mScaling = tex->UVScaling();
             uvTrafo.mTranslation = tex->UVTranslation();
+            uvTrafo.mRotation = tex->UVRotation();
             out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0);
 
             int uvIndex = 0;
@@ -2599,7 +2604,7 @@ void FBXConverter::ConvertAnimationStack(const AnimationStack &st) {
             anim->mMorphMeshChannels = new aiMeshMorphAnim *[numMorphMeshChannels];
             anim->mNumMorphMeshChannels = numMorphMeshChannels;
             unsigned int i = 0;
-            for (auto morphAnimIt : morphAnimDatas) {
+            for (const auto &morphAnimIt : morphAnimDatas) {
                 morphAnimData *animData = morphAnimIt.second;
                 unsigned int numKeys = static_cast<unsigned int>(animData->size());
                 aiMeshMorphAnim *meshMorphAnim = new aiMeshMorphAnim();
@@ -3569,7 +3574,7 @@ void FBXConverter::ConvertOrphanedEmbeddedTextures() {
                         if (texture->Media() && texture->Media()->ContentLength() > 0) {
                             realTexture = texture;
                         }
-                    }    
+                    }
                 }
             } catch (...) {
                 // do nothing

+ 2 - 2
code/AssetLib/FBX/FBXConverter.h

@@ -76,7 +76,7 @@ namespace Assimp {
 namespace FBX {
 
 class Document;
-/** 
+/**
  *  Convert a FBX #Document to #aiScene
  *  @param out Empty scene to be populated
  *  @param doc Parsed FBX document
@@ -182,7 +182,7 @@ private:
     // ------------------------------------------------------------------------------------------------
     void ConvertModel(const Model &model, aiNode *parent, aiNode *root_node,
                       const aiMatrix4x4 &absolute_transform);
-    
+
     // ------------------------------------------------------------------------------------------------
     // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
     std::vector<unsigned int>

+ 5 - 6
code/AssetLib/FBX/FBXDocument.cpp

@@ -57,9 +57,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <assimp/DefaultLogger.hpp>
 
-#include <memory>
 #include <functional>
 #include <map>
+#include <memory>
+#include <utility>
 
 namespace Assimp {
 namespace FBX {
@@ -248,10 +249,8 @@ Object::~Object()
 }
 
 // ------------------------------------------------------------------------------------------------
-FileGlobalSettings::FileGlobalSettings(const Document& doc, std::shared_ptr<const PropertyTable> props)
-: props(props)
-, doc(doc)
-{
+FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr<const PropertyTable> props) :
+        props(std::move(props)), doc(doc) {
     // empty
 }
 
@@ -636,7 +635,7 @@ std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_
 }
 
 // ------------------------------------------------------------------------------------------------
-std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source, 
+std::vector<const Connection*> Document::GetConnectionsBySourceSequenced(uint64_t source,
         const char* const* classnames, size_t count) const
 {
     return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count);

+ 6 - 1
code/AssetLib/FBX/FBXDocument.h

@@ -500,6 +500,10 @@ public:
         return uvScaling;
     }
 
+    const ai_real &UVRotation() const {
+        return uvRotation;
+    }
+
     const PropertyTable& Props() const {
         ai_assert(props.get());
         return *props.get();
@@ -517,6 +521,7 @@ public:
 private:
     aiVector2D uvTrans;
     aiVector2D uvScaling;
+    ai_real    uvRotation;
 
     std::string type;
     std::string relativeFileName;
@@ -688,7 +693,7 @@ private:
 typedef std::vector<int64_t> KeyTimeList;
 typedef std::vector<float> KeyValueList;
 
-/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefor) */
+/** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefore) */
 class AnimationCurve : public Object {
 public:
     AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& doc);

+ 2 - 3
code/AssetLib/FBX/FBXExportNode.cpp

@@ -144,9 +144,8 @@ void FBX::Node::AddP70time(
 // public member functions for writing nodes to stream
 
 void FBX::Node::Dump(
-    std::shared_ptr<Assimp::IOStream> outfile,
-    bool binary, int indent
-) {
+        const std::shared_ptr<Assimp::IOStream> &outfile,
+        bool binary, int indent) {
     if (binary) {
         Assimp::StreamWriterLE outstream(outfile);
         DumpBinary(outstream);

+ 3 - 4
code/AssetLib/FBX/FBXExportNode.h

@@ -60,7 +60,7 @@ namespace FBX {
 }
 
 class FBX::Node {
-public: 
+public:
     // TODO: accessors
     std::string name; // node name
     std::vector<FBX::FBXExportProperty> properties; // node properties
@@ -157,9 +157,8 @@ public: // member functions for writing data to a file or stream
 
     // write the full node to the given file or stream
     void Dump(
-        std::shared_ptr<Assimp::IOStream> outfile,
-        bool binary, int indent
-    );
+            const std::shared_ptr<Assimp::IOStream> &outfile,
+            bool binary, int indent);
     void Dump(Assimp::StreamWriterLE &s, bool binary, int indent);
 
     // these other functions are for writing data piece by piece.

+ 113 - 38
code/AssetLib/FBX/FBXExporter.cpp

@@ -498,7 +498,7 @@ void FBXExporter::WriteDocuments ()
     if (!binary) {
         WriteAsciiSectionHeader("Documents Description");
     }
-    
+
     // not sure what the use of multiple documents would be,
     // or whether any end-application supports it
     FBX::Node docs("Documents");
@@ -541,10 +541,17 @@ void FBXExporter::WriteReferences ()
 // (before any actual data is written)
 // ---------------------------------------------------------------
 
-size_t count_nodes(const aiNode* n) {
-    size_t count = 1;
+size_t count_nodes(const aiNode* n, const aiNode* root) {
+    size_t count;
+    if (n == root) {
+        count = n->mNumMeshes; // (not counting root node)
+    } else if (n->mNumMeshes > 1) {
+        count = n->mNumMeshes + 1;
+    } else {
+        count = 1;
+    }
     for (size_t i = 0; i < n->mNumChildren; ++i) {
-        count += count_nodes(n->mChildren[i]);
+        count += count_nodes(n->mChildren[i], root);
     }
     return count;
 }
@@ -714,7 +721,7 @@ void FBXExporter::WriteDefinitions ()
 
     // Model / FbxNode
     // <~~ node hierarchy
-    count = int32_t(count_nodes(mScene->mRootNode)) - 1; // (not counting root node)
+    count = int32_t(count_nodes(mScene->mRootNode, mScene->mRootNode));
     if (count) {
         n = FBX::Node("ObjectType", "Model");
         n.AddChild("Count", count);
@@ -1251,7 +1258,7 @@ void FBXExporter::WriteObjects ()
             indent = 2;
             vertexcolors.End(outstream, binary, indent, true);
         }
-        
+
         // uvs, if any
         for (size_t uvi = 0; uvi < m->GetNumUVChannels(); ++uvi) {
             if (m->mNumUVComponents[uvi] > 2) {
@@ -1681,6 +1688,10 @@ void FBXExporter::WriteObjects ()
             // link the image data to the texture
             connections.emplace_back("C", "OO", image_uid, texture_uid);
 
+            aiUVTransform trafo;
+            unsigned int max = sizeof(aiUVTransform);
+            aiGetMaterialFloatArray(mat, AI_MATKEY_UVTRANSFORM(aiTextureType_DIFFUSE, 0), (ai_real *)&trafo, &max);
+
             // now write the actual texture node
             FBX::Node tnode("Texture");
             // TODO: some way to determine texture name?
@@ -1691,11 +1702,14 @@ void FBXExporter::WriteObjects ()
             tnode.AddChild("Version", int32_t(202));
             tnode.AddChild("TextureName", texture_name);
             FBX::Node p("Properties70");
+            p.AddP70vectorA("Translation", trafo.mTranslation[0], trafo.mTranslation[1], 0.0);
+            p.AddP70vectorA("Rotation", 0, 0, trafo.mRotation);
+            p.AddP70vectorA("Scaling", trafo.mScaling[0], trafo.mScaling[1], 0.0);
             p.AddP70enum("CurrentTextureBlendMode", 0); // TODO: verify
             //p.AddP70string("UVSet", ""); // TODO: how should this work?
             p.AddP70bool("UseMaterial", 1);
             tnode.AddChild(p);
-            // can't easily detrmine which texture path will be correct,
+            // can't easily determine which texture path will be correct,
             // so just store what we have in every field.
             // these being incorrect is a common problem with FBX anyway.
             tnode.AddChild("FileName", texture_path);
@@ -1737,7 +1751,7 @@ void FBXExporter::WriteObjects ()
         bsnode.AddProperty(blendshape_uid);
         bsnode.AddProperty(blendshape_name + FBX::SEPARATOR + "Blendshape");
         bsnode.AddProperty("Shape");
-        bsnode.AddChild("Version", int32_t(100));        
+        bsnode.AddChild("Version", int32_t(100));
         bsnode.Begin(outstream, binary, indent);
         bsnode.DumpProperties(outstream, binary, indent);
         bsnode.EndProperties(outstream, binary, indent);
@@ -1789,7 +1803,7 @@ void FBXExporter::WriteObjects ()
             blendchannel_uid, blendshape_name + FBX::SEPARATOR + "SubDeformer", "BlendShapeChannel"
         );
         sdnode.AddChild("Version", int32_t(100));
-        sdnode.AddChild("DeformPercent", float_t(0.0));
+        sdnode.AddChild("DeformPercent", float(0.0));
         FBX::Node p("Properties70");
         p.AddP70numberA("DeformPercent", 0.0);
         sdnode.AddChild(p);
@@ -1863,7 +1877,7 @@ void FBXExporter::WriteObjects ()
     // at the same time we can build a list of all the skeleton nodes,
     // which will be used later to mark them as type "limbNode".
     std::unordered_set<const aiNode*> limbnodes;
-    
+
     //actual bone nodes in fbx, without parenting-up
     std::unordered_set<std::string> setAllBoneNamesInScene;
     for(unsigned int m = 0; m < mScene->mNumMeshes; ++ m)
@@ -1873,7 +1887,7 @@ void FBXExporter::WriteObjects ()
             setAllBoneNamesInScene.insert(pMesh->mBones[b]->mName.data);
     }
     aiMatrix4x4 mxTransIdentity;
-    
+
     // and a map of nodes by bone name, as finding them is annoying.
     std::map<std::string,aiNode*> node_by_bone;
     for (size_t mi = 0; mi < mScene->mNumMeshes; ++mi) {
@@ -1901,7 +1915,7 @@ void FBXExporter::WriteObjects ()
             // mark all parent nodes as skeleton as well,
             // up until we find the root node,
             // or else the node containing the mesh,
-            // or else the parent of a node containig the mesh.
+            // or else the parent of a node containing the mesh.
             for (
                 const aiNode* parent = n->mParent;
                 parent && parent != mScene->mRootNode;
@@ -1942,7 +1956,7 @@ void FBXExporter::WriteObjects ()
                     }
                     if (end) { break; }
                 }
-                
+
                 // if it was the skeleton root we can finish here
                 if (end) { break; }
             }
@@ -2196,7 +2210,65 @@ void FBXExporter::WriteObjects ()
         bpnode.Dump(outstream, binary, indent);
     }*/
 
-    // TODO: cameras, lights
+    // lights
+    indent = 1;
+    lights_uids.clear();
+    for (size_t li = 0; li < mScene->mNumLights; ++li) {
+        aiLight* l = mScene->mLights[li];
+
+        int64_t uid = generate_uid();
+        const std::string lightNodeAttributeName = l->mName.C_Str() + FBX::SEPARATOR + "NodeAttribute";
+
+        FBX::Node lna("NodeAttribute");
+        lna.AddProperties(uid, lightNodeAttributeName, "Light");
+        FBX::Node lnap("Properties70");
+
+        // Light color.
+        lnap.AddP70colorA("Color", l->mColorDiffuse.r, l->mColorDiffuse.g, l->mColorDiffuse.b);
+
+        // TODO Assimp light description is quite concise and do not handle light intensity.
+        // Default value to 1000W.
+        lnap.AddP70numberA("Intensity", 1000);
+
+        // FBXLight::EType conversion
+        switch (l->mType) {
+        case aiLightSource_POINT:
+            lnap.AddP70enum("LightType", 0);
+            break;
+        case aiLightSource_DIRECTIONAL:
+            lnap.AddP70enum("LightType", 1);
+            break;
+        case aiLightSource_SPOT:
+            lnap.AddP70enum("LightType", 2);
+            lnap.AddP70numberA("InnerAngle", AI_RAD_TO_DEG(l->mAngleInnerCone));
+            lnap.AddP70numberA("OuterAngle", AI_RAD_TO_DEG(l->mAngleOuterCone));
+            break;
+        // TODO Assimp do not handle 'area' nor 'volume' lights, but FBX does.
+        /*case aiLightSource_AREA:
+            lnap.AddP70enum("LightType", 3);
+            lnap.AddP70enum("AreaLightShape", 0); // 0=Rectangle, 1=Sphere
+            break;
+        case aiLightSource_VOLUME:
+            lnap.AddP70enum("LightType", 4);
+            break;*/
+        default:
+            break;
+        }
+
+        // Did not understood how to configure the decay so disabling attenuation.
+        lnap.AddP70enum("DecayType", 0);
+
+        // Dump to FBX stream
+        lna.AddChild(lnap);
+        lna.AddChild("TypeFlags", FBX::FBXExportProperty("Light"));
+        lna.AddChild("GeometryVersion", FBX::FBXExportProperty(int32_t(124)));
+        lna.Dump(outstream, binary, indent);
+
+        // Store name and uid (will be used later when parsing scene nodes)
+        lights_uids[l->mName.C_Str()] = uid;
+    }
+
+    // TODO: cameras
 
     // write nodes (i.e. model hierarchy)
     // start at root node
@@ -2600,10 +2672,19 @@ void FBXExporter::WriteModelNodes(
         // and connect them
         connections.emplace_back("C", "OO", node_attribute_uid, node_uid);
     } else {
-        // generate a null node so we can add children to it
-        WriteModelNode(
-            outstream, binary, node, node_uid, "Null", transform_chain
-        );
+        const auto& lightIt = lights_uids.find(node->mName.C_Str());
+        if(lightIt != lights_uids.end()) {
+            // Node has a light connected to it.
+            WriteModelNode(
+                outstream, binary, node, node_uid, "Light", transform_chain
+            );
+            connections.emplace_back("C", "OO", lightIt->second, node_uid);
+        } else {
+            // generate a null node so we can add children to it
+            WriteModelNode(
+                outstream, binary, node, node_uid, "Null", transform_chain
+            );
+        }
     }
 
     // if more than one child mesh, make nodes for each mesh
@@ -2625,17 +2706,14 @@ void FBXExporter::WriteModelNodes(
                 ],
                 new_node_uid
             );
-            // write model node
-            FBX::Node m("Model");
+
+            aiNode new_node;
             // take name from mesh name, if it exists
-            std::string name = mScene->mMeshes[node->mMeshes[i]]->mName.C_Str();
-            name += FBX::SEPARATOR + "Model";
-            m.AddProperties(new_node_uid, name, "Mesh");
-            m.AddChild("Version", int32_t(232));
-            FBX::Node p("Properties70");
-            p.AddP70enum("InheritType", 1);
-            m.AddChild(p);
-            m.Dump(outstream, binary, 1);
+            new_node.mName = mScene->mMeshes[node->mMeshes[i]]->mName;
+            // write model node
+            WriteModelNode(
+                outstream, binary, &new_node, new_node_uid, "Mesh", std::vector<std::pair<std::string,aiVector3D>>()
+            );
         }
     }
 
@@ -2647,16 +2725,14 @@ void FBXExporter::WriteModelNodes(
     }
 }
 
-
 void FBXExporter::WriteAnimationCurveNode(
-    StreamWriterLE& outstream,
-    int64_t uid,
-    const std::string& name, // "T", "R", or "S"
-    aiVector3D default_value,
-    std::string property_name, // "Lcl Translation" etc
-    int64_t layer_uid,
-    int64_t node_uid
-) {
+        StreamWriterLE &outstream,
+        int64_t uid,
+        const std::string &name, // "T", "R", or "S"
+        aiVector3D default_value,
+        const std::string &property_name, // "Lcl Translation" etc
+        int64_t layer_uid,
+        int64_t node_uid) {
     FBX::Node n("AnimationCurveNode");
     n.AddProperties(uid, name + FBX::SEPARATOR + "AnimCurveNode", "");
     FBX::Node p("Properties70");
@@ -2671,7 +2747,6 @@ void FBXExporter::WriteAnimationCurveNode(
     this->connections.emplace_back("C", "OP", uid, node_uid, property_name);
 }
 
-
 void FBXExporter::WriteAnimationCurve(
     StreamWriterLE& outstream,
     double default_value,

+ 10 - 11
code/AssetLib/FBX/FBXExporter.h

@@ -63,10 +63,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 struct aiScene;
 struct aiNode;
-//struct aiMaterial;
+struct aiLight;
 
-namespace Assimp
-{
+namespace Assimp {
     class IOSystem;
     class IOStream;
     class ExportProperties;
@@ -95,6 +94,7 @@ namespace Assimp
         std::vector<int64_t> mesh_uids;
         std::vector<int64_t> material_uids;
         std::map<const aiNode*,int64_t> node_uids;
+        std::map<std::string,int64_t> lights_uids;
 
         // this crude unique-ID system is actually fine
         int64_t last_uid = 999999;
@@ -154,14 +154,13 @@ namespace Assimp
             FBX::TransformInheritance ti_type=FBX::TransformInheritance_RSrs
         );
         void WriteAnimationCurveNode(
-            StreamWriterLE& outstream,
-            int64_t uid,
-            const std::string& name, // "T", "R", or "S"
-            aiVector3D default_value,
-            std::string property_name, // "Lcl Translation" etc
-            int64_t animation_layer_uid,
-            int64_t node_uid
-        );
+                StreamWriterLE &outstream,
+                int64_t uid,
+                const std::string &name, // "T", "R", or "S"
+                aiVector3D default_value,
+                const std::string &property_name, // "Lcl Translation" etc
+                int64_t animation_layer_uid,
+                int64_t node_uid);
         void WriteAnimationCurve(
             StreamWriterLE& outstream,
             double default_value,

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

@@ -108,7 +108,7 @@ bool FBXImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
 
 	else if ((!extension.length() || checkSig) && pIOHandler) {
 		// at least ASCII-FBX files usually have a 'FBX' somewhere in their head
-		const char *tokens[] = { "fbx" };
+		static const char * const tokens[] = { "fbx" };
 		return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
 	}
 	return false;

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

@@ -70,28 +70,29 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
 class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
 public:
     FBXImporter();
-    virtual ~FBXImporter();
+    ~FBXImporter() override;
 
     // --------------------
     bool CanRead(const std::string &pFile,
             IOSystem *pIOHandler,
-            bool checkSig) const;
+            bool checkSig) const override;
 
 protected:
     // --------------------
-    const aiImporterDesc *GetInfo() const;
+    const aiImporterDesc *GetInfo() const override;
 
     // --------------------
-    void SetupProperties(const Importer *pImp);
+    void SetupProperties(const Importer *pImp) override;
 
     // --------------------
     void InternReadFile(const std::string &pFile,
             aiScene *pScene,
-            IOSystem *pIOHandler);
+            IOSystem *pIOHandler) override;
 
 private:
     FBX::ImportSettings settings;
 }; // !class FBXImporter
 
 } // end of namespace Assimp
+
 #endif // !INCLUDED_AI_FBX_IMPORTER_H

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

@@ -142,8 +142,8 @@ Material::~Material() {
 
 // ------------------------------------------------------------------------------------------------
 Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
-        Object(id,element,name), 
-        uvScaling(1.0f,1.0f), 
+        Object(id,element,name),
+        uvScaling(1.0f,1.0f),
         media(0) {
     const Scope& sc = GetRequiredScope(element);
 
@@ -210,6 +210,11 @@ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const
         uvTrans.y = trans.y;
     }
 
+    const aiVector3D &rotation = PropertyGet<aiVector3D>(*props, "Rotation", ok);
+    if (ok) {
+        uvRotation = rotation.z;
+    }
+
     // resolve video links
     if(doc.Settings().readTextures) {
         const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID());
@@ -273,8 +278,8 @@ void LayeredTexture::fillTexture(const Document& doc) {
 
 // ------------------------------------------------------------------------------------------------
 Video::Video(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
-        Object(id,element,name), 
-        contentLength(0), 
+        Object(id,element,name),
+        contentLength(0),
         content(0) {
     const Scope& sc = GetRequiredScope(element);
 

+ 4 - 4
code/AssetLib/FBX/FBXMeshGeometry.cpp

@@ -604,15 +604,15 @@ void MeshGeometry::ReadVertexDataTangents(std::vector<aiVector3D>& tangents_out,
 }
 
 // ------------------------------------------------------------------------------------------------
-static const std::string BinormalIndexToken = "BinormalIndex";
-static const std::string BinormalsIndexToken = "BinormalsIndex";
+static const char * BinormalIndexToken = "BinormalIndex";
+static const char * BinormalsIndexToken = "BinormalsIndex";
 
 void MeshGeometry::ReadVertexDataBinormals(std::vector<aiVector3D>& binormals_out, const Scope& source,
     const std::string& MappingInformationType,
     const std::string& ReferenceInformationType)
 {
     const char * str = source.Elements().count( "Binormals" ) > 0 ? "Binormals" : "Binormal";
-    const char * strIdx = source.Elements().count( "Binormals" ) > 0 ? BinormalsIndexToken.c_str() : BinormalIndexToken.c_str();
+    const char * strIdx = source.Elements().count( "Binormals" ) > 0 ? BinormalsIndexToken : BinormalIndexToken;
     ResolveVertexDataArray(binormals_out,source,MappingInformationType,ReferenceInformationType,
         str,
         strIdx,
@@ -633,7 +633,7 @@ void MeshGeometry::ReadVertexDataMaterials(std::vector<int>& materials_out, cons
     {
         return;
     }
-    
+
     // materials are handled separately. First of all, they are assigned per-face
     // and not per polyvert. Secondly, ReferenceInformationType=IndexToDirect
     // has a slightly different meaning for materials.

+ 4 - 4
code/AssetLib/FBX/FBXMeshGeometry.h

@@ -52,8 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace FBX {
 
-/** 
- *  DOM base class for all kinds of FBX geometry 
+/**
+ *  DOM base class for all kinds of FBX geometry
  */
 class Geometry : public Object
 {
@@ -76,7 +76,7 @@ private:
 typedef std::vector<int> MatIndexArray;
 
 
-/** 
+/**
  *  DOM class for FBX geometry of type "Mesh"
  */
 class MeshGeometry : public Geometry
@@ -84,7 +84,7 @@ class MeshGeometry : public Geometry
 public:
     /** The class constructor */
     MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
-    
+
     /** The class destructor */
     virtual ~MeshGeometry();
 

+ 12 - 16
code/AssetLib/FBX/FBXParser.cpp

@@ -192,6 +192,10 @@ Scope::Scope(Parser& parser,bool topLevel)
         }
 
         const std::string& str = n->StringContents();
+        if (str.empty()) {
+            ParseError("unexpected content: empty string.");
+        }
+        
         elements.insert(ElementMap::value_type(str,new_Element(*n,parser)));
 
         // Element() should stop at the next Key token (or right after a Close token)
@@ -642,8 +646,7 @@ void ParseVectorDataArray(std::vector<aiVector3D>& out, const Element& el)
 
         ai_assert(data == end);
         uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
-        ai_assert(buff.size() == dataToRead);
-        if (dataToRead > buff.size()) {
+        if (dataToRead != buff.size()) {
             ParseError("Invalid read size (binary)",&el);
         }
 
@@ -733,8 +736,7 @@ void ParseVectorDataArray(std::vector<aiColor4D>& out, const Element& el)
 
         ai_assert(data == end);
         uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
-        ai_assert(buff.size() == dataToRead);
-        if (dataToRead > buff.size()) {
+        if (dataToRead != buff.size()) {
             ParseError("Invalid read size (binary)",&el);
         }
 
@@ -816,8 +818,7 @@ void ParseVectorDataArray(std::vector<aiVector2D>& out, const Element& el)
 
         ai_assert(data == end);
         uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
-        ai_assert(buff.size() == dataToRead);
-        if (dataToRead > buff.size()) {
+        if (dataToRead != buff.size()) {
             ParseError("Invalid read size (binary)",&el);
         }
 
@@ -892,8 +893,7 @@ void ParseVectorDataArray(std::vector<int>& out, const Element& el)
 
         ai_assert(data == end);
         uint64_t dataToRead = static_cast<uint64_t>(count) * 4;
-        ai_assert(buff.size() == dataToRead);
-        if (dataToRead > buff.size()) {
+        if (dataToRead != buff.size()) {
             ParseError("Invalid read size (binary)",&el);
         }
 
@@ -954,8 +954,7 @@ void ParseVectorDataArray(std::vector<float>& out, const Element& el)
 
         ai_assert(data == end);
         uint64_t dataToRead = static_cast<uint64_t>(count) * (type == 'd' ? 8 : 4);
-        ai_assert(buff.size() == dataToRead);
-        if (dataToRead > buff.size()) {
+        if (dataToRead != buff.size()) {
             ParseError("Invalid read size (binary)",&el);
         }
 
@@ -1019,8 +1018,7 @@ void ParseVectorDataArray(std::vector<unsigned int>& out, const Element& el)
 
         ai_assert(data == end);
         uint64_t dataToRead = static_cast<uint64_t>(count) * 4;
-        ai_assert(buff.size() == dataToRead);
-        if (dataToRead > buff.size()) {
+        if (dataToRead != buff.size()) {
             ParseError("Invalid read size (binary)",&el);
         }
 
@@ -1088,8 +1086,7 @@ void ParseVectorDataArray(std::vector<uint64_t>& out, const Element& el)
 
         ai_assert(data == end);
         uint64_t dataToRead = static_cast<uint64_t>(count) * 8;
-        ai_assert(buff.size() == dataToRead);
-        if (dataToRead > buff.size()) {
+        if (dataToRead != buff.size()) {
             ParseError("Invalid read size (binary)",&el);
         }
 
@@ -1150,8 +1147,7 @@ void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el)
 
         ai_assert(data == end);
         uint64_t dataToRead = static_cast<uint64_t>(count) * 8;
-        ai_assert(buff.size() == dataToRead);
-        if (dataToRead > buff.size()) {
+        if (dataToRead != buff.size()) {
             ParseError("Invalid read size (binary)",&el);
         }
 

+ 4 - 5
code/AssetLib/FBX/FBXProperties.cpp

@@ -52,6 +52,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "FBXDocumentUtil.h"
 #include "FBXProperties.h"
 
+#include <utility>
+
 namespace Assimp {
 namespace FBX {
 
@@ -172,10 +174,8 @@ PropertyTable::PropertyTable()
 }
 
 // ------------------------------------------------------------------------------------------------
-PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const PropertyTable> templateProps)
-: templateProps(templateProps)
-, element(&element)
-{
+PropertyTable::PropertyTable(const Element &element, std::shared_ptr<const PropertyTable> templateProps) :
+        templateProps(std::move(templateProps)), element(&element) {
     const Scope& scope = GetRequiredScope(element);
     for(const ElementMap::value_type& v : scope.Elements()) {
         if(v.first != "P") {
@@ -199,7 +199,6 @@ PropertyTable::PropertyTable(const Element& element, std::shared_ptr<const Prope
     }
 }
 
-
 // ------------------------------------------------------------------------------------------------
 PropertyTable::~PropertyTable()
 {

+ 3 - 3
code/AssetLib/FBX/FBXProperties.h

@@ -98,7 +98,7 @@ typedef std::fbx_unordered_map<std::string,std::shared_ptr<Property> > DirectPro
 typedef std::fbx_unordered_map<std::string,const Property*>            PropertyMap;
 typedef std::fbx_unordered_map<std::string,const Element*>             LazyPropertyMap;
 
-/** 
+/**
  *  Represents a property table as can be found in the newer FBX files (Properties60, Properties70)
  */
 class PropertyTable {
@@ -130,7 +130,7 @@ private:
 
 // ------------------------------------------------------------------------------------------------
 template <typename T>
-inline 
+inline
 T PropertyGet(const PropertyTable& in, const std::string& name, const T& defaultValue) {
     const Property* const prop = in.Get(name);
     if( nullptr == prop) {
@@ -148,7 +148,7 @@ T PropertyGet(const PropertyTable& in, const std::string& name, const T& default
 
 // ------------------------------------------------------------------------------------------------
 template <typename T>
-inline 
+inline
 T PropertyGet(const PropertyTable& in, const std::string& name, bool& result, bool useTemplate=false ) {
     const Property* prop = in.Get(name);
     if( nullptr == prop) {

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

@@ -101,7 +101,7 @@ std::string GetLineAndColumnText(unsigned int line, unsigned int column)
 std::string GetTokenText(const Token* tok)
 {
     if(tok->IsBinary()) {
-        return static_cast<std::string>( Formatter::format() << 
+        return static_cast<std::string>( Formatter::format() <<
             " (" << TokenTypeString(tok->Type()) <<
             ", offset 0x" << std::hex << tok->Offset() << ") " );
     }

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

@@ -153,10 +153,10 @@ void HMPImporter::InternReadFile(const std::string &pFile,
     } else {
         // Print the magic word to the logger
         std::string szBuffer = ai_str_toprintable((const char *)&iMagic, sizeof(iMagic));
-    
+
         delete[] mBuffer;
         mBuffer = nullptr;
-        
+
         // We're definitely unable to load this file
         throw DeadlyImportError("Unknown HMP subformat ", pFile,
                                 ". Magic word (", szBuffer, ") is not known");
@@ -451,6 +451,7 @@ void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char *szC
 
     // now we need to skip any other skins ...
     for (unsigned int i = 1; i < iNumSkins; ++i) {
+        SizeCheck(szCursor + 3 * sizeof(uint32_t));
         iType = *((uint32_t *)szCursor);
         szCursor += sizeof(uint32_t);
         iWidth = *((uint32_t *)szCursor);

+ 20 - 33
code/AssetLib/HMP/HMPLoader.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 Copyright (c) 2006-2021, assimp team
 
-
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -42,15 +41,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  HMPLoader.h
  *  @brief Declaration of the HMP importer class
  */
-
+#pragma once
 #ifndef AI_HMPLOADER_H_INCLUDED
 #define AI_HMPLOADER_H_INCLUDED
 
-// internal headers
 #include <assimp/BaseImporter.h>
 
-#include "AssetLib/MDL/MDLLoader.h"
+// internal headers
 #include "AssetLib/HMP/HMPFileData.h"
+#include "AssetLib/MDL/MDLLoader.h"
 
 namespace Assimp {
 using namespace HMP;
@@ -58,66 +57,58 @@ using namespace HMP;
 // ---------------------------------------------------------------------------
 /** Used to load 3D GameStudio HMP files (terrains)
 */
-class HMPImporter : public MDLImporter
-{
+class HMPImporter : public MDLImporter {
 public:
     HMPImporter();
-    ~HMPImporter();
-
-
-public:
+    ~HMPImporter() override;
 
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.
      * See BaseImporter::CanRead() for details.
      */
-    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
+            bool checkSig) const override;
 
 protected:
-
-
     // -------------------------------------------------------------------
     /** Return importer meta information.
      * See #BaseImporter::GetInfo for the details
      */
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc *GetInfo() const override;
 
     // -------------------------------------------------------------------
     /** Imports the given file into the given scene structure.
     * See BaseImporter::InternReadFile() for details
     */
-    void InternReadFile( const std::string& pFile, aiScene* pScene,
-        IOSystem* pIOHandler);
-
-protected:
+    void InternReadFile(const std::string &pFile, aiScene *pScene,
+            IOSystem *pIOHandler) override;
 
     // -------------------------------------------------------------------
     /** Import a HMP4 file
     */
-    void InternReadFile_HMP4( );
+    void InternReadFile_HMP4();
 
     // -------------------------------------------------------------------
     /** Import a HMP5 file
     */
-    void InternReadFile_HMP5( );
+    void InternReadFile_HMP5();
 
     // -------------------------------------------------------------------
     /** Import a HMP7 file
     */
-    void InternReadFile_HMP7( );
+    void InternReadFile_HMP7();
 
     // -------------------------------------------------------------------
     /** Validate a HMP 5,4,7 file header
     */
-    void ValidateHeader_HMP457( );
+    void ValidateHeader_HMP457();
 
     // -------------------------------------------------------------------
     /** Try to load one material from the file, if this fails create
      * a default material
     */
-    void CreateMaterial(const unsigned char* szCurrent,
-        const unsigned char** szCurrentOut);
+    void CreateMaterial(const unsigned char *szCurrent,
+            const unsigned char **szCurrentOut);
 
     // -------------------------------------------------------------------
     /** Build a list of output faces and vertices. The function
@@ -125,7 +116,7 @@ protected:
      * \param width Width of the height field
      * \param width Height of the height field
     */
-    void CreateOutputFaceList(unsigned int width,unsigned int height);
+    void CreateOutputFaceList(unsigned int width, unsigned int height);
 
     // -------------------------------------------------------------------
     /** Generate planar texture coordinates for a terrain
@@ -133,21 +124,17 @@ protected:
      * \param height Height of the terrain, in vertices
     */
     void GenerateTextureCoords(const unsigned int width,
-        const unsigned int height);
+            const unsigned int height);
 
     // -------------------------------------------------------------------
     /** Read the first skin from the file and skip all others ...
      *  \param iNumSkins Number of skins in the file
      *  \param szCursor Position of the first skin (offset 84)
     */
-    void ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
-        const unsigned char** szCursorOut);
-
-private:
-
+    void ReadFirstSkin(unsigned int iNumSkins, const unsigned char *szCursor,
+            const unsigned char **szCursorOut);
 };
 
 } // end of namespace Assimp
 
 #endif // AI_HMPIMPORTER_H_INC
-

+ 1 - 2
code/AssetLib/IFC/IFCBoolean.cpp

@@ -48,7 +48,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "Common/PolyTools.h"
 #include "PostProcessing/ProcessHelper.h"
 
-#include <assimp/Defines.h>
 
 #include <iterator>
 #include <tuple>
@@ -513,7 +512,7 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly
             }
 
             // we got a list of in-out-combinations of intersections. That should be an even number of intersections, or
-            // we're fucked.
+            // we are facing a non-recoverable error.
             if ((intersections.size() & 1) != 0) {
                 IFCImporter::LogWarn("Odd number of intersections, can't work with that. Omitting half space boundary check.");
                 continue;

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

@@ -514,7 +514,7 @@ IfcFloat Curve::GetParametricRangeDelta() const {
 
 // ------------------------------------------------------------------------------------------------
 size_t Curve::EstimateSampleCount(IfcFloat a, IfcFloat b) const {
-    (void)(a); (void)(b);  
+    (void)(a); (void)(b);
     ai_assert( InRange( a ) );
     ai_assert( InRange( b ) );
 

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

@@ -740,7 +740,7 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned
     bool fix_orientation = false;
     std::shared_ptr< TempMesh > meshtmp = std::make_shared<TempMesh>();
     if(const Schema_2x3::IfcShellBasedSurfaceModel* shellmod = geo.ToPtr<Schema_2x3::IfcShellBasedSurfaceModel>()) {
-        for(std::shared_ptr<const Schema_2x3::IfcShell> shell :shellmod->SbsmBoundary) {
+        for (const std::shared_ptr<const Schema_2x3::IfcShell> &shell : shellmod->SbsmBoundary) {
             try {
                 const ::Assimp::STEP::EXPRESS::ENTITY& e = shell->To<::Assimp::STEP::EXPRESS::ENTITY>();
                 const Schema_2x3::IfcConnectedFaceSet& fs = conv.db.MustGetObject(e).To<Schema_2x3::IfcConnectedFaceSet>();

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

@@ -137,9 +137,8 @@ bool IFCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
         // note: this is the common identification for STEP-encoded files, so
         // it is only unambiguous as long as we don't support any further
         // file formats with STEP as their encoding.
-        const char *tokens[] = { "ISO-10303-21" };
-        const bool found(SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1));
-        return found;
+        static const char * const tokens[] = { "ISO-10303-21" };
+        return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
     }
     return false;
 }

+ 34 - 52
code/AssetLib/IFC/IFCLoader.h

@@ -49,18 +49,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/BaseImporter.h>
 #include <assimp/LogAux.h>
 
-namespace Assimp    {
+namespace Assimp {
 
-    // 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;
-    }
+// TinyFormatter.h
+namespace Formatter {
 
-    namespace STEP {
-        class DB;
-    }
+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
+
+namespace STEP {
+
+class DB;
+
+}
 
 // -------------------------------------------------------------------------------------------
 /** Load the IFC format, which is an open specification to describe building and construction
@@ -69,63 +73,41 @@ namespace Assimp    {
  See http://en.wikipedia.org/wiki/Industry_Foundation_Classes
 */
 // -------------------------------------------------------------------------------------------
-class IFCImporter : public BaseImporter, public LogFunctions<IFCImporter>
-{
+class IFCImporter : public BaseImporter, public LogFunctions<IFCImporter> {
 public:
-    IFCImporter();
-    ~IFCImporter();
+    // loader settings, publicly accessible via their corresponding AI_CONFIG constants
+    struct Settings {
+        Settings() :
+                skipSpaceRepresentations(), useCustomTriangulation(), skipAnnotations(), conicSamplingAngle(10.f), cylindricalTessellation(32) {}
 
+        bool skipSpaceRepresentations;
+        bool useCustomTriangulation;
+        bool skipAnnotations;
+        float conicSamplingAngle;
+        int cylindricalTessellation;
+    };
 
-public:
+    IFCImporter();
+    ~IFCImporter() override;
 
     // --------------------
-    bool CanRead( const std::string& pFile,
-        IOSystem* pIOHandler,
-        bool checkSig
-    ) const;
+    bool CanRead(const std::string &pFile,
+            IOSystem *pIOHandler,
+            bool checkSig) const override;
 
 protected:
-
     // --------------------
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc *GetInfo() const override;
 
     // --------------------
-    void SetupProperties(const Importer* pImp);
+    void SetupProperties(const Importer *pImp) override;
 
     // --------------------
-    void InternReadFile( const std::string& pFile,
-        aiScene* pScene,
-        IOSystem* pIOHandler
-    );
-
-private:
-
-
-public:
-
-
-    // loader settings, publicly accessible via their corresponding AI_CONFIG constants
-    struct Settings
-    {
-        Settings()
-            : skipSpaceRepresentations()
-            , useCustomTriangulation()
-            , skipAnnotations()
-            , conicSamplingAngle(10.f)
-			, cylindricalTessellation(32)
-        {}
-
-
-        bool skipSpaceRepresentations;
-        bool useCustomTriangulation;
-        bool skipAnnotations;
-        float conicSamplingAngle;
-		int cylindricalTessellation;
-    };
-
+    void InternReadFile(const std::string &pFile,
+            aiScene *pScene,
+            IOSystem *pIOHandler) override;
 
 private:
-
     Settings settings;
 
 }; // !class IFCImporter

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

@@ -75,7 +75,7 @@ static void FillMaterial(aiMaterial* mat,const IFC::Schema_2x3::IfcSurfaceStyle*
     mat->AddProperty(&name,AI_MATKEY_NAME);
 
     // now see which kinds of surface information are present
-    for(std::shared_ptr< const IFC::Schema_2x3::IfcSurfaceStyleElementSelect > sel2 : surf->Styles) {
+    for (const std::shared_ptr<const IFC::Schema_2x3::IfcSurfaceStyleElementSelect> &sel2 : surf->Styles) {
         if (const IFC::Schema_2x3::IfcSurfaceStyleShading* shade = sel2->ResolveSelectPtr<IFC::Schema_2x3::IfcSurfaceStyleShading>(conv.db)) {
             aiColor4D col_base,col;
 
@@ -124,7 +124,7 @@ static void FillMaterial(aiMaterial* mat,const IFC::Schema_2x3::IfcSurfaceStyle*
                     }
                 }
             }
-        } 
+        }
     }
 }
 
@@ -134,7 +134,7 @@ unsigned int ProcessMaterials(uint64_t id, unsigned int prevMatId, ConversionDat
     for(;range.first != range.second; ++range.first) {
         if(const IFC::Schema_2x3::IfcStyledItem* const styled = conv.db.GetObject((*range.first).second)->ToPtr<IFC::Schema_2x3::IfcStyledItem>()) {
             for(const IFC::Schema_2x3::IfcPresentationStyleAssignment& as : styled->Styles) {
-                for(std::shared_ptr<const IFC::Schema_2x3::IfcPresentationStyleSelect> sel : as.Styles) {
+                for (const std::shared_ptr<const IFC::Schema_2x3::IfcPresentationStyleSelect> &sel : as.Styles) {
 
                     if( const IFC::Schema_2x3::IfcSurfaceStyle* const surf = sel->ResolveSelectPtr<IFC::Schema_2x3::IfcSurfaceStyle>(conv.db) ) {
                         // try to satisfy from cache

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

@@ -911,14 +911,14 @@ size_t CloseWindows(ContourVector& contours,
             // compare base poly normal and contour normal to detect if we need to reverse the face winding
 			if(curmesh.mVertcnt.size() > 0) {
 				IfcVector3 basePolyNormal = TempMesh::ComputePolygonNormal(curmesh.mVerts.data(), curmesh.mVertcnt.front());
-				
+
 				std::vector<IfcVector3> worldSpaceContourVtx(it->contour.size());
-				
+
 				for(size_t a = 0; a < it->contour.size(); ++a)
 					worldSpaceContourVtx[a] = minv * IfcVector3(it->contour[a].x, it->contour[a].y, 0.0);
-				
+
 				IfcVector3 contourNormal = TempMesh::ComputePolygonNormal(worldSpaceContourVtx.data(), worldSpaceContourVtx.size());
-				
+
 				reverseCountourFaces = (contourNormal * basePolyNormal) > 0.0;
 			}
 

+ 116 - 116
code/AssetLib/IFC/IFCReaderGen1_2x3.cpp

@@ -5,8 +5,8 @@ Open Asset Import Library (ASSIMP)
 Copyright (c) 2006-2020, ASSIMP Development Team
 All rights reserved.
 
-Redistribution and use of this software in source and binary forms, 
-with or without modification, are permitted provided that the 
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
 following conditions are met:
 
 * Redistributions of source code must retain the above
@@ -23,16 +23,16 @@ following conditions are met:
   derived from this software without specific prior
   written permission of the ASSIMP Development Team.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 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.
 
 ----------------------------------------------------------------------
@@ -1063,27 +1063,27 @@ template <> size_t GenericFill<IfcRoot>(const DB& db, const LIST& params, IfcRoo
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRoot"); }    do { // convert the 'GlobalId' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRoot,4>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->GlobalId, arg, db ); break; } 
+        try { GenericConvert( in->GlobalId, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRoot to be a `IfcGloballyUniqueId`")); }
     } while(0);
     do { // convert the 'OwnerHistory' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRoot,4>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->OwnerHistory, arg, db ); break; } 
+        try { GenericConvert( in->OwnerHistory, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRoot to be a `IfcOwnerHistory`")); }
     } while(0);
     do { // convert the 'Name' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRoot,4>::aux_is_derived[2]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Name, arg, db ); break; } 
+        try { GenericConvert( in->Name, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcRoot to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'Description' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRoot,4>::aux_is_derived[3]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Description, arg, db ); break; } 
+        try { GenericConvert( in->Description, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRoot to be a `IfcText`")); }
     } while(0);
 	return base;
@@ -1150,27 +1150,27 @@ template <> size_t GenericFill<IfcRepresentation>(const DB& db, const LIST& para
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRepresentation"); }    do { // convert the 'ContextOfItems' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRepresentation,4>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->ContextOfItems, arg, db ); break; } 
+        try { GenericConvert( in->ContextOfItems, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRepresentation to be a `IfcRepresentationContext`")); }
     } while(0);
     do { // convert the 'RepresentationIdentifier' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRepresentation,4>::aux_is_derived[1]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->RepresentationIdentifier, arg, db ); break; } 
+        try { GenericConvert( in->RepresentationIdentifier, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRepresentation to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'RepresentationType' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRepresentation,4>::aux_is_derived[2]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->RepresentationType, arg, db ); break; } 
+        try { GenericConvert( in->RepresentationType, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcRepresentation to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'Items' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRepresentation,4>::aux_is_derived[3]=true; break; }
-        try { GenericConvert( in->Items, arg, db ); break; } 
+        try { GenericConvert( in->Items, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRepresentation to be a `SET [1:?] OF IfcRepresentationItem`")); }
     } while(0);
 	return base;
@@ -1237,7 +1237,7 @@ template <> size_t GenericFill<IfcObject>(const DB& db, const LIST& params, IfcO
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcObject,1>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->ObjectType, arg, db ); break; } 
+        try { GenericConvert( in->ObjectType, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcObject to be a `IfcLabel`")); }
     } while(0);
 	return base;
@@ -1290,20 +1290,20 @@ template <> size_t GenericFill<IfcProductRepresentation>(const DB& db, const LIS
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcProductRepresentation,3>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Name, arg, db ); break; } 
+        try { GenericConvert( in->Name, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcProductRepresentation to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'Description' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcProductRepresentation,3>::aux_is_derived[1]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Description, arg, db ); break; } 
+        try { GenericConvert( in->Description, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcProductRepresentation to be a `IfcText`")); }
     } while(0);
     do { // convert the 'Representations' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcProductRepresentation,3>::aux_is_derived[2]=true; break; }
-        try { GenericConvert( in->Representations, arg, db ); break; } 
+        try { GenericConvert( in->Representations, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcProductRepresentation to be a `LIST [1:?] OF IfcRepresentation`")); }
     } while(0);
 	return base;
@@ -1316,14 +1316,14 @@ template <> size_t GenericFill<IfcProduct>(const DB& db, const LIST& params, Ifc
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcProduct,2>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->ObjectPlacement, arg, db ); break; } 
+        try { GenericConvert( in->ObjectPlacement, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcProduct to be a `IfcObjectPlacement`")); }
     } while(0);
     do { // convert the 'Representation' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcProduct,2>::aux_is_derived[1]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Representation, arg, db ); break; } 
+        try { GenericConvert( in->Representation, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcProduct to be a `IfcProductRepresentation`")); }
     } while(0);
 	return base;
@@ -1336,7 +1336,7 @@ template <> size_t GenericFill<IfcElement>(const DB& db, const LIST& params, Ifc
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcElement,1>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Tag, arg, db ); break; } 
+        try { GenericConvert( in->Tag, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcElement to be a `IfcIdentifier`")); }
     } while(0);
 	return base;
@@ -1374,13 +1374,13 @@ template <> size_t GenericFill<IfcCompositeCurve>(const DB& db, const LIST& para
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcCompositeCurve"); }    do { // convert the 'Segments' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcCompositeCurve,2>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Segments, arg, db ); break; } 
+        try { GenericConvert( in->Segments, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCompositeCurve to be a `LIST [1:?] OF IfcCompositeCurveSegment`")); }
     } while(0);
     do { // convert the 'SelfIntersect' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcCompositeCurve,2>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->SelfIntersect, arg, db ); break; } 
+        try { GenericConvert( in->SelfIntersect, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCompositeCurve to be a `LOGICAL`")); }
     } while(0);
 	return base;
@@ -1400,27 +1400,27 @@ template <> size_t GenericFill<IfcCartesianTransformationOperator>(const DB& db,
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcCartesianTransformationOperator,4>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Axis1, arg, db ); break; } 
+        try { GenericConvert( in->Axis1, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCartesianTransformationOperator to be a `IfcDirection`")); }
     } while(0);
     do { // convert the 'Axis2' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcCartesianTransformationOperator,4>::aux_is_derived[1]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Axis2, arg, db ); break; } 
+        try { GenericConvert( in->Axis2, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCartesianTransformationOperator to be a `IfcDirection`")); }
     } while(0);
     do { // convert the 'LocalOrigin' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcCartesianTransformationOperator,4>::aux_is_derived[2]=true; break; }
-        try { GenericConvert( in->LocalOrigin, arg, db ); break; } 
+        try { GenericConvert( in->LocalOrigin, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcCartesianTransformationOperator to be a `IfcCartesianPoint`")); }
     } while(0);
     do { // convert the 'Scale' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcCartesianTransformationOperator,4>::aux_is_derived[3]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Scale, arg, db ); break; } 
+        try { GenericConvert( in->Scale, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcCartesianTransformationOperator to be a `REAL`")); }
     } while(0);
 	return base;
@@ -1433,7 +1433,7 @@ template <> size_t GenericFill<IfcCartesianTransformationOperator3D>(const DB& d
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcCartesianTransformationOperator3D,1>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Axis3, arg, db ); break; } 
+        try { GenericConvert( in->Axis3, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcCartesianTransformationOperator3D to be a `IfcDirection`")); }
     } while(0);
 	return base;
@@ -1445,14 +1445,14 @@ template <> size_t GenericFill<IfcProperty>(const DB& db, const LIST& params, If
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcProperty"); }    do { // convert the 'Name' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcProperty,2>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Name, arg, db ); break; } 
+        try { GenericConvert( in->Name, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcProperty to be a `IfcIdentifier`")); }
     } while(0);
     do { // convert the 'Description' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcProperty,2>::aux_is_derived[1]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Description, arg, db ); break; } 
+        try { GenericConvert( in->Description, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcProperty to be a `IfcText`")); }
     } while(0);
 	return base;
@@ -1497,7 +1497,7 @@ template <> size_t GenericFill<IfcElementarySurface>(const DB& db, const LIST& p
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcElementarySurface"); }    do { // convert the 'Position' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcElementarySurface,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Position, arg, db ); break; } 
+        try { GenericConvert( in->Position, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcElementarySurface to be a `IfcAxis2Placement3D`")); }
     } while(0);
 	return base;
@@ -1515,19 +1515,19 @@ template <> size_t GenericFill<IfcBooleanResult>(const DB& db, const LIST& param
 	if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcBooleanResult"); }    do { // convert the 'Operator' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcBooleanResult,3>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Operator, arg, db ); break; } 
+        try { GenericConvert( in->Operator, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcBooleanResult to be a `IfcBooleanOperator`")); }
     } while(0);
     do { // convert the 'FirstOperand' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcBooleanResult,3>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->FirstOperand, arg, db ); break; } 
+        try { GenericConvert( in->FirstOperand, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcBooleanResult to be a `IfcBooleanOperand`")); }
     } while(0);
     do { // convert the 'SecondOperand' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcBooleanResult,3>::aux_is_derived[2]=true; break; }
-        try { GenericConvert( in->SecondOperand, arg, db ); break; } 
+        try { GenericConvert( in->SecondOperand, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcBooleanResult to be a `IfcBooleanOperand`")); }
     } while(0);
 	return base;
@@ -1551,7 +1551,7 @@ template <> size_t GenericFill<IfcManifoldSolidBrep>(const DB& db, const LIST& p
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcManifoldSolidBrep"); }    do { // convert the 'Outer' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcManifoldSolidBrep,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Outer, arg, db ); break; } 
+        try { GenericConvert( in->Outer, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcManifoldSolidBrep to be a `IfcClosedShell`")); }
     } while(0);
 	return base;
@@ -1630,12 +1630,12 @@ template <> size_t GenericFill<IfcRelFillsElement>(const DB& db, const LIST& par
 	size_t base = GenericFill(db,params,static_cast<IfcRelConnects*>(in));
 	if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelFillsElement"); }    do { // convert the 'RelatingOpeningElement' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->RelatingOpeningElement, arg, db ); break; } 
+        try { GenericConvert( in->RelatingOpeningElement, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelFillsElement to be a `IfcOpeningElement`")); }
     } while(0);
     do { // convert the 'RelatedBuildingElement' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->RelatedBuildingElement, arg, db ); break; } 
+        try { GenericConvert( in->RelatedBuildingElement, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelFillsElement to be a `IfcElement`")); }
     } while(0);
 	return base;
@@ -1681,12 +1681,12 @@ template <> size_t GenericFill<IfcRelContainedInSpatialStructure>(const DB& db,
 	size_t base = GenericFill(db,params,static_cast<IfcRelConnects*>(in));
 	if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelContainedInSpatialStructure"); }    do { // convert the 'RelatedElements' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->RelatedElements, arg, db ); break; } 
+        try { GenericConvert( in->RelatedElements, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelContainedInSpatialStructure to be a `SET [1:?] OF IfcProduct`")); }
     } while(0);
     do { // convert the 'RelatingStructure' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->RelatingStructure, arg, db ); break; } 
+        try { GenericConvert( in->RelatingStructure, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelContainedInSpatialStructure to be a `IfcSpatialStructureElement`")); }
     } while(0);
 	return base;
@@ -1772,7 +1772,7 @@ template <> size_t GenericFill<IfcDirection>(const DB& db, const LIST& params, I
 	size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcDirection"); }    do { // convert the 'DirectionRatios' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->DirectionRatios, arg, db ); break; } 
+        try { GenericConvert( in->DirectionRatios, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcDirection to be a `LIST [2:3] OF REAL`")); }
     } while(0);
 	return base;
@@ -1784,14 +1784,14 @@ template <> size_t GenericFill<IfcProfileDef>(const DB& db, const LIST& params,
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcProfileDef"); }    do { // convert the 'ProfileType' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcProfileDef,2>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->ProfileType, arg, db ); break; } 
+        try { GenericConvert( in->ProfileType, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcProfileDef to be a `IfcProfileTypeEnum`")); }
     } while(0);
     do { // convert the 'ProfileName' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcProfileDef,2>::aux_is_derived[1]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->ProfileName, arg, db ); break; } 
+        try { GenericConvert( in->ProfileName, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcProfileDef to be a `IfcLabel`")); }
     } while(0);
 	return base;
@@ -1803,7 +1803,7 @@ template <> size_t GenericFill<IfcParameterizedProfileDef>(const DB& db, const L
 	if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcParameterizedProfileDef"); }    do { // convert the 'Position' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcParameterizedProfileDef,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Position, arg, db ); break; } 
+        try { GenericConvert( in->Position, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcParameterizedProfileDef to be a `IfcAxis2Placement2D`")); }
     } while(0);
 	return base;
@@ -1910,7 +1910,7 @@ template <> size_t GenericFill<IfcCircleProfileDef>(const DB& db, const LIST& pa
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcCircleProfileDef"); }    do { // convert the 'Radius' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcCircleProfileDef,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Radius, arg, db ); break; } 
+        try { GenericConvert( in->Radius, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcCircleProfileDef to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
 	return base;
@@ -1921,7 +1921,7 @@ template <> size_t GenericFill<IfcCircleHollowProfileDef>(const DB& db, const LI
 	size_t base = GenericFill(db,params,static_cast<IfcCircleProfileDef*>(in));
 	if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcCircleHollowProfileDef"); }    do { // convert the 'WallThickness' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->WallThickness, arg, db ); break; } 
+        try { GenericConvert( in->WallThickness, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcCircleHollowProfileDef to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
 	return base;
@@ -1933,7 +1933,7 @@ template <> size_t GenericFill<IfcPlacement>(const DB& db, const LIST& params, I
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPlacement"); }    do { // convert the 'Location' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcPlacement,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Location, arg, db ); break; } 
+        try { GenericConvert( in->Location, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPlacement to be a `IfcCartesianPoint`")); }
     } while(0);
 	return base;
@@ -1945,13 +1945,13 @@ template <> size_t GenericFill<IfcAxis2Placement3D>(const DB& db, const LIST& pa
 	if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcAxis2Placement3D"); }    do { // convert the 'Axis' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Axis, arg, db ); break; } 
+        try { GenericConvert( in->Axis, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis2Placement3D to be a `IfcDirection`")); }
     } while(0);
     do { // convert the 'RefDirection' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->RefDirection, arg, db ); break; } 
+        try { GenericConvert( in->RefDirection, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcAxis2Placement3D to be a `IfcDirection`")); }
     } while(0);
 	return base;
@@ -1964,7 +1964,7 @@ template <> size_t GenericFill<IfcPresentationStyle>(const DB& db, const LIST& p
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcPresentationStyle,1>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Name, arg, db ); break; } 
+        try { GenericConvert( in->Name, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPresentationStyle to be a `IfcLabel`")); }
     } while(0);
 	return base;
@@ -1982,17 +1982,17 @@ template <> size_t GenericFill<IfcCompositeCurveSegment>(const DB& db, const LIS
 	size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
 	if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcCompositeCurveSegment"); }    do { // convert the 'Transition' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Transition, arg, db ); break; } 
+        try { GenericConvert( in->Transition, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCompositeCurveSegment to be a `IfcTransitionCode`")); }
     } while(0);
     do { // convert the 'SameSense' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->SameSense, arg, db ); break; } 
+        try { GenericConvert( in->SameSense, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCompositeCurveSegment to be a `BOOLEAN`")); }
     } while(0);
     do { // convert the 'ParentCurve' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->ParentCurve, arg, db ); break; } 
+        try { GenericConvert( in->ParentCurve, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcCompositeCurveSegment to be a `IfcCurve`")); }
     } while(0);
 	return base;
@@ -2004,13 +2004,13 @@ template <> size_t GenericFill<IfcRectangleProfileDef>(const DB& db, const LIST&
 	if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcRectangleProfileDef"); }    do { // convert the 'XDim' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRectangleProfileDef,2>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->XDim, arg, db ); break; } 
+        try { GenericConvert( in->XDim, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRectangleProfileDef to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'YDim' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRectangleProfileDef,2>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->YDim, arg, db ); break; } 
+        try { GenericConvert( in->YDim, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRectangleProfileDef to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
 	return base;
@@ -2106,12 +2106,12 @@ template <> size_t GenericFill<IfcLocalPlacement>(const DB& db, const LIST& para
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcLocalPlacement"); }    do { // convert the 'PlacementRelTo' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->PlacementRelTo, arg, db ); break; } 
+        try { GenericConvert( in->PlacementRelTo, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcLocalPlacement to be a `IfcObjectPlacement`")); }
     } while(0);
     do { // convert the 'RelativePlacement' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->RelativePlacement, arg, db ); break; } 
+        try { GenericConvert( in->RelativePlacement, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcLocalPlacement to be a `IfcAxis2Placement`")); }
     } while(0);
 	return base;
@@ -2123,13 +2123,13 @@ template <> size_t GenericFill<IfcSweptAreaSolid>(const DB& db, const LIST& para
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcSweptAreaSolid"); }    do { // convert the 'SweptArea' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcSweptAreaSolid,2>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->SweptArea, arg, db ); break; } 
+        try { GenericConvert( in->SweptArea, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSweptAreaSolid to be a `IfcProfileDef`")); }
     } while(0);
     do { // convert the 'Position' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcSweptAreaSolid,2>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->Position, arg, db ); break; } 
+        try { GenericConvert( in->Position, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSweptAreaSolid to be a `IfcAxis2Placement3D`")); }
     } while(0);
 	return base;
@@ -2140,12 +2140,12 @@ template <> size_t GenericFill<IfcRevolvedAreaSolid>(const DB& db, const LIST& p
 	size_t base = GenericFill(db,params,static_cast<IfcSweptAreaSolid*>(in));
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcRevolvedAreaSolid"); }    do { // convert the 'Axis' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Axis, arg, db ); break; } 
+        try { GenericConvert( in->Axis, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcRevolvedAreaSolid to be a `IfcAxis1Placement`")); }
     } while(0);
     do { // convert the 'Angle' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Angle, arg, db ); break; } 
+        try { GenericConvert( in->Angle, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcRevolvedAreaSolid to be a `IfcPlaneAngleMeasure`")); }
     } while(0);
 	return base;
@@ -2170,28 +2170,28 @@ template <> size_t GenericFill<IfcSweptDiskSolid>(const DB& db, const LIST& para
 	size_t base = GenericFill(db,params,static_cast<IfcSolidModel*>(in));
 	if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcSweptDiskSolid"); }    do { // convert the 'Directrix' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Directrix, arg, db ); break; } 
+        try { GenericConvert( in->Directrix, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSweptDiskSolid to be a `IfcCurve`")); }
     } while(0);
     do { // convert the 'Radius' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Radius, arg, db ); break; } 
+        try { GenericConvert( in->Radius, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSweptDiskSolid to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'InnerRadius' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->InnerRadius, arg, db ); break; } 
+        try { GenericConvert( in->InnerRadius, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSweptDiskSolid to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'StartParam' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->StartParam, arg, db ); break; } 
+        try { GenericConvert( in->StartParam, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcSweptDiskSolid to be a `IfcParameterValue`")); }
     } while(0);
     do { // convert the 'EndParam' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->EndParam, arg, db ); break; } 
+        try { GenericConvert( in->EndParam, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcSweptDiskSolid to be a `IfcParameterValue`")); }
     } while(0);
 	return base;
@@ -2203,13 +2203,13 @@ template <> size_t GenericFill<IfcHalfSpaceSolid>(const DB& db, const LIST& para
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcHalfSpaceSolid"); }    do { // convert the 'BaseSurface' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcHalfSpaceSolid,2>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->BaseSurface, arg, db ); break; } 
+        try { GenericConvert( in->BaseSurface, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcHalfSpaceSolid to be a `IfcSurface`")); }
     } while(0);
     do { // convert the 'AgreementFlag' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcHalfSpaceSolid,2>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->AgreementFlag, arg, db ); break; } 
+        try { GenericConvert( in->AgreementFlag, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcHalfSpaceSolid to be a `BOOLEAN`")); }
     } while(0);
 	return base;
@@ -2220,12 +2220,12 @@ template <> size_t GenericFill<IfcPolygonalBoundedHalfSpace>(const DB& db, const
 	size_t base = GenericFill(db,params,static_cast<IfcHalfSpaceSolid*>(in));
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPolygonalBoundedHalfSpace"); }    do { // convert the 'Position' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Position, arg, db ); break; } 
+        try { GenericConvert( in->Position, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcPolygonalBoundedHalfSpace to be a `IfcAxis2Placement3D`")); }
     } while(0);
     do { // convert the 'PolygonalBoundary' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->PolygonalBoundary, arg, db ); break; } 
+        try { GenericConvert( in->PolygonalBoundary, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcPolygonalBoundedHalfSpace to be a `IfcBoundedCurve`")); }
     } while(0);
 	return base;
@@ -2251,23 +2251,23 @@ template <> size_t GenericFill<IfcProject>(const DB& db, const LIST& params, Ifc
 	if (params.GetSize() < 9) { throw STEP::TypeError("expected 9 arguments to IfcProject"); }    do { // convert the 'LongName' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->LongName, arg, db ); break; } 
+        try { GenericConvert( in->LongName, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcProject to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'Phase' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Phase, arg, db ); break; } 
+        try { GenericConvert( in->Phase, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcProject to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'RepresentationContexts' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->RepresentationContexts, arg, db ); break; } 
+        try { GenericConvert( in->RepresentationContexts, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcProject to be a `SET [1:?] OF IfcRepresentationContext`")); }
     } while(0);
     do { // convert the 'UnitsInContext' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->UnitsInContext, arg, db ); break; } 
+        try { GenericConvert( in->UnitsInContext, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcProject to be a `IfcUnitAssignment`")); }
     } while(0);
 	return base;
@@ -2327,27 +2327,27 @@ template <> size_t GenericFill<IfcTrimmedCurve>(const DB& db, const LIST& params
 	size_t base = GenericFill(db,params,static_cast<IfcBoundedCurve*>(in));
 	if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcTrimmedCurve"); }    do { // convert the 'BasisCurve' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->BasisCurve, arg, db ); break; } 
+        try { GenericConvert( in->BasisCurve, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcTrimmedCurve to be a `IfcCurve`")); }
     } while(0);
     do { // convert the 'Trim1' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Trim1, arg, db ); break; } 
+        try { GenericConvert( in->Trim1, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcTrimmedCurve to be a `SET [1:2] OF IfcTrimmingSelect`")); }
     } while(0);
     do { // convert the 'Trim2' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Trim2, arg, db ); break; } 
+        try { GenericConvert( in->Trim2, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcTrimmedCurve to be a `SET [1:2] OF IfcTrimmingSelect`")); }
     } while(0);
     do { // convert the 'SenseAgreement' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->SenseAgreement, arg, db ); break; } 
+        try { GenericConvert( in->SenseAgreement, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcTrimmedCurve to be a `BOOLEAN`")); }
     } while(0);
     do { // convert the 'MasterRepresentation' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->MasterRepresentation, arg, db ); break; } 
+        try { GenericConvert( in->MasterRepresentation, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcTrimmedCurve to be a `IfcTrimmingPreference`")); }
     } while(0);
 	return base;
@@ -2359,7 +2359,7 @@ template <> size_t GenericFill<IfcRelDefines>(const DB& db, const LIST& params,
 	if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcRelDefines"); }    do { // convert the 'RelatedObjects' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRelDefines,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->RelatedObjects, arg, db ); break; } 
+        try { GenericConvert( in->RelatedObjects, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelDefines to be a `SET [1:?] OF IfcObject`")); }
     } while(0);
 	return base;
@@ -2371,7 +2371,7 @@ template <> size_t GenericFill<IfcRelDefinesByProperties>(const DB& db, const LI
 	if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelDefinesByProperties"); }    do { // convert the 'RelatingPropertyDefinition' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRelDefinesByProperties,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->RelatingPropertyDefinition, arg, db ); break; } 
+        try { GenericConvert( in->RelatingPropertyDefinition, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelDefinesByProperties to be a `IfcPropertySetDefinition`")); }
     } while(0);
 	return base;
@@ -2404,7 +2404,7 @@ template <> size_t GenericFill<IfcArbitraryOpenProfileDef>(const DB& db, const L
 	if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcArbitraryOpenProfileDef"); }    do { // convert the 'Curve' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcArbitraryOpenProfileDef,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Curve, arg, db ); break; } 
+        try { GenericConvert( in->Curve, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcArbitraryOpenProfileDef to be a `IfcBoundedCurve`")); }
     } while(0);
 	return base;
@@ -2570,13 +2570,13 @@ template <> size_t GenericFill<IfcRelDecomposes>(const DB& db, const LIST& param
 	if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelDecomposes"); }    do { // convert the 'RelatingObject' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRelDecomposes,2>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->RelatingObject, arg, db ); break; } 
+        try { GenericConvert( in->RelatingObject, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelDecomposes to be a `IfcObjectDefinition`")); }
     } while(0);
     do { // convert the 'RelatedObjects' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRelDecomposes,2>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->RelatedObjects, arg, db ); break; } 
+        try { GenericConvert( in->RelatedObjects, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelDecomposes to be a `SET [1:?] OF IfcObjectDefinition`")); }
     } while(0);
 	return base;
@@ -2594,7 +2594,7 @@ template <> size_t GenericFill<IfcPolyline>(const DB& db, const LIST& params, If
 	size_t base = GenericFill(db,params,static_cast<IfcBoundedCurve*>(in));
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPolyline"); }    do { // convert the 'Points' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Points, arg, db ); break; } 
+        try { GenericConvert( in->Points, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPolyline to be a `LIST [2:?] OF IfcCartesianPoint`")); }
     } while(0);
 	return base;
@@ -2626,12 +2626,12 @@ template <> size_t GenericFill<IfcMappedItem>(const DB& db, const LIST& params,
 	size_t base = GenericFill(db,params,static_cast<IfcRepresentationItem*>(in));
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcMappedItem"); }    do { // convert the 'MappingSource' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->MappingSource, arg, db ); break; } 
+        try { GenericConvert( in->MappingSource, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcMappedItem to be a `IfcRepresentationMap`")); }
     } while(0);
     do { // convert the 'MappingTarget' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->MappingTarget, arg, db ); break; } 
+        try { GenericConvert( in->MappingTarget, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcMappedItem to be a `IfcCartesianTransformationOperator`")); }
     } while(0);
 	return base;
@@ -2658,13 +2658,13 @@ template <> size_t GenericFill<IfcNamedUnit>(const DB& db, const LIST& params, I
         std::shared_ptr<const DataType> arg = params[base++];
 		if (dynamic_cast<const UNSET*>(&*arg)) break;
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcNamedUnit,2>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Dimensions, arg, db ); break; } 
+        try { GenericConvert( in->Dimensions, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcNamedUnit to be a `IfcDimensionalExponents`")); }
     } while(0);
     do { // convert the 'UnitType' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcNamedUnit,2>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->UnitType, arg, db ); break; } 
+        try { GenericConvert( in->UnitType, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcNamedUnit to be a `IfcUnitEnum`")); }
     } while(0);
 	return base;
@@ -2719,13 +2719,13 @@ template <> size_t GenericFill<IfcSpatialStructureElement>(const DB& db, const L
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcSpatialStructureElement,2>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->LongName, arg, db ); break; } 
+        try { GenericConvert( in->LongName, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcSpatialStructureElement to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'CompositionType' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcSpatialStructureElement,2>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->CompositionType, arg, db ); break; } 
+        try { GenericConvert( in->CompositionType, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcSpatialStructureElement to be a `IfcElementCompositionEnum`")); }
     } while(0);
 	return base;
@@ -2737,19 +2737,19 @@ template <> size_t GenericFill<IfcBuilding>(const DB& db, const LIST& params, If
 	if (params.GetSize() < 12) { throw STEP::TypeError("expected 12 arguments to IfcBuilding"); }    do { // convert the 'ElevationOfRefHeight' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->ElevationOfRefHeight, arg, db ); break; } 
+        try { GenericConvert( in->ElevationOfRefHeight, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcBuilding to be a `IfcLengthMeasure`")); }
     } while(0);
     do { // convert the 'ElevationOfTerrain' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->ElevationOfTerrain, arg, db ); break; } 
+        try { GenericConvert( in->ElevationOfTerrain, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 10 to IfcBuilding to be a `IfcLengthMeasure`")); }
     } while(0);
     do { // convert the 'BuildingAddress' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->BuildingAddress, arg, db ); break; } 
+        try { GenericConvert( in->BuildingAddress, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 11 to IfcBuilding to be a `IfcPostalAddress`")); }
     } while(0);
 	return base;
@@ -2761,7 +2761,7 @@ template <> size_t GenericFill<IfcConnectedFaceSet>(const DB& db, const LIST& pa
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcConnectedFaceSet"); }    do { // convert the 'CfsFaces' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcConnectedFaceSet,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->CfsFaces, arg, db ); break; } 
+        try { GenericConvert( in->CfsFaces, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcConnectedFaceSet to be a `SET [1:?] OF IfcFace`")); }
     } while(0);
 	return base;
@@ -2787,7 +2787,7 @@ template <> size_t GenericFill<IfcConic>(const DB& db, const LIST& params, IfcCo
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcConic"); }    do { // convert the 'Position' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcConic,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Position, arg, db ); break; } 
+        try { GenericConvert( in->Position, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcConic to be a `IfcAxis2Placement`")); }
     } while(0);
 	return base;
@@ -2834,32 +2834,32 @@ template <> size_t GenericFill<IfcIShapeProfileDef>(const DB& db, const LIST& pa
 	if (params.GetSize() < 8) { throw STEP::TypeError("expected 8 arguments to IfcIShapeProfileDef"); }    do { // convert the 'OverallWidth' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcIShapeProfileDef,5>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->OverallWidth, arg, db ); break; } 
+        try { GenericConvert( in->OverallWidth, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'OverallDepth' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcIShapeProfileDef,5>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->OverallDepth, arg, db ); break; } 
+        try { GenericConvert( in->OverallDepth, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'WebThickness' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcIShapeProfileDef,5>::aux_is_derived[2]=true; break; }
-        try { GenericConvert( in->WebThickness, arg, db ); break; } 
+        try { GenericConvert( in->WebThickness, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'FlangeThickness' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcIShapeProfileDef,5>::aux_is_derived[3]=true; break; }
-        try { GenericConvert( in->FlangeThickness, arg, db ); break; } 
+        try { GenericConvert( in->FlangeThickness, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'FilletRadius' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcIShapeProfileDef,5>::aux_is_derived[4]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->FilletRadius, arg, db ); break; } 
+        try { GenericConvert( in->FilletRadius, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcIShapeProfileDef to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
 	return base;
@@ -2933,13 +2933,13 @@ template <> size_t GenericFill<IfcPropertyListValue>(const DB& db, const LIST& p
 	size_t base = GenericFill(db,params,static_cast<IfcSimpleProperty*>(in));
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPropertyListValue"); }    do { // convert the 'ListValues' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->ListValues, arg, db ); break; } 
+        try { GenericConvert( in->ListValues, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcPropertyListValue to be a `LIST [1:?] OF IfcValue`")); }
     } while(0);
     do { // convert the 'Unit' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Unit, arg, db ); break; } 
+        try { GenericConvert( in->Unit, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcPropertyListValue to be a `IfcUnit`")); }
     } while(0);
 	return base;
@@ -2965,13 +2965,13 @@ template <> size_t GenericFill<IfcDoor>(const DB& db, const LIST& params, IfcDoo
 	if (params.GetSize() < 10) { throw STEP::TypeError("expected 10 arguments to IfcDoor"); }    do { // convert the 'OverallHeight' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->OverallHeight, arg, db ); break; } 
+        try { GenericConvert( in->OverallHeight, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcDoor to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'OverallWidth' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->OverallWidth, arg, db ); break; } 
+        try { GenericConvert( in->OverallWidth, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcDoor to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
 	return base;
@@ -2984,20 +2984,20 @@ template <> size_t GenericFill<IfcStyledItem>(const DB& db, const LIST& params,
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcStyledItem,3>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Item, arg, db ); break; } 
+        try { GenericConvert( in->Item, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcStyledItem to be a `IfcRepresentationItem`")); }
     } while(0);
     do { // convert the 'Styles' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcStyledItem,3>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->Styles, arg, db ); break; } 
+        try { GenericConvert( in->Styles, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcStyledItem to be a `SET [1:?] OF IfcPresentationStyleAssignment`")); }
     } while(0);
     do { // convert the 'Name' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcStyledItem,3>::aux_is_derived[2]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Name, arg, db ); break; } 
+        try { GenericConvert( in->Name, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcStyledItem to be a `IfcLabel`")); }
     } while(0);
 	return base;
@@ -3023,7 +3023,7 @@ template <> size_t GenericFill<IfcArbitraryClosedProfileDef>(const DB& db, const
 	if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcArbitraryClosedProfileDef"); }    do { // convert the 'OuterCurve' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcArbitraryClosedProfileDef,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->OuterCurve, arg, db ); break; } 
+        try { GenericConvert( in->OuterCurve, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcArbitraryClosedProfileDef to be a `IfcCurve`")); }
     } while(0);
 	return base;
@@ -3041,12 +3041,12 @@ template <> size_t GenericFill<IfcLine>(const DB& db, const LIST& params, IfcLin
 	size_t base = GenericFill(db,params,static_cast<IfcCurve*>(in));
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcLine"); }    do { // convert the 'Pnt' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Pnt, arg, db ); break; } 
+        try { GenericConvert( in->Pnt, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcLine to be a `IfcCartesianPoint`")); }
     } while(0);
     do { // convert the 'Dir' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Dir, arg, db ); break; } 
+        try { GenericConvert( in->Dir, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcLine to be a `IfcVector`")); }
     } while(0);
 	return base;
@@ -3072,13 +3072,13 @@ template <> size_t GenericFill<IfcPropertySingleValue>(const DB& db, const LIST&
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcPropertySingleValue"); }    do { // convert the 'NominalValue' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->NominalValue, arg, db ); break; } 
+        try { GenericConvert( in->NominalValue, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcPropertySingleValue to be a `IfcValue`")); }
     } while(0);
     do { // convert the 'Unit' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Unit, arg, db ); break; } 
+        try { GenericConvert( in->Unit, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcPropertySingleValue to be a `IfcUnit`")); }
     } while(0);
 	return base;
@@ -3111,7 +3111,7 @@ template <> size_t GenericFill<IfcSurfaceStyleShading>(const DB& db, const LIST&
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcSurfaceStyleShading"); }    do { // convert the 'SurfaceColour' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcSurfaceStyleShading,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->SurfaceColour, arg, db ); break; } 
+        try { GenericConvert( in->SurfaceColour, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSurfaceStyleShading to be a `IfcColourRgb`")); }
     } while(0);
 	return base;

+ 81 - 81
code/AssetLib/IFC/IFCReaderGen2_2x3.cpp

@@ -5,8 +5,8 @@ Open Asset Import Library (ASSIMP)
 Copyright (c) 2006-2020, ASSIMP Development Team
 All rights reserved.
 
-Redistribution and use of this software in source and binary forms, 
-with or without modification, are permitted provided that the 
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
 following conditions are met:
 
 * Redistributions of source code must retain the above
@@ -23,16 +23,16 @@ following conditions are met:
   derived from this software without specific prior
   written permission of the ASSIMP Development Team.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 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.
 
 ----------------------------------------------------------------------
@@ -59,12 +59,12 @@ template <> size_t GenericFill<IfcSurfaceStyle>(const DB& db, const LIST& params
 	size_t base = GenericFill(db,params,static_cast<IfcPresentationStyle*>(in));
 	if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcSurfaceStyle"); }    do { // convert the 'Side' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Side, arg, db ); break; } 
+        try { GenericConvert( in->Side, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSurfaceStyle to be a `IfcSurfaceSide`")); }
     } while(0);
     do { // convert the 'Styles' argument
         std::shared_ptr<const DataType> arg = params[ base++ ];
-        try { GenericConvert( in->Styles, arg, db ); break; } 
+        try { GenericConvert( in->Styles, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSurfaceStyle to be a `SET [1:5] OF IfcSurfaceStyleElementSelect`")); }
     } while(0);
 	return base;
@@ -118,7 +118,7 @@ template <> size_t GenericFill<IfcFace>(const DB& db, const LIST& params, IfcFac
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcFace"); }    do { // convert the 'Bounds' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcFace,1>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Bounds, arg, db ); break; } 
+        try { GenericConvert( in->Bounds, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcFace to be a `SET [1:?] OF IfcFaceBound`")); }
     } while(0);
 	return base;
@@ -173,7 +173,7 @@ template <> size_t GenericFill<IfcColourSpecification>(const DB& db, const LIST&
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcColourSpecification,1>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Name, arg, db ); break; } 
+        try { GenericConvert( in->Name, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcColourSpecification to be a `IfcLabel`")); }
     } while(0);
 	return base;
@@ -184,12 +184,12 @@ template <> size_t GenericFill<IfcVector>(const DB& db, const LIST& params, IfcV
 	size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcVector"); }    do { // convert the 'Orientation' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Orientation, arg, db ); break; } 
+        try { GenericConvert( in->Orientation, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcVector to be a `IfcDirection`")); }
     } while(0);
     do { // convert the 'Magnitude' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Magnitude, arg, db ); break; } 
+        try { GenericConvert( in->Magnitude, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcVector to be a `IfcLengthMeasure`")); }
     } while(0);
 	return base;
@@ -207,17 +207,17 @@ template <> size_t GenericFill<IfcColourRgb>(const DB& db, const LIST& params, I
 	size_t base = GenericFill(db,params,static_cast<IfcColourSpecification*>(in));
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcColourRgb"); }    do { // convert the 'Red' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Red, arg, db ); break; } 
+        try { GenericConvert( in->Red, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcColourRgb to be a `IfcNormalisedRatioMeasure`")); }
     } while(0);
     do { // convert the 'Green' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Green, arg, db ); break; } 
+        try { GenericConvert( in->Green, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcColourRgb to be a `IfcNormalisedRatioMeasure`")); }
     } while(0);
     do { // convert the 'Blue' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Blue, arg, db ); break; } 
+        try { GenericConvert( in->Blue, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcColourRgb to be a `IfcNormalisedRatioMeasure`")); }
     } while(0);
 	return base;
@@ -243,31 +243,31 @@ template <> size_t GenericFill<IfcSite>(const DB& db, const LIST& params, IfcSit
 	if (params.GetSize() < 14) { throw STEP::TypeError("expected 14 arguments to IfcSite"); }    do { // convert the 'RefLatitude' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->RefLatitude, arg, db ); break; } 
+        try { GenericConvert( in->RefLatitude, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcSite to be a `IfcCompoundPlaneAngleMeasure`")); }
     } while(0);
     do { // convert the 'RefLongitude' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->RefLongitude, arg, db ); break; } 
+        try { GenericConvert( in->RefLongitude, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 10 to IfcSite to be a `IfcCompoundPlaneAngleMeasure`")); }
     } while(0);
     do { // convert the 'RefElevation' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->RefElevation, arg, db ); break; } 
+        try { GenericConvert( in->RefElevation, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 11 to IfcSite to be a `IfcLengthMeasure`")); }
     } while(0);
     do { // convert the 'LandTitleNumber' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->LandTitleNumber, arg, db ); break; } 
+        try { GenericConvert( in->LandTitleNumber, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 12 to IfcSite to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'SiteAddress' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->SiteAddress, arg, db ); break; } 
+        try { GenericConvert( in->SiteAddress, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 13 to IfcSite to be a `IfcPostalAddress`")); }
     } while(0);
 	return base;
@@ -412,31 +412,31 @@ template <> size_t GenericFill<IfcBSplineCurve>(const DB& db, const LIST& params
 	if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcBSplineCurve"); }    do { // convert the 'Degree' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcBSplineCurve,5>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Degree, arg, db ); break; } 
+        try { GenericConvert( in->Degree, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcBSplineCurve to be a `INTEGER`")); }
     } while(0);
     do { // convert the 'ControlPointsList' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcBSplineCurve,5>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->ControlPointsList, arg, db ); break; } 
+        try { GenericConvert( in->ControlPointsList, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcBSplineCurve to be a `LIST [2:?] OF IfcCartesianPoint`")); }
     } while(0);
     do { // convert the 'CurveForm' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcBSplineCurve,5>::aux_is_derived[2]=true; break; }
-        try { GenericConvert( in->CurveForm, arg, db ); break; } 
+        try { GenericConvert( in->CurveForm, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcBSplineCurve to be a `IfcBSplineCurveForm`")); }
     } while(0);
     do { // convert the 'ClosedCurve' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcBSplineCurve,5>::aux_is_derived[3]=true; break; }
-        try { GenericConvert( in->ClosedCurve, arg, db ); break; } 
+        try { GenericConvert( in->ClosedCurve, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcBSplineCurve to be a `LOGICAL`")); }
     } while(0);
     do { // convert the 'SelfIntersect' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcBSplineCurve,5>::aux_is_derived[4]=true; break; }
-        try { GenericConvert( in->SelfIntersect, arg, db ); break; } 
+        try { GenericConvert( in->SelfIntersect, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcBSplineCurve to be a `LOGICAL`")); }
     } while(0);
 	return base;
@@ -474,7 +474,7 @@ template <> size_t GenericFill<IfcShellBasedSurfaceModel>(const DB& db, const LI
 	size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcShellBasedSurfaceModel"); }    do { // convert the 'SbsmBoundary' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->SbsmBoundary, arg, db ); break; } 
+        try { GenericConvert( in->SbsmBoundary, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcShellBasedSurfaceModel to be a `SET [1:?] OF IfcShell`")); }
     } while(0);
 	return base;
@@ -492,12 +492,12 @@ template <> size_t GenericFill<IfcExtrudedAreaSolid>(const DB& db, const LIST& p
 	size_t base = GenericFill(db,params,static_cast<IfcSweptAreaSolid*>(in));
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcExtrudedAreaSolid"); }    do { // convert the 'ExtrudedDirection' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->ExtrudedDirection, arg, db ); break; } 
+        try { GenericConvert( in->ExtrudedDirection, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcExtrudedAreaSolid to be a `IfcDirection`")); }
     } while(0);
     do { // convert the 'Depth' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Depth, arg, db ); break; } 
+        try { GenericConvert( in->Depth, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcExtrudedAreaSolid to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
 	return base;
@@ -522,12 +522,12 @@ template <> size_t GenericFill<IfcRelVoidsElement>(const DB& db, const LIST& par
 	size_t base = GenericFill(db,params,static_cast<IfcRelConnects*>(in));
 	if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcRelVoidsElement"); }    do { // convert the 'RelatingBuildingElement' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->RelatingBuildingElement, arg, db ); break; } 
+        try { GenericConvert( in->RelatingBuildingElement, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcRelVoidsElement to be a `IfcElement`")); }
     } while(0);
     do { // convert the 'RelatedOpeningElement' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->RelatedOpeningElement, arg, db ); break; } 
+        try { GenericConvert( in->RelatedOpeningElement, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcRelVoidsElement to be a `IfcFeatureElementSubtraction`")); }
     } while(0);
 	return base;
@@ -546,13 +546,13 @@ template <> size_t GenericFill<IfcCartesianTransformationOperator3DnonUniform>(c
 	if (params.GetSize() < 7) { throw STEP::TypeError("expected 7 arguments to IfcCartesianTransformationOperator3DnonUniform"); }    do { // convert the 'Scale2' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Scale2, arg, db ); break; } 
+        try { GenericConvert( in->Scale2, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcCartesianTransformationOperator3DnonUniform to be a `REAL`")); }
     } while(0);
     do { // convert the 'Scale3' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Scale3, arg, db ); break; } 
+        try { GenericConvert( in->Scale3, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcCartesianTransformationOperator3DnonUniform to be a `REAL`")); }
     } while(0);
 	return base;
@@ -634,7 +634,7 @@ template <> size_t GenericFill<IfcAxis2Placement2D>(const DB& db, const LIST& pa
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcAxis2Placement2D"); }    do { // convert the 'RefDirection' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->RefDirection, arg, db ); break; } 
+        try { GenericConvert( in->RefDirection, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis2Placement2D to be a `IfcDirection`")); }
     } while(0);
 	return base;
@@ -658,7 +658,7 @@ template <> size_t GenericFill<IfcCartesianPoint>(const DB& db, const LIST& para
 	size_t base = GenericFill(db,params,static_cast<IfcPoint*>(in));
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcCartesianPoint"); }    do { // convert the 'Coordinates' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Coordinates, arg, db ); break; } 
+        try { GenericConvert( in->Coordinates, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcCartesianPoint to be a `LIST [1:3] OF IfcLengthMeasure`")); }
     } while(0);
 	return base;
@@ -682,7 +682,7 @@ template <> size_t GenericFill<IfcPolyLoop>(const DB& db, const LIST& params, If
 	size_t base = GenericFill(db,params,static_cast<IfcLoop*>(in));
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPolyLoop"); }    do { // convert the 'Polygon' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Polygon, arg, db ); break; } 
+        try { GenericConvert( in->Polygon, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPolyLoop to be a `LIST [3:?] OF IfcCartesianPoint`")); }
     } while(0);
 	return base;
@@ -716,14 +716,14 @@ template <> size_t GenericFill<IfcRepresentationContext>(const DB& db, const LIS
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRepresentationContext,2>::aux_is_derived[0]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->ContextIdentifier, arg, db ); break; } 
+        try { GenericConvert( in->ContextIdentifier, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRepresentationContext to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'ContextType' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcRepresentationContext,2>::aux_is_derived[1]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->ContextType, arg, db ); break; } 
+        try { GenericConvert( in->ContextType, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRepresentationContext to be a `IfcLabel`")); }
     } while(0);
 	return base;
@@ -735,27 +735,27 @@ template <> size_t GenericFill<IfcGeometricRepresentationContext>(const DB& db,
 	if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcGeometricRepresentationContext"); }    do { // convert the 'CoordinateSpaceDimension' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcGeometricRepresentationContext,4>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->CoordinateSpaceDimension, arg, db ); break; } 
+        try { GenericConvert( in->CoordinateSpaceDimension, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcGeometricRepresentationContext to be a `IfcDimensionCount`")); }
     } while(0);
     do { // convert the 'Precision' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcGeometricRepresentationContext,4>::aux_is_derived[1]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Precision, arg, db ); break; } 
+        try { GenericConvert( in->Precision, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcGeometricRepresentationContext to be a `REAL`")); }
     } while(0);
     do { // convert the 'WorldCoordinateSystem' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcGeometricRepresentationContext,4>::aux_is_derived[2]=true; break; }
-        try { GenericConvert( in->WorldCoordinateSystem, arg, db ); break; } 
+        try { GenericConvert( in->WorldCoordinateSystem, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcGeometricRepresentationContext to be a `IfcAxis2Placement`")); }
     } while(0);
     do { // convert the 'TrueNorth' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcGeometricRepresentationContext,4>::aux_is_derived[3]=true; break; }
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->TrueNorth, arg, db ); break; } 
+        try { GenericConvert( in->TrueNorth, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcGeometricRepresentationContext to be a `IfcDirection`")); }
     } while(0);
 	return base;
@@ -774,12 +774,12 @@ template <> size_t GenericFill<IfcSIUnit>(const DB& db, const LIST& params, IfcS
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcSIUnit"); }    do { // convert the 'Prefix' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Prefix, arg, db ); break; } 
+        try { GenericConvert( in->Prefix, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSIUnit to be a `IfcSIPrefix`")); }
     } while(0);
     do { // convert the 'Name' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Name, arg, db ); break; } 
+        try { GenericConvert( in->Name, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcSIUnit to be a `IfcSIUnitName`")); }
     } while(0);
 	return base;
@@ -805,7 +805,7 @@ template <> size_t GenericFill<IfcAxis1Placement>(const DB& db, const LIST& para
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcAxis1Placement"); }    do { // convert the 'Axis' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Axis, arg, db ); break; } 
+        try { GenericConvert( in->Axis, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcAxis1Placement to be a `IfcDirection`")); }
     } while(0);
 	return base;
@@ -858,12 +858,12 @@ template <> size_t GenericFill<IfcRepresentationMap>(const DB& db, const LIST& p
 	size_t base = 0;
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcRepresentationMap"); }    do { // convert the 'MappingOrigin' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->MappingOrigin, arg, db ); break; } 
+        try { GenericConvert( in->MappingOrigin, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcRepresentationMap to be a `IfcAxis2Placement`")); }
     } while(0);
     do { // convert the 'MappedRepresentation' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->MappedRepresentation, arg, db ); break; } 
+        try { GenericConvert( in->MappedRepresentation, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcRepresentationMap to be a `IfcRepresentation`")); }
     } while(0);
 	return base;
@@ -1012,12 +1012,12 @@ template <> size_t GenericFill<IfcMeasureWithUnit>(const DB& db, const LIST& par
 	size_t base = 0;
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcMeasureWithUnit"); }    do { // convert the 'ValueComponent' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->ValueComponent, arg, db ); break; } 
+        try { GenericConvert( in->ValueComponent, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcMeasureWithUnit to be a `IfcValue`")); }
     } while(0);
     do { // convert the 'UnitComponent' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->UnitComponent, arg, db ); break; } 
+        try { GenericConvert( in->UnitComponent, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcMeasureWithUnit to be a `IfcUnit`")); }
     } while(0);
 	return base;
@@ -1125,7 +1125,7 @@ template <> size_t GenericFill<IfcFaceBasedSurfaceModel>(const DB& db, const LIS
 	size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcFaceBasedSurfaceModel"); }    do { // convert the 'FbsmFaces' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->FbsmFaces, arg, db ); break; } 
+        try { GenericConvert( in->FbsmFaces, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcFaceBasedSurfaceModel to be a `SET [1:?] OF IfcConnectedFaceSet`")); }
     } while(0);
 	return base;
@@ -1172,13 +1172,13 @@ template <> size_t GenericFill<IfcFaceBound>(const DB& db, const LIST& params, I
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcFaceBound"); }    do { // convert the 'Bound' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcFaceBound,2>::aux_is_derived[0]=true; break; }
-        try { GenericConvert( in->Bound, arg, db ); break; } 
+        try { GenericConvert( in->Bound, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcFaceBound to be a `IfcLoop`")); }
     } while(0);
     do { // convert the 'Orientation' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const ISDERIVED*>(&*arg)) { in->ObjectHelper<Assimp::IFC::Schema_2x3::IfcFaceBound,2>::aux_is_derived[1]=true; break; }
-        try { GenericConvert( in->Orientation, arg, db ); break; } 
+        try { GenericConvert( in->Orientation, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcFaceBound to be a `BOOLEAN`")); }
     } while(0);
 	return base;
@@ -1216,12 +1216,12 @@ template <> size_t GenericFill<IfcComplexProperty>(const DB& db, const LIST& par
 	size_t base = GenericFill(db,params,static_cast<IfcProperty*>(in));
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcComplexProperty"); }    do { // convert the 'UsageName' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->UsageName, arg, db ); break; } 
+        try { GenericConvert( in->UsageName, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcComplexProperty to be a `IfcIdentifier`")); }
     } while(0);
     do { // convert the 'HasProperties' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->HasProperties, arg, db ); break; } 
+        try { GenericConvert( in->HasProperties, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcComplexProperty to be a `SET [1:?] OF IfcProperty`")); }
     } while(0);
 	return base;
@@ -1274,7 +1274,7 @@ template <> size_t GenericFill<IfcUnitAssignment>(const DB& db, const LIST& para
 	size_t base = 0;
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcUnitAssignment"); }    do { // convert the 'Units' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Units, arg, db ); break; } 
+        try { GenericConvert( in->Units, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcUnitAssignment to be a `SET [1:?] OF IfcUnit`")); }
     } while(0);
 	return base;
@@ -1307,12 +1307,12 @@ template <> size_t GenericFill<IfcElementQuantity>(const DB& db, const LIST& par
 	if (params.GetSize() < 6) { throw STEP::TypeError("expected 6 arguments to IfcElementQuantity"); }    do { // convert the 'MethodOfMeasurement' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->MethodOfMeasurement, arg, db ); break; } 
+        try { GenericConvert( in->MethodOfMeasurement, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcElementQuantity to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'Quantities' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Quantities, arg, db ); break; } 
+        try { GenericConvert( in->Quantities, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcElementQuantity to be a `SET [1:?] OF IfcPhysicalQuantity`")); }
     } while(0);
 	return base;
@@ -1379,7 +1379,7 @@ template <> size_t GenericFill<IfcPresentationStyleAssignment>(const DB& db, con
 	size_t base = 0;
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcPresentationStyleAssignment"); }    do { // convert the 'Styles' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Styles, arg, db ); break; } 
+        try { GenericConvert( in->Styles, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcPresentationStyleAssignment to be a `SET [1:?] OF IfcPresentationStyleSelect`")); }
     } while(0);
 	return base;
@@ -1418,13 +1418,13 @@ template <> size_t GenericFill<IfcSpace>(const DB& db, const LIST& params, IfcSp
 	size_t base = GenericFill(db,params,static_cast<IfcSpatialStructureElement*>(in));
 	if (params.GetSize() < 11) { throw STEP::TypeError("expected 11 arguments to IfcSpace"); }    do { // convert the 'InteriorOrExteriorSpace' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->InteriorOrExteriorSpace, arg, db ); break; } 
+        try { GenericConvert( in->InteriorOrExteriorSpace, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 9 to IfcSpace to be a `IfcInternalOrExternalEnum`")); }
     } while(0);
     do { // convert the 'ElevationWithFlooring' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->ElevationWithFlooring, arg, db ); break; } 
+        try { GenericConvert( in->ElevationWithFlooring, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 10 to IfcSpace to be a `IfcLengthMeasure`")); }
     } while(0);
 	return base;
@@ -1484,7 +1484,7 @@ template <> size_t GenericFill<IfcSurfaceStyleWithTextures>(const DB& db, const
 	size_t base = 0;
 	if (params.GetSize() < 1) { throw STEP::TypeError("expected 1 arguments to IfcSurfaceStyleWithTextures"); }    do { // convert the 'Textures' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Textures, arg, db ); break; } 
+        try { GenericConvert( in->Textures, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcSurfaceStyleWithTextures to be a `LIST [1:?] OF IfcSurfaceTexture`")); }
     } while(0);
 	return base;
@@ -1495,22 +1495,22 @@ template <> size_t GenericFill<IfcBoundingBox>(const DB& db, const LIST& params,
 	size_t base = GenericFill(db,params,static_cast<IfcGeometricRepresentationItem*>(in));
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcBoundingBox"); }    do { // convert the 'Corner' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Corner, arg, db ); break; } 
+        try { GenericConvert( in->Corner, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 0 to IfcBoundingBox to be a `IfcCartesianPoint`")); }
     } while(0);
     do { // convert the 'XDim' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->XDim, arg, db ); break; } 
+        try { GenericConvert( in->XDim, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcBoundingBox to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'YDim' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->YDim, arg, db ); break; } 
+        try { GenericConvert( in->YDim, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcBoundingBox to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'ZDim' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->ZDim, arg, db ); break; } 
+        try { GenericConvert( in->ZDim, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcBoundingBox to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
 	return base;
@@ -1535,7 +1535,7 @@ template <> size_t GenericFill<IfcCircle>(const DB& db, const LIST& params, IfcC
 	size_t base = GenericFill(db,params,static_cast<IfcConic*>(in));
 	if (params.GetSize() < 2) { throw STEP::TypeError("expected 2 arguments to IfcCircle"); }    do { // convert the 'Radius' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Radius, arg, db ); break; } 
+        try { GenericConvert( in->Radius, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcCircle to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
 	return base;
@@ -1623,12 +1623,12 @@ template <> size_t GenericFill<IfcConversionBasedUnit>(const DB& db, const LIST&
 	size_t base = GenericFill(db,params,static_cast<IfcNamedUnit*>(in));
 	if (params.GetSize() < 4) { throw STEP::TypeError("expected 4 arguments to IfcConversionBasedUnit"); }    do { // convert the 'Name' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->Name, arg, db ); break; } 
+        try { GenericConvert( in->Name, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcConversionBasedUnit to be a `IfcLabel`")); }
     } while(0);
     do { // convert the 'ConversionFactor' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->ConversionFactor, arg, db ); break; } 
+        try { GenericConvert( in->ConversionFactor, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcConversionBasedUnit to be a `IfcMeasureWithUnit`")); }
     } while(0);
 	return base;
@@ -1744,12 +1744,12 @@ template <> size_t GenericFill<IfcEllipse>(const DB& db, const LIST& params, Ifc
 	size_t base = GenericFill(db,params,static_cast<IfcConic*>(in));
 	if (params.GetSize() < 3) { throw STEP::TypeError("expected 3 arguments to IfcEllipse"); }    do { // convert the 'SemiAxis1' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->SemiAxis1, arg, db ); break; } 
+        try { GenericConvert( in->SemiAxis1, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcEllipse to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
     do { // convert the 'SemiAxis2' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->SemiAxis2, arg, db ); break; } 
+        try { GenericConvert( in->SemiAxis2, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcEllipse to be a `IfcPositiveLengthMeasure`")); }
     } while(0);
 	return base;
@@ -1816,7 +1816,7 @@ template <> size_t GenericFill<IfcPropertySet>(const DB& db, const LIST& params,
 	size_t base = GenericFill(db,params,static_cast<IfcPropertySetDefinition*>(in));
 	if (params.GetSize() < 5) { throw STEP::TypeError("expected 5 arguments to IfcPropertySet"); }    do { // convert the 'HasProperties' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->HasProperties, arg, db ); break; } 
+        try { GenericConvert( in->HasProperties, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcPropertySet to be a `SET [1:?] OF IfcProperty`")); }
     } while(0);
 	return base;
@@ -1828,48 +1828,48 @@ template <> size_t GenericFill<IfcSurfaceStyleRendering>(const DB& db, const LIS
 	if (params.GetSize() < 9) { throw STEP::TypeError("expected 9 arguments to IfcSurfaceStyleRendering"); }    do { // convert the 'Transparency' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->Transparency, arg, db ); break; } 
+        try { GenericConvert( in->Transparency, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 1 to IfcSurfaceStyleRendering to be a `IfcNormalisedRatioMeasure`")); }
     } while(0);
     do { // convert the 'DiffuseColour' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->DiffuseColour, arg, db ); break; } 
+        try { GenericConvert( in->DiffuseColour, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 2 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
     } while(0);
     do { // convert the 'TransmissionColour' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->TransmissionColour, arg, db ); break; } 
+        try { GenericConvert( in->TransmissionColour, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 3 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
     } while(0);
     do { // convert the 'DiffuseTransmissionColour' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->DiffuseTransmissionColour, arg, db ); break; } 
+        try { GenericConvert( in->DiffuseTransmissionColour, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 4 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
     } while(0);
     do { // convert the 'ReflectionColour' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->ReflectionColour, arg, db ); break; } 
+        try { GenericConvert( in->ReflectionColour, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 5 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
     } while(0);
     do { // convert the 'SpecularColour' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->SpecularColour, arg, db ); break; } 
+        try { GenericConvert( in->SpecularColour, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 6 to IfcSurfaceStyleRendering to be a `IfcColourOrFactor`")); }
     } while(0);
     do { // convert the 'SpecularHighlight' argument
         std::shared_ptr<const DataType> arg = params[base++];
         if (dynamic_cast<const UNSET*>(&*arg)) break;
-        try { GenericConvert( in->SpecularHighlight, arg, db ); break; } 
+        try { GenericConvert( in->SpecularHighlight, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 7 to IfcSurfaceStyleRendering to be a `IfcSpecularHighlightSelect`")); }
     } while(0);
     do { // convert the 'ReflectanceMethod' argument
         std::shared_ptr<const DataType> arg = params[base++];
-        try { GenericConvert( in->ReflectanceMethod, arg, db ); break; } 
+        try { GenericConvert( in->ReflectanceMethod, arg, db ); break; }
         catch (const TypeError& t) { throw TypeError(t.what() + std::string(" - expected argument 8 to IfcSurfaceStyleRendering to be a `IfcReflectanceMethodEnum`")); }
     } while(0);
 	return base;

La diferencia del archivo ha sido suprimido porque es demasiado grande
+ 129 - 129
code/AssetLib/IFC/IFCReaderGen_4.cpp


+ 13 - 13
code/AssetLib/IFC/IFCReaderGen_4.h

@@ -5,8 +5,8 @@ Open Asset Import Library (ASSIMP)
 Copyright (c) 2006-2020, ASSIMP Development Team
 All rights reserved.
 
-Redistribution and use of this software in source and binary forms, 
-with or without modification, are permitted provided that the 
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
 following conditions are met:
 
 * Redistributions of source code must retain the above
@@ -23,16 +23,16 @@ following conditions are met:
   derived from this software without specific prior
   written permission of the ASSIMP Development Team.
 
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 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.
 
 ----------------------------------------------------------------------
@@ -51,12 +51,12 @@ namespace Schema_4 {
 
 	using namespace STEP;
 	using namespace STEP::EXPRESS;
-	
-	
+
+
 	struct NotImplemented : public ObjectHelper<NotImplemented,0> {
-		
+
 	};
-	
+
 
 	// ******************************************************************************
 	// IFC Custom data types

+ 0 - 1
code/AssetLib/IFC/IFCUtil.cpp

@@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AssetLib/IFC/IFCUtil.h"
 #include "Common/PolyTools.h"
 #include "PostProcessing/ProcessHelper.h"
-#include <assimp/Defines.h>
 
 namespace Assimp {
 namespace IFC {

+ 6 - 8
code/AssetLib/IFC/IFCUtil.h

@@ -54,6 +54,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/mesh.h>
 #include <assimp/material.h>
 
+#include <utility>
+
 struct aiNode;
 
 namespace Assimp {
@@ -137,14 +139,10 @@ struct TempOpening
     }
 
     // ------------------------------------------------------------------------------
-    TempOpening(const IFC::Schema_2x3::IfcSolidModel* solid,IfcVector3 extrusionDir,
-        std::shared_ptr<TempMesh> profileMesh,
-        std::shared_ptr<TempMesh> profileMesh2D)
-        : solid(solid)
-        , extrusionDir(extrusionDir)
-        , profileMesh(profileMesh)
-        , profileMesh2D(profileMesh2D)
-    {
+    TempOpening(const IFC::Schema_2x3::IfcSolidModel *solid, IfcVector3 extrusionDir,
+            std::shared_ptr<TempMesh> profileMesh,
+            std::shared_ptr<TempMesh> profileMesh2D) :
+            solid(solid), extrusionDir(extrusionDir), profileMesh(std::move(profileMesh)), profileMesh2D(std::move(profileMesh2D)) {
     }
 
     // ------------------------------------------------------------------------------

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

@@ -106,7 +106,7 @@ bool IRRImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
 		if (nullptr == pIOHandler) {
 			return true;
 		}
-		const char *tokens[] = { "irr_scene" };
+		static const char * const tokens[] = { "irr_scene" };
 		return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
 	}
 
@@ -132,7 +132,7 @@ void IRRImporter::SetupProperties(const Importer *pImp) {
 }
 
 // ------------------------------------------------------------------------------------------------
-// Build a mesh tha consists of a single squad (a side of a skybox)
+// Build a mesh that consists of a single squad (a side of a skybox)
 aiMesh *IRRImporter::BuildSingleQuadMesh(const SkyboxVertex &v1,
 		const SkyboxVertex &v2,
 		const SkyboxVertex &v3,

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