浏览代码

Merge branch 'master' into master

Kim Kulling 2 年之前
父节点
当前提交
03163a1dda
共有 100 个文件被更改,包括 714 次插入657 次删除
  1. 0 2
      .coveralls.yml
  2. 1 1
      .github/workflows/ccpp.yml
  3. 10 0
      .github/workflows/sanitizer.yml
  4. 28 22
      CMakeLists.txt
  5. 128 0
      CODE_OF_CONDUCT.md
  6. 18 20
      Readme.md
  7. 5 120
      code/AssetLib/3DS/3DSHelper.h
  8. 7 0
      code/AssetLib/3DS/3DSLoader.cpp
  9. 1 1
      code/AssetLib/3DS/3DSLoader.h
  10. 5 7
      code/AssetLib/3MF/3MFTypes.h
  11. 1 1
      code/AssetLib/3MF/D3MFExporter.cpp
  12. 1 1
      code/AssetLib/3MF/D3MFOpcPackage.cpp
  13. 2 2
      code/AssetLib/3MF/XmlSerializer.cpp
  14. 6 4
      code/AssetLib/AC/ACLoader.cpp
  15. 2 2
      code/AssetLib/AC/ACLoader.h
  16. 1 5
      code/AssetLib/AMF/AMFImporter.cpp
  17. 5 5
      code/AssetLib/AMF/AMFImporter.hpp
  18. 4 6
      code/AssetLib/AMF/AMFImporter_Node.hpp
  19. 1 0
      code/AssetLib/AMF/AMFImporter_Postprocess.cpp
  20. 0 16
      code/AssetLib/ASE/ASELoader.cpp
  21. 0 16
      code/AssetLib/ASE/ASEParser.cpp
  22. 1 1
      code/AssetLib/Assbin/AssbinExporter.h
  23. 3 3
      code/AssetLib/Assbin/AssbinFileWriter.cpp
  24. 1 1
      code/AssetLib/Assjson/cencode.c
  25. 5 5
      code/AssetLib/Assjson/json_exporter.cpp
  26. 1 2
      code/AssetLib/B3D/B3DImporter.cpp
  27. 1 2
      code/AssetLib/Blender/BlenderBMesh.cpp
  28. 2 1
      code/AssetLib/Blender/BlenderCustomData.cpp
  29. 1 3
      code/AssetLib/Blender/BlenderDNA.h
  30. 1 2
      code/AssetLib/Blender/BlenderLoader.cpp
  31. 1 3
      code/AssetLib/Blender/BlenderModifier.h
  32. 1 1
      code/AssetLib/Blender/BlenderScene.cpp
  33. 7 18
      code/AssetLib/Blender/BlenderScene.h
  34. 3 7
      code/AssetLib/Blender/BlenderTessellator.cpp
  35. 4 10
      code/AssetLib/C4D/C4DImporter.cpp
  36. 2 2
      code/AssetLib/Collada/ColladaExporter.cpp
  37. 1 1
      code/AssetLib/Collada/ColladaExporter.h
  38. 1 1
      code/AssetLib/Collada/ColladaHelper.h
  39. 1 10
      code/AssetLib/Collada/ColladaLoader.cpp
  40. 1 1
      code/AssetLib/Collada/ColladaParser.cpp
  41. 1 3
      code/AssetLib/DXF/DXFHelper.h
  42. 1 1
      code/AssetLib/DXF/DXFLoader.cpp
  43. 5 6
      code/AssetLib/FBX/FBXBinaryTokenizer.cpp
  44. 1 0
      code/AssetLib/FBX/FBXCommon.h
  45. 31 16
      code/AssetLib/FBX/FBXConverter.cpp
  46. 8 4
      code/AssetLib/FBX/FBXDeformer.cpp
  47. 22 12
      code/AssetLib/FBX/FBXDocument.cpp
  48. 11 6
      code/AssetLib/FBX/FBXDocument.h
  49. 1 1
      code/AssetLib/FBX/FBXExportNode.cpp
  50. 0 4
      code/AssetLib/FBX/FBXExportNode.h
  51. 13 15
      code/AssetLib/FBX/FBXImporter.cpp
  52. 0 14
      code/AssetLib/FBX/FBXMaterial.cpp
  53. 5 2
      code/AssetLib/FBX/FBXMeshGeometry.cpp
  54. 51 35
      code/AssetLib/FBX/FBXMeshGeometry.h
  55. 37 14
      code/AssetLib/FBX/FBXParser.cpp
  56. 21 15
      code/AssetLib/FBX/FBXParser.h
  57. 10 10
      code/AssetLib/FBX/FBXTokenizer.cpp
  58. 5 4
      code/AssetLib/FBX/FBXTokenizer.h
  59. 11 0
      code/AssetLib/FBX/FBXUtil.h
  60. 3 3
      code/AssetLib/HMP/HMPLoader.cpp
  61. 1 1
      code/AssetLib/HMP/HMPLoader.h
  62. 1 2
      code/AssetLib/IFC/IFCLoader.cpp
  63. 2 1
      code/AssetLib/IFC/IFCUtil.cpp
  64. 1 5
      code/AssetLib/Irr/IRRMeshLoader.cpp
  65. 1 3
      code/AssetLib/Irr/IRRShared.h
  66. 5 3
      code/AssetLib/LWO/LWOAnimation.cpp
  67. 0 1
      code/AssetLib/LWO/LWOBLoader.cpp
  68. 69 48
      code/AssetLib/LWO/LWOLoader.cpp
  69. 1 1
      code/AssetLib/LWO/LWOMaterial.cpp
  70. 1 1
      code/AssetLib/M3D/M3DImporter.h
  71. 1 3
      code/AssetLib/M3D/M3DWrapper.cpp
  72. 1 3
      code/AssetLib/M3D/M3DWrapper.h
  73. 9 7
      code/AssetLib/MD5/MD5Parser.cpp
  74. 5 4
      code/AssetLib/MD5/MD5Parser.h
  75. 39 5
      code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp
  76. 11 1
      code/AssetLib/MDL/HalfLife/HL1MDLLoader.h
  77. 1 1
      code/AssetLib/MDL/MDLLoader.cpp
  78. 1 1
      code/AssetLib/MDL/MDLLoader.h
  79. 1 1
      code/AssetLib/MDL/MDLMaterialLoader.cpp
  80. 1 1
      code/AssetLib/MMD/MMDImporter.cpp
  81. 2 1
      code/AssetLib/MMD/MMDPmxParser.h
  82. 2 2
      code/AssetLib/MS3D/MS3DLoader.cpp
  83. 1 1
      code/AssetLib/NFF/NFFLoader.h
  84. 4 3
      code/AssetLib/OFF/OFFLoader.cpp
  85. 5 7
      code/AssetLib/Obj/ObjFileImporter.cpp
  86. 5 5
      code/AssetLib/Obj/ObjFileMtlImporter.cpp
  87. 3 3
      code/AssetLib/Obj/ObjFileParser.cpp
  88. 17 13
      code/AssetLib/Obj/ObjTools.h
  89. 4 4
      code/AssetLib/Ogre/OgreImporter.h
  90. 2 3
      code/AssetLib/Ogre/OgreXmlSerializer.cpp
  91. 0 10
      code/AssetLib/OpenGEX/OpenGEXImporter.cpp
  92. 3 3
      code/AssetLib/Ply/PlyParser.cpp
  93. 4 16
      code/AssetLib/Ply/PlyParser.h
  94. 1 13
      code/AssetLib/Q3BSP/Q3BSPFileData.h
  95. 1 1
      code/AssetLib/Q3BSP/Q3BSPFileImporter.cpp
  96. 1 2
      code/AssetLib/Q3D/Q3DLoader.cpp
  97. 1 1
      code/AssetLib/Raw/RawLoader.h
  98. 1 1
      code/AssetLib/SIB/SIBImporter.cpp
  99. 2 3
      code/AssetLib/SMD/SMDLoader.cpp
  100. 2 2
      code/AssetLib/SMD/SMDLoader.h

+ 0 - 2
.coveralls.yml

@@ -1,2 +0,0 @@
-service_name: travis-pro
-repo_token: GZXuNlublKFy7HAewHAZLk5ZwgipTFAOA

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

@@ -99,7 +99,7 @@ jobs:
     - name: Set Windows specific CMake arguments
     - name: Set Windows specific CMake arguments
       if: contains(matrix.name, 'windows')
       if: contains(matrix.name, 'windows')
       id: windows_extra_cmake_args
       id: windows_extra_cmake_args
-      run: echo "::set-output name=args::-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1"
+      run: echo "::set-output name=args::-DASSIMP_BUILD_ASSIMP_TOOLS=1 -DASSIMP_BUILD_ASSIMP_VIEW=1 -DASSIMP_BUILD_ZLIB=1"
     
     
     - name: Set Hunter specific CMake arguments
     - name: Set Hunter specific CMake arguments
       if: contains(matrix.name, 'hunter')
       if: contains(matrix.name, 'hunter')

+ 10 - 0
.github/workflows/sanitizer.yml

@@ -57,3 +57,13 @@ jobs:
     - name: test
     - name: test
       run: cd build/bin && ./unit
       run: cd build/bin && ./unit
       shell: bash
       shell: bash
+
+  job3:
+    name: printf-sanitizer
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v3
+    
+    - name: run scan_printf script
+      run: ./scripts/scan_printf.sh
+      shell: bash

+ 28 - 22
CMakeLists.txt

@@ -1,6 +1,6 @@
 # Open Asset Import Library (assimp)
 # Open Asset Import Library (assimp)
 # ----------------------------------------------------------------------
 # ----------------------------------------------------------------------
-# Copyright (c) 2006-2022, assimp team
+# Copyright (c) 2006-2023, assimp team
 #
 #
 # All rights reserved.
 # All rights reserved.
 #
 #
@@ -84,10 +84,6 @@ OPTION( ASSIMP_NO_EXPORT
   "Disable Assimp's export functionality."
   "Disable Assimp's export functionality."
   OFF
   OFF
 )
 )
-OPTION( ASSIMP_BUILD_ZLIB
-  "Build your own zlib"
-  OFF
-)
 OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
 OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
   "If the supplementary tools for Assimp are built in addition to the library."
   "If the supplementary tools for Assimp are built in addition to the library."
   OFF
   OFF
@@ -134,6 +130,18 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH
    OFF
    OFF
 )
 )
 
 
+IF (WIN32)
+  OPTION( ASSIMP_BUILD_ZLIB
+    "Build your own zlib"
+    ON
+  )
+ELSE()
+  OPTION( ASSIMP_BUILD_ZLIB
+    "Build your own zlib"
+    ON
+  )
+ENDIF()
+
 IF (WIN32)
 IF (WIN32)
   # Use subset of Windows.h
   # Use subset of Windows.h
   ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
   ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
@@ -262,13 +270,13 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW)
   ENDIF()
   ENDIF()
   # hide all not-exported symbols
   # hide all not-exported symbols
   IF(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "mips64" )
   IF(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "mips64" )
-	SET(CMAKE_CXX_FLAGS "-mxgot -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
-	SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
-	SET(LIBSTDC++_LIBRARIES -lstdc++)
+    SET(CMAKE_CXX_FLAGS "-mxgot -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
+    SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
+    SET(LIBSTDC++_LIBRARIES -lstdc++)
   ELSE()
   ELSE()
-	SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
-	SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
-	SET(LIBSTDC++_LIBRARIES -lstdc++)
+    SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
+    SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
+    SET(LIBSTDC++_LIBRARIES -lstdc++)
   ENDIF()
   ENDIF()
 ELSEIF(MSVC)
 ELSEIF(MSVC)
   # enable multi-core compilation with MSVC
   # enable multi-core compilation with MSVC
@@ -277,13 +285,15 @@ ELSEIF(MSVC)
   ELSE() # msvc
   ELSE() # msvc
     ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX)
     ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX)
   ENDIF()
   ENDIF()
+  
   # disable "elements of array '' will be default initialized" warning on MSVC2013
   # disable "elements of array '' will be default initialized" warning on MSVC2013
   IF(MSVC12)
   IF(MSVC12)
     ADD_COMPILE_OPTIONS(/wd4351)	
     ADD_COMPILE_OPTIONS(/wd4351)	
   ENDIF()
   ENDIF()
-  ADD_COMPILE_OPTIONS(/wd4244) #supress warning for double to float conversion if Double precission is activated
+  # supress warning for double to float conversion if Double precission is activated
+  ADD_COMPILE_OPTIONS(/wd4244) 
   SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
   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_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
   SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
   SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DEBUG:FULL /PDBALTPATH:%_PDB% /OPT:REF /OPT:ICF")
 ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
 ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
   IF(NOT ASSIMP_HUNTER_ENABLED)
   IF(NOT ASSIMP_HUNTER_ENABLED)
@@ -388,14 +398,6 @@ IF (NOT TARGET uninstall AND ASSIMP_INSTALL)
   ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
   ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
 ENDIF()
 ENDIF()
 
 
-# cmake configuration files
-if(${BUILD_SHARED_LIBS})
-  set(BUILD_LIB_TYPE SHARED)
-else()
-  set(BUILD_LIB_TYPE STATIC)
-  add_definitions(-DDDL_STATIC_LIBRARY=OFF)
-endif()
-
 IF( UNIX )
 IF( UNIX )
   # Use GNUInstallDirs for Unix predefined directories
   # Use GNUInstallDirs for Unix predefined directories
   INCLUDE(GNUInstallDirs)
   INCLUDE(GNUInstallDirs)
@@ -488,7 +490,11 @@ ELSE()
     FIND_PACKAGE(ZLIB)
     FIND_PACKAGE(ZLIB)
   ENDIF()
   ENDIF()
 
 
-  IF( NOT ZLIB_FOUND )
+  IF ( NOT ZLIB_FOUND AND NOT ASSIMP_BUILD_ZLIB )
+    message( FATAL_ERROR
+      "Build configured with -DASSIMP_BUILD_ZLIB=OFF but unable to find zlib"
+    )
+  ELSEIF( NOT ZLIB_FOUND )
     MESSAGE(STATUS "compiling zlib from sources")
     MESSAGE(STATUS "compiling zlib from sources")
     INCLUDE(CheckIncludeFile)
     INCLUDE(CheckIncludeFile)
     INCLUDE(CheckTypeSize)
     INCLUDE(CheckTypeSize)

+ 128 - 0
CODE_OF_CONDUCT.md

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

+ 18 - 20
Readme.md

@@ -1,6 +1,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ==================================
 ==================================
-A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
+
+Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
+
 ### Current project status ###
 ### Current project status ###
 [![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp) 
 [![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp) 
 ![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
 ![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
@@ -14,7 +16,6 @@ A library to import and export various 3d-model-formats including scene-post-pro
 [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
 [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
 [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
 [![Percentage of issues still open](http://isitmaintained.com/badge/open/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Percentage of issues still open")
 [![Percentage of issues still open](http://isitmaintained.com/badge/open/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Percentage of issues still open")
-[![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
 <br>
 <br>
 
 
 APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
 APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
@@ -23,15 +24,19 @@ Additionally, assimp features various __mesh post processing tools__: normals an
 ### Latest Doc's ###
 ### Latest Doc's ###
 Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/). 
 Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/). 
 
 
-### Get involved ###
-This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
-<br>
-You find a bug in the docs? Use [Doc-Repo](https://github.com/assimp/assimp-docs).
-<br>
-Please check our Wiki as well: https://github.com/assimp/assimp/wiki
+### Prebuild binaries ###
+Please check our [Itchi Projectspace](https://kimkulling.itch.io/the-asset-importer-lib)
 
 
 If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
 If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
 
 
+### Communities ###
+- Ask a question at [The Assimp-Discussion Board](https://github.com/assimp/assimp/discussions)
+- Ask on [Assimp-Community on Reddit](https://www.reddit.com/r/Assimp/)
+- Ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). 
+- Nothing has worked? File a question or an issue-report at [The Assimp-Issue Tracker](https://github.com/assimp/assimp/issues)
+
+And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
+
 #### Supported file formats ####
 #### Supported file formats ####
 You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md)
 You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md)
 
 
@@ -66,25 +71,18 @@ Open Asset Import Library is implemented in C++. The directory structure looks l
 	/port		Ports to other languages and scripts to maintain those.
 	/port		Ports to other languages and scripts to maintain those.
 	/test		Unit- and regression tests, test suite of models
 	/test		Unit- and regression tests, test suite of models
 	/tools		Tools (old assimp viewer, command line `assimp`)
 	/tools		Tools (old assimp viewer, command line `assimp`)
-	/samples	A small number of samples to illustrate possible
-                        use cases for Assimp
+	/samples	A small number of samples to illustrate possible use-cases for Assimp
 
 
 The source code is organized in the following way:
 The source code is organized in the following way:
 
 
 	code/Common			The base implementation for importers and the infrastructure
 	code/Common			The base implementation for importers and the infrastructure
+	code/CApi                       Special implementations which are only used for the C-API
+	code/Geometry                   A collection of geometry tools
+	code/Material                   The material system
+	code/PBR                        An exporter for physical based models
 	code/PostProcessing		The post-processing steps
 	code/PostProcessing		The post-processing steps
 	code/AssetLib/<FormatName>	Implementation for import and export for the format
 	code/AssetLib/<FormatName>	Implementation for import and export for the format
 
 
-### Where to get help ###
-For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
-(CHMs for Windows are included in some release packages and should be located right here in the root folder).
-
-If the docs don't solve your problem, ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
-
-Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
-
-And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
-
 ### Contributing ###
 ### Contributing ###
 Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
 Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
 a pull request with your changes against the main repository's `master` branch.
 a pull request with your changes against the main repository's `master` branch.

+ 5 - 120
code/AssetLib/3DS/3DSHelper.h

@@ -322,7 +322,6 @@ struct Texture {
     //! Default constructor
     //! Default constructor
     Texture() AI_NO_EXCEPT
     Texture() AI_NO_EXCEPT
             : mTextureBlend(0.0f),
             : mTextureBlend(0.0f),
-              mMapName(),
               mOffsetU(0.0),
               mOffsetU(0.0),
               mOffsetV(0.0),
               mOffsetV(0.0),
               mScaleU(1.0),
               mScaleU(1.0),
@@ -334,51 +333,11 @@ struct Texture {
         mTextureBlend = get_qnan();
         mTextureBlend = get_qnan();
     }
     }
 
 
-    Texture(const Texture &other) :
-            mTextureBlend(other.mTextureBlend),
-            mMapName(other.mMapName),
-            mOffsetU(other.mOffsetU),
-            mOffsetV(other.mOffsetV),
-            mScaleU(other.mScaleU),
-            mScaleV(other.mScaleV),
-            mRotation(other.mRotation),
-            mMapMode(other.mMapMode),
-            bPrivate(other.bPrivate),
-            iUVSrc(other.iUVSrc) {
-        // empty
-    }
+    Texture(const Texture &other) = default;
 
 
-    Texture(Texture &&other) AI_NO_EXCEPT : mTextureBlend(other.mTextureBlend),
-                                            mMapName(std::move(other.mMapName)),
-                                            mOffsetU(other.mOffsetU),
-                                            mOffsetV(other.mOffsetV),
-                                            mScaleU(other.mScaleU),
-                                            mScaleV(other.mScaleV),
-                                            mRotation(other.mRotation),
-                                            mMapMode(other.mMapMode),
-                                            bPrivate(other.bPrivate),
-                                            iUVSrc(other.iUVSrc) {
-        // empty
-    }
+    Texture(Texture &&other) AI_NO_EXCEPT = default;
 
 
-    Texture &operator=(Texture &&other) AI_NO_EXCEPT {
-        if (this == &other) {
-            return *this;
-        }
-
-        mTextureBlend = other.mTextureBlend;
-        mMapName = std::move(other.mMapName);
-        mOffsetU = other.mOffsetU;
-        mOffsetV = other.mOffsetV;
-        mScaleU = other.mScaleU;
-        mScaleV = other.mScaleV;
-        mRotation = other.mRotation;
-        mMapMode = other.mMapMode;
-        bPrivate = other.bPrivate;
-        iUVSrc = other.iUVSrc;
-
-        return *this;
-    }
+    Texture &operator=(Texture &&other) AI_NO_EXCEPT = default;
 
 
     //! Specifies the blend factor for the texture
     //! Specifies the blend factor for the texture
     ai_real mTextureBlend;
     ai_real mTextureBlend;
@@ -436,83 +395,9 @@ struct Material {
         // empty
         // empty
     }
     }
 
 
-    Material(const Material &other) :
-            mName(other.mName),
-            mDiffuse(other.mDiffuse),
-            mSpecularExponent(other.mSpecularExponent),
-            mShininessStrength(other.mShininessStrength),
-            mSpecular(other.mSpecular),
-            mAmbient(other.mAmbient),
-            mShading(other.mShading),
-            mTransparency(other.mTransparency),
-            sTexDiffuse(other.sTexDiffuse),
-            sTexOpacity(other.sTexOpacity),
-            sTexSpecular(other.sTexSpecular),
-            sTexReflective(other.sTexReflective),
-            sTexBump(other.sTexBump),
-            sTexEmissive(other.sTexEmissive),
-            sTexShininess(other.sTexShininess),
-            mBumpHeight(other.mBumpHeight),
-            mEmissive(other.mEmissive),
-            sTexAmbient(other.sTexAmbient),
-            mTwoSided(other.mTwoSided) {
-        // empty
-    }
-
-    //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
-    Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)),
-                                              mDiffuse(other.mDiffuse),
-                                              mSpecularExponent(other.mSpecularExponent),
-                                              mShininessStrength(other.mShininessStrength),
-                                              mSpecular(other.mSpecular),
-                                              mAmbient(other.mAmbient),
-                                              mShading(other.mShading),
-                                              mTransparency(other.mTransparency),
-                                              sTexDiffuse(std::move(other.sTexDiffuse)),
-                                              sTexOpacity(std::move(other.sTexOpacity)),
-                                              sTexSpecular(std::move(other.sTexSpecular)),
-                                              sTexReflective(std::move(other.sTexReflective)),
-                                              sTexBump(std::move(other.sTexBump)),
-                                              sTexEmissive(std::move(other.sTexEmissive)),
-                                              sTexShininess(std::move(other.sTexShininess)),
-                                              mBumpHeight(other.mBumpHeight),
-                                              mEmissive(other.mEmissive),
-                                              sTexAmbient(std::move(other.sTexAmbient)),
-                                              mTwoSided(other.mTwoSided) {
-        // empty
-    }
+    Material(const Material &other) = default;
 
 
-    Material &operator=(Material &&other) AI_NO_EXCEPT {
-        if (this == &other) {
-            return *this;
-        }
-
-        mName = std::move(other.mName);
-        mDiffuse = other.mDiffuse;
-        mSpecularExponent = other.mSpecularExponent;
-        mShininessStrength = other.mShininessStrength,
-        mSpecular = other.mSpecular;
-        mAmbient = other.mAmbient;
-        mShading = other.mShading;
-        mTransparency = other.mTransparency;
-        sTexDiffuse = std::move(other.sTexDiffuse);
-        sTexOpacity = std::move(other.sTexOpacity);
-        sTexSpecular = std::move(other.sTexSpecular);
-        sTexReflective = std::move(other.sTexReflective);
-        sTexBump = std::move(other.sTexBump);
-        sTexEmissive = std::move(other.sTexEmissive);
-        sTexShininess = std::move(other.sTexShininess);
-        mBumpHeight = other.mBumpHeight;
-        mEmissive = other.mEmissive;
-        sTexAmbient = std::move(other.sTexAmbient);
-        mTwoSided = other.mTwoSided;
-
-        return *this;
-    }
-
-    virtual ~Material() {
-        // empty
-    }
+    virtual ~Material() = default;
 
 
     //! Name of the material
     //! Name of the material
     std::string mName;
     std::string mName;

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

@@ -266,8 +266,15 @@ void Discreet3DSImporter::ParseMainChunk() {
     };
     };
 
 
     ASSIMP_3DS_END_CHUNK();
     ASSIMP_3DS_END_CHUNK();
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunreachable-code-return"
+#endif
     // recursively continue processing this hierarchy level
     // recursively continue processing this hierarchy level
     return ParseMainChunk();
     return ParseMainChunk();
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

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

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

+ 5 - 7
code/AssetLib/3MF/3MFTypes.h

@@ -69,9 +69,7 @@ public:
         // empty
         // empty
     }
     }
 
 
-    virtual ~Resource() {
-        // empty
-    }
+    virtual ~Resource() = default;
 
 
     virtual ResourceType getType() const {
     virtual ResourceType getType() const {
         return ResourceType::RT_Unknown;
         return ResourceType::RT_Unknown;
@@ -95,7 +93,7 @@ public:
         // empty
         // empty
     }
     }
 
 
-    ~EmbeddedTexture() = default;
+    ~EmbeddedTexture() override = default;
 
 
     ResourceType getType() const override {
     ResourceType getType() const override {
         return ResourceType::RT_EmbeddedTexture2D;
         return ResourceType::RT_EmbeddedTexture2D;
@@ -112,7 +110,7 @@ public:
         // empty
         // empty
     }
     }
 
 
-    ~Texture2DGroup() = default;
+    ~Texture2DGroup() override = default;
 
 
     ResourceType getType() const override {
     ResourceType getType() const override {
         return ResourceType::RT_Texture2DGroup;
         return ResourceType::RT_Texture2DGroup;
@@ -129,7 +127,7 @@ public:
         // empty
         // empty
     }
     }
 
 
-    ~BaseMaterials() = default;
+    ~BaseMaterials() override = default;
 
 
     ResourceType getType() const override {
     ResourceType getType() const override {
         return ResourceType::RT_BaseMaterials;
         return ResourceType::RT_BaseMaterials;
@@ -154,7 +152,7 @@ public:
         // empty
         // empty
     }
     }
 
 
-    ~Object() = default;
+    ~Object() override = default;
 
 
     ResourceType getType() const override {
     ResourceType getType() const override {
         return ResourceType::RT_Object;
         return ResourceType::RT_Object;

+ 1 - 1
code/AssetLib/3MF/D3MFExporter.cpp

@@ -83,7 +83,7 @@ void ExportScene3MF(const char *pFile, IOSystem *pIOSystem, const aiScene *pScen
 namespace D3MF {
 namespace D3MF {
 
 
 D3MFExporter::D3MFExporter(const char *pFile, const aiScene *pScene) :
 D3MFExporter::D3MFExporter(const char *pFile, const aiScene *pScene) :
-        mArchiveName(pFile), m_zipArchive(nullptr), mScene(pScene), mModelOutput(), mRelOutput(), mContentOutput(), mBuildItems(), mRelations() {
+        mArchiveName(pFile), m_zipArchive(nullptr), mScene(pScene) {
     // empty
     // empty
 }
 }
 
 

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

@@ -160,7 +160,7 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
                     // deal with zip-bug
                     // deal with zip-bug
                     rootFile = rootFile.substr(1);
                     rootFile = rootFile.substr(1);
                 }
                 }
-            } 
+            }
 
 
             ASSIMP_LOG_VERBOSE_DEBUG(rootFile);
             ASSIMP_LOG_VERBOSE_DEBUG(rootFile);
 
 

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

@@ -216,7 +216,7 @@ void XmlSerializer::ImportXml(aiScene *scene) {
     if (nullptr == scene) {
     if (nullptr == scene) {
         return;
         return;
     }
     }
-    
+
     scene->mRootNode = new aiNode(XmlTag::RootTag);
     scene->mRootNode = new aiNode(XmlTag::RootTag);
     XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
     XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
     if (node.empty()) {
     if (node.empty()) {
@@ -444,7 +444,7 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
                             }
                             }
                             mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
                             mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
                         }
                         }
-                    } 
+                    }
                 }
                 }
             }
             }
 
 

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

@@ -227,7 +227,9 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
             }
             }
         } else if (TokenMatch(buffer, "texture", 7)) {
         } else if (TokenMatch(buffer, "texture", 7)) {
             SkipSpaces(&buffer);
             SkipSpaces(&buffer);
-            buffer = AcGetString(buffer, obj.texture);
+            std::string texture;
+            buffer = AcGetString(buffer, texture);
+            obj.textures.push_back(texture);
         } else if (TokenMatch(buffer, "texrep", 6)) {
         } else if (TokenMatch(buffer, "texrep", 6)) {
             SkipSpaces(&buffer);
             SkipSpaces(&buffer);
             buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texRepeat);
             buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texRepeat);
@@ -351,8 +353,8 @@ void AC3DImporter::ConvertMaterial(const Object &object,
         s.Set(matSrc.name);
         s.Set(matSrc.name);
         matDest.AddProperty(&s, AI_MATKEY_NAME);
         matDest.AddProperty(&s, AI_MATKEY_NAME);
     }
     }
-    if (object.texture.length()) {
-        s.Set(object.texture);
+    if (!object.textures.empty()) {
+        s.Set(object.textures[0]);
         matDest.AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
         matDest.AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
 
 
         // UV transformation
         // UV transformation
@@ -532,7 +534,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
                 // allocate UV coordinates, but only if the texture name for the
                 // allocate UV coordinates, but only if the texture name for the
                 // surface is not empty
                 // surface is not empty
                 aiVector3D *uv = nullptr;
                 aiVector3D *uv = nullptr;
-                if (object.texture.length()) {
+                if (!object.textures.empty()) {
                     uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
                     uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
                     mesh->mNumUVComponents[0] = 2;
                     mesh->mNumUVComponents[0] = 2;
                 }
                 }

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

@@ -125,7 +125,6 @@ public:
                 type(World),
                 type(World),
                 name(),
                 name(),
                 children(),
                 children(),
-                texture(),
                 texRepeat(1.f, 1.f),
                 texRepeat(1.f, 1.f),
                 texOffset(0.0f, 0.0f),
                 texOffset(0.0f, 0.0f),
                 rotation(),
                 rotation(),
@@ -151,7 +150,8 @@ public:
         std::vector<Object> children;
         std::vector<Object> children;
 
 
         // texture to be assigned to all surfaces of the object
         // texture to be assigned to all surfaces of the object
-        std::string texture;
+        // the .acc format supports up to 4 textures
+        std::vector<std::string> textures;
 
 
         // texture repat factors (scaling for all coordinates)
         // texture repat factors (scaling for all coordinates)
         aiVector2D texRepeat, texOffset;
         aiVector2D texRepeat, texOffset;

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

@@ -83,11 +83,7 @@ void AMFImporter::Clear() {
 
 
 AMFImporter::AMFImporter() AI_NO_EXCEPT :
 AMFImporter::AMFImporter() AI_NO_EXCEPT :
         mNodeElement_Cur(nullptr),
         mNodeElement_Cur(nullptr),
-        mXmlParser(nullptr),
-        mUnit(),
-        mVersion(),
-        mMaterial_Converted(),
-        mTexture_Converted() {
+        mXmlParser(nullptr) {
     // empty
     // empty
 }
 }
 
 

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

@@ -282,11 +282,11 @@ public:
     bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;
     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_ConvertedNode(const std::string &pID, NodeArray &nodeArray, aiNode **pNode) const;
     bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const;
     bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const;
-    void Throw_CloseNotFound(const std::string &nodeName);
-    void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName);
-    void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName);
-    void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription);
-    void Throw_ID_NotFound(const std::string &pID) const;
+    AI_WONT_RETURN void Throw_CloseNotFound(const std::string &nodeName) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX;
     void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
     void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
     bool XML_SearchNode(const std::string &nodeName);
     bool XML_SearchNode(const std::string &nodeName);
     void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString);
     void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString);

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

@@ -88,9 +88,7 @@ public:
 	std::list<AMFNodeElementBase *> Child; ///< Child elements.
 	std::list<AMFNodeElementBase *> Child; ///< Child elements.
 
 
 public: /// Destructor, virtual..
 public: /// Destructor, virtual..
-	virtual ~AMFNodeElementBase() {
-		// empty
-	}
+	virtual ~AMFNodeElementBase() = default;
 
 
 	/// Disabled copy constructor and co.
 	/// Disabled copy constructor and co.
 	AMFNodeElementBase(const AMFNodeElementBase &pNodeElement) = delete;
 	AMFNodeElementBase(const AMFNodeElementBase &pNodeElement) = delete;
@@ -103,7 +101,7 @@ protected:
 	/// \param [in] pType - element type.
 	/// \param [in] pType - element type.
 	/// \param [in] pParent - parent element.
 	/// \param [in] pParent - parent element.
 	AMFNodeElementBase(const EType pType, AMFNodeElementBase *pParent) :
 	AMFNodeElementBase(const EType pType, AMFNodeElementBase *pParent) :
-			Type(pType), ID(), Parent(pParent), Child() {
+			Type(pType), Parent(pParent) {
 		// empty
 		// empty
 	}
 	}
 }; // class IAMFImporter_NodeElement
 }; // class IAMFImporter_NodeElement
@@ -174,7 +172,7 @@ struct AMFColor : public AMFNodeElementBase {
 	/// @brief  Constructor.
 	/// @brief  Constructor.
 	/// @param [in] pParent - pointer to parent node.
 	/// @param [in] pParent - pointer to parent node.
 	AMFColor(AMFNodeElementBase *pParent) :
 	AMFColor(AMFNodeElementBase *pParent) :
-			AMFNodeElementBase(ENET_Color, pParent), Composed(false), Color(), Profile() {
+			AMFNodeElementBase(ENET_Color, pParent), Composed(false), Color() {
 		// empty
 		// empty
 	}
 	}
 };
 };
@@ -270,7 +268,7 @@ struct AMFTexMap : public AMFNodeElementBase {
 	/// Constructor.
 	/// Constructor.
 	/// \param [in] pParent - pointer to parent node.
 	/// \param [in] pParent - pointer to parent node.
 	AMFTexMap(AMFNodeElementBase *pParent) :
 	AMFTexMap(AMFNodeElementBase *pParent) :
-			AMFNodeElementBase(ENET_TexMap, pParent), TextureCoordinate{}, TextureID_R(), TextureID_G(), TextureID_B(), TextureID_A() {
+			AMFNodeElementBase(ENET_TexMap, pParent), TextureCoordinate{} {
 		// empty
 		// empty
 	}
 	}
 };
 };

+ 1 - 0
code/AssetLib/AMF/AMFImporter_Postprocess.cpp

@@ -815,6 +815,7 @@ nl_clean_loop:
             for (; next_it != nodeArray.end(); ++next_it) {
             for (; next_it != nodeArray.end(); ++next_it) {
                 if ((*next_it)->FindNode((*nl_it)->mName) != nullptr) {
                 if ((*next_it)->FindNode((*nl_it)->mName) != nullptr) {
                     // if current top node(nl_it) found in another top node then erase it from node_list and restart search loop.
                     // if current top node(nl_it) found in another top node then erase it from node_list and restart search loop.
+                    // FIXME: this leaks memory on test models test8.amf and test9.amf
                     nodeArray.erase(nl_it);
                     nodeArray.erase(nl_it);
 
 
                     goto nl_clean_loop;
                     goto nl_clean_loop;

+ 0 - 16
code/AssetLib/ASE/ASELoader.cpp

@@ -44,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
  */
 
 
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
-
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 
 // internal headers
 // internal headers
@@ -322,21 +321,6 @@ void ASEImporter::BuildAnimations(const std::vector<BaseNode *> &nodes) {
                 aiNodeAnim *nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
                 aiNodeAnim *nd = pcAnim->mChannels[iNum++] = new aiNodeAnim();
                 nd->mNodeName.Set(me->mName + ".Target");
                 nd->mNodeName.Set(me->mName + ".Target");
 
 
-                // If there is no input position channel we will need
-                // to supply the default position from the node's
-                // local transformation matrix.
-                /*TargetAnimationHelper helper;
-                if (me->mAnim.akeyPositions.empty())
-                {
-                    aiMatrix4x4& mat = (*i)->mTransform;
-                    helper.SetFixedMainAnimationChannel(aiVector3D(
-                        mat.a4, mat.b4, mat.c4));
-                }
-                else helper.SetMainAnimationChannel (&me->mAnim.akeyPositions);
-                helper.SetTargetAnimationChannel (&me->mTargetAnim.akeyPositions);
-
-                helper.Process(&me->mTargetAnim.akeyPositions);*/
-
                 // Allocate the key array and fill it
                 // Allocate the key array and fill it
                 nd->mNumPositionKeys = (unsigned int)me->mTargetAnim.akeyPositions.size();
                 nd->mNumPositionKeys = (unsigned int)me->mTargetAnim.akeyPositions.size();
                 nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];
                 nd->mPositionKeys = new aiVectorKey[nd->mNumPositionKeys];

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

@@ -304,7 +304,6 @@ void Parser::Parse() {
         }
         }
         AI_ASE_HANDLE_TOP_LEVEL_SECTION();
         AI_ASE_HANDLE_TOP_LEVEL_SECTION();
     }
     }
-    return;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -734,7 +733,6 @@ void Parser::ParseLV3MapBlock(Texture &map) {
         }
         }
         AI_ASE_HANDLE_SECTION("3", "*MAP_XXXXXX");
         AI_ASE_HANDLE_SECTION("3", "*MAP_XXXXXX");
     }
     }
-    return;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -859,7 +857,6 @@ void Parser::ParseLV1ObjectBlock(ASE::BaseNode &node) {
         }
         }
         AI_ASE_HANDLE_TOP_LEVEL_SECTION();
         AI_ASE_HANDLE_TOP_LEVEL_SECTION();
     }
     }
-    return;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -883,7 +880,6 @@ void Parser::ParseLV2CameraSettingsBlock(ASE::Camera &camera) {
         }
         }
         AI_ASE_HANDLE_SECTION("2", "CAMERA_SETTINGS");
         AI_ASE_HANDLE_SECTION("2", "CAMERA_SETTINGS");
     }
     }
-    return;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -1189,7 +1185,6 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode &mesh) {
         }
         }
         AI_ASE_HANDLE_SECTION("2", "*NODE_TM");
         AI_ASE_HANDLE_SECTION("2", "*NODE_TM");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) {
 void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) {
@@ -1310,7 +1305,6 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) {
         }
         }
         AI_ASE_HANDLE_SECTION("2", "*MESH");
         AI_ASE_HANDLE_SECTION("2", "*MESH");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) {
 void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) {
@@ -1344,7 +1338,6 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) {
         }
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_WEIGHTS");
         AI_ASE_HANDLE_SECTION("3", "*MESH_WEIGHTS");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshBones(unsigned int iNumBones, ASE::Mesh &mesh) {
 void Parser::ParseLV4MeshBones(unsigned int iNumBones, ASE::Mesh &mesh) {
@@ -1414,7 +1407,6 @@ void Parser::ParseLV4MeshBonesVertices(unsigned int iNumVertices, ASE::Mesh &mes
         }
         }
         AI_ASE_HANDLE_SECTION("4", "*MESH_BONE_VERTEX");
         AI_ASE_HANDLE_SECTION("4", "*MESH_BONE_VERTEX");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshVertexListBlock(
 void Parser::ParseLV3MeshVertexListBlock(
@@ -1443,7 +1435,6 @@ void Parser::ParseLV3MeshVertexListBlock(
         }
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_VERTEX_LIST");
         AI_ASE_HANDLE_SECTION("3", "*MESH_VERTEX_LIST");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) {
 void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) {
@@ -1470,7 +1461,6 @@ void Parser::ParseLV3MeshFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh)
         }
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_FACE_LIST");
         AI_ASE_HANDLE_SECTION("3", "*MESH_FACE_LIST");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
 void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
@@ -1503,7 +1493,6 @@ void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
         }
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_TVERT_LIST");
         AI_ASE_HANDLE_SECTION("3", "*MESH_TVERT_LIST");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
 void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
@@ -1532,7 +1521,6 @@ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
         }
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_TFACE_LIST");
         AI_ASE_HANDLE_SECTION("3", "*MESH_TFACE_LIST");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh &mesh) {
 void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh &mesh) {
@@ -1567,7 +1555,6 @@ void Parser::ParseLV3MappingChannel(unsigned int iChannel, ASE::Mesh &mesh) {
         }
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_MAPPING_CHANNEL");
         AI_ASE_HANDLE_SECTION("3", "*MESH_MAPPING_CHANNEL");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh &mesh) {
 void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh &mesh) {
@@ -1595,7 +1582,6 @@ void Parser::ParseLV3MeshCListBlock(unsigned int iNumVertices, ASE::Mesh &mesh)
         }
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_CVERTEX_LIST");
         AI_ASE_HANDLE_SECTION("3", "*MESH_CVERTEX_LIST");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) {
 void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh) {
@@ -1623,7 +1609,6 @@ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh &mesh)
         }
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_CFACE_LIST");
         AI_ASE_HANDLE_SECTION("3", "*MESH_CFACE_LIST");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) {
 void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) {
@@ -1681,7 +1666,6 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) {
         }
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_NORMALS");
         AI_ASE_HANDLE_SECTION("3", "*MESH_NORMALS");
     }
     }
-    return;
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshFace(ASE::Face &out) {
 void Parser::ParseLV4MeshFace(ASE::Face &out) {

+ 1 - 1
code/AssetLib/Assbin/AssbinExporter.h

@@ -56,5 +56,5 @@ namespace Assimp {
 void ASSIMP_API ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/);
 void ASSIMP_API ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/);
 
 
 }
 }
-#endif 
+#endif
 #endif // AI_ASSBINEXPORTER_H_INC
 #endif // AI_ASSBINEXPORTER_H_INC

+ 3 - 3
code/AssetLib/Assbin/AssbinFileWriter.cpp

@@ -291,15 +291,15 @@ public:
     size_t Read(void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override {
     size_t Read(void * /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) override {
         return 0;
         return 0;
     }
     }
-    
+
     aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) override {
     aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) override {
         return aiReturn_FAILURE;
         return aiReturn_FAILURE;
     }
     }
-    
+
     size_t Tell() const override {
     size_t Tell() const override {
         return cursor;
         return cursor;
     }
     }
-    
+
     void Flush() override {
     void Flush() override {
         // not implemented
         // not implemented
     }
     }

+ 1 - 1
code/AssetLib/Assjson/cencode.c

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

+ 5 - 5
code/AssetLib/Assjson/json_exporter.cpp

@@ -43,7 +43,7 @@ public:
         Flag_WriteSpecialFloats = 0x2,
         Flag_WriteSpecialFloats = 0x2,
         Flag_SkipWhitespaces = 0x4
         Flag_SkipWhitespaces = 0x4
     };
     };
-    
+
     JSONWriter(Assimp::IOStream &out, unsigned int flags = 0u) :
     JSONWriter(Assimp::IOStream &out, unsigned int flags = 0u) :
             out(out), indent (""), newline("\n"), space(" "), buff (), first(false), 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
         // make sure that all formatting happens using the standard, C locale and not the user's current locale
@@ -499,18 +499,18 @@ static void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
                 }
                 }
                 break;
                 break;
 
 
-            case aiPTI_String: 
+            case aiPTI_String:
                 {
                 {
                     aiString s;
                     aiString s;
                     aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
                     aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
                     out.SimpleValue(s);
                     out.SimpleValue(s);
-                } 
+                }
                 break;
                 break;
-            case aiPTI_Buffer: 
+            case aiPTI_Buffer:
                 {
                 {
                     // binary data is written as series of hex-encoded octets
                     // binary data is written as series of hex-encoded octets
                     out.SimpleValue(prop->mData, prop->mDataLength);
                     out.SimpleValue(prop->mData, prop->mDataLength);
-                } 
+                }
                 break;
                 break;
             default:
             default:
                 ai_assert(false);
                 ai_assert(false);

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

@@ -150,7 +150,7 @@ AI_WONT_RETURN void B3DImporter::Fail(const string &str) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 int B3DImporter::ReadByte() {
 int B3DImporter::ReadByte() {
-    if (_pos > _buf.size()) {
+    if (_pos >= _buf.size()) {
         Fail("EOF");
         Fail("EOF");
     }
     }
 
 
@@ -418,7 +418,6 @@ void B3DImporter::ReadTRIS(int v0) {
             ASSIMP_LOG_ERROR("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2);
             ASSIMP_LOG_ERROR("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2);
 #endif
 #endif
             Fail("Bad triangle index");
             Fail("Bad triangle index");
-            continue;
         }
         }
         face->mNumIndices = 3;
         face->mNumIndices = 3;
         face->mIndices = new unsigned[3];
         face->mIndices = new unsigned[3];

+ 1 - 2
code/AssetLib/Blender/BlenderBMesh.cpp

@@ -52,8 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace Assimp {
 template <>
 template <>
 const char *LogFunctions<BlenderBMeshConverter>::Prefix() {
 const char *LogFunctions<BlenderBMeshConverter>::Prefix() {
-    static auto prefix = "BLEND_BMESH: ";
-    return prefix;
+    return "BLEND_BMESH: ";
 }
 }
 } // namespace Assimp
 } // namespace Assimp
 
 

+ 2 - 1
code/AssetLib/Blender/BlenderCustomData.cpp

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

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

@@ -106,9 +106,7 @@ struct ElemBase {
         // empty
         // empty
     }
     }
 
 
-    virtual ~ElemBase() {
-        // empty
-    }
+    virtual ~ElemBase() = default;
 
 
     /** Type name of the element. The type
     /** Type name of the element. The type
      * string points is the `c_str` of the `name` attribute of the
      * string points is the `c_str` of the `name` attribute of the

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

@@ -80,8 +80,7 @@ namespace Assimp {
 
 
 template <>
 template <>
 const char *LogFunctions<BlenderImporter>::Prefix() {
 const char *LogFunctions<BlenderImporter>::Prefix() {
-    static auto prefix = "BLEND: ";
-    return prefix;
+    return "BLEND: ";
 }
 }
 
 
 } // namespace Assimp
 } // namespace Assimp

+ 1 - 3
code/AssetLib/Blender/BlenderModifier.h

@@ -62,9 +62,7 @@ public:
     /**
     /**
      *  The class destructor, virtual.
      *  The class destructor, virtual.
      */
      */
-    virtual ~BlenderModifier() {
-        // empty
-    }
+    virtual ~BlenderModifier() = default;
 
 
     // --------------------
     // --------------------
     /**
     /**

+ 1 - 1
code/AssetLib/Blender/BlenderScene.cpp

@@ -569,7 +569,7 @@ void Structure ::Convert<MVert>(
         const FileDatabase &db) const {
         const FileDatabase &db) const {
 
 
     ReadFieldArray<ErrorPolicy_Fail>(dest.co, "co", db);
     ReadFieldArray<ErrorPolicy_Fail>(dest.co, "co", db);
-    ReadFieldArray<ErrorPolicy_Fail>(dest.no, "no", db);
+    ReadFieldArray<ErrorPolicy_Warn>(dest.no, "no", db);
     ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
     ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
     //ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
     //ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
     ReadField<ErrorPolicy_Igno>(dest.bweight, "bweight", db);
     ReadField<ErrorPolicy_Igno>(dest.bweight, "bweight", db);

+ 7 - 18
code/AssetLib/Blender/BlenderScene.h

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

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

@@ -62,8 +62,7 @@ namspace Assimp
 {
 {
     template< > const char* LogFunctions< BlenderTessellatorGL >::Prefix()
     template< > const char* LogFunctions< BlenderTessellatorGL >::Prefix()
     {
     {
-        static auto prefix = "BLEND_TESS_GL: ";
-        return prefix;
+        return "BLEND_TESS_GL: ";
     }
     }
 }
 }
 
 
@@ -81,9 +80,7 @@ BlenderTessellatorGL::BlenderTessellatorGL( BlenderBMeshConverter& converter ):
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-BlenderTessellatorGL::~BlenderTessellatorGL( )
-{
-}
+BlenderTessellatorGL::~BlenderTessellatorGL() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
 void BlenderTessellatorGL::Tessellate( const MLoop* polyLoop, int vertexCount, const std::vector< MVert >& vertices )
@@ -259,8 +256,7 @@ namespace Assimp
 {
 {
     template< > const char* LogFunctions< BlenderTessellatorP2T >::Prefix()
     template< > const char* LogFunctions< BlenderTessellatorP2T >::Prefix()
     {
     {
-        static auto prefix = "BLEND_TESS_P2T: ";
-        return prefix;
+        return "BLEND_TESS_P2T: ";
     }
     }
 }
 }
 
 

+ 4 - 10
code/AssetLib/C4D/C4DImporter.cpp

@@ -86,8 +86,7 @@ void GetWriterInfo(int &id, String &appname) {
 
 
 namespace Assimp {
 namespace Assimp {
     template<> const char* LogFunctions<C4DImporter>::Prefix() {
     template<> const char* LogFunctions<C4DImporter>::Prefix() {
-        static auto prefix = "C4D: ";
-        return prefix;
+        return "C4D: ";
     }
     }
 }
 }
 
 
@@ -106,15 +105,10 @@ static const aiImporterDesc desc = {
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-C4DImporter::C4DImporter()
-: BaseImporter() {
-    // empty
-}
+C4DImporter::C4DImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-C4DImporter::~C4DImporter() {
-    // empty
-}
+C4DImporter::~C4DImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 bool C4DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const {
 bool C4DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const {
@@ -124,7 +118,7 @@ bool C4DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, b
     } else if ((!extension.length() || checkSig) && pIOHandler)   {
     } else if ((!extension.length() || checkSig) && pIOHandler)   {
         // TODO
         // TODO
     }
     }
-    
+
     return false;
     return false;
 }
 }
 
 

+ 2 - 2
code/AssetLib/Collada/ColladaExporter.cpp

@@ -448,7 +448,7 @@ void ColladaExporter::WriteLight(size_t pIndex) {
     PushTag();
     PushTag();
     switch (light->mType) {
     switch (light->mType) {
     case aiLightSource_AMBIENT:
     case aiLightSource_AMBIENT:
-        WriteAmbienttLight(light);
+        WriteAmbientLight(light);
         break;
         break;
     case aiLightSource_DIRECTIONAL:
     case aiLightSource_DIRECTIONAL:
         WriteDirectionalLight(light);
         WriteDirectionalLight(light);
@@ -543,7 +543,7 @@ void ColladaExporter::WriteSpotLight(const aiLight *const light) {
     mOutput << startstr << "</spot>" << endstr;
     mOutput << startstr << "</spot>" << endstr;
 }
 }
 
 
-void ColladaExporter::WriteAmbienttLight(const aiLight *const light) {
+void ColladaExporter::WriteAmbientLight(const aiLight *const light) {
 
 
     const aiColor3D &color = light->mColorAmbient;
     const aiColor3D &color = light->mColorAmbient;
     mOutput << startstr << "<ambient>" << endstr;
     mOutput << startstr << "<ambient>" << endstr;

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

@@ -101,7 +101,7 @@ protected:
     void WritePointLight(const aiLight *const light);
     void WritePointLight(const aiLight *const light);
     void WriteDirectionalLight(const aiLight *const light);
     void WriteDirectionalLight(const aiLight *const light);
     void WriteSpotLight(const aiLight *const light);
     void WriteSpotLight(const aiLight *const light);
-    void WriteAmbienttLight(const aiLight *const light);
+    void WriteAmbientLight(const aiLight *const light);
 
 
     /// Writes the controller library
     /// Writes the controller library
     void WriteControllerLibrary();
     void WriteControllerLibrary();

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

@@ -666,7 +666,7 @@ struct ChannelEntry {
     const Collada::Accessor *mTimeAccessor; ///> Collada accessor to the time values
     const Collada::Accessor *mTimeAccessor; ///> Collada accessor to the time values
     const Collada::Data *mTimeData; ///> Source data array for the time values
     const Collada::Data *mTimeData; ///> Source data array for the time values
     const Collada::Accessor *mValueAccessor; ///> Collada accessor to the key value values
     const Collada::Accessor *mValueAccessor; ///> Collada accessor to the key value values
-    const Collada::Data *mValueData; ///> Source datat array for the key value values
+    const Collada::Data *mValueData; ///> Source data array for the key value values
 
 
     ChannelEntry() :
     ChannelEntry() :
             mChannel(),
             mChannel(),

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

@@ -92,15 +92,6 @@ inline void AddNodeMetaData(aiNode *node, const std::string &key, const T &value
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 ColladaLoader::ColladaLoader() :
 ColladaLoader::ColladaLoader() :
-        mFileName(),
-        mMeshIndexByID(),
-        mMaterialIndexByName(),
-        mMeshes(),
-        newMats(),
-        mCameras(),
-        mLights(),
-        mTextures(),
-        mAnims(),
         noSkeletonMesh(false),
         noSkeletonMesh(false),
         removeEmptyBones(false),
         removeEmptyBones(false),
         ignoreUpDirection(false),
         ignoreUpDirection(false),
@@ -1523,7 +1514,7 @@ void ColladaLoader::AddTexture(aiMaterial &mat,
         map = -1;
         map = -1;
         for (std::string::const_iterator it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
         for (std::string::const_iterator it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
             if (IsNumeric(*it)) {
             if (IsNumeric(*it)) {
-                map = strtoul10(&(*it));        
+                map = strtoul10(&(*it));
                 break;
                 break;
             }
             }
         }
         }

+ 1 - 1
code/AssetLib/Collada/ColladaParser.cpp

@@ -762,6 +762,7 @@ void ColladaParser::ReadControllerWeights(XmlNode &node, Collada::Controller &pC
                 if (text == nullptr) {
                 if (text == nullptr) {
                     throw DeadlyImportError("Out of data while reading <vertex_weights>");
                     throw DeadlyImportError("Out of data while reading <vertex_weights>");
                 }
                 }
+                SkipSpacesAndLineEnd(&text);
                 it->first = strtoul10(text, &text);
                 it->first = strtoul10(text, &text);
                 SkipSpacesAndLineEnd(&text);
                 SkipSpacesAndLineEnd(&text);
                 if (*text == 0) {
                 if (*text == 0) {
@@ -1854,7 +1855,6 @@ size_t ColladaParser::ReadPrimitives(XmlNode &node, Mesh &pMesh, std::vector<Inp
         default:
         default:
             // LineStrip is not supported due to expected index unmangling
             // LineStrip is not supported due to expected index unmangling
             throw DeadlyImportError("Unsupported primitive type.");
             throw DeadlyImportError("Unsupported primitive type.");
-            break;
         }
         }
 
 
         // store the face size to later reconstruct the face from
         // store the face size to later reconstruct the face from

+ 1 - 3
code/AssetLib/DXF/DXFHelper.h

@@ -65,7 +65,6 @@ public:
     LineReader(StreamReaderLE& reader)
     LineReader(StreamReaderLE& reader)
     : splitter(reader,false,true)
     : splitter(reader,false,true)
     , groupcode( 0 )
     , groupcode( 0 )
-    , value()
     , end() {
     , end() {
         // empty
         // empty
     }
     }
@@ -186,8 +185,7 @@ struct InsertBlock {
     InsertBlock()
     InsertBlock()
     : pos()
     : pos()
     , scale(1.f,1.f,1.f)
     , scale(1.f,1.f,1.f)
-    , angle()
-    , name() {
+    , angle() {
         // empty
         // empty
     }
     }
 
 

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

@@ -371,7 +371,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
                 ASSIMP_LOG_ERROR("DXF: PolyLine instance is nullptr, skipping.");
                 ASSIMP_LOG_ERROR("DXF: PolyLine instance is nullptr, skipping.");
                 continue;
                 continue;
             }
             }
-            
+
             std::shared_ptr<DXF::PolyLine> pl_out = std::shared_ptr<DXF::PolyLine>(new DXF::PolyLine(*pl_in));
             std::shared_ptr<DXF::PolyLine> pl_out = std::shared_ptr<DXF::PolyLine>(new DXF::PolyLine(*pl_in));
 
 
             if (bl_src.base.Length() || insert.scale.x!=1.f || insert.scale.y!=1.f || insert.scale.z!=1.f || insert.angle || insert.pos.Length()) {
             if (bl_src.base.Length() || insert.scale.x!=1.f || insert.scale.y!=1.f || insert.scale.z!=1.f || insert.angle || insert.pos.Length()) {

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

@@ -139,6 +139,7 @@ size_t Offset(const char* begin, const char* cursor) {
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
+AI_WONT_RETURN void TokenizeError(const std::string& message, const char* begin, const char* cursor) AI_WONT_RETURN_SUFFIX;
 void TokenizeError(const std::string& message, const char* begin, const char* cursor) {
 void TokenizeError(const std::string& message, const char* begin, const char* cursor) {
     TokenizeError(message, Offset(begin, cursor));
     TokenizeError(message, Offset(begin, cursor));
 }
 }
@@ -341,8 +342,7 @@ void ReadData(const char*& sbegin_out, const char*& send_out, const char* input,
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor, const char* end, bool const is64bits)
-{
+bool ReadScope(TokenList &output_tokens, StackAllocator &token_allocator, const char *input, const char *&cursor, const char *end, bool const is64bits) {
     // the first word contains the offset at which this block ends
     // the first word contains the offset at which this block ends
 	const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
 	const uint64_t end_offset = is64bits ? ReadDoubleWord(input, cursor, end) : ReadWord(input, cursor, end);
 
 
@@ -408,7 +408,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
 
 
         // XXX this is vulnerable to stack overflowing ..
         // XXX this is vulnerable to stack overflowing ..
         while(Offset(input, cursor) < end_offset - sentinel_block_length) {
         while(Offset(input, cursor) < end_offset - sentinel_block_length) {
-			ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits);
+            ReadScope(output_tokens, token_allocator, input, cursor, input + end_offset - sentinel_block_length, is64bits);
         }
         }
         output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
         output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
 
 
@@ -431,8 +431,7 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
 // TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
-void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
-{
+void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length, StackAllocator &token_allocator) {
 	ai_assert(input);
 	ai_assert(input);
 	ASSIMP_LOG_DEBUG("Tokenizing binary FBX file");
 	ASSIMP_LOG_DEBUG("Tokenizing binary FBX file");
 
 
@@ -465,7 +464,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
     try
     try
     {
     {
         while (cursor < end ) {
         while (cursor < end ) {
-		    if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
+            if (!ReadScope(output_tokens, token_allocator, input, cursor, input + length, is64bits)) {
                 break;
                 break;
             }
             }
         }
         }

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

@@ -55,6 +55,7 @@ const char NULL_RECORD[NumNullRecords] = { // 25 null bytes in 64-bit and 13 nul
     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0',
     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
     '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0', '\0'
 }; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
 }; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
+static std::string NULL_RECORD_STRING(NumNullRecords, '\0');
 const std::string SEPARATOR = { '\x00', '\x01' }; // for use inside strings
 const std::string SEPARATOR = { '\x00', '\x01' }; // for use inside strings
 const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
 const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
 const int64_t SECOND = 46186158000; // FBX's kTime unit
 const int64_t SECOND = 46186158000; // FBX's kTime unit

+ 31 - 16
code/AssetLib/FBX/FBXConverter.cpp

@@ -421,6 +421,8 @@ void FBXConverter::ConvertCamera(const Camera &cam, const std::string &orig_name
 
 
     out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
     out_camera->mAspect = cam.AspectWidth() / cam.AspectHeight();
 
 
+    // NOTE: Camera mPosition, mLookAt and mUp must be set to default here.
+    // All transformations to the camera will be handled by its node in the scenegraph.
     out_camera->mPosition = aiVector3D(0.0f);
     out_camera->mPosition = aiVector3D(0.0f);
     out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
     out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
     out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
     out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
@@ -640,7 +642,7 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
 bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
 bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
     const PropertyTable &props = model.Props();
     const PropertyTable &props = model.Props();
 
 
-    const auto zero_epsilon = ai_epsilon;
+    const auto zero_epsilon = Math::getEpsilon<ai_real>();
     const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
     const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
     for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
     for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
         const TransformationComp comp = static_cast<TransformationComp>(i);
         const TransformationComp comp = static_cast<TransformationComp>(i);
@@ -873,8 +875,12 @@ void FBXConverter::SetupNodeMetadata(const Model &model, aiNode &nd) {
             data->Set(index++, prop.first, interpretedBool->Value());
             data->Set(index++, prop.first, interpretedBool->Value());
         } else if (const TypedProperty<int> *interpretedInt = prop.second->As<TypedProperty<int>>()) {
         } else if (const TypedProperty<int> *interpretedInt = prop.second->As<TypedProperty<int>>()) {
             data->Set(index++, prop.first, interpretedInt->Value());
             data->Set(index++, prop.first, interpretedInt->Value());
+        } else if (const TypedProperty<uint32_t> *interpretedUInt = prop.second->As<TypedProperty<uint32_t>>()) {
+            data->Set(index++, prop.first, interpretedUInt->Value());
         } else if (const TypedProperty<uint64_t> *interpretedUint64 = prop.second->As<TypedProperty<uint64_t>>()) {
         } else if (const TypedProperty<uint64_t> *interpretedUint64 = prop.second->As<TypedProperty<uint64_t>>()) {
             data->Set(index++, prop.first, interpretedUint64->Value());
             data->Set(index++, prop.first, interpretedUint64->Value());
+        } else if (const TypedProperty<int64_t> *interpretedint64 = prop.second->As<TypedProperty<int64_t>>()) {
+            data->Set(index++, prop.first, interpretedint64->Value());
         } else if (const TypedProperty<float> *interpretedFloat = prop.second->As<TypedProperty<float>>()) {
         } else if (const TypedProperty<float> *interpretedFloat = prop.second->As<TypedProperty<float>>()) {
             data->Set(index++, prop.first, interpretedFloat->Value());
             data->Set(index++, prop.first, interpretedFloat->Value());
         } else if (const TypedProperty<std::string> *interpretedString = prop.second->As<TypedProperty<std::string>>()) {
         } else if (const TypedProperty<std::string> *interpretedString = prop.second->As<TypedProperty<std::string>>()) {
@@ -1176,15 +1182,23 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
     std::vector<aiAnimMesh *> animMeshes;
     std::vector<aiAnimMesh *> animMeshes;
     for (const BlendShape *blendShape : mesh.GetBlendShapes()) {
     for (const BlendShape *blendShape : mesh.GetBlendShapes()) {
         for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) {
         for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) {
-            const std::vector<const ShapeGeometry *> &shapeGeometries = blendShapeChannel->GetShapeGeometries();
-            for (size_t i = 0; i < shapeGeometries.size(); i++) {
+            const auto& shapeGeometries = blendShapeChannel->GetShapeGeometries();
+            for (const ShapeGeometry *shapeGeometry : shapeGeometries) {
                 aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
                 aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
-                const ShapeGeometry *shapeGeometry = shapeGeometries.at(i);
-                const std::vector<aiVector3D> &curVertices = shapeGeometry->GetVertices();
-                const std::vector<aiVector3D> &curNormals = shapeGeometry->GetNormals();
-                const std::vector<unsigned int> &curIndices = shapeGeometry->GetIndices();
+                const auto &curVertices = shapeGeometry->GetVertices();
+                const auto &curNormals = shapeGeometry->GetNormals();
+                const auto &curIndices = shapeGeometry->GetIndices();
                 //losing channel name if using shapeGeometry->Name()
                 //losing channel name if using shapeGeometry->Name()
-                animMesh->mName.Set(FixAnimMeshName(blendShapeChannel->Name()));
+                // if blendShapeChannel Name is empty or don't have a ".", add geoMetryName;
+                auto aniName = FixAnimMeshName(blendShapeChannel->Name());
+                auto geoMetryName = FixAnimMeshName(shapeGeometry->Name());
+                if (aniName.empty()) {
+                    aniName = geoMetryName;
+                }
+                else if (aniName.find('.') == aniName.npos) {
+                    aniName += "." + geoMetryName;
+                }
+                animMesh->mName.Set(aniName);
                 for (size_t j = 0; j < curIndices.size(); j++) {
                 for (size_t j = 0; j < curIndices.size(); j++) {
                     const unsigned int curIndex = curIndices.at(j);
                     const unsigned int curIndex = curIndices.at(j);
                     aiVector3D vertex = curVertices.at(j);
                     aiVector3D vertex = curVertices.at(j);
@@ -1406,13 +1420,12 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
     std::vector<aiAnimMesh *> animMeshes;
     std::vector<aiAnimMesh *> animMeshes;
     for (const BlendShape *blendShape : mesh.GetBlendShapes()) {
     for (const BlendShape *blendShape : mesh.GetBlendShapes()) {
         for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) {
         for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) {
-            const std::vector<const ShapeGeometry *> &shapeGeometries = blendShapeChannel->GetShapeGeometries();
-            for (size_t i = 0; i < shapeGeometries.size(); i++) {
+            const auto& shapeGeometries = blendShapeChannel->GetShapeGeometries();
+            for (const ShapeGeometry *shapeGeometry : shapeGeometries) {
                 aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
                 aiAnimMesh *animMesh = aiCreateAnimMesh(out_mesh);
-                const ShapeGeometry *shapeGeometry = shapeGeometries.at(i);
-                const std::vector<aiVector3D> &curVertices = shapeGeometry->GetVertices();
-                const std::vector<aiVector3D> &curNormals = shapeGeometry->GetNormals();
-                const std::vector<unsigned int> &curIndices = shapeGeometry->GetIndices();
+                const auto& curVertices = shapeGeometry->GetVertices();
+                const auto& curNormals = shapeGeometry->GetNormals();
+                const auto& curIndices = shapeGeometry->GetIndices();
                 animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name()));
                 animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name()));
                 for (size_t j = 0; j < curIndices.size(); j++) {
                 for (size_t j = 0; j < curIndices.size(); j++) {
                     unsigned int curIndex = curIndices.at(j);
                     unsigned int curIndex = curIndices.at(j);
@@ -1455,7 +1468,9 @@ static void copyBoneToSkeletonBone(aiMesh *mesh, aiBone *bone, aiSkeletonBone *s
     skeletonBone->mWeights = bone->mWeights;
     skeletonBone->mWeights = bone->mWeights;
     skeletonBone->mOffsetMatrix = bone->mOffsetMatrix;
     skeletonBone->mOffsetMatrix = bone->mOffsetMatrix;
     skeletonBone->mMeshId = mesh;
     skeletonBone->mMeshId = mesh;
+#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
     skeletonBone->mNode = bone->mNode;
     skeletonBone->mNode = bone->mNode;
+#endif
     skeletonBone->mParent = -1;
     skeletonBone->mParent = -1;
 }
 }
 
 
@@ -1563,7 +1578,7 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
         out->mBones = nullptr;
         out->mBones = nullptr;
         out->mNumBones = 0;
         out->mNumBones = 0;
         return;
         return;
-    } 
+    }
 
 
     out->mBones = new aiBone *[bones.size()]();
     out->mBones = new aiBone *[bones.size()]();
     out->mNumBones = static_cast<unsigned int>(bones.size());
     out->mNumBones = static_cast<unsigned int>(bones.size());
@@ -3228,7 +3243,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
     }
     }
 
 
     bool ok = false;
     bool ok = false;
-    
+
     const auto zero_epsilon = ai_epsilon;
     const auto zero_epsilon = ai_epsilon;
 
 
     const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
     const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);

+ 8 - 4
code/AssetLib/FBX/FBXDeformer.cpp

@@ -154,8 +154,10 @@ BlendShape::BlendShape(uint64_t id, const Element& element, const Document& doc,
     for (const Connection* con : conns) {
     for (const Connection* con : conns) {
         const BlendShapeChannel* const bspc = ProcessSimpleConnection<BlendShapeChannel>(*con, false, "BlendShapeChannel -> BlendShape", element);
         const BlendShapeChannel* const bspc = ProcessSimpleConnection<BlendShapeChannel>(*con, false, "BlendShapeChannel -> BlendShape", element);
         if (bspc) {
         if (bspc) {
-            blendShapeChannels.push_back(bspc);
-            continue;
+            auto pr = blendShapeChannels.insert(bspc);
+            if (!pr.second) {
+                FBXImporter::LogWarn("there is the same blendShapeChannel id ", bspc->ID());
+            }
         }
         }
     }
     }
 }
 }
@@ -179,8 +181,10 @@ BlendShapeChannel::BlendShapeChannel(uint64_t id, const Element& element, const
     for (const Connection* con : conns) {
     for (const Connection* con : conns) {
         const ShapeGeometry* const sg = ProcessSimpleConnection<ShapeGeometry>(*con, false, "Shape -> BlendShapeChannel", element);
         const ShapeGeometry* const sg = ProcessSimpleConnection<ShapeGeometry>(*con, false, "Shape -> BlendShapeChannel", element);
         if (sg) {
         if (sg) {
-            shapeGeometries.push_back(sg);
-            continue;
+            auto pr = shapeGeometries.insert(sg);
+            if (!pr.second) {
+                FBXImporter::LogWarn("there is the same shapeGeometrie id ", sg->ID());
+            }
         }
         }
     }
     }
 }
 }

+ 22 - 12
code/AssetLib/FBX/FBXDocument.cpp

@@ -243,7 +243,7 @@ FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptr<cons
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Document::Document(const Parser& parser, const ImportSettings& settings) :
+Document::Document(Parser& parser, const ImportSettings& settings) :
      settings(settings), parser(parser) {
      settings(settings), parser(parser) {
 	ASSIMP_LOG_DEBUG("Creating FBX Document");
 	ASSIMP_LOG_DEBUG("Creating FBX Document");
 
 
@@ -265,13 +265,17 @@ Document::Document(const Parser& parser, const ImportSettings& settings) :
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Document::~Document() {
-    for(ObjectMap::value_type& v : objects) {
-        delete v.second;
+Document::~Document()
+{
+	// The document does not own the memory for the following objects, but we need to call their d'tor
+	// so they can properly free memory like string members:
+	
+    for (ObjectMap::value_type &v : objects) {
+        delete_LazyObject(v.second);
     }
     }
 
 
-    for(ConnectionMap::value_type& v : src_connections) {
-        delete v.second;
+    for (ConnectionMap::value_type &v : src_connections) {
+        delete_Connection(v.second);
     }
     }
     // |dest_connections| contain the same Connection objects as the |src_connections|
     // |dest_connections| contain the same Connection objects as the |src_connections|
 }
 }
@@ -356,9 +360,11 @@ void Document::ReadObjects() {
         DOMError("no Objects dictionary found");
         DOMError("no Objects dictionary found");
     }
     }
 
 
+    StackAllocator &allocator = parser.GetAllocator();
+
     // add a dummy entry to represent the Model::RootNode object (id 0),
     // add a dummy entry to represent the Model::RootNode object (id 0),
     // which is only indirectly defined in the input file
     // which is only indirectly defined in the input file
-    objects[0] = new LazyObject(0L, *eobjects, *this);
+    objects[0] = new_LazyObject(0L, *eobjects, *this);
 
 
     const Scope& sobjects = *eobjects->Compound();
     const Scope& sobjects = *eobjects->Compound();
     for(const ElementMap::value_type& el : sobjects.Elements()) {
     for(const ElementMap::value_type& el : sobjects.Elements()) {
@@ -381,11 +387,13 @@ void Document::ReadObjects() {
             DOMError("encountered object with implicitly defined id 0",el.second);
             DOMError("encountered object with implicitly defined id 0",el.second);
         }
         }
 
 
-        if(objects.find(id) != objects.end()) {
+        const auto foundObject = objects.find(id);
+        if(foundObject != objects.end()) {
             DOMWarning("encountered duplicate object id, ignoring first occurrence",el.second);
             DOMWarning("encountered duplicate object id, ignoring first occurrence",el.second);
+            delete foundObject->second;
         }
         }
 
 
-        objects[id] = new LazyObject(id, *el.second, *this);
+        objects[id] = new_LazyObject(id, *el.second, *this);
 
 
         // grab all animation stacks upfront since there is no listing of them
         // grab all animation stacks upfront since there is no listing of them
         if(!strcmp(el.first.c_str(),"AnimationStack")) {
         if(!strcmp(el.first.c_str(),"AnimationStack")) {
@@ -452,8 +460,10 @@ void Document::ReadPropertyTemplates() {
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void Document::ReadConnections() {
-    const Scope& sc = parser.GetRootScope();
+void Document::ReadConnections()
+{
+    StackAllocator &allocator = parser.GetAllocator();
+    const Scope &sc = parser.GetRootScope();
     // read property templates from "Definitions" section
     // read property templates from "Definitions" section
     const Element* const econns = sc["Connections"];
     const Element* const econns = sc["Connections"];
     if(!econns || !econns->Compound()) {
     if(!econns || !econns->Compound()) {
@@ -492,7 +502,7 @@ void Document::ReadConnections() {
         }
         }
 
 
         // add new connection
         // add new connection
-        const Connection* const c = new Connection(insertionOrder++,src,dest,prop,*this);
+        const Connection* const c = new_Connection(insertionOrder++,src,dest,prop,*this);
         src_connections.insert(ConnectionMap::value_type(src,c));
         src_connections.insert(ConnectionMap::value_type(src,c));
         dest_connections.insert(ConnectionMap::value_type(dest,c));
         dest_connections.insert(ConnectionMap::value_type(dest,c));
     }
     }

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

@@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_FBX_DOCUMENT_H
 #define INCLUDED_AI_FBX_DOCUMENT_H
 
 
 #include <numeric>
 #include <numeric>
+#include <unordered_set>
 #include <stdint.h>
 #include <stdint.h>
 #include <assimp/mesh.h>
 #include <assimp/mesh.h>
 #include "FBXProperties.h"
 #include "FBXProperties.h"
@@ -80,6 +81,10 @@ class BlendShape;
 class Skin;
 class Skin;
 class Cluster;
 class Cluster;
 
 
+#define new_LazyObject new (allocator.Allocate(sizeof(LazyObject))) LazyObject
+#define new_Connection new (allocator.Allocate(sizeof(Connection))) Connection
+#define delete_LazyObject(_p) (_p)->~LazyObject()
+#define delete_Connection(_p) (_p)->~Connection()
 
 
 /** Represents a delay-parsed FBX objects. Many objects in the scene
 /** Represents a delay-parsed FBX objects. Many objects in the scene
  *  are not needed by assimp, so it makes no sense to parse them
  *  are not needed by assimp, so it makes no sense to parse them
@@ -855,14 +860,14 @@ public:
         return fullWeights;
         return fullWeights;
     }
     }
 
 
-    const std::vector<const ShapeGeometry*>& GetShapeGeometries() const {
+    const std::unordered_set<const ShapeGeometry*>& GetShapeGeometries() const {
         return shapeGeometries;
         return shapeGeometries;
     }
     }
 
 
 private:
 private:
     float percent;
     float percent;
     WeightArray fullWeights;
     WeightArray fullWeights;
-    std::vector<const ShapeGeometry*> shapeGeometries;
+    std::unordered_set<const ShapeGeometry*> shapeGeometries;
 };
 };
 
 
 /** DOM class for BlendShape deformers */
 /** DOM class for BlendShape deformers */
@@ -872,12 +877,12 @@ public:
 
 
     virtual ~BlendShape();
     virtual ~BlendShape();
 
 
-    const std::vector<const BlendShapeChannel*>& BlendShapeChannels() const {
+    const std::unordered_set<const BlendShapeChannel*>& BlendShapeChannels() const {
         return blendShapeChannels;
         return blendShapeChannels;
     }
     }
 
 
 private:
 private:
-    std::vector<const BlendShapeChannel*> blendShapeChannels;
+    std::unordered_set<const BlendShapeChannel*> blendShapeChannels;
 };
 };
 
 
 /** DOM class for skin deformer clusters (aka sub-deformers) */
 /** DOM class for skin deformer clusters (aka sub-deformers) */
@@ -1072,7 +1077,7 @@ private:
 /** DOM root for a FBX file */
 /** DOM root for a FBX file */
 class Document {
 class Document {
 public:
 public:
-    Document(const Parser& parser, const ImportSettings& settings);
+    Document(Parser& parser, const ImportSettings& settings);
 
 
     ~Document();
     ~Document();
 
 
@@ -1156,7 +1161,7 @@ private:
     const ImportSettings& settings;
     const ImportSettings& settings;
 
 
     ObjectMap objects;
     ObjectMap objects;
-    const Parser& parser;
+    Parser& parser;
 
 
     PropertyTemplateMap templates;
     PropertyTemplateMap templates;
     ConnectionMap src_connections;
     ConnectionMap src_connections;

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

@@ -360,7 +360,7 @@ void FBX::Node::EndBinary(
     bool has_children
     bool has_children
 ) {
 ) {
     // if there were children, add a null record
     // if there were children, add a null record
-    if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD); }
+    if (has_children) { s.PutString(Assimp::FBX::NULL_RECORD_STRING); }
 
 
     // now go back and write initial pos
     // now go back and write initial pos
     this->end_pos = s.Tell();
     this->end_pos = s.Tell();

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

@@ -77,8 +77,6 @@ public: // constructors
     /// The class constructor with the name.
     /// The class constructor with the name.
     Node(const std::string& n)
     Node(const std::string& n)
     : name(n)
     : name(n)
-    , properties()
-    , children()
     , force_has_children( false ) {
     , force_has_children( false ) {
         // empty
         // empty
     }
     }
@@ -87,8 +85,6 @@ public: // constructors
     template <typename... More>
     template <typename... More>
     Node(const std::string& n, More&&... more)
     Node(const std::string& n, More&&... more)
     : name(n)
     : name(n)
-    , properties()
-    , children()
     , force_has_children(false) {
     , force_has_children(false) {
         AddProperties(std::forward<More>(more)...);
         AddProperties(std::forward<More>(more)...);
     }
     }

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

@@ -62,8 +62,7 @@ namespace Assimp {
 
 
 template <>
 template <>
 const char *LogFunctions<FBXImporter>::Prefix() {
 const char *LogFunctions<FBXImporter>::Prefix() {
-	static auto prefix = "FBX: ";
-	return prefix;
+	return "FBX: ";
 }
 }
 
 
 } // namespace Assimp
 } // namespace Assimp
@@ -90,10 +89,7 @@ static const aiImporterDesc desc = {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by #Importer
 // Constructor to be privately used by #Importer
-FBXImporter::FBXImporter() :
-        mSettings() {
-    // empty
-}
+FBXImporter::FBXImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
@@ -156,19 +152,19 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 	// broad-phase tokenized pass in which we identify the core
 	// broad-phase tokenized pass in which we identify the core
 	// syntax elements of FBX (brackets, commas, key:value mappings)
 	// syntax elements of FBX (brackets, commas, key:value mappings)
 	TokenList tokens;
 	TokenList tokens;
-	try {
-
+    Assimp::StackAllocator tempAllocator;
+    try {
 		bool is_binary = false;
 		bool is_binary = false;
 		if (!strncmp(begin, "Kaydara FBX Binary", 18)) {
 		if (!strncmp(begin, "Kaydara FBX Binary", 18)) {
 			is_binary = true;
 			is_binary = true;
-			TokenizeBinary(tokens, begin, contents.size());
+            TokenizeBinary(tokens, begin, contents.size(), tempAllocator);
 		} else {
 		} else {
-			Tokenize(tokens, begin);
+            Tokenize(tokens, begin, tempAllocator);
 		}
 		}
 
 
 		// use this information to construct a very rudimentary
 		// use this information to construct a very rudimentary
 		// parse-tree representing the FBX scope structure
 		// parse-tree representing the FBX scope structure
-		Parser parser(tokens, is_binary);
+        Parser parser(tokens, tempAllocator, is_binary);
 
 
 		// take the raw parse-tree and convert it to a FBX DOM
 		// take the raw parse-tree and convert it to a FBX DOM
 		Document doc(parser, mSettings);
 		Document doc(parser, mSettings);
@@ -187,10 +183,12 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 		// assimp universal format (M)
 		// assimp universal format (M)
 		SetFileScale(size_relative_to_cm * 0.01f);
 		SetFileScale(size_relative_to_cm * 0.01f);
 
 
-		std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>());
-	} catch (std::exception &) {
-		std::for_each(tokens.begin(), tokens.end(), Util::delete_fun<Token>());
-		throw;
+		// This collection does not own the memory for the tokens, but we need to call their d'tor
+        std::for_each(tokens.begin(), tokens.end(), Util::destructor_fun<Token>());
+
+    } catch (std::exception &) {
+        std::for_each(tokens.begin(), tokens.end(), Util::destructor_fun<Token>());
+        throw;
 	}
 	}
 }
 }
 
 

+ 0 - 14
code/AssetLib/FBX/FBXMaterial.cpp

@@ -138,20 +138,6 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 Material::~Material() = default;
 Material::~Material() = default;
 
 
-    aiVector2D uvTrans;
-    aiVector2D uvScaling;
-    ai_real    uvRotation;
-
-    std::string type;
-    std::string relativeFileName;
-    std::string fileName;
-    std::string alphaSource;
-    std::shared_ptr<const PropertyTable> props;
-
-    unsigned int crop[4]{};
-
-    const Video* media;
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
 Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) :
         Object(id,element,name),
         Object(id,element,name),

+ 5 - 2
code/AssetLib/FBX/FBXMeshGeometry.cpp

@@ -69,13 +69,16 @@ Geometry::Geometry(uint64_t id, const Element& element, const std::string& name,
         }
         }
         const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
         const BlendShape* const bsp = ProcessSimpleConnection<BlendShape>(*con, false, "BlendShape -> Geometry", element);
         if (bsp) {
         if (bsp) {
-            blendShapes.push_back(bsp);
+            auto pr = blendShapes.insert(bsp);
+            if (!pr.second) {
+                FBXImporter::LogWarn("there is the same blendShape id ", bsp->ID());
+            }
         }
         }
     }
     }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-const std::vector<const BlendShape*>& Geometry::GetBlendShapes() const {
+const std::unordered_set<const BlendShape*>& Geometry::GetBlendShapes() const {
     return blendShapes;
     return blendShapes;
 }
 }
 
 

+ 51 - 35
code/AssetLib/FBX/FBXMeshGeometry.h

@@ -2,8 +2,7 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2022, assimp team
-
+Copyright (c) 2006-2023, assimp team
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -53,84 +52,101 @@ namespace Assimp {
 namespace FBX {
 namespace FBX {
 
 
 /**
 /**
- *  DOM base class for all kinds of FBX geometry
+ *  @brief DOM base class for all kinds of FBX geometry
  */
  */
 class Geometry : public Object {
 class Geometry : public Object {
 public:
 public:
     /// @brief The class constructor with all parameters.
     /// @brief The class constructor with all parameters.
     /// @param id       The id.
     /// @param id       The id.
-    /// @param element  
-    /// @param name 
-    /// @param doc 
+    /// @param element  The element instance
+    /// @param name     The name instance
+    /// @param doc      The document instance
     Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
     Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
+
+    /// @brief The class destructor, default.
     virtual ~Geometry() = default;
     virtual ~Geometry() = default;
 
 
-    /// Get the Skin attached to this geometry or nullptr
+    /// @brief Get the Skin attached to this geometry or nullptr.
+    /// @return The deformer skip instance as a pointer, nullptr if none.
     const Skin* DeformerSkin() const;
     const Skin* DeformerSkin() const;
 
 
-    /// Get the BlendShape attached to this geometry or nullptr
-    const std::vector<const BlendShape*>& GetBlendShapes() const;
+    /// @brief Get the BlendShape attached to this geometry or nullptr
+    /// @return The blendshape arrays.
+    const std::unordered_set<const BlendShape*>& GetBlendShapes() const;
 
 
 private:
 private:
     const Skin* skin;
     const Skin* skin;
-    std::vector<const BlendShape*> blendShapes;
+    std::unordered_set<const BlendShape*> blendShapes;
+
 };
 };
 
 
 typedef std::vector<int> MatIndexArray;
 typedef std::vector<int> MatIndexArray;
 
 
-
 /**
 /**
- *  DOM class for FBX geometry of type "Mesh"
+ *  @brief DOM class for FBX geometry of type "Mesh"
  */
  */
 class MeshGeometry : public Geometry {
 class MeshGeometry : public Geometry {
 public:
 public:
-    /** The class constructor */
+    /// @brief The class constructor
+    /// @param id       The id.
+    /// @param element  The element instance
+    /// @param name     The name instance
+    /// @param doc      The document instance
     MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
     MeshGeometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
 
 
-    /** The class destructor */
+    /// @brief The class destructor, default.
     virtual ~MeshGeometry() = default;
     virtual ~MeshGeometry() = default;
 
 
-    /** Get a list of all vertex points, non-unique*/
+    /// brief Get a vector of all vertex points, non-unique.
+    /// @return The vertices vector.
     const std::vector<aiVector3D>& GetVertices() const;
     const std::vector<aiVector3D>& GetVertices() const;
 
 
-    /** Get a list of all vertex normals or an empty array if
-    *  no normals are specified. */
+    /// @brief Get a vector of all vertex normals or an empty array if no normals are specified.
+    /// @return The normal vector.
     const std::vector<aiVector3D>& GetNormals() const;
     const std::vector<aiVector3D>& GetNormals() const;
 
 
-    /** Get a list of all vertex tangents or an empty array
-    *  if no tangents are specified */
+    /// @brief Get a vector of all vertex tangents or an empty array if no tangents are specified.
+    /// @return The vertex tangents vector.
     const std::vector<aiVector3D>& GetTangents() const;
     const std::vector<aiVector3D>& GetTangents() const;
 
 
-    /** Get a list of all vertex bi-normals or an empty array
-    *  if no bi-normals are specified */
+    /// @brief Get a vector of all vertex bi-normals or an empty array if no bi-normals are specified.
+    /// @return The binomal vector.
     const std::vector<aiVector3D>& GetBinormals() const;
     const std::vector<aiVector3D>& GetBinormals() const;
 
 
-    /** Return list of faces - each entry denotes a face and specifies
-    *  how many vertices it has. Vertices are taken from the
-    *  vertex data arrays in sequential order. */
+    /// @brief Return list of faces - each entry denotes a face and specifies how many vertices it has.
+    ///        Vertices are taken from the vertex data arrays in sequential order.
+    /// @return The face indices vector.
     const std::vector<unsigned int>& GetFaceIndexCounts() const;
     const std::vector<unsigned int>& GetFaceIndexCounts() const;
 
 
-    /** Get a UV coordinate slot, returns an empty array if
-    *  the requested slot does not exist. */
+    /// @brief Get a UV coordinate slot, returns an empty array if the requested slot does not exist.
+    /// @param index    The requested texture coordinate slot.
+    /// @return The texture coordinates.
     const std::vector<aiVector2D>& GetTextureCoords( unsigned int index ) const;
     const std::vector<aiVector2D>& GetTextureCoords( unsigned int index ) const;
 
 
-    /** Get a UV coordinate slot, returns an empty array if
-    *  the requested slot does not exist. */
+    /// @brief Get a UV coordinate slot, returns an empty array if the requested slot does not exist.
+    /// @param index    The requested texture coordinate slot.
+    /// @return The texture coordinate channel name.
     std::string GetTextureCoordChannelName( unsigned int index ) const;
     std::string GetTextureCoordChannelName( unsigned int index ) const;
 
 
-    /** Get a vertex color coordinate slot, returns an empty array if
-    *  the requested slot does not exist. */
+    /// @brief Get a vertex color coordinate slot, returns an empty array if the requested slot does not exist.
+    /// @param index    The requested texture coordinate slot.
+    /// @return The vertex color vector.
     const std::vector<aiColor4D>& GetVertexColors( unsigned int index ) const;
     const std::vector<aiColor4D>& GetVertexColors( unsigned int index ) const;
 
 
-    /** Get per-face-vertex material assignments */
+    /// @brief Get per-face-vertex material assignments.
+    /// @return The Material indices Array.
     const MatIndexArray& GetMaterialIndices() const;
     const MatIndexArray& GetMaterialIndices() const;
 
 
-    /** Convert from a fbx file vertex index (for example from a #Cluster weight) or nullptr
-    * if the vertex index is not valid. */
+    /// @brief Convert from a fbx file vertex index (for example from a #Cluster weight) or nullptr if the vertex index is not valid.
+    /// @param in_index   The requested input index.
+    /// @param count      The number of indices.
+    /// @return The indices.
     const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const;
     const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const;
 
 
-    /** Determine the face to which a particular output vertex index belongs.
-    *  This mapping is always unique. */
+    /// @brief Determine the face to which a particular output vertex index belongs.
+    ///        This mapping is always unique.
+    /// @param in_index   The requested input index.
+    /// @return The face-to-vertex index.
     unsigned int FaceForVertexIndex( unsigned int in_index ) const;
     unsigned int FaceForVertexIndex( unsigned int in_index ) const;
 
 
 private:
 private:

+ 37 - 14
code/AssetLib/FBX/FBXParser.cpp

@@ -88,6 +88,7 @@ namespace {
 
 
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
+    AI_WONT_RETURN void ParseError(const std::string& message, TokenPtr token) AI_WONT_RETURN_SUFFIX;
     void ParseError(const std::string& message, TokenPtr token)
     void ParseError(const std::string& message, TokenPtr token)
     {
     {
         if(token) {
         if(token) {
@@ -115,8 +116,11 @@ namespace Assimp {
 namespace FBX {
 namespace FBX {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Element::Element(const Token& key_token, Parser& parser) : key_token(key_token) {
+Element::Element(const Token& key_token, Parser& parser) :
+    key_token(key_token), compound(nullptr)
+{
     TokenPtr n = nullptr;
     TokenPtr n = nullptr;
+    StackAllocator &allocator = parser.GetAllocator();
     do {
     do {
         n = parser.AdvanceToNextToken();
         n = parser.AdvanceToNextToken();
         if(!n) {
         if(!n) {
@@ -145,7 +149,7 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token)
         }
         }
 
 
         if (n->Type() == TokenType_OPEN_BRACKET) {
         if (n->Type() == TokenType_OPEN_BRACKET) {
-            compound.reset(new Scope(parser));
+            compound = new_Scope(parser);
 
 
             // current token should be a TOK_CLOSE_BRACKET
             // current token should be a TOK_CLOSE_BRACKET
             n = parser.CurrentToken();
             n = parser.CurrentToken();
@@ -163,6 +167,15 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token)
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
+Element::~Element()
+{
+    if (compound) {
+        delete_Scope(compound);
+    }
+
+     // no need to delete tokens, they are owned by the parser
+}
+
 Scope::Scope(Parser& parser,bool topLevel)
 Scope::Scope(Parser& parser,bool topLevel)
 {
 {
     if(!topLevel) {
     if(!topLevel) {
@@ -172,6 +185,7 @@ Scope::Scope(Parser& parser,bool topLevel)
         }
         }
     }
     }
 
 
+    StackAllocator &allocator = parser.GetAllocator();
     TokenPtr n = parser.AdvanceToNextToken();
     TokenPtr n = parser.AdvanceToNextToken();
     if (n == nullptr) {
     if (n == nullptr) {
         ParseError("unexpected end of file");
         ParseError("unexpected end of file");
@@ -187,37 +201,46 @@ Scope::Scope(Parser& parser,bool topLevel)
         if (str.empty()) {
         if (str.empty()) {
             ParseError("unexpected content: empty string.");
             ParseError("unexpected content: empty string.");
         }
         }
-        
-        elements.insert(ElementMap::value_type(str,new_Element(*n,parser)));
+
+        auto *element = new_Element(*n, parser);
 
 
         // Element() should stop at the next Key token (or right after a Close token)
         // Element() should stop at the next Key token (or right after a Close token)
         n = parser.CurrentToken();
         n = parser.CurrentToken();
         if (n == nullptr) {
         if (n == nullptr) {
             if (topLevel) {
             if (topLevel) {
+                elements.insert(ElementMap::value_type(str, element));
                 return;
                 return;
             }
             }
+            delete element;
             ParseError("unexpected end of file",parser.LastToken());
             ParseError("unexpected end of file",parser.LastToken());
+        } else {
+            elements.insert(ElementMap::value_type(str, element));
         }
         }
     }
     }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Scope::~Scope() {
-    for(ElementMap::value_type& v : elements) {
-        delete v.second;
+Scope::~Scope()
+{
+	// This collection does not own the memory for the elements, but we need to call their d'tor:
+
+    for (ElementMap::value_type &v : elements) {
+        delete_Element(v.second);
     }
     }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Parser::Parser (const TokenList& tokens, bool is_binary)
-: tokens(tokens)
-, last()
-, current()
-, cursor(tokens.begin())
-, is_binary(is_binary)
+Parser::Parser(const TokenList &tokens, StackAllocator &allocator, bool is_binary) :
+        tokens(tokens), allocator(allocator), last(), current(), cursor(tokens.begin()), is_binary(is_binary)
 {
 {
     ASSIMP_LOG_DEBUG("Parsing FBX tokens");
     ASSIMP_LOG_DEBUG("Parsing FBX tokens");
-    root.reset(new Scope(*this,true));
+    root = new_Scope(*this, true);
+}
+
+// ------------------------------------------------------------------------------------------------
+Parser::~Parser()
+{
+    delete_Scope(root);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 21 - 15
code/AssetLib/FBX/FBXParser.h

@@ -52,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/LogAux.h>
 #include <assimp/LogAux.h>
 #include <assimp/fast_atof.h>
 #include <assimp/fast_atof.h>
 
 
+#include "Common/StackAllocator.h"
 #include "FBXCompileConfig.h"
 #include "FBXCompileConfig.h"
 #include "FBXTokenizer.h"
 #include "FBXTokenizer.h"
 
 
@@ -63,14 +64,14 @@ class Parser;
 class Element;
 class Element;
 
 
 // XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
 // XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
-typedef std::vector< Scope* > ScopeList;
-typedef std::fbx_unordered_multimap< std::string, Element* > ElementMap;
-
-typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> ElementCollection;
-
-#   define new_Scope new Scope
-#   define new_Element new Element
+using ScopeList = std::vector<Scope*>;
+using ElementMap = std::fbx_unordered_multimap< std::string, Element*>;
+using ElementCollection = std::pair<ElementMap::const_iterator,ElementMap::const_iterator>;
 
 
+#define new_Scope new (allocator.Allocate(sizeof(Scope))) Scope
+#define new_Element new (allocator.Allocate(sizeof(Element))) Element
+#define delete_Scope(_p) (_p)->~Scope()
+#define delete_Element(_p) (_p)->~Element()
 
 
 /** FBX data entity that consists of a key:value tuple.
 /** FBX data entity that consists of a key:value tuple.
  *
  *
@@ -82,15 +83,16 @@ typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> Element
  *  @endverbatim
  *  @endverbatim
  *
  *
  *  As can be seen in this sample, elements can contain nested #Scope
  *  As can be seen in this sample, elements can contain nested #Scope
- *  as their trailing member.  **/
+ *  as their trailing member.  
+**/
 class Element
 class Element
 {
 {
 public:
 public:
     Element(const Token& key_token, Parser& parser);
     Element(const Token& key_token, Parser& parser);
-    ~Element() = default;
+    ~Element();
 
 
     const Scope* Compound() const {
     const Scope* Compound() const {
-        return compound.get();
+        return compound;
     }
     }
 
 
     const Token& KeyToken() const {
     const Token& KeyToken() const {
@@ -104,7 +106,7 @@ public:
 private:
 private:
     const Token& key_token;
     const Token& key_token;
     TokenList tokens;
     TokenList tokens;
-    std::unique_ptr<Scope> compound;
+    Scope* compound;
 };
 };
 
 
 /** FBX data entity that consists of a 'scope', a collection
 /** FBX data entity that consists of a 'scope', a collection
@@ -159,8 +161,8 @@ class Parser
 public:
 public:
     /** Parse given a token list. Does not take ownership of the tokens -
     /** Parse given a token list. Does not take ownership of the tokens -
      *  the objects must persist during the entire parser lifetime */
      *  the objects must persist during the entire parser lifetime */
-    Parser (const TokenList& tokens,bool is_binary);
-    ~Parser() = default;
+    Parser(const TokenList &tokens, StackAllocator &allocator, bool is_binary);
+    ~Parser();
 
 
     const Scope& GetRootScope() const {
     const Scope& GetRootScope() const {
         return *root;
         return *root;
@@ -170,6 +172,10 @@ public:
         return is_binary;
         return is_binary;
     }
     }
 
 
+    StackAllocator &GetAllocator() {
+        return allocator;
+    }
+
 private:
 private:
     friend class Scope;
     friend class Scope;
     friend class Element;
     friend class Element;
@@ -180,10 +186,10 @@ private:
 
 
 private:
 private:
     const TokenList& tokens;
     const TokenList& tokens;
-
+    StackAllocator &allocator;
     TokenPtr last, current;
     TokenPtr last, current;
     TokenList::const_iterator cursor;
     TokenList::const_iterator cursor;
-    std::unique_ptr<Scope> root;
+    Scope *root;
 
 
     const bool is_binary;
     const bool is_binary;
 };
 };

+ 10 - 10
code/AssetLib/FBX/FBXTokenizer.cpp

@@ -94,7 +94,8 @@ AI_WONT_RETURN void TokenizeError(const std::string& message, unsigned int line,
 
 
 // process a potential data token up to 'cur', adding it to 'output_tokens'.
 // process a potential data token up to 'cur', adding it to 'output_tokens'.
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*& end,
+void ProcessDataToken(TokenList &output_tokens, StackAllocator &token_allocator,
+                      const char*& start, const char*& end,
                       unsigned int line,
                       unsigned int line,
                       unsigned int column,
                       unsigned int column,
                       TokenType type = TokenType_DATA,
                       TokenType type = TokenType_DATA,
@@ -131,8 +132,7 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void Tokenize(TokenList& output_tokens, const char* input)
-{
+void Tokenize(TokenList &output_tokens, const char *input, StackAllocator &token_allocator) {
 	ai_assert(input);
 	ai_assert(input);
 	ASSIMP_LOG_DEBUG("Tokenizing ASCII FBX file");
 	ASSIMP_LOG_DEBUG("Tokenizing ASCII FBX file");
 
 
@@ -164,7 +164,7 @@ void Tokenize(TokenList& output_tokens, const char* input)
                 in_double_quotes = false;
                 in_double_quotes = false;
                 token_end = cur;
                 token_end = cur;
 
 
-                ProcessDataToken(output_tokens,token_begin,token_end,line,column);
+                ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
                 pending_data_token = false;
                 pending_data_token = false;
             }
             }
             continue;
             continue;
@@ -181,30 +181,30 @@ void Tokenize(TokenList& output_tokens, const char* input)
             continue;
             continue;
 
 
         case ';':
         case ';':
-            ProcessDataToken(output_tokens,token_begin,token_end,line,column);
+            ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
             comment = true;
             comment = true;
             continue;
             continue;
 
 
         case '{':
         case '{':
-            ProcessDataToken(output_tokens,token_begin,token_end, line, column);
+            ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
             output_tokens.push_back(new_Token(cur,cur+1,TokenType_OPEN_BRACKET,line,column));
             output_tokens.push_back(new_Token(cur,cur+1,TokenType_OPEN_BRACKET,line,column));
             continue;
             continue;
 
 
         case '}':
         case '}':
-            ProcessDataToken(output_tokens,token_begin,token_end,line,column);
+            ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
             output_tokens.push_back(new_Token(cur,cur+1,TokenType_CLOSE_BRACKET,line,column));
             output_tokens.push_back(new_Token(cur,cur+1,TokenType_CLOSE_BRACKET,line,column));
             continue;
             continue;
 
 
         case ',':
         case ',':
             if (pending_data_token) {
             if (pending_data_token) {
-                ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_DATA,true);
+                ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, TokenType_DATA, true);
             }
             }
             output_tokens.push_back(new_Token(cur,cur+1,TokenType_COMMA,line,column));
             output_tokens.push_back(new_Token(cur,cur+1,TokenType_COMMA,line,column));
             continue;
             continue;
 
 
         case ':':
         case ':':
             if (pending_data_token) {
             if (pending_data_token) {
-                ProcessDataToken(output_tokens,token_begin,token_end,line,column,TokenType_KEY,true);
+                ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, TokenType_KEY, true);
             }
             }
             else {
             else {
                 TokenizeError("unexpected colon", line, column);
                 TokenizeError("unexpected colon", line, column);
@@ -226,7 +226,7 @@ void Tokenize(TokenList& output_tokens, const char* input)
                     }
                     }
                 }
                 }
 
 
-                ProcessDataToken(output_tokens,token_begin,token_end,line,column,type);
+                ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column, type);
             }
             }
 
 
             pending_data_token = false;
             pending_data_token = false;

+ 5 - 4
code/AssetLib/FBX/FBXTokenizer.h

@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_FBX_TOKENIZER_H
 #define INCLUDED_AI_FBX_TOKENIZER_H
 
 
 #include "FBXCompileConfig.h"
 #include "FBXCompileConfig.h"
+#include "Common/StackAllocator.h"
 #include <assimp/ai_assert.h>
 #include <assimp/ai_assert.h>
 #include <assimp/defs.h>
 #include <assimp/defs.h>
 #include <vector>
 #include <vector>
@@ -154,11 +155,11 @@ private:
     const unsigned int column;
     const unsigned int column;
 };
 };
 
 
-// XXX should use C++11's unique_ptr - but assimp's need to keep working with 03
 typedef const Token* TokenPtr;
 typedef const Token* TokenPtr;
 typedef std::vector< TokenPtr > TokenList;
 typedef std::vector< TokenPtr > TokenList;
 
 
-#define new_Token new Token
+#define new_Token new (token_allocator.Allocate(sizeof(Token))) Token
+#define delete_Token(_p) (_p)->~Token()
 
 
 
 
 /** Main FBX tokenizer function. Transform input buffer into a list of preprocessed tokens.
 /** Main FBX tokenizer function. Transform input buffer into a list of preprocessed tokens.
@@ -168,7 +169,7 @@ typedef std::vector< TokenPtr > TokenList;
  * @param output_tokens Receives a list of all tokens in the input data.
  * @param output_tokens Receives a list of all tokens in the input data.
  * @param input_buffer Textual input buffer to be processed, 0-terminated.
  * @param input_buffer Textual input buffer to be processed, 0-terminated.
  * @throw DeadlyImportError if something goes wrong */
  * @throw DeadlyImportError if something goes wrong */
-void Tokenize(TokenList& output_tokens, const char* input);
+void Tokenize(TokenList &output_tokens, const char *input, StackAllocator &tokenAllocator);
 
 
 
 
 /** Tokenizer function for binary FBX files.
 /** Tokenizer function for binary FBX files.
@@ -179,7 +180,7 @@ void Tokenize(TokenList& output_tokens, const char* input);
  * @param input_buffer Binary input buffer to be processed.
  * @param input_buffer Binary input buffer to be processed.
  * @param length Length of input buffer, in bytes. There is no 0-terminal.
  * @param length Length of input buffer, in bytes. There is no 0-terminal.
  * @throw DeadlyImportError if something goes wrong */
  * @throw DeadlyImportError if something goes wrong */
-void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length);
+void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length, StackAllocator &tokenAllocator);
 
 
 
 
 } // ! FBX
 } // ! FBX

+ 11 - 0
code/AssetLib/FBX/FBXUtil.h

@@ -66,6 +66,17 @@ struct delete_fun
     }
     }
 };
 };
 
 
+/** helper for std::for_each to call the destructor on all items in a container without freeing their heap*/
+template <typename T>
+struct destructor_fun {
+    void operator()(const volatile T* del) {
+        if (del) {
+            del->~T();
+        }
+    }
+};
+
+
 /** Get a string representation for a #TokenType. */
 /** Get a string representation for a #TokenType. */
 const char* TokenTypeString(TokenType t);
 const char* TokenTypeString(TokenType t);
 
 

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

@@ -327,7 +327,7 @@ void HMPImporter::CreateMaterial(const unsigned char *szCurrent,
         ReadFirstSkin(pcHeader->numskins, szCurrent, &szCurrent);
         ReadFirstSkin(pcHeader->numskins, szCurrent, &szCurrent);
         *szCurrentOut = szCurrent;
         *szCurrentOut = szCurrent;
         return;
         return;
-    } 
+    }
 
 
     // generate a default material
     // generate a default material
     const int iMode = (int)aiShadingMode_Gouraud;
     const int iMode = (int)aiShadingMode_Gouraud;
@@ -484,11 +484,11 @@ void HMPImporter::GenerateTextureCoords(const unsigned int width, const unsigned
     if (uv == nullptr) {
     if (uv == nullptr) {
         return;
         return;
     }
     }
-    
+
     if (height == 0.0f || width == 0.0) {
     if (height == 0.0f || width == 0.0) {
         return;
         return;
     }
     }
-    
+
     const float fY = (1.0f / height) + (1.0f / height) / height;
     const float fY = (1.0f / height) + (1.0f / height) / height;
     const float fX = (1.0f / width) + (1.0f / width) / width;
     const float fX = (1.0f / width) + (1.0f / width) / width;
 
 

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

@@ -86,7 +86,7 @@ protected:
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Import a HMP4 file
     /** Import a HMP4 file
     */
     */
-    void InternReadFile_HMP4();
+    AI_WONT_RETURN void InternReadFile_HMP4() AI_WONT_RETURN_SUFFIX;
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Import a HMP5 file
     /** Import a HMP5 file

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

@@ -73,8 +73,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace Assimp {
 template <>
 template <>
 const char *LogFunctions<IFCImporter>::Prefix() {
 const char *LogFunctions<IFCImporter>::Prefix() {
-    static auto prefix = "IFC: ";
-    return prefix;
+    return "IFC: ";
 }
 }
 } // namespace Assimp
 } // namespace Assimp
 
 

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

@@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "AssetLib/IFC/IFCUtil.h"
 #include "AssetLib/IFC/IFCUtil.h"
 #include "Common/PolyTools.h"
 #include "Common/PolyTools.h"
+#include "Geometry/GeometryUtils.h"
 #include "PostProcessing/ProcessHelper.h"
 #include "PostProcessing/ProcessHelper.h"
 
 
 namespace Assimp {
 namespace Assimp {
@@ -235,7 +236,7 @@ IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const {
 struct CompareVector {
 struct CompareVector {
     bool operator () (const IfcVector3& a, const IfcVector3& b) const {
     bool operator () (const IfcVector3& a, const IfcVector3& b) const {
         IfcVector3 d = a - b;
         IfcVector3 d = a - b;
-        IfcFloat eps = ai_epsilon;
+        constexpr IfcFloat eps = ai_epsilon;
         return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps);
         return d.x < -eps || (std::abs(d.x) < eps && d.y < -eps) || (std::abs(d.x) < eps && std::abs(d.y) < eps && d.z < -eps);
     }
     }
 };
 };

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

@@ -71,11 +71,7 @@ static const aiImporterDesc desc = {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
-IRRMeshImporter::IRRMeshImporter() :
-        BaseImporter(),
-        IrrlichtBase() {
-    // empty
-}
+IRRMeshImporter::IRRMeshImporter() = default;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well

+ 1 - 3
code/AssetLib/Irr/IRRShared.h

@@ -63,9 +63,7 @@ protected:
         // empty
         // empty
     }
     }
 
 
-    ~IrrlichtBase() {
-        // empty
-    }
+    ~IrrlichtBase() = default;
 
 
     /** @brief Data structure for a simple name-value property
     /** @brief Data structure for a simple name-value property
      */
      */

+ 5 - 3
code/AssetLib/LWO/LWOAnimation.cpp

@@ -162,8 +162,11 @@ void AnimResolver::UpdateAnimRangeSetup() {
         const double my_last = (*it).keys.back().time;
         const double my_last = (*it).keys.back().time;
 
 
         const double delta = my_last - my_first;
         const double delta = my_last - my_first;
-        const size_t old_size = (*it).keys.size();
+        if (delta == 0.0) {
+            continue;
+        }
 
 
+        const size_t old_size = (*it).keys.size();
         const float value_delta = (*it).keys.back().value - (*it).keys.front().value;
         const float value_delta = (*it).keys.back().value - (*it).keys.front().value;
 
 
         // NOTE: We won't handle reset, linear and constant here.
         // NOTE: We won't handle reset, linear and constant here.
@@ -176,8 +179,7 @@ void AnimResolver::UpdateAnimRangeSetup() {
         case LWO::PrePostBehaviour_Oscillate: {
         case LWO::PrePostBehaviour_Oscillate: {
             const double start_time = delta - std::fmod(my_first - first, delta);
             const double start_time = delta - std::fmod(my_first - first, delta);
             std::vector<LWO::Key>::iterator n = std::find_if((*it).keys.begin(), (*it).keys.end(),
             std::vector<LWO::Key>::iterator n = std::find_if((*it).keys.begin(), (*it).keys.end(),
-                                                    [start_time](double t) { return start_time > t; }),
-                                            m;
+                                                    [start_time](double t) { return start_time > t; }), m;
 
 
             size_t ofs = 0;
             size_t ofs = 0;
             if (n != (*it).keys.end()) {
             if (n != (*it).keys.end()) {

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

@@ -65,7 +65,6 @@ void LWOImporter::LoadLWOBFile()
         if (mFileBuffer + head.length > end)
         if (mFileBuffer + head.length > end)
         {
         {
             throw DeadlyImportError("LWOB: Invalid chunk length");
             throw DeadlyImportError("LWOB: Invalid chunk length");
-            break;
         }
         }
         uint8_t* const next = mFileBuffer+head.length;
         uint8_t* const next = mFileBuffer+head.length;
         switch (head.type)
         switch (head.type)

+ 69 - 48
code/AssetLib/LWO/LWOLoader.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2022, assimp team
 Copyright (c) 2006-2022, assimp team
 
 
-
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -51,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AssetLib/LWO/LWOLoader.h"
 #include "AssetLib/LWO/LWOLoader.h"
 #include "PostProcessing/ConvertToLHProcess.h"
 #include "PostProcessing/ConvertToLHProcess.h"
 #include "PostProcessing/ProcessHelper.h"
 #include "PostProcessing/ProcessHelper.h"
+#include "Geometry/GeometryUtils.h"
 
 
 #include <assimp/ByteSwapper.h>
 #include <assimp/ByteSwapper.h>
 #include <assimp/SGSpatialSort.h>
 #include <assimp/SGSpatialSort.h>
@@ -178,7 +177,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
     mLayers->push_back(Layer());
     mLayers->push_back(Layer());
     mCurLayer = &mLayers->back();
     mCurLayer = &mLayers->back();
     mCurLayer->mName = "<LWODefault>";
     mCurLayer->mName = "<LWODefault>";
-    mCurLayer->mIndex = (uint16_t) -1;
+    mCurLayer->mIndex = 1;
 
 
     // old lightwave file format (prior to v6)
     // old lightwave file format (prior to v6)
     mIsLWO2 = false;
     mIsLWO2 = false;
@@ -215,7 +214,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
         } else {
         } else {
             mIsLWO2 = true;
             mIsLWO2 = true;
         }
         }
-        
+
         LoadLWO2File();
         LoadLWO2File();
 
 
         // The newer lightwave format allows the user to configure the
         // The newer lightwave format allows the user to configure the
@@ -398,14 +397,6 @@ void LWOImporter::InternReadFile(const std::string &pFile,
                             pvVC[w]++;
                             pvVC[w]++;
                         }
                         }
 
 
-#if 0
-                        // process vertex weights. We can't properly reconstruct the whole skeleton for now,
-                        // but we can create dummy bones for all weight channels which we have.
-                        for (unsigned int w = 0; w < layer.mWeightChannels.size();++w)
-                        {
-                        }
-#endif
-
                         face.mIndices[q] = vert;
                         face.mIndices[q] = vert;
                     }
                     }
                     pf->mIndices = face.mIndices;
                     pf->mIndices = face.mIndices;
@@ -429,7 +420,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
         // Generate nodes to render the mesh. Store the source layer in the mParent member of the nodes
         // Generate nodes to render the mesh. Store the source layer in the mParent member of the nodes
         unsigned int num = static_cast<unsigned int>(apcMeshes.size() - meshStart);
         unsigned int num = static_cast<unsigned int>(apcMeshes.size() - meshStart);
         if (layer.mName != "<LWODefault>" || num > 0) {
         if (layer.mName != "<LWODefault>" || num > 0) {
-            aiNode *pcNode = new aiNode();
+            std::unique_ptr<aiNode> pcNode(new aiNode());
             pcNode->mName.Set(layer.mName);
             pcNode->mName.Set(layer.mName);
             pcNode->mParent = (aiNode *)&layer;
             pcNode->mParent = (aiNode *)&layer;
             pcNode->mNumMeshes = num;
             pcNode->mNumMeshes = num;
@@ -439,7 +430,8 @@ void LWOImporter::InternReadFile(const std::string &pFile,
                 for (unsigned int p = 0; p < pcNode->mNumMeshes; ++p)
                 for (unsigned int p = 0; p < pcNode->mNumMeshes; ++p)
                     pcNode->mMeshes[p] = p + meshStart;
                     pcNode->mMeshes[p] = p + meshStart;
             }
             }
-            apcNodes[layer.mIndex] = pcNode;
+            ASSIMP_LOG_DEBUG("insert apcNode for layer ", layer.mIndex, " \"", layer.mName, "\"");
+            apcNodes[layer.mIndex] = pcNode.release();
         }
         }
     }
     }
 
 
@@ -535,7 +527,6 @@ void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector<unsigned int> &
                         continue;
                         continue;
                     vNormals += v;
                     vNormals += v;
                 }
                 }
-                mesh->mNormals[idx] = vNormals.Normalize();
             }
             }
         }
         }
     }
     }
@@ -556,7 +547,6 @@ void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector<unsigned int> &
                     const aiVector3D &v = faceNormals[*a];
                     const aiVector3D &v = faceNormals[*a];
                     vNormals += v;
                     vNormals += v;
                 }
                 }
-                vNormals.Normalize();
                 for (std::vector<unsigned int>::const_iterator a = poResult.begin(); a != poResult.end(); ++a) {
                 for (std::vector<unsigned int>::const_iterator a = poResult.begin(); a != poResult.end(); ++a) {
                     mesh->mNormals[*a] = vNormals;
                     mesh->mNormals[*a] = vNormals;
                     vertexDone[*a] = true;
                     vertexDone[*a] = true;
@@ -564,6 +554,7 @@ void LWOImporter::ComputeNormals(aiMesh *mesh, const std::vector<unsigned int> &
             }
             }
         }
         }
     }
     }
+    GeometryUtils::normalizeVectorArray(mesh->mNormals, mesh->mNormals, mesh->mNumVertices);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -572,40 +563,64 @@ void LWOImporter::GenerateNodeGraph(std::map<uint16_t, aiNode *> &apcNodes) {
     aiNode *root = mScene->mRootNode = new aiNode();
     aiNode *root = mScene->mRootNode = new aiNode();
     root->mName.Set("<LWORoot>");
     root->mName.Set("<LWORoot>");
 
 
-    //Set parent of all children, inserting pivots
-    std::map<uint16_t, aiNode *> mapPivot;
-    for (auto itapcNodes = apcNodes.begin(); itapcNodes != apcNodes.end(); ++itapcNodes) {
-
-        //Get the parent index
-        LWO::Layer *nodeLayer = (LWO::Layer *)(itapcNodes->second->mParent);
-        uint16_t parentIndex = nodeLayer->mParent;
+    ASSIMP_LOG_DEBUG("apcNodes initial size: ", apcNodes.size());
+    if (!apcNodes.empty()) {
+        ASSIMP_LOG_DEBUG("first apcNode is: ", apcNodes.begin()->first, " \"", apcNodes.begin()->second->mName.C_Str(), "\"");
+    }
 
 
-        //Create pivot node, store it into the pivot map, and set the parent as the pivot
-        aiNode *pivotNode = new aiNode();
-        pivotNode->mName.Set("Pivot-" + std::string(itapcNodes->second->mName.data));
-        itapcNodes->second->mParent = pivotNode;
+    //Set parent of all children, inserting pivots
+    {
+        std::map<uint16_t, aiNode *> mapPivot;
+        for (auto itapcNodes = apcNodes.begin(); itapcNodes != apcNodes.end(); ++itapcNodes) {
+
+            //Get the parent index
+            LWO::Layer *nodeLayer = (LWO::Layer *)(itapcNodes->second->mParent);
+            uint16_t parentIndex = nodeLayer->mParent;
+
+            //Create pivot node, store it into the pivot map, and set the parent as the pivot
+            std::unique_ptr<aiNode> pivotNode(new aiNode());
+            pivotNode->mName.Set("Pivot-" + std::string(itapcNodes->second->mName.data));
+            itapcNodes->second->mParent = pivotNode.get();
+
+            //Look for the parent node to attach the pivot to
+            if (apcNodes.find(parentIndex) != apcNodes.end()) {
+                pivotNode->mParent = apcNodes[parentIndex];
+            } else {
+                //If not, attach to the root node
+                pivotNode->mParent = root;
+            }
 
 
-        //Look for the parent node to attach the pivot to
-        if (apcNodes.find(parentIndex) != apcNodes.end()) {
-            pivotNode->mParent = apcNodes[parentIndex];
-        } else {
-            //If not, attach to the root node
-            pivotNode->mParent = root;
+            //Set the node and the pivot node transformation
+            itapcNodes->second->mTransformation.a4 = -nodeLayer->mPivot.x;
+            itapcNodes->second->mTransformation.b4 = -nodeLayer->mPivot.y;
+            itapcNodes->second->mTransformation.c4 = -nodeLayer->mPivot.z;
+            pivotNode->mTransformation.a4 = nodeLayer->mPivot.x;
+            pivotNode->mTransformation.b4 = nodeLayer->mPivot.y;
+            pivotNode->mTransformation.c4 = nodeLayer->mPivot.z;
+            uint16_t pivotNodeId = static_cast<uint16_t>(-(itapcNodes->first + 2));
+            ASSIMP_LOG_DEBUG("insert pivot node: ", pivotNodeId);
+            auto oldNodeIt = mapPivot.find(pivotNodeId);
+            if (oldNodeIt != mapPivot.end()) {
+                ASSIMP_LOG_ERROR("attempted to insert pivot node which already exists in pivot map ", pivotNodeId, " \"", pivotNode->mName.C_Str(), "\"");
+            } else {
+                mapPivot.emplace(pivotNodeId, pivotNode.release());
+            }
         }
         }
 
 
-        //Set the node and the pivot node transformation
-        itapcNodes->second->mTransformation.a4 = -nodeLayer->mPivot.x;
-        itapcNodes->second->mTransformation.b4 = -nodeLayer->mPivot.y;
-        itapcNodes->second->mTransformation.c4 = -nodeLayer->mPivot.z;
-        pivotNode->mTransformation.a4 = nodeLayer->mPivot.x;
-        pivotNode->mTransformation.b4 = nodeLayer->mPivot.y;
-        pivotNode->mTransformation.c4 = nodeLayer->mPivot.z;
-        mapPivot[-(itapcNodes->first + 2)] = pivotNode;
-    }
-
-    //Merge pivot map into node map
-    for (auto itMapPivot = mapPivot.begin(); itMapPivot != mapPivot.end(); ++itMapPivot) {
-        apcNodes[itMapPivot->first] = itMapPivot->second;
+        ASSIMP_LOG_DEBUG("pivot nodes: ", mapPivot.size());
+        //Merge pivot map into node map
+        for (auto itMapPivot = mapPivot.begin(); itMapPivot != mapPivot.end();) {
+            uint16_t pivotNodeId = itMapPivot->first;
+            auto oldApcNodeIt = apcNodes.find(pivotNodeId);
+            if (oldApcNodeIt != apcNodes.end()) {
+                ASSIMP_LOG_ERROR("attempted to insert pivot node which already exists in apc nodes ", pivotNodeId, " \"", itMapPivot->second->mName.C_Str(), "\"");
+            } else {
+                apcNodes.emplace(pivotNodeId, itMapPivot->second);
+            }
+            itMapPivot->second = nullptr;
+            itMapPivot = mapPivot.erase(itMapPivot);
+        }
+        ASSIMP_LOG_DEBUG("total nodes: ", apcNodes.size());
     }
     }
 
 
     //Set children of all parents
     //Set children of all parents
@@ -627,8 +642,15 @@ void LWOImporter::GenerateNodeGraph(std::map<uint16_t, aiNode *> &apcNodes) {
         }
         }
     }
     }
 
 
-    if (!mScene->mRootNode->mNumChildren)
+    if (!mScene->mRootNode->mNumChildren) {
+        ASSIMP_LOG_DEBUG("All apcNodes:");
+        for (auto nodeIt = apcNodes.begin(); nodeIt != apcNodes.end(); ) {
+            ASSIMP_LOG_DEBUG("Node ", nodeIt->first, " \"", nodeIt->second->mName.C_Str(), "\"");
+            nodeIt->second = nullptr;
+            nodeIt = apcNodes.erase(nodeIt);
+        }
         throw DeadlyImportError("LWO: Unable to build a valid node graph");
         throw DeadlyImportError("LWO: Unable to build a valid node graph");
+    }
 
 
     // Remove a single root node with no meshes assigned to it ...
     // Remove a single root node with no meshes assigned to it ...
     if (1 == mScene->mRootNode->mNumChildren) {
     if (1 == mScene->mRootNode->mNumChildren) {
@@ -1462,7 +1484,6 @@ void LWOImporter::LoadLWO2File() {
 
 
         if (mFileBuffer + head.length > end) {
         if (mFileBuffer + head.length > end) {
             throw DeadlyImportError("LWO2: Chunk length points behind the file");
             throw DeadlyImportError("LWO2: Chunk length points behind the file");
-            break;
         }
         }
         uint8_t *const next = mFileBuffer + head.length;
         uint8_t *const next = mFileBuffer + head.length;
         mFileBuffer += bufOffset;
         mFileBuffer += bufOffset;

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

@@ -345,7 +345,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface &surf, aiMaterial *pcMat) {
 
 
     // (the diffuse value is just a scaling factor)
     // (the diffuse value is just a scaling factor)
     // If a diffuse texture is set, we set this value to 1.0
     // If a diffuse texture is set, we set this value to 1.0
-    clr = (b && false ? aiColor3D(1.0, 1.0, 1.0) : surf.mColor);
+    clr = (b ? aiColor3D(1.0, 1.0, 1.0) : surf.mColor);
     clr.r *= surf.mDiffuseValue;
     clr.r *= surf.mDiffuseValue;
     clr.g *= surf.mDiffuseValue;
     clr.g *= surf.mDiffuseValue;
     clr.b *= surf.mDiffuseValue;
     clr.b *= surf.mDiffuseValue;

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

@@ -65,7 +65,7 @@ class M3DImporter : public BaseImporter {
 public:
 public:
 	/// \brief  Default constructor
 	/// \brief  Default constructor
 	M3DImporter();
 	M3DImporter();
-    ~M3DImporter() override {}
+    ~M3DImporter() override = default;
 
 
 	/// \brief  Returns whether the class can handle the format of the given file.
 	/// \brief  Returns whether the class can handle the format of the given file.
 	/// \remark See BaseImporter::CanRead() for details.
 	/// \remark See BaseImporter::CanRead() for details.

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

@@ -39,8 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 */
 */
-#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
-#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER)
+#if !defined ASSIMP_BUILD_NO_M3D_IMPORTER || !(defined ASSIMP_BUILD_NO_EXPORT || defined ASSIMP_BUILD_NO_M3D_EXPORTER)
 
 
 #include "M3DWrapper.h"
 #include "M3DWrapper.h"
 
 
@@ -149,4 +148,3 @@ void M3DWrapper::ClearSave() {
 } // namespace Assimp
 } // namespace Assimp
 
 
 #endif
 #endif
-#endif

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

@@ -47,8 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_M3DWRAPPER_H_INC
 #ifndef AI_M3DWRAPPER_H_INC
 #define AI_M3DWRAPPER_H_INC
 #define AI_M3DWRAPPER_H_INC
 
 
-#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
-#if !(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER)  
+#if !defined ASSIMP_BUILD_NO_M3D_IMPORTER || !(defined ASSIMP_BUILD_NO_EXPORT || defined ASSIMP_BUILD_NO_M3D_EXPORTER)
 
 
 #include <memory>
 #include <memory>
 #include <vector>
 #include <vector>
@@ -126,7 +125,6 @@ inline m3d_t *M3DWrapper::M3D() const {
 
 
 } // namespace Assimp
 } // namespace Assimp
 
 
-#endif
 #endif // ASSIMP_BUILD_NO_M3D_IMPORTER
 #endif // ASSIMP_BUILD_NO_M3D_IMPORTER
 
 
 #endif // AI_M3DWRAPPER_H_INC
 #endif // AI_M3DWRAPPER_H_INC

+ 9 - 7
code/AssetLib/MD5/MD5Parser.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2022, assimp team
 Copyright (c) 2006-2022, assimp team
 
 
-
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -117,6 +115,9 @@ void MD5Parser::ParseHeader() {
         ReportError("MD5 version tag is unknown (10 is expected)");
         ReportError("MD5 version tag is unknown (10 is expected)");
     }
     }
     SkipLine();
     SkipLine();
+    if (buffer == bufferEnd) {
+        return;
+    }
 
 
     // print the command line options to the console
     // print the command line options to the console
     // FIX: can break the log length limit, so we need to be careful
     // FIX: can break the log length limit, so we need to be careful
@@ -135,8 +136,9 @@ bool MD5Parser::ParseSection(Section &out) {
 
 
     // first parse the name of the section
     // first parse the name of the section
     char *sz = buffer;
     char *sz = buffer;
-    while (!IsSpaceOrNewLine(*buffer))
-        buffer++;
+    while (!IsSpaceOrNewLine(*buffer)) {
+        ++buffer;
+    }
     out.mName = std::string(sz, (uintptr_t)(buffer - sz));
     out.mName = std::string(sz, (uintptr_t)(buffer - sz));
     SkipSpaces();
     SkipSpaces();
 
 
@@ -144,14 +146,14 @@ bool MD5Parser::ParseSection(Section &out) {
     while (running) {
     while (running) {
         if ('{' == *buffer) {
         if ('{' == *buffer) {
             // it is a normal section so read all lines
             // it is a normal section so read all lines
-            buffer++;
+            ++buffer;
             bool run = true;
             bool run = true;
             while (run) {
             while (run) {
                 if (!SkipSpacesAndLineEnd()) {
                 if (!SkipSpacesAndLineEnd()) {
                     return false; // seems this was the last section
                     return false; // seems this was the last section
                 }
                 }
                 if ('}' == *buffer) {
                 if ('}' == *buffer) {
-                    buffer++;
+                    ++buffer;
                     break;
                     break;
                 }
                 }
 
 
@@ -163,7 +165,7 @@ bool MD5Parser::ParseSection(Section &out) {
 
 
                 // terminate the line with zero
                 // terminate the line with zero
                 while (!IsLineEnd(*buffer))
                 while (!IsLineEnd(*buffer))
-                    buffer++;
+                    ++buffer;
                 if (*buffer) {
                 if (*buffer) {
                     ++lineNumber;
                     ++lineNumber;
                     *buffer++ = '\0';
                     *buffer++ = '\0';

+ 5 - 4
code/AssetLib/MD5/MD5Parser.h

@@ -365,9 +365,7 @@ public:
     static void ReportWarning (const char* warn, unsigned int line);
     static void ReportWarning (const char* warn, unsigned int line);
 
 
 
 
-    void ReportError (const char* error) {
-        return ReportError(error, lineNumber);
-    }
+    AI_WONT_RETURN void ReportError (const char* error) AI_WONT_RETURN_SUFFIX;
 
 
     void ReportWarning (const char* warn) {
     void ReportWarning (const char* warn) {
         return ReportWarning(warn, lineNumber);
         return ReportWarning(warn, lineNumber);
@@ -394,7 +392,7 @@ private:
 
 
     bool SkipLine(const char* in, const char** out);
     bool SkipLine(const char* in, const char** out);
     bool SkipLine( );
     bool SkipLine( );
-    bool SkipSpacesAndLineEnd( const char* in, const char** out);    
+    bool SkipSpacesAndLineEnd( const char* in, const char** out);
     bool SkipSpacesAndLineEnd();
     bool SkipSpacesAndLineEnd();
     bool SkipSpaces();
     bool SkipSpaces();
 
 
@@ -404,6 +402,9 @@ private:
     unsigned int lineNumber;
     unsigned int lineNumber;
 };
 };
 
 
+inline void MD5Parser::ReportError(const char* error) {
+    ReportError(error, lineNumber);
+}
 // -------------------------------------------------------------------
 // -------------------------------------------------------------------
 inline bool MD5Parser::SkipLine(const char* in, const char** out) {
 inline bool MD5Parser::SkipLine(const char* in, const char** out) {
     ++lineNumber;
     ++lineNumber;

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

@@ -470,14 +470,16 @@ void HL1MDLLoader::read_bones() {
 
 
     temp_bones_.resize(header_->numbones);
     temp_bones_.resize(header_->numbones);
 
 
+    // Create the main 'bones' node that will contain all MDL root bones.
     aiNode *bones_node = new aiNode(AI_MDL_HL1_NODE_BONES);
     aiNode *bones_node = new aiNode(AI_MDL_HL1_NODE_BONES);
     rootnode_children_.push_back(bones_node);
     rootnode_children_.push_back(bones_node);
-    bones_node->mNumChildren = static_cast<unsigned int>(header_->numbones);
-    bones_node->mChildren = new aiNode *[bones_node->mNumChildren];
+
+    // Store roots bones IDs temporarily.
+    std::vector<int> roots;
 
 
     // Create bone matrices in local space.
     // Create bone matrices in local space.
     for (int i = 0; i < header_->numbones; ++i) {
     for (int i = 0; i < header_->numbones; ++i) {
-        aiNode *bone_node = temp_bones_[i].node = bones_node->mChildren[i] = new aiNode(unique_bones_names[i]);
+        aiNode *bone_node = temp_bones_[i].node = new aiNode(unique_bones_names[i]);
 
 
         aiVector3D angles(pbone[i].value[3], pbone[i].value[4], pbone[i].value[5]);
         aiVector3D angles(pbone[i].value[3], pbone[i].value[4], pbone[i].value[5]);
         temp_bones_[i].absolute_transform = bone_node->mTransformation =
         temp_bones_[i].absolute_transform = bone_node->mTransformation =
@@ -485,9 +487,11 @@ void HL1MDLLoader::read_bones() {
                         aiVector3D(pbone[i].value[0], pbone[i].value[1], pbone[i].value[2]));
                         aiVector3D(pbone[i].value[0], pbone[i].value[1], pbone[i].value[2]));
 
 
         if (pbone[i].parent == -1) {
         if (pbone[i].parent == -1) {
-            bone_node->mParent = scene_->mRootNode;
+            bone_node->mParent = bones_node;
+            roots.push_back(i); // This bone has no parent. Add it to the roots list.
         } else {
         } else {
-            bone_node->mParent = bones_node->mChildren[pbone[i].parent];
+            bone_node->mParent = temp_bones_[pbone[i].parent].node;
+            temp_bones_[pbone[i].parent].children.push_back(i); // Add this bone to the parent bone's children list.
 
 
             temp_bones_[i].absolute_transform =
             temp_bones_[i].absolute_transform =
                     temp_bones_[pbone[i].parent].absolute_transform * bone_node->mTransformation;
                     temp_bones_[pbone[i].parent].absolute_transform * bone_node->mTransformation;
@@ -496,6 +500,36 @@ void HL1MDLLoader::read_bones() {
         temp_bones_[i].offset_matrix = temp_bones_[i].absolute_transform;
         temp_bones_[i].offset_matrix = temp_bones_[i].absolute_transform;
         temp_bones_[i].offset_matrix.Inverse();
         temp_bones_[i].offset_matrix.Inverse();
     }
     }
+
+    // Allocate memory for each MDL root bone.
+    bones_node->mNumChildren = static_cast<unsigned int>(roots.size());
+    bones_node->mChildren = new aiNode *[bones_node->mNumChildren];
+
+    // Build all bones children hierarchy starting from each MDL root bone.
+    for (size_t i = 0; i < roots.size(); ++i)
+    {
+        const TempBone &root_bone = temp_bones_[roots[i]];
+        bones_node->mChildren[i] = root_bone.node;
+        build_bone_children_hierarchy(root_bone);
+    }
+}
+
+void HL1MDLLoader::build_bone_children_hierarchy(const TempBone &bone)
+{
+    if (bone.children.empty())
+        return;
+
+    aiNode* bone_node = bone.node;
+    bone_node->mNumChildren = static_cast<unsigned int>(bone.children.size());
+    bone_node->mChildren = new aiNode *[bone_node->mNumChildren];
+
+    // Build each child bone's hierarchy recursively.
+    for (size_t i = 0; i < bone.children.size(); ++i)
+    {
+        const TempBone &child_bone = temp_bones_[bone.children[i]];
+        bone_node->mChildren[i] = child_bone.node;
+        build_bone_children_hierarchy(child_bone);
+    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 11 - 1
code/AssetLib/MDL/HalfLife/HL1MDLLoader.h

@@ -143,6 +143,14 @@ private:
      */
      */
     static bool get_num_blend_controllers(const int num_blend_animations, int &num_blend_controllers);
     static bool get_num_blend_controllers(const int num_blend_animations, int &num_blend_controllers);
 
 
+    /**
+     *  \brief Build a bone's node children hierarchy.
+     *
+     * \param[in] bone The bone for which we must build all children hierarchy.
+     */
+    struct TempBone;
+    void build_bone_children_hierarchy(const TempBone& bone);
+
     /** Output scene to be filled */
     /** Output scene to be filled */
     aiScene *scene_;
     aiScene *scene_;
 
 
@@ -198,11 +206,13 @@ private:
         TempBone() :
         TempBone() :
             node(nullptr),
             node(nullptr),
             absolute_transform(),
             absolute_transform(),
-            offset_matrix() {}
+            offset_matrix(),
+            children() {}
 
 
         aiNode *node;
         aiNode *node;
         aiMatrix4x4 absolute_transform;
         aiMatrix4x4 absolute_transform;
         aiMatrix4x4 offset_matrix;
         aiMatrix4x4 offset_matrix;
+        std::vector<int> children; // Bone children
     };
     };
 
 
     std::vector<TempBone> temp_bones_;
     std::vector<TempBone> temp_bones_;

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

@@ -975,7 +975,7 @@ void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones)
                     }
                     }
 
 
                     // store the name of the bone
                     // store the name of the bone
-                    pcOutBone->mName.length = (size_t)iMaxLen;
+                    pcOutBone->mName.length = static_cast<ai_uint32>(iMaxLen);
                     ::memcpy(pcOutBone->mName.data, pcBone->name, pcOutBone->mName.length);
                     ::memcpy(pcOutBone->mName.data, pcBone->name, pcOutBone->mName.length);
                     pcOutBone->mName.data[pcOutBone->mName.length] = '\0';
                     pcOutBone->mName.data[pcOutBone->mName.length] = '\0';
                 }
                 }

+ 1 - 1
code/AssetLib/MDL/MDLLoader.h

@@ -139,7 +139,7 @@ protected:
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Import a CS:S/HL2 MDL file (not fully implemented)
     /** Import a CS:S/HL2 MDL file (not fully implemented)
     */
     */
-    void InternReadFile_HL2( );
+    AI_WONT_RETURN void InternReadFile_HL2( ) AI_WONT_RETURN_SUFFIX;
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Check whether a given position is inside the valid range
     /** Check whether a given position is inside the valid range

+ 1 - 1
code/AssetLib/MDL/MDLMaterialLoader.cpp

@@ -470,7 +470,7 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
             ASSIMP_LOG_ERROR("Found a reference to an embedded DDS texture, but texture width is zero, aborting import.");
             ASSIMP_LOG_ERROR("Found a reference to an embedded DDS texture, but texture width is zero, aborting import.");
             return;
             return;
         }
         }
-        
+
         pcNew.reset(new aiTexture);
         pcNew.reset(new aiTexture);
         pcNew->mHeight = 0;
         pcNew->mHeight = 0;
         pcNew->mWidth = iWidth;
         pcNew->mWidth = iWidth;

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

@@ -269,7 +269,7 @@ aiMesh *MMDImporter::CreateMesh(const pmx::PmxModel *pModel,
                 dynamic_cast<pmx::PmxVertexSkinningSDEF *>(v->skinning.get());
                 dynamic_cast<pmx::PmxVertexSkinningSDEF *>(v->skinning.get());
         switch (v->skinning_type) {
         switch (v->skinning_type) {
         case pmx::PmxVertexSkinningType::BDEF1:
         case pmx::PmxVertexSkinningType::BDEF1:
-            bone_vertex_map[vsBDEF1_ptr->bone_index].emplace_back(index, 1.0);
+            bone_vertex_map[vsBDEF1_ptr->bone_index].emplace_back(index, static_cast<ai_real>(1));
             break;
             break;
         case pmx::PmxVertexSkinningType::BDEF2:
         case pmx::PmxVertexSkinningType::BDEF2:
             bone_vertex_map[vsBDEF2_ptr->bone_index1].emplace_back(index, vsBDEF2_ptr->bone_weight);
             bone_vertex_map[vsBDEF2_ptr->bone_index1].emplace_back(index, vsBDEF2_ptr->bone_weight);

+ 2 - 1
code/AssetLib/MMD/MMDPmxParser.h

@@ -46,6 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <iostream>
 #include <iostream>
 #include <fstream>
 #include <fstream>
 #include <memory>
 #include <memory>
+#include <assimp/types.h>
 #include "MMDCpp14.h"
 #include "MMDCpp14.h"
 
 
 namespace pmx
 namespace pmx
@@ -730,7 +731,7 @@ namespace pmx
 		std::unique_ptr<PmxAncherRigidBody []> anchers;
 		std::unique_ptr<PmxAncherRigidBody []> anchers;
 		int pin_vertex_count;
 		int pin_vertex_count;
 		std::unique_ptr<int []> pin_vertices;
 		std::unique_ptr<int []> pin_vertices;
-		void Read(std::istream *stream, PmxSetting *setting);
+		AI_WONT_RETURN void Read(std::istream *stream, PmxSetting *setting) AI_WONT_RETURN_SUFFIX;
 	};
 	};
 
 
 	class PmxModel
 	class PmxModel

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

@@ -486,7 +486,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
 
 
         for (unsigned int j = 0,n = 0; j < m->mNumFaces; ++j) {
         for (unsigned int j = 0,n = 0; j < m->mNumFaces; ++j) {
             aiFace& f = m->mFaces[j];
             aiFace& f = m->mFaces[j];
-            if (g.triangles[j]>triangles.size()) {
+            if (g.triangles[j] >= triangles.size()) {
                 throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed");
                 throw DeadlyImportError("MS3D: Encountered invalid triangle index, file is malformed");
             }
             }
 
 
@@ -494,7 +494,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
             f.mIndices = new unsigned int[f.mNumIndices=3];
             f.mIndices = new unsigned int[f.mNumIndices=3];
 
 
             for (unsigned int k = 0; k < 3; ++k,++n) {
             for (unsigned int k = 0; k < 3; ++k,++n) {
-                if (t.indices[k]>vertices.size()) {
+                if (t.indices[k] >= vertices.size()) {
                     throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed");
                     throw DeadlyImportError("MS3D: Encountered invalid vertex index, file is malformed");
                 }
                 }
 
 

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

@@ -107,7 +107,7 @@ private:
 
 
         aiColor3D color, diffuse, specular, ambient, emissive;
         aiColor3D color, diffuse, specular, ambient, emissive;
         ai_real refracti;
         ai_real refracti;
-        std::string texFile;        
+        std::string texFile;
         bool twoSided; // For NFF2
         bool twoSided; // For NFF2
         bool shaded;
         bool shaded;
         ai_real opacity, shininess;
         ai_real opacity, shininess;

+ 4 - 3
code/AssetLib/OFF/OFFLoader.cpp

@@ -290,11 +290,12 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
         sz = line; SkipSpaces(&sz);
         sz = line; SkipSpaces(&sz);
         idx = strtoul10(sz,&sz);
         idx = strtoul10(sz,&sz);
         if(!idx || idx > 9) {
         if(!idx || idx > 9) {
-	    ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed");
+	        ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed");
             --mesh->mNumFaces;
             --mesh->mNumFaces;
+            ++i;
             continue;
             continue;
-	}
-	faces->mNumIndices = idx;
+	    }
+	    faces->mNumIndices = idx;
         faces->mIndices = new unsigned int[faces->mNumIndices];
         faces->mIndices = new unsigned int[faces->mNumIndices];
         for (unsigned int m = 0; m < faces->mNumIndices;++m) {
         for (unsigned int m = 0; m < faces->mNumIndices;++m) {
             SkipSpaces(&sz);
             SkipSpaces(&sz);

+ 5 - 7
code/AssetLib/Obj/ObjFileImporter.cpp

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2020, assimp team
+Copyright (c) 2006-2023, assimp team
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -84,7 +84,6 @@ ObjFileImporter::ObjFileImporter() :
 //  Destructor.
 //  Destructor.
 ObjFileImporter::~ObjFileImporter() {
 ObjFileImporter::~ObjFileImporter() {
     delete m_pRootObject;
     delete m_pRootObject;
-    m_pRootObject = nullptr;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -270,7 +269,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
     for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) {
     for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) {
         unsigned int meshId = pObject->m_Meshes[i];
         unsigned int meshId = pObject->m_Meshes[i];
         aiMesh *pMesh = createTopology(pModel, pObject, meshId);
         aiMesh *pMesh = createTopology(pModel, pObject, meshId);
-        if (pMesh) {
+        if (pMesh != nullptr) {
             if (pMesh->mNumFaces > 0) {
             if (pMesh->mNumFaces > 0) {
                 MeshArray.push_back(pMesh);
                 MeshArray.push_back(pMesh);
             } else {
             } else {
@@ -324,14 +323,13 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
         return nullptr;
         return nullptr;
     }
     }
 
 
-    std::unique_ptr<aiMesh> pMesh(new aiMesh);
+    aiMesh *pMesh = new aiMesh;
     if (!pObjMesh->m_name.empty()) {
     if (!pObjMesh->m_name.empty()) {
         pMesh->mName.Set(pObjMesh->m_name);
         pMesh->mName.Set(pObjMesh->m_name);
     }
     }
 
 
     for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
     for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
         const ObjFile::Face *inp = pObjMesh->m_Faces[index];
         const ObjFile::Face *inp = pObjMesh->m_Faces[index];
-        //ai_assert(nullptr != inp);
 
 
         if (inp->mPrimitiveType == aiPrimitiveType_LINE) {
         if (inp->mPrimitiveType == aiPrimitiveType_LINE) {
             pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size() - 1);
             pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size() - 1);
@@ -387,9 +385,9 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
     }
     }
 
 
     // Create mesh vertices
     // Create mesh vertices
-    createVertexArray(pModel, pData, meshIndex, pMesh.get(), uiIdxCount);
+    createVertexArray(pModel, pData, meshIndex, pMesh, uiIdxCount);
 
 
-    return pMesh.release();
+    return pMesh;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 5 - 5
code/AssetLib/Obj/ObjFileMtlImporter.cpp

@@ -514,16 +514,16 @@ void ObjFileMtlImporter::getTextureOption(bool &clamp, int &clampIndex, aiString
             DataArrayIt it = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
             DataArrayIt it = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
             getFloat(it, m_DataItEnd, m_pModel->mCurrentMaterial->bump_multiplier);
             getFloat(it, m_DataItEnd, m_pModel->mCurrentMaterial->bump_multiplier);
             skipToken = 2;
             skipToken = 2;
-        } else if (!ASSIMP_strincmp(pPtr, BlendUOption, static_cast<unsigned int>(strlen(BlendUOption))) || 
+        } else if (!ASSIMP_strincmp(pPtr, BlendUOption, static_cast<unsigned int>(strlen(BlendUOption))) ||
                 !ASSIMP_strincmp(pPtr, BlendVOption, static_cast<unsigned int>(strlen(BlendVOption))) ||
                 !ASSIMP_strincmp(pPtr, BlendVOption, static_cast<unsigned int>(strlen(BlendVOption))) ||
-                !ASSIMP_strincmp(pPtr, BoostOption, static_cast<unsigned int>(strlen(BoostOption))) || 
-                !ASSIMP_strincmp(pPtr, ResolutionOption, static_cast<unsigned int>(strlen(ResolutionOption))) || 
+                !ASSIMP_strincmp(pPtr, BoostOption, static_cast<unsigned int>(strlen(BoostOption))) ||
+                !ASSIMP_strincmp(pPtr, ResolutionOption, static_cast<unsigned int>(strlen(ResolutionOption))) ||
                 !ASSIMP_strincmp(pPtr, ChannelOption, static_cast<unsigned int>(strlen(ChannelOption)))) {
                 !ASSIMP_strincmp(pPtr, ChannelOption, static_cast<unsigned int>(strlen(ChannelOption)))) {
             skipToken = 2;
             skipToken = 2;
         } else if (!ASSIMP_strincmp(pPtr, ModifyMapOption, static_cast<unsigned int>(strlen(ModifyMapOption)))) {
         } else if (!ASSIMP_strincmp(pPtr, ModifyMapOption, static_cast<unsigned int>(strlen(ModifyMapOption)))) {
             skipToken = 3;
             skipToken = 3;
-        } else if (!ASSIMP_strincmp(pPtr, OffsetOption, static_cast<unsigned int>(strlen(OffsetOption))) || 
-                !ASSIMP_strincmp(pPtr, ScaleOption, static_cast<unsigned int>(strlen(ScaleOption))) || 
+        } else if (!ASSIMP_strincmp(pPtr, OffsetOption, static_cast<unsigned int>(strlen(OffsetOption))) ||
+                !ASSIMP_strincmp(pPtr, ScaleOption, static_cast<unsigned int>(strlen(ScaleOption))) ||
                 !ASSIMP_strincmp(pPtr, TurbulenceOption, static_cast<unsigned int>(strlen(TurbulenceOption)))) {
                 !ASSIMP_strincmp(pPtr, TurbulenceOption, static_cast<unsigned int>(strlen(TurbulenceOption)))) {
             skipToken = 4;
             skipToken = 4;
         }
         }

+ 3 - 3
code/AssetLib/Obj/ObjFileParser.cpp

@@ -236,7 +236,7 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
             getNameNoSpace(m_DataIt, m_DataItEnd, name);
             getNameNoSpace(m_DataIt, m_DataItEnd, name);
             insideCstype = name == "cstype";
             insideCstype = name == "cstype";
             goto pf_skip_line;
             goto pf_skip_line;
-        } break;
+        }
 
 
         default: {
         default: {
         pf_skip_line:
         pf_skip_line:
@@ -440,7 +440,7 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
     const bool vt = (!m_pModel->mTextureCoord.empty());
     const bool vt = (!m_pModel->mTextureCoord.empty());
     const bool vn = (!m_pModel->mNormals.empty());
     const bool vn = (!m_pModel->mNormals.empty());
     int iPos = 0;
     int iPos = 0;
-    while (m_DataIt != m_DataItEnd) {
+    while (m_DataIt < m_DataItEnd) {
         int iStep = 1;
         int iStep = 1;
 
 
         if (IsLineEnd(*m_DataIt)) {
         if (IsLineEnd(*m_DataIt)) {
@@ -458,7 +458,7 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
             //OBJ USES 1 Base ARRAYS!!!!
             //OBJ USES 1 Base ARRAYS!!!!
             const char *token = &(*m_DataIt);
             const char *token = &(*m_DataIt);
             const int iVal = ::atoi(token);
             const int iVal = ::atoi(token);
-            
+
             // increment iStep position based off of the sign and # of digits
             // increment iStep position based off of the sign and # of digits
             int tmp = iVal;
             int tmp = iVal;
             if (iVal < 0) {
             if (iVal < 0) {

+ 17 - 13
code/AssetLib/Obj/ObjTools.h

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2021, assimp team
+Copyright (c) 2006-2022, assimp team
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 namespace Assimp {
 namespace Assimp {
 
 
-/** 
+/**
  *  @brief  Returns true, if the last entry of the buffer is reached.
  *  @brief  Returns true, if the last entry of the buffer is reached.
  *  @param[in] it   Iterator of current position.
  *  @param[in] it   Iterator of current position.
  *  @param[in] end  Iterator with end of buffer.
  *  @param[in] end  Iterator with end of buffer.
@@ -67,7 +67,7 @@ inline bool isEndOfBuffer(char_t it, char_t end) {
     return (it == end);
     return (it == end);
 }
 }
 
 
-/** 
+/**
  *  @brief  Returns next word separated by a space
  *  @brief  Returns next word separated by a space
  *  @param[in] pBuffer  Pointer to data buffer
  *  @param[in] pBuffer  Pointer to data buffer
  *  @param[in] pEnd     Pointer to end of buffer
  *  @param[in] pEnd     Pointer to end of buffer
@@ -85,7 +85,7 @@ inline Char_T getNextWord(Char_T pBuffer, Char_T pEnd) {
     return pBuffer;
     return pBuffer;
 }
 }
 
 
-/** 
+/**
  *  @brief  Returns pointer a next token
  *  @brief  Returns pointer a next token
  *  @param[in] pBuffer  Pointer to data buffer
  *  @param[in] pBuffer  Pointer to data buffer
  *  @param[in] pEnd     Pointer to end of buffer
  *  @param[in] pEnd     Pointer to end of buffer
@@ -102,7 +102,7 @@ inline Char_T getNextToken(Char_T pBuffer, Char_T pEnd) {
     return getNextWord(pBuffer, pEnd);
     return getNextWord(pBuffer, pEnd);
 }
 }
 
 
-/** 
+/**
  *  @brief  Skips a line
  *  @brief  Skips a line
  *  @param[in]  it      Iterator set to current position
  *  @param[in]  it      Iterator set to current position
  *  @param[in]  end     Iterator set to end of scratch buffer for readout
  *  @param[in]  end     Iterator set to end of scratch buffer for readout
@@ -111,6 +111,10 @@ inline Char_T getNextToken(Char_T pBuffer, Char_T pEnd) {
  */
  */
 template <class char_t>
 template <class char_t>
 inline char_t skipLine(char_t it, char_t end, unsigned int &uiLine) {
 inline char_t skipLine(char_t it, char_t end, unsigned int &uiLine) {
+    if (it >= end) {
+        return it;
+    }
+
     while (!isEndOfBuffer(it, end) && !IsLineEnd(*it)) {
     while (!isEndOfBuffer(it, end) && !IsLineEnd(*it)) {
         ++it;
         ++it;
     }
     }
@@ -127,9 +131,9 @@ inline char_t skipLine(char_t it, char_t end, unsigned int &uiLine) {
     return it;
     return it;
 }
 }
 
 
-/** 
+/**
  *  @brief  Get a name from the current line. Preserve space in the middle,
  *  @brief  Get a name from the current line. Preserve space in the middle,
- *    but trim it at the end.
+ *          but trim it at the end.
  *  @param[in]  it      set to current position
  *  @param[in]  it      set to current position
  *  @param[in]  end     set to end of scratch buffer for readout
  *  @param[in]  end     set to end of scratch buffer for readout
  *  @param[out] name    Separated name
  *  @param[out] name    Separated name
@@ -158,13 +162,13 @@ inline char_t getName(char_t it, char_t end, std::string &name) {
     std::string strName(pStart, &(*it));
     std::string strName(pStart, &(*it));
     if (!strName.empty()) {
     if (!strName.empty()) {
         name = strName;
         name = strName;
-    } 
-    
+    }
+
 
 
     return it;
     return it;
 }
 }
 
 
-/** 
+/**
  *  @brief  Get a name from the current line. Do not preserve space
  *  @brief  Get a name from the current line. Do not preserve space
  *    in the middle, but trim it at the end.
  *    in the middle, but trim it at the end.
  *  @param  it      set to current position
  *  @param  it      set to current position
@@ -198,11 +202,11 @@ inline char_t getNameNoSpace(char_t it, char_t end, std::string &name) {
     if (!strName.empty()) {
     if (!strName.empty()) {
         name = strName;
         name = strName;
     }
     }
-        
+
     return it;
     return it;
 }
 }
 
 
-/** 
+/**
  *  @brief  Get next word from given line
  *  @brief  Get next word from given line
  *  @param[in] it      set to current position
  *  @param[in] it      set to current position
  *  @param[in] end     set to end of scratch buffer for readout
  *  @param[in] end     set to end of scratch buffer for readout
@@ -226,7 +230,7 @@ inline char_t CopyNextWord(char_t it, char_t end, char *pBuffer, size_t length)
     return it;
     return it;
 }
 }
 
 
-/** 
+/**
  *  @brief  Get next float from given line
  *  @brief  Get next float from given line
  *  @param[in]  it      set to current position
  *  @param[in]  it      set to current position
  *  @param[in]  end     set to end of scratch buffer for readout
  *  @param[in]  end     set to end of scratch buffer for readout

+ 4 - 4
code/AssetLib/Ogre/OgreImporter.h

@@ -60,17 +60,17 @@ namespace Ogre {
 class OgreImporter : public BaseImporter {
 class OgreImporter : public BaseImporter {
 public:
 public:
     /// BaseImporter override.
     /// BaseImporter override.
-    virtual bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
 
 
 protected:
 protected:
     /// BaseImporter override.
     /// BaseImporter override.
-    virtual void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
+    void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
 
 
     /// BaseImporter override.
     /// BaseImporter override.
-    virtual const aiImporterDesc *GetInfo() const override;
+    const aiImporterDesc *GetInfo() const override;
 
 
     /// BaseImporter override.
     /// BaseImporter override.
-    virtual void SetupProperties(const Importer *pImp) override;
+    void SetupProperties(const Importer *pImp) override;
 
 
 private:
 private:
     /// Read materials referenced by the @c mesh to @c pScene.
     /// Read materials referenced by the @c mesh to @c pScene.

+ 2 - 3
code/AssetLib/Ogre/OgreXmlSerializer.cpp

@@ -57,7 +57,7 @@ namespace Assimp {
 namespace Ogre {
 namespace Ogre {
 
 
 //AI_WONT_RETURN void ThrowAttibuteError(const XmlParser *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
 //AI_WONT_RETURN void ThrowAttibuteError(const XmlParser *reader, const std::string &name, const std::string &error = "") AI_WONT_RETURN_SUFFIX;
-
+AI_WONT_RETURN void ThrowAttibuteError(const std::string &nodeName, const std::string &name, const std::string &error) AI_WONT_RETURN_SUFFIX;
 AI_WONT_RETURN void ThrowAttibuteError(const std::string &nodeName, const std::string &name, const std::string &error) {
 AI_WONT_RETURN void ThrowAttibuteError(const std::string &nodeName, const std::string &name, const std::string &error) {
     if (!error.empty()) {
     if (!error.empty()) {
         throw DeadlyImportError(error, " in node '", nodeName, "' and attribute '", name, "'");
         throw DeadlyImportError(error, " in node '", nodeName, "' and attribute '", name, "'");
@@ -128,7 +128,6 @@ bool OgreXmlSerializer::ReadAttribute<bool>(XmlNode &xmlNode, const char *name)
     }
     }
 
 
     ThrowAttibuteError(xmlNode.name(), name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
     ThrowAttibuteError(xmlNode.name(), name, "Boolean value is expected to be 'true' or 'false', encountered '" + value + "'");
-    return false;
 }
 }
 
 
 // Mesh XML constants
 // Mesh XML constants
@@ -490,7 +489,7 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *me
     OgreXmlSerializer serializer(xmlParser.get());
     OgreXmlSerializer serializer(xmlParser.get());
     XmlNode root = xmlParser->getRootNode();
     XmlNode root = xmlParser->getRootNode();
     if (std::string(root.name()) != nnSkeleton) {
     if (std::string(root.name()) != nnSkeleton) {
-        printf("\nSkeleton is not a valid root: %s\n", root.name());
+        ASSIMP_LOG_VERBOSE_DEBUG("nSkeleton is not a valid root: ", root.name(), ".");
         for (auto &a : root.children()) {
         for (auto &a : root.children()) {
             if (std::string(a.name()) == nnSkeleton) {
             if (std::string(a.name()) == nnSkeleton) {
                 root = a;
                 root = a;

+ 0 - 10
code/AssetLib/OpenGEX/OpenGEXImporter.cpp

@@ -261,7 +261,6 @@ OpenGEXImporter::RefInfo::RefInfo(aiNode *node, Type type, std::vector<std::stri
 OpenGEXImporter::OpenGEXImporter() :
 OpenGEXImporter::OpenGEXImporter() :
         m_root(nullptr),
         m_root(nullptr),
         m_nodeChildMap(),
         m_nodeChildMap(),
-        m_meshCache(),
         m_mesh2refMap(),
         m_mesh2refMap(),
         m_material2refMap(),
         m_material2refMap(),
         m_ctx(nullptr),
         m_ctx(nullptr),
@@ -461,14 +460,12 @@ void OpenGEXImporter::handleMetricNode(DDLNode *node, aiScene * /*pScene*/) {
 void OpenGEXImporter::handleNameNode(DDLNode *node, aiScene * /*pScene*/) {
 void OpenGEXImporter::handleNameNode(DDLNode *node, aiScene * /*pScene*/) {
     if (nullptr == m_currentNode) {
     if (nullptr == m_currentNode) {
         throw DeadlyImportError("No current node for name.");
         throw DeadlyImportError("No current node for name.");
-        return;
     }
     }
 
 
     Value *val(node->getValue());
     Value *val(node->getValue());
     if (nullptr != val) {
     if (nullptr != val) {
         if (Value::ValueType::ddl_string != val->m_type) {
         if (Value::ValueType::ddl_string != val->m_type) {
             throw DeadlyImportError("OpenGEX: invalid data type for value in node name.");
             throw DeadlyImportError("OpenGEX: invalid data type for value in node name.");
-            return;
         }
         }
 
 
         const std::string name(val->getString());
         const std::string name(val->getString());
@@ -509,7 +506,6 @@ static void getRefNames(DDLNode *node, std::vector<std::string> &names) {
 void OpenGEXImporter::handleObjectRefNode(DDLNode *node, aiScene * /*pScene*/) {
 void OpenGEXImporter::handleObjectRefNode(DDLNode *node, aiScene * /*pScene*/) {
     if (nullptr == m_currentNode) {
     if (nullptr == m_currentNode) {
         throw DeadlyImportError("No parent node for name.");
         throw DeadlyImportError("No parent node for name.");
-        return;
     }
     }
 
 
     std::vector<std::string> objRefNames;
     std::vector<std::string> objRefNames;
@@ -533,7 +529,6 @@ void OpenGEXImporter::handleObjectRefNode(DDLNode *node, aiScene * /*pScene*/) {
 void OpenGEXImporter::handleMaterialRefNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
 void OpenGEXImporter::handleMaterialRefNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
     if (nullptr == m_currentNode) {
     if (nullptr == m_currentNode) {
         throw DeadlyImportError("No parent node for name.");
         throw DeadlyImportError("No parent node for name.");
-        return;
     }
     }
 
 
     std::vector<std::string> matRefNames;
     std::vector<std::string> matRefNames;
@@ -673,14 +668,12 @@ static void setMatrix(aiNode *node, DataArrayList *transformData) {
 void OpenGEXImporter::handleTransformNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
 void OpenGEXImporter::handleTransformNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
     if (nullptr == m_currentNode) {
     if (nullptr == m_currentNode) {
         throw DeadlyImportError("No parent node for name.");
         throw DeadlyImportError("No parent node for name.");
-        return;
     }
     }
 
 
     DataArrayList *transformData(node->getDataArrayList());
     DataArrayList *transformData(node->getDataArrayList());
     if (nullptr != transformData) {
     if (nullptr != transformData) {
         if (transformData->m_numItems != 16) {
         if (transformData->m_numItems != 16) {
             throw DeadlyImportError("Invalid number of data for transform matrix.");
             throw DeadlyImportError("Invalid number of data for transform matrix.");
-            return;
         }
         }
         setMatrix(m_currentNode, transformData);
         setMatrix(m_currentNode, transformData);
     }
     }
@@ -836,7 +829,6 @@ static void copyColor4DArray(size_t numItems, DataArrayList *vaList, aiColor4D *
 void OpenGEXImporter::handleVertexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
 void OpenGEXImporter::handleVertexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
     if (nullptr == node) {
     if (nullptr == node) {
         throw DeadlyImportError("No parent node for name.");
         throw DeadlyImportError("No parent node for name.");
-        return;
     }
     }
 
 
     Property *prop = node->getProperties();
     Property *prop = node->getProperties();
@@ -877,12 +869,10 @@ void OpenGEXImporter::handleVertexArrayNode(ODDLParser::DDLNode *node, aiScene *
 void OpenGEXImporter::handleIndexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
 void OpenGEXImporter::handleIndexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
     if (nullptr == node) {
     if (nullptr == node) {
         throw DeadlyImportError("No parent node for name.");
         throw DeadlyImportError("No parent node for name.");
-        return;
     }
     }
 
 
     if (nullptr == m_currentMesh) {
     if (nullptr == m_currentMesh) {
         throw DeadlyImportError("No current mesh for index data found.");
         throw DeadlyImportError("No current mesh for index data found.");
-        return;
     }
     }
 
 
     DataArrayList *vaList = node->getDataArrayList();
     DataArrayList *vaList = node->getDataArrayList();

+ 3 - 3
code/AssetLib/Ply/PlyParser.cpp

@@ -308,8 +308,8 @@ bool PLY::Element::ParseElement(IOStreamBuffer<char> &streamBuffer, std::vector<
         streamBuffer.getNextLine(buffer);
         streamBuffer.getNextLine(buffer);
         pCur = (char *)&buffer[0];
         pCur = (char *)&buffer[0];
 
 
-        // skip all comments
-        PLY::DOM::SkipComments(buffer);
+        // skip all comments and go to next line
+        if (PLY::DOM::SkipComments(buffer)) continue;
 
 
         PLY::Property prop;
         PLY::Property prop;
         if (!PLY::Property::ParseProperty(buffer, &prop))
         if (!PLY::Property::ParseProperty(buffer, &prop))
@@ -420,7 +420,7 @@ bool PLY::DOM::ParseHeader(IOStreamBuffer<char> &streamBuffer, std::vector<char>
         if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) {
         if (PLY::Element::ParseElement(streamBuffer, buffer, &out)) {
             // add the element to the list of elements
             // add the element to the list of elements
             alElements.push_back(out);
             alElements.push_back(out);
-        } else if (TokenMatch(buffer, "end_header", 10)) { //checks for /n ending, if it doesn't end with /r/n
+        } else if (TokenMatch(buffer, "end_header", 10)) {
             // we have reached the end of the header
             // we have reached the end of the header
             break;
             break;
         } else {
         } else {

+ 4 - 16
code/AssetLib/Ply/PlyParser.h

@@ -296,9 +296,7 @@ class PropertyInstance
 public:
 public:
 
 
     //! Default constructor
     //! Default constructor
-    PropertyInstance() AI_NO_EXCEPT {
-        // empty
-    }
+    PropertyInstance() AI_NO_EXCEPT = default;
 
 
     union ValueUnion
     union ValueUnion
     {
     {
@@ -359,10 +357,7 @@ public:
 class ElementInstance {
 class ElementInstance {
 public:
 public:
     //! Default constructor
     //! Default constructor
-    ElementInstance()  AI_NO_EXCEPT
-    : alProperties() {
-        // empty
-    }
+    ElementInstance() AI_NO_EXCEPT = default;
 
 
     //! List of all parsed properties
     //! List of all parsed properties
     std::vector< PropertyInstance > alProperties;
     std::vector< PropertyInstance > alProperties;
@@ -386,10 +381,7 @@ class ElementInstanceList
 public:
 public:
 
 
     //! Default constructor
     //! Default constructor
-    ElementInstanceList() AI_NO_EXCEPT
-    : alInstances() {
-        // empty
-    }
+    ElementInstanceList() AI_NO_EXCEPT = default;
 
 
     //! List of all element instances
     //! List of all element instances
     std::vector< ElementInstance > alInstances;
     std::vector< ElementInstance > alInstances;
@@ -413,11 +405,7 @@ class DOM
 public:
 public:
 
 
     //! Default constructor
     //! Default constructor
-    DOM() AI_NO_EXCEPT
-    : alElements()
-    , alElementData() {
-
-    }
+    DOM() AI_NO_EXCEPT = default;
 
 
 
 
     //! Contains all elements of the file format
     //! Contains all elements of the file format

+ 1 - 13
code/AssetLib/Q3BSP/Q3BSPFileData.h

@@ -169,19 +169,7 @@ struct Q3BSPModel {
     std::vector<char> m_EntityData;
     std::vector<char> m_EntityData;
     std::string m_ModelName;
     std::string m_ModelName;
 
 
-    Q3BSPModel() :
-        m_Data(),
-        m_Lumps(),
-        m_Vertices(),
-        m_Faces(),
-        m_Indices(),
-        m_Textures(),
-        m_Lightmaps(),
-        m_EntityData(),
-        m_ModelName()
-    {
-        // empty
-    }
+    Q3BSPModel() = default;
 
 
     ~Q3BSPModel() {
     ~Q3BSPModel() {
         for ( unsigned int i=0; i<m_Lumps.size(); i++ ) {
         for ( unsigned int i=0; i<m_Lumps.size(); i++ ) {

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

@@ -139,7 +139,7 @@ static void normalizePathName(const std::string &rPath, std::string &normalizedP
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //  Constructor.
 //  Constructor.
 Q3BSPFileImporter::Q3BSPFileImporter() :
 Q3BSPFileImporter::Q3BSPFileImporter() :
-        m_pCurrentMesh(nullptr), m_pCurrentFace(nullptr), m_MaterialLookupMap(), mTextures() {
+        m_pCurrentMesh(nullptr), m_pCurrentFace(nullptr) {
     // empty
     // empty
 }
 }
 
 

+ 1 - 2
code/AssetLib/Q3D/Q3DLoader.cpp

@@ -382,11 +382,10 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
 
 
             // TODO
             // TODO
             goto outer;
             goto outer;
-        } break;
+        }
 
 
         default:
         default:
             throw DeadlyImportError("Quick3D: Unknown chunk");
             throw DeadlyImportError("Quick3D: Unknown chunk");
-            break;
         };
         };
     }
     }
 outer:
 outer:

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

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

+ 1 - 1
code/AssetLib/SIB/SIBImporter.cpp

@@ -85,7 +85,7 @@ static const aiImporterDesc desc = {
 struct SIBChunk {
 struct SIBChunk {
     uint32_t Tag;
     uint32_t Tag;
     uint32_t Size;
     uint32_t Size;
-} PACK_STRUCT;
+};
 
 
 enum {
 enum {
     POS,
     POS,

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

@@ -83,12 +83,11 @@ static const aiImporterDesc desc = {
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 SMDImporter::SMDImporter() :
 SMDImporter::SMDImporter() :
         configFrameID(), 
         configFrameID(), 
-        mBuffer(), 
         pScene( nullptr ), 
         pScene( nullptr ), 
         iFileSize( 0 ), 
         iFileSize( 0 ), 
         iSmallestFrame( INT_MAX ),
         iSmallestFrame( INT_MAX ),
         dLengthOfAnim( 0.0 ),
         dLengthOfAnim( 0.0 ),
-        bHasUVs(false ), 
+        bHasUVs(false ),
         iLineNumber((unsigned int)-1)  {
         iLineNumber((unsigned int)-1)  {
     // empty
     // empty
 }
 }
@@ -591,7 +590,7 @@ void SMDImporter::CreateOutputMaterials() {
         pScene->mMaterials[iMat] = pcMat;
         pScene->mMaterials[iMat] = pcMat;
 
 
         aiString szName;
         aiString szName;
-        szName.length = (size_t)ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat);
+        szName.length = static_cast<ai_uint32>(ai_snprintf(szName.data,MAXLEN,"Texture_%u",iMat));
         pcMat->AddProperty(&szName,AI_MATKEY_NAME);
         pcMat->AddProperty(&szName,AI_MATKEY_NAME);
 
 
         if (aszTextures[iMat].length())
         if (aszTextures[iMat].length())

+ 2 - 2
code/AssetLib/SMD/SMDLoader.h

@@ -87,10 +87,10 @@ struct Vertex {
 */
 */
 struct Face {
 struct Face {
     Face() AI_NO_EXCEPT :
     Face() AI_NO_EXCEPT :
-            iTexture(0x0), avVertices{} {
+            iTexture(0x0) {
         // empty
         // empty
     }
     }
-    
+
     //! Texture index for the face
     //! Texture index for the face
     unsigned int iTexture;
     unsigned int iTexture;
 
 

部分文件因为文件数量过多而无法显示