2
0
Эх сурвалжийг харах

Merge branch 'master' into master

Kim Kulling 2 жил өмнө
parent
commit
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
       if: contains(matrix.name, 'windows')
       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
       if: contains(matrix.name, 'hunter')

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

@@ -57,3 +57,13 @@ jobs:
     - name: test
       run: cd build/bin && ./unit
       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)
 # ----------------------------------------------------------------------
-# Copyright (c) 2006-2022, assimp team
+# Copyright (c) 2006-2023, assimp team
 #
 # All rights reserved.
 #
@@ -84,10 +84,6 @@ OPTION( ASSIMP_NO_EXPORT
   "Disable Assimp's export functionality."
   OFF
 )
-OPTION( ASSIMP_BUILD_ZLIB
-  "Build your own zlib"
-  OFF
-)
 OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
   "If the supplementary tools for Assimp are built in addition to the library."
   OFF
@@ -134,6 +130,18 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH
    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)
   # Use subset of Windows.h
   ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
@@ -262,13 +270,13 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT MINGW)
   ENDIF()
   # hide all not-exported symbols
   IF(CMAKE_HOST_SYSTEM_PROCESSOR MATCHES "mips64" )
-	SET(CMAKE_CXX_FLAGS "-mxgot -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
-	SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
-	SET(LIBSTDC++_LIBRARIES -lstdc++)
+    SET(CMAKE_CXX_FLAGS "-mxgot -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
+    SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
+    SET(LIBSTDC++_LIBRARIES -lstdc++)
   ELSE()
-	SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
-	SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
-	SET(LIBSTDC++_LIBRARIES -lstdc++)
+    SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
+    SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
+    SET(LIBSTDC++_LIBRARIES -lstdc++)
   ENDIF()
 ELSEIF(MSVC)
   # enable multi-core compilation with MSVC
@@ -277,13 +285,15 @@ ELSEIF(MSVC)
   ELSE() # msvc
     ADD_COMPILE_OPTIONS(/MP /bigobj /W4 /WX)
   ENDIF()
+  
   # disable "elements of array '' will be default initialized" warning on MSVC2013
   IF(MSVC12)
     ADD_COMPILE_OPTIONS(/wd4351)	
   ENDIF()
-  ADD_COMPILE_OPTIONS(/wd4244) #supress warning for double to float conversion if Double precission is activated
+  # supress warning for double to float conversion if Double precission is activated
+  ADD_COMPILE_OPTIONS(/wd4244) 
   SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
-  SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /Zi")
+  SET(CMAKE_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")
 ELSEIF (CMAKE_CXX_COMPILER_ID MATCHES "Clang" )
   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")
 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 )
   # Use GNUInstallDirs for Unix predefined directories
   INCLUDE(GNUInstallDirs)
@@ -488,7 +490,11 @@ ELSE()
     FIND_PACKAGE(ZLIB)
   ENDIF()
 
-  IF( NOT ZLIB_FOUND )
+  IF ( NOT ZLIB_FOUND AND NOT ASSIMP_BUILD_ZLIB )
+    message( FATAL_ERROR
+      "Build configured with -DASSIMP_BUILD_ZLIB=OFF but unable to find zlib"
+    )
+  ELSEIF( NOT ZLIB_FOUND )
     MESSAGE(STATUS "compiling zlib from sources")
     INCLUDE(CheckIncludeFile)
     INCLUDE(CheckTypeSize)

+ 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)
 ==================================
-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 ###
 [![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)
@@ -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)
 [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
 [![Percentage of issues still open](http://isitmaintained.com/badge/open/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Percentage of issues still open")
-[![Total alerts](https://img.shields.io/lgtm/alerts/g/assimp/assimp.svg?logo=lgtm&logoWidth=18)](https://lgtm.com/projects/g/assimp/assimp/alerts/)
 <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.
@@ -23,15 +24,19 @@ Additionally, assimp features various __mesh post processing tools__: normals an
 ### Latest Doc's ###
 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
 
+### 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 ####
 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.
 	/test		Unit- and regression tests, test suite of models
 	/tools		Tools (old assimp viewer, command line `assimp`)
-	/samples	A small number of samples to illustrate possible
-                        use cases for Assimp
+	/samples	A small number of samples to illustrate possible use-cases for Assimp
 
 The source code is organized in the following way:
 
 	code/Common			The base implementation for importers and the infrastructure
+	code/CApi                       Special implementations which are only used for the C-API
+	code/Geometry                   A collection of geometry tools
+	code/Material                   The material system
+	code/PBR                        An exporter for physical based models
 	code/PostProcessing		The post-processing steps
 	code/AssetLib/<FormatName>	Implementation for import and export for the format
 
-### Where to get help ###
-For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
-(CHMs for Windows are included in some release packages and should be located right here in the root folder).
-
-If the docs don't solve your problem, ask on [StackOverflow with the assimp-tag](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
-
-Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
-
-And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
-
 ### Contributing ###
 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.

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

@@ -322,7 +322,6 @@ struct Texture {
     //! Default constructor
     Texture() AI_NO_EXCEPT
             : mTextureBlend(0.0f),
-              mMapName(),
               mOffsetU(0.0),
               mOffsetV(0.0),
               mScaleU(1.0),
@@ -334,51 +333,11 @@ struct Texture {
         mTextureBlend = get_qnan();
     }
 
-    Texture(const Texture &other) :
-            mTextureBlend(other.mTextureBlend),
-            mMapName(other.mMapName),
-            mOffsetU(other.mOffsetU),
-            mOffsetV(other.mOffsetV),
-            mScaleU(other.mScaleU),
-            mScaleV(other.mScaleV),
-            mRotation(other.mRotation),
-            mMapMode(other.mMapMode),
-            bPrivate(other.bPrivate),
-            iUVSrc(other.iUVSrc) {
-        // empty
-    }
+    Texture(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
     ai_real mTextureBlend;
@@ -436,83 +395,9 @@ struct Material {
         // empty
     }
 
-    Material(const Material &other) :
-            mName(other.mName),
-            mDiffuse(other.mDiffuse),
-            mSpecularExponent(other.mSpecularExponent),
-            mShininessStrength(other.mShininessStrength),
-            mSpecular(other.mSpecular),
-            mAmbient(other.mAmbient),
-            mShading(other.mShading),
-            mTransparency(other.mTransparency),
-            sTexDiffuse(other.sTexDiffuse),
-            sTexOpacity(other.sTexOpacity),
-            sTexSpecular(other.sTexSpecular),
-            sTexReflective(other.sTexReflective),
-            sTexBump(other.sTexBump),
-            sTexEmissive(other.sTexEmissive),
-            sTexShininess(other.sTexShininess),
-            mBumpHeight(other.mBumpHeight),
-            mEmissive(other.mEmissive),
-            sTexAmbient(other.sTexAmbient),
-            mTwoSided(other.mTwoSided) {
-        // empty
-    }
-
-    //! 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
     std::string mName;

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

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

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

@@ -68,7 +68,7 @@ using namespace D3DS;
 class Discreet3DSImporter : public BaseImporter {
 public:
     Discreet3DSImporter();
-    ~Discreet3DSImporter();
+    ~Discreet3DSImporter() override;
 
     // -------------------------------------------------------------------
     /** 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
     }
 
-    virtual ~Resource() {
-        // empty
-    }
+    virtual ~Resource() = default;
 
     virtual ResourceType getType() const {
         return ResourceType::RT_Unknown;
@@ -95,7 +93,7 @@ public:
         // empty
     }
 
-    ~EmbeddedTexture() = default;
+    ~EmbeddedTexture() override = default;
 
     ResourceType getType() const override {
         return ResourceType::RT_EmbeddedTexture2D;
@@ -112,7 +110,7 @@ public:
         // empty
     }
 
-    ~Texture2DGroup() = default;
+    ~Texture2DGroup() override = default;
 
     ResourceType getType() const override {
         return ResourceType::RT_Texture2DGroup;
@@ -129,7 +127,7 @@ public:
         // empty
     }
 
-    ~BaseMaterials() = default;
+    ~BaseMaterials() override = default;
 
     ResourceType getType() const override {
         return ResourceType::RT_BaseMaterials;
@@ -154,7 +152,7 @@ public:
         // empty
     }
 
-    ~Object() = default;
+    ~Object() override = default;
 
     ResourceType getType() const override {
         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 {
 
 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
 }
 

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

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

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

@@ -216,7 +216,7 @@ void XmlSerializer::ImportXml(aiScene *scene) {
     if (nullptr == scene) {
         return;
     }
-    
+
     scene->mRootNode = new aiNode(XmlTag::RootTag);
     XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
     if (node.empty()) {
@@ -444,7 +444,7 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
                             }
                             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)) {
             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)) {
             SkipSpaces(&buffer);
             buffer = TAcCheckedLoadFloatArray(buffer, "", 0, 2, &obj.texRepeat);
@@ -351,8 +353,8 @@ void AC3DImporter::ConvertMaterial(const Object &object,
         s.Set(matSrc.name);
         matDest.AddProperty(&s, AI_MATKEY_NAME);
     }
-    if (object.texture.length()) {
-        s.Set(object.texture);
+    if (!object.textures.empty()) {
+        s.Set(object.textures[0]);
         matDest.AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
 
         // UV transformation
@@ -532,7 +534,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
                 // allocate UV coordinates, but only if the texture name for the
                 // surface is not empty
                 aiVector3D *uv = nullptr;
-                if (object.texture.length()) {
+                if (!object.textures.empty()) {
                     uv = mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
                     mesh->mNumUVComponents[0] = 2;
                 }

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

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

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

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

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

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

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

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

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

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

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

@@ -304,7 +304,6 @@ void Parser::Parse() {
         }
         AI_ASE_HANDLE_TOP_LEVEL_SECTION();
     }
-    return;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -734,7 +733,6 @@ void Parser::ParseLV3MapBlock(Texture &map) {
         }
         AI_ASE_HANDLE_SECTION("3", "*MAP_XXXXXX");
     }
-    return;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -859,7 +857,6 @@ void Parser::ParseLV1ObjectBlock(ASE::BaseNode &node) {
         }
         AI_ASE_HANDLE_TOP_LEVEL_SECTION();
     }
-    return;
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -883,7 +880,6 @@ void Parser::ParseLV2CameraSettingsBlock(ASE::Camera &camera) {
         }
         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");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) {
@@ -1310,7 +1305,6 @@ void Parser::ParseLV2MeshBlock(ASE::Mesh &mesh) {
         }
         AI_ASE_HANDLE_SECTION("2", "*MESH");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) {
@@ -1344,7 +1338,6 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh &mesh) {
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_WEIGHTS");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 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");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshVertexListBlock(
@@ -1443,7 +1435,6 @@ void Parser::ParseLV3MeshVertexListBlock(
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_VERTEX_LIST");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 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");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
@@ -1503,7 +1493,6 @@ void Parser::ParseLV3MeshTListBlock(unsigned int iNumVertices,
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_TVERT_LIST");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
@@ -1532,7 +1521,6 @@ void Parser::ParseLV3MeshTFaceListBlock(unsigned int iNumFaces,
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_TFACE_LIST");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 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");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 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");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 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");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) {
@@ -1681,7 +1666,6 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh &sMesh) {
         }
         AI_ASE_HANDLE_SECTION("3", "*MESH_NORMALS");
     }
-    return;
 }
 // ------------------------------------------------------------------------------------------------
 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*/);
 
 }
-#endif 
+#endif
 #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 {
         return 0;
     }
-    
+
     aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/) override {
         return aiReturn_FAILURE;
     }
-    
+
     size_t Tell() const override {
         return cursor;
     }
-    
+
     void Flush() override {
         // not implemented
     }

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

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

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

@@ -43,7 +43,7 @@ public:
         Flag_WriteSpecialFloats = 0x2,
         Flag_SkipWhitespaces = 0x4
     };
-    
+
     JSONWriter(Assimp::IOStream &out, unsigned int flags = 0u) :
             out(out), indent (""), newline("\n"), space(" "), buff (), first(false), flags(flags) {
         // make sure that all formatting happens using the standard, C locale and not the user's current locale
@@ -499,18 +499,18 @@ static void Write(JSONWriter &out, const aiMaterial &ai, bool is_elem = true) {
                 }
                 break;
 
-            case aiPTI_String: 
+            case aiPTI_String:
                 {
                     aiString s;
                     aiGetMaterialString(&ai, prop->mKey.data, prop->mSemantic, prop->mIndex, &s);
                     out.SimpleValue(s);
-                } 
+                }
                 break;
-            case aiPTI_Buffer: 
+            case aiPTI_Buffer:
                 {
                     // binary data is written as series of hex-encoded octets
                     out.SimpleValue(prop->mData, prop->mDataLength);
-                } 
+                }
                 break;
             default:
                 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() {
-    if (_pos > _buf.size()) {
+    if (_pos >= _buf.size()) {
         Fail("EOF");
     }
 
@@ -418,7 +418,6 @@ void B3DImporter::ReadTRIS(int v0) {
             ASSIMP_LOG_ERROR("Bad triangle index: i0=", i0, ", i1=", i1, ", i2=", i2);
 #endif
             Fail("Bad triangle index");
-            continue;
         }
         face->mNumIndices = 3;
         face->mIndices = new unsigned[3];

+ 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 {
 template <>
 const char *LogFunctions<BlenderBMeshConverter>::Prefix() {
-    static auto prefix = "BLEND_BMESH: ";
-    return prefix;
+    return "BLEND_BMESH: ";
 }
 } // 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
         *           use a special readfunction for that cases
         */
-std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { { DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
+static std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
+        DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
         DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
         DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
         DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),

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

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

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

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

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

@@ -62,9 +62,7 @@ public:
     /**
      *  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 {
 
     ReadFieldArray<ErrorPolicy_Fail>(dest.co, "co", db);
-    ReadFieldArray<ErrorPolicy_Fail>(dest.no, "no", db);
+    ReadFieldArray<ErrorPolicy_Warn>(dest.no, "no", db);
     ReadField<ErrorPolicy_Igno>(dest.flag, "flag", db);
     //ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
     ReadField<ErrorPolicy_Igno>(dest.bweight, "bweight", db);

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

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

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

@@ -62,8 +62,7 @@ namspace Assimp
 {
     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 )
@@ -259,8 +256,7 @@ namespace Assimp
 {
     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 {
     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 {
@@ -124,7 +118,7 @@ bool C4DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, b
     } else if ((!extension.length() || checkSig) && pIOHandler)   {
         // TODO
     }
-    
+
     return false;
 }
 

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

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

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

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

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

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

+ 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
 ColladaLoader::ColladaLoader() :
-        mFileName(),
-        mMeshIndexByID(),
-        mMaterialIndexByName(),
-        mMeshes(),
-        newMats(),
-        mCameras(),
-        mLights(),
-        mTextures(),
-        mAnims(),
         noSkeletonMesh(false),
         removeEmptyBones(false),
         ignoreUpDirection(false),
@@ -1523,7 +1514,7 @@ void ColladaLoader::AddTexture(aiMaterial &mat,
         map = -1;
         for (std::string::const_iterator it = sampler.mUVChannel.begin(); it != sampler.mUVChannel.end(); ++it) {
             if (IsNumeric(*it)) {
-                map = strtoul10(&(*it));        
+                map = strtoul10(&(*it));
                 break;
             }
         }

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

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

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

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

+ 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.");
                 continue;
             }
-            
+
             std::shared_ptr<DXF::PolyLine> pl_out = std::shared_ptr<DXF::PolyLine>(new DXF::PolyLine(*pl_in));
 
             if (bl_src.base.Length() || insert.scale.x!=1.f || insert.scale.y!=1.f || insert.scale.z!=1.f || insert.angle || insert.pos.Length()) {

+ 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) {
     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
 	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 ..
         while(Offset(input, cursor) < end_offset - sentinel_block_length) {
-			ReadScope(output_tokens, input, cursor, input + end_offset - sentinel_block_length, is64bits);
+            ReadScope(output_tokens, token_allocator, input, cursor, input + end_offset - sentinel_block_length, is64bits);
         }
         output_tokens.push_back(new_Token(cursor, cursor + 1, TokenType_CLOSE_BRACKET, Offset(input, cursor) ));
 
@@ -431,8 +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
-void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
-{
+void TokenizeBinary(TokenList &output_tokens, const char *input, size_t length, StackAllocator &token_allocator) {
 	ai_assert(input);
 	ASSIMP_LOG_DEBUG("Tokenizing binary FBX file");
 
@@ -465,7 +464,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
     try
     {
         while (cursor < end ) {
-		    if (!ReadScope(output_tokens, input, cursor, input + length, is64bits)) {
+            if (!ReadScope(output_tokens, token_allocator, input, cursor, input + length, is64bits)) {
                 break;
             }
         }

+ 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'
 }; // who knows why, it looks like two integers 32/64 bit (compressed and uncompressed sizes?) + 1 byte (might be compression type?)
+static std::string NULL_RECORD_STRING(NumNullRecords, '\0');
 const std::string SEPARATOR = { '\x00', '\x01' }; // for use inside strings
 const std::string MAGIC_NODE_TAG = "_$AssimpFbx$"; // from import
 const int64_t SECOND = 46186158000; // FBX's kTime unit

+ 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();
 
+    // NOTE: Camera mPosition, mLookAt and mUp must be set to default here.
+    // All transformations to the camera will be handled by its node in the scenegraph.
     out_camera->mPosition = aiVector3D(0.0f);
     out_camera->mLookAt = aiVector3D(1.0f, 0.0f, 0.0f);
     out_camera->mUp = aiVector3D(0.0f, 1.0f, 0.0f);
@@ -640,7 +642,7 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
 bool FBXConverter::NeedsComplexTransformationChain(const Model &model) {
     const PropertyTable &props = model.Props();
 
-    const auto zero_epsilon = ai_epsilon;
+    const auto zero_epsilon = Math::getEpsilon<ai_real>();
     const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
     for (size_t i = 0; i < TransformationComp_MAXIMUM; ++i) {
         const TransformationComp comp = static_cast<TransformationComp>(i);
@@ -873,8 +875,12 @@ void FBXConverter::SetupNodeMetadata(const Model &model, aiNode &nd) {
             data->Set(index++, prop.first, interpretedBool->Value());
         } else if (const TypedProperty<int> *interpretedInt = prop.second->As<TypedProperty<int>>()) {
             data->Set(index++, prop.first, interpretedInt->Value());
+        } else if (const TypedProperty<uint32_t> *interpretedUInt = prop.second->As<TypedProperty<uint32_t>>()) {
+            data->Set(index++, prop.first, interpretedUInt->Value());
         } else if (const TypedProperty<uint64_t> *interpretedUint64 = prop.second->As<TypedProperty<uint64_t>>()) {
             data->Set(index++, prop.first, interpretedUint64->Value());
+        } else if (const TypedProperty<int64_t> *interpretedint64 = prop.second->As<TypedProperty<int64_t>>()) {
+            data->Set(index++, prop.first, interpretedint64->Value());
         } else if (const TypedProperty<float> *interpretedFloat = prop.second->As<TypedProperty<float>>()) {
             data->Set(index++, prop.first, interpretedFloat->Value());
         } else if (const TypedProperty<std::string> *interpretedString = prop.second->As<TypedProperty<std::string>>()) {
@@ -1176,15 +1182,23 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
     std::vector<aiAnimMesh *> animMeshes;
     for (const BlendShape *blendShape : mesh.GetBlendShapes()) {
         for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) {
-            const std::vector<const ShapeGeometry *> &shapeGeometries = blendShapeChannel->GetShapeGeometries();
-            for (size_t i = 0; i < shapeGeometries.size(); i++) {
+            const auto& shapeGeometries = blendShapeChannel->GetShapeGeometries();
+            for (const ShapeGeometry *shapeGeometry : shapeGeometries) {
                 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()
-                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++) {
                     const unsigned int curIndex = curIndices.at(j);
                     aiVector3D vertex = curVertices.at(j);
@@ -1406,13 +1420,12 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
     std::vector<aiAnimMesh *> animMeshes;
     for (const BlendShape *blendShape : mesh.GetBlendShapes()) {
         for (const BlendShapeChannel *blendShapeChannel : blendShape->BlendShapeChannels()) {
-            const std::vector<const ShapeGeometry *> &shapeGeometries = blendShapeChannel->GetShapeGeometries();
-            for (size_t i = 0; i < shapeGeometries.size(); i++) {
+            const auto& shapeGeometries = blendShapeChannel->GetShapeGeometries();
+            for (const ShapeGeometry *shapeGeometry : shapeGeometries) {
                 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()));
                 for (size_t j = 0; j < curIndices.size(); 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->mOffsetMatrix = bone->mOffsetMatrix;
     skeletonBone->mMeshId = mesh;
+#ifndef ASSIMP_BUILD_NO_ARMATUREPOPULATE_PROCESS
     skeletonBone->mNode = bone->mNode;
+#endif
     skeletonBone->mParent = -1;
 }
 
@@ -1563,7 +1578,7 @@ void FBXConverter::ConvertWeights(aiMesh *out, const MeshGeometry &geo, const ai
         out->mBones = nullptr;
         out->mNumBones = 0;
         return;
-    } 
+    }
 
     out->mBones = new aiBone *[bones.size()]();
     out->mNumBones = static_cast<unsigned int>(bones.size());
@@ -3228,7 +3243,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
     }
 
     bool ok = false;
-    
+
     const auto zero_epsilon = ai_epsilon;
 
     const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);

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

+ 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) {
 	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|
 }
@@ -356,9 +360,11 @@ void Document::ReadObjects() {
         DOMError("no Objects dictionary found");
     }
 
+    StackAllocator &allocator = parser.GetAllocator();
+
     // add a dummy entry to represent the Model::RootNode object (id 0),
     // which is only indirectly defined in the input file
-    objects[0] = new LazyObject(0L, *eobjects, *this);
+    objects[0] = new_LazyObject(0L, *eobjects, *this);
 
     const Scope& sobjects = *eobjects->Compound();
     for(const ElementMap::value_type& el : sobjects.Elements()) {
@@ -381,11 +387,13 @@ void Document::ReadObjects() {
             DOMError("encountered object with implicitly defined id 0",el.second);
         }
 
-        if(objects.find(id) != objects.end()) {
+        const auto foundObject = objects.find(id);
+        if(foundObject != objects.end()) {
             DOMWarning("encountered duplicate object id, ignoring first occurrence",el.second);
+            delete foundObject->second;
         }
 
-        objects[id] = new LazyObject(id, *el.second, *this);
+        objects[id] = new_LazyObject(id, *el.second, *this);
 
         // grab all animation stacks upfront since there is no listing of them
         if(!strcmp(el.first.c_str(),"AnimationStack")) {
@@ -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
     const Element* const econns = sc["Connections"];
     if(!econns || !econns->Compound()) {
@@ -492,7 +502,7 @@ void Document::ReadConnections() {
         }
 
         // add new connection
-        const Connection* const c = new Connection(insertionOrder++,src,dest,prop,*this);
+        const Connection* const c = new_Connection(insertionOrder++,src,dest,prop,*this);
         src_connections.insert(ConnectionMap::value_type(src,c));
         dest_connections.insert(ConnectionMap::value_type(dest,c));
     }

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

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

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

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

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

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

@@ -62,8 +62,7 @@ namespace Assimp {
 
 template <>
 const char *LogFunctions<FBXImporter>::Prefix() {
-	static auto prefix = "FBX: ";
-	return prefix;
+	return "FBX: ";
 }
 
 } // namespace Assimp
@@ -90,10 +89,7 @@ static const aiImporterDesc desc = {
 
 // ------------------------------------------------------------------------------------------------
 // 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.
@@ -156,19 +152,19 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 	// broad-phase tokenized pass in which we identify the core
 	// syntax elements of FBX (brackets, commas, key:value mappings)
 	TokenList tokens;
-	try {
-
+    Assimp::StackAllocator tempAllocator;
+    try {
 		bool is_binary = false;
 		if (!strncmp(begin, "Kaydara FBX Binary", 18)) {
 			is_binary = true;
-			TokenizeBinary(tokens, begin, contents.size());
+            TokenizeBinary(tokens, begin, contents.size(), tempAllocator);
 		} else {
-			Tokenize(tokens, begin);
+            Tokenize(tokens, begin, tempAllocator);
 		}
 
 		// use this information to construct a very rudimentary
 		// 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
 		Document doc(parser, mSettings);
@@ -187,10 +183,12 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 		// assimp universal format (M)
 		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;
 
-    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) :
         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);
         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;
 }
 

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

@@ -2,8 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2022, assimp team
-
+Copyright (c) 2006-2023, assimp team
 
 All rights reserved.
 
@@ -53,84 +52,101 @@ namespace Assimp {
 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 {
 public:
     /// @brief The class constructor with all parameters.
     /// @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 );
+
+    /// @brief The class destructor, 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;
 
-    /// 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:
     const Skin* skin;
-    std::vector<const BlendShape*> blendShapes;
+    std::unordered_set<const BlendShape*> blendShapes;
+
 };
 
 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 {
 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 );
 
-    /** The class destructor */
+    /// @brief The class destructor, 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;
 
-    /** 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;
 
-    /** 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;
 
-    /** 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;
 
-    /** 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;
 
-    /** 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;
 
-    /** 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;
 
-    /** 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;
 
-    /** Get per-face-vertex material assignments */
+    /// @brief Get per-face-vertex material assignments.
+    /// @return The Material indices Array.
     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;
 
-    /** 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;
 
 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)
     {
         if(token) {
@@ -115,8 +116,11 @@ namespace Assimp {
 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;
+    StackAllocator &allocator = parser.GetAllocator();
     do {
         n = parser.AdvanceToNextToken();
         if(!n) {
@@ -145,7 +149,7 @@ Element::Element(const Token& key_token, Parser& parser) : key_token(key_token)
         }
 
         if (n->Type() == TokenType_OPEN_BRACKET) {
-            compound.reset(new Scope(parser));
+            compound = new_Scope(parser);
 
             // current token should be a TOK_CLOSE_BRACKET
             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)
 {
     if(!topLevel) {
@@ -172,6 +185,7 @@ Scope::Scope(Parser& parser,bool topLevel)
         }
     }
 
+    StackAllocator &allocator = parser.GetAllocator();
     TokenPtr n = parser.AdvanceToNextToken();
     if (n == nullptr) {
         ParseError("unexpected end of file");
@@ -187,37 +201,46 @@ Scope::Scope(Parser& parser,bool topLevel)
         if (str.empty()) {
             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)
         n = parser.CurrentToken();
         if (n == nullptr) {
             if (topLevel) {
+                elements.insert(ElementMap::value_type(str, element));
                 return;
             }
+            delete element;
             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");
-    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/fast_atof.h>
 
+#include "Common/StackAllocator.h"
 #include "FBXCompileConfig.h"
 #include "FBXTokenizer.h"
 
@@ -63,14 +64,14 @@ class Parser;
 class Element;
 
 // 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.
  *
@@ -82,15 +83,16 @@ typedef std::pair<ElementMap::const_iterator,ElementMap::const_iterator> Element
  *  @endverbatim
  *
  *  As can be seen in this sample, elements can contain nested #Scope
- *  as their trailing member.  **/
+ *  as their trailing member.  
+**/
 class Element
 {
 public:
     Element(const Token& key_token, Parser& parser);
-    ~Element() = default;
+    ~Element();
 
     const Scope* Compound() const {
-        return compound.get();
+        return compound;
     }
 
     const Token& KeyToken() const {
@@ -104,7 +106,7 @@ public:
 private:
     const Token& key_token;
     TokenList tokens;
-    std::unique_ptr<Scope> compound;
+    Scope* compound;
 };
 
 /** FBX data entity that consists of a 'scope', a collection
@@ -159,8 +161,8 @@ class Parser
 public:
     /** Parse given a token list. Does not take ownership of the tokens -
      *  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 {
         return *root;
@@ -170,6 +172,10 @@ public:
         return is_binary;
     }
 
+    StackAllocator &GetAllocator() {
+        return allocator;
+    }
+
 private:
     friend class Scope;
     friend class Element;
@@ -180,10 +186,10 @@ private:
 
 private:
     const TokenList& tokens;
-
+    StackAllocator &allocator;
     TokenPtr last, current;
     TokenList::const_iterator cursor;
-    std::unique_ptr<Scope> root;
+    Scope *root;
 
     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'.
 // ------------------------------------------------------------------------------------------------
-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 column,
                       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);
 	ASSIMP_LOG_DEBUG("Tokenizing ASCII FBX file");
 
@@ -164,7 +164,7 @@ void Tokenize(TokenList& output_tokens, const char* input)
                 in_double_quotes = false;
                 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;
             }
             continue;
@@ -181,30 +181,30 @@ void Tokenize(TokenList& output_tokens, const char* input)
             continue;
 
         case ';':
-            ProcessDataToken(output_tokens,token_begin,token_end,line,column);
+            ProcessDataToken(output_tokens, token_allocator, token_begin, token_end, line, column);
             comment = true;
             continue;
 
         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));
             continue;
 
         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));
             continue;
 
         case ',':
             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));
             continue;
 
         case ':':
             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 {
                 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;

+ 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
 
 #include "FBXCompileConfig.h"
+#include "Common/StackAllocator.h"
 #include <assimp/ai_assert.h>
 #include <assimp/defs.h>
 #include <vector>
@@ -154,11 +155,11 @@ private:
     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 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.
@@ -168,7 +169,7 @@ typedef std::vector< TokenPtr > TokenList;
  * @param output_tokens Receives a list of all tokens in the input data.
  * @param input_buffer Textual input buffer to be processed, 0-terminated.
  * @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.
@@ -179,7 +180,7 @@ void Tokenize(TokenList& output_tokens, const char* input);
  * @param input_buffer Binary input buffer to be processed.
  * @param length Length of input buffer, in bytes. There is no 0-terminal.
  * @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

+ 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. */
 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);
         *szCurrentOut = szCurrent;
         return;
-    } 
+    }
 
     // generate a default material
     const int iMode = (int)aiShadingMode_Gouraud;
@@ -484,11 +484,11 @@ void HMPImporter::GenerateTextureCoords(const unsigned int width, const unsigned
     if (uv == nullptr) {
         return;
     }
-    
+
     if (height == 0.0f || width == 0.0) {
         return;
     }
-    
+
     const float fY = (1.0f / height) + (1.0f / height) / height;
     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
     */
-    void InternReadFile_HMP4();
+    AI_WONT_RETURN void InternReadFile_HMP4() AI_WONT_RETURN_SUFFIX;
 
     // -------------------------------------------------------------------
     /** 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 {
 template <>
 const char *LogFunctions<IFCImporter>::Prefix() {
-    static auto prefix = "IFC: ";
-    return prefix;
+    return "IFC: ";
 }
 } // 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 "Common/PolyTools.h"
+#include "Geometry/GeometryUtils.h"
 #include "PostProcessing/ProcessHelper.h"
 
 namespace Assimp {
@@ -235,7 +236,7 @@ IfcVector3 TempMesh::ComputeLastPolygonNormal(bool normalize) const {
 struct CompareVector {
     bool operator () (const IfcVector3& a, const IfcVector3& b) const {
         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);
     }
 };

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

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

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

@@ -63,9 +63,7 @@ protected:
         // empty
     }
 
-    ~IrrlichtBase() {
-        // empty
-    }
+    ~IrrlichtBase() = default;
 
     /** @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 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;
 
         // NOTE: We won't handle reset, linear and constant here.
@@ -176,8 +179,7 @@ void AnimResolver::UpdateAnimRangeSetup() {
         case LWO::PrePostBehaviour_Oscillate: {
             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(),
-                                                    [start_time](double t) { return start_time > t; }),
-                                            m;
+                                                    [start_time](double t) { return start_time > t; }), m;
 
             size_t ofs = 0;
             if (n != (*it).keys.end()) {

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

@@ -65,7 +65,6 @@ void LWOImporter::LoadLWOBFile()
         if (mFileBuffer + head.length > end)
         {
             throw DeadlyImportError("LWOB: Invalid chunk length");
-            break;
         }
         uint8_t* const next = mFileBuffer+head.length;
         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
 
-
-
 All rights reserved.
 
 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 "PostProcessing/ConvertToLHProcess.h"
 #include "PostProcessing/ProcessHelper.h"
+#include "Geometry/GeometryUtils.h"
 
 #include <assimp/ByteSwapper.h>
 #include <assimp/SGSpatialSort.h>
@@ -178,7 +177,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
     mLayers->push_back(Layer());
     mCurLayer = &mLayers->back();
     mCurLayer->mName = "<LWODefault>";
-    mCurLayer->mIndex = (uint16_t) -1;
+    mCurLayer->mIndex = 1;
 
     // old lightwave file format (prior to v6)
     mIsLWO2 = false;
@@ -215,7 +214,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
         } else {
             mIsLWO2 = true;
         }
-        
+
         LoadLWO2File();
 
         // The newer lightwave format allows the user to configure the
@@ -398,14 +397,6 @@ void LWOImporter::InternReadFile(const std::string &pFile,
                             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;
                     }
                     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
         unsigned int num = static_cast<unsigned int>(apcMeshes.size() - meshStart);
         if (layer.mName != "<LWODefault>" || num > 0) {
-            aiNode *pcNode = new aiNode();
+            std::unique_ptr<aiNode> pcNode(new aiNode());
             pcNode->mName.Set(layer.mName);
             pcNode->mParent = (aiNode *)&layer;
             pcNode->mNumMeshes = num;
@@ -439,7 +430,8 @@ void LWOImporter::InternReadFile(const std::string &pFile,
                 for (unsigned int p = 0; p < pcNode->mNumMeshes; ++p)
                     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;
                     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];
                     vNormals += v;
                 }
-                vNormals.Normalize();
                 for (std::vector<unsigned int>::const_iterator a = poResult.begin(); a != poResult.end(); ++a) {
                     mesh->mNormals[*a] = vNormals;
                     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();
     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
@@ -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");
+    }
 
     // Remove a single root node with no meshes assigned to it ...
     if (1 == mScene->mRootNode->mNumChildren) {
@@ -1462,7 +1484,6 @@ void LWOImporter::LoadLWO2File() {
 
         if (mFileBuffer + head.length > end) {
             throw DeadlyImportError("LWO2: Chunk length points behind the file");
-            break;
         }
         uint8_t *const next = mFileBuffer + head.length;
         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)
     // 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.g *= surf.mDiffuseValue;
     clr.b *= surf.mDiffuseValue;

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

@@ -65,7 +65,7 @@ class M3DImporter : public BaseImporter {
 public:
 	/// \brief  Default constructor
 	M3DImporter();
-    ~M3DImporter() override {}
+    ~M3DImporter() override = default;
 
 	/// \brief  Returns whether the class can handle the format of the given file.
 	/// \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"
 
@@ -149,4 +148,3 @@ void M3DWrapper::ClearSave() {
 } // namespace Assimp
 
 #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
 #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 <vector>
@@ -126,7 +125,6 @@ inline m3d_t *M3DWrapper::M3D() const {
 
 } // namespace Assimp
 
-#endif
 #endif // ASSIMP_BUILD_NO_M3D_IMPORTER
 
 #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
 
-
-
 All rights reserved.
 
 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)");
     }
     SkipLine();
+    if (buffer == bufferEnd) {
+        return;
+    }
 
     // print the command line options to the console
     // 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
     char *sz = buffer;
-    while (!IsSpaceOrNewLine(*buffer))
-        buffer++;
+    while (!IsSpaceOrNewLine(*buffer)) {
+        ++buffer;
+    }
     out.mName = std::string(sz, (uintptr_t)(buffer - sz));
     SkipSpaces();
 
@@ -144,14 +146,14 @@ bool MD5Parser::ParseSection(Section &out) {
     while (running) {
         if ('{' == *buffer) {
             // it is a normal section so read all lines
-            buffer++;
+            ++buffer;
             bool run = true;
             while (run) {
                 if (!SkipSpacesAndLineEnd()) {
                     return false; // seems this was the last section
                 }
                 if ('}' == *buffer) {
-                    buffer++;
+                    ++buffer;
                     break;
                 }
 
@@ -163,7 +165,7 @@ bool MD5Parser::ParseSection(Section &out) {
 
                 // terminate the line with zero
                 while (!IsLineEnd(*buffer))
-                    buffer++;
+                    ++buffer;
                 if (*buffer) {
                     ++lineNumber;
                     *buffer++ = '\0';

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

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

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

@@ -470,14 +470,16 @@ void HL1MDLLoader::read_bones() {
 
     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);
     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.
     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]);
         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]));
 
         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 {
-            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_[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.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);
 
+    /**
+     *  \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 */
     aiScene *scene_;
 
@@ -198,11 +206,13 @@ private:
         TempBone() :
             node(nullptr),
             absolute_transform(),
-            offset_matrix() {}
+            offset_matrix(),
+            children() {}
 
         aiNode *node;
         aiMatrix4x4 absolute_transform;
         aiMatrix4x4 offset_matrix;
+        std::vector<int> children; // Bone children
     };
 
     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
-                    pcOutBone->mName.length = (size_t)iMaxLen;
+                    pcOutBone->mName.length = static_cast<ai_uint32>(iMaxLen);
                     ::memcpy(pcOutBone->mName.data, pcBone->name, pcOutBone->mName.length);
                     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)
     */
-    void InternReadFile_HL2( );
+    AI_WONT_RETURN void InternReadFile_HL2( ) AI_WONT_RETURN_SUFFIX;
 
     // -------------------------------------------------------------------
     /** 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.");
             return;
         }
-        
+
         pcNew.reset(new aiTexture);
         pcNew->mHeight = 0;
         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());
         switch (v->skinning_type) {
         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;
         case pmx::PmxVertexSkinningType::BDEF2:
             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 <fstream>
 #include <memory>
+#include <assimp/types.h>
 #include "MMDCpp14.h"
 
 namespace pmx
@@ -730,7 +731,7 @@ namespace pmx
 		std::unique_ptr<PmxAncherRigidBody []> anchers;
 		int pin_vertex_count;
 		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

+ 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) {
             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");
             }
 
@@ -494,7 +494,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
             f.mIndices = new unsigned int[f.mNumIndices=3];
 
             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");
                 }
 

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

@@ -107,7 +107,7 @@ private:
 
         aiColor3D color, diffuse, specular, ambient, emissive;
         ai_real refracti;
-        std::string texFile;        
+        std::string texFile;
         bool twoSided; // For NFF2
         bool shaded;
         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);
         idx = strtoul10(sz,&sz);
         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;
+            ++i;
             continue;
-	}
-	faces->mNumIndices = idx;
+	    }
+	    faces->mNumIndices = idx;
         faces->mIndices = new unsigned int[faces->mNumIndices];
         for (unsigned int m = 0; m < faces->mNumIndices;++m) {
             SkipSpaces(&sz);

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

@@ -3,7 +3,7 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2020, assimp team
+Copyright (c) 2006-2023, assimp team
 
 All rights reserved.
 
@@ -84,7 +84,6 @@ ObjFileImporter::ObjFileImporter() :
 //  Destructor.
 ObjFileImporter::~ObjFileImporter() {
     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) {
         unsigned int meshId = pObject->m_Meshes[i];
         aiMesh *pMesh = createTopology(pModel, pObject, meshId);
-        if (pMesh) {
+        if (pMesh != nullptr) {
             if (pMesh->mNumFaces > 0) {
                 MeshArray.push_back(pMesh);
             } else {
@@ -324,14 +323,13 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
         return nullptr;
     }
 
-    std::unique_ptr<aiMesh> pMesh(new aiMesh);
+    aiMesh *pMesh = new aiMesh;
     if (!pObjMesh->m_name.empty()) {
         pMesh->mName.Set(pObjMesh->m_name);
     }
 
     for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
         const ObjFile::Face *inp = pObjMesh->m_Faces[index];
-        //ai_assert(nullptr != inp);
 
         if (inp->mPrimitiveType == aiPrimitiveType_LINE) {
             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
-    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);
             getFloat(it, m_DataItEnd, m_pModel->mCurrentMaterial->bump_multiplier);
             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, 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)))) {
             skipToken = 2;
         } else if (!ASSIMP_strincmp(pPtr, ModifyMapOption, static_cast<unsigned int>(strlen(ModifyMapOption)))) {
             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)))) {
             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);
             insideCstype = name == "cstype";
             goto pf_skip_line;
-        } break;
+        }
 
         default: {
         pf_skip_line:
@@ -440,7 +440,7 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
     const bool vt = (!m_pModel->mTextureCoord.empty());
     const bool vn = (!m_pModel->mNormals.empty());
     int iPos = 0;
-    while (m_DataIt != m_DataItEnd) {
+    while (m_DataIt < m_DataItEnd) {
         int iStep = 1;
 
         if (IsLineEnd(*m_DataIt)) {
@@ -458,7 +458,7 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
             //OBJ USES 1 Base ARRAYS!!!!
             const char *token = &(*m_DataIt);
             const int iVal = ::atoi(token);
-            
+
             // increment iStep position based off of the sign and # of digits
             int tmp = iVal;
             if (iVal < 0) {

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

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2021, assimp team
+Copyright (c) 2006-2022, assimp team
 
 All rights reserved.
 
@@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp {
 
-/** 
+/**
  *  @brief  Returns true, if the last entry of the buffer is reached.
  *  @param[in] it   Iterator of current position.
  *  @param[in] end  Iterator with end of buffer.
@@ -67,7 +67,7 @@ inline bool isEndOfBuffer(char_t it, char_t end) {
     return (it == end);
 }
 
-/** 
+/**
  *  @brief  Returns next word separated by a space
  *  @param[in] pBuffer  Pointer to data 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;
 }
 
-/** 
+/**
  *  @brief  Returns pointer a next token
  *  @param[in] pBuffer  Pointer to data 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);
 }
 
-/** 
+/**
  *  @brief  Skips a line
  *  @param[in]  it      Iterator set to current position
  *  @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>
 inline char_t skipLine(char_t it, char_t end, unsigned int &uiLine) {
+    if (it >= end) {
+        return it;
+    }
+
     while (!isEndOfBuffer(it, end) && !IsLineEnd(*it)) {
         ++it;
     }
@@ -127,9 +131,9 @@ inline char_t skipLine(char_t it, char_t end, unsigned int &uiLine) {
     return it;
 }
 
-/** 
+/**
  *  @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]  end     set to end of scratch buffer for readout
  *  @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));
     if (!strName.empty()) {
         name = strName;
-    } 
-    
+    }
+
 
     return it;
 }
 
-/** 
+/**
  *  @brief  Get a name from the current line. Do not preserve space
  *    in the middle, but trim it at the end.
  *  @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()) {
         name = strName;
     }
-        
+
     return it;
 }
 
-/** 
+/**
  *  @brief  Get next word from given line
  *  @param[in] it      set to current position
  *  @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;
 }
 
-/** 
+/**
  *  @brief  Get next float from given line
  *  @param[in]  it      set to current position
  *  @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 {
 public:
     /// 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:
     /// 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.
-    virtual const aiImporterDesc *GetInfo() const override;
+    const aiImporterDesc *GetInfo() const override;
 
     /// BaseImporter override.
-    virtual void SetupProperties(const Importer *pImp) override;
+    void SetupProperties(const Importer *pImp) override;
 
 private:
     /// 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 {
 
 //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) {
     if (!error.empty()) {
         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 + "'");
-    return false;
 }
 
 // Mesh XML constants
@@ -490,7 +489,7 @@ bool OgreXmlSerializer::ImportSkeleton(Assimp::IOSystem *pIOHandler, MeshXml *me
     OgreXmlSerializer serializer(xmlParser.get());
     XmlNode root = xmlParser->getRootNode();
     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()) {
             if (std::string(a.name()) == nnSkeleton) {
                 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() :
         m_root(nullptr),
         m_nodeChildMap(),
-        m_meshCache(),
         m_mesh2refMap(),
         m_material2refMap(),
         m_ctx(nullptr),
@@ -461,14 +460,12 @@ void OpenGEXImporter::handleMetricNode(DDLNode *node, aiScene * /*pScene*/) {
 void OpenGEXImporter::handleNameNode(DDLNode *node, aiScene * /*pScene*/) {
     if (nullptr == m_currentNode) {
         throw DeadlyImportError("No current node for name.");
-        return;
     }
 
     Value *val(node->getValue());
     if (nullptr != val) {
         if (Value::ValueType::ddl_string != val->m_type) {
             throw DeadlyImportError("OpenGEX: invalid data type for value in node name.");
-            return;
         }
 
         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*/) {
     if (nullptr == m_currentNode) {
         throw DeadlyImportError("No parent node for name.");
-        return;
     }
 
     std::vector<std::string> objRefNames;
@@ -533,7 +529,6 @@ void OpenGEXImporter::handleObjectRefNode(DDLNode *node, aiScene * /*pScene*/) {
 void OpenGEXImporter::handleMaterialRefNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
     if (nullptr == m_currentNode) {
         throw DeadlyImportError("No parent node for name.");
-        return;
     }
 
     std::vector<std::string> matRefNames;
@@ -673,14 +668,12 @@ static void setMatrix(aiNode *node, DataArrayList *transformData) {
 void OpenGEXImporter::handleTransformNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
     if (nullptr == m_currentNode) {
         throw DeadlyImportError("No parent node for name.");
-        return;
     }
 
     DataArrayList *transformData(node->getDataArrayList());
     if (nullptr != transformData) {
         if (transformData->m_numItems != 16) {
             throw DeadlyImportError("Invalid number of data for transform matrix.");
-            return;
         }
         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*/) {
     if (nullptr == node) {
         throw DeadlyImportError("No parent node for name.");
-        return;
     }
 
     Property *prop = node->getProperties();
@@ -877,12 +869,10 @@ void OpenGEXImporter::handleVertexArrayNode(ODDLParser::DDLNode *node, aiScene *
 void OpenGEXImporter::handleIndexArrayNode(ODDLParser::DDLNode *node, aiScene * /*pScene*/) {
     if (nullptr == node) {
         throw DeadlyImportError("No parent node for name.");
-        return;
     }
 
     if (nullptr == m_currentMesh) {
         throw DeadlyImportError("No current mesh for index data found.");
-        return;
     }
 
     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);
         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;
         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)) {
             // add the element to the list of elements
             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
             break;
         } else {

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

@@ -296,9 +296,7 @@ class PropertyInstance
 public:
 
     //! Default constructor
-    PropertyInstance() AI_NO_EXCEPT {
-        // empty
-    }
+    PropertyInstance() AI_NO_EXCEPT = default;
 
     union ValueUnion
     {
@@ -359,10 +357,7 @@ public:
 class ElementInstance {
 public:
     //! Default constructor
-    ElementInstance()  AI_NO_EXCEPT
-    : alProperties() {
-        // empty
-    }
+    ElementInstance() AI_NO_EXCEPT = default;
 
     //! List of all parsed properties
     std::vector< PropertyInstance > alProperties;
@@ -386,10 +381,7 @@ class ElementInstanceList
 public:
 
     //! Default constructor
-    ElementInstanceList() AI_NO_EXCEPT
-    : alInstances() {
-        // empty
-    }
+    ElementInstanceList() AI_NO_EXCEPT = default;
 
     //! List of all element instances
     std::vector< ElementInstance > alInstances;
@@ -413,11 +405,7 @@ class DOM
 public:
 
     //! Default constructor
-    DOM() AI_NO_EXCEPT
-    : alElements()
-    , alElementData() {
-
-    }
+    DOM() AI_NO_EXCEPT = default;
 
 
     //! 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::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() {
         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.
 Q3BSPFileImporter::Q3BSPFileImporter() :
-        m_pCurrentMesh(nullptr), m_pCurrentFace(nullptr), m_MaterialLookupMap(), mTextures() {
+        m_pCurrentMesh(nullptr), m_pCurrentFace(nullptr) {
     // empty
 }
 

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

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

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

@@ -58,7 +58,7 @@ namespace Assimp {
 class RAWImporter : public BaseImporter {
 public:
     RAWImporter();
-    ~RAWImporter();
+    ~RAWImporter() override;
 
     // -------------------------------------------------------------------
     /** 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 {
     uint32_t Tag;
     uint32_t Size;
-} PACK_STRUCT;
+};
 
 enum {
     POS,

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

@@ -83,12 +83,11 @@ static const aiImporterDesc desc = {
 // Constructor to be privately used by Importer
 SMDImporter::SMDImporter() :
         configFrameID(), 
-        mBuffer(), 
         pScene( nullptr ), 
         iFileSize( 0 ), 
         iSmallestFrame( INT_MAX ),
         dLengthOfAnim( 0.0 ),
-        bHasUVs(false ), 
+        bHasUVs(false ),
         iLineNumber((unsigned int)-1)  {
     // empty
 }
@@ -591,7 +590,7 @@ void SMDImporter::CreateOutputMaterials() {
         pScene->mMaterials[iMat] = pcMat;
 
         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);
 
         if (aszTextures[iMat].length())

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

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

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно