Переглянути джерело

Rollup to upstream/master

RichardTea 5 роки тому
батько
коміт
9e27fb3b89
100 змінених файлів з 4262 додано та 3789 видалено
  1. 38 0
      .github/ISSUE_TEMPLATE/bug_report.md
  2. 20 0
      .github/ISSUE_TEMPLATE/feature_request.md
  3. 6 0
      .gitignore
  4. 50 50
      INSTALL
  5. 11 96
      Readme.md
  6. 6 0
      assimpTargets-debug.cmake.in
  7. 6 0
      assimpTargets-release.cmake.in
  8. 707 0
      code/AMF/AMFImporter.cpp
  9. 2 2
      code/AssetLib/3DS/3DSConverter.cpp
  10. 1 1
      code/AssetLib/3DS/3DSExporter.cpp
  11. 25 22
      code/AssetLib/3DS/3DSHelper.h
  12. 4 4
      code/AssetLib/3MF/D3MFImporter.cpp
  13. 53 56
      code/AssetLib/3MF/D3MFOpcPackage.cpp
  14. 3 3
      code/AssetLib/AC/ACLoader.cpp
  15. 3 1
      code/AssetLib/AMF/AMFImporter.cpp
  16. 1 1
      code/AssetLib/AMF/AMFImporter_Geometry.cpp
  17. 1 1
      code/AssetLib/AMF/AMFImporter_Macro.hpp
  18. 1 1
      code/AssetLib/AMF/AMFImporter_Material.cpp
  19. 1 1
      code/AssetLib/AMF/AMFImporter_Node.hpp
  20. 1 1
      code/AssetLib/ASE/ASELoader.cpp
  21. 5 5
      code/AssetLib/ASE/ASEParser.cpp
  22. 94 122
      code/AssetLib/ASE/ASEParser.h
  23. 3 3
      code/AssetLib/Assbin/AssbinFileWriter.cpp
  24. 1 1
      code/AssetLib/Assbin/AssbinLoader.cpp
  25. 1 1
      code/AssetLib/Assxml/AssxmlFileWriter.cpp
  26. 24 31
      code/AssetLib/BVH/BVHLoader.cpp
  27. 1 1
      code/AssetLib/Blender/BlenderDNA.cpp
  28. 6 6
      code/AssetLib/Blender/BlenderDNA.h
  29. 3 2
      code/AssetLib/Blender/BlenderDNA.inl
  30. 240 281
      code/AssetLib/Blender/BlenderLoader.cpp
  31. 3 1
      code/AssetLib/COB/COBLoader.cpp
  32. 1 1
      code/AssetLib/CSM/CSMLoader.cpp
  33. 313 216
      code/AssetLib/Collada/ColladaExporter.cpp
  34. 115 80
      code/AssetLib/Collada/ColladaExporter.h
  35. 8 15
      code/AssetLib/Collada/ColladaHelper.cpp
  36. 185 224
      code/AssetLib/Collada/ColladaHelper.h
  37. 234 253
      code/AssetLib/Collada/ColladaLoader.cpp
  38. 179 330
      code/AssetLib/Collada/ColladaParser.cpp
  39. 235 236
      code/AssetLib/Collada/ColladaParser.h
  40. 1 1
      code/AssetLib/DXF/DXFHelper.h
  41. 3 3
      code/AssetLib/DXF/DXFLoader.cpp
  42. 77 92
      code/AssetLib/FBX/FBXAnimation.cpp
  43. 4 1
      code/AssetLib/FBX/FBXBinaryTokenizer.cpp
  44. 23 24
      code/AssetLib/FBX/FBXConverter.cpp
  45. 3 3
      code/AssetLib/FBX/FBXConverter.h
  46. 7 2
      code/AssetLib/FBX/FBXDocument.cpp
  47. 6 5
      code/AssetLib/FBX/FBXDocument.h
  48. 3 3
      code/AssetLib/FBX/FBXDocumentUtil.cpp
  49. 2 0
      code/AssetLib/FBX/FBXImporter.cpp
  50. 1 1
      code/AssetLib/FBX/FBXMaterial.cpp
  51. 1 1
      code/AssetLib/FBX/FBXMeshGeometry.cpp
  52. 3 3
      code/AssetLib/FBX/FBXMeshGeometry.h
  53. 13 11
      code/AssetLib/FBX/FBXParser.cpp
  54. 2 2
      code/AssetLib/FBX/FBXParser.h
  55. 3 3
      code/AssetLib/FBX/FBXProperties.cpp
  56. 1 1
      code/AssetLib/FBX/FBXProperties.h
  57. 5 3
      code/AssetLib/FBX/FBXTokenizer.cpp
  58. 154 180
      code/AssetLib/HMP/HMPLoader.cpp
  59. 6 6
      code/AssetLib/IFC/IFCBoolean.cpp
  60. 6 4
      code/AssetLib/IFC/IFCCurve.cpp
  61. 4 4
      code/AssetLib/IFC/IFCGeometry.cpp
  62. 10 10
      code/AssetLib/IFC/IFCLoader.cpp
  63. 1 1
      code/AssetLib/IFC/IFCOpenings.cpp
  64. 327 327
      code/AssetLib/IFC/IFCReaderGen1_2x3.cpp
  65. 3 3
      code/AssetLib/IFC/IFCUtil.cpp
  66. 1 1
      code/AssetLib/IFC/IFCUtil.h
  67. 365 397
      code/AssetLib/Irr/IRRLoader.cpp
  68. 3 2
      code/AssetLib/Irr/IRRMeshLoader.cpp
  69. 2 2
      code/AssetLib/LWO/LWOAnimation.cpp
  70. 2 2
      code/AssetLib/LWO/LWOAnimation.h
  71. 1 1
      code/AssetLib/LWO/LWOBLoader.cpp
  72. 2 2
      code/AssetLib/LWO/LWOLoader.cpp
  73. 1 1
      code/AssetLib/LWO/LWOLoader.h
  74. 3 3
      code/AssetLib/LWO/LWOMaterial.cpp
  75. 4 4
      code/AssetLib/LWS/LWSLoader.cpp
  76. 13 1
      code/AssetLib/LWS/LWSLoader.h
  77. 4 4
      code/AssetLib/M3D/M3DExporter.cpp
  78. 4 2
      code/AssetLib/M3D/M3DImporter.cpp
  79. 12 12
      code/AssetLib/M3D/M3DMaterials.h
  80. 1 1
      code/AssetLib/M3D/M3DWrapper.cpp
  81. 1 1
      code/AssetLib/M3D/m3d.h
  82. 6 5
      code/AssetLib/MD2/MD2Loader.cpp
  83. 235 272
      code/AssetLib/MD3/MD3Loader.cpp
  84. 87 71
      code/AssetLib/MD5/MD5Loader.cpp
  85. 7 8
      code/AssetLib/MD5/MD5Loader.h
  86. 164 179
      code/AssetLib/MD5/MD5Parser.cpp
  87. 4 4
      code/AssetLib/MDC/MDCLoader.cpp
  88. 1 1
      code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp
  89. 4 2
      code/AssetLib/MDL/HalfLife/HL1MDLLoader.h
  90. 23 20
      code/AssetLib/MDL/MDLLoader.cpp
  91. 1 1
      code/AssetLib/MDL/MDLLoader.h
  92. 2 2
      code/AssetLib/MDL/MDLMaterialLoader.cpp
  93. 1 1
      code/AssetLib/MMD/MMDImporter.cpp
  94. 1 1
      code/AssetLib/MMD/MMDImporter.h
  95. 1 1
      code/AssetLib/MMD/MMDPmdParser.h
  96. 1 1
      code/AssetLib/MS3D/MS3DLoader.cpp
  97. 12 12
      code/AssetLib/NFF/NFFLoader.cpp
  98. 3 3
      code/AssetLib/Obj/ObjExporter.cpp
  99. 15 11
      code/AssetLib/Obj/ObjFileData.h
  100. 15 15
      code/AssetLib/Obj/ObjFileImporter.cpp

+ 38 - 0
.github/ISSUE_TEMPLATE/bug_report.md

@@ -0,0 +1,38 @@
+---
+name: Bug report
+about: Create a report to help us improve
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Describe the bug**
+A clear and concise description of what the bug is.
+
+**To Reproduce**
+Steps to reproduce the behavior:
+1. Go to '...'
+2. Click on '....'
+3. Scroll down to '....'
+4. See error
+
+**Expected behavior**
+A clear and concise description of what you expected to happen.
+
+**Screenshots**
+If applicable, add screenshots to help explain your problem.
+
+**Desktop (please complete the following information):**
+ - OS: [e.g. iOS]
+ - Browser [e.g. chrome, safari]
+ - Version [e.g. 22]
+
+**Smartphone (please complete the following information):**
+ - Device: [e.g. iPhone6]
+ - OS: [e.g. iOS8.1]
+ - Browser [e.g. stock browser, safari]
+ - Version [e.g. 22]
+
+**Additional context**
+Add any other context about the problem here.

+ 20 - 0
.github/ISSUE_TEMPLATE/feature_request.md

@@ -0,0 +1,20 @@
+---
+name: Feature request
+about: Suggest an idea for this project
+title: ''
+labels: ''
+assignees: ''
+
+---
+
+**Is your feature request related to a problem? Please describe.**
+A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
+
+**Describe the solution you'd like**
+A clear and concise description of what you want to happen.
+
+**Describe alternatives you've considered**
+A clear and concise description of any alternative solutions or features you've considered.
+
+**Additional context**
+Add any other context or screenshots about the feature request here.

+ 6 - 0
.gitignore

@@ -79,6 +79,12 @@ test/gtest/src/gtest-stamp/Debug/
 tools/assimp_view/assimp_viewer.vcxproj.user
 tools/assimp_view/assimp_viewer.vcxproj.user
 *.pyc
 *.pyc
 
 
+### Rust ###
+# Generated by Cargo; will have compiled files and executables
+port/assimp_rs/target/
+# Backup files generated by rustfmt
+port/assimp_rs/**/*.rs.bk
+
 # Unix editor backups
 # Unix editor backups
 *~
 *~
 test/gtest/src/gtest-stamp/gtest-gitinfo.txt
 test/gtest/src/gtest-stamp/gtest-gitinfo.txt

+ 50 - 50
INSTALL

@@ -1,50 +1,50 @@
-	
-========================================================================
-Open Asset Import Library (assimp) INSTALL 
-========================================================================
-
-------------------------------
-Getting the documentation
-------------------------------
-
-A regularly-updated copy is available at 
-http://assimp.sourceforge.net/lib_html/index.html
-
-A CHM file is included in the SVN repos: ./doc/AssimpDoc_Html/AssimpDoc.chm.
-To build the doxygen documentation on your own, follow these steps:
-
-a) download & install latest doxygen 
-b) make sure doxygen is in the executable search path
-c) navigate to ./doc
-d) and run 'doxygen'
-
-Open the generated HTML (AssimpDoc_Html/index.html) in the browser of your choice.
-Windows only: To generate the CHM doc, install 'Microsoft HTML Workshop'
-and configure the path to it in the DOXYFILE first. 
-
-------------------------------
-Building Assimp 
-------------------------------
-
-More detailed build instructions can be found in the documentation,
-this section is just for the inpatient among you.
-
-CMake is the preferred build system for Assimp. The minimum required version 
-is 2.6. If you don't have it yet, downloads for CMake can be found on
-http://www.cmake.org/. 
-
-For Unix:
-
-1. mkdir build && cd build
-2. cmake .. -G 'Unix Makefiles'
-3. make -j4
-
-For Windows:
-1. Open a command prompt
-2. mkdir build
-3. cd build
-4. cmake ..
-5. cmake --build .
-
-For iOS:
-Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS
+	
+========================================================================
+Open Asset Import Library (assimp) INSTALL 
+========================================================================
+
+------------------------------
+Getting the documentation
+------------------------------
+
+A regularly-updated copy is available at 
+http://assimp.sourceforge.net/lib_html/index.html
+
+A CHM file is included in the SVN repos: ./doc/AssimpDoc_Html/AssimpDoc.chm.
+To build the doxygen documentation on your own, follow these steps:
+
+a) download & install latest doxygen 
+b) make sure doxygen is in the executable search path
+c) navigate to ./doc
+d) and run 'doxygen'
+
+Open the generated HTML (AssimpDoc_Html/index.html) in the browser of your choice.
+Windows only: To generate the CHM doc, install 'Microsoft HTML Workshop'
+and configure the path to it in the DOXYFILE first. 
+
+------------------------------
+Building Assimp 
+------------------------------
+
+More detailed build instructions can be found in the documentation,
+this section is just for the inpatient among you.
+
+CMake is the preferred build system for Assimp. The minimum required version 
+is 2.6. If you don't have it yet, downloads for CMake can be found on
+http://www.cmake.org/. 
+
+For Unix:
+
+1. mkdir build && cd build
+2. cmake .. -G 'Unix Makefiles'
+3. make -j4
+
+For Windows:
+1. Open a command prompt
+2. mkdir build
+3. cd build
+4. cmake ..
+5. cmake --build .
+
+For iOS:
+Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS

+ 11 - 96
Readme.md

@@ -25,107 +25,12 @@ Additionally, assimp features various __mesh post processing tools__: normals an
 
 
 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).
 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).
 
 
-Monthly donations via Patreon:
-<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp)
-
-<br>
-
-One-off donations via PayPal:
-<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4)
-
-<br>
-
 Please check our Wiki as well: https://github.com/assimp/assimp/wiki
 Please check our Wiki as well: https://github.com/assimp/assimp/wiki
 
 
 If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
 If you want to check our Model-Database, use the following repo: https://github.com/assimp/assimp-mdb
 
 
 #### Supported file formats ####
 #### Supported file formats ####
-
-__Importers__:
-
-- 3D
-- [3DS](https://en.wikipedia.org/wiki/.3ds)
-- [3MF](https://en.wikipedia.org/wiki/3D_Manufacturing_Format)
-- AC
-- [AC3D](https://en.wikipedia.org/wiki/AC3D)
-- ACC
-- AMJ
-- ASE
-- ASK
-- B3D
-- [BLEND](https://en.wikipedia.org/wiki/.blend_(file_format))
-- [BVH](https://en.wikipedia.org/wiki/Biovision_Hierarchy)
-- CMS
-- COB
-- [DAE/Collada](https://en.wikipedia.org/wiki/COLLADA)
-- [DXF](https://en.wikipedia.org/wiki/AutoCAD_DXF)
-- ENFF
-- [FBX](https://en.wikipedia.org/wiki/FBX)
-- [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB
-- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0):
-  At the moment for glTF2.0 the following extensions are supported:
-  + KHR_lights_punctual ( 5.0 )
-  + KHR_materials_pbrSpecularGlossiness ( 5.0 )
-  + KHR_materials_unlit ( 5.0 )
-  + KHR_texture_transform ( 5.1 under test )
-- HMB
-- IFC-STEP
-- IRR / IRRMESH
-- [LWO](https://en.wikipedia.org/wiki/LightWave_3D)
-- LWS
-- LXO
-- [M3D](https://bztsrc.gitlab.io/model3d)
-- MD2
-- MD3
-- MD5
-- MDC
-- MDL
-- MESH / MESH.XML
-- MOT
-- MS3D
-- NDO
-- NFF
-- [OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file)
-- [OFF](https://en.wikipedia.org/wiki/OFF_(file_format))
-- [OGEX](https://en.wikipedia.org/wiki/Open_Game_Engine_Exchange)
-- [PLY](https://en.wikipedia.org/wiki/PLY_(file_format))
-- PMX
-- PRJ
-- Q3O
-- Q3S
-- RAW
-- SCN
-- SIB
-- SMD
-- [STP](https://en.wikipedia.org/wiki/ISO_10303-21)
-- [STL](https://en.wikipedia.org/wiki/STL_(file_format))
-- TER
-- UC
-- VTA
-- X
-- [X3D](https://en.wikipedia.org/wiki/X3D)
-- XGL
-- ZGL
-
-Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
-
-- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange) IMporting geometry + node hierarchy are currently supported
-
-__Exporters__:
-
-- DAE (Collada)
-- STL
-- OBJ
-- PLY
-- X
-- 3DS
-- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
-- ASSBIN
-- STEP
-- glTF 1.0 (partial)
-- glTF 2.0 (partial)
-- 3MF ( experimental )
-- FBX ( experimental )
+You can find the complete list of supported file-formats [here](https://github.com/assimp/assimp/blob/master/doc/Fileformats.md)
 
 
 ### Building ###
 ### Building ###
 Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
 Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
@@ -196,6 +101,16 @@ Become a financial contributor and help us sustain our community. [[Contribute](
 
 
 <a href="https://opencollective.com/assimp"><img src="https://opencollective.com/assimp/individuals.svg?width=890"></a>
 <a href="https://opencollective.com/assimp"><img src="https://opencollective.com/assimp/individuals.svg?width=890"></a>
 
 
+Monthly donations via Patreon:
+<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp)
+
+<br>
+
+One-off donations via PayPal:
+<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4)
+
+<br>
+
 #### Organizations
 #### Organizations
 
 
 Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)]
 Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)]

+ 6 - 0
assimpTargets-debug.cmake.in

@@ -73,6 +73,9 @@ else()
     else()
     else()
       set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
       set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
     endif()
     endif()
+
+    # Import target "assimp::assimp" for configuration "Debug"
+    set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
     set_target_properties(assimp::assimp PROPERTIES
     set_target_properties(assimp::assimp PROPERTIES
       IMPORTED_SONAME_DEBUG "${sharedLibraryName}"
       IMPORTED_SONAME_DEBUG "${sharedLibraryName}"
       IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}"
       IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}"
@@ -81,6 +84,9 @@ else()
     list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}" )
     list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}" )
   else()
   else()
     set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@")
     set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@")
+
+    # Import target "assimp::assimp" for configuration "Debug"
+    set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
     set_target_properties(assimp::assimp PROPERTIES
     set_target_properties(assimp::assimp PROPERTIES
       IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
       IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
     )
     )

+ 6 - 0
assimpTargets-release.cmake.in

@@ -73,6 +73,9 @@ else()
     else()
     else()
       set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
       set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
     endif()
     endif()
+
+    # Import target "assimp::assimp" for configuration "Release"
+    set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
     set_target_properties(assimp::assimp PROPERTIES
     set_target_properties(assimp::assimp PROPERTIES
       IMPORTED_SONAME_RELEASE "${sharedLibraryName}"
       IMPORTED_SONAME_RELEASE "${sharedLibraryName}"
       IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}"
       IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}"
@@ -81,6 +84,9 @@ else()
     list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}" )
     list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}" )
   else()
   else()
     set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@")
     set(staticLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@")
+
+    # Import target "assimp::assimp" for configuration "Release"
+    set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
     set_target_properties(assimp::assimp PROPERTIES
     set_target_properties(assimp::assimp PROPERTIES
       IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
       IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
     )
     )

+ 707 - 0
code/AMF/AMFImporter.cpp

@@ -0,0 +1,707 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+/// \file AMFImporter.cpp
+/// \brief AMF-format files importer for Assimp: main algorithm implementation.
+/// \date 2016
+/// \author [email protected]
+
+#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
+
+// Header files, Assimp.
+#include "AMFImporter.hpp"
+#include "AMFImporter_Macro.hpp"
+
+#include <assimp/fast_atof.h>
+#include <assimp/DefaultIOSystem.h>
+
+// Header files, stdlib.
+#include <memory>
+
+namespace Assimp
+{
+
+/// \var aiImporterDesc AMFImporter::Description
+/// Conastant which hold importer description
+const aiImporterDesc AMFImporter::Description = {
+	"Additive manufacturing file format(AMF) Importer",
+	"smalcom",
+	"",
+	"See documentation in source code. Chapter: Limitations.",
+	aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
+	0,
+	0,
+	0,
+	0,
+	"amf"
+};
+
+void AMFImporter::Clear()
+{
+	mNodeElement_Cur = nullptr;
+	mUnit.clear();
+	mMaterial_Converted.clear();
+	mTexture_Converted.clear();
+	// Delete all elements
+	if(!mNodeElement_List.empty())
+	{
+		for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; }
+
+		mNodeElement_List.clear();
+	}
+}
+
+AMFImporter::~AMFImporter()
+{
+	if(mReader != nullptr) delete mReader;
+	// Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
+	Clear();
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************ Functions: find set ************************************************************/
+/*********************************************************************************************************************************************/
+
+bool AMFImporter::Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const
+{
+	for(CAMFImporter_NodeElement* ne: mNodeElement_List)
+	{
+		if((ne->ID == pID) && (ne->Type == pType))
+		{
+			if(pNodeElement != nullptr) *pNodeElement = ne;
+
+			return true;
+		}
+	}// for(CAMFImporter_NodeElement* ne: mNodeElement_List)
+
+	return false;
+}
+
+bool AMFImporter::Find_ConvertedNode(const std::string& pID, std::list<aiNode*>& pNodeList, aiNode** pNode) const
+{
+aiString node_name(pID.c_str());
+
+	for(aiNode* node: pNodeList)
+	{
+		if(node->mName == node_name)
+		{
+			if(pNode != nullptr) *pNode = node;
+
+			return true;
+		}
+	}// for(aiNode* node: pNodeList)
+
+	return false;
+}
+
+bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const
+{
+	for(const SPP_Material& mat: mMaterial_Converted)
+	{
+		if(mat.ID == pID)
+		{
+			if(pConvertedMaterial != nullptr) *pConvertedMaterial = &mat;
+
+			return true;
+		}
+	}// for(const SPP_Material& mat: mMaterial_Converted)
+
+	return false;
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************ Functions: throw set ***********************************************************/
+/*********************************************************************************************************************************************/
+
+void AMFImporter::Throw_CloseNotFound(const std::string& pNode)
+{
+	throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt.");
+}
+
+void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName)
+{
+	throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\".");
+}
+
+void AMFImporter::Throw_IncorrectAttrValue(const std::string& pAttrName)
+{
+	throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value.");
+}
+
+void AMFImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription)
+{
+	throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription);
+}
+
+void AMFImporter::Throw_ID_NotFound(const std::string& pID) const
+{
+	throw DeadlyImportError("Not found node with name \"" + pID + "\".");
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************* Functions: XML set ************************************************************/
+/*********************************************************************************************************************************************/
+
+void AMFImporter::XML_CheckNode_MustHaveChildren()
+{
+	if(mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children.");
+}
+
+void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
+{
+    static const size_t Uns_Skip_Len = 3;
+    const char* Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" };
+
+    static bool skipped_before[Uns_Skip_Len] = { false, false, false };
+
+    std::string nn(mReader->getNodeName());
+    bool found = false;
+    bool close_found = false;
+    size_t sk_idx;
+
+	for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
+	{
+		if(nn != Uns_Skip[sk_idx]) continue;
+
+		found = true;
+		if(mReader->isEmptyElement())
+		{
+			close_found = true;
+
+			goto casu_cres;
+		}
+
+		while(mReader->read())
+		{
+			if((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName()))
+			{
+				close_found = true;
+
+				goto casu_cres;
+			}
+		}
+	}// for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
+
+casu_cres:
+
+	if(!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + ".");
+	if(!close_found) Throw_CloseNotFound(nn);
+
+	if(!skipped_before[sk_idx])
+	{
+		skipped_before[sk_idx] = true;
+        ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, ".");
+	}
+}
+
+bool AMFImporter::XML_SearchNode(const std::string& pNodeName)
+{
+	while(mReader->read())
+	{
+		if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true;
+	}
+
+	return false;
+}
+
+bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
+{
+    std::string val(mReader->getAttributeValue(pAttrIdx));
+
+	if((val == "false") || (val == "0"))
+		return false;
+	else if((val == "true") || (val == "1"))
+		return true;
+	else
+		throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\"");
+}
+
+float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
+{
+    std::string val;
+    float tvalf;
+
+	ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
+	fast_atoreal_move(val.c_str(), tvalf, false);
+
+	return tvalf;
+}
+
+uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx)
+{
+	return strtoul10(mReader->getAttributeValue(pAttrIdx));
+}
+
+float AMFImporter::XML_ReadNode_GetVal_AsFloat()
+{
+    std::string val;
+    float tvalf;
+
+	if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt.");
+	if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt.");
+
+	ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val);
+	fast_atoreal_move(val.c_str(), tvalf, false);
+
+	return tvalf;
+}
+
+uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32()
+{
+	if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt.");
+	if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt.");
+
+	return strtoul10(mReader->getNodeData());
+}
+
+void AMFImporter::XML_ReadNode_GetVal_AsString(std::string& pValue)
+{
+	if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt.");
+	if(mReader->getNodeType() != irr::io::EXN_TEXT)
+		throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt.");
+
+	pValue = mReader->getNodeData();
+}
+
+/*********************************************************************************************************************************************/
+/************************************************************ Functions: parse set ***********************************************************/
+/*********************************************************************************************************************************************/
+
+void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode)
+{
+	mNodeElement_Cur->Child.push_back(pNode);// add new element to current element child list.
+	mNodeElement_Cur = pNode;// switch current element to new one.
+}
+
+void AMFImporter::ParseHelper_Node_Exit()
+{
+	// check if we can walk up.
+	if(mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent;
+}
+
+void AMFImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString)
+{
+    size_t instr_len;
+
+	pOutString.clear();
+	instr_len = strlen(pInStr);
+	if(!instr_len) return;
+
+	pOutString.reserve(instr_len * 3 / 2);
+	// check and correct floats in format ".x". Must be "x.y".
+	if(pInStr[0] == '.') pOutString.push_back('0');
+
+	pOutString.push_back(pInStr[0]);
+	for(size_t ci = 1; ci < instr_len; ci++)
+	{
+		if((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t')))
+		{
+			pOutString.push_back('0');
+			pOutString.push_back('.');
+		}
+		else
+		{
+			pOutString.push_back(pInStr[ci]);
+		}
+	}
+}
+
+static bool ParseHelper_Decode_Base64_IsBase64(const char pChar)
+{
+	return (isalnum(pChar) || (pChar == '+') || (pChar == '/'));
+}
+
+void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const
+{
+    // With help from
+    // René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html
+    const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+
+    uint8_t tidx = 0;
+    uint8_t arr4[4], arr3[3];
+
+	// check input data
+	if(pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
+	// prepare output place
+	pOutputData.clear();
+	pOutputData.reserve(pInputBase64.size() / 4 * 3);
+
+	for(size_t in_len = pInputBase64.size(), in_idx = 0; (in_len > 0) && (pInputBase64[in_idx] != '='); in_len--)
+	{
+		if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx]))
+		{
+			arr4[tidx++] = pInputBase64[in_idx++];
+			if(tidx == 4)
+			{
+				for(tidx = 0; tidx < 4; tidx++) arr4[tidx] = (uint8_t)base64_chars.find(arr4[tidx]);
+
+				arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4);
+				arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2);
+				arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3];
+				for(tidx = 0; tidx < 3; tidx++) pOutputData.push_back(arr3[tidx]);
+
+				tidx = 0;
+			}// if(tidx == 4)
+		}// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx]))
+		else
+		{
+			in_idx++;
+		}// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) else
+	}
+
+	if(tidx)
+	{
+		for(uint8_t i = tidx; i < 4; i++) arr4[i] = 0;
+		for(uint8_t i = 0; i < 4; i++) arr4[i] = (uint8_t)(base64_chars.find(arr4[i]));
+
+		arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4);
+		arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2);
+		arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3];
+		for(uint8_t i = 0; i < (tidx - 1); i++) pOutputData.push_back(arr3[i]);
+	}
+}
+
+void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
+{
+    irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader.
+    std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
+
+	// Check whether we can read from the file
+    if (file.get() == nullptr) {
+        throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
+    }
+
+	// generate a XML reader for it
+	std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
+	mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
+	if(!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
+	//
+	// start reading
+	// search for root tag <amf>
+	if(XML_SearchNode("amf"))
+		ParseNode_Root();
+	else
+		throw DeadlyImportError("Root node \"amf\" not found.");
+
+	delete mReader;
+	// restore old XMLreader
+	mReader = OldReader;
+}
+
+// <amf
+// unit="" - The units to be used. May be "inch", "millimeter", "meter", "feet", or "micron".
+// version="" - Version of file format.
+// >
+// </amf>
+// Root XML element.
+// Multi elements - No.
+void AMFImporter::ParseNode_Root()
+{
+    std::string unit, version;
+    CAMFImporter_NodeElement *ne( nullptr );
+
+	// Read attributes for node <amf>.
+	MACRO_ATTRREAD_LOOPBEG;
+		MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue);
+		MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue);
+	MACRO_ATTRREAD_LOOPEND_WSKIP;
+
+	// Check attributes
+	if(!mUnit.empty())
+	{
+		if((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) Throw_IncorrectAttrValue("unit");
+	}
+
+	// create root node element.
+	ne = new CAMFImporter_NodeElement_Root(nullptr);
+	mNodeElement_Cur = ne;// set first "current" element
+	// and assign attribute's values
+	((CAMFImporter_NodeElement_Root*)ne)->Unit = unit;
+	((CAMFImporter_NodeElement_Root*)ne)->Version = version;
+
+	// Check for child nodes
+	if(!mReader->isEmptyElement())
+	{
+		MACRO_NODECHECK_LOOPBEGIN("amf");
+			if(XML_CheckNode_NameEqual("object")) { ParseNode_Object(); continue; }
+			if(XML_CheckNode_NameEqual("material")) { ParseNode_Material(); continue; }
+			if(XML_CheckNode_NameEqual("texture")) { ParseNode_Texture(); continue; }
+			if(XML_CheckNode_NameEqual("constellation")) { ParseNode_Constellation(); continue; }
+			if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
+		MACRO_NODECHECK_LOOPEND("amf");
+		mNodeElement_Cur = ne;// force restore "current" element
+	}// if(!mReader->isEmptyElement())
+
+	mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph.
+}
+
+// <constellation
+// id="" - The Object ID of the new constellation being defined.
+// >
+// </constellation>
+// A collection of objects or constellations with specific relative locations.
+// Multi elements - Yes.
+// Parent element - <amf>.
+void AMFImporter::ParseNode_Constellation()
+{
+    std::string id;
+    CAMFImporter_NodeElement* ne( nullptr );
+
+	// Read attributes for node <constellation>.
+	MACRO_ATTRREAD_LOOPBEG;
+		MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
+	MACRO_ATTRREAD_LOOPEND;
+
+	// create and if needed - define new grouping object.
+	ne = new CAMFImporter_NodeElement_Constellation(mNodeElement_Cur);
+
+	CAMFImporter_NodeElement_Constellation& als = *((CAMFImporter_NodeElement_Constellation*)ne);// alias for convenience
+
+	if(!id.empty()) als.ID = id;
+	// Check for child nodes
+	if(!mReader->isEmptyElement())
+	{
+		ParseHelper_Node_Enter(ne);
+		MACRO_NODECHECK_LOOPBEGIN("constellation");
+			if(XML_CheckNode_NameEqual("instance")) { ParseNode_Instance(); continue; }
+			if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
+		MACRO_NODECHECK_LOOPEND("constellation");
+		ParseHelper_Node_Exit();
+	}// if(!mReader->isEmptyElement())
+	else
+	{
+		mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+	}// if(!mReader->isEmptyElement()) else
+
+	mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <instance
+// objectid="" - The Object ID of the new constellation being defined.
+// >
+// </instance>
+// A collection of objects or constellations with specific relative locations.
+// Multi elements - Yes.
+// Parent element - <amf>.
+void AMFImporter::ParseNode_Instance()
+{
+    std::string objectid;
+    CAMFImporter_NodeElement* ne( nullptr );
+
+	// Read attributes for node <constellation>.
+	MACRO_ATTRREAD_LOOPBEG;
+		MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue);
+	MACRO_ATTRREAD_LOOPEND;
+
+	// used object id must be defined, check that.
+	if(objectid.empty()) throw DeadlyImportError("\"objectid\" in <instance> must be defined.");
+	// create and define new grouping object.
+	ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur);
+
+	CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne);// alias for convenience
+
+	als.ObjectID = objectid;
+	// Check for child nodes
+	if(!mReader->isEmptyElement())
+	{
+		bool read_flag[6] = { false, false, false, false, false, false };
+
+		als.Delta.Set(0, 0, 0);
+		als.Rotation.Set(0, 0, 0);
+		ParseHelper_Node_Enter(ne);
+		MACRO_NODECHECK_LOOPBEGIN("instance");
+			MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x);
+			MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y);
+			MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z);
+			MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x);
+			MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y);
+			MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z);
+		MACRO_NODECHECK_LOOPEND("instance");
+		ParseHelper_Node_Exit();
+		// also convert degrees to radians.
+		als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f;
+		als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f;
+		als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f;
+	}// if(!mReader->isEmptyElement())
+	else
+	{
+		mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+	}// if(!mReader->isEmptyElement()) else
+
+	mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <object
+// id="" - A unique ObjectID for the new object being defined.
+// >
+// </object>
+// An object definition.
+// Multi elements - Yes.
+// Parent element - <amf>.
+void AMFImporter::ParseNode_Object()
+{
+    std::string id;
+    CAMFImporter_NodeElement* ne( nullptr );
+
+	// Read attributes for node <object>.
+	MACRO_ATTRREAD_LOOPBEG;
+		MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
+	MACRO_ATTRREAD_LOOPEND;
+
+	// create and if needed - define new geometry object.
+	ne = new CAMFImporter_NodeElement_Object(mNodeElement_Cur);
+
+	CAMFImporter_NodeElement_Object& als = *((CAMFImporter_NodeElement_Object*)ne);// alias for convenience
+
+	if(!id.empty()) als.ID = id;
+	// Check for child nodes
+	if(!mReader->isEmptyElement())
+	{
+		bool col_read = false;
+
+		ParseHelper_Node_Enter(ne);
+		MACRO_NODECHECK_LOOPBEGIN("object");
+			if(XML_CheckNode_NameEqual("color"))
+			{
+				// Check if color already defined for object.
+				if(col_read) Throw_MoreThanOnceDefined("color", "Only one color can be defined for <object>.");
+				// read data and set flag about it
+				ParseNode_Color();
+				col_read = true;
+
+				continue;
+			}
+
+			if(XML_CheckNode_NameEqual("mesh")) { ParseNode_Mesh(); continue; }
+			if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
+		MACRO_NODECHECK_LOOPEND("object");
+		ParseHelper_Node_Exit();
+	}// if(!mReader->isEmptyElement())
+	else
+	{
+		mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+	}// if(!mReader->isEmptyElement()) else
+
+	mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+// <metadata
+// type="" - The type of the attribute.
+// >
+// </metadata>
+// Specify additional information about an entity.
+// Multi elements - Yes.
+// Parent element - <amf>, <object>, <volume>, <material>, <vertex>.
+//
+// Reserved types are:
+// "Name" - The alphanumeric label of the entity, to be used by the interpreter if interacting with the user.
+// "Description" - A description of the content of the entity
+// "URL" - A link to an external resource relating to the entity
+// "Author" - Specifies the name(s) of the author(s) of the entity
+// "Company" - Specifying the company generating the entity
+// "CAD" - specifies the name of the originating CAD software and version
+// "Revision" - specifies the revision of the entity
+// "Tolerance" - specifies the desired manufacturing tolerance of the entity in entity's unit system
+// "Volume" - specifies the total volume of the entity, in the entity's unit system, to be used for verification (object and volume only)
+void AMFImporter::ParseNode_Metadata()
+{
+    std::string type, value;
+    CAMFImporter_NodeElement* ne( nullptr );
+
+	// read attribute
+	MACRO_ATTRREAD_LOOPBEG;
+		MACRO_ATTRREAD_CHECK_RET("type", type, mReader->getAttributeValue);
+	MACRO_ATTRREAD_LOOPEND;
+	// and value of node.
+	value = mReader->getNodeData();
+	// Create node element and assign read data.
+	ne = new CAMFImporter_NodeElement_Metadata(mNodeElement_Cur);
+	((CAMFImporter_NodeElement_Metadata*)ne)->Type = type;
+	((CAMFImporter_NodeElement_Metadata*)ne)->Value = value;
+	mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
+	mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
+}
+
+/*********************************************************************************************************************************************/
+/******************************************************** Functions: BaseImporter set ********************************************************/
+/*********************************************************************************************************************************************/
+
+bool AMFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool pCheckSig) const
+{
+    const std::string extension = GetExtension(pFile);
+
+    if ( extension == "amf" ) {
+        return true;
+    }
+
+	if(!extension.length() || pCheckSig)
+	{
+		const char* tokens[] = { "<amf" };
+
+		return SearchFileHeaderForToken( pIOHandler, pFile, tokens, 1 );
+	}
+
+	return false;
+}
+
+void AMFImporter::GetExtensionList(std::set<std::string>& pExtensionList)
+{
+	pExtensionList.insert("amf");
+}
+
+const aiImporterDesc* AMFImporter::GetInfo () const
+{
+	return &Description;
+}
+
+void AMFImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler)
+{
+	Clear();// delete old graph.
+	ParseFile(pFile, pIOHandler);
+	Postprocess_BuildScene(pScene);
+	// scene graph is ready, exit.
+}
+
+}// namespace Assimp
+
+#endif // !ASSIMP_BUILD_NO_AMF_IMPORTER

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

@@ -539,7 +539,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
         ai_assert(nullptr != anim);
         ai_assert(nullptr != anim);
 
 
         if (pcIn->aCameraRollKeys.size() > 1) {
         if (pcIn->aCameraRollKeys.size() > 1) {
-            ASSIMP_LOG_DEBUG("3DS: Converting camera roll track ...");
+            ASSIMP_LOG_VERBOSE_DEBUG("3DS: Converting camera roll track ...");
 
 
             // Camera roll keys - in fact they're just rotations
             // Camera roll keys - in fact they're just rotations
             // around the camera's z axis. The angles are given
             // around the camera's z axis. The angles are given
@@ -558,7 +558,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut,
 #if 0
 #if 0
         if (pcIn->aTargetPositionKeys.size() > 1)
         if (pcIn->aTargetPositionKeys.size() > 1)
         {
         {
-            ASSIMP_LOG_DEBUG("3DS: Converting target track ...");
+            ASSIMP_LOG_VERBOSE_DEBUG("3DS: Converting target track ...");
 
 
             // Camera or spot light - need to convert the separate
             // Camera or spot light - need to convert the separate
             // target position channel to our representation
             // target position channel to our representation

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

@@ -367,7 +367,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial &mat, aiTextureType type
         aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
         aiTextureMapMode_Wrap, aiTextureMapMode_Wrap
     };
     };
     ai_real blend = 1.0;
     ai_real blend = 1.0;
-    if (mat.GetTexture(type, 0, &path, NULL, NULL, &blend, NULL, map_mode) != AI_SUCCESS || !path.length) {
+    if (mat.GetTexture(type, 0, &path, nullptr, nullptr, &blend, nullptr, map_mode) != AI_SUCCESS || !path.length) {
         return;
         return;
     }
     }
 
 

+ 25 - 22
code/AssetLib/3DS/3DSHelper.h

@@ -462,30 +462,28 @@ struct Material {
             sTexAmbient(other.sTexAmbient),
             sTexAmbient(other.sTexAmbient),
             mTwoSided(other.mTwoSided) {
             mTwoSided(other.mTwoSided) {
         // empty
         // empty
-
     }
     }
 
 
     //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
     //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
-    Material(Material &&other) AI_NO_EXCEPT :
-            mName(std::move(other.mName)),
-            mDiffuse(std::move(other.mDiffuse)),
-            mSpecularExponent(std::move(other.mSpecularExponent)),
-            mShininessStrength(std::move(other.mShininessStrength)),
-            mSpecular(std::move(other.mSpecular)),
-            mAmbient(std::move(other.mAmbient)),
-            mShading(std::move(other.mShading)),
-            mTransparency(std::move(other.mTransparency)),
-            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(std::move(other.mBumpHeight)),
-            mEmissive(std::move(other.mEmissive)),
-            sTexAmbient(std::move(other.sTexAmbient)),
-            mTwoSided(std::move(other.mTwoSided)) {
+    Material(Material &&other) AI_NO_EXCEPT : mName(std::move(other.mName)),
+                                              mDiffuse(std::move(other.mDiffuse)),
+                                              mSpecularExponent(std::move(other.mSpecularExponent)),
+                                              mShininessStrength(std::move(other.mShininessStrength)),
+                                              mSpecular(std::move(other.mSpecular)),
+                                              mAmbient(std::move(other.mAmbient)),
+                                              mShading(std::move(other.mShading)),
+                                              mTransparency(std::move(other.mTransparency)),
+                                              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(std::move(other.mBumpHeight)),
+                                              mEmissive(std::move(other.mEmissive)),
+                                              sTexAmbient(std::move(other.sTexAmbient)),
+                                              mTwoSided(std::move(other.mTwoSided)) {
         // empty
         // empty
     }
     }
 
 
@@ -615,7 +613,12 @@ struct Node {
     Node() = delete;
     Node() = delete;
 
 
     explicit Node(const std::string &name) :
     explicit Node(const std::string &name) :
-            mParent(NULL), mName(name), mInstanceNumber(0), mHierarchyPos(0), mHierarchyIndex(0), mInstanceCount(1) {
+            mParent(nullptr),
+            mName(name),
+            mInstanceNumber(0),
+            mHierarchyPos(0),
+            mHierarchyIndex(0),
+            mInstanceCount(1) {
         aRotationKeys.reserve(20);
         aRotationKeys.reserve(20);
         aPositionKeys.reserve(20);
         aPositionKeys.reserve(20);
         aScalingKeys.reserve(20);
         aScalingKeys.reserve(20);

+ 4 - 4
code/AssetLib/3MF/D3MFImporter.cpp

@@ -314,19 +314,19 @@ private:
         ++buf;
         ++buf;
         comp[1] = *buf;
         comp[1] = *buf;
         ++buf;
         ++buf;
-        diffuse.r = static_cast<ai_real>(strtol(comp, NULL, 16)) / ai_real(255.0);
+        diffuse.r = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
 
 
         comp[0] = *buf;
         comp[0] = *buf;
         ++buf;
         ++buf;
         comp[1] = *buf;
         comp[1] = *buf;
         ++buf;
         ++buf;
-        diffuse.g = static_cast<ai_real>(strtol(comp, NULL, 16)) / ai_real(255.0);
+        diffuse.g = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
 
 
         comp[0] = *buf;
         comp[0] = *buf;
         ++buf;
         ++buf;
         comp[1] = *buf;
         comp[1] = *buf;
         ++buf;
         ++buf;
-        diffuse.b = static_cast<ai_real>(strtol(comp, NULL, 16)) / ai_real(255.0);
+        diffuse.b = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
 
 
         if (7 == len)
         if (7 == len)
             return true;
             return true;
@@ -334,7 +334,7 @@ private:
         ++buf;
         ++buf;
         comp[1] = *buf;
         comp[1] = *buf;
         ++buf;
         ++buf;
-        diffuse.a = static_cast<ai_real>(strtol(comp, NULL, 16)) / ai_real(255.0);
+        diffuse.a = static_cast<ai_real>(strtol(comp, nullptr, 16)) / ai_real(255.0);
 
 
         return true;
         return true;
     }
     }

+ 53 - 56
code/AssetLib/3MF/D3MFOpcPackage.cpp

@@ -45,19 +45,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "D3MFOpcPackage.h"
 #include "D3MFOpcPackage.h"
 #include <assimp/Exceptional.h>
 #include <assimp/Exceptional.h>
 
 
+#include <assimp/ZipArchiveIOSystem.h>
+#include <assimp/ai_assert.h>
+#include <assimp/DefaultLogger.hpp>
 #include <assimp/IOStream.hpp>
 #include <assimp/IOStream.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/ai_assert.h>
-#include <assimp/ZipArchiveIOSystem.h>
 
 
+#include "3MFXmlTags.h"
+#include <algorithm>
+#include <cassert>
 #include <cstdlib>
 #include <cstdlib>
+#include <map>
 #include <memory>
 #include <memory>
 #include <vector>
 #include <vector>
-#include <map>
-#include <algorithm>
-#include <cassert>
-#include "3MFXmlTags.h"
 
 
 namespace Assimp {
 namespace Assimp {
 
 
@@ -68,49 +68,45 @@ typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
 
 
 class OpcPackageRelationshipReader {
 class OpcPackageRelationshipReader {
 public:
 public:
-    OpcPackageRelationshipReader(XmlReader* xmlReader) {        
-        while(xmlReader->read()) {
-            if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
-               xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER)
-            {
+    OpcPackageRelationshipReader(XmlReader *xmlReader) {
+        while (xmlReader->read()) {
+            if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
+                    xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER) {
                 ParseRootNode(xmlReader);
                 ParseRootNode(xmlReader);
             }
             }
         }
         }
     }
     }
 
 
-    void ParseRootNode(XmlReader* xmlReader)
-    {       
+    void ParseRootNode(XmlReader *xmlReader) {
         ParseAttributes(xmlReader);
         ParseAttributes(xmlReader);
 
 
-        while(xmlReader->read())
-        {
-            if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
-               xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_NODE)
-            {
+        while (xmlReader->read()) {
+            if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
+                    xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_NODE) {
                 ParseChildNode(xmlReader);
                 ParseChildNode(xmlReader);
             }
             }
         }
         }
     }
     }
 
 
-    void ParseAttributes(XmlReader*) {
+    void ParseAttributes(XmlReader *) {
         // empty
         // empty
     }
     }
 
 
-    bool validateRels( OpcPackageRelationshipPtr &relPtr ) {
-        if ( relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty() ) {
+    bool validateRels(OpcPackageRelationshipPtr &relPtr) {
+        if (relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty()) {
             return false;
             return false;
         }
         }
         return true;
         return true;
     }
     }
 
 
-    void ParseChildNode(XmlReader* xmlReader) {        
+    void ParseChildNode(XmlReader *xmlReader) {
         OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
         OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
 
 
         relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str());
         relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str());
         relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str());
         relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str());
         relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str());
         relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str());
-        if ( validateRels( relPtr ) ) {
-            m_relationShips.push_back( relPtr );
+        if (validateRels(relPtr)) {
+            m_relationShips.push_back(relPtr);
         }
         }
     }
     }
 
 
@@ -118,51 +114,52 @@ public:
 };
 };
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
-: mRootStream(nullptr)
-, mZipArchive() {    
-    mZipArchive.reset( new ZipArchiveIOSystem( pIOHandler, rFile ) );
-    if(!mZipArchive->isOpen()) {
-        throw DeadlyImportError("Failed to open file " + rFile+ ".");
+D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
+        mRootStream(nullptr), mZipArchive() {
+    mZipArchive.reset(new ZipArchiveIOSystem(pIOHandler, rFile));
+    if (!mZipArchive->isOpen()) {
+        throw DeadlyImportError("Failed to open file " + rFile + ".");
     }
     }
 
 
     std::vector<std::string> fileList;
     std::vector<std::string> fileList;
     mZipArchive->getFileList(fileList);
     mZipArchive->getFileList(fileList);
 
 
-    for (auto& file: fileList) {
-        if(file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE) {
-            //PkgRelationshipReader pkgRelReader(file, archive);
-            ai_assert(mZipArchive->Exists(file.c_str()));
+    for (auto &file : fileList) {
+        if (file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE) {
+            if (!mZipArchive->Exists(file.c_str())) {
+                continue;
+            }
 
 
             IOStream *fileStream = mZipArchive->Open(file.c_str());
             IOStream *fileStream = mZipArchive->Open(file.c_str());
-
-            ai_assert(fileStream != nullptr);
+            if (nullptr == fileStream) {
+                ai_assert(fileStream != nullptr);
+                continue;
+            }
 
 
             std::string rootFile = ReadPackageRootRelationship(fileStream);
             std::string rootFile = ReadPackageRootRelationship(fileStream);
-            if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) {
-                rootFile = rootFile.substr( 1 );
-                if ( rootFile[ 0 ] == '/' ) {
+            if (rootFile.size() > 0 && rootFile[0] == '/') {
+                rootFile = rootFile.substr(1);
+                if (rootFile[0] == '/') {
                     // deal with zip-bug
                     // deal with zip-bug
-                    rootFile = rootFile.substr( 1 );
+                    rootFile = rootFile.substr(1);
                 }
                 }
             }
             }
 
 
-            ASSIMP_LOG_DEBUG(rootFile);
+            ASSIMP_LOG_VERBOSE_DEBUG(rootFile);
 
 
             mZipArchive->Close(fileStream);
             mZipArchive->Close(fileStream);
 
 
             mRootStream = mZipArchive->Open(rootFile.c_str());
             mRootStream = mZipArchive->Open(rootFile.c_str());
-            ai_assert( mRootStream != nullptr );
-            if ( nullptr == mRootStream ) {
-                throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile );
+            ai_assert(mRootStream != nullptr);
+            if (nullptr == mRootStream) {
+                throw DeadlyExportError("Cannot open root-file in archive : " + rootFile);
             }
             }
 
 
-        } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
-            ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES",file);
+        } else if (file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
+            ASSIMP_LOG_WARN_F("Ignored file of unsupported type CONTENT_TYPES_ARCHIVES", file);
         } else {
         } else {
-            ASSIMP_LOG_WARN_F("Ignored file of unknown type: ",file);
+            ASSIMP_LOG_WARN_F("Ignored file of unknown type: ", file);
         }
         }
-
     }
     }
 }
 }
 
 
@@ -170,32 +167,32 @@ D3MFOpcPackage::~D3MFOpcPackage() {
     mZipArchive->Close(mRootStream);
     mZipArchive->Close(mRootStream);
 }
 }
 
 
-IOStream* D3MFOpcPackage::RootStream() const {
+IOStream *D3MFOpcPackage::RootStream() const {
     return mRootStream;
     return mRootStream;
 }
 }
 
 
 static const std::string ModelRef = "3D/3dmodel.model";
 static const std::string ModelRef = "3D/3dmodel.model";
 
 
 bool D3MFOpcPackage::validate() {
 bool D3MFOpcPackage::validate() {
-    if ( nullptr == mRootStream || nullptr == mZipArchive ) {
+    if (nullptr == mRootStream || nullptr == mZipArchive) {
         return false;
         return false;
     }
     }
 
 
-    return mZipArchive->Exists( ModelRef.c_str() );
+    return mZipArchive->Exists(ModelRef.c_str());
 }
 }
 
 
-std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
+std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
     std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
     std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
     std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
     std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
 
 
     OpcPackageRelationshipReader reader(xml.get());
     OpcPackageRelationshipReader reader(xml.get());
 
 
-    auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr& rel){
+    auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) {
         return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
         return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
     });
     });
 
 
-    if ( itr == reader.m_relationShips.end() ) {
-        throw DeadlyImportError( "Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE );
+    if (itr == reader.m_relationShips.end()) {
+        throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
     }
     }
 
 
     return (*itr)->target;
     return (*itr)->target;

+ 3 - 3
code/AssetLib/AC/ACLoader.cpp

@@ -207,7 +207,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
         light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1);
         light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i", static_cast<unsigned int>(mLights->size()) - 1);
         obj.name = std::string(light->mName.data);
         obj.name = std::string(light->mName.data);
 
 
-        ASSIMP_LOG_DEBUG("AC3D: Light source encountered");
+        ASSIMP_LOG_VERBOSE_DEBUG("AC3D: Light source encountered");
         obj.type = Object::Light;
         obj.type = Object::Light;
     } else if (!ASSIMP_strincmp(buffer, "group", 5)) {
     } else if (!ASSIMP_strincmp(buffer, "group", 5)) {
         obj.type = Object::Group;
         obj.type = Object::Group;
@@ -294,7 +294,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object> &objects) {
                     // example writes no surf chunks
                     // example writes no surf chunks
                     if (!Q3DWorkAround) {
                     if (!Q3DWorkAround) {
                         ASSIMP_LOG_WARN("AC3D: SURF token was expected");
                         ASSIMP_LOG_WARN("AC3D: SURF token was expected");
-                        ASSIMP_LOG_DEBUG("Continuing with Quick3D Workaround enabled");
+                        ASSIMP_LOG_VERBOSE_DEBUG("Continuing with Quick3D Workaround enabled");
                     }
                     }
                     --buffer; // make sure the line is processed a second time
                     --buffer; // make sure the line is processed a second time
                     // break; --- see fix notes above
                     // break; --- see fix notes above
@@ -627,7 +627,7 @@ aiNode *AC3DImporter::ConvertObjectSection(Object &object,
                     std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
                     std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
                     ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: " + object.name);
                     ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: " + object.name);
 
 
-                    std::vector<aiMesh *> cpy(meshes.size() - oldm, NULL);
+                    std::vector<aiMesh *> cpy(meshes.size() - oldm, nullptr);
                     div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true);
                     div->Subdivide(&meshes[oldm], cpy.size(), &cpy.front(), object.subDiv, true);
                     std::copy(cpy.begin(), cpy.end(), meshes.begin() + oldm);
                     std::copy(cpy.begin(), cpy.end(), meshes.begin() + oldm);
 
 

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

@@ -366,7 +366,9 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
     std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
 
 
     // Check whether we can read from the file
     // Check whether we can read from the file
-    if (file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
+    if (file.get() == nullptr) {
+        throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
+    }
 
 
     // generate a XML reader for it
     // generate a XML reader for it
     std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
     std::unique_ptr<CIrrXML_IOStreamReader> mIOWrapper(new CIrrXML_IOStreamReader(file.get()));

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

@@ -1,4 +1,4 @@
-/*
+/*
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------

+ 1 - 1
code/AssetLib/AMF/AMFImporter_Macro.hpp

@@ -1,4 +1,4 @@
-/*
+/*
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------

+ 1 - 1
code/AssetLib/AMF/AMFImporter_Material.cpp

@@ -1,4 +1,4 @@
-/*
+/*
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------

+ 1 - 1
code/AssetLib/AMF/AMFImporter_Node.hpp

@@ -1,4 +1,4 @@
-/*
+/*
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------

+ 1 - 1
code/AssetLib/ASE/ASELoader.cpp

@@ -614,7 +614,7 @@ void ASEImporter::AddNodes(const std::vector<BaseNode *> &nodes,
             node->mNumChildren++;
             node->mNumChildren++;
 
 
             // What we did is so great, it is at least worth a debug message
             // What we did is so great, it is at least worth a debug message
-            ASSIMP_LOG_DEBUG("ASE: Generating separate target node (" + snode->mName + ")");
+            ASSIMP_LOG_VERBOSE_DEBUG("ASE: Generating separate target node (" + snode->mName + ")");
         }
         }
     }
     }
 
 

+ 5 - 5
code/AssetLib/ASE/ASEParser.cpp

@@ -925,7 +925,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode &mesh) {
 
 
                         ASSIMP_LOG_ERROR("ASE: Found target animation channel "
                         ASSIMP_LOG_ERROR("ASE: Found target animation channel "
                                          "but the node is neither a camera nor a spot light");
                                          "but the node is neither a camera nor a spot light");
-                        anim = NULL;
+                        anim = nullptr;
                     } else
                     } else
                         anim = &mesh.mTargetAnim;
                         anim = &mesh.mTargetAnim;
                 }
                 }
@@ -1797,14 +1797,14 @@ void Parser::ParseLV4MeshFace(ASE::Face &out) {
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshLongTriple(unsigned int *apOut) {
 void Parser::ParseLV4MeshLongTriple(unsigned int *apOut) {
-    ai_assert(NULL != apOut);
+    ai_assert(nullptr != apOut);
 
 
     for (unsigned int i = 0; i < 3; ++i)
     for (unsigned int i = 0; i < 3; ++i)
         ParseLV4MeshLong(apOut[i]);
         ParseLV4MeshLong(apOut[i]);
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut) {
 void Parser::ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut) {
-    ai_assert(NULL != apOut);
+    ai_assert(nullptr != apOut);
 
 
     // parse the index
     // parse the index
     ParseLV4MeshLong(rIndexOut);
     ParseLV4MeshLong(rIndexOut);
@@ -1814,7 +1814,7 @@ void Parser::ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) {
 void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) {
-    ai_assert(NULL != apOut);
+    ai_assert(nullptr != apOut);
 
 
     // parse the index
     // parse the index
     ParseLV4MeshLong(rIndexOut);
     ParseLV4MeshLong(rIndexOut);
@@ -1824,7 +1824,7 @@ void Parser::ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut) {
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Parser::ParseLV4MeshFloatTriple(ai_real *apOut) {
 void Parser::ParseLV4MeshFloatTriple(ai_real *apOut) {
-    ai_assert(NULL != apOut);
+    ai_assert(nullptr != apOut);
 
 
     for (unsigned int i = 0; i < 3; ++i)
     for (unsigned int i = 0; i < 3; ++i)
         ParseLV4MeshFloat(apOut[i]);
         ParseLV4MeshFloat(apOut[i]);

+ 94 - 122
code/AssetLib/ASE/ASEParser.h

@@ -40,15 +40,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 */
 */
 
 
-
 /** @file Defines the helper data structures for importing ASE files  */
 /** @file Defines the helper data structures for importing ASE files  */
 #ifndef AI_ASEFILEHELPER_H_INC
 #ifndef AI_ASEFILEHELPER_H_INC
 #define AI_ASEFILEHELPER_H_INC
 #define AI_ASEFILEHELPER_H_INC
 
 
 // public ASSIMP headers
 // public ASSIMP headers
-#include <assimp/types.h>
-#include <assimp/mesh.h>
 #include <assimp/anim.h>
 #include <assimp/anim.h>
+#include <assimp/mesh.h>
+#include <assimp/types.h>
 
 
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 
@@ -59,27 +58,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // ASE is quite similar to 3ds. We can reuse some structures
 // ASE is quite similar to 3ds. We can reuse some structures
 #include "AssetLib/3DS/3DSLoader.h"
 #include "AssetLib/3DS/3DSLoader.h"
 
 
-namespace Assimp    {
-namespace ASE   {
+namespace Assimp {
+namespace ASE {
 
 
 using namespace D3DS;
 using namespace D3DS;
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** Helper structure representing an ASE material */
 /** Helper structure representing an ASE material */
-struct Material : public D3DS::Material
-{
+struct Material : public D3DS::Material {
     //! Default constructor has been deleted
     //! Default constructor has been deleted
     Material() = delete;
     Material() = delete;
 
 
     //! Constructor with explicit name
     //! Constructor with explicit name
-    explicit Material(const std::string &name)
-    : D3DS::Material(name)
-    , pcInstance(NULL)
-    , bNeed (false) {
+    explicit Material(const std::string &name) :
+            D3DS::Material(name),
+            pcInstance(nullptr),
+            bNeed(false) {
         // empty
         // empty
     }
     }
 
 
-    Material(const Material &other)            = default;
+    Material(const Material &other) = default;
 
 
     Material &operator=(const Material &other) {
     Material &operator=(const Material &other) {
         if (this == &other) {
         if (this == &other) {
@@ -93,19 +91,16 @@ struct Material : public D3DS::Material
         return *this;
         return *this;
     }
     }
 
 
-
     //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
     //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
     Material(Material &&other) AI_NO_EXCEPT
     Material(Material &&other) AI_NO_EXCEPT
-    : D3DS::Material(std::move(other))
-    , avSubMaterials(std::move(other.avSubMaterials))
-    , pcInstance(std::move(other.pcInstance))
-    , bNeed(std::move(other.bNeed))
-    {
+            : D3DS::Material(std::move(other)),
+              avSubMaterials(std::move(other.avSubMaterials)),
+              pcInstance(std::move(other.pcInstance)),
+              bNeed(std::move(other.bNeed)) {
         other.pcInstance = nullptr;
         other.pcInstance = nullptr;
     }
     }
 
 
-
-    Material &operator=( Material &&other) AI_NO_EXCEPT {
+    Material &operator=(Material &&other) AI_NO_EXCEPT {
         if (this == &other) {
         if (this == &other) {
             return *this;
             return *this;
         }
         }
@@ -121,15 +116,13 @@ struct Material : public D3DS::Material
         return *this;
         return *this;
     }
     }
 
 
-
     ~Material() {}
     ~Material() {}
 
 
-
     //! Contains all sub materials of this material
     //! Contains all sub materials of this material
     std::vector<Material> avSubMaterials;
     std::vector<Material> avSubMaterials;
 
 
     //! aiMaterial object
     //! aiMaterial object
-    aiMaterial* pcInstance;
+    aiMaterial *pcInstance;
 
 
     //! Can we remove this material?
     //! Can we remove this material?
     bool bNeed;
     bool bNeed;
@@ -140,8 +133,8 @@ struct Material : public D3DS::Material
 struct Face : public FaceWithSmoothingGroup {
 struct Face : public FaceWithSmoothingGroup {
     //! Default constructor. Initializes everything with 0
     //! Default constructor. Initializes everything with 0
     Face() AI_NO_EXCEPT
     Face() AI_NO_EXCEPT
-    : iMaterial(DEFAULT_MATINDEX)
-    , iFace(0) {
+            : iMaterial(DEFAULT_MATINDEX),
+              iFace(0) {
         // empty
         // empty
     }
     }
 
 
@@ -172,8 +165,8 @@ struct Bone {
     Bone() = delete;
     Bone() = delete;
 
 
     //! Construction from an existing name
     //! Construction from an existing name
-    explicit Bone( const std::string& name)
-    : mName(name) {
+    explicit Bone(const std::string &name) :
+            mName(name) {
         // empty
         // empty
     }
     }
 
 
@@ -186,33 +179,34 @@ struct Bone {
 struct BoneVertex {
 struct BoneVertex {
     //! Bone and corresponding vertex weight.
     //! Bone and corresponding vertex weight.
     //! -1 for unrequired bones ....
     //! -1 for unrequired bones ....
-    std::vector<std::pair<int,float> > mBoneWeights;
+    std::vector<std::pair<int, float>> mBoneWeights;
 };
 };
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE file animation */
 /** Helper structure to represent an ASE file animation */
 struct Animation {
 struct Animation {
     enum Type {
     enum Type {
-        TRACK   = 0x0,
-        BEZIER  = 0x1,
-        TCB     = 0x2
-    } mRotationType, mScalingType, mPositionType;
+        TRACK = 0x0,
+        BEZIER = 0x1,
+        TCB = 0x2
+    } mRotationType,
+            mScalingType, mPositionType;
 
 
     Animation() AI_NO_EXCEPT
     Animation() AI_NO_EXCEPT
-    :   mRotationType   (TRACK)
-    ,   mScalingType    (TRACK)
-    ,   mPositionType   (TRACK) {
+            : mRotationType(TRACK),
+              mScalingType(TRACK),
+              mPositionType(TRACK) {
         // empty
         // empty
     }
     }
 
 
     //! List of track rotation keyframes
     //! List of track rotation keyframes
-    std::vector< aiQuatKey > akeyRotations;
+    std::vector<aiQuatKey> akeyRotations;
 
 
     //! List of track position keyframes
     //! List of track position keyframes
-    std::vector< aiVectorKey > akeyPositions;
+    std::vector<aiVectorKey> akeyPositions;
 
 
     //! List of track scaling keyframes
     //! List of track scaling keyframes
-    std::vector< aiVectorKey > akeyScaling;
+    std::vector<aiVectorKey> akeyScaling;
 };
 };
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -220,7 +214,7 @@ struct Animation {
 struct InheritanceInfo {
 struct InheritanceInfo {
     //! Default constructor
     //! Default constructor
     InheritanceInfo() AI_NO_EXCEPT {
     InheritanceInfo() AI_NO_EXCEPT {
-        for ( size_t i=0; i<3; ++i ) {
+        for (size_t i = 0; i < 3; ++i) {
             abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
             abInheritPosition[i] = abInheritRotation[i] = abInheritScaling[i] = true;
         }
         }
     }
     }
@@ -239,17 +233,15 @@ struct InheritanceInfo {
 /** Represents an ASE file node. Base class for mesh, light and cameras */
 /** Represents an ASE file node. Base class for mesh, light and cameras */
 struct BaseNode {
 struct BaseNode {
     enum Type {
     enum Type {
-        Light, 
-        Camera, 
-        Mesh, 
+        Light,
+        Camera,
+        Mesh,
         Dummy
         Dummy
     } mType;
     } mType;
 
 
     //! Construction from an existing name
     //! Construction from an existing name
-    BaseNode(Type _mType, const std::string &name)
-    : mType         (_mType)
-    , mName         (name)
-    , mProcessed    (false) {
+    BaseNode(Type _mType, const std::string &name) :
+            mType(_mType), mName(name), mProcessed(false) {
         // Set mTargetPosition to qnan
         // Set mTargetPosition to qnan
         const ai_real qnan = get_qnan();
         const ai_real qnan = get_qnan();
         mTargetPosition.x = qnan;
         mTargetPosition.x = qnan;
@@ -289,14 +281,9 @@ struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode {
     Mesh() = delete;
     Mesh() = delete;
 
 
     //! Construction from an existing name
     //! Construction from an existing name
-    explicit Mesh(const std::string &name)
-    : BaseNode( BaseNode::Mesh, name )
-    , mVertexColors()
-    , mBoneVertices()
-    , mBones()
-    , iMaterialIndex(Face::DEFAULT_MATINDEX)
-    , bSkip     (false) {
-        for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c) {
+    explicit Mesh(const std::string &name) :
+            BaseNode(BaseNode::Mesh, name), mVertexColors(), mBoneVertices(), mBones(), iMaterialIndex(Face::DEFAULT_MATINDEX), bSkip(false) {
+        for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) {
             this->mNumUVComponents[c] = 2;
             this->mNumUVComponents[c] = 2;
         }
         }
     }
     }
@@ -325,10 +312,8 @@ struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode {
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE light source */
 /** Helper structure to represent an ASE light source */
-struct Light : public BaseNode
-{
-    enum LightType
-    {
+struct Light : public BaseNode {
+    enum LightType {
         OMNI,
         OMNI,
         TARGET,
         TARGET,
         FREE,
         FREE,
@@ -339,17 +324,13 @@ struct Light : public BaseNode
     Light() = delete;
     Light() = delete;
 
 
     //! Construction from an existing name
     //! Construction from an existing name
-    explicit Light(const std::string &name)
-    : BaseNode   (BaseNode::Light, name)
-    , mLightType (OMNI)
-    , mColor     (1.f,1.f,1.f)
-    , mIntensity (1.f) // light is white by default
-    , mAngle     (45.f)
-    , mFalloff   (0.f)
-    {
+    explicit Light(const std::string &name) :
+            BaseNode(BaseNode::Light, name), mLightType(OMNI), mColor(1.f, 1.f, 1.f), mIntensity(1.f) // light is white by default
+            ,
+            mAngle(45.f),
+            mFalloff(0.f) {
     }
     }
 
 
-
     LightType mLightType;
     LightType mLightType;
     aiColor3D mColor;
     aiColor3D mColor;
     ai_real mIntensity;
     ai_real mIntensity;
@@ -359,10 +340,8 @@ struct Light : public BaseNode
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** Helper structure to represent an ASE camera */
 /** Helper structure to represent an ASE camera */
-struct Camera : public BaseNode
-{
-    enum CameraType
-    {
+struct Camera : public BaseNode {
+    enum CameraType {
         FREE,
         FREE,
         TARGET
         TARGET
     };
     };
@@ -370,18 +349,16 @@ struct Camera : public BaseNode
     //! Default constructor has been deleted
     //! Default constructor has been deleted
     Camera() = delete;
     Camera() = delete;
 
 
-
     //! Construction from an existing name
     //! Construction from an existing name
-    explicit Camera(const std::string &name)
-    : BaseNode    (BaseNode::Camera, name)
-    , mFOV        (0.75f)   // in radians
-    , mNear       (0.1f)
-    , mFar        (1000.f)  // could be zero
-    , mCameraType (FREE)
-    {
+    explicit Camera(const std::string &name) :
+            BaseNode(BaseNode::Camera, name), mFOV(0.75f) // in radians
+            ,
+            mNear(0.1f),
+            mFar(1000.f) // could be zero
+            ,
+            mCameraType(FREE) {
     }
     }
 
 
-
     ai_real mFOV, mNear, mFar;
     ai_real mFOV, mNear, mFar;
     CameraType mCameraType;
     CameraType mCameraType;
 };
 };
@@ -391,7 +368,7 @@ struct Camera : public BaseNode
 struct Dummy : public BaseNode {
 struct Dummy : public BaseNode {
     //! Constructor
     //! Constructor
     Dummy() AI_NO_EXCEPT
     Dummy() AI_NO_EXCEPT
-    : BaseNode  (BaseNode::Dummy, "DUMMY") {
+            : BaseNode(BaseNode::Dummy, "DUMMY") {
         // empty
         // empty
     }
     }
 };
 };
@@ -414,7 +391,6 @@ private:
     }
     }
 
 
 public:
 public:
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Construct a parser from a given input file which is
     //! Construct a parser from a given input file which is
     //! guaranteed to be terminated with zero.
     //! guaranteed to be terminated with zero.
@@ -422,15 +398,13 @@ public:
     //! @param fileFormatDefault Assumed file format version. If the
     //! @param fileFormatDefault Assumed file format version. If the
     //!   file format is specified in the file the new value replaces
     //!   file format is specified in the file the new value replaces
     //!   the default value.
     //!   the default value.
-    Parser (const char* szFile, unsigned int fileFormatDefault);
+    Parser(const char *szFile, unsigned int fileFormatDefault);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parses the file into the parsers internal representation
     //! Parses the file into the parsers internal representation
     void Parse();
     void Parse();
 
 
-
 private:
 private:
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse the *SCENE block in a file
     //! Parse the *SCENE block in a file
     void ParseLV1SceneBlock();
     void ParseLV1SceneBlock();
@@ -446,45 +420,45 @@ private:
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *<xxx>OBJECT block in a file
     //! Parse a *<xxx>OBJECT block in a file
     //! \param mesh Node to be filled
     //! \param mesh Node to be filled
-    void ParseLV1ObjectBlock(BaseNode& mesh);
+    void ParseLV1ObjectBlock(BaseNode &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MATERIAL blocks in a material list
     //! Parse a *MATERIAL blocks in a material list
     //! \param mat Material structure to be filled
     //! \param mat Material structure to be filled
-    void ParseLV2MaterialBlock(Material& mat);
+    void ParseLV2MaterialBlock(Material &mat);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *NODE_TM block in a file
     //! Parse a *NODE_TM block in a file
     //! \param mesh Node (!) object to be filled
     //! \param mesh Node (!) object to be filled
-    void ParseLV2NodeTransformBlock(BaseNode& mesh);
+    void ParseLV2NodeTransformBlock(BaseNode &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *TM_ANIMATION block in a file
     //! Parse a *TM_ANIMATION block in a file
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
-    void ParseLV2AnimationBlock(BaseNode& mesh);
-    void ParseLV3PosAnimationBlock(ASE::Animation& anim);
-    void ParseLV3ScaleAnimationBlock(ASE::Animation& anim);
-    void ParseLV3RotAnimationBlock(ASE::Animation& anim);
+    void ParseLV2AnimationBlock(BaseNode &mesh);
+    void ParseLV3PosAnimationBlock(ASE::Animation &anim);
+    void ParseLV3ScaleAnimationBlock(ASE::Animation &anim);
+    void ParseLV3RotAnimationBlock(ASE::Animation &anim);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH block in a file
     //! Parse a *MESH block in a file
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
-    void ParseLV2MeshBlock(Mesh& mesh);
+    void ParseLV2MeshBlock(Mesh &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *LIGHT_SETTINGS block in a file
     //! Parse a *LIGHT_SETTINGS block in a file
     //! \param light Light object to be filled
     //! \param light Light object to be filled
-    void ParseLV2LightSettingsBlock(Light& light);
+    void ParseLV2LightSettingsBlock(Light &light);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *CAMERA_SETTINGS block in a file
     //! Parse a *CAMERA_SETTINGS block in a file
     //! \param cam Camera object to be filled
     //! \param cam Camera object to be filled
-    void ParseLV2CameraSettingsBlock(Camera& cam);
+    void ParseLV2CameraSettingsBlock(Camera &cam);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse the *MAP_XXXXXX blocks in a material
     //! Parse the *MAP_XXXXXX blocks in a material
     //! \param map Texture structure to be filled
     //! \param map Texture structure to be filled
-    void ParseLV3MapBlock(Texture& map);
+    void ParseLV3MapBlock(Texture &map);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_VERTEX_LIST block in a file
     //! Parse a *MESH_VERTEX_LIST block in a file
@@ -493,7 +467,7 @@ private:
     //! A warning is sent to the logger if the validations fails.
     //! A warning is sent to the logger if the validations fails.
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
     void ParseLV3MeshVertexListBlock(
     void ParseLV3MeshVertexListBlock(
-        unsigned int iNumVertices,Mesh& mesh);
+            unsigned int iNumVertices, Mesh &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_FACE_LIST block in a file
     //! Parse a *MESH_FACE_LIST block in a file
@@ -502,7 +476,7 @@ private:
     //! A warning is sent to the logger if the validations fails.
     //! A warning is sent to the logger if the validations fails.
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
     void ParseLV3MeshFaceListBlock(
     void ParseLV3MeshFaceListBlock(
-        unsigned int iNumFaces,Mesh& mesh);
+            unsigned int iNumFaces, Mesh &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_TVERT_LIST block in a file
     //! Parse a *MESH_TVERT_LIST block in a file
@@ -512,7 +486,7 @@ private:
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
     //! \param iChannel Output UVW channel
     //! \param iChannel Output UVW channel
     void ParseLV3MeshTListBlock(
     void ParseLV3MeshTListBlock(
-        unsigned int iNumVertices,Mesh& mesh, unsigned int iChannel = 0);
+            unsigned int iNumVertices, Mesh &mesh, unsigned int iChannel = 0);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_TFACELIST block in a file
     //! Parse a *MESH_TFACELIST block in a file
@@ -522,7 +496,7 @@ private:
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
     //! \param iChannel Output UVW channel
     //! \param iChannel Output UVW channel
     void ParseLV3MeshTFaceListBlock(
     void ParseLV3MeshTFaceListBlock(
-        unsigned int iNumFaces,Mesh& mesh, unsigned int iChannel = 0);
+            unsigned int iNumFaces, Mesh &mesh, unsigned int iChannel = 0);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse an additional mapping channel
     //! Parse an additional mapping channel
@@ -530,7 +504,7 @@ private:
     //! \param iChannel Channel index to be filled
     //! \param iChannel Channel index to be filled
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
     void ParseLV3MappingChannel(
     void ParseLV3MappingChannel(
-        unsigned int iChannel, Mesh& mesh);
+            unsigned int iChannel, Mesh &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_CVERTLIST block in a file
     //! Parse a *MESH_CVERTLIST block in a file
@@ -539,7 +513,7 @@ private:
     //! A warning is sent to the logger if the validations fails.
     //! A warning is sent to the logger if the validations fails.
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
     void ParseLV3MeshCListBlock(
     void ParseLV3MeshCListBlock(
-        unsigned int iNumVertices, Mesh& mesh);
+            unsigned int iNumVertices, Mesh &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_CFACELIST block in a file
     //! Parse a *MESH_CFACELIST block in a file
@@ -548,70 +522,70 @@ private:
     //! A warning is sent to the logger if the validations fails.
     //! A warning is sent to the logger if the validations fails.
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
     void ParseLV3MeshCFaceListBlock(
     void ParseLV3MeshCFaceListBlock(
-        unsigned int iNumFaces, Mesh& mesh);
+            unsigned int iNumFaces, Mesh &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_NORMALS block in a file
     //! Parse a *MESH_NORMALS block in a file
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
-    void ParseLV3MeshNormalListBlock(Mesh& mesh);
+    void ParseLV3MeshNormalListBlock(Mesh &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_WEIGHTSblock in a file
     //! Parse a *MESH_WEIGHTSblock in a file
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
-    void ParseLV3MeshWeightsBlock(Mesh& mesh);
+    void ParseLV3MeshWeightsBlock(Mesh &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse the bone list of a file
     //! Parse the bone list of a file
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
     //! \param iNumBones Number of bones in the mesh
     //! \param iNumBones Number of bones in the mesh
-    void ParseLV4MeshBones(unsigned int iNumBones,Mesh& mesh);
+    void ParseLV4MeshBones(unsigned int iNumBones, Mesh &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse the bone vertices list of a file
     //! Parse the bone vertices list of a file
     //! \param mesh Mesh object to be filled
     //! \param mesh Mesh object to be filled
     //! \param iNumVertices Number of vertices to be parsed
     //! \param iNumVertices Number of vertices to be parsed
-    void ParseLV4MeshBonesVertices(unsigned int iNumVertices,Mesh& mesh);
+    void ParseLV4MeshBonesVertices(unsigned int iNumVertices, Mesh &mesh);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_FACE block in a file
     //! Parse a *MESH_FACE block in a file
     //! \param out receive the face data
     //! \param out receive the face data
-    void ParseLV4MeshFace(ASE::Face& out);
+    void ParseLV4MeshFace(ASE::Face &out);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_VERT block in a file
     //! Parse a *MESH_VERT block in a file
     //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
     //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
     //! \param apOut Output buffer (3 floats)
     //! \param apOut Output buffer (3 floats)
     //! \param rIndexOut Output index
     //! \param rIndexOut Output index
-    void ParseLV4MeshFloatTriple(ai_real* apOut, unsigned int& rIndexOut);
+    void ParseLV4MeshFloatTriple(ai_real *apOut, unsigned int &rIndexOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_VERT block in a file
     //! Parse a *MESH_VERT block in a file
     //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
     //! (also works for MESH_TVERT, MESH_CFACE, MESH_VERTCOL  ...)
     //! \param apOut Output buffer (3 floats)
     //! \param apOut Output buffer (3 floats)
-    void ParseLV4MeshFloatTriple(ai_real* apOut);
+    void ParseLV4MeshFloatTriple(ai_real *apOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_TFACE block in a file
     //! Parse a *MESH_TFACE block in a file
     //! (also works for MESH_CFACE)
     //! (also works for MESH_CFACE)
     //! \param apOut Output buffer (3 ints)
     //! \param apOut Output buffer (3 ints)
     //! \param rIndexOut Output index
     //! \param rIndexOut Output index
-    void ParseLV4MeshLongTriple(unsigned int* apOut, unsigned int& rIndexOut);
+    void ParseLV4MeshLongTriple(unsigned int *apOut, unsigned int &rIndexOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a *MESH_TFACE block in a file
     //! Parse a *MESH_TFACE block in a file
     //! (also works for MESH_CFACE)
     //! (also works for MESH_CFACE)
     //! \param apOut Output buffer (3 ints)
     //! \param apOut Output buffer (3 ints)
-    void ParseLV4MeshLongTriple(unsigned int* apOut);
+    void ParseLV4MeshLongTriple(unsigned int *apOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a single float element
     //! Parse a single float element
     //! \param fOut Output float
     //! \param fOut Output float
-    void ParseLV4MeshFloat(ai_real& fOut);
+    void ParseLV4MeshFloat(ai_real &fOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a single int element
     //! Parse a single int element
     //! \param iOut Output integer
     //! \param iOut Output integer
-    void ParseLV4MeshLong(unsigned int& iOut);
+    void ParseLV4MeshLong(unsigned int &iOut);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Skip everything to the next: '*' or '\0'
     //! Skip everything to the next: '*' or '\0'
@@ -625,17 +599,17 @@ private:
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Output a warning to the logger
     //! Output a warning to the logger
     //! \param szWarn Warn message
     //! \param szWarn Warn message
-    void LogWarning(const char* szWarn);
+    void LogWarning(const char *szWarn);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Output a message to the logger
     //! Output a message to the logger
     //! \param szWarn Message
     //! \param szWarn Message
-    void LogInfo(const char* szWarn);
+    void LogInfo(const char *szWarn);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Output an error to the logger
     //! Output an error to the logger
     //! \param szWarn Error message
     //! \param szWarn Error message
-    AI_WONT_RETURN void LogError(const char* szWarn) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void LogError(const char *szWarn) AI_WONT_RETURN_SUFFIX;
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Parse a string, enclosed in double quotation marks
     //! Parse a string, enclosed in double quotation marks
@@ -643,12 +617,11 @@ private:
     //! \param szName Name of the enclosing element -> used in error
     //! \param szName Name of the enclosing element -> used in error
     //! messages.
     //! messages.
     //! \return false if an error occurred
     //! \return false if an error occurred
-    bool ParseString(std::string& out,const char* szName);
+    bool ParseString(std::string &out, const char *szName);
 
 
 public:
 public:
-
     //! Pointer to current data
     //! Pointer to current data
-    const char* filePtr;
+    const char *filePtr;
 
 
     //! background color to be passed to the viewer
     //! background color to be passed to the viewer
     //! QNAN if none was found
     //! QNAN if none was found
@@ -695,9 +668,8 @@ public:
     unsigned int iFileFormat;
     unsigned int iFileFormat;
 };
 };
 
 
-
 } // Namespace ASE
 } // Namespace ASE
-} // Namespace ASSIMP
+} // namespace Assimp
 
 
 #endif // ASSIMP_BUILD_NO_3DS_IMPORTER
 #endif // ASSIMP_BUILD_NO_3DS_IMPORTER
 
 

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

@@ -336,7 +336,7 @@ protected:
     void WriteBinaryNode(IOStream *container, const aiNode *node) {
     void WriteBinaryNode(IOStream *container, const aiNode *node) {
         AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AINODE);
         AssbinChunkWriter chunk(container, ASSBIN_CHUNK_AINODE);
 
 
-        unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0);
+        unsigned int nb_metadata = (node->mMetaData != nullptr ? node->mMetaData->mNumProperties : 0);
 
 
         Write<aiString>(&chunk, node->mName);
         Write<aiString>(&chunk, node->mName);
         Write<aiMatrix4x4>(&chunk, node->mTransformation);
         Write<aiMatrix4x4>(&chunk, node->mTransformation);
@@ -744,7 +744,7 @@ public:
         };
         };
 
 
         try {
         try {
-            time_t tt = time(NULL);
+            time_t tt = time(nullptr);
 #if _WIN32
 #if _WIN32
             tm *p = gmtime(&tt);
             tm *p = gmtime(&tt);
 #else
 #else
@@ -790,7 +790,7 @@ public:
             // Up to here the data is uncompressed. For compressed files, the rest
             // Up to here the data is uncompressed. For compressed files, the rest
             // is compressed using standard DEFLATE from zlib.
             // is compressed using standard DEFLATE from zlib.
             if (compressed) {
             if (compressed) {
-                AssbinChunkWriter uncompressedStream(NULL, 0);
+                AssbinChunkWriter uncompressedStream(nullptr, 0);
                 WriteBinaryScene(&uncompressedStream, pScene);
                 WriteBinaryScene(&uncompressedStream, pScene);
 
 
                 uLongf uncompressedSize = static_cast<uLongf>(uncompressedStream.Tell());
                 uLongf uncompressedSize = static_cast<uLongf>(uncompressedStream.Tell());

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

@@ -604,7 +604,7 @@ void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) {
 
 
     // Read node graph
     // Read node graph
     //scene->mRootNode = new aiNode[1];
     //scene->mRootNode = new aiNode[1];
-    ReadBinaryNode(stream, &scene->mRootNode, (aiNode *)NULL);
+    ReadBinaryNode(stream, &scene->mRootNode, (aiNode *)nullptr);
 
 
     // Read all meshes
     // Read all meshes
     if (scene->mNumMeshes) {
     if (scene->mNumMeshes) {

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

@@ -189,7 +189,7 @@ static std::string encodeXML(const std::string &data) {
 // -----------------------------------------------------------------------------------
 // -----------------------------------------------------------------------------------
 // Write a text model dump
 // Write a text model dump
 static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene, IOStream *io, bool shortened) {
 static void WriteDump(const char *pFile, const char *cmd, const aiScene *scene, IOStream *io, bool shortened) {
-    time_t tt = ::time(NULL);
+    time_t tt = ::time(nullptr);
 #if _WIN32
 #if _WIN32
     tm *p = gmtime(&tt);
     tm *p = gmtime(&tt);
 #else
 #else

+ 24 - 31
code/AssetLib/BVH/BVHLoader.cpp

@@ -422,9 +422,9 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
     anim->mNumChannels = static_cast<unsigned int>(mNodes.size());
     anim->mNumChannels = static_cast<unsigned int>(mNodes.size());
     anim->mChannels = new aiNodeAnim *[anim->mNumChannels];
     anim->mChannels = new aiNodeAnim *[anim->mNumChannels];
 
 
-    // FIX: set the array elements to NULL to ensure proper deletion if an exception is thrown
+    // FIX: set the array elements to nullptr to ensure proper deletion if an exception is thrown
     for (unsigned int i = 0; i < anim->mNumChannels; ++i)
     for (unsigned int i = 0; i < anim->mNumChannels; ++i)
-        anim->mChannels[i] = NULL;
+        anim->mChannels[i] = nullptr;
 
 
     for (unsigned int a = 0; a < anim->mNumChannels; a++) {
     for (unsigned int a = 0; a < anim->mNumChannels; a++) {
         const Node &node = mNodes[a];
         const Node &node = mNodes[a];
@@ -493,37 +493,30 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
             for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) {
             for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) {
                 aiMatrix4x4 temp;
                 aiMatrix4x4 temp;
                 aiMatrix3x3 rotMatrix;
                 aiMatrix3x3 rotMatrix;
-                for (BVHLoader::ChannelType channel = Channel_RotationX; channel <= Channel_RotationZ; channel = (BVHLoader::ChannelType)(channel + 1)) {
-                    //Find channel in node
-                    std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
-
-                    if (mapIter == channelMap.end())
-                        throw DeadlyImportError("Missing rotation channel in node " + nodeName);
-                    else {
-                        int channelIdx = mapIter->second;
-                        // translate ZXY euler angels into a quaternion
+				for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++ channelIdx) {
+					switch (node.mChannels[channelIdx]) {
+                    case Channel_RotationX:
+                        {
                         const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
                         const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
-
-                        // Compute rotation transformations in the right order
-                        switch (channel) {
-                        case Channel_RotationX:
-                            aiMatrix4x4::RotationX(angle, temp);
-                            rotMatrix *= aiMatrix3x3(temp);
-                            break;
-                        case Channel_RotationY:
-                            aiMatrix4x4::RotationY(angle, temp);
-                            rotMatrix *= aiMatrix3x3(temp);
-                            break;
-                        case Channel_RotationZ:
-                            aiMatrix4x4::RotationZ(angle, temp);
-                            rotMatrix *= aiMatrix3x3(temp);
-                            break;
-                        default:
-                            break;
+                        aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp);
                         }
                         }
-                    }
-                }
-
+                        break;
+                    case Channel_RotationY:
+                        {
+                        const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
+                        aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp);
+                        }
+                        break;
+                    case Channel_RotationZ:
+                        {
+                        const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
+                        aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp);
+                        }
+                        break;
+                    default:
+                        break;
+					}
+				}
                 rotkey->mTime = double(fr);
                 rotkey->mTime = double(fr);
                 rotkey->mValue = aiQuaternion(rotMatrix);
                 rotkey->mValue = aiQuaternion(rotMatrix);
                 ++rotkey;
                 ++rotkey;

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

@@ -353,7 +353,7 @@ void SectionParser ::Next() {
     }
     }
 
 
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
-    ASSIMP_LOG_DEBUG(current.id);
+    ASSIMP_LOG_VERBOSE_DEBUG(current.id);
 #endif
 #endif
 }
 }
 
 

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

@@ -230,7 +230,7 @@ public:
 
 
     // --------------------------------------------------------
     // --------------------------------------------------------
     /** Access a field of the structure by its canonical name. The pointer version
     /** Access a field of the structure by its canonical name. The pointer version
-     *  returns NULL on failure while the reference version raises an import error. */
+     *  returns nullptr on failure while the reference version raises an import error. */
     inline const Field &operator[](const std::string &ss) const;
     inline const Field &operator[](const std::string &ss) const;
     inline const Field *Get(const std::string &ss) const;
     inline const Field *Get(const std::string &ss) const;
 
 
@@ -359,7 +359,7 @@ private:
     template <typename T>
     template <typename T>
     T *_allocate(vector<T> &out, size_t &s) const {
     T *_allocate(vector<T> &out, size_t &s) const {
         out.resize(s);
         out.resize(s);
-        return s ? &out.front() : NULL;
+        return s ? &out.front() : nullptr;
     }
     }
 
 
     // --------------------------------------------------------
     // --------------------------------------------------------
@@ -367,14 +367,14 @@ private:
     struct _defaultInitializer {
     struct _defaultInitializer {
 
 
         template <typename T, unsigned int N>
         template <typename T, unsigned int N>
-        void operator()(T (&out)[N], const char * = NULL) {
+        void operator()(T (&out)[N], const char * = nullptr) {
             for (unsigned int i = 0; i < N; ++i) {
             for (unsigned int i = 0; i < N; ++i) {
                 out[i] = T();
                 out[i] = T();
             }
             }
         }
         }
 
 
         template <typename T, unsigned int N, unsigned int M>
         template <typename T, unsigned int N, unsigned int M>
-        void operator()(T (&out)[N][M], const char * = NULL) {
+        void operator()(T (&out)[N][M], const char * = nullptr) {
             for (unsigned int i = 0; i < N; ++i) {
             for (unsigned int i = 0; i < N; ++i) {
                 for (unsigned int j = 0; j < M; ++j) {
                 for (unsigned int j = 0; j < M; ++j) {
                     out[i][j] = T();
                     out[i][j] = T();
@@ -383,7 +383,7 @@ private:
         }
         }
 
 
         template <typename T>
         template <typename T>
-        void operator()(T &out, const char * = NULL) {
+        void operator()(T &out, const char * = nullptr) {
             out = T();
             out = T();
         }
         }
     };
     };
@@ -448,7 +448,7 @@ public:
 
 
 public:
 public:
     // --------------------------------------------------------
     // --------------------------------------------------------
-    /** Access a structure by its canonical name, the pointer version returns NULL on failure
+    /** Access a structure by its canonical name, the pointer version returns nullptr on failure
       * while the reference version raises an error. */
       * while the reference version raises an error. */
     inline const Structure &operator[](const std::string &ss) const;
     inline const Structure &operator[](const std::string &ss) const;
     inline const Structure *Get(const std::string &ss) const;
     inline const Structure *Get(const std::string &ss) const;

+ 3 - 2
code/AssetLib/Blender/BlenderDNA.inl

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2020, assimp team
 Copyright (c) 2006-2020, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -70,7 +69,7 @@ const Field& Structure :: operator [] (const std::string& ss) const
 const Field* Structure :: Get (const std::string& ss) const
 const Field* Structure :: Get (const std::string& ss) const
 {
 {
     std::map<std::string, size_t>::const_iterator it = indices.find(ss);
     std::map<std::string, size_t>::const_iterator it = indices.find(ss);
-    return it == indices.end() ? NULL : &fields[(*it).second];
+    return it == indices.end() ? nullptr : &fields[(*it).second];
 }
 }
 
 
 //--------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------
@@ -239,11 +238,13 @@ bool Structure :: ReadFieldPtr(TOUT<T> (&out)[N], const char* name,
     try {
     try {
         f = &(*this)[name];
         f = &(*this)[name];
 
 
+#ifdef _DEBUG
         // sanity check, should never happen if the genblenddna script is right
         // sanity check, should never happen if the genblenddna script is right
         if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) {
         if ((FieldFlag_Pointer|FieldFlag_Pointer) != (f->flags & (FieldFlag_Pointer|FieldFlag_Pointer))) {
             throw Error((Formatter::format(),"Field `",name,"` of structure `",
             throw Error((Formatter::format(),"Field `",name,"` of structure `",
                 this->name,"` ought to be a pointer AND an array"));
                 this->name,"` ought to be a pointer AND an array"));
         }
         }
+#endif // _DEBUG
 
 
         db.reader->IncPtr(f->offset);
         db.reader->IncPtr(f->offset);
 
 

Різницю між файлами не показано, бо вона завелика
+ 240 - 281
code/AssetLib/Blender/BlenderLoader.cpp


+ 3 - 1
code/AssetLib/COB/COBLoader.cpp

@@ -290,7 +290,7 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
                     }
                     }
                     std::unique_ptr<const Material> defmat;
                     std::unique_ptr<const Material> defmat;
                     if (!min) {
                     if (!min) {
-                        ASSIMP_LOG_DEBUG(format() << "Could not resolve material index "
+                        ASSIMP_LOG_VERBOSE_DEBUG(format() << "Could not resolve material index "
                                                   << reflist.first << " - creating default material for this slot");
                                                   << reflist.first << " - creating default material for this slot");
 
 
                         defmat.reset(min = new Material());
                         defmat.reset(min = new Material());
@@ -322,7 +322,9 @@ aiNode *COBImporter::BuildNodes(const Node &root, const Scene &scin, aiScene *fi
                             break;
                             break;
 
 
                         default:
                         default:
+                            ASSIMP_LOG_ERROR("Unknown option.");
                             ai_assert(false); // shouldn't be here
                             ai_assert(false); // shouldn't be here
+                            break;
                         }
                         }
                         mat->AddProperty(&shader, 1, AI_MATKEY_SHADING_MODEL);
                         mat->AddProperty(&shader, 1, AI_MATKEY_SHADING_MODEL);
                         if (shader != aiShadingMode_Gouraud) {
                         if (shader != aiShadingMode_Gouraud) {

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

@@ -127,7 +127,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
     std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
     std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb"));
 
 
     // Check whether we can read from the file
     // Check whether we can read from the file
-    if( file.get() == NULL) {
+    if( file.get() == nullptr) {
         throw DeadlyImportError( "Failed to open CSM file " + pFile + ".");
         throw DeadlyImportError( "Failed to open CSM file " + pFile + ".");
     }
     }
 
 

+ 313 - 216
code/AssetLib/Collada/ColladaExporter.cpp

@@ -44,8 +44,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
 #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
 
 
 #include "ColladaExporter.h"
 #include "ColladaExporter.h"
+
 #include <assimp/Bitmap.h>
 #include <assimp/Bitmap.h>
+#include <assimp/ColladaMetaData.h>
 #include <assimp/DefaultIOSystem.h>
 #include <assimp/DefaultIOSystem.h>
+#include <assimp/Exceptional.h>
 #include <assimp/MathFunctions.h>
 #include <assimp/MathFunctions.h>
 #include <assimp/SceneCombiner.h>
 #include <assimp/SceneCombiner.h>
 #include <assimp/StringUtils.h>
 #include <assimp/StringUtils.h>
@@ -56,15 +59,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/Exporter.hpp>
 #include <assimp/Exporter.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
 
 
-#include <assimp/Exceptional.h>
-
 #include <ctime>
 #include <ctime>
-#include <iostream>
 #include <memory>
 #include <memory>
-#include <set>
-#include <vector>
-
-using namespace Assimp;
 
 
 namespace Assimp {
 namespace Assimp {
 
 
@@ -91,8 +87,6 @@ void ExportSceneCollada(const char *pFile, IOSystem *pIOSystem, const aiScene *p
     outfile->Write(iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()), 1);
     outfile->Write(iDoTheExportThing.mOutput.str().c_str(), static_cast<size_t>(iDoTheExportThing.mOutput.tellp()), 1);
 }
 }
 
 
-} // end of namespace Assimp
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Encodes a string into a valid XML ID using the xsd:ID schema qualifications.
 // Encodes a string into a valid XML ID using the xsd:ID schema qualifications.
 static const std::string XMLIDEncode(const std::string &name) {
 static const std::string XMLIDEncode(const std::string &name) {
@@ -115,7 +109,7 @@ static const std::string XMLIDEncode(const std::string &name) {
         if (strchr(XML_ID_CHARS, *it) != nullptr) {
         if (strchr(XML_ID_CHARS, *it) != nullptr) {
             idEncoded << *it;
             idEncoded << *it;
         } else {
         } else {
-            // Select placeholder character based on invalid character to prevent name collisions
+            // Select placeholder character based on invalid character to reduce ID collisions
             idEncoded << XML_ID_CHARS[(*it) % XML_ID_CHARS_COUNT];
             idEncoded << XML_ID_CHARS[(*it) % XML_ID_CHARS_COUNT];
         }
         }
     }
     }
@@ -123,20 +117,37 @@ static const std::string XMLIDEncode(const std::string &name) {
     return idEncoded.str();
     return idEncoded.str();
 }
 }
 
 
+// ------------------------------------------------------------------------------------------------
+// Helper functions to create unique ids
+inline bool IsUniqueId(const std::unordered_set<std::string> &idSet, const std::string &idStr) {
+    return (idSet.find(idStr) == idSet.end());
+}
+
+inline std::string MakeUniqueId(const std::unordered_set<std::string> &idSet, const std::string &idPrefix, const std::string &postfix) {
+    std::string result(idPrefix + postfix);
+    if (!IsUniqueId(idSet, result)) {
+        // Select a number to append
+        size_t idnum = 1;
+        do {
+            result = idPrefix + '_' + to_string(idnum) + postfix;
+            ++idnum;
+        } while (!IsUniqueId(idSet, result));
+    }
+    return result;
+}
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor for a specific scene to export
 // Constructor for a specific scene to export
 ColladaExporter::ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file) :
 ColladaExporter::ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file) :
-        mIOSystem(pIOSystem), mPath(path), mFile(file) {
+        mIOSystem(pIOSystem),
+        mPath(path),
+        mFile(file),
+        mScene(pScene),
+        endstr("\n") {
     // make sure that all formatting happens using the standard, C locale and not the user's current locale
     // make sure that all formatting happens using the standard, C locale and not the user's current locale
     mOutput.imbue(std::locale("C"));
     mOutput.imbue(std::locale("C"));
     mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION);
     mOutput.precision(ASSIMP_AI_REAL_TEXT_PRECISION);
 
 
-    mScene = pScene;
-    mSceneOwned = false;
-
-    // set up strings
-    endstr = "\n";
-
     // start writing the file
     // start writing the file
     WriteFile();
     WriteFile();
 }
 }
@@ -144,9 +155,6 @@ ColladaExporter::ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, con
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor
 // Destructor
 ColladaExporter::~ColladaExporter() {
 ColladaExporter::~ColladaExporter() {
-    if (mSceneOwned) {
-        delete mScene;
-    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -161,6 +169,9 @@ void ColladaExporter::WriteFile() {
     WriteTextures();
     WriteTextures();
     WriteHeader();
     WriteHeader();
 
 
+    // Add node names to the unique id database first so they are most likely to use their names as unique ids
+    CreateNodeIds(mScene->mRootNode);
+
     WriteCamerasLibrary();
     WriteCamerasLibrary();
     WriteLightsLibrary();
     WriteLightsLibrary();
     WriteMaterials();
     WriteMaterials();
@@ -172,10 +183,11 @@ void ColladaExporter::WriteFile() {
     // customized, Writes the animation library
     // customized, Writes the animation library
     WriteAnimationsLibrary();
     WriteAnimationsLibrary();
 
 
-    // useless Collada fu at the end, just in case we haven't had enough indirections, yet.
+    // instantiate the scene(s)
+    // For Assimp there will only ever be one
     mOutput << startstr << "<scene>" << endstr;
     mOutput << startstr << "<scene>" << endstr;
     PushTag();
     PushTag();
-    mOutput << startstr << "<instance_visual_scene url=\"#" + XMLIDEncode(mScene->mRootNode->mName.C_Str()) + "\" />" << endstr;
+    mOutput << startstr << "<instance_visual_scene url=\"#" + mSceneId + "\" />" << endstr;
     PopTag();
     PopTag();
     mOutput << startstr << "</scene>" << endstr;
     mOutput << startstr << "</scene>" << endstr;
     PopTag();
     PopTag();
@@ -201,7 +213,7 @@ void ColladaExporter::WriteHeader() {
 
 
     static const unsigned int date_nb_chars = 20;
     static const unsigned int date_nb_chars = 20;
     char date_str[date_nb_chars];
     char date_str[date_nb_chars];
-    std::time_t date = std::time(NULL);
+    std::time_t date = std::time(nullptr);
     std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date));
     std::strftime(date_str, date_nb_chars, "%Y-%m-%dT%H:%M:%S", std::localtime(&date));
 
 
     aiVector3D scaling;
     aiVector3D scaling;
@@ -210,13 +222,13 @@ void ColladaExporter::WriteHeader() {
     mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position);
     mScene->mRootNode->mTransformation.Decompose(scaling, rotation, position);
     rotation.Normalize();
     rotation.Normalize();
 
 
-    bool add_root_node = false;
+    mAdd_root_node = false;
 
 
     ai_real scale = 1.0;
     ai_real scale = 1.0;
     if (std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) {
     if (std::abs(scaling.x - scaling.y) <= epsilon && std::abs(scaling.x - scaling.z) <= epsilon && std::abs(scaling.y - scaling.z) <= epsilon) {
         scale = (ai_real)((((double)scaling.x) + ((double)scaling.y) + ((double)scaling.z)) / 3.0);
         scale = (ai_real)((((double)scaling.x) + ((double)scaling.y) + ((double)scaling.z)) / 3.0);
     } else {
     } else {
-        add_root_node = true;
+        mAdd_root_node = true;
     }
     }
 
 
     std::string up_axis = "Y_UP";
     std::string up_axis = "Y_UP";
@@ -227,33 +239,19 @@ void ColladaExporter::WriteHeader() {
     } else if (rotation.Equal(z_rot, epsilon)) {
     } else if (rotation.Equal(z_rot, epsilon)) {
         up_axis = "Z_UP";
         up_axis = "Z_UP";
     } else {
     } else {
-        add_root_node = true;
+        mAdd_root_node = true;
     }
     }
 
 
     if (!position.Equal(aiVector3D(0, 0, 0))) {
     if (!position.Equal(aiVector3D(0, 0, 0))) {
-        add_root_node = true;
+        mAdd_root_node = true;
     }
     }
 
 
-    if (mScene->mRootNode->mNumChildren == 0) {
-        add_root_node = true;
+    // Assimp root nodes can have meshes, Collada Scenes cannot
+    if (mScene->mRootNode->mNumChildren == 0 || mScene->mRootNode->mMeshes != 0) {
+        mAdd_root_node = true;
     }
     }
 
 
-    if (add_root_node) {
-        aiScene *scene;
-        SceneCombiner::CopyScene(&scene, mScene);
-
-        aiNode *root = new aiNode("Scene");
-
-        root->mNumChildren = 1;
-        root->mChildren = new aiNode *[root->mNumChildren];
-
-        root->mChildren[0] = scene->mRootNode;
-        scene->mRootNode->mParent = root;
-        scene->mRootNode = root;
-
-        mScene = scene;
-        mSceneOwned = true;
-
+    if (mAdd_root_node) {
         up_axis = "Y_UP";
         up_axis = "Y_UP";
         scale = 1.0;
         scale = 1.0;
     }
     }
@@ -352,7 +350,7 @@ void ColladaExporter::WriteTextures() {
             std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char *)texture->achFormatHint);
             std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char *)texture->achFormatHint);
 
 
             std::unique_ptr<IOStream> outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb"));
             std::unique_ptr<IOStream> outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb"));
-            if (outfile == NULL) {
+            if (outfile == nullptr) {
                 throw DeadlyExportError("could not open output texture file: " + mPath + name);
                 throw DeadlyExportError("could not open output texture file: " + mPath + name);
             }
             }
 
 
@@ -388,10 +386,10 @@ void ColladaExporter::WriteCamerasLibrary() {
 void ColladaExporter::WriteCamera(size_t pIndex) {
 void ColladaExporter::WriteCamera(size_t pIndex) {
 
 
     const aiCamera *cam = mScene->mCameras[pIndex];
     const aiCamera *cam = mScene->mCameras[pIndex];
-    const std::string cameraName = XMLEscape(cam->mName.C_Str());
-    const std::string cameraId = XMLIDEncode(cam->mName.C_Str());
+    const std::string cameraId = GetObjectUniqueId(AiObjectType::Camera, pIndex);
+    const std::string cameraName = GetObjectName(AiObjectType::Camera, pIndex);
 
 
-    mOutput << startstr << "<camera id=\"" << cameraId << "-camera\" name=\"" << cameraName << "\" >" << endstr;
+    mOutput << startstr << "<camera id=\"" << cameraId << "\" name=\"" << cameraName << "\" >" << endstr;
     PushTag();
     PushTag();
     mOutput << startstr << "<optics>" << endstr;
     mOutput << startstr << "<optics>" << endstr;
     PushTag();
     PushTag();
@@ -441,10 +439,10 @@ void ColladaExporter::WriteLightsLibrary() {
 void ColladaExporter::WriteLight(size_t pIndex) {
 void ColladaExporter::WriteLight(size_t pIndex) {
 
 
     const aiLight *light = mScene->mLights[pIndex];
     const aiLight *light = mScene->mLights[pIndex];
-    const std::string lightName = XMLEscape(light->mName.C_Str());
-    const std::string lightId = XMLIDEncode(light->mName.C_Str());
+    const std::string lightId = GetObjectUniqueId(AiObjectType::Light, pIndex);
+    const std::string lightName = GetObjectName(AiObjectType::Light, pIndex);
 
 
-    mOutput << startstr << "<light id=\"" << lightId << "-light\" name=\""
+    mOutput << startstr << "<light id=\"" << lightId << "\" name=\""
             << lightName << "\" >" << endstr;
             << lightName << "\" >" << endstr;
     PushTag();
     PushTag();
     mOutput << startstr << "<technique_common>" << endstr;
     mOutput << startstr << "<technique_common>" << endstr;
@@ -561,12 +559,11 @@ void ColladaExporter::WriteAmbienttLight(const aiLight *const light) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Reads a single surface entry from the given material keys
 // Reads a single surface entry from the given material keys
-void ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial *pSrcMat,
-        aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex) {
-    if (pSrcMat->GetTextureCount(pTexture) > 0) {
+bool ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial &pSrcMat, aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex) {
+    if (pSrcMat.GetTextureCount(pTexture) > 0) {
         aiString texfile;
         aiString texfile;
         unsigned int uvChannel = 0;
         unsigned int uvChannel = 0;
-        pSrcMat->GetTexture(pTexture, 0, &texfile, NULL, &uvChannel);
+        pSrcMat.GetTexture(pTexture, 0, &texfile, nullptr, &uvChannel);
 
 
         std::string index_str(texfile.C_Str());
         std::string index_str(texfile.C_Str());
 
 
@@ -596,8 +593,9 @@ void ColladaExporter::ReadMaterialSurface(Surface &poSurface, const aiMaterial *
         poSurface.exist = true;
         poSurface.exist = true;
     } else {
     } else {
         if (pKey)
         if (pKey)
-            poSurface.exist = pSrcMat->Get(pKey, static_cast<unsigned int>(pType), static_cast<unsigned int>(pIndex), poSurface.color) == aiReturn_SUCCESS;
+            poSurface.exist = pSrcMat.Get(pKey, static_cast<unsigned int>(pType), static_cast<unsigned int>(pIndex), poSurface.color) == aiReturn_SUCCESS;
     }
     }
+    return poSurface.exist;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -608,9 +606,9 @@ static bool isalnum_C(char c) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Writes an image entry for the given surface
 // Writes an image entry for the given surface
-void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string &pNameAdd) {
+void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string &imageId) {
     if (!pSurface.texture.empty()) {
     if (!pSurface.texture.empty()) {
-        mOutput << startstr << "<image id=\"" << XMLIDEncode(pNameAdd) << "\">" << endstr;
+        mOutput << startstr << "<image id=\"" << imageId << "\">" << endstr;
         PushTag();
         PushTag();
         mOutput << startstr << "<init_from>";
         mOutput << startstr << "<init_from>";
 
 
@@ -631,14 +629,14 @@ void ColladaExporter::WriteImageEntry(const Surface &pSurface, const std::string
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Writes a color-or-texture entry into an effect definition
 // Writes a color-or-texture entry into an effect definition
-void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pImageName) {
+void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &imageId) {
     if (pSurface.exist) {
     if (pSurface.exist) {
         mOutput << startstr << "<" << pTypeName << ">" << endstr;
         mOutput << startstr << "<" << pTypeName << ">" << endstr;
         PushTag();
         PushTag();
         if (pSurface.texture.empty()) {
         if (pSurface.texture.empty()) {
             mOutput << startstr << "<color sid=\"" << pTypeName << "\">" << pSurface.color.r << "   " << pSurface.color.g << "   " << pSurface.color.b << "   " << pSurface.color.a << "</color>" << endstr;
             mOutput << startstr << "<color sid=\"" << pTypeName << "\">" << pSurface.color.r << "   " << pSurface.color.g << "   " << pSurface.color.b << "   " << pSurface.color.a << "</color>" << endstr;
         } else {
         } else {
-            mOutput << startstr << "<texture texture=\"" << XMLIDEncode(pImageName) << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
+            mOutput << startstr << "<texture texture=\"" << imageId << "\" texcoord=\"CHANNEL" << pSurface.channel << "\" />" << endstr;
         }
         }
         PopTag();
         PopTag();
         mOutput << startstr << "</" << pTypeName << ">" << endstr;
         mOutput << startstr << "</" << pTypeName << ">" << endstr;
@@ -647,24 +645,24 @@ void ColladaExporter::WriteTextureColorEntry(const Surface &pSurface, const std:
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Writes the two parameters necessary for referencing a texture in an effect entry
 // Writes the two parameters necessary for referencing a texture in an effect entry
-void ColladaExporter::WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &pMatName) {
+void ColladaExporter::WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &materialId) {
     // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture
     // if surface is a texture, write out the sampler and the surface parameters necessary to reference the texture
     if (!pSurface.texture.empty()) {
     if (!pSurface.texture.empty()) {
-        mOutput << startstr << "<newparam sid=\"" << XMLIDEncode(pMatName) << "-" << pTypeName << "-surface\">" << endstr;
+        mOutput << startstr << "<newparam sid=\"" << materialId << "-" << pTypeName << "-surface\">" << endstr;
         PushTag();
         PushTag();
         mOutput << startstr << "<surface type=\"2D\">" << endstr;
         mOutput << startstr << "<surface type=\"2D\">" << endstr;
         PushTag();
         PushTag();
-        mOutput << startstr << "<init_from>" << XMLIDEncode(pMatName) << "-" << pTypeName << "-image</init_from>" << endstr;
+        mOutput << startstr << "<init_from>" << materialId << "-" << pTypeName << "-image</init_from>" << endstr;
         PopTag();
         PopTag();
         mOutput << startstr << "</surface>" << endstr;
         mOutput << startstr << "</surface>" << endstr;
         PopTag();
         PopTag();
         mOutput << startstr << "</newparam>" << endstr;
         mOutput << startstr << "</newparam>" << endstr;
 
 
-        mOutput << startstr << "<newparam sid=\"" << XMLIDEncode(pMatName) << "-" << pTypeName << "-sampler\">" << endstr;
+        mOutput << startstr << "<newparam sid=\"" << materialId << "-" << pTypeName << "-sampler\">" << endstr;
         PushTag();
         PushTag();
         mOutput << startstr << "<sampler2D>" << endstr;
         mOutput << startstr << "<sampler2D>" << endstr;
         PushTag();
         PushTag();
-        mOutput << startstr << "<source>" << XMLIDEncode(pMatName) << "-" << pTypeName << "-surface</source>" << endstr;
+        mOutput << startstr << "<source>" << materialId << "-" << pTypeName << "-surface</source>" << endstr;
         PopTag();
         PopTag();
         mOutput << startstr << "</sampler2D>" << endstr;
         mOutput << startstr << "</sampler2D>" << endstr;
         PopTag();
         PopTag();
@@ -687,80 +685,63 @@ void ColladaExporter::WriteFloatEntry(const Property &pProperty, const std::stri
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Writes the material setup
 // Writes the material setup
 void ColladaExporter::WriteMaterials() {
 void ColladaExporter::WriteMaterials() {
+    std::vector<Material> materials;
     materials.resize(mScene->mNumMaterials);
     materials.resize(mScene->mNumMaterials);
 
 
     /// collect all materials from the scene
     /// collect all materials from the scene
     size_t numTextures = 0;
     size_t numTextures = 0;
     for (size_t a = 0; a < mScene->mNumMaterials; ++a) {
     for (size_t a = 0; a < mScene->mNumMaterials; ++a) {
-        const aiMaterial *mat = mScene->mMaterials[a];
-
-        aiString name;
-        if (mat->Get(AI_MATKEY_NAME, name) != aiReturn_SUCCESS) {
-            name = "mat";
-            materials[a].name = std::string("m") + to_string(a) + name.C_Str();
-        } else {
-            // try to use the material's name if no other material has already taken it, else append #
-            std::string testName = name.C_Str();
-            size_t materialCountWithThisName = 0;
-            for (size_t i = 0; i < a; i++) {
-                if (materials[i].name == testName) {
-                    materialCountWithThisName++;
-                }
-            }
-            if (materialCountWithThisName == 0) {
-                materials[a].name = name.C_Str();
-            } else {
-                materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName);
-            }
-        }
+        Material &material = materials[a];
+        material.id = GetObjectUniqueId(AiObjectType::Material, a);
+        material.name = GetObjectName(AiObjectType::Material, a);
 
 
+        const aiMaterial &mat = *(mScene->mMaterials[a]);
         aiShadingMode shading = aiShadingMode_Flat;
         aiShadingMode shading = aiShadingMode_Flat;
-        materials[a].shading_model = "phong";
-        if (mat->Get(AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) {
+        material.shading_model = "phong";
+        if (mat.Get(AI_MATKEY_SHADING_MODEL, shading) == aiReturn_SUCCESS) {
             if (shading == aiShadingMode_Phong) {
             if (shading == aiShadingMode_Phong) {
-                materials[a].shading_model = "phong";
+                material.shading_model = "phong";
             } else if (shading == aiShadingMode_Blinn) {
             } else if (shading == aiShadingMode_Blinn) {
-                materials[a].shading_model = "blinn";
+                material.shading_model = "blinn";
             } else if (shading == aiShadingMode_NoShading) {
             } else if (shading == aiShadingMode_NoShading) {
-                materials[a].shading_model = "constant";
+                material.shading_model = "constant";
             } else if (shading == aiShadingMode_Gouraud) {
             } else if (shading == aiShadingMode_Gouraud) {
-                materials[a].shading_model = "lambert";
+                material.shading_model = "lambert";
             }
             }
         }
         }
 
 
-        ReadMaterialSurface(materials[a].ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT);
-        if (!materials[a].ambient.texture.empty()) numTextures++;
-        ReadMaterialSurface(materials[a].diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE);
-        if (!materials[a].diffuse.texture.empty()) numTextures++;
-        ReadMaterialSurface(materials[a].specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR);
-        if (!materials[a].specular.texture.empty()) numTextures++;
-        ReadMaterialSurface(materials[a].emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE);
-        if (!materials[a].emissive.texture.empty()) numTextures++;
-        ReadMaterialSurface(materials[a].reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE);
-        if (!materials[a].reflective.texture.empty()) numTextures++;
-        ReadMaterialSurface(materials[a].transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT);
-        if (!materials[a].transparent.texture.empty()) numTextures++;
-        ReadMaterialSurface(materials[a].normal, mat, aiTextureType_NORMALS, NULL, 0, 0);
-        if (!materials[a].normal.texture.empty()) numTextures++;
-
-        materials[a].shininess.exist = mat->Get(AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS;
-        materials[a].transparency.exist = mat->Get(AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS;
-        materials[a].index_refraction.exist = mat->Get(AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS;
+        if (ReadMaterialSurface(material.ambient, mat, aiTextureType_AMBIENT, AI_MATKEY_COLOR_AMBIENT))
+            ++numTextures;
+        if (ReadMaterialSurface(material.diffuse, mat, aiTextureType_DIFFUSE, AI_MATKEY_COLOR_DIFFUSE))
+            ++numTextures;
+        if (ReadMaterialSurface(material.specular, mat, aiTextureType_SPECULAR, AI_MATKEY_COLOR_SPECULAR))
+            ++numTextures;
+        if (ReadMaterialSurface(material.emissive, mat, aiTextureType_EMISSIVE, AI_MATKEY_COLOR_EMISSIVE))
+            ++numTextures;
+        if (ReadMaterialSurface(material.reflective, mat, aiTextureType_REFLECTION, AI_MATKEY_COLOR_REFLECTIVE))
+            ++numTextures;
+        if (ReadMaterialSurface(material.transparent, mat, aiTextureType_OPACITY, AI_MATKEY_COLOR_TRANSPARENT))
+            ++numTextures;
+        if (ReadMaterialSurface(material.normal, mat, aiTextureType_NORMALS, nullptr, 0, 0))
+            ++numTextures;
+
+        material.shininess.exist = mat.Get(AI_MATKEY_SHININESS, material.shininess.value) == aiReturn_SUCCESS;
+        material.transparency.exist = mat.Get(AI_MATKEY_OPACITY, material.transparency.value) == aiReturn_SUCCESS;
+        material.index_refraction.exist = mat.Get(AI_MATKEY_REFRACTI, material.index_refraction.value) == aiReturn_SUCCESS;
     }
     }
 
 
     // output textures if present
     // output textures if present
     if (numTextures > 0) {
     if (numTextures > 0) {
         mOutput << startstr << "<library_images>" << endstr;
         mOutput << startstr << "<library_images>" << endstr;
         PushTag();
         PushTag();
-        for (std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) {
-            const Material &mat = *it;
-            WriteImageEntry(mat.ambient, mat.name + "-ambient-image");
-            WriteImageEntry(mat.diffuse, mat.name + "-diffuse-image");
-            WriteImageEntry(mat.specular, mat.name + "-specular-image");
-            WriteImageEntry(mat.emissive, mat.name + "-emission-image");
-            WriteImageEntry(mat.reflective, mat.name + "-reflective-image");
-            WriteImageEntry(mat.transparent, mat.name + "-transparent-image");
-            WriteImageEntry(mat.normal, mat.name + "-normal-image");
+        for (const Material &mat : materials) {
+            WriteImageEntry(mat.ambient, mat.id + "-ambient-image");
+            WriteImageEntry(mat.diffuse, mat.id + "-diffuse-image");
+            WriteImageEntry(mat.specular, mat.id + "-specular-image");
+            WriteImageEntry(mat.emissive, mat.id + "-emission-image");
+            WriteImageEntry(mat.reflective, mat.id + "-reflective-image");
+            WriteImageEntry(mat.transparent, mat.id + "-transparent-image");
+            WriteImageEntry(mat.normal, mat.id + "-normal-image");
         }
         }
         PopTag();
         PopTag();
         mOutput << startstr << "</library_images>" << endstr;
         mOutput << startstr << "</library_images>" << endstr;
@@ -770,40 +751,39 @@ void ColladaExporter::WriteMaterials() {
     if (!materials.empty()) {
     if (!materials.empty()) {
         mOutput << startstr << "<library_effects>" << endstr;
         mOutput << startstr << "<library_effects>" << endstr;
         PushTag();
         PushTag();
-        for (std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) {
-            const Material &mat = *it;
+        for (const Material &mat : materials) {
             // this is so ridiculous it must be right
             // this is so ridiculous it must be right
-            mOutput << startstr << "<effect id=\"" << XMLIDEncode(mat.name) << "-fx\" name=\"" << XMLEscape(mat.name) << "\">" << endstr;
+            mOutput << startstr << "<effect id=\"" << mat.id << "-fx\" name=\"" << mat.name << "\">" << endstr;
             PushTag();
             PushTag();
             mOutput << startstr << "<profile_COMMON>" << endstr;
             mOutput << startstr << "<profile_COMMON>" << endstr;
             PushTag();
             PushTag();
 
 
             // write sampler- and surface params for the texture entries
             // write sampler- and surface params for the texture entries
-            WriteTextureParamEntry(mat.emissive, "emission", mat.name);
-            WriteTextureParamEntry(mat.ambient, "ambient", mat.name);
-            WriteTextureParamEntry(mat.diffuse, "diffuse", mat.name);
-            WriteTextureParamEntry(mat.specular, "specular", mat.name);
-            WriteTextureParamEntry(mat.reflective, "reflective", mat.name);
-            WriteTextureParamEntry(mat.transparent, "transparent", mat.name);
-            WriteTextureParamEntry(mat.normal, "normal", mat.name);
+            WriteTextureParamEntry(mat.emissive, "emission", mat.id);
+            WriteTextureParamEntry(mat.ambient, "ambient", mat.id);
+            WriteTextureParamEntry(mat.diffuse, "diffuse", mat.id);
+            WriteTextureParamEntry(mat.specular, "specular", mat.id);
+            WriteTextureParamEntry(mat.reflective, "reflective", mat.id);
+            WriteTextureParamEntry(mat.transparent, "transparent", mat.id);
+            WriteTextureParamEntry(mat.normal, "normal", mat.id);
 
 
             mOutput << startstr << "<technique sid=\"standard\">" << endstr;
             mOutput << startstr << "<technique sid=\"standard\">" << endstr;
             PushTag();
             PushTag();
             mOutput << startstr << "<" << mat.shading_model << ">" << endstr;
             mOutput << startstr << "<" << mat.shading_model << ">" << endstr;
             PushTag();
             PushTag();
 
 
-            WriteTextureColorEntry(mat.emissive, "emission", mat.name + "-emission-sampler");
-            WriteTextureColorEntry(mat.ambient, "ambient", mat.name + "-ambient-sampler");
-            WriteTextureColorEntry(mat.diffuse, "diffuse", mat.name + "-diffuse-sampler");
-            WriteTextureColorEntry(mat.specular, "specular", mat.name + "-specular-sampler");
+            WriteTextureColorEntry(mat.emissive, "emission", mat.id + "-emission-sampler");
+            WriteTextureColorEntry(mat.ambient, "ambient", mat.id + "-ambient-sampler");
+            WriteTextureColorEntry(mat.diffuse, "diffuse", mat.id + "-diffuse-sampler");
+            WriteTextureColorEntry(mat.specular, "specular", mat.id + "-specular-sampler");
             WriteFloatEntry(mat.shininess, "shininess");
             WriteFloatEntry(mat.shininess, "shininess");
-            WriteTextureColorEntry(mat.reflective, "reflective", mat.name + "-reflective-sampler");
-            WriteTextureColorEntry(mat.transparent, "transparent", mat.name + "-transparent-sampler");
+            WriteTextureColorEntry(mat.reflective, "reflective", mat.id + "-reflective-sampler");
+            WriteTextureColorEntry(mat.transparent, "transparent", mat.id + "-transparent-sampler");
             WriteFloatEntry(mat.transparency, "transparency");
             WriteFloatEntry(mat.transparency, "transparency");
             WriteFloatEntry(mat.index_refraction, "index_of_refraction");
             WriteFloatEntry(mat.index_refraction, "index_of_refraction");
 
 
             if (!mat.normal.texture.empty()) {
             if (!mat.normal.texture.empty()) {
-                WriteTextureColorEntry(mat.normal, "bump", mat.name + "-normal-sampler");
+                WriteTextureColorEntry(mat.normal, "bump", mat.id + "-normal-sampler");
             }
             }
 
 
             PopTag();
             PopTag();
@@ -823,9 +803,9 @@ void ColladaExporter::WriteMaterials() {
         PushTag();
         PushTag();
         for (std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) {
         for (std::vector<Material>::const_iterator it = materials.begin(); it != materials.end(); ++it) {
             const Material &mat = *it;
             const Material &mat = *it;
-            mOutput << startstr << "<material id=\"" << XMLIDEncode(mat.name) << "\" name=\"" << XMLEscape(mat.name) << "\">" << endstr;
+            mOutput << startstr << "<material id=\"" << mat.id << "\" name=\"" << mat.name << "\">" << endstr;
             PushTag();
             PushTag();
-            mOutput << startstr << "<instance_effect url=\"#" << XMLIDEncode(mat.name) << "-fx\"/>" << endstr;
+            mOutput << startstr << "<instance_effect url=\"#" << mat.id << "-fx\"/>" << endstr;
             PopTag();
             PopTag();
             mOutput << startstr << "</material>" << endstr;
             mOutput << startstr << "</material>" << endstr;
         }
         }
@@ -852,20 +832,18 @@ void ColladaExporter::WriteControllerLibrary() {
 // Writes a skin controller of the given mesh
 // Writes a skin controller of the given mesh
 void ColladaExporter::WriteController(size_t pIndex) {
 void ColladaExporter::WriteController(size_t pIndex) {
     const aiMesh *mesh = mScene->mMeshes[pIndex];
     const aiMesh *mesh = mScene->mMeshes[pIndex];
-    const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str();
-    const std::string idstrEscaped = XMLIDEncode(idstr);
-
-    if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
+    // Is there a skin controller?
+    if (mesh->mNumBones == 0 || mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
         return;
         return;
 
 
-    if (mesh->mNumBones == 0)
-        return;
+    const std::string idstr = GetObjectUniqueId(AiObjectType::Mesh, pIndex);
+    const std::string namestr = GetObjectName(AiObjectType::Mesh, pIndex);
 
 
-    mOutput << startstr << "<controller id=\"" << idstrEscaped << "-skin\" ";
+    mOutput << startstr << "<controller id=\"" << idstr << "-skin\" ";
     mOutput << "name=\"skinCluster" << pIndex << "\">" << endstr;
     mOutput << "name=\"skinCluster" << pIndex << "\">" << endstr;
     PushTag();
     PushTag();
 
 
-    mOutput << startstr << "<skin source=\"#" << idstrEscaped << "\">" << endstr;
+    mOutput << startstr << "<skin source=\"#" << idstr << "\">" << endstr;
     PushTag();
     PushTag();
 
 
     // bind pose matrix
     // bind pose matrix
@@ -882,20 +860,20 @@ void ColladaExporter::WriteController(size_t pIndex) {
     PopTag();
     PopTag();
     mOutput << startstr << "</bind_shape_matrix>" << endstr;
     mOutput << startstr << "</bind_shape_matrix>" << endstr;
 
 
-    mOutput << startstr << "<source id=\"" << idstrEscaped << "-skin-joints\" name=\"" << idstrEscaped << "-skin-joints\">" << endstr;
+    mOutput << startstr << "<source id=\"" << idstr << "-skin-joints\" name=\"" << namestr << "-skin-joints\">" << endstr;
     PushTag();
     PushTag();
 
 
-    mOutput << startstr << "<Name_array id=\"" << idstrEscaped << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\">";
+    mOutput << startstr << "<Name_array id=\"" << idstr << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\">";
 
 
     for (size_t i = 0; i < mesh->mNumBones; ++i)
     for (size_t i = 0; i < mesh->mNumBones; ++i)
-        mOutput << XMLIDEncode(mesh->mBones[i]->mName.C_Str()) << " ";
+        mOutput << GetBoneUniqueId(mesh->mBones[i]) << ' ';
 
 
     mOutput << "</Name_array>" << endstr;
     mOutput << "</Name_array>" << endstr;
 
 
     mOutput << startstr << "<technique_common>" << endstr;
     mOutput << startstr << "<technique_common>" << endstr;
     PushTag();
     PushTag();
 
 
-    mOutput << startstr << "<accessor source=\"#" << idstrEscaped << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\" stride=\"" << 1 << "\">" << endstr;
+    mOutput << startstr << "<accessor source=\"#" << idstr << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\" stride=\"" << 1 << "\">" << endstr;
     PushTag();
     PushTag();
 
 
     mOutput << startstr << "<param name=\"JOINT\" type=\"Name\"></param>" << endstr;
     mOutput << startstr << "<param name=\"JOINT\" type=\"Name\"></param>" << endstr;
@@ -932,8 +910,8 @@ void ColladaExporter::WriteController(size_t pIndex) {
     mOutput << startstr << "<joints>" << endstr;
     mOutput << startstr << "<joints>" << endstr;
     PushTag();
     PushTag();
 
 
-    mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstrEscaped << "-skin-joints\"></input>" << endstr;
-    mOutput << startstr << "<input semantic=\"INV_BIND_MATRIX\" source=\"#" << idstrEscaped << "-skin-bind_poses\"></input>" << endstr;
+    mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstr << "-skin-joints\"></input>" << endstr;
+    mOutput << startstr << "<input semantic=\"INV_BIND_MATRIX\" source=\"#" << idstr << "-skin-bind_poses\"></input>" << endstr;
 
 
     PopTag();
     PopTag();
     mOutput << startstr << "</joints>" << endstr;
     mOutput << startstr << "</joints>" << endstr;
@@ -941,8 +919,8 @@ void ColladaExporter::WriteController(size_t pIndex) {
     mOutput << startstr << "<vertex_weights count=\"" << mesh->mNumVertices << "\">" << endstr;
     mOutput << startstr << "<vertex_weights count=\"" << mesh->mNumVertices << "\">" << endstr;
     PushTag();
     PushTag();
 
 
-    mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstrEscaped << "-skin-joints\" offset=\"0\"></input>" << endstr;
-    mOutput << startstr << "<input semantic=\"WEIGHT\" source=\"#" << idstrEscaped << "-skin-weights\" offset=\"1\"></input>" << endstr;
+    mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstr << "-skin-joints\" offset=\"0\"></input>" << endstr;
+    mOutput << startstr << "<input semantic=\"WEIGHT\" source=\"#" << idstr << "-skin-weights\" offset=\"1\"></input>" << endstr;
 
 
     mOutput << startstr << "<vcount>";
     mOutput << startstr << "<vcount>";
 
 
@@ -1017,9 +995,8 @@ void ColladaExporter::WriteGeometryLibrary() {
 // Writes the given mesh
 // Writes the given mesh
 void ColladaExporter::WriteGeometry(size_t pIndex) {
 void ColladaExporter::WriteGeometry(size_t pIndex) {
     const aiMesh *mesh = mScene->mMeshes[pIndex];
     const aiMesh *mesh = mScene->mMeshes[pIndex];
-    const std::string idstr = mesh->mName.length == 0 ? GetMeshId(pIndex) : mesh->mName.C_Str();
-    const std::string geometryName = XMLEscape(idstr);
-    const std::string geometryId = XMLIDEncode(idstr);
+    const std::string geometryId = GetObjectUniqueId(AiObjectType::Mesh, pIndex);
+    const std::string geometryName = GetObjectName(AiObjectType::Mesh, pIndex);
 
 
     if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
     if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
         return;
         return;
@@ -1032,15 +1009,15 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
     PushTag();
     PushTag();
 
 
     // Positions
     // Positions
-    WriteFloatArray(idstr + "-positions", FloatType_Vector, (ai_real *)mesh->mVertices, mesh->mNumVertices);
+    WriteFloatArray(geometryId + "-positions", FloatType_Vector, (ai_real *)mesh->mVertices, mesh->mNumVertices);
     // Normals, if any
     // Normals, if any
     if (mesh->HasNormals())
     if (mesh->HasNormals())
-        WriteFloatArray(idstr + "-normals", FloatType_Vector, (ai_real *)mesh->mNormals, mesh->mNumVertices);
+        WriteFloatArray(geometryId + "-normals", FloatType_Vector, (ai_real *)mesh->mNormals, mesh->mNumVertices);
 
 
     // texture coords
     // texture coords
     for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
     for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
         if (mesh->HasTextureCoords(static_cast<unsigned int>(a))) {
         if (mesh->HasTextureCoords(static_cast<unsigned int>(a))) {
-            WriteFloatArray(idstr + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
+            WriteFloatArray(geometryId + "-tex" + to_string(a), mesh->mNumUVComponents[a] == 3 ? FloatType_TexCoord3 : FloatType_TexCoord2,
                     (ai_real *)mesh->mTextureCoords[a], mesh->mNumVertices);
                     (ai_real *)mesh->mTextureCoords[a], mesh->mNumVertices);
         }
         }
     }
     }
@@ -1048,7 +1025,7 @@ void ColladaExporter::WriteGeometry(size_t pIndex) {
     // vertex colors
     // vertex colors
     for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
     for (size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a) {
         if (mesh->HasVertexColors(static_cast<unsigned int>(a)))
         if (mesh->HasVertexColors(static_cast<unsigned int>(a)))
-            WriteFloatArray(idstr + "-color" + to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices);
+            WriteFloatArray(geometryId + "-color" + to_string(a), FloatType_Color, (ai_real *)mesh->mColors[a], mesh->mNumVertices);
     }
     }
 
 
     // assemble vertex structure
     // assemble vertex structure
@@ -1248,17 +1225,29 @@ void ColladaExporter::WriteFloatArray(const std::string &pIdString, FloatDataTyp
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Writes the scene library
 // Writes the scene library
 void ColladaExporter::WriteSceneLibrary() {
 void ColladaExporter::WriteSceneLibrary() {
-    const std::string sceneName = XMLEscape(mScene->mRootNode->mName.C_Str());
-    const std::string sceneId = XMLIDEncode(mScene->mRootNode->mName.C_Str());
+    // Determine if we are using the aiScene root or our own
+    std::string sceneName("Scene");
+    if (mAdd_root_node) {
+        mSceneId = MakeUniqueId(mUniqueIds, sceneName, std::string());
+        mUniqueIds.insert(mSceneId);
+    } else {
+        mSceneId = GetNodeUniqueId(mScene->mRootNode);
+        sceneName = GetNodeName(mScene->mRootNode);
+    }
 
 
     mOutput << startstr << "<library_visual_scenes>" << endstr;
     mOutput << startstr << "<library_visual_scenes>" << endstr;
     PushTag();
     PushTag();
-    mOutput << startstr << "<visual_scene id=\"" + sceneId + "\" name=\"" + sceneName + "\">" << endstr;
+    mOutput << startstr << "<visual_scene id=\"" + mSceneId + "\" name=\"" + sceneName + "\">" << endstr;
     PushTag();
     PushTag();
 
 
-    // start recursive write at the root node
-    for (size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a)
-        WriteNode(mScene, mScene->mRootNode->mChildren[a]);
+    if (mAdd_root_node) {
+        // Export the root node
+        WriteNode(mScene->mRootNode);
+    } else {
+        // Have already exported the root node
+        for (size_t a = 0; a < mScene->mRootNode->mNumChildren; ++a)
+            WriteNode(mScene->mRootNode->mChildren[a]);
+    }
 
 
     PopTag();
     PopTag();
     mOutput << startstr << "</visual_scene>" << endstr;
     mOutput << startstr << "</visual_scene>" << endstr;
@@ -1272,20 +1261,10 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex) {
     if (anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels == 0)
     if (anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels == 0)
         return;
         return;
 
 
-    const std::string animation_name_escaped = XMLEscape(anim->mName.C_Str());
-    std::string idstr = anim->mName.C_Str();
-    std::string ending = std::string("AnimId") + to_string(pIndex);
-    if (idstr.length() >= ending.length()) {
-        if (0 != idstr.compare(idstr.length() - ending.length(), ending.length(), ending)) {
-            idstr = idstr + ending;
-        }
-    } else {
-        idstr = idstr + ending;
-    }
-
-    const std::string idstrEscaped = XMLIDEncode(idstr);
+    const std::string animationNameEscaped = GetObjectName(AiObjectType::Animation, pIndex);
+    const std::string idstrEscaped = GetObjectUniqueId(AiObjectType::Animation, pIndex);
 
 
-    mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
+    mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animationNameEscaped + "\">" << endstr;
     PushTag();
     PushTag();
 
 
     std::string cur_node_idstr;
     std::string cur_node_idstr;
@@ -1435,20 +1414,21 @@ void ColladaExporter::WriteAnimationsLibrary() {
 }
 }
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Helper to find a bone by name in the scene
 // Helper to find a bone by name in the scene
-aiBone *findBone(const aiScene *scene, const char *name) {
+aiBone *findBone(const aiScene *scene, const aiString &name) {
     for (size_t m = 0; m < scene->mNumMeshes; m++) {
     for (size_t m = 0; m < scene->mNumMeshes; m++) {
         aiMesh *mesh = scene->mMeshes[m];
         aiMesh *mesh = scene->mMeshes[m];
         for (size_t b = 0; b < mesh->mNumBones; b++) {
         for (size_t b = 0; b < mesh->mNumBones; b++) {
             aiBone *bone = mesh->mBones[b];
             aiBone *bone = mesh->mBones[b];
-            if (0 == strcmp(name, bone->mName.C_Str())) {
+            if (name == bone->mName) {
                 return bone;
                 return bone;
             }
             }
         }
         }
     }
     }
-    return NULL;
+    return nullptr;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
+// Helper to find the node associated with a bone in the scene
 const aiNode *findBoneNode(const aiNode *aNode, const aiBone *bone) {
 const aiNode *findBoneNode(const aiNode *aNode, const aiBone *bone) {
     if (aNode && bone && aNode->mName == bone->mName) {
     if (aNode && bone && aNode->mName == bone->mName) {
         return aNode;
         return aNode;
@@ -1457,15 +1437,17 @@ const aiNode *findBoneNode(const aiNode *aNode, const aiBone *bone) {
     if (aNode && bone) {
     if (aNode && bone) {
         for (unsigned int i = 0; i < aNode->mNumChildren; ++i) {
         for (unsigned int i = 0; i < aNode->mNumChildren; ++i) {
             aiNode *aChild = aNode->mChildren[i];
             aiNode *aChild = aNode->mChildren[i];
-            const aiNode *foundFromChild = 0;
+            const aiNode *foundFromChild = nullptr;
             if (aChild) {
             if (aChild) {
                 foundFromChild = findBoneNode(aChild, bone);
                 foundFromChild = findBoneNode(aChild, bone);
-                if (foundFromChild) return foundFromChild;
+                if (foundFromChild) {
+                    return foundFromChild;
+                }
             }
             }
         }
         }
     }
     }
 
 
-    return NULL;
+    return nullptr;
 }
 }
 
 
 const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) {
 const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) {
@@ -1476,7 +1458,7 @@ const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) {
 
 
             const aiNode *node = findBoneNode(scene->mRootNode, bone);
             const aiNode *node = findBoneNode(scene->mRootNode, bone);
             if (node) {
             if (node) {
-                while (node->mParent && findBone(scene, node->mParent->mName.C_Str()) != 0) {
+                while (node->mParent && findBone(scene, node->mParent->mName) != nullptr) {
                     node = node->mParent;
                     node = node->mParent;
                 }
                 }
                 topParentBoneNodes.insert(node);
                 topParentBoneNodes.insert(node);
@@ -1496,45 +1478,36 @@ const aiNode *findSkeletonRootNode(const aiScene *scene, const aiMesh *mesh) {
         }
         }
     }
     }
 
 
-    return NULL;
+    return nullptr;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Recursively writes the given node
 // Recursively writes the given node
-void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) {
-    // the node must have a name
-    if (pNode->mName.length == 0) {
-        std::stringstream ss;
-        ss << "Node_" << pNode;
-        pNode->mName.Set(ss.str());
-    }
-
+void ColladaExporter::WriteNode(const aiNode *pNode) {
     // If the node is associated with a bone, it is a joint node (JOINT)
     // If the node is associated with a bone, it is a joint node (JOINT)
     // otherwise it is a normal node (NODE)
     // otherwise it is a normal node (NODE)
+    // Assimp-specific: nodes with no name cannot be associated with bones
     const char *node_type;
     const char *node_type;
     bool is_joint, is_skeleton_root = false;
     bool is_joint, is_skeleton_root = false;
-    if (nullptr == findBone(pScene, pNode->mName.C_Str())) {
+    if (pNode->mName.length == 0 || nullptr == findBone(mScene, pNode->mName)) {
         node_type = "NODE";
         node_type = "NODE";
         is_joint = false;
         is_joint = false;
     } else {
     } else {
         node_type = "JOINT";
         node_type = "JOINT";
         is_joint = true;
         is_joint = true;
-        if (!pNode->mParent || nullptr == findBone(pScene, pNode->mParent->mName.C_Str())) {
+        if (!pNode->mParent || nullptr == findBone(mScene, pNode->mParent->mName)) {
             is_skeleton_root = true;
             is_skeleton_root = true;
         }
         }
     }
     }
 
 
-    const std::string node_id = XMLIDEncode(pNode->mName.data);
-    const std::string node_name = XMLEscape(pNode->mName.data);
+    const std::string node_id = GetNodeUniqueId(pNode);
+    const std::string node_name = GetNodeName(pNode);
     mOutput << startstr << "<node ";
     mOutput << startstr << "<node ";
     if (is_skeleton_root) {
     if (is_skeleton_root) {
-        mOutput << "id=\"" << node_id << "\" " << (is_joint ? "sid=\"" + node_id + "\"" : ""); // For now, only support one skeleton in a scene.
-        mFoundSkeletonRootNodeID = node_id;
-    } else {
-        mOutput << "id=\"" << node_id << "\" " << (is_joint ? "sid=\"" + node_id + "\"" : "");
+        mFoundSkeletonRootNodeID = node_id; // For now, only support one skeleton in a scene.
     }
     }
-
-    mOutput << " name=\"" << node_name
+    mOutput << "id=\"" << node_id << "\" " << (is_joint ? "sid=\"" + node_id + "\" " : "");
+    mOutput << "name=\"" << node_name
             << "\" type=\"" << node_type
             << "\" type=\"" << node_type
             << "\">" << endstr;
             << "\">" << endstr;
     PushTag();
     PushTag();
@@ -1573,14 +1546,14 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) {
         //check if it is a camera node
         //check if it is a camera node
         for (size_t i = 0; i < mScene->mNumCameras; i++) {
         for (size_t i = 0; i < mScene->mNumCameras; i++) {
             if (mScene->mCameras[i]->mName == pNode->mName) {
             if (mScene->mCameras[i]->mName == pNode->mName) {
-                mOutput << startstr << "<instance_camera url=\"#" << node_id << "-camera\"/>" << endstr;
+                mOutput << startstr << "<instance_camera url=\"#" << GetObjectUniqueId(AiObjectType::Camera, i) << "\"/>" << endstr;
                 break;
                 break;
             }
             }
         }
         }
         //check if it is a light node
         //check if it is a light node
         for (size_t i = 0; i < mScene->mNumLights; i++) {
         for (size_t i = 0; i < mScene->mNumLights; i++) {
             if (mScene->mLights[i]->mName == pNode->mName) {
             if (mScene->mLights[i]->mName == pNode->mName) {
-                mOutput << startstr << "<instance_light url=\"#" << node_id << "-light\"/>" << endstr;
+                mOutput << startstr << "<instance_light url=\"#" << GetObjectUniqueId(AiObjectType::Light, i) << "\"/>" << endstr;
                 break;
                 break;
             }
             }
         }
         }
@@ -1593,22 +1566,22 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) {
             if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
             if (mesh->mNumFaces == 0 || mesh->mNumVertices == 0)
                 continue;
                 continue;
 
 
-            const std::string meshName = mesh->mName.length == 0 ? GetMeshId(pNode->mMeshes[a]) : mesh->mName.C_Str();
+            const std::string meshId = GetObjectUniqueId(AiObjectType::Mesh, pNode->mMeshes[a]);
 
 
             if (mesh->mNumBones == 0) {
             if (mesh->mNumBones == 0) {
-                mOutput << startstr << "<instance_geometry url=\"#" << XMLIDEncode(meshName) << "\">" << endstr;
+                mOutput << startstr << "<instance_geometry url=\"#" << meshId << "\">" << endstr;
                 PushTag();
                 PushTag();
             } else {
             } else {
                 mOutput << startstr
                 mOutput << startstr
-                        << "<instance_controller url=\"#" << XMLIDEncode(meshName) << "-skin\">"
+                        << "<instance_controller url=\"#" << meshId << "-skin\">"
                         << endstr;
                         << endstr;
                 PushTag();
                 PushTag();
 
 
                 // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node.
                 // note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node.
                 // use the first bone to find skeleton root
                 // use the first bone to find skeleton root
-                const aiNode *skeletonRootBoneNode = findSkeletonRootNode(pScene, mesh);
+                const aiNode *skeletonRootBoneNode = findSkeletonRootNode(mScene, mesh);
                 if (skeletonRootBoneNode) {
                 if (skeletonRootBoneNode) {
-                    mFoundSkeletonRootNodeID = XMLIDEncode(skeletonRootBoneNode->mName.C_Str());
+                    mFoundSkeletonRootNodeID = GetNodeUniqueId(skeletonRootBoneNode);
                 }
                 }
                 mOutput << startstr << "<skeleton>#" << mFoundSkeletonRootNodeID << "</skeleton>" << endstr;
                 mOutput << startstr << "<skeleton>#" << mFoundSkeletonRootNodeID << "</skeleton>" << endstr;
             }
             }
@@ -1616,7 +1589,7 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) {
             PushTag();
             PushTag();
             mOutput << startstr << "<technique_common>" << endstr;
             mOutput << startstr << "<technique_common>" << endstr;
             PushTag();
             PushTag();
-            mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << XMLIDEncode(materials[mesh->mMaterialIndex].name) << "\">" << endstr;
+            mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << GetObjectUniqueId(AiObjectType::Material, mesh->mMaterialIndex) << "\">" << endstr;
             PushTag();
             PushTag();
             for (size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa) {
             for (size_t aa = 0; aa < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++aa) {
                 if (mesh->HasTextureCoords(static_cast<unsigned int>(aa)))
                 if (mesh->HasTextureCoords(static_cast<unsigned int>(aa)))
@@ -1641,11 +1614,135 @@ void ColladaExporter::WriteNode(const aiScene *pScene, aiNode *pNode) {
 
 
     // recurse into subnodes
     // recurse into subnodes
     for (size_t a = 0; a < pNode->mNumChildren; ++a)
     for (size_t a = 0; a < pNode->mNumChildren; ++a)
-        WriteNode(pScene, pNode->mChildren[a]);
+        WriteNode(pNode->mChildren[a]);
 
 
     PopTag();
     PopTag();
     mOutput << startstr << "</node>" << endstr;
     mOutput << startstr << "</node>" << endstr;
 }
 }
 
 
+void ColladaExporter::CreateNodeIds(const aiNode *node) {
+    GetNodeUniqueId(node);
+    for (size_t a = 0; a < node->mNumChildren; ++a)
+        CreateNodeIds(node->mChildren[a]);
+}
+
+std::string ColladaExporter::GetNodeUniqueId(const aiNode *node) {
+    // Use the pointer as the key. This is safe because the scene is immutable.
+    auto idIt = mNodeIdMap.find(node);
+    if (idIt != mNodeIdMap.cend())
+        return idIt->second;
+
+    // Prefer the requested Collada Id if extant
+    std::string idStr;
+    aiString origId;
+    if (node->mMetaData && node->mMetaData->Get(AI_METADATA_COLLADA_ID, origId)) {
+        idStr = origId.C_Str();
+    } else {
+        idStr = node->mName.C_Str();
+    }
+    // Make sure the requested id is valid
+    if (idStr.empty())
+        idStr = "node";
+    else
+        idStr = XMLIDEncode(idStr);
+
+    // Ensure it's unique
+    idStr = MakeUniqueId(mUniqueIds, idStr, std::string());
+    mUniqueIds.insert(idStr);
+    mNodeIdMap.insert(std::make_pair(node, idStr));
+    return idStr;
+}
+
+std::string ColladaExporter::GetNodeName(const aiNode *node) {
+
+    return XMLEscape(node->mName.C_Str());
+}
+
+std::string ColladaExporter::GetBoneUniqueId(const aiBone *bone) {
+    // Find the Node that is this Bone
+    const aiNode *boneNode = findBoneNode(mScene->mRootNode, bone);
+    if (boneNode == nullptr)
+        return std::string();
+
+    return GetNodeUniqueId(boneNode);
+}
+
+std::string ColladaExporter::GetObjectUniqueId(AiObjectType type, size_t pIndex) {
+    auto idIt = GetObjectIdMap(type).find(pIndex);
+    if (idIt != GetObjectIdMap(type).cend())
+        return idIt->second;
+
+    // Not seen this object before, create and add
+    NameIdPair result = AddObjectIndexToMaps(type, pIndex);
+    return result.second;
+}
+
+std::string ColladaExporter::GetObjectName(AiObjectType type, size_t pIndex) {
+    auto objectName = GetObjectNameMap(type).find(pIndex);
+    if (objectName != GetObjectNameMap(type).cend())
+        return objectName->second;
+
+    // Not seen this object before, create and add
+    NameIdPair result = AddObjectIndexToMaps(type, pIndex);
+    return result.first;
+}
+
+// Determine unique id and add the name and id to the maps
+// @param type object type
+// @param index object index
+// @param name in/out. Caller to set the original name if known.
+// @param idStr in/out. Caller to set the preferred id if known.
+ColladaExporter::NameIdPair ColladaExporter::AddObjectIndexToMaps(AiObjectType type, size_t index) {
+
+    std::string name;
+    std::string idStr;
+    std::string idPostfix;
+
+    // Get the name and id postfix
+    switch (type) {
+    case AiObjectType::Mesh: name = mScene->mMeshes[index]->mName.C_Str(); break;
+    case AiObjectType::Material: name = mScene->mMaterials[index]->GetName().C_Str(); break;
+    case AiObjectType::Animation: name = mScene->mAnimations[index]->mName.C_Str(); break;
+    case AiObjectType::Light:
+        name = mScene->mLights[index]->mName.C_Str();
+        idPostfix = "-light";
+        break;
+    case AiObjectType::Camera:
+        name = mScene->mCameras[index]->mName.C_Str();
+        idPostfix = "-camera";
+        break;
+    case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type");
+    }
+
+    if (name.empty()) {
+        // Default ids if empty name
+        switch (type) {
+        case AiObjectType::Mesh: idStr = std::string("mesh_"); break;
+        case AiObjectType::Material: idStr = std::string("material_"); break; // This one should never happen
+        case AiObjectType::Animation: idStr = std::string("animation_"); break;
+        case AiObjectType::Light: idStr = std::string("light_"); break;
+        case AiObjectType::Camera: idStr = std::string("camera_"); break;
+        case AiObjectType::Count: throw std::logic_error("ColladaExporter::AiObjectType::Count is not an object type");
+        }
+        idStr.append(to_string(index));
+    } else {
+        idStr = XMLIDEncode(name);
+    }
+
+    if (!name.empty())
+        name = XMLEscape(name);
+
+    idStr = MakeUniqueId(mUniqueIds, idStr, idPostfix);
+
+    // Add to maps
+    mUniqueIds.insert(idStr);
+    GetObjectIdMap(type).insert(std::make_pair(index, idStr));
+    GetObjectNameMap(type).insert(std::make_pair(index, name));
+
+    return std::make_pair(name, idStr);
+}
+
+} // end of namespace Assimp
+
 #endif
 #endif
 #endif
 #endif

+ 115 - 80
code/AssetLib/Collada/ColladaExporter.h

@@ -48,28 +48,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include <assimp/ai_assert.h>
 #include <assimp/ai_assert.h>
 #include <assimp/material.h>
 #include <assimp/material.h>
-#include <assimp/mesh.h>
-#include <assimp/light.h>
-#include <assimp/Exporter.hpp>
+
+#include <array>
+#include <map>
 #include <sstream>
 #include <sstream>
+#include <unordered_set>
 #include <vector>
 #include <vector>
-#include <map>
-
-#include <assimp/StringUtils.h>
 
 
 struct aiScene;
 struct aiScene;
 struct aiNode;
 struct aiNode;
+struct aiLight;
+struct aiBone;
 
 
-namespace Assimp
-{
+namespace Assimp {
+
+class IOSystem;
 
 
 /// Helper class to export a given scene to a Collada file. Just for my personal
 /// Helper class to export a given scene to a Collada file. Just for my personal
 /// comfort when implementing it.
 /// comfort when implementing it.
-class ColladaExporter
-{
+class ColladaExporter {
 public:
 public:
     /// Constructor for a specific scene to export
     /// Constructor for a specific scene to export
-    ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, const std::string& path, const std::string& file);
+    ColladaExporter(const aiScene *pScene, IOSystem *pIOSystem, const std::string &path, const std::string &file);
 
 
     /// Destructor
     /// Destructor
     virtual ~ColladaExporter();
     virtual ~ColladaExporter();
@@ -107,51 +107,87 @@ protected:
     void WriteControllerLibrary();
     void WriteControllerLibrary();
 
 
     /// Writes a skin controller of the given mesh
     /// Writes a skin controller of the given mesh
-    void WriteController( size_t pIndex);
+    void WriteController(size_t pIndex);
 
 
     /// Writes the geometry library
     /// Writes the geometry library
     void WriteGeometryLibrary();
     void WriteGeometryLibrary();
 
 
     /// Writes the given mesh
     /// Writes the given mesh
-    void WriteGeometry( size_t pIndex);
+    void WriteGeometry(size_t pIndex);
 
 
     //enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight };
     //enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight };
     // customized to add animation related type
     // customized to add animation related type
-	enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight, FloatType_Time };
+    enum FloatDataType { FloatType_Vector,
+        FloatType_TexCoord2,
+        FloatType_TexCoord3,
+        FloatType_Color,
+        FloatType_Mat4x4,
+        FloatType_Weight,
+        FloatType_Time };
 
 
     /// Writes a float array of the given type
     /// Writes a float array of the given type
-    void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount);
+    void WriteFloatArray(const std::string &pIdString, FloatDataType pType, const ai_real *pData, size_t pElementCount);
 
 
     /// Writes the scene library
     /// Writes the scene library
     void WriteSceneLibrary();
     void WriteSceneLibrary();
 
 
-	// customized, Writes the animation library
-	void WriteAnimationsLibrary();
-	void WriteAnimationLibrary( size_t pIndex);
-	std::string mFoundSkeletonRootNodeID = "skeleton_root";	 	// will be replaced by found node id in the WriteNode call.
-	
+    // customized, Writes the animation library
+    void WriteAnimationsLibrary();
+    void WriteAnimationLibrary(size_t pIndex);
+    std::string mFoundSkeletonRootNodeID = "skeleton_root"; // will be replaced by found node id in the WriteNode call.
+
     /// Recursively writes the given node
     /// Recursively writes the given node
-    void WriteNode( const aiScene* scene, aiNode* pNode);
+    void WriteNode(const aiNode *pNode);
 
 
     /// Enters a new xml element, which increases the indentation
     /// Enters a new xml element, which increases the indentation
-    void PushTag() { startstr.append( "  "); }
+    void PushTag() { startstr.append("  "); }
     /// Leaves an element, decreasing the indentation
     /// Leaves an element, decreasing the indentation
-    void PopTag() { 
-        ai_assert( startstr.length() > 1); 
-        startstr.erase( startstr.length() - 2); 
+    void PopTag() {
+        ai_assert(startstr.length() > 1);
+        startstr.erase(startstr.length() - 2);
     }
     }
 
 
-    /// Creates a mesh ID for the given mesh
-    std::string GetMeshId( size_t pIndex) const {
-        return std::string( "meshId" ) + to_string(pIndex);
-    }
+    void CreateNodeIds(const aiNode *node);
+
+    /// Get or Create a unique Node ID string for the given Node
+    std::string GetNodeUniqueId(const aiNode *node);
+    std::string GetNodeName(const aiNode *node);
+
+    std::string GetBoneUniqueId(const aiBone *bone);
+
+    enum class AiObjectType {
+        Mesh,
+        Material,
+        Animation,
+        Light,
+        Camera,
+        Count,
+    };
+    /// Get or Create a unique ID string for the given scene object index
+    std::string GetObjectUniqueId(AiObjectType type, size_t pIndex);
+    /// Get or Create a name string for the given scene object index
+    std::string GetObjectName(AiObjectType type, size_t pIndex);
+
+    typedef std::map<size_t, std::string> IndexIdMap;
+    typedef std::pair<std::string, std::string> NameIdPair;
+    NameIdPair AddObjectIndexToMaps(AiObjectType type, size_t pIndex);
+
+    // Helpers
+    inline IndexIdMap &GetObjectIdMap(AiObjectType type) { return mObjectIdMap[static_cast<size_t>(type)]; }
+    inline IndexIdMap &GetObjectNameMap(AiObjectType type) { return mObjectNameMap[static_cast<size_t>(type)]; }
+
+private:
+    std::unordered_set<std::string> mUniqueIds; // Cache of used unique ids
+    std::map<const void *, std::string> mNodeIdMap; // Cache of encoded node and bone ids
+    std::array<IndexIdMap, static_cast<size_t>(AiObjectType::Count)> mObjectIdMap; // Cache of encoded unique IDs
+    std::array<IndexIdMap, static_cast<size_t>(AiObjectType::Count)> mObjectNameMap; // Cache of encoded names
 
 
 public:
 public:
     /// Stringstream to write all output into
     /// Stringstream to write all output into
     std::stringstream mOutput;
     std::stringstream mOutput;
 
 
     /// The IOSystem for output
     /// The IOSystem for output
-    IOSystem* mIOSystem;
+    IOSystem *mIOSystem;
 
 
     /// Path of the directory where the scene will be exported
     /// Path of the directory where the scene will be exported
     const std::string mPath;
     const std::string mPath;
@@ -160,63 +196,62 @@ public:
     const std::string mFile;
     const std::string mFile;
 
 
     /// The scene to be written
     /// The scene to be written
-    const aiScene* mScene;
-    bool mSceneOwned;
+    const aiScene *const mScene;
+    std::string mSceneId;
+    bool mAdd_root_node = false;
 
 
     /// current line start string, contains the current indentation for simple stream insertion
     /// current line start string, contains the current indentation for simple stream insertion
     std::string startstr;
     std::string startstr;
     /// current line end string for simple stream insertion
     /// current line end string for simple stream insertion
-    std::string endstr;
-
-  // pair of color and texture - texture precedences color
-  struct Surface
-  {
-    bool exist;
-    aiColor4D color;
-    std::string texture;
-    size_t channel;
-    Surface() { exist = false; channel = 0; }
-  };
-
-  struct Property
-  {
-    bool exist;
-     ai_real value;
-     Property()
-         : exist(false)
-         , value(0.0)
-     {}
-  };
-
-  // summarize a material in an convenient way.
-  struct Material
-  {
-    std::string name;
-    std::string shading_model;
-    Surface ambient, diffuse, specular, emissive, reflective, transparent, normal;
-    Property shininess, transparency, index_refraction;
-
-    Material() {}
-  };
-
-  std::vector<Material> materials;
-
-  std::map<unsigned int, std::string> textures;
+    const std::string endstr;
+
+    // pair of color and texture - texture precedences color
+    struct Surface {
+        bool exist;
+        aiColor4D color;
+        std::string texture;
+        size_t channel;
+        Surface() {
+            exist = false;
+            channel = 0;
+        }
+    };
+
+    struct Property {
+        bool exist;
+        ai_real value;
+        Property() :
+                exist(false),
+                value(0.0) {}
+    };
+
+    // summarize a material in an convenient way.
+    struct Material {
+        std::string id;
+        std::string name;
+        std::string shading_model;
+        Surface ambient, diffuse, specular, emissive, reflective, transparent, normal;
+        Property shininess, transparency, index_refraction;
+
+        Material() {}
+    };
+
+    std::map<unsigned int, std::string> textures;
 
 
 public:
 public:
-  /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions
-  /// Reads a single surface entry from the given material keys
-  void ReadMaterialSurface( Surface& poSurface, const aiMaterial* pSrcMat, aiTextureType pTexture, const char* pKey, size_t pType, size_t pIndex);
-  /// Writes an image entry for the given surface
-  void WriteImageEntry( const Surface& pSurface, const std::string& pNameAdd);
-  /// Writes the two parameters necessary for referencing a texture in an effect entry
-  void WriteTextureParamEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pMatName);
-  /// Writes a color-or-texture entry into an effect definition
-  void WriteTextureColorEntry( const Surface& pSurface, const std::string& pTypeName, const std::string& pImageName);
-  /// Writes a scalar property
-  void WriteFloatEntry( const Property& pProperty, const std::string& pTypeName);
+    /// Dammit C++ - y u no compile two-pass? No I have to add all methods below the struct definitions
+    /// Reads a single surface entry from the given material keys
+    bool ReadMaterialSurface(Surface &poSurface, const aiMaterial &pSrcMat, aiTextureType pTexture, const char *pKey, size_t pType, size_t pIndex);
+    /// Writes an image entry for the given surface
+    void WriteImageEntry(const Surface &pSurface, const std::string &imageId);
+    /// Writes the two parameters necessary for referencing a texture in an effect entry
+    void WriteTextureParamEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &materialId);
+    /// Writes a color-or-texture entry into an effect definition
+    void WriteTextureColorEntry(const Surface &pSurface, const std::string &pTypeName, const std::string &imageId);
+    /// Writes a scalar property
+    void WriteFloatEntry(const Property &pProperty, const std::string &pTypeName);
 };
 };
 
 
-}
+} // namespace Assimp
 
 
 #endif // !! AI_COLLADAEXPORTER_H_INC
 #endif // !! AI_COLLADAEXPORTER_H_INC

+ 8 - 15
code/AssetLib/Collada/ColladaHelper.cpp

@@ -43,8 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "ColladaHelper.h"
 #include "ColladaHelper.h"
 
 
-#include <assimp/commonMetaData.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/ParsingUtils.h>
+#include <assimp/commonMetaData.h>
 
 
 namespace Assimp {
 namespace Assimp {
 namespace Collada {
 namespace Collada {
@@ -63,42 +63,35 @@ const MetaKeyPairVector &GetColladaAssimpMetaKeys() {
 
 
 const MetaKeyPairVector MakeColladaAssimpMetaKeysCamelCase() {
 const MetaKeyPairVector MakeColladaAssimpMetaKeysCamelCase() {
     MetaKeyPairVector result = MakeColladaAssimpMetaKeys();
     MetaKeyPairVector result = MakeColladaAssimpMetaKeys();
-    for (auto &val : result)
-    {
+    for (auto &val : result) {
         ToCamelCase(val.first);
         ToCamelCase(val.first);
     }
     }
     return result;
     return result;
 };
 };
 
 
-const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase()
-{
+const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase() {
     static const MetaKeyPairVector result = MakeColladaAssimpMetaKeysCamelCase();
     static const MetaKeyPairVector result = MakeColladaAssimpMetaKeysCamelCase();
     return result;
     return result;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Convert underscore_separated to CamelCase: "authoring_tool" becomes "AuthoringTool"
 // Convert underscore_separated to CamelCase: "authoring_tool" becomes "AuthoringTool"
-void ToCamelCase(std::string &text)
-{
+void ToCamelCase(std::string &text) {
     if (text.empty())
     if (text.empty())
         return;
         return;
     // Capitalise first character
     // Capitalise first character
     auto it = text.begin();
     auto it = text.begin();
     (*it) = ToUpper(*it);
     (*it) = ToUpper(*it);
     ++it;
     ++it;
-    for (/*started above*/ ; it != text.end(); /*iterated below*/)
-    {
-        if ((*it) == '_')
-        {
+    for (/*started above*/; it != text.end(); /*iterated below*/) {
+        if ((*it) == '_') {
             it = text.erase(it);
             it = text.erase(it);
             if (it != text.end())
             if (it != text.end())
                 (*it) = ToUpper(*it);
                 (*it) = ToUpper(*it);
-        }
-        else
-        {
+        } else {
             // Make lower case
             // Make lower case
             (*it) = ToLower(*it);
             (*it) = ToLower(*it);
-            ++it;               
+            ++it;
         }
         }
     }
     }
 }
 }

+ 185 - 224
code/AssetLib/Collada/ColladaHelper.h

@@ -45,31 +45,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_COLLADAHELPER_H_INC
 #ifndef AI_COLLADAHELPER_H_INC
 #define AI_COLLADAHELPER_H_INC
 #define AI_COLLADAHELPER_H_INC
 
 
-#include <map>
-#include <vector>
-#include <set>
-#include <stdint.h>
 #include <assimp/light.h>
 #include <assimp/light.h>
-#include <assimp/mesh.h>
 #include <assimp/material.h>
 #include <assimp/material.h>
+#include <assimp/mesh.h>
+#include <stdint.h>
+#include <map>
+#include <set>
+#include <vector>
 
 
 struct aiMaterial;
 struct aiMaterial;
 
 
-namespace Assimp    {
-namespace Collada       {
+namespace Assimp {
+namespace Collada {
 
 
 /** Collada file versions which evolved during the years ... */
 /** Collada file versions which evolved during the years ... */
-enum FormatVersion
-{
+enum FormatVersion {
     FV_1_5_n,
     FV_1_5_n,
     FV_1_4_n,
     FV_1_4_n,
     FV_1_3_n
     FV_1_3_n
 };
 };
 
 
-
 /** Transformation types that can be applied to a node */
 /** Transformation types that can be applied to a node */
-enum TransformType
-{
+enum TransformType {
     TF_LOOKAT,
     TF_LOOKAT,
     TF_ROTATE,
     TF_ROTATE,
     TF_TRANSLATE,
     TF_TRANSLATE,
@@ -79,10 +76,9 @@ enum TransformType
 };
 };
 
 
 /** Different types of input data to a vertex or face */
 /** Different types of input data to a vertex or face */
-enum InputType
-{
+enum InputType {
     IT_Invalid,
     IT_Invalid,
-    IT_Vertex,  // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
+    IT_Vertex, // special type for per-index data referring to the <vertices> element carrying the per-vertex data.
     IT_Position,
     IT_Position,
     IT_Normal,
     IT_Normal,
     IT_Texcoord,
     IT_Texcoord,
@@ -92,15 +88,13 @@ enum InputType
 };
 };
 
 
 /** Supported controller types */
 /** Supported controller types */
-enum ControllerType
-{
+enum ControllerType {
     Skin,
     Skin,
     Morph
     Morph
 };
 };
 
 
 /** Supported morph methods */
 /** Supported morph methods */
-enum MorphMethod
-{
+enum MorphMethod {
     Normalized,
     Normalized,
     Relative
     Relative
 };
 };
@@ -118,24 +112,21 @@ const MetaKeyPairVector &GetColladaAssimpMetaKeysCamelCase();
 void ToCamelCase(std::string &text);
 void ToCamelCase(std::string &text);
 
 
 /** Contains all data for one of the different transformation types */
 /** Contains all data for one of the different transformation types */
-struct Transform
-{
-    std::string mID;  ///< SID of the transform step, by which anim channels address their target node
+struct Transform {
+    std::string mID; ///< SID of the transform step, by which anim channels address their target node
     TransformType mType;
     TransformType mType;
     ai_real f[16]; ///< Interpretation of data depends on the type of the transformation
     ai_real f[16]; ///< Interpretation of data depends on the type of the transformation
 };
 };
 
 
 /** A collada camera. */
 /** A collada camera. */
-struct Camera
-{
-    Camera()
-        :   mOrtho  (false)
-        ,   mHorFov (10e10f)
-        ,   mVerFov (10e10f)
-        ,   mAspect (10e10f)
-        ,   mZNear  (0.1f)
-        ,   mZFar   (1000.f)
-    {}
+struct Camera {
+    Camera() :
+            mOrtho(false),
+            mHorFov(10e10f),
+            mVerFov(10e10f),
+            mAspect(10e10f),
+            mZNear(0.1f),
+            mZFar(1000.f) {}
 
 
     // Name of camera
     // Name of camera
     std::string mName;
     std::string mName;
@@ -159,19 +150,17 @@ struct Camera
 #define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
 #define ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET 1e9f
 
 
 /** A collada light source. */
 /** A collada light source. */
-struct Light
-{
-    Light()
-        :   mType            (aiLightSource_UNDEFINED)
-        ,   mAttConstant     (1.f)
-        ,   mAttLinear       (0.f)
-        ,   mAttQuadratic    (0.f)
-        ,   mFalloffAngle    (180.f)
-        ,   mFalloffExponent (0.f)
-        ,   mPenumbraAngle   (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
-        ,   mOuterAngle      (ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET)
-        ,   mIntensity       (1.f)
-    {}
+struct Light {
+    Light() :
+            mType(aiLightSource_UNDEFINED),
+            mAttConstant(1.f),
+            mAttLinear(0.f),
+            mAttQuadratic(0.f),
+            mFalloffAngle(180.f),
+            mFalloffExponent(0.f),
+            mPenumbraAngle(ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET),
+            mOuterAngle(ASSIMP_COLLADA_LIGHT_ANGLE_NOT_SET),
+            mIntensity(1.f) {}
 
 
     //! Type of the light source aiLightSourceType + ambient
     //! Type of the light source aiLightSourceType + ambient
     unsigned int mType;
     unsigned int mType;
@@ -180,7 +169,7 @@ struct Light
     aiColor3D mColor;
     aiColor3D mColor;
 
 
     //! Light attenuation
     //! Light attenuation
-    ai_real mAttConstant,mAttLinear,mAttQuadratic;
+    ai_real mAttConstant, mAttLinear, mAttQuadratic;
 
 
     //! Spot light falloff
     //! Spot light falloff
     ai_real mFalloffAngle;
     ai_real mFalloffAngle;
@@ -198,12 +187,10 @@ struct Light
 };
 };
 
 
 /** Short vertex index description */
 /** Short vertex index description */
-struct InputSemanticMapEntry
-{
-    InputSemanticMapEntry()
-        :   mSet(0)
-        ,   mType(IT_Invalid)
-    {}
+struct InputSemanticMapEntry {
+    InputSemanticMapEntry() :
+            mSet(0),
+            mType(IT_Invalid) {}
 
 
     //! Index of set, optional
     //! Index of set, optional
     unsigned int mSet;
     unsigned int mSet;
@@ -213,8 +200,7 @@ struct InputSemanticMapEntry
 };
 };
 
 
 /** Table to map from effect to vertex input semantics */
 /** Table to map from effect to vertex input semantics */
-struct SemanticMappingTable
-{
+struct SemanticMappingTable {
     //! Name of material
     //! Name of material
     std::string mMatName;
     std::string mMatName;
 
 
@@ -222,7 +208,7 @@ struct SemanticMappingTable
     std::map<std::string, InputSemanticMapEntry> mMap;
     std::map<std::string, InputSemanticMapEntry> mMap;
 
 
     //! For std::find
     //! For std::find
-    bool operator == (const std::string& s) const {
+    bool operator==(const std::string &s) const {
         return s == mMatName;
         return s == mMatName;
     }
     }
 };
 };
@@ -230,8 +216,7 @@ struct SemanticMappingTable
 /** A reference to a mesh inside a node, including materials assigned to the various subgroups.
 /** A reference to a mesh inside a node, including materials assigned to the various subgroups.
  * The ID refers to either a mesh or a controller which specifies the mesh
  * The ID refers to either a mesh or a controller which specifies the mesh
  */
  */
-struct MeshInstance
-{
+struct MeshInstance {
     ///< ID of the mesh or controller to be instanced
     ///< ID of the mesh or controller to be instanced
     std::string mMeshOrController;
     std::string mMeshOrController;
 
 
@@ -240,34 +225,30 @@ struct MeshInstance
 };
 };
 
 
 /** A reference to a camera inside a node*/
 /** A reference to a camera inside a node*/
-struct CameraInstance
-{
-     ///< ID of the camera
+struct CameraInstance {
+    ///< ID of the camera
     std::string mCamera;
     std::string mCamera;
 };
 };
 
 
 /** A reference to a light inside a node*/
 /** A reference to a light inside a node*/
-struct LightInstance
-{
-     ///< ID of the camera
+struct LightInstance {
+    ///< ID of the camera
     std::string mLight;
     std::string mLight;
 };
 };
 
 
 /** A reference to a node inside a node*/
 /** A reference to a node inside a node*/
-struct NodeInstance
-{
-     ///< ID of the node
+struct NodeInstance {
+    ///< ID of the node
     std::string mNode;
     std::string mNode;
 };
 };
 
 
 /** A node in a scene hierarchy */
 /** A node in a scene hierarchy */
-struct Node
-{
+struct Node {
     std::string mName;
     std::string mName;
     std::string mID;
     std::string mID;
     std::string mSID;
     std::string mSID;
-    Node* mParent;
-    std::vector<Node*> mChildren;
+    Node *mParent;
+    std::vector<Node *> mChildren;
 
 
     /** Operations in order to calculate the resulting transformation to parent. */
     /** Operations in order to calculate the resulting transformation to parent. */
     std::vector<Transform> mTransforms;
     std::vector<Transform> mTransforms;
@@ -288,80 +269,83 @@ struct Node
     std::string mPrimaryCamera;
     std::string mPrimaryCamera;
 
 
     //! Constructor. Begin with a zero parent
     //! Constructor. Begin with a zero parent
-    Node()
-    : mParent( nullptr ){
+    Node() :
+            mParent(nullptr) {
         // empty
         // empty
     }
     }
 
 
     //! Destructor: delete all children subsequently
     //! Destructor: delete all children subsequently
     ~Node() {
     ~Node() {
-        for( std::vector<Node*>::iterator it = mChildren.begin(); it != mChildren.end(); ++it)
+        for (std::vector<Node *>::iterator it = mChildren.begin(); it != mChildren.end(); ++it)
             delete *it;
             delete *it;
     }
     }
 };
 };
 
 
 /** Data source array: either floats or strings */
 /** Data source array: either floats or strings */
-struct Data
-{
+struct Data {
     bool mIsStringArray;
     bool mIsStringArray;
     std::vector<ai_real> mValues;
     std::vector<ai_real> mValues;
     std::vector<std::string> mStrings;
     std::vector<std::string> mStrings;
 };
 };
 
 
 /** Accessor to a data array */
 /** Accessor to a data array */
-struct Accessor
-{
-    size_t mCount;   // in number of objects
-    size_t mSize;    // size of an object, in elements (floats or strings, mostly 1)
-    size_t mOffset;  // in number of values
-    size_t mStride;  // Stride in number of values
+struct Accessor {
+    size_t mCount; // in number of objects
+    size_t mSize; // size of an object, in elements (floats or strings, mostly 1)
+    size_t mOffset; // in number of values
+    size_t mStride; // Stride in number of values
     std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
     std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
     size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on.
     size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on.
-                          // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
-    std::string mSource;   // URL of the source array
-    mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
-
-    Accessor()
-    {
-        mCount = 0; mSize = 0; mOffset = 0; mStride = 0; mData = NULL;
+            // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
+    std::string mSource; // URL of the source array
+    mutable const Data *mData; // Pointer to the source array, if resolved. nullptr else
+
+    Accessor() {
+        mCount = 0;
+        mSize = 0;
+        mOffset = 0;
+        mStride = 0;
+        mData = nullptr;
         mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
         mSubOffset[0] = mSubOffset[1] = mSubOffset[2] = mSubOffset[3] = 0;
     }
     }
 };
 };
 
 
 /** A single face in a mesh */
 /** A single face in a mesh */
-struct Face
-{
+struct Face {
     std::vector<size_t> mIndices;
     std::vector<size_t> mIndices;
 };
 };
 
 
 /** An input channel for mesh data, referring to a single accessor */
 /** An input channel for mesh data, referring to a single accessor */
-struct InputChannel
-{
-    InputType mType;      // Type of the data
-    size_t mIndex;        // Optional index, if multiple sets of the same data type are given
-    size_t mOffset;       // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
+struct InputChannel {
+    InputType mType; // Type of the data
+    size_t mIndex; // Optional index, if multiple sets of the same data type are given
+    size_t mOffset; // Index offset in the indices array of per-face indices. Don't ask, can't explain that any better.
     std::string mAccessor; // ID of the accessor where to read the actual values from.
     std::string mAccessor; // ID of the accessor where to read the actual values from.
-    mutable const Accessor* mResolved; // Pointer to the accessor, if resolved. NULL else
+    mutable const Accessor *mResolved; // Pointer to the accessor, if resolved. nullptr else
 
 
-    InputChannel() { mType = IT_Invalid; mIndex = 0; mOffset = 0; mResolved = NULL; }
+    InputChannel() {
+        mType = IT_Invalid;
+        mIndex = 0;
+        mOffset = 0;
+        mResolved = nullptr;
+    }
 };
 };
 
 
 /** Subset of a mesh with a certain material */
 /** Subset of a mesh with a certain material */
-struct SubMesh
-{
+struct SubMesh {
     std::string mMaterial; ///< subgroup identifier
     std::string mMaterial; ///< subgroup identifier
     size_t mNumFaces; ///< number of faces in this submesh
     size_t mNumFaces; ///< number of faces in this submesh
 };
 };
 
 
 /** Contains data for a single mesh */
 /** Contains data for a single mesh */
-struct Mesh
-{
-    Mesh()
-    {
-        for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS;++i)
+struct Mesh {
+    Mesh(const std::string &id) :
+            mId(id) {
+        for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i)
             mNumUVComponents[i] = 2;
             mNumUVComponents[i] = 2;
     }
     }
 
 
+    const std::string mId;
     std::string mName;
     std::string mName;
 
 
     // just to check if there's some sophisticated addressing involved...
     // just to check if there's some sophisticated addressing involved...
@@ -377,7 +361,7 @@ struct Mesh
     std::vector<aiVector3D> mTangents;
     std::vector<aiVector3D> mTangents;
     std::vector<aiVector3D> mBitangents;
     std::vector<aiVector3D> mBitangents;
     std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
     std::vector<aiVector3D> mTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
-    std::vector<aiColor4D>  mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
+    std::vector<aiColor4D> mColors[AI_MAX_NUMBER_OF_COLOR_SETS];
 
 
     unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
     unsigned int mNumUVComponents[AI_MAX_NUMBER_OF_TEXTURECOORDS];
 
 
@@ -394,8 +378,7 @@ struct Mesh
 };
 };
 
 
 /** Which type of primitives the ReadPrimitives() function is going to read */
 /** Which type of primitives the ReadPrimitives() function is going to read */
-enum PrimitiveType
-{
+enum PrimitiveType {
     Prim_Invalid,
     Prim_Invalid,
     Prim_Lines,
     Prim_Lines,
     Prim_LineStrip,
     Prim_LineStrip,
@@ -407,8 +390,7 @@ enum PrimitiveType
 };
 };
 
 
 /** A skeleton controller to deform a mesh with the use of joints */
 /** A skeleton controller to deform a mesh with the use of joints */
-struct Controller
-{
+struct Controller {
     // controller type
     // controller type
     ControllerType mType;
     ControllerType mType;
 
 
@@ -436,36 +418,32 @@ struct Controller
     std::vector<size_t> mWeightCounts;
     std::vector<size_t> mWeightCounts;
 
 
     // JointIndex-WeightIndex pairs for all vertices
     // JointIndex-WeightIndex pairs for all vertices
-    std::vector< std::pair<size_t, size_t> > mWeights;
+    std::vector<std::pair<size_t, size_t>> mWeights;
 
 
     std::string mMorphTarget;
     std::string mMorphTarget;
     std::string mMorphWeight;
     std::string mMorphWeight;
 };
 };
 
 
 /** A collada material. Pretty much the only member is a reference to an effect. */
 /** A collada material. Pretty much the only member is a reference to an effect. */
-struct Material
-{
+struct Material {
     std::string mName;
     std::string mName;
     std::string mEffect;
     std::string mEffect;
 };
 };
 
 
 /** Type of the effect param */
 /** Type of the effect param */
-enum ParamType
-{
+enum ParamType {
     Param_Sampler,
     Param_Sampler,
     Param_Surface
     Param_Surface
 };
 };
 
 
 /** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */
 /** A param for an effect. Might be of several types, but they all just refer to each other, so I summarize them */
-struct EffectParam
-{
+struct EffectParam {
     ParamType mType;
     ParamType mType;
     std::string mReference; // to which other thing the param is referring to.
     std::string mReference; // to which other thing the param is referring to.
 };
 };
 
 
 /** Shading type supported by the standard effect spec of Collada */
 /** Shading type supported by the standard effect spec of Collada */
-enum ShadeType
-{
+enum ShadeType {
     Shade_Invalid,
     Shade_Invalid,
     Shade_Constant,
     Shade_Constant,
     Shade_Lambert,
     Shade_Lambert,
@@ -474,18 +452,16 @@ enum ShadeType
 };
 };
 
 
 /** Represents a texture sampler in collada */
 /** Represents a texture sampler in collada */
-struct Sampler
-{
-    Sampler()
-        :   mWrapU      (true)
-        ,   mWrapV      (true)
-        ,   mMirrorU    ()
-        ,   mMirrorV    ()
-        ,   mOp         (aiTextureOp_Multiply)
-        ,   mUVId       (UINT_MAX)
-        ,   mWeighting  (1.f)
-        ,   mMixWithPrevious (1.f)
-    {}
+struct Sampler {
+    Sampler() :
+            mWrapU(true),
+            mWrapV(true),
+            mMirrorU(),
+            mMirrorV(),
+            mOp(aiTextureOp_Multiply),
+            mUVId(UINT_MAX),
+            mWeighting(1.f),
+            mMixWithPrevious(1.f) {}
 
 
     /** Name of image reference
     /** Name of image reference
      */
      */
@@ -537,18 +513,17 @@ struct Sampler
 
 
 /** A collada effect. Can contain about anything according to the Collada spec,
 /** A collada effect. Can contain about anything according to the Collada spec,
     but we limit our version to a reasonable subset. */
     but we limit our version to a reasonable subset. */
-struct Effect
-{
+struct Effect {
     // Shading mode
     // Shading mode
     ShadeType mShadeType;
     ShadeType mShadeType;
 
 
     // Colors
     // Colors
     aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular,
     aiColor4D mEmissive, mAmbient, mDiffuse, mSpecular,
-        mTransparent, mReflective;
+            mTransparent, mReflective;
 
 
     // Textures
     // Textures
     Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular,
     Sampler mTexEmissive, mTexAmbient, mTexDiffuse, mTexSpecular,
-        mTexTransparent, mTexBump, mTexReflective;
+            mTexTransparent, mTexBump, mTexReflective;
 
 
     // Scalar factory
     // Scalar factory
     ai_real mShininess, mRefractIndex, mReflectivity;
     ai_real mShininess, mRefractIndex, mReflectivity;
@@ -566,30 +541,28 @@ struct Effect
     // Double-sided?
     // Double-sided?
     bool mDoubleSided, mWireframe, mFaceted;
     bool mDoubleSided, mWireframe, mFaceted;
 
 
-    Effect()
-        : mShadeType    (Shade_Phong)
-        , mEmissive     ( 0, 0, 0, 1)
-        , mAmbient      ( 0.1f, 0.1f, 0.1f, 1)
-        , mDiffuse      ( 0.6f, 0.6f, 0.6f, 1)
-        , mSpecular     ( 0.4f, 0.4f, 0.4f, 1)
-        , mTransparent  ( 0, 0, 0, 1)
-        , mShininess    (10.0f)
-        , mRefractIndex (1.f)
-        , mReflectivity (0.f)
-        , mTransparency (1.f)
-        , mHasTransparency (false)
-        , mRGBTransparency(false)
-        , mInvertTransparency(false)
-        , mDoubleSided  (false)
-        , mWireframe    (false)
-        , mFaceted      (false)
-    {
+    Effect() :
+            mShadeType(Shade_Phong),
+            mEmissive(0, 0, 0, 1),
+            mAmbient(0.1f, 0.1f, 0.1f, 1),
+            mDiffuse(0.6f, 0.6f, 0.6f, 1),
+            mSpecular(0.4f, 0.4f, 0.4f, 1),
+            mTransparent(0, 0, 0, 1),
+            mShininess(10.0f),
+            mRefractIndex(1.f),
+            mReflectivity(0.f),
+            mTransparency(1.f),
+            mHasTransparency(false),
+            mRGBTransparency(false),
+            mInvertTransparency(false),
+            mDoubleSided(false),
+            mWireframe(false),
+            mFaceted(false) {
     }
     }
 };
 };
 
 
 /** An image, meaning texture */
 /** An image, meaning texture */
-struct Image
-{
+struct Image {
     std::string mFileName;
     std::string mFileName;
 
 
     /** Embedded image data */
     /** Embedded image data */
@@ -600,8 +573,7 @@ struct Image
 };
 };
 
 
 /** An animation channel. */
 /** An animation channel. */
-struct AnimationChannel
-{
+struct AnimationChannel {
     /** URL of the data to animate. Could be about anything, but we support only the
     /** URL of the data to animate. Could be about anything, but we support only the
      * "NodeID/TransformID.SubElement" notation
      * "NodeID/TransformID.SubElement" notation
      */
      */
@@ -620,8 +592,7 @@ struct AnimationChannel
 };
 };
 
 
 /** An animation. Container for 0-x animation channels or 0-x animations */
 /** An animation. Container for 0-x animation channels or 0-x animations */
-struct Animation
-{
+struct Animation {
     /** Anim name */
     /** Anim name */
     std::string mName;
     std::string mName;
 
 
@@ -629,96 +600,86 @@ struct Animation
     std::vector<AnimationChannel> mChannels;
     std::vector<AnimationChannel> mChannels;
 
 
     /** the sub-animations, if any */
     /** the sub-animations, if any */
-    std::vector<Animation*> mSubAnims;
+    std::vector<Animation *> mSubAnims;
 
 
     /** Destructor */
     /** Destructor */
-    ~Animation()
-    {
-        for( std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
+    ~Animation() {
+        for (std::vector<Animation *>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
             delete *it;
             delete *it;
     }
     }
 
 
-	/** Collect all channels in the animation hierarchy into a single channel list. */
-	void CollectChannelsRecursively(std::vector<AnimationChannel> &channels)
-	{
-		channels.insert(channels.end(), mChannels.begin(), mChannels.end());
+    /** Collect all channels in the animation hierarchy into a single channel list. */
+    void CollectChannelsRecursively(std::vector<AnimationChannel> &channels) {
+        channels.insert(channels.end(), mChannels.begin(), mChannels.end());
 
 
-		for (std::vector<Animation*>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it)
-		{
-			Animation *pAnim = (*it);
+        for (std::vector<Animation *>::iterator it = mSubAnims.begin(); it != mSubAnims.end(); ++it) {
+            Animation *pAnim = (*it);
 
 
-			pAnim->CollectChannelsRecursively(channels);
-		}
-	}
+            pAnim->CollectChannelsRecursively(channels);
+        }
+    }
 
 
-	/** Combine all single-channel animations' channel into the same (parent) animation channel list. */
-	void CombineSingleChannelAnimations()
-	{
-		CombineSingleChannelAnimationsRecursively(this);
-	}
+    /** Combine all single-channel animations' channel into the same (parent) animation channel list. */
+    void CombineSingleChannelAnimations() {
+        CombineSingleChannelAnimationsRecursively(this);
+    }
 
 
-	void CombineSingleChannelAnimationsRecursively(Animation *pParent)
-	{
-		std::set<std::string> childrenTargets;
-		bool childrenAnimationsHaveDifferentChannels = true;
+    void CombineSingleChannelAnimationsRecursively(Animation *pParent) {
+        std::set<std::string> childrenTargets;
+        bool childrenAnimationsHaveDifferentChannels = true;
 
 
-		for (std::vector<Animation*>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();)
-		{
-			Animation *anim = *it;
-			CombineSingleChannelAnimationsRecursively(anim);
+        for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
+            Animation *anim = *it;
+            CombineSingleChannelAnimationsRecursively(anim);
 
 
-			if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 &&
-				childrenTargets.find(anim->mChannels[0].mTarget) == childrenTargets.end()) {
-				childrenTargets.insert(anim->mChannels[0].mTarget);
-			} else {
-				childrenAnimationsHaveDifferentChannels = false;
-			}
+            if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 &&
+                    childrenTargets.find(anim->mChannels[0].mTarget) == childrenTargets.end()) {
+                childrenTargets.insert(anim->mChannels[0].mTarget);
+            } else {
+                childrenAnimationsHaveDifferentChannels = false;
+            }
 
 
-			++it;
-		}
+            ++it;
+        }
 
 
-		// We only want to combine animations if they have different channels
-		if (childrenAnimationsHaveDifferentChannels)
-		{
-			for (std::vector<Animation*>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();)
-			{
-				Animation *anim = *it;
+        // We only want to combine animations if they have different channels
+        if (childrenAnimationsHaveDifferentChannels) {
+            for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
+                Animation *anim = *it;
 
 
-				pParent->mChannels.push_back(anim->mChannels[0]);
+                pParent->mChannels.push_back(anim->mChannels[0]);
 
 
-				it = pParent->mSubAnims.erase(it);
+                it = pParent->mSubAnims.erase(it);
 
 
-				delete anim;
-				continue;
-			}
-		}
-	}
+                delete anim;
+                continue;
+            }
+        }
+    }
 };
 };
 
 
 /** Description of a collada animation channel which has been determined to affect the current node */
 /** Description of a collada animation channel which has been determined to affect the current node */
-struct ChannelEntry
-{
-    const Collada::AnimationChannel* mChannel; ///> the source channel
+struct ChannelEntry {
+    const Collada::AnimationChannel *mChannel; ///> the source channel
     std::string mTargetId;
     std::string mTargetId;
-    std::string mTransformId;   // the ID of the transformation step of the node which is influenced
+    std::string mTransformId; // the ID of the transformation step of the node which is influenced
     size_t mTransformIndex; // Index into the node's transform chain to apply the channel to
     size_t mTransformIndex; // Index into the node's transform chain to apply the channel to
     size_t mSubElement; // starting index inside the transform data
     size_t mSubElement; // starting index inside the transform data
 
 
     // resolved data references
     // resolved data references
-    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
-
-    ChannelEntry()
-      : mChannel()
-      , mTransformIndex()
-      , mSubElement()
-      , mTimeAccessor()
-      , mTimeData()
-      , mValueAccessor()
-      , mValueData()
-   {}
+    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
+
+    ChannelEntry() :
+            mChannel(),
+            mTransformIndex(),
+            mSubElement(),
+            mTimeAccessor(),
+            mTimeData(),
+            mValueAccessor(),
+            mValueData() {}
 };
 };
 
 
 } // end of namespace Collada
 } // end of namespace Collada

Різницю між файлами не показано, бо вона завелика
+ 234 - 253
code/AssetLib/Collada/ColladaLoader.cpp


Різницю між файлами не показано, бо вона завелика
+ 179 - 330
code/AssetLib/Collada/ColladaParser.cpp


+ 235 - 236
code/AssetLib/Collada/ColladaParser.h

@@ -47,346 +47,345 @@
 #ifndef AI_COLLADAPARSER_H_INC
 #ifndef AI_COLLADAPARSER_H_INC
 #define AI_COLLADAPARSER_H_INC
 #define AI_COLLADAPARSER_H_INC
 
 
-#include <assimp/irrXMLWrapper.h>
 #include "ColladaHelper.h"
 #include "ColladaHelper.h"
-#include <assimp/ai_assert.h>
 #include <assimp/TinyFormatter.h>
 #include <assimp/TinyFormatter.h>
+#include <assimp/ai_assert.h>
+#include <assimp/irrXMLWrapper.h>
 
 
-namespace Assimp
-{
-    class ZipArchiveIOSystem;
+namespace Assimp {
+class ZipArchiveIOSystem;
 
 
-    // ------------------------------------------------------------------------------------------
-    /** Parser helper class for the Collada loader.
+// ------------------------------------------------------------------------------------------
+/** Parser helper class for the Collada loader.
      *
      *
      *  Does all the XML reading and builds internal data structures from it,
      *  Does all the XML reading and builds internal data structures from it,
      *  but leaves the resolving of all the references to the loader.
      *  but leaves the resolving of all the references to the loader.
      */
      */
-    class ColladaParser
-    {
-        friend class ColladaLoader;
+class ColladaParser {
+    friend class ColladaLoader;
 
 
-        /** Converts a path read from a collada file to the usual representation */
-        static void UriDecodePath(aiString& ss);
+    /** Converts a path read from a collada file to the usual representation */
+    static void UriDecodePath(aiString &ss);
 
 
-    protected:
-        /** Map for generic metadata as aiString */
-        typedef std::map<std::string, aiString> StringMetaData;
+protected:
+    /** Map for generic metadata as aiString */
+    typedef std::map<std::string, aiString> StringMetaData;
 
 
-        /** Constructor from XML file */
-        ColladaParser(IOSystem* pIOHandler, const std::string& pFile);
+    /** Constructor from XML file */
+    ColladaParser(IOSystem *pIOHandler, const std::string &pFile);
 
 
-        /** Destructor */
-        ~ColladaParser();
+    /** Destructor */
+    ~ColladaParser();
 
 
-        /** Attempts to read the ZAE manifest and returns the DAE to open */
-        static std::string ReadZaeManifest(ZipArchiveIOSystem &zip_archive);
+    /** Attempts to read the ZAE manifest and returns the DAE to open */
+    static std::string ReadZaeManifest(ZipArchiveIOSystem &zip_archive);
 
 
-        /** Reads the contents of the file */
-        void ReadContents();
+    /** Reads the contents of the file */
+    void ReadContents();
 
 
-        /** Reads the structure of the file */
-        void ReadStructure();
+    /** Reads the structure of the file */
+    void ReadStructure();
 
 
-        /** Reads asset information such as coordinate system information and legal blah */
-        void ReadAssetInfo();
+    /** Reads asset information such as coordinate system information and legal blah */
+    void ReadAssetInfo();
 
 
-        /** Reads contributor information such as author and legal blah */
-        void ReadContributorInfo();
+    /** Reads contributor information such as author and legal blah */
+    void ReadContributorInfo();
 
 
-        /** Reads generic metadata into provided map and renames keys for Assimp */
-        void ReadMetaDataItem(StringMetaData &metadata);
+    /** Reads generic metadata into provided map and renames keys for Assimp */
+    void ReadMetaDataItem(StringMetaData &metadata);
 
 
-        /** Reads the animation library */
-        void ReadAnimationLibrary();
+    /** Reads the animation library */
+    void ReadAnimationLibrary();
 
 
-		/** Reads the animation clip library */
-		void ReadAnimationClipLibrary();
+    /** Reads the animation clip library */
+    void ReadAnimationClipLibrary();
 
 
-        /** Unwrap controllers dependency hierarchy */
-        void PostProcessControllers();
-    
-		/** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */
-		void PostProcessRootAnimations();
+    /** Unwrap controllers dependency hierarchy */
+    void PostProcessControllers();
 
 
-        /** Reads an animation into the given parent structure */
-        void ReadAnimation( Collada::Animation* pParent);
+    /** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */
+    void PostProcessRootAnimations();
 
 
-        /** Reads an animation sampler into the given anim channel */
-        void ReadAnimationSampler( Collada::AnimationChannel& pChannel);
+    /** Reads an animation into the given parent structure */
+    void ReadAnimation(Collada::Animation *pParent);
 
 
-        /** Reads the skeleton controller library */
-        void ReadControllerLibrary();
+    /** Reads an animation sampler into the given anim channel */
+    void ReadAnimationSampler(Collada::AnimationChannel &pChannel);
 
 
-        /** Reads a controller into the given mesh structure */
-        void ReadController( Collada::Controller& pController);
+    /** Reads the skeleton controller library */
+    void ReadControllerLibrary();
 
 
-        /** Reads the joint definitions for the given controller */
-        void ReadControllerJoints( Collada::Controller& pController);
+    /** Reads a controller into the given mesh structure */
+    void ReadController(Collada::Controller &pController);
 
 
-        /** Reads the joint weights for the given controller */
-        void ReadControllerWeights( Collada::Controller& pController);
+    /** Reads the joint definitions for the given controller */
+    void ReadControllerJoints(Collada::Controller &pController);
 
 
-        /** Reads the image library contents */
-        void ReadImageLibrary();
+    /** Reads the joint weights for the given controller */
+    void ReadControllerWeights(Collada::Controller &pController);
 
 
-        /** Reads an image entry into the given image */
-        void ReadImage( Collada::Image& pImage);
+    /** Reads the image library contents */
+    void ReadImageLibrary();
 
 
-        /** Reads the material library */
-        void ReadMaterialLibrary();
+    /** Reads an image entry into the given image */
+    void ReadImage(Collada::Image &pImage);
 
 
-        /** Reads a material entry into the given material */
-        void ReadMaterial( Collada::Material& pMaterial);
+    /** Reads the material library */
+    void ReadMaterialLibrary();
 
 
-        /** Reads the camera library */
-        void ReadCameraLibrary();
+    /** Reads a material entry into the given material */
+    void ReadMaterial(Collada::Material &pMaterial);
 
 
-        /** Reads a camera entry into the given camera */
-        void ReadCamera( Collada::Camera& pCamera);
+    /** Reads the camera library */
+    void ReadCameraLibrary();
 
 
-        /** Reads the light library */
-        void ReadLightLibrary();
+    /** Reads a camera entry into the given camera */
+    void ReadCamera(Collada::Camera &pCamera);
 
 
-        /** Reads a light entry into the given light */
-        void ReadLight( Collada::Light& pLight);
+    /** Reads the light library */
+    void ReadLightLibrary();
 
 
-        /** Reads the effect library */
-        void ReadEffectLibrary();
+    /** Reads a light entry into the given light */
+    void ReadLight(Collada::Light &pLight);
 
 
-        /** Reads an effect entry into the given effect*/
-        void ReadEffect( Collada::Effect& pEffect);
+    /** Reads the effect library */
+    void ReadEffectLibrary();
 
 
-        /** Reads an COMMON effect profile */
-        void ReadEffectProfileCommon( Collada::Effect& pEffect);
+    /** Reads an effect entry into the given effect*/
+    void ReadEffect(Collada::Effect &pEffect);
 
 
-        /** Read sampler properties */
-        void ReadSamplerProperties( Collada::Sampler& pSampler);
+    /** Reads an COMMON effect profile */
+    void ReadEffectProfileCommon(Collada::Effect &pEffect);
 
 
-        /** Reads an effect entry containing a color or a texture defining that color */
-        void ReadEffectColor( aiColor4D& pColor, Collada::Sampler& pSampler);
+    /** Read sampler properties */
+    void ReadSamplerProperties(Collada::Sampler &pSampler);
 
 
-        /** Reads an effect entry containing a float */
-        void ReadEffectFloat( ai_real& pFloat);
+    /** Reads an effect entry containing a color or a texture defining that color */
+    void ReadEffectColor(aiColor4D &pColor, Collada::Sampler &pSampler);
 
 
-        /** Reads an effect parameter specification of any kind */
-        void ReadEffectParam( Collada::EffectParam& pParam);
+    /** Reads an effect entry containing a float */
+    void ReadEffectFloat(ai_real &pFloat);
 
 
-        /** Reads the geometry library contents */
-        void ReadGeometryLibrary();
+    /** Reads an effect parameter specification of any kind */
+    void ReadEffectParam(Collada::EffectParam &pParam);
 
 
-        /** Reads a geometry from the geometry library. */
-        void ReadGeometry( Collada::Mesh* pMesh);
+    /** Reads the geometry library contents */
+    void ReadGeometryLibrary();
 
 
-        /** Reads a mesh from the geometry library */
-        void ReadMesh( Collada::Mesh* pMesh);
+    /** Reads a geometry from the geometry library. */
+    void ReadGeometry(Collada::Mesh &pMesh);
 
 
-        /** Reads a source element - a combination of raw data and an accessor defining
+    /** Reads a mesh from the geometry library */
+    void ReadMesh(Collada::Mesh &pMesh);
+
+    /** Reads a source element - a combination of raw data and an accessor defining
          * things that should not be redefinable. Yes, that's another rant.
          * things that should not be redefinable. Yes, that's another rant.
          */
          */
-        void ReadSource();
+    void ReadSource();
 
 
-        /** Reads a data array holding a number of elements, and stores it in the global library.
+    /** Reads a data array holding a number of elements, and stores it in the global library.
          * Currently supported are array of floats and arrays of strings.
          * Currently supported are array of floats and arrays of strings.
          */
          */
-        void ReadDataArray();
+    void ReadDataArray();
 
 
-        /** Reads an accessor and stores it in the global library under the given ID -
+    /** Reads an accessor and stores it in the global library under the given ID -
          * accessors use the ID of the parent <source> element
          * accessors use the ID of the parent <source> element
          */
          */
-        void ReadAccessor( const std::string& pID);
+    void ReadAccessor(const std::string &pID);
 
 
-        /** Reads input declarations of per-vertex mesh data into the given mesh */
-        void ReadVertexData( Collada::Mesh* pMesh);
+    /** Reads input declarations of per-vertex mesh data into the given mesh */
+    void ReadVertexData(Collada::Mesh &pMesh);
 
 
-        /** Reads input declarations of per-index mesh data into the given mesh */
-        void ReadIndexData( Collada::Mesh* pMesh);
+    /** Reads input declarations of per-index mesh data into the given mesh */
+    void ReadIndexData(Collada::Mesh &pMesh);
 
 
-        /** Reads a single input channel element and stores it in the given array, if valid */
-        void ReadInputChannel( std::vector<Collada::InputChannel>& poChannels);
+    /** Reads a single input channel element and stores it in the given array, if valid */
+    void ReadInputChannel(std::vector<Collada::InputChannel> &poChannels);
 
 
-        /** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
-        size_t ReadPrimitives( Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
-                              size_t pNumPrimitives, const std::vector<size_t>& pVCount, Collada::PrimitiveType pPrimType);
+    /** Reads a <p> primitive index list and assembles the mesh data into the given mesh */
+    size_t ReadPrimitives(Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
+            size_t pNumPrimitives, const std::vector<size_t> &pVCount, Collada::PrimitiveType pPrimType);
 
 
-        /** Copies the data for a single primitive into the mesh, based on the InputChannels */
-        void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
-                        Collada::Mesh* pMesh, std::vector<Collada::InputChannel>& pPerIndexChannels,
-                        size_t currentPrimitive, const std::vector<size_t>& indices);
+    /** Copies the data for a single primitive into the mesh, based on the InputChannels */
+    void CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset,
+            Collada::Mesh &pMesh, std::vector<Collada::InputChannel> &pPerIndexChannels,
+            size_t currentPrimitive, const std::vector<size_t> &indices);
 
 
-        /** Reads one triangle of a tristrip into the mesh */
-        void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh* pMesh,
-                               std::vector<Collada::InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices);
+    /** Reads one triangle of a tristrip into the mesh */
+    void ReadPrimTriStrips(size_t numOffsets, size_t perVertexOffset, Collada::Mesh &pMesh,
+            std::vector<Collada::InputChannel> &pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t> &indices);
 
 
-        /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
-        void ExtractDataObjectFromChannel( const Collada::InputChannel& pInput, size_t pLocalIndex, Collada::Mesh* pMesh);
+    /** Extracts a single object from an input channel and stores it in the appropriate mesh data array */
+    void ExtractDataObjectFromChannel(const Collada::InputChannel &pInput, size_t pLocalIndex, Collada::Mesh &pMesh);
 
 
-        /** Reads the library of node hierarchies and scene parts */
-        void ReadSceneLibrary();
+    /** Reads the library of node hierarchies and scene parts */
+    void ReadSceneLibrary();
 
 
-        /** Reads a scene node's contents including children and stores it in the given node */
-        void ReadSceneNode( Collada::Node* pNode);
+    /** Reads a scene node's contents including children and stores it in the given node */
+    void ReadSceneNode(Collada::Node *pNode);
 
 
-        /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
-        void ReadNodeTransformation( Collada::Node* pNode, Collada::TransformType pType);
+    /** Reads a node transformation entry of the given type and adds it to the given node's transformation list. */
+    void ReadNodeTransformation(Collada::Node *pNode, Collada::TransformType pType);
 
 
-        /** Reads a mesh reference in a node and adds it to the node's mesh list */
-        void ReadNodeGeometry( Collada::Node* pNode);
+    /** Reads a mesh reference in a node and adds it to the node's mesh list */
+    void ReadNodeGeometry(Collada::Node *pNode);
 
 
-        /** Reads the collada scene */
-        void ReadScene();
+    /** Reads the collada scene */
+    void ReadScene();
 
 
-        // Processes bind_vertex_input and bind elements
-        void ReadMaterialVertexInputBinding( Collada::SemanticMappingTable& tbl);
+    // Processes bind_vertex_input and bind elements
+    void ReadMaterialVertexInputBinding(Collada::SemanticMappingTable &tbl);
 
 
-        /** Reads embedded textures from a ZAE archive*/
-        void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive);
+    /** Reads embedded textures from a ZAE archive*/
+    void ReadEmbeddedTextures(ZipArchiveIOSystem &zip_archive);
 
 
-    protected:
-        /** Aborts the file reading with an exception */
-        AI_WONT_RETURN void ThrowException( const std::string& pError) const AI_WONT_RETURN_SUFFIX;
-        void ReportWarning(const char* msg,...);
+protected:
+    /** Aborts the file reading with an exception */
+    AI_WONT_RETURN void ThrowException(const std::string &pError) const AI_WONT_RETURN_SUFFIX;
+    void ReportWarning(const char *msg, ...);
 
 
-        /** Skips all data until the end node of the current element */
-        void SkipElement();
+    /** Skips all data until the end node of the current element */
+    void SkipElement();
 
 
-        /** Skips all data until the end node of the given element */
-        void SkipElement( const char* pElement);
+    /** Skips all data until the end node of the given element */
+    void SkipElement(const char *pElement);
 
 
-        /** Compares the current xml element name to the given string and returns true if equal */
-        bool IsElement( const char* pName) const;
+    /** Compares the current xml element name to the given string and returns true if equal */
+    bool IsElement(const char *pName) const;
 
 
-        /** Tests for the opening tag of the given element, throws an exception if not found */
-        void TestOpening( const char* pName);
+    /** Tests for the opening tag of the given element, throws an exception if not found */
+    void TestOpening(const char *pName);
 
 
-        /** Tests for the closing tag of the given element, throws an exception if not found */
-        void TestClosing( const char* pName);
+    /** Tests for the closing tag of the given element, throws an exception if not found */
+    void TestClosing(const char *pName);
 
 
-        /** Checks the present element for the presence of the attribute, returns its index
+    /** Checks the present element for the presence of the attribute, returns its index
          or throws an exception if not found */
          or throws an exception if not found */
-        int GetAttribute( const char* pAttr) const;
+    int GetAttribute(const char *pAttr) const;
 
 
-        /** Returns the index of the named attribute or -1 if not found. Does not throw,
+    /** Returns the index of the named attribute or -1 if not found. Does not throw,
          therefore useful for optional attributes */
          therefore useful for optional attributes */
-        int TestAttribute( const char* pAttr) const;
+    int TestAttribute(const char *pAttr) const;
 
 
-        /** Reads the text contents of an element, throws an exception if not given.
+    /** Reads the text contents of an element, throws an exception if not given.
          Skips leading whitespace. */
          Skips leading whitespace. */
-        const char* GetTextContent();
+    const char *GetTextContent();
 
 
-        /** Reads the text contents of an element, returns NULL if not given.
+    /** Reads the text contents of an element, returns nullptr if not given.
          Skips leading whitespace. */
          Skips leading whitespace. */
-        const char* TestTextContent();
+    const char *TestTextContent();
 
 
-        /** Reads a single bool from current text content */
-        bool ReadBoolFromTextContent();
+    /** Reads a single bool from current text content */
+    bool ReadBoolFromTextContent();
 
 
-        /** Reads a single float from current text content */
-        ai_real ReadFloatFromTextContent();
+    /** Reads a single float from current text content */
+    ai_real ReadFloatFromTextContent();
 
 
-        /** Calculates the resulting transformation from all the given transform steps */
-        aiMatrix4x4 CalculateResultTransform( const std::vector<Collada::Transform>& pTransforms) const;
+    /** Calculates the resulting transformation from all the given transform steps */
+    aiMatrix4x4 CalculateResultTransform(const std::vector<Collada::Transform> &pTransforms) const;
 
 
-        /** Determines the input data type for the given semantic string */
-        Collada::InputType GetTypeForSemantic( const std::string& pSemantic);
+    /** Determines the input data type for the given semantic string */
+    Collada::InputType GetTypeForSemantic(const std::string &pSemantic);
 
 
-        /** Finds the item in the given library by its reference, throws if not found */
-        template <typename Type> const Type& ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const;
+    /** Finds the item in the given library by its reference, throws if not found */
+    template <typename Type>
+    const Type &ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const;
 
 
-    protected:
-        /** Filename, for a verbose error message */
-        std::string mFileName;
+protected:
+    /** Filename, for a verbose error message */
+    std::string mFileName;
 
 
-        /** XML reader, member for everyday use */
-        irr::io::IrrXMLReader* mReader;
+    /** XML reader, member for everyday use */
+    irr::io::IrrXMLReader *mReader;
 
 
-        /** All data arrays found in the file by ID. Might be referred to by actually
+    /** All data arrays found in the file by ID. Might be referred to by actually
          everyone. Collada, you are a steaming pile of indirection. */
          everyone. Collada, you are a steaming pile of indirection. */
-        typedef std::map<std::string, Collada::Data> DataLibrary;
-        DataLibrary mDataLibrary;
+    typedef std::map<std::string, Collada::Data> DataLibrary;
+    DataLibrary mDataLibrary;
 
 
-        /** Same for accessors which define how the data in a data array is accessed. */
-        typedef std::map<std::string, Collada::Accessor> AccessorLibrary;
-        AccessorLibrary mAccessorLibrary;
+    /** Same for accessors which define how the data in a data array is accessed. */
+    typedef std::map<std::string, Collada::Accessor> AccessorLibrary;
+    AccessorLibrary mAccessorLibrary;
 
 
-        /** Mesh library: mesh by ID */
-        typedef std::map<std::string, Collada::Mesh*> MeshLibrary;
-        MeshLibrary mMeshLibrary;
+    /** Mesh library: mesh by ID */
+    typedef std::map<std::string, Collada::Mesh *> MeshLibrary;
+    MeshLibrary mMeshLibrary;
 
 
-        /** node library: root node of the hierarchy part by ID */
-        typedef std::map<std::string, Collada::Node*> NodeLibrary;
-        NodeLibrary mNodeLibrary;
+    /** node library: root node of the hierarchy part by ID */
+    typedef std::map<std::string, Collada::Node *> NodeLibrary;
+    NodeLibrary mNodeLibrary;
 
 
-        /** Image library: stores texture properties by ID */
-        typedef std::map<std::string, Collada::Image> ImageLibrary;
-        ImageLibrary mImageLibrary;
+    /** Image library: stores texture properties by ID */
+    typedef std::map<std::string, Collada::Image> ImageLibrary;
+    ImageLibrary mImageLibrary;
 
 
-        /** Effect library: surface attributes by ID */
-        typedef std::map<std::string, Collada::Effect> EffectLibrary;
-        EffectLibrary mEffectLibrary;
+    /** Effect library: surface attributes by ID */
+    typedef std::map<std::string, Collada::Effect> EffectLibrary;
+    EffectLibrary mEffectLibrary;
 
 
-        /** Material library: surface material by ID */
-        typedef std::map<std::string, Collada::Material> MaterialLibrary;
-        MaterialLibrary mMaterialLibrary;
+    /** Material library: surface material by ID */
+    typedef std::map<std::string, Collada::Material> MaterialLibrary;
+    MaterialLibrary mMaterialLibrary;
 
 
-        /** Light library: surface light by ID */
-        typedef std::map<std::string, Collada::Light> LightLibrary;
-        LightLibrary mLightLibrary;
+    /** Light library: surface light by ID */
+    typedef std::map<std::string, Collada::Light> LightLibrary;
+    LightLibrary mLightLibrary;
 
 
-        /** Camera library: surface material by ID */
-        typedef std::map<std::string, Collada::Camera> CameraLibrary;
-        CameraLibrary mCameraLibrary;
+    /** Camera library: surface material by ID */
+    typedef std::map<std::string, Collada::Camera> CameraLibrary;
+    CameraLibrary mCameraLibrary;
 
 
-        /** Controller library: joint controllers by ID */
-        typedef std::map<std::string, Collada::Controller> ControllerLibrary;
-        ControllerLibrary mControllerLibrary;
+    /** Controller library: joint controllers by ID */
+    typedef std::map<std::string, Collada::Controller> ControllerLibrary;
+    ControllerLibrary mControllerLibrary;
 
 
-		/** Animation library: animation references by ID */
-		typedef std::map<std::string, Collada::Animation*> AnimationLibrary;
-		AnimationLibrary mAnimationLibrary;
+    /** Animation library: animation references by ID */
+    typedef std::map<std::string, Collada::Animation *> AnimationLibrary;
+    AnimationLibrary mAnimationLibrary;
 
 
-		/** Animation clip library: clip animation references by ID */
-		typedef std::vector<std::pair<std::string, std::vector<std::string> > > AnimationClipLibrary;
-		AnimationClipLibrary mAnimationClipLibrary;
+    /** Animation clip library: clip animation references by ID */
+    typedef std::vector<std::pair<std::string, std::vector<std::string>>> AnimationClipLibrary;
+    AnimationClipLibrary mAnimationClipLibrary;
 
 
-        /** Pointer to the root node. Don't delete, it just points to one of
+    /** Pointer to the root node. Don't delete, it just points to one of
          the nodes in the node library. */
          the nodes in the node library. */
-        Collada::Node* mRootNode;
-
-        /** Root animation container */
-        Collada::Animation mAnims;
-
-        /** Size unit: how large compared to a meter */
-        ai_real mUnitSize;
-
-        /** Which is the up vector */
-        enum { UP_X, UP_Y, UP_Z } mUpDirection;
-
-        /** Asset metadata (global for scene) */
-        StringMetaData mAssetMetaData;
-
-        /** Collada file format version */
-        Collada::FormatVersion mFormat;
-    };
-
-    // ------------------------------------------------------------------------------------------------
-    // Check for element match
-    inline bool ColladaParser::IsElement( const char* pName) const
-    {
-        ai_assert( mReader->getNodeType() == irr::io::EXN_ELEMENT);
-        return ::strcmp( mReader->getNodeName(), pName) == 0;
-    }
-
-    // ------------------------------------------------------------------------------------------------
-    // Finds the item in the given library by its reference, throws if not found
-    template <typename Type>
-    const Type& ColladaParser::ResolveLibraryReference( const std::map<std::string, Type>& pLibrary, const std::string& pURL) const
-    {
-        typename std::map<std::string, Type>::const_iterator it = pLibrary.find( pURL);
-        if( it == pLibrary.end())
-            ThrowException( Formatter::format() << "Unable to resolve library reference \"" << pURL << "\"." );
-        return it->second;
-    }
+    Collada::Node *mRootNode;
+
+    /** Root animation container */
+    Collada::Animation mAnims;
+
+    /** Size unit: how large compared to a meter */
+    ai_real mUnitSize;
+
+    /** Which is the up vector */
+    enum { UP_X,
+        UP_Y,
+        UP_Z } mUpDirection;
+
+    /** Asset metadata (global for scene) */
+    StringMetaData mAssetMetaData;
+
+    /** Collada file format version */
+    Collada::FormatVersion mFormat;
+};
+
+// ------------------------------------------------------------------------------------------------
+// Check for element match
+inline bool ColladaParser::IsElement(const char *pName) const {
+    ai_assert(mReader->getNodeType() == irr::io::EXN_ELEMENT);
+    return ::strcmp(mReader->getNodeName(), pName) == 0;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Finds the item in the given library by its reference, throws if not found
+template <typename Type>
+const Type &ColladaParser::ResolveLibraryReference(const std::map<std::string, Type> &pLibrary, const std::string &pURL) const {
+    typename std::map<std::string, Type>::const_iterator it = pLibrary.find(pURL);
+    if (it == pLibrary.end())
+        ThrowException(Formatter::format() << "Unable to resolve library reference \"" << pURL << "\".");
+    return it->second;
+}
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp
 
 

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

@@ -135,7 +135,7 @@ public:
                 for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
                 for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
 
 
                 splitter++;
                 splitter++;
-                ASSIMP_LOG_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
+                ASSIMP_LOG_VERBOSE_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
             }
             }
         } catch(std::logic_error&) {
         } catch(std::logic_error&) {
             ai_assert(!splitter);
             ai_assert(!splitter);

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

@@ -241,7 +241,7 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output) {
             }
             }
         }
         }
 
 
-        ASSIMP_LOG_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount);
+        ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount);
     }
     }
 
 
     if (! output.blocks.size()  ) {
     if (! output.blocks.size()  ) {
@@ -473,7 +473,7 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) {
         ++reader;
         ++reader;
     }
     }
 
 
-    ASSIMP_LOG_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" );
+    ASSIMP_LOG_VERBOSE_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" );
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -549,7 +549,7 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
         ++reader;
         ++reader;
     }
     }
 
 
-    ASSIMP_LOG_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), 
+    ASSIMP_LOG_VERBOSE_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), 
         " inserted blocks in ENTITIES" );
         " inserted blocks in ENTITIES" );
 }
 }
 
 

+ 77 - 92
code/AssetLib/FBX/FBXAnimation.cpp

@@ -47,10 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 #ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
 
 
-#include "FBXParser.h"
 #include "FBXDocument.h"
 #include "FBXDocument.h"
-#include "FBXImporter.h"
 #include "FBXDocumentUtil.h"
 #include "FBXDocumentUtil.h"
+#include "FBXImporter.h"
+#include "FBXParser.h"
 
 
 namespace Assimp {
 namespace Assimp {
 namespace FBX {
 namespace FBX {
@@ -58,65 +58,60 @@ namespace FBX {
 using namespace Util;
 using namespace Util;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AnimationCurve::AnimationCurve(uint64_t id, const Element& element, const std::string& name, const Document& /*doc*/)
-: Object(id, element, name)
-{
-    const Scope& sc = GetRequiredScope(element);
-    const Element& KeyTime = GetRequiredElement(sc,"KeyTime");
-    const Element& KeyValueFloat = GetRequiredElement(sc,"KeyValueFloat");
+AnimationCurve::AnimationCurve(uint64_t id, const Element &element, const std::string &name, const Document & /*doc*/) :
+        Object(id, element, name) {
+    const Scope &sc = GetRequiredScope(element);
+    const Element &KeyTime = GetRequiredElement(sc, "KeyTime");
+    const Element &KeyValueFloat = GetRequiredElement(sc, "KeyValueFloat");
 
 
     ParseVectorDataArray(keys, KeyTime);
     ParseVectorDataArray(keys, KeyTime);
     ParseVectorDataArray(values, KeyValueFloat);
     ParseVectorDataArray(values, KeyValueFloat);
 
 
-    if(keys.size() != values.size()) {
-        DOMError("the number of key times does not match the number of keyframe values",&KeyTime);
+    if (keys.size() != values.size()) {
+        DOMError("the number of key times does not match the number of keyframe values", &KeyTime);
     }
     }
 
 
     // check if the key times are well-ordered
     // check if the key times are well-ordered
-    if(!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) {
-        DOMError("the keyframes are not in ascending order",&KeyTime);
+    if (!std::equal(keys.begin(), keys.end() - 1, keys.begin() + 1, std::less<KeyTimeList::value_type>())) {
+        DOMError("the keyframes are not in ascending order", &KeyTime);
     }
     }
 
 
-    const Element* KeyAttrDataFloat = sc["KeyAttrDataFloat"];
-    if(KeyAttrDataFloat) {
+    const Element *KeyAttrDataFloat = sc["KeyAttrDataFloat"];
+    if (KeyAttrDataFloat) {
         ParseVectorDataArray(attributes, *KeyAttrDataFloat);
         ParseVectorDataArray(attributes, *KeyAttrDataFloat);
     }
     }
 
 
-    const Element* KeyAttrFlags = sc["KeyAttrFlags"];
-    if(KeyAttrFlags) {
+    const Element *KeyAttrFlags = sc["KeyAttrFlags"];
+    if (KeyAttrFlags) {
         ParseVectorDataArray(flags, *KeyAttrFlags);
         ParseVectorDataArray(flags, *KeyAttrFlags);
     }
     }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AnimationCurve::~AnimationCurve()
-{
+AnimationCurve::~AnimationCurve() {
     // empty
     // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, 
-        const Document& doc, const char* const * target_prop_whitelist /*= NULL*/, 
-        size_t whitelist_size /*= 0*/)
-: Object(id, element, name)
-, target()
-, doc(doc)
-{
-    const Scope& sc = GetRequiredScope(element);
+AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element &element, const std::string &name,
+        const Document &doc, const char *const *target_prop_whitelist /*= nullptr*/,
+        size_t whitelist_size /*= 0*/) :
+        Object(id, element, name), target(), doc(doc) {
+    const Scope &sc = GetRequiredScope(element);
 
 
     // find target node
     // find target node
-    const char* whitelist[] = {"Model","NodeAttribute","Deformer"};
-    const std::vector<const Connection*>& conns = doc.GetConnectionsBySourceSequenced(ID(),whitelist,3);
+    const char *whitelist[] = { "Model", "NodeAttribute", "Deformer" };
+    const std::vector<const Connection *> &conns = doc.GetConnectionsBySourceSequenced(ID(), whitelist, 3);
 
 
-    for(const Connection* con : conns) {
+    for (const Connection *con : conns) {
 
 
         // link should go for a property
         // link should go for a property
         if (!con->PropertyName().length()) {
         if (!con->PropertyName().length()) {
             continue;
             continue;
         }
         }
 
 
-        if(target_prop_whitelist) {
-            const char* const s = con->PropertyName().c_str();
+        if (target_prop_whitelist) {
+            const char *const s = con->PropertyName().c_str();
             bool ok = false;
             bool ok = false;
             for (size_t i = 0; i < whitelist_size; ++i) {
             for (size_t i = 0; i < whitelist_size; ++i) {
                 if (!strcmp(s, target_prop_whitelist[i])) {
                 if (!strcmp(s, target_prop_whitelist[i])) {
@@ -130,16 +125,14 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
             }
             }
         }
         }
 
 
-        const Object* const ob = con->DestinationObject();
-        if(!ob) {
-            DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring",&element);
+        const Object *const ob = con->DestinationObject();
+        if (!ob) {
+            DOMWarning("failed to read destination object for AnimationCurveNode->Model link, ignoring", &element);
             continue;
             continue;
         }
         }
 
 
-        // XXX support constraints as DOM class
-        //ai_assert(dynamic_cast<const Model*>(ob) || dynamic_cast<const NodeAttribute*>(ob));
         target = ob;
         target = ob;
-        if(!target) {
+        if (!target) {
             continue;
             continue;
         }
         }
 
 
@@ -147,42 +140,40 @@ AnimationCurveNode::AnimationCurveNode(uint64_t id, const Element& element, cons
         break;
         break;
     }
     }
 
 
-    if(!target) {
-        DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode",&element);
+    if (!target) {
+        DOMWarning("failed to resolve target Model/NodeAttribute/Constraint for AnimationCurveNode", &element);
     }
     }
 
 
-    props = GetPropertyTable(doc,"AnimationCurveNode.FbxAnimCurveNode",element,sc,false);
+    props = GetPropertyTable(doc, "AnimationCurveNode.FbxAnimCurveNode", element, sc, false);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AnimationCurveNode::~AnimationCurveNode()
-{
+AnimationCurveNode::~AnimationCurveNode() {
     // empty
     // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-const AnimationCurveMap& AnimationCurveNode::Curves() const
-{
-    if ( curves.empty() ) {
+const AnimationCurveMap &AnimationCurveNode::Curves() const {
+    if (curves.empty()) {
         // resolve attached animation curves
         // resolve attached animation curves
-        const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurve");
+        const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationCurve");
 
 
-        for(const Connection* con : conns) {
+        for (const Connection *con : conns) {
 
 
             // link should go for a property
             // link should go for a property
             if (!con->PropertyName().length()) {
             if (!con->PropertyName().length()) {
                 continue;
                 continue;
             }
             }
 
 
-            const Object* const ob = con->SourceObject();
-            if(!ob) {
-                DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring",&element);
+            const Object *const ob = con->SourceObject();
+            if (nullptr == ob) {
+                DOMWarning("failed to read source object for AnimationCurve->AnimationCurveNode link, ignoring", &element);
                 continue;
                 continue;
             }
             }
 
 
-            const AnimationCurve* const anim = dynamic_cast<const AnimationCurve*>(ob);
-            if(!anim) {
-                DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve",&element);
+            const AnimationCurve *const anim = dynamic_cast<const AnimationCurve *>(ob);
+            if (nullptr == anim) {
+                DOMWarning("source object for ->AnimationCurveNode link is not an AnimationCurve", &element);
                 continue;
                 continue;
             }
             }
 
 
@@ -194,53 +185,49 @@ const AnimationCurveMap& AnimationCurveNode::Curves() const
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AnimationLayer::AnimationLayer(uint64_t id, const Element& element, const std::string& name, const Document& doc)
-: Object(id, element, name)
-, doc(doc)
-{
-    const Scope& sc = GetRequiredScope(element);
+AnimationLayer::AnimationLayer(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
+        Object(id, element, name), doc(doc) {
+    const Scope &sc = GetRequiredScope(element);
 
 
     // note: the props table here bears little importance and is usually absent
     // note: the props table here bears little importance and is usually absent
-    props = GetPropertyTable(doc,"AnimationLayer.FbxAnimLayer",element,sc, true);
+    props = GetPropertyTable(doc, "AnimationLayer.FbxAnimLayer", element, sc, true);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AnimationLayer::~AnimationLayer()
-{
+AnimationLayer::~AnimationLayer() {
     // empty
     // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whitelist /*= NULL*/,
-    size_t whitelist_size /*= 0*/) const
-{
+AnimationCurveNodeList AnimationLayer::Nodes(const char *const *target_prop_whitelist /*= nullptr*/,
+        size_t whitelist_size /*= 0*/) const {
     AnimationCurveNodeList nodes;
     AnimationCurveNodeList nodes;
 
 
     // resolve attached animation nodes
     // resolve attached animation nodes
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationCurveNode");
+    const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationCurveNode");
     nodes.reserve(conns.size());
     nodes.reserve(conns.size());
 
 
-    for(const Connection* con : conns) {
+    for (const Connection *con : conns) {
 
 
         // link should not go to a property
         // link should not go to a property
         if (con->PropertyName().length()) {
         if (con->PropertyName().length()) {
             continue;
             continue;
         }
         }
 
 
-        const Object* const ob = con->SourceObject();
-        if(!ob) {
-            DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring",&element);
+        const Object *const ob = con->SourceObject();
+        if (!ob) {
+            DOMWarning("failed to read source object for AnimationCurveNode->AnimationLayer link, ignoring", &element);
             continue;
             continue;
         }
         }
 
 
-        const AnimationCurveNode* const anim = dynamic_cast<const AnimationCurveNode*>(ob);
-        if(!anim) {
-            DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode",&element);
+        const AnimationCurveNode *const anim = dynamic_cast<const AnimationCurveNode *>(ob);
+        if (!anim) {
+            DOMWarning("source object for ->AnimationLayer link is not an AnimationCurveNode", &element);
             continue;
             continue;
         }
         }
 
 
-        if(target_prop_whitelist) {
-            const char* s = anim->TargetProperty().c_str();
+        if (target_prop_whitelist) {
+            const char *s = anim->TargetProperty().c_str();
             bool ok = false;
             bool ok = false;
             for (size_t i = 0; i < whitelist_size; ++i) {
             for (size_t i = 0; i < whitelist_size; ++i) {
                 if (!strcmp(s, target_prop_whitelist[i])) {
                 if (!strcmp(s, target_prop_whitelist[i])) {
@@ -248,7 +235,7 @@ AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whi
                     break;
                     break;
                 }
                 }
             }
             }
-            if(!ok) {
+            if (!ok) {
                 continue;
                 continue;
             }
             }
         }
         }
@@ -259,34 +246,33 @@ AnimationCurveNodeList AnimationLayer::Nodes(const char* const * target_prop_whi
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::string& name, const Document& doc)
-: Object(id, element, name)
-{
-    const Scope& sc = GetRequiredScope(element);
+AnimationStack::AnimationStack(uint64_t id, const Element &element, const std::string &name, const Document &doc) :
+        Object(id, element, name) {
+    const Scope &sc = GetRequiredScope(element);
 
 
     // note: we don't currently use any of these properties so we shouldn't bother if it is missing
     // note: we don't currently use any of these properties so we shouldn't bother if it is missing
-    props = GetPropertyTable(doc,"AnimationStack.FbxAnimStack",element,sc, true);
+    props = GetPropertyTable(doc, "AnimationStack.FbxAnimStack", element, sc, true);
 
 
     // resolve attached animation layers
     // resolve attached animation layers
-    const std::vector<const Connection*>& conns = doc.GetConnectionsByDestinationSequenced(ID(),"AnimationLayer");
+    const std::vector<const Connection *> &conns = doc.GetConnectionsByDestinationSequenced(ID(), "AnimationLayer");
     layers.reserve(conns.size());
     layers.reserve(conns.size());
 
 
-    for(const Connection* con : conns) {
+    for (const Connection *con : conns) {
 
 
         // link should not go to a property
         // link should not go to a property
         if (con->PropertyName().length()) {
         if (con->PropertyName().length()) {
             continue;
             continue;
         }
         }
 
 
-        const Object* const ob = con->SourceObject();
-        if(!ob) {
-            DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring",&element);
+        const Object *const ob = con->SourceObject();
+        if (!ob) {
+            DOMWarning("failed to read source object for AnimationLayer->AnimationStack link, ignoring", &element);
             continue;
             continue;
         }
         }
 
 
-        const AnimationLayer* const anim = dynamic_cast<const AnimationLayer*>(ob);
-        if(!anim) {
-            DOMWarning("source object for ->AnimationStack link is not an AnimationLayer",&element);
+        const AnimationLayer *const anim = dynamic_cast<const AnimationLayer *>(ob);
+        if (!anim) {
+            DOMWarning("source object for ->AnimationStack link is not an AnimationLayer", &element);
             continue;
             continue;
         }
         }
         layers.push_back(anim);
         layers.push_back(anim);
@@ -294,12 +280,11 @@ AnimationStack::AnimationStack(uint64_t id, const Element& element, const std::s
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-AnimationStack::~AnimationStack()
-{
+AnimationStack::~AnimationStack() {
     // empty
     // empty
 }
 }
 
 
-} //!FBX
-} //!Assimp
+} // namespace FBX
+} // namespace Assimp
 
 
 #endif // ASSIMP_BUILD_NO_FBX_IMPORTER
 #endif // ASSIMP_BUILD_NO_FBX_IMPORTER

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

@@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <stdint.h>
 #include <stdint.h>
 #include <assimp/Exceptional.h>
 #include <assimp/Exceptional.h>
 #include <assimp/ByteSwapper.h>
 #include <assimp/ByteSwapper.h>
+#include <assimp/DefaultLogger.hpp>
 
 
 namespace Assimp {
 namespace Assimp {
 namespace FBX {
 namespace FBX {
@@ -426,7 +427,8 @@ bool ReadScope(TokenList& output_tokens, const char* input, const char*& cursor,
 // TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
 // TODO: Test FBX Binary files newer than the 7500 version to check if the 64 bits address behaviour is consistent
 void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
 void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
 {
 {
-    ai_assert(input);
+	ai_assert(input);
+	ASSIMP_LOG_DEBUG("Tokenizing binary FBX file");
 
 
     if(length < 0x1b) {
     if(length < 0x1b) {
         TokenizeError("file is too short",0);
         TokenizeError("file is too short",0);
@@ -451,6 +453,7 @@ void TokenizeBinary(TokenList& output_tokens, const char* input, size_t length)
 	/*Result ignored*/ ReadByte(input, cursor, input + length);
 	/*Result ignored*/ ReadByte(input, cursor, input + length);
 	/*Result ignored*/ ReadByte(input, cursor, input + length);
 	/*Result ignored*/ ReadByte(input, cursor, input + length);
 	const uint32_t version = ReadWord(input, cursor, input + length);
 	const uint32_t version = ReadWord(input, cursor, input + length);
+	ASSIMP_LOG_DEBUG_F("FBX version: ", version);
 	const bool is64bits = version >= 7500;
 	const bool is64bits = version >= 7500;
     const char *end = input + length;
     const char *end = input + length;
     while (cursor < end ) {
     while (cursor < end ) {

+ 23 - 24
code/AssetLib/FBX/FBXConverter.cpp

@@ -105,7 +105,7 @@ FBXConverter::FBXConverter(aiScene *out, const Document &doc, bool removeEmptyBo
     // The idea here is to traverse all objects to find these Textures and convert them,
     // The idea here is to traverse all objects to find these Textures and convert them,
     // so later during material conversion it will find converted texture in the textures_converted array.
     // so later during material conversion it will find converted texture in the textures_converted array.
     if (doc.Settings().readTextures) {
     if (doc.Settings().readTextures) {
-        ConvertOrphantEmbeddedTextures();
+        ConvertOrphanedEmbeddedTextures();
     }
     }
     ConvertRootNode();
     ConvertRootNode();
 
 
@@ -804,11 +804,6 @@ bool FBXConverter::GenerateTransformationNodeChain(const Model &model, const std
         aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]);
         aiMatrix4x4::Translation(-GeometricTranslation, chain[TransformationComp_GeometricTranslationInverse]);
     }
     }
 
 
-    // is_complex needs to be consistent with NeedsComplexTransformationChain()
-    // or the interplay between this code and the animation converter would
-    // not be guaranteed.
-    //ai_assert(NeedsComplexTransformationChain(model) == ((chainBits & chainMaskComplex) != 0));
-
     // now, if we have more than just Translation, Scaling and Rotation,
     // now, if we have more than just Translation, Scaling and Rotation,
     // we need to generate a full node chain to accommodate for assimp's
     // we need to generate a full node chain to accommodate for assimp's
     // lack to express pivots and offsets.
     // lack to express pivots and offsets.
@@ -1163,7 +1158,8 @@ unsigned int FBXConverter::ConvertMeshSingleMaterial(const MeshGeometry &mesh, c
                 const std::vector<aiVector3D> &curVertices = shapeGeometry->GetVertices();
                 const std::vector<aiVector3D> &curVertices = shapeGeometry->GetVertices();
                 const std::vector<aiVector3D> &curNormals = shapeGeometry->GetNormals();
                 const std::vector<aiVector3D> &curNormals = shapeGeometry->GetNormals();
                 const std::vector<unsigned int> &curIndices = shapeGeometry->GetIndices();
                 const std::vector<unsigned int> &curIndices = shapeGeometry->GetIndices();
-                animMesh->mName.Set(FixAnimMeshName(shapeGeometry->Name()));
+                //losing channel name if using shapeGeometry->Name()
+                animMesh->mName.Set(FixAnimMeshName(blendShapeChannel->Name()));
                 for (size_t j = 0; j < curIndices.size(); j++) {
                 for (size_t j = 0; j < curIndices.size(); j++) {
                     const unsigned int curIndex = curIndices.at(j);
                     const unsigned int curIndex = curIndices.at(j);
                     aiVector3D vertex = curVertices.at(j);
                     aiVector3D vertex = curVertices.at(j);
@@ -1289,7 +1285,8 @@ unsigned int FBXConverter::ConvertMeshMultiMaterial(const MeshGeometry &mesh, co
         }
         }
 
 
         if (binormals) {
         if (binormals) {
-            ai_assert(tangents.size() == vertices.size() && binormals->size() == vertices.size());
+            ai_assert(tangents.size() == vertices.size());
+            ai_assert(binormals->size() == vertices.size());
 
 
             out_mesh->mTangents = new aiVector3D[vertices.size()];
             out_mesh->mTangents = new aiVector3D[vertices.size()];
             out_mesh->mBitangents = new aiVector3D[vertices.size()];
             out_mesh->mBitangents = new aiVector3D[vertices.size()];
@@ -1542,10 +1539,10 @@ void FBXConverter::ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const
     aiBone *bone = nullptr;
     aiBone *bone = nullptr;
 
 
     if (bone_map.count(deformer_name)) {
     if (bone_map.count(deformer_name)) {
-        ASSIMP_LOG_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name);
+        ASSIMP_LOG_VERBOSE_DEBUG_F("retrieved bone from lookup ", bone_name.C_Str(), ". Deformer:", deformer_name);
         bone = bone_map[deformer_name];
         bone = bone_map[deformer_name];
     } else {
     } else {
-        ASSIMP_LOG_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name);
+        ASSIMP_LOG_VERBOSE_DEBUG_F("created new bone ", bone_name.C_Str(), ". Deformer: ", deformer_name);
         bone = new aiBone();
         bone = new aiBone();
         bone->mName = bone_name;
         bone->mName = bone_name;
 
 
@@ -1999,19 +1996,19 @@ void FBXConverter::SetTextureProperties(aiMaterial *out_mat, const TextureMap &_
     TrySetTextureProperties(out_mat, _textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh);
     TrySetTextureProperties(out_mat, _textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh);
 
 
     // Maya PBR
     // Maya PBR
-    TrySetTextureProperties(out_mat, _textures, "Maya|baseColor|file", aiTextureType_BASE_COLOR, mesh);
-    TrySetTextureProperties(out_mat, _textures, "Maya|normalCamera|file", aiTextureType_NORMAL_CAMERA, mesh);
-    TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor|file", aiTextureType_EMISSION_COLOR, mesh);
-    TrySetTextureProperties(out_mat, _textures, "Maya|metalness|file", aiTextureType_METALNESS, mesh);
-    TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|baseColor", aiTextureType_BASE_COLOR, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|normalCamera", aiTextureType_NORMAL_CAMERA, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|emissionColor", aiTextureType_EMISSION_COLOR, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|metalness", aiTextureType_METALNESS, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|diffuseRoughness", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
 
 
     // Maya stingray
     // Maya stingray
-    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map|file", aiTextureType_BASE_COLOR, mesh);
-    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_normal_map|file", aiTextureType_NORMAL_CAMERA, mesh);
-    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_emissive_map|file", aiTextureType_EMISSION_COLOR, mesh);
-    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_metallic_map|file", aiTextureType_METALNESS, mesh);
-    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_roughness_map|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
-    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_ao_map|file", aiTextureType_AMBIENT_OCCLUSION, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_color_map", aiTextureType_BASE_COLOR, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_normal_map", aiTextureType_NORMAL_CAMERA, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_emissive_map", aiTextureType_EMISSION_COLOR, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_metallic_map", aiTextureType_METALNESS, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_roughness_map", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
+    TrySetTextureProperties(out_mat, _textures, "Maya|TEX_ao_map", aiTextureType_AMBIENT_OCCLUSION, mesh);
 
 
     // 3DSMax PBR
     // 3DSMax PBR
     TrySetTextureProperties(out_mat, _textures, "3dsMax|Parameters|base_color_map", aiTextureType_BASE_COLOR, mesh);
     TrySetTextureProperties(out_mat, _textures, "3dsMax|Parameters|base_color_map", aiTextureType_BASE_COLOR, mesh);
@@ -2719,7 +2716,7 @@ void FBXConverter::GenerateNodeAnimations(std::vector<aiNodeAnim *> &node_anims,
             if (doc.Settings().optimizeEmptyAnimationCurves &&
             if (doc.Settings().optimizeEmptyAnimationCurves &&
                     IsRedundantAnimationData(target, comp, (chain[i]->second))) {
                     IsRedundantAnimationData(target, comp, (chain[i]->second))) {
 
 
-                FBXImporter::LogDebug("dropping redundant animation channel for node " + target.Name());
+                FBXImporter::LogVerboseDebug("dropping redundant animation channel for node " + target.Name());
                 continue;
                 continue;
             }
             }
 
 
@@ -3164,7 +3161,8 @@ FBXConverter::KeyFrameListList FBXConverter::GetKeyframeList(const std::vector<c
             }
             }
 
 
             const AnimationCurve *const curve = kv.second;
             const AnimationCurve *const curve = kv.second;
-            ai_assert(curve->GetKeys().size() == curve->GetValues().size() && curve->GetKeys().size());
+            ai_assert(curve->GetKeys().size() == curve->GetValues().size());
+            ai_assert(curve->GetKeys().size());
 
 
             //get values within the start/stop time window
             //get values within the start/stop time window
             std::shared_ptr<KeyTimeList> Keys(new KeyTimeList());
             std::shared_ptr<KeyTimeList> Keys(new KeyTimeList());
@@ -3315,6 +3313,7 @@ void FBXConverter::InterpolateKeys(aiQuatKey *valOut, const KeyTimeList &keys, c
         // http://www.3dkingdoms.com/weekly/weekly.php?a=36
         // http://www.3dkingdoms.com/weekly/weekly.php?a=36
         if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0) {
         if (quat.x * lastq.x + quat.y * lastq.y + quat.z * lastq.z + quat.w * lastq.w < 0) {
             quat.Conjugate();
             quat.Conjugate();
+            quat.w = -quat.w;
         }
         }
         lastq = quat;
         lastq = quat;
 
 
@@ -3466,7 +3465,7 @@ void FBXConverter::TransferDataToScene() {
     }
     }
 }
 }
 
 
-void FBXConverter::ConvertOrphantEmbeddedTextures() {
+void FBXConverter::ConvertOrphanedEmbeddedTextures() {
     // in C++14 it could be:
     // in C++14 it could be:
     // for (auto&& [id, object] : objects)
     // for (auto&& [id, object] : objects)
     for (auto &&id_and_object : doc.Objects()) {
     for (auto &&id_and_object : doc.Objects()) {

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

@@ -220,8 +220,8 @@ private:
     *    each output vertex the DOM index it maps to.
     *    each output vertex the DOM index it maps to.
     */
     */
     void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
     void ConvertWeights(aiMesh *out, const MeshGeometry &geo, const aiMatrix4x4 &absolute_transform,
-                        aiNode *parent = NULL, unsigned int materialIndex = NO_MATERIAL_SEPARATION,
-                        std::vector<unsigned int> *outputVertStartIndices = NULL);
+            aiNode *parent = nullptr, unsigned int materialIndex = NO_MATERIAL_SEPARATION,
+            std::vector<unsigned int> *outputVertStartIndices = nullptr);
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
     void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
     void ConvertCluster(std::vector<aiBone *> &local_mesh_bones, const Cluster *cl,
@@ -412,7 +412,7 @@ private:
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
     // FBX file could have embedded textures not connected to anything
     // FBX file could have embedded textures not connected to anything
-    void ConvertOrphantEmbeddedTextures();
+    void ConvertOrphanedEmbeddedTextures();
 
 
 private:
 private:
     // 0: not assigned yet, others: index is value - 1
     // 0: not assigned yet, others: index is value - 1

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

@@ -55,6 +55,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "FBXDocumentUtil.h"
 #include "FBXDocumentUtil.h"
 #include "FBXProperties.h"
 #include "FBXProperties.h"
 
 
+#include <assimp/DefaultLogger.hpp>
+
 #include <memory>
 #include <memory>
 #include <functional>
 #include <functional>
 #include <map>
 #include <map>
@@ -219,7 +221,7 @@ const Object* LazyObject::Get(bool dieOnError)
         if(!DefaultLogger::isNullLogger()) {
         if(!DefaultLogger::isNullLogger()) {
             ASSIMP_LOG_ERROR(ex.what());
             ASSIMP_LOG_ERROR(ex.what());
         }
         }
-        return NULL;
+        return nullptr;
     }
     }
 
 
     if (!object.get()) {
     if (!object.get()) {
@@ -264,6 +266,8 @@ Document::Document(const Parser& parser, const ImportSettings& settings)
 : settings(settings)
 : settings(settings)
 , parser(parser)
 , parser(parser)
 {
 {
+	ASSIMP_LOG_DEBUG("Creating FBX Document");
+
     // Cannot use array default initialization syntax because vc8 fails on it
     // Cannot use array default initialization syntax because vc8 fails on it
     for (auto &timeStamp : creationTimeStamp) {
     for (auto &timeStamp : creationTimeStamp) {
         timeStamp = 0;
         timeStamp = 0;
@@ -308,6 +312,7 @@ void Document::ReadHeader() {
 
 
     const Scope& shead = *ehead->Compound();
     const Scope& shead = *ehead->Compound();
     fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
     fbxVersion = ParseTokenAsInt(GetRequiredToken(GetRequiredElement(shead,"FBXVersion",ehead),0));
+	ASSIMP_LOG_DEBUG_F("FBX Version: ", fbxVersion);
 
 
     // While we may have some success with newer files, we don't support
     // While we may have some success with newer files, we don't support
     // the older 6.n fbx format
     // the older 6.n fbx format
@@ -462,7 +467,7 @@ void Document::ReadPropertyTemplates()
             const Element *Properties70 = (*innerSc)["Properties70"];
             const Element *Properties70 = (*innerSc)["Properties70"];
             if(Properties70) {
             if(Properties70) {
                 std::shared_ptr<const PropertyTable> props = std::make_shared<const PropertyTable>(
                 std::shared_ptr<const PropertyTable> props = std::make_shared<const PropertyTable>(
-                    *Properties70,std::shared_ptr<const PropertyTable>(static_cast<const PropertyTable*>(NULL))
+                        *Properties70, std::shared_ptr<const PropertyTable>(static_cast<const PropertyTable *>(nullptr))
                 );
                 );
 
 
                 templates[oname+"."+pname] = props;
                 templates[oname+"."+pname] = props;

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

@@ -96,7 +96,7 @@ public:
     template <typename T>
     template <typename T>
     const T* Get(bool dieOnError = false) {
     const T* Get(bool dieOnError = false) {
         const Object* const ob = Get(dieOnError);
         const Object* const ob = Get(dieOnError);
-        return ob ? dynamic_cast<const T*>(ob) : NULL;
+        return ob ? dynamic_cast<const T *>(ob) : nullptr;
     }
     }
 
 
     uint64_t ID() const {
     uint64_t ID() const {
@@ -213,7 +213,8 @@ private:
     type name() const { \
     type name() const { \
         const int ival = PropertyGet<int>(Props(), fbx_stringize(name), static_cast<int>(default_value)); \
         const int ival = PropertyGet<int>(Props(), fbx_stringize(name), static_cast<int>(default_value)); \
         if (ival < 0 || ival >= AI_CONCAT(type, _MAX)) { \
         if (ival < 0 || ival >= AI_CONCAT(type, _MAX)) { \
-            ai_assert(static_cast<int>(default_value) >= 0 && static_cast<int>(default_value) < AI_CONCAT(type, _MAX)); \
+            ai_assert(static_cast<int>(default_value) >= 0); \
+            ai_assert(static_cast<int>(default_value) < AI_CONCAT(type, _MAX)); \
             return static_cast<type>(default_value); \
             return static_cast<type>(default_value); \
         } \
         } \
         return static_cast<type>(ival); \
         return static_cast<type>(ival); \
@@ -744,7 +745,7 @@ public:
     wants animations for. If the curve node does not match one of these, std::range_error
     wants animations for. If the curve node does not match one of these, std::range_error
     will be thrown. */
     will be thrown. */
     AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
     AnimationCurveNode(uint64_t id, const Element& element, const std::string& name, const Document& doc,
-        const char* const * target_prop_whitelist = NULL, size_t whitelist_size = 0);
+            const char *const *target_prop_whitelist = nullptr, size_t whitelist_size = 0);
 
 
     virtual ~AnimationCurveNode();
     virtual ~AnimationCurveNode();
 
 
@@ -756,7 +757,7 @@ public:
 
 
     const AnimationCurveMap& Curves() const;
     const AnimationCurveMap& Curves() const;
 
 
-    /** Object the curve is assigned to, this can be NULL if the
+    /** Object the curve is assigned to, this can be nullptr if the
      *  target object has no DOM representation or could not
      *  target object has no DOM representation or could not
      *  be read for other reasons.*/
      *  be read for other reasons.*/
     const Object* Target() const {
     const Object* Target() const {
@@ -968,7 +969,7 @@ public:
 
 
     // note: a connection ensures that the source and dest objects exist, but
     // note: a connection ensures that the source and dest objects exist, but
     // not that they have DOM representations, so the return value of one of
     // not that they have DOM representations, so the return value of one of
-    // these functions can still be NULL.
+    // these functions can still be nullptr.
     const Object* SourceObject() const;
     const Object* SourceObject() const;
     const Object* DestinationObject() const;
     const Object* DestinationObject() const;
 
 

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

@@ -65,7 +65,7 @@ void DOMError(const std::string& message, const Token& token)
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void DOMError(const std::string& message, const Element* element /*= NULL*/)
+void DOMError(const std::string& message, const Element* element /*= nullptr*/)
 {
 {
     if(element) {
     if(element) {
         DOMError(message,element->KeyToken());
         DOMError(message,element->KeyToken());
@@ -84,7 +84,7 @@ void DOMWarning(const std::string& message, const Token& token)
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void DOMWarning(const std::string& message, const Element* element /*= NULL*/)
+void DOMWarning(const std::string& message, const Element* element /*= nullptr*/)
 {
 {
     if(element) {
     if(element) {
         DOMWarning(message,element->KeyToken());
         DOMWarning(message,element->KeyToken());
@@ -106,7 +106,7 @@ std::shared_ptr<const PropertyTable> GetPropertyTable(const Document& doc,
 {
 {
     const Element* const Properties70 = sc["Properties70"];
     const Element* const Properties70 = sc["Properties70"];
     std::shared_ptr<const PropertyTable> templateProps = std::shared_ptr<const PropertyTable>(
     std::shared_ptr<const PropertyTable> templateProps = std::shared_ptr<const PropertyTable>(
-        static_cast<const PropertyTable*>(NULL));
+            static_cast<const PropertyTable *>(nullptr));
 
 
     if(templateName.length()) {
     if(templateName.length()) {
         PropertyTemplateMap::const_iterator it = doc.Templates().find(templateName);
         PropertyTemplateMap::const_iterator it = doc.Templates().find(templateName);

+ 2 - 0
code/AssetLib/FBX/FBXImporter.cpp

@@ -146,6 +146,8 @@ void FBXImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
 		ThrowException("Could not open file for reading");
 		ThrowException("Could not open file for reading");
 	}
 	}
 
 
+    ASSIMP_LOG_DEBUG("Reading FBX file");
+
 	// read entire file into memory - no streaming for this, fbx
 	// read entire file into memory - no streaming for this, fbx
 	// files can grow large, but the assimp output data structure
 	// files can grow large, but the assimp output data structure
 	// then becomes very large, too. Assimp doesn't support
 	// then becomes very large, too. Assimp doesn't support

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

@@ -383,7 +383,7 @@ Video::Video(uint64_t id, const Element& element, const Document& doc, const std
         } catch (const runtime_error& runtimeError)
         } catch (const runtime_error& runtimeError)
         {
         {
             //we don't need the content data for contents that has already been loaded
             //we don't need the content data for contents that has already been loaded
-            ASSIMP_LOG_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
+            ASSIMP_LOG_VERBOSE_DEBUG_F("Caught exception in FBXMaterial (likely because content was already loaded): ",
                     runtimeError.what());
                     runtimeError.what());
         }
         }
     }
     }

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

@@ -241,7 +241,7 @@ const MatIndexArray& MeshGeometry::GetMaterialIndices() const {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
 const unsigned int* MeshGeometry::ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const {
     if ( in_index >= m_mapping_counts.size() ) {
     if ( in_index >= m_mapping_counts.size() ) {
-        return NULL;
+        return nullptr;
     }
     }
 
 
     ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() );
     ai_assert( m_mapping_counts.size() == m_mapping_offsets.size() );

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

@@ -61,10 +61,10 @@ public:
     Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
     Geometry( uint64_t id, const Element& element, const std::string& name, const Document& doc );
     virtual ~Geometry();
     virtual ~Geometry();
 
 
-    /** Get the Skin attached to this geometry or NULL */
+    /** Get the Skin attached to this geometry or nullptr */
     const Skin* DeformerSkin() const;
     const Skin* DeformerSkin() const;
 
 
-    /** Get the BlendShape attached to this geometry or NULL */
+    /** Get the BlendShape attached to this geometry or nullptr */
     const std::vector<const BlendShape*>& GetBlendShapes() const;
     const std::vector<const BlendShape*>& GetBlendShapes() const;
 
 
 private:
 private:
@@ -123,7 +123,7 @@ public:
     /** Get per-face-vertex material assignments */
     /** Get per-face-vertex material assignments */
     const MatIndexArray& GetMaterialIndices() const;
     const MatIndexArray& GetMaterialIndices() const;
 
 
-    /** Convert from a fbx file vertex index (for example from a #Cluster weight) or NULL
+    /** Convert from a fbx file vertex index (for example from a #Cluster weight) or nullptr
     * if the vertex index is not valid. */
     * if the vertex index is not valid. */
     const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const;
     const unsigned int* ToOutputVertexIndex( unsigned int in_index, unsigned int& count ) const;
 
 

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

@@ -59,6 +59,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/ParsingUtils.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/fast_atof.h>
 #include <assimp/fast_atof.h>
 #include <assimp/ByteSwapper.h>
 #include <assimp/ByteSwapper.h>
+#include <assimp/DefaultLogger.hpp>
 
 
 #include <iostream>
 #include <iostream>
 
 
@@ -76,7 +77,7 @@ namespace {
     }
     }
 
 
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
-    AI_WONT_RETURN void ParseError(const std::string& message, const Element* element = NULL) AI_WONT_RETURN_SUFFIX;
+    AI_WONT_RETURN void ParseError(const std::string &message, const Element *element = nullptr) AI_WONT_RETURN_SUFFIX;
     AI_WONT_RETURN void ParseError(const std::string& message, const Element* element)
     AI_WONT_RETURN void ParseError(const std::string& message, const Element* element)
     {
     {
         if(element) {
         if(element) {
@@ -180,7 +181,7 @@ Scope::Scope(Parser& parser,bool topLevel)
     }
     }
 
 
     TokenPtr n = parser.AdvanceToNextToken();
     TokenPtr n = parser.AdvanceToNextToken();
-    if(n == NULL) {
+    if (n == nullptr) {
         ParseError("unexpected end of file");
         ParseError("unexpected end of file");
     }
     }
 
 
@@ -195,7 +196,7 @@ Scope::Scope(Parser& parser,bool topLevel)
 
 
         // Element() should stop at the next Key token (or right after a Close token)
         // Element() should stop at the next Key token (or right after a Close token)
         n = parser.CurrentToken();
         n = parser.CurrentToken();
-        if(n == NULL) {
+        if (n == nullptr) {
             if (topLevel) {
             if (topLevel) {
                 return;
                 return;
             }
             }
@@ -220,6 +221,7 @@ Parser::Parser (const TokenList& tokens, bool is_binary)
 , cursor(tokens.begin())
 , cursor(tokens.begin())
 , is_binary(is_binary)
 , is_binary(is_binary)
 {
 {
+    ASSIMP_LOG_DEBUG("Parsing FBX tokens");
     root.reset(new Scope(*this,true));
     root.reset(new Scope(*this,true));
 }
 }
 
 
@@ -234,7 +236,7 @@ TokenPtr Parser::AdvanceToNextToken()
 {
 {
     last = current;
     last = current;
     if (cursor == tokens.end()) {
     if (cursor == tokens.end()) {
-        current = NULL;
+        current = nullptr;
     } else {
     } else {
         current = *cursor++;
         current = *cursor++;
     }
     }
@@ -256,7 +258,7 @@ TokenPtr Parser::LastToken() const
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
 uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
 {
 {
-    err_out = NULL;
+    err_out = nullptr;
 
 
     if (t.Type() != TokenType_DATA) {
     if (t.Type() != TokenType_DATA) {
         err_out = "expected TOK_DATA token";
         err_out = "expected TOK_DATA token";
@@ -294,7 +296,7 @@ uint64_t ParseTokenAsID(const Token& t, const char*& err_out)
 size_t ParseTokenAsDim(const Token& t, const char*& err_out)
 size_t ParseTokenAsDim(const Token& t, const char*& err_out)
 {
 {
     // same as ID parsing, except there is a trailing asterisk
     // same as ID parsing, except there is a trailing asterisk
-    err_out = NULL;
+    err_out = nullptr;
 
 
     if (t.Type() != TokenType_DATA) {
     if (t.Type() != TokenType_DATA) {
         err_out = "expected TOK_DATA token";
         err_out = "expected TOK_DATA token";
@@ -340,7 +342,7 @@ size_t ParseTokenAsDim(const Token& t, const char*& err_out)
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 float ParseTokenAsFloat(const Token& t, const char*& err_out)
 float ParseTokenAsFloat(const Token& t, const char*& err_out)
 {
 {
-    err_out = NULL;
+    err_out = nullptr;
 
 
     if (t.Type() != TokenType_DATA) {
     if (t.Type() != TokenType_DATA) {
         err_out = "expected TOK_DATA token";
         err_out = "expected TOK_DATA token";
@@ -383,7 +385,7 @@ float ParseTokenAsFloat(const Token& t, const char*& err_out)
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 int ParseTokenAsInt(const Token& t, const char*& err_out)
 int ParseTokenAsInt(const Token& t, const char*& err_out)
 {
 {
-    err_out = NULL;
+    err_out = nullptr;
 
 
     if (t.Type() != TokenType_DATA) {
     if (t.Type() != TokenType_DATA) {
         err_out = "expected TOK_DATA token";
         err_out = "expected TOK_DATA token";
@@ -419,7 +421,7 @@ int ParseTokenAsInt(const Token& t, const char*& err_out)
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
 int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
 {
 {
-    err_out = NULL;
+    err_out = nullptr;
 
 
     if (t.Type() != TokenType_DATA) {
     if (t.Type() != TokenType_DATA) {
         err_out = "expected TOK_DATA token";
         err_out = "expected TOK_DATA token";
@@ -456,7 +458,7 @@ int64_t ParseTokenAsInt64(const Token& t, const char*& err_out)
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 std::string ParseTokenAsString(const Token& t, const char*& err_out)
 std::string ParseTokenAsString(const Token& t, const char*& err_out)
 {
 {
-    err_out = NULL;
+    err_out = nullptr;
 
 
     if (t.Type() != TokenType_DATA) {
     if (t.Type() != TokenType_DATA) {
         err_out = "expected TOK_DATA token";
         err_out = "expected TOK_DATA token";
@@ -1209,7 +1211,7 @@ bool HasElement( const Scope& sc, const std::string& index ) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // extract a required element from a scope, abort if the element cannot be found
 // extract a required element from a scope, abort if the element cannot be found
-const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= NULL*/)
+const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element /*= nullptr*/)
 {
 {
     const Element* el = sc[index];
     const Element* el = sc[index];
     if(!el) {
     if(!el) {

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

@@ -137,7 +137,7 @@ public:
 				return element->second;
 				return element->second;
 			}
 			}
 		}
 		}
-		return NULL;
+        return nullptr;
 	}
 	}
 
 
     ElementCollection GetCollection(const std::string& index) const {
     ElementCollection GetCollection(const std::string& index) const {
@@ -219,7 +219,7 @@ void ParseVectorDataArray(std::vector<int64_t>& out, const Element& el);
 bool HasElement( const Scope& sc, const std::string& index );
 bool HasElement( const Scope& sc, const std::string& index );
 
 
 // extract a required element from a scope, abort if the element cannot be found
 // extract a required element from a scope, abort if the element cannot be found
-const Element& GetRequiredElement(const Scope& sc, const std::string& index, const Element* element = NULL);
+const Element &GetRequiredElement(const Scope &sc, const std::string &index, const Element *element = nullptr);
 
 
 // extract required compound scope
 // extract required compound scope
 const Scope& GetRequiredScope(const Element& el);
 const Scope& GetRequiredScope(const Element& el);

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

@@ -70,7 +70,7 @@ Property::~Property()
 namespace {
 namespace {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-// read a typed property out of a FBX element. The return value is NULL if the property cannot be read.
+// read a typed property out of a FBX element. The return value is nullptr if the property cannot be read.
 Property* ReadTypedProperty(const Element& element)
 Property* ReadTypedProperty(const Element& element)
 {
 {
     ai_assert(element.KeyToken().StringContents() == "P");
     ai_assert(element.KeyToken().StringContents() == "P");
@@ -112,7 +112,7 @@ Property* ReadTypedProperty(const Element& element)
     else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) {
     else if (!strcmp(cs,"double") || !strcmp(cs,"Number") || !strcmp(cs,"Float") || !strcmp(cs,"FieldOfView") || !strcmp( cs, "UnitScaleFactor" ) ) {
         return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
         return new TypedProperty<float>(ParseTokenAsFloat(*tok[4]));
     }
     }
-    return NULL;
+    return nullptr;
 }
 }
 
 
 
 
@@ -197,7 +197,7 @@ const Property* PropertyTable::Get(const std::string& name) const
                 return templateProps->Get(name);
                 return templateProps->Get(name);
             }
             }
 
 
-            return NULL;
+            return nullptr;
         }
         }
     }
     }
 
 

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

@@ -110,7 +110,7 @@ public:
 
 
     const Property* Get(const std::string& name) const;
     const Property* Get(const std::string& name) const;
 
 
-    // PropertyTable's need not be coupled with FBX elements so this can be NULL
+    // PropertyTable's need not be coupled with FBX elements so this can be nullptr
     const Element* GetElement() const {
     const Element* GetElement() const {
         return element;
         return element;
     }
     }

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

@@ -54,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "FBXTokenizer.h"
 #include "FBXTokenizer.h"
 #include "FBXUtil.h"
 #include "FBXUtil.h"
 #include <assimp/Exceptional.h>
 #include <assimp/Exceptional.h>
+#include <assimp/DefaultLogger.hpp>
 
 
 namespace Assimp {
 namespace Assimp {
 namespace FBX {
 namespace FBX {
@@ -126,7 +127,7 @@ void ProcessDataToken( TokenList& output_tokens, const char*& start, const char*
         TokenizeError("unexpected character, expected data token", line, column);
         TokenizeError("unexpected character, expected data token", line, column);
     }
     }
 
 
-    start = end = NULL;
+    start = end = nullptr;
 }
 }
 
 
 }
 }
@@ -134,7 +135,8 @@ 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)
 {
 {
-    ai_assert(input);
+	ai_assert(input);
+	ASSIMP_LOG_DEBUG("Tokenizing ASCII FBX file");
 
 
     // line and column numbers numbers are one-based
     // line and column numbers numbers are one-based
     unsigned int line = 1;
     unsigned int line = 1;
@@ -144,7 +146,7 @@ void Tokenize(TokenList& output_tokens, const char* input)
     bool in_double_quotes = false;
     bool in_double_quotes = false;
     bool pending_data_token = false;
     bool pending_data_token = false;
 
 
-    const char* token_begin = NULL, *token_end = NULL;
+    const char *token_begin = nullptr, *token_end = nullptr;
     for (const char* cur = input;*cur;column += (*cur == '\t' ? ASSIMP_FBX_TAB_WIDTH : 1), ++cur) {
     for (const char* cur = input;*cur;column += (*cur == '\t' ? ASSIMP_FBX_TAB_WIDTH : 1), ++cur) {
         const char c = *cur;
         const char c = *cur;
 
 

+ 154 - 180
code/AssetLib/HMP/HMPLoader.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2020, assimp team
 Copyright (c) 2006-2020, assimp team
 
 
-
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -43,17 +41,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 /** @file Implementation of the MDL importer class */
 /** @file Implementation of the MDL importer class */
 
 
-
 #ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
 #ifndef ASSIMP_BUILD_NO_HMP_IMPORTER
 
 
 // internal headers
 // internal headers
 #include "AssetLib/HMP/HMPLoader.h"
 #include "AssetLib/HMP/HMPLoader.h"
 #include "AssetLib/MD2/MD2FileData.h"
 #include "AssetLib/MD2/MD2FileData.h"
 
 
-#include <assimp/IOSystem.hpp>
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/scene.h>
 #include <assimp/importerdesc.h>
 #include <assimp/importerdesc.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/IOSystem.hpp>
 
 
 #include <memory>
 #include <memory>
 
 
@@ -74,24 +71,21 @@ static const aiImporterDesc desc = {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
-HMPImporter::HMPImporter()
-{
+HMPImporter::HMPImporter() {
     // nothing to do here
     // nothing to do here
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-HMPImporter::~HMPImporter()
-{
+HMPImporter::~HMPImporter() {
     // nothing to do here
     // nothing to do here
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
-bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool cs) const
-{
+bool HMPImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const {
     const std::string extension = GetExtension(pFile);
     const std::string extension = GetExtension(pFile);
-    if (extension == "hmp" )
+    if (extension == "hmp")
         return true;
         return true;
 
 
     // if check for extension is not enough, check for the magic tokens
     // if check for extension is not enough, check for the magic tokens
@@ -100,167 +94,155 @@ bool HMPImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool
         tokens[0] = AI_HMP_MAGIC_NUMBER_LE_4;
         tokens[0] = AI_HMP_MAGIC_NUMBER_LE_4;
         tokens[1] = AI_HMP_MAGIC_NUMBER_LE_5;
         tokens[1] = AI_HMP_MAGIC_NUMBER_LE_5;
         tokens[2] = AI_HMP_MAGIC_NUMBER_LE_7;
         tokens[2] = AI_HMP_MAGIC_NUMBER_LE_7;
-        return CheckMagicToken(pIOHandler,pFile,tokens,3,0);
+        return CheckMagicToken(pIOHandler, pFile, tokens, 3, 0);
     }
     }
     return false;
     return false;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Get list of all file extensions that are handled by this loader
 // Get list of all file extensions that are handled by this loader
-const aiImporterDesc* HMPImporter::GetInfo () const
-{
+const aiImporterDesc *HMPImporter::GetInfo() const {
     return &desc;
     return &desc;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
 // Imports the given file into the given scene structure.
-void HMPImporter::InternReadFile( const std::string& pFile,
-                                 aiScene* _pScene, IOSystem* _pIOHandler)
-{
-    pScene     = _pScene;
+void HMPImporter::InternReadFile(const std::string &pFile,
+        aiScene *_pScene, IOSystem *_pIOHandler) {
+    pScene = _pScene;
     mIOHandler = _pIOHandler;
     mIOHandler = _pIOHandler;
     std::unique_ptr<IOStream> file(mIOHandler->Open(pFile));
     std::unique_ptr<IOStream> file(mIOHandler->Open(pFile));
 
 
     // Check whether we can read from the file
     // Check whether we can read from the file
-    if( file.get() == nullptr)
-        throw DeadlyImportError( "Failed to open HMP file " + pFile + ".");
+    if (file.get() == nullptr) {
+        throw DeadlyImportError("Failed to open HMP file " + pFile + ".");
+    }
 
 
     // Check whether the HMP file is large enough to contain
     // Check whether the HMP file is large enough to contain
     // at least the file header
     // at least the file header
     const size_t fileSize = file->FileSize();
     const size_t fileSize = file->FileSize();
-    if( fileSize < 50)
-        throw DeadlyImportError( "HMP File is too small.");
+    if (fileSize < 50)
+        throw DeadlyImportError("HMP File is too small.");
 
 
     // Allocate storage and copy the contents of the file to a memory buffer
     // Allocate storage and copy the contents of the file to a memory buffer
     mBuffer = new uint8_t[fileSize];
     mBuffer = new uint8_t[fileSize];
-    file->Read( (void*)mBuffer, 1, fileSize);
+    file->Read((void *)mBuffer, 1, fileSize);
     iFileSize = (unsigned int)fileSize;
     iFileSize = (unsigned int)fileSize;
 
 
     // Determine the file subtype and call the appropriate member function
     // Determine the file subtype and call the appropriate member function
-    const uint32_t iMagic = *((uint32_t*)this->mBuffer);
+    const uint32_t iMagic = *((uint32_t *)this->mBuffer);
 
 
     // HMP4 format
     // HMP4 format
     if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic ||
     if (AI_HMP_MAGIC_NUMBER_LE_4 == iMagic ||
-        AI_HMP_MAGIC_NUMBER_BE_4 == iMagic)
-    {
+            AI_HMP_MAGIC_NUMBER_BE_4 == iMagic) {
         ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A4, magic word is HMP4");
         ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A4, magic word is HMP4");
         InternReadFile_HMP4();
         InternReadFile_HMP4();
     }
     }
     // HMP5 format
     // HMP5 format
     else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic ||
     else if (AI_HMP_MAGIC_NUMBER_LE_5 == iMagic ||
-             AI_HMP_MAGIC_NUMBER_BE_5 == iMagic)
-    {
+             AI_HMP_MAGIC_NUMBER_BE_5 == iMagic) {
         ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A5, magic word is HMP5");
         ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A5, magic word is HMP5");
         InternReadFile_HMP5();
         InternReadFile_HMP5();
     }
     }
     // HMP7 format
     // HMP7 format
     else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic ||
     else if (AI_HMP_MAGIC_NUMBER_LE_7 == iMagic ||
-             AI_HMP_MAGIC_NUMBER_BE_7 == iMagic)
-    {
+             AI_HMP_MAGIC_NUMBER_BE_7 == iMagic) {
         ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A7, magic word is HMP7");
         ASSIMP_LOG_DEBUG("HMP subtype: 3D GameStudio A7, magic word is HMP7");
         InternReadFile_HMP7();
         InternReadFile_HMP7();
-    }
-    else
-    {
+    } else {
         // Print the magic word to the logger
         // Print the magic word to the logger
         char szBuffer[5];
         char szBuffer[5];
-        szBuffer[0] = ((char*)&iMagic)[0];
-        szBuffer[1] = ((char*)&iMagic)[1];
-        szBuffer[2] = ((char*)&iMagic)[2];
-        szBuffer[3] = ((char*)&iMagic)[3];
+        szBuffer[0] = ((char *)&iMagic)[0];
+        szBuffer[1] = ((char *)&iMagic)[1];
+        szBuffer[2] = ((char *)&iMagic)[2];
+        szBuffer[3] = ((char *)&iMagic)[3];
         szBuffer[4] = '\0';
         szBuffer[4] = '\0';
 
 
         // We're definitely unable to load this file
         // We're definitely unable to load this file
-        throw DeadlyImportError( "Unknown HMP subformat " + pFile +
-            ". Magic word (" + szBuffer + ") is not known");
+        throw DeadlyImportError("Unknown HMP subformat " + pFile +
+                                ". Magic word (" + szBuffer + ") is not known");
     }
     }
 
 
     // Set the AI_SCENE_FLAGS_TERRAIN bit
     // Set the AI_SCENE_FLAGS_TERRAIN bit
     pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
     pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
 
 
     delete[] mBuffer;
     delete[] mBuffer;
-    mBuffer= nullptr;
-
+    mBuffer = nullptr;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void HMPImporter::ValidateHeader_HMP457( )
-{
-    const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
+void HMPImporter::ValidateHeader_HMP457() {
+    const HMP::Header_HMP5 *const pcHeader = (const HMP::Header_HMP5 *)mBuffer;
 
 
-    if (120 > iFileSize)
-    {
+    if (120 > iFileSize) {
         throw DeadlyImportError("HMP file is too small (header size is "
         throw DeadlyImportError("HMP file is too small (header size is "
-            "120 bytes, this file is smaller)");
+                                "120 bytes, this file is smaller)");
     }
     }
 
 
     if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y)
     if (!pcHeader->ftrisize_x || !pcHeader->ftrisize_y)
         throw DeadlyImportError("Size of triangles in either  x or y direction is zero");
         throw DeadlyImportError("Size of triangles in either  x or y direction is zero");
 
 
-    if(pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts/pcHeader->fnumverts_x) < 1.0f)
+    if (pcHeader->fnumverts_x < 1.0f || (pcHeader->numverts / pcHeader->fnumverts_x) < 1.0f)
         throw DeadlyImportError("Number of triangles in either x or y direction is zero");
         throw DeadlyImportError("Number of triangles in either x or y direction is zero");
 
 
-    if(!pcHeader->numframes)
+    if (!pcHeader->numframes)
         throw DeadlyImportError("There are no frames. At least one should be there");
         throw DeadlyImportError("There are no frames. At least one should be there");
-
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void HMPImporter::InternReadFile_HMP4( )
-{
+void HMPImporter::InternReadFile_HMP4() {
     throw DeadlyImportError("HMP4 is currently not supported");
     throw DeadlyImportError("HMP4 is currently not supported");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void HMPImporter::InternReadFile_HMP5( )
-{
+void HMPImporter::InternReadFile_HMP5() {
     // read the file header and skip everything to byte 84
     // read the file header and skip everything to byte 84
-    const HMP::Header_HMP5* pcHeader = (const HMP::Header_HMP5*)mBuffer;
-    const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84);
+    const HMP::Header_HMP5 *pcHeader = (const HMP::Header_HMP5 *)mBuffer;
+    const unsigned char *szCurrent = (const unsigned char *)(mBuffer + 84);
     ValidateHeader_HMP457();
     ValidateHeader_HMP457();
 
 
     // generate an output mesh
     // generate an output mesh
     pScene->mNumMeshes = 1;
     pScene->mNumMeshes = 1;
-    pScene->mMeshes = new aiMesh*[1];
-    aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
+    pScene->mMeshes = new aiMesh *[1];
+    aiMesh *pcMesh = pScene->mMeshes[0] = new aiMesh();
 
 
     pcMesh->mMaterialIndex = 0;
     pcMesh->mMaterialIndex = 0;
     pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
     pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
     pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
     pcMesh->mNormals = new aiVector3D[pcHeader->numverts];
 
 
     const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
     const unsigned int height = (unsigned int)(pcHeader->numverts / pcHeader->fnumverts_x);
-    const unsigned int width =  (unsigned int)pcHeader->fnumverts_x;
+    const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
 
 
     // generate/load a material for the terrain
     // generate/load a material for the terrain
-    CreateMaterial(szCurrent,&szCurrent);
+    CreateMaterial(szCurrent, &szCurrent);
 
 
     // goto offset 120, I don't know why ...
     // goto offset 120, I don't know why ...
     // (fixme) is this the frame header? I assume yes since it starts with 2.
     // (fixme) is this the frame header? I assume yes since it starts with 2.
     szCurrent += 36;
     szCurrent += 36;
-    SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width);
+    SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7) * height * width);
 
 
     // now load all vertices from the file
     // now load all vertices from the file
-    aiVector3D* pcVertOut = pcMesh->mVertices;
-    aiVector3D* pcNorOut = pcMesh->mNormals;
-    const HMP::Vertex_HMP5* src = (const HMP::Vertex_HMP5*) szCurrent;
-    for (unsigned int y = 0; y < height;++y)
-    {
-        for (unsigned int x = 0; x < width;++x)
-        {
+    aiVector3D *pcVertOut = pcMesh->mVertices;
+    aiVector3D *pcNorOut = pcMesh->mNormals;
+    const HMP::Vertex_HMP5 *src = (const HMP::Vertex_HMP5 *)szCurrent;
+    for (unsigned int y = 0; y < height; ++y) {
+        for (unsigned int x = 0; x < width; ++x) {
             pcVertOut->x = x * pcHeader->ftrisize_x;
             pcVertOut->x = x * pcHeader->ftrisize_x;
             pcVertOut->y = y * pcHeader->ftrisize_y;
             pcVertOut->y = y * pcHeader->ftrisize_y;
-            pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f;
-            MD2::LookupNormalIndex(src->normals162index, *pcNorOut );
-            ++pcVertOut;++pcNorOut;++src;
+            pcVertOut->z = (((float)src->z / 0xffff) - 0.5f) * pcHeader->ftrisize_x * 8.0f;
+            MD2::LookupNormalIndex(src->normals162index, *pcNorOut);
+            ++pcVertOut;
+            ++pcNorOut;
+            ++src;
         }
         }
     }
     }
 
 
     // generate texture coordinates if necessary
     // generate texture coordinates if necessary
     if (pcHeader->numskins)
     if (pcHeader->numskins)
-        GenerateTextureCoords(width,height);
+        GenerateTextureCoords(width, height);
 
 
     // now build a list of faces
     // now build a list of faces
-    CreateOutputFaceList(width,height);
+    CreateOutputFaceList(width, height);
 
 
     // there is no nodegraph in HMP files. Simply assign the one mesh
     // there is no nodegraph in HMP files. Simply assign the one mesh
     // (no, not the one ring) to the root node
     // (no, not the one ring) to the root node
@@ -272,17 +254,16 @@ void HMPImporter::InternReadFile_HMP5( )
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void HMPImporter::InternReadFile_HMP7( )
-{
+void HMPImporter::InternReadFile_HMP7() {
     // read the file header and skip everything to byte 84
     // read the file header and skip everything to byte 84
-    const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
-    const unsigned char* szCurrent = (const unsigned char*)(mBuffer+84);
+    const HMP::Header_HMP5 *const pcHeader = (const HMP::Header_HMP5 *)mBuffer;
+    const unsigned char *szCurrent = (const unsigned char *)(mBuffer + 84);
     ValidateHeader_HMP457();
     ValidateHeader_HMP457();
 
 
     // generate an output mesh
     // generate an output mesh
     pScene->mNumMeshes = 1;
     pScene->mNumMeshes = 1;
-    pScene->mMeshes = new aiMesh*[1];
-    aiMesh* pcMesh = pScene->mMeshes[0] = new aiMesh();
+    pScene->mMeshes = new aiMesh *[1];
+    aiMesh *pcMesh = pScene->mMeshes[0] = new aiMesh();
 
 
     pcMesh->mMaterialIndex = 0;
     pcMesh->mMaterialIndex = 0;
     pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
     pcMesh->mVertices = new aiVector3D[pcHeader->numverts];
@@ -292,44 +273,44 @@ void HMPImporter::InternReadFile_HMP7( )
     const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
     const unsigned int width = (unsigned int)pcHeader->fnumverts_x;
 
 
     // generate/load a material for the terrain
     // generate/load a material for the terrain
-    CreateMaterial(szCurrent,&szCurrent);
+    CreateMaterial(szCurrent, &szCurrent);
 
 
     // goto offset 120, I don't know why ...
     // goto offset 120, I don't know why ...
     // (fixme) is this the frame header? I assume yes since it starts with 2.
     // (fixme) is this the frame header? I assume yes since it starts with 2.
     szCurrent += 36;
     szCurrent += 36;
 
 
-    SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7)*height*width);
+    SizeCheck(szCurrent + sizeof(const HMP::Vertex_HMP7) * height * width);
 
 
     // now load all vertices from the file
     // now load all vertices from the file
-    aiVector3D* pcVertOut = pcMesh->mVertices;
-    aiVector3D* pcNorOut = pcMesh->mNormals;
-    const HMP::Vertex_HMP7* src = (const HMP::Vertex_HMP7*) szCurrent;
-    for (unsigned int y = 0; y < height;++y)
-    {
-        for (unsigned int x = 0; x < width;++x)
-        {
+    aiVector3D *pcVertOut = pcMesh->mVertices;
+    aiVector3D *pcNorOut = pcMesh->mNormals;
+    const HMP::Vertex_HMP7 *src = (const HMP::Vertex_HMP7 *)szCurrent;
+    for (unsigned int y = 0; y < height; ++y) {
+        for (unsigned int x = 0; x < width; ++x) {
             pcVertOut->x = x * pcHeader->ftrisize_x;
             pcVertOut->x = x * pcHeader->ftrisize_x;
             pcVertOut->y = y * pcHeader->ftrisize_y;
             pcVertOut->y = y * pcHeader->ftrisize_y;
 
 
             // FIXME: What exctly is the correct scaling factor to use?
             // FIXME: What exctly is the correct scaling factor to use?
             // possibly pcHeader->scale_origin[2] in combination with a
             // possibly pcHeader->scale_origin[2] in combination with a
             // signed interpretation of src->z?
             // signed interpretation of src->z?
-            pcVertOut->z = (((float)src->z / 0xffff)-0.5f) * pcHeader->ftrisize_x * 8.0f;
+            pcVertOut->z = (((float)src->z / 0xffff) - 0.5f) * pcHeader->ftrisize_x * 8.0f;
 
 
-            pcNorOut->x = ((float)src->normal_x / 0x80 ); // * pcHeader->scale_origin[0];
-            pcNorOut->y = ((float)src->normal_y / 0x80 ); // * pcHeader->scale_origin[1];
+            pcNorOut->x = ((float)src->normal_x / 0x80); // * pcHeader->scale_origin[0];
+            pcNorOut->y = ((float)src->normal_y / 0x80); // * pcHeader->scale_origin[1];
             pcNorOut->z = 1.0f;
             pcNorOut->z = 1.0f;
             pcNorOut->Normalize();
             pcNorOut->Normalize();
 
 
-            ++pcVertOut;++pcNorOut;++src;
+            ++pcVertOut;
+            ++pcNorOut;
+            ++src;
         }
         }
     }
     }
 
 
     // generate texture coordinates if necessary
     // generate texture coordinates if necessary
-    if (pcHeader->numskins)GenerateTextureCoords(width,height);
+    if (pcHeader->numskins) GenerateTextureCoords(width, height);
 
 
     // now build a list of faces
     // now build a list of faces
-    CreateOutputFaceList(width,height);
+    CreateOutputFaceList(width, height);
 
 
     // there is no nodegraph in HMP files. Simply assign the one mesh
     // there is no nodegraph in HMP files. Simply assign the one mesh
     // (no, not the One Ring) to the root node
     // (no, not the One Ring) to the root node
@@ -341,96 +322,89 @@ void HMPImporter::InternReadFile_HMP7( )
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void HMPImporter::CreateMaterial(const unsigned char* szCurrent,
-    const unsigned char** szCurrentOut)
-{
-    aiMesh* const pcMesh = pScene->mMeshes[0];
-    const HMP::Header_HMP5* const pcHeader = (const HMP::Header_HMP5*)mBuffer;
+void HMPImporter::CreateMaterial(const unsigned char *szCurrent,
+        const unsigned char **szCurrentOut) {
+    aiMesh *const pcMesh = pScene->mMeshes[0];
+    const HMP::Header_HMP5 *const pcHeader = (const HMP::Header_HMP5 *)mBuffer;
 
 
     // we don't need to generate texture coordinates if
     // we don't need to generate texture coordinates if
     // we have no textures in the file ...
     // we have no textures in the file ...
-    if (pcHeader->numskins)
-    {
+    if (pcHeader->numskins) {
         pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts];
         pcMesh->mTextureCoords[0] = new aiVector3D[pcHeader->numverts];
         pcMesh->mNumUVComponents[0] = 2;
         pcMesh->mNumUVComponents[0] = 2;
 
 
         // now read the first skin and skip all others
         // now read the first skin and skip all others
-        ReadFirstSkin(pcHeader->numskins,szCurrent,&szCurrent);
-    }
-    else
-    {
+        ReadFirstSkin(pcHeader->numskins, szCurrent, &szCurrent);
+    } else {
         // generate a default material
         // generate a default material
         const int iMode = (int)aiShadingMode_Gouraud;
         const int iMode = (int)aiShadingMode_Gouraud;
-        aiMaterial* pcHelper = new aiMaterial();
+        aiMaterial *pcHelper = new aiMaterial();
         pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
         pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
 
 
         aiColor3D clr;
         aiColor3D clr;
         clr.b = clr.g = clr.r = 0.6f;
         clr.b = clr.g = clr.r = 0.6f;
-        pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_DIFFUSE);
-        pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_SPECULAR);
+        pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
+        pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
 
 
         clr.b = clr.g = clr.r = 0.05f;
         clr.b = clr.g = clr.r = 0.05f;
-        pcHelper->AddProperty<aiColor3D>(&clr, 1,AI_MATKEY_COLOR_AMBIENT);
+        pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_AMBIENT);
 
 
         aiString szName;
         aiString szName;
         szName.Set(AI_DEFAULT_MATERIAL_NAME);
         szName.Set(AI_DEFAULT_MATERIAL_NAME);
-        pcHelper->AddProperty(&szName,AI_MATKEY_NAME);
+        pcHelper->AddProperty(&szName, AI_MATKEY_NAME);
 
 
         // add the material to the scene
         // add the material to the scene
         pScene->mNumMaterials = 1;
         pScene->mNumMaterials = 1;
-        pScene->mMaterials = new aiMaterial*[1];
+        pScene->mMaterials = new aiMaterial *[1];
         pScene->mMaterials[0] = pcHelper;
         pScene->mMaterials[0] = pcHelper;
     }
     }
     *szCurrentOut = szCurrent;
     *szCurrentOut = szCurrent;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height)
-{
-    aiMesh* const pcMesh = this->pScene->mMeshes[0];
+void HMPImporter::CreateOutputFaceList(unsigned int width, unsigned int height) {
+    aiMesh *const pcMesh = this->pScene->mMeshes[0];
 
 
     // Allocate enough storage
     // Allocate enough storage
-    pcMesh->mNumFaces = (width-1) * (height-1);
+    pcMesh->mNumFaces = (width - 1) * (height - 1);
     pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
     pcMesh->mFaces = new aiFace[pcMesh->mNumFaces];
 
 
-    pcMesh->mNumVertices   = pcMesh->mNumFaces*4;
-    aiVector3D* pcVertices = new aiVector3D[pcMesh->mNumVertices];
-    aiVector3D* pcNormals  = new aiVector3D[pcMesh->mNumVertices];
+    pcMesh->mNumVertices = pcMesh->mNumFaces * 4;
+    aiVector3D *pcVertices = new aiVector3D[pcMesh->mNumVertices];
+    aiVector3D *pcNormals = new aiVector3D[pcMesh->mNumVertices];
 
 
-    aiFace* pcFaceOut(pcMesh->mFaces);
-    aiVector3D* pcVertOut = pcVertices;
-    aiVector3D* pcNorOut = pcNormals;
+    aiFace *pcFaceOut(pcMesh->mFaces);
+    aiVector3D *pcVertOut = pcVertices;
+    aiVector3D *pcNorOut = pcNormals;
 
 
-    aiVector3D* pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : NULL;
-    aiVector3D* pcUVOut(pcUVs);
+    aiVector3D *pcUVs = pcMesh->mTextureCoords[0] ? new aiVector3D[pcMesh->mNumVertices] : nullptr;
+    aiVector3D *pcUVOut(pcUVs);
 
 
     // Build the terrain square
     // Build the terrain square
     unsigned int iCurrent = 0;
     unsigned int iCurrent = 0;
-    for (unsigned int y = 0; y < height-1;++y)  {
-        for (unsigned int x = 0; x < width-1;++x,++pcFaceOut)   {
+    for (unsigned int y = 0; y < height - 1; ++y) {
+        for (unsigned int x = 0; x < width - 1; ++x, ++pcFaceOut) {
             pcFaceOut->mNumIndices = 4;
             pcFaceOut->mNumIndices = 4;
             pcFaceOut->mIndices = new unsigned int[4];
             pcFaceOut->mIndices = new unsigned int[4];
 
 
-            *pcVertOut++ = pcMesh->mVertices[y*width+x];
-            *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x];
-            *pcVertOut++ = pcMesh->mVertices[(y+1)*width+x+1];
-            *pcVertOut++ = pcMesh->mVertices[y*width+x+1];
-
-
-            *pcNorOut++ = pcMesh->mNormals[y*width+x];
-            *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x];
-            *pcNorOut++ = pcMesh->mNormals[(y+1)*width+x+1];
-            *pcNorOut++ = pcMesh->mNormals[y*width+x+1];
-
-            if (pcMesh->mTextureCoords[0])
-            {
-                *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x];
-                *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x];
-                *pcUVOut++ = pcMesh->mTextureCoords[0][(y+1)*width+x+1];
-                *pcUVOut++ = pcMesh->mTextureCoords[0][y*width+x+1];
+            *pcVertOut++ = pcMesh->mVertices[y * width + x];
+            *pcVertOut++ = pcMesh->mVertices[(y + 1) * width + x];
+            *pcVertOut++ = pcMesh->mVertices[(y + 1) * width + x + 1];
+            *pcVertOut++ = pcMesh->mVertices[y * width + x + 1];
+
+            *pcNorOut++ = pcMesh->mNormals[y * width + x];
+            *pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x];
+            *pcNorOut++ = pcMesh->mNormals[(y + 1) * width + x + 1];
+            *pcNorOut++ = pcMesh->mNormals[y * width + x + 1];
+
+            if (pcMesh->mTextureCoords[0]) {
+                *pcUVOut++ = pcMesh->mTextureCoords[0][y * width + x];
+                *pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x];
+                *pcUVOut++ = pcMesh->mTextureCoords[0][(y + 1) * width + x + 1];
+                *pcUVOut++ = pcMesh->mTextureCoords[0][y * width + x + 1];
             }
             }
 
 
-            for (unsigned int i = 0; i < 4;++i)
+            for (unsigned int i = 0; i < 4; ++i)
                 pcFaceOut->mIndices[i] = iCurrent++;
                 pcFaceOut->mIndices[i] = iCurrent++;
         }
         }
     }
     }
@@ -440,58 +414,58 @@ void HMPImporter::CreateOutputFaceList(unsigned int width,unsigned int height)
     delete[] pcMesh->mNormals;
     delete[] pcMesh->mNormals;
     pcMesh->mNormals = pcNormals;
     pcMesh->mNormals = pcNormals;
 
 
-    if (pcMesh->mTextureCoords[0])
-    {
+    if (pcMesh->mTextureCoords[0]) {
         delete[] pcMesh->mTextureCoords[0];
         delete[] pcMesh->mTextureCoords[0];
         pcMesh->mTextureCoords[0] = pcUVs;
         pcMesh->mTextureCoords[0] = pcUVs;
     }
     }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szCursor,
-    const unsigned char** szCursorOut)
-{
-    ai_assert( 0 != iNumSkins );
-    ai_assert( nullptr != szCursor);
+void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char *szCursor,
+        const unsigned char **szCursorOut) {
+    ai_assert(0 != iNumSkins);
+    ai_assert(nullptr != szCursor);
 
 
     // read the type of the skin ...
     // read the type of the skin ...
     // sometimes we need to skip 12 bytes here, I don't know why ...
     // sometimes we need to skip 12 bytes here, I don't know why ...
-    uint32_t iType = *((uint32_t*)szCursor);
+    uint32_t iType = *((uint32_t *)szCursor);
     szCursor += sizeof(uint32_t);
     szCursor += sizeof(uint32_t);
-    if (0 == iType)
-    {
+    if (0 == iType) {
         szCursor += sizeof(uint32_t) * 2;
         szCursor += sizeof(uint32_t) * 2;
-        iType = *((uint32_t*)szCursor);
+        iType = *((uint32_t *)szCursor);
         szCursor += sizeof(uint32_t);
         szCursor += sizeof(uint32_t);
         if (!iType)
         if (!iType)
             throw DeadlyImportError("Unable to read HMP7 skin chunk");
             throw DeadlyImportError("Unable to read HMP7 skin chunk");
-
     }
     }
     // read width and height
     // read width and height
-    uint32_t iWidth  = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
-    uint32_t iHeight = *((uint32_t*)szCursor); szCursor += sizeof(uint32_t);
+    uint32_t iWidth = *((uint32_t *)szCursor);
+    szCursor += sizeof(uint32_t);
+    uint32_t iHeight = *((uint32_t *)szCursor);
+    szCursor += sizeof(uint32_t);
 
 
     // allocate an output material
     // allocate an output material
-    aiMaterial* pcMat = new aiMaterial();
+    aiMaterial *pcMat = new aiMaterial();
 
 
     // read the skin, this works exactly as for MDL7
     // read the skin, this works exactly as for MDL7
-    ParseSkinLump_3DGS_MDL7(szCursor,&szCursor,
-        pcMat,iType,iWidth,iHeight);
+    ParseSkinLump_3DGS_MDL7(szCursor, &szCursor,
+            pcMat, iType, iWidth, iHeight);
 
 
     // now we need to skip any other skins ...
     // now we need to skip any other skins ...
-    for (unsigned int i = 1; i< iNumSkins;++i)
-    {
-        iType   = *((uint32_t*)szCursor);   szCursor += sizeof(uint32_t);
-        iWidth  = *((uint32_t*)szCursor);   szCursor += sizeof(uint32_t);
-        iHeight = *((uint32_t*)szCursor);   szCursor += sizeof(uint32_t);
+    for (unsigned int i = 1; i < iNumSkins; ++i) {
+        iType = *((uint32_t *)szCursor);
+        szCursor += sizeof(uint32_t);
+        iWidth = *((uint32_t *)szCursor);
+        szCursor += sizeof(uint32_t);
+        iHeight = *((uint32_t *)szCursor);
+        szCursor += sizeof(uint32_t);
 
 
-        SkipSkinLump_3DGS_MDL7(szCursor,&szCursor,iType,iWidth,iHeight);
+        SkipSkinLump_3DGS_MDL7(szCursor, &szCursor, iType, iWidth, iHeight);
         SizeCheck(szCursor);
         SizeCheck(szCursor);
     }
     }
 
 
     // setup the material ...
     // setup the material ...
     pScene->mNumMaterials = 1;
     pScene->mNumMaterials = 1;
-    pScene->mMaterials = new aiMaterial*[1];
+    pScene->mMaterials = new aiMaterial *[1];
     pScene->mMaterials[0] = pcMat;
     pScene->mMaterials[0] = pcMat;
 
 
     *szCursorOut = szCursor;
     *szCursorOut = szCursor;
@@ -500,20 +474,20 @@ void HMPImporter::ReadFirstSkin(unsigned int iNumSkins, const unsigned char* szC
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Generate proepr texture coords
 // Generate proepr texture coords
 void HMPImporter::GenerateTextureCoords(
 void HMPImporter::GenerateTextureCoords(
-    const unsigned int width, const unsigned int height)
-{
-    ai_assert(NULL != pScene->mMeshes && NULL != pScene->mMeshes[0] &&
-              NULL != pScene->mMeshes[0]->mTextureCoords[0]);
+        const unsigned int width, const unsigned int height) {
+    ai_assert(nullptr != pScene->mMeshes);
+    ai_assert(nullptr != pScene->mMeshes[0]);
+    ai_assert(nullptr != pScene->mMeshes[0]->mTextureCoords[0]);
 
 
-    aiVector3D* uv = pScene->mMeshes[0]->mTextureCoords[0];
+    aiVector3D *uv = pScene->mMeshes[0]->mTextureCoords[0];
 
 
-    const float fY = (1.0f / height) + (1.0f / height) / (height-1);
-    const float fX = (1.0f / width) + (1.0f / width) / (width-1);
+    const float fY = (1.0f / height) + (1.0f / height) / (height - 1);
+    const float fX = (1.0f / width) + (1.0f / width) / (width - 1);
 
 
-    for (unsigned int y = 0; y < height;++y)    {
-        for (unsigned int x = 0; x < width;++x,++uv)    {
-            uv->y = fY*y;
-            uv->x = fX*x;
+    for (unsigned int y = 0; y < height; ++y) {
+        for (unsigned int x = 0; x < width; ++x, ++uv) {
+            uv->y = fY * y;
+            uv->x = fX * x;
             uv->z = 0.0f;
             uv->z = 0.0f;
         }
         }
     }
     }

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

@@ -131,7 +131,7 @@ void WritePolygon(std::vector<IfcVector3> &resultpoly, TempMesh &result) {
 void ProcessBooleanHalfSpaceDifference(const Schema_2x3::IfcHalfSpaceSolid *hs, TempMesh &result,
 void ProcessBooleanHalfSpaceDifference(const Schema_2x3::IfcHalfSpaceSolid *hs, TempMesh &result,
         const TempMesh &first_operand,
         const TempMesh &first_operand,
         ConversionData & /*conv*/) {
         ConversionData & /*conv*/) {
-    ai_assert(hs != NULL);
+    ai_assert(hs != nullptr);
 
 
     const Schema_2x3::IfcPlane *const plane = hs->BaseSurface->ToPtr<Schema_2x3::IfcPlane>();
     const Schema_2x3::IfcPlane *const plane = hs->BaseSurface->ToPtr<Schema_2x3::IfcPlane>();
     if (!plane) {
     if (!plane) {
@@ -221,7 +221,7 @@ void ProcessBooleanHalfSpaceDifference(const Schema_2x3::IfcHalfSpaceSolid *hs,
                 result.mVerts.pop_back();
                 result.mVerts.pop_back();
             }
             }
     }
     }
-    IFCImporter::LogDebug("generating CSG geometry by plane clipping (IfcBooleanClippingResult)");
+    IFCImporter::LogVerboseDebug("generating CSG geometry by plane clipping (IfcBooleanClippingResult)");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -366,7 +366,7 @@ bool PointInPoly(const IfcVector3 &p, const std::vector<IfcVector3> &boundary) {
 void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPolygonalBoundedHalfSpace *hs, TempMesh &result,
 void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPolygonalBoundedHalfSpace *hs, TempMesh &result,
         const TempMesh &first_operand,
         const TempMesh &first_operand,
         ConversionData &conv) {
         ConversionData &conv) {
-    ai_assert(hs != NULL);
+    ai_assert(hs != nullptr);
 
 
     const Schema_2x3::IfcPlane *const plane = hs->BaseSurface->ToPtr<Schema_2x3::IfcPlane>();
     const Schema_2x3::IfcPlane *const plane = hs->BaseSurface->ToPtr<Schema_2x3::IfcPlane>();
     if (!plane) {
     if (!plane) {
@@ -658,14 +658,14 @@ void ProcessPolygonalBoundedBooleanHalfSpaceDifference(const Schema_2x3::IfcPoly
             }
             }
         }
         }
     }
     }
-    IFCImporter::LogDebug("generating CSG geometry by plane clipping with polygonal bounding (IfcBooleanClippingResult)");
+    IFCImporter::LogVerboseDebug("generating CSG geometry by plane clipping with polygonal bounding (IfcBooleanClippingResult)");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedAreaSolid *as, TempMesh &result,
 void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedAreaSolid *as, TempMesh &result,
         const TempMesh &first_operand,
         const TempMesh &first_operand,
         ConversionData &conv) {
         ConversionData &conv) {
-    ai_assert(as != NULL);
+    ai_assert(as != nullptr);
 
 
     // This case is handled by reduction to an instance of the quadrify() algorithm.
     // This case is handled by reduction to an instance of the quadrify() algorithm.
     // Obviously, this won't work for arbitrarily complex cases. In fact, the first
     // Obviously, this won't work for arbitrarily complex cases. In fact, the first
@@ -706,7 +706,7 @@ void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedArea
         vit += pcount;
         vit += pcount;
     }
     }
 
 
-    IFCImporter::LogDebug("generating CSG geometry by geometric difference to a solid (IfcExtrudedAreaSolid)");
+    IFCImporter::LogVerboseDebug("generating CSG geometry by geometric difference to a solid (IfcExtrudedAreaSolid)");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 6 - 4
code/AssetLib/IFC/IFCCurve.cpp

@@ -223,7 +223,7 @@ public:
             }
             }
 
 
             if ( (std::string)curveSegment.Transition != "CONTINUOUS" ) {
             if ( (std::string)curveSegment.Transition != "CONTINUOUS" ) {
-                IFCImporter::LogDebug("ignoring transition code on composite curve segment, only continuous transitions are supported");
+                IFCImporter::LogVerboseDebug("ignoring transition code on composite curve segment, only continuous transitions are supported");
             }
             }
 
 
             curves.push_back( CurveEntry(bc,IsTrue(curveSegment.SameSense)) );
             curves.push_back( CurveEntry(bc,IsTrue(curveSegment.SameSense)) );
@@ -389,7 +389,8 @@ public:
 
 
     // --------------------------------------------------
     // --------------------------------------------------
     void SampleDiscrete(TempMesh& out,IfcFloat a,IfcFloat b) const {
     void SampleDiscrete(TempMesh& out,IfcFloat a,IfcFloat b) const {
-        ai_assert(InRange(a) && InRange(b));
+        ai_assert(InRange(a));
+        ai_assert(InRange(b));
         return base->SampleDiscrete(out,TrimParam(a),TrimParam(b));
         return base->SampleDiscrete(out,TrimParam(a),TrimParam(b));
     }
     }
 
 
@@ -446,7 +447,8 @@ public:
 
 
     // --------------------------------------------------
     // --------------------------------------------------
     size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
     size_t EstimateSampleCount(IfcFloat a, IfcFloat b) const {
-        ai_assert(InRange(a) && InRange(b));
+        ai_assert(InRange(a));
+        ai_assert(InRange(b));
         return static_cast<size_t>( std::ceil(b) - std::floor(a) );
         return static_cast<size_t>( std::ceil(b) - std::floor(a) );
     }
     }
 
 
@@ -489,7 +491,7 @@ Curve* Curve::Convert(const IFC::Schema_2x3::IfcCurve& curve,ConversionData& con
     }
     }
 
 
     // XXX OffsetCurve2D, OffsetCurve3D not currently supported
     // XXX OffsetCurve2D, OffsetCurve3D not currently supported
-    return NULL;
+    return nullptr;
 }
 }
 
 
 #ifdef ASSIMP_BUILD_DEBUG
 #ifdef ASSIMP_BUILD_DEBUG

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

@@ -174,7 +174,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
         TempOpening& opening = fake_openings.back();
         TempOpening& opening = fake_openings.back();
 
 
         opening.extrusionDir = master_normal;
         opening.extrusionDir = master_normal;
-        opening.solid = NULL;
+        opening.solid = nullptr;
 
 
         opening.profileMesh = std::make_shared<TempMesh>();
         opening.profileMesh = std::make_shared<TempMesh>();
         opening.profileMesh->mVerts.reserve(*iit);
         opening.profileMesh->mVerts.reserve(*iit);
@@ -319,7 +319,7 @@ void ProcessRevolvedAreaSolid(const Schema_2x3::IfcRevolvedAreaSolid& solid, Tem
     ConvertAxisPlacement(trafo, solid.Position);
     ConvertAxisPlacement(trafo, solid.Position);
 
 
     result.Transform(trafo);
     result.Transform(trafo);
-    IFCImporter::LogDebug("generate mesh procedurally by radial extrusion (IfcRevolvedAreaSolid)");
+    IFCImporter::LogVerboseDebug("generate mesh procedurally by radial extrusion (IfcRevolvedAreaSolid)");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -457,7 +457,7 @@ void ProcessSweptDiskSolid(const Schema_2x3::IfcSweptDiskSolid &solid, TempMesh&
         }
         }
     }
     }
 
 
-    IFCImporter::LogDebug("generate mesh procedurally by sweeping a disk along a curve (IfcSweptDiskSolid)");
+    IFCImporter::LogVerboseDebug("generate mesh procedurally by sweeping a disk along a curve (IfcSweptDiskSolid)");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -660,7 +660,7 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
         IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
         IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
     }
     }
 
 
-    IFCImporter::LogDebug("generate mesh procedurally by extrusion (IfcExtrudedAreaSolid)");
+    IFCImporter::LogVerboseDebug("generate mesh procedurally by extrusion (IfcExtrudedAreaSolid)");
 
 
     // If this is an opening element, store both the extruded mesh and the 2D profile mesh
     // If this is an opening element, store both the extruded mesh and the 2D profile mesh
     // it was created from. Return an empty mesh to the caller.
     // it was created from. Return an empty mesh to the caller.

+ 10 - 10
code/AssetLib/IFC/IFCLoader.cpp

@@ -172,7 +172,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
     if (GetExtension(pFile) == "ifczip") {
     if (GetExtension(pFile) == "ifczip") {
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_IFC
         unzFile zip = unzOpen(pFile.c_str());
         unzFile zip = unzOpen(pFile.c_str());
-        if (zip == NULL) {
+        if (zip == nullptr) {
             ThrowException("Could not open ifczip file for reading, unzip failed");
             ThrowException("Could not open ifczip file for reading, unzip failed");
         }
         }
 
 
@@ -373,7 +373,7 @@ void SetUnits(ConversionData &conv) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void SetCoordinateSpace(ConversionData &conv) {
 void SetCoordinateSpace(ConversionData &conv) {
-    const Schema_2x3::IfcRepresentationContext *fav = NULL;
+    const Schema_2x3::IfcRepresentationContext *fav = nullptr;
     for (const Schema_2x3::IfcRepresentationContext &v : conv.proj.RepresentationContexts) {
     for (const Schema_2x3::IfcRepresentationContext &v : conv.proj.RepresentationContexts) {
         fav = &v;
         fav = &v;
         // Model should be the most suitable type of context, hence ignore the others
         // Model should be the most suitable type of context, hence ignore the others
@@ -641,14 +641,14 @@ aiNode *ProcessSpatialStructure(aiNode *parent, const Schema_2x3::IfcProduct &el
     bool skipGeometry = false;
     bool skipGeometry = false;
     if (conv.settings.skipSpaceRepresentations) {
     if (conv.settings.skipSpaceRepresentations) {
         if (el.ToPtr<Schema_2x3::IfcSpace>()) {
         if (el.ToPtr<Schema_2x3::IfcSpace>()) {
-            IFCImporter::LogDebug("skipping IfcSpace entity due to importer settings");
+            IFCImporter::LogVerboseDebug("skipping IfcSpace entity due to importer settings");
             skipGeometry = true;
             skipGeometry = true;
         }
         }
     }
     }
 
 
     if (conv.settings.skipAnnotations) {
     if (conv.settings.skipAnnotations) {
         if (el.ToPtr<Schema_2x3::IfcAnnotation>()) {
         if (el.ToPtr<Schema_2x3::IfcAnnotation>()) {
-            IFCImporter::LogDebug("skipping IfcAnnotation entity due to importer settings");
+            IFCImporter::LogVerboseDebug("skipping IfcAnnotation entity due to importer settings");
             return nullptr;
             return nullptr;
         }
         }
     }
     }
@@ -790,7 +790,7 @@ aiNode *ProcessSpatialStructure(aiNode *parent, const Schema_2x3::IfcProduct &el
                 for (const Schema_2x3::IfcObjectDefinition &def : aggr->RelatedObjects) {
                 for (const Schema_2x3::IfcObjectDefinition &def : aggr->RelatedObjects) {
                     if (const Schema_2x3::IfcProduct *const prod = def.ToPtr<Schema_2x3::IfcProduct>()) {
                     if (const Schema_2x3::IfcProduct *const prod = def.ToPtr<Schema_2x3::IfcProduct>()) {
 
 
-                        aiNode *const ndnew = ProcessSpatialStructure(nd_aggr.get(), *prod, conv, NULL);
+                        aiNode *const ndnew = ProcessSpatialStructure(nd_aggr.get(), *prod, conv, nullptr);
                         if (ndnew) {
                         if (ndnew) {
                             nd_aggr->mChildren[nd_aggr->mNumChildren++] = ndnew;
                             nd_aggr->mChildren[nd_aggr->mNumChildren++] = ndnew;
                         }
                         }
@@ -856,7 +856,7 @@ void ProcessSpatialStructures(ConversionData &conv) {
         if (!prod) {
         if (!prod) {
             continue;
             continue;
         }
         }
-        IFCImporter::LogDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : ""));
+        IFCImporter::LogVerboseDebug("looking at spatial structure `" + (prod->Name ? prod->Name.Get() : "unnamed") + "`" + (prod->ObjectType ? " which is of type " + prod->ObjectType.Get() : ""));
 
 
         // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT
         // the primary sites are referenced by an IFCRELAGGREGATES element which assigns them to the IFCPRODUCT
         const STEP::DB::RefMap &refs = conv.db.GetRefs();
         const STEP::DB::RefMap &refs = conv.db.GetRefs();
@@ -868,9 +868,9 @@ void ProcessSpatialStructures(ConversionData &conv) {
                     // comparing pointer values is not sufficient, we would need to cast them to the same type first
                     // comparing pointer values is not sufficient, we would need to cast them to the same type first
                     // as there is multiple inheritance in the game.
                     // as there is multiple inheritance in the game.
                     if (def.GetID() == prod->GetID()) {
                     if (def.GetID() == prod->GetID()) {
-                        IFCImporter::LogDebug("selecting this spatial structure as root structure");
+                        IFCImporter::LogVerboseDebug("selecting this spatial structure as root structure");
                         // got it, this is one primary site.
                         // got it, this is one primary site.
-                        nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL));
+                        nodes.push_back(ProcessSpatialStructure(nullptr, *prod, conv, nullptr));
                     }
                     }
                 }
                 }
             }
             }
@@ -887,7 +887,7 @@ void ProcessSpatialStructures(ConversionData &conv) {
                 continue;
                 continue;
             }
             }
 
 
-            nodes.push_back(ProcessSpatialStructure(NULL, *prod, conv, NULL));
+            nodes.push_back(ProcessSpatialStructure(nullptr, *prod, conv, nullptr));
         }
         }
 
 
         nb_nodes = nodes.size();
         nb_nodes = nodes.size();
@@ -897,7 +897,7 @@ void ProcessSpatialStructures(ConversionData &conv) {
         conv.out->mRootNode = nodes[0];
         conv.out->mRootNode = nodes[0];
     } else if (nb_nodes > 1) {
     } else if (nb_nodes > 1) {
         conv.out->mRootNode = new aiNode("Root");
         conv.out->mRootNode = new aiNode("Root");
-        conv.out->mRootNode->mParent = NULL;
+        conv.out->mRootNode->mParent = nullptr;
         conv.out->mRootNode->mNumChildren = static_cast<unsigned int>(nb_nodes);
         conv.out->mRootNode->mNumChildren = static_cast<unsigned int>(nb_nodes);
         conv.out->mRootNode->mChildren = new aiNode *[conv.out->mRootNode->mNumChildren];
         conv.out->mRootNode->mChildren = new aiNode *[conv.out->mRootNode->mNumChildren];
 
 

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

@@ -1359,7 +1359,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
                     break;
                     break;
                 }
                 }
                 else {
                 else {
-                    IFCImporter::LogDebug("merging overlapping openings");
+                    IFCImporter::LogVerboseDebug("merging overlapping openings");
                     ExtractVerticesFromClipper(poly[0].outer, temp_contour, false);
                     ExtractVerticesFromClipper(poly[0].outer, temp_contour, false);
 
 
                     // Generate the union of the bounding boxes
                     // Generate the union of the bounding boxes

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

@@ -54,333 +54,333 @@ namespace {
 	typedef EXPRESS::ConversionSchema::SchemaEntry SchemaEntry;
 	typedef EXPRESS::ConversionSchema::SchemaEntry SchemaEntry;
 
 
     static const SchemaEntry schema_raw_2x3[] =  {
     static const SchemaEntry schema_raw_2x3[] =  {
-		SchemaEntry("ifcstairtypeenum",NULL )
-,		SchemaEntry("ifcspacetypeenum",NULL )
-,		SchemaEntry("ifcwalltypeenum",NULL )
-,		SchemaEntry("ifcmonthinyearnumber",NULL )
-,		SchemaEntry("ifcheatfluxdensitymeasure",NULL )
-,		SchemaEntry("ifckinematicviscositymeasure",NULL )
-,		SchemaEntry("ifcsequenceenum",NULL )
-,		SchemaEntry("ifcairtoairheatrecoverytypeenum",NULL )
-,		SchemaEntry("ifcactorselect",NULL )
-,		SchemaEntry("ifctransformertypeenum",NULL )
-,		SchemaEntry("ifcunitaryequipmenttypeenum",NULL )
-,		SchemaEntry("ifcelectricflowstoragedevicetypeenum",NULL )
-,		SchemaEntry("ifcenergysequenceenum",NULL )
-,		SchemaEntry("ifcworkcontroltypeenum",NULL )
-,		SchemaEntry("ifccurvaturemeasure",NULL )
-,		SchemaEntry("ifcparametervalue",NULL )
-,		SchemaEntry("ifcappliedvalueselect",NULL )
-,		SchemaEntry("ifcwarpingconstantmeasure",NULL )
-,		SchemaEntry("ifcarithmeticoperatorenum",NULL )
-,		SchemaEntry("ifclinearforcemeasure",NULL )
-,		SchemaEntry("ifcwindowpanelpositionenum",NULL )
-,		SchemaEntry("ifcflowmetertypeenum",NULL )
-,		SchemaEntry("ifcrampflighttypeenum",NULL )
-,		SchemaEntry("ifcspecularhighlightselect",NULL )
-,		SchemaEntry("ifcactiontypeenum",NULL )
-,		SchemaEntry("ifcgeometricprojectionenum",NULL )
-,		SchemaEntry("ifctimeseriesdatatypeenum",NULL )
-,		SchemaEntry("ifcmagneticfluxmeasure",NULL )
-,		SchemaEntry("ifcobjecttypeenum",NULL )
-,		SchemaEntry("ifcdataoriginenum",NULL )
-,		SchemaEntry("ifcmassdensitymeasure",NULL )
-,		SchemaEntry("ifclightfixturetypeenum",NULL )
-,		SchemaEntry("ifcservicelifetypeenum",NULL )
-,		SchemaEntry("ifcelectricvoltagemeasure",NULL )
-,		SchemaEntry("ifcheatingvaluemeasure",NULL )
-,		SchemaEntry("ifcpresentabletext",NULL )
-,		SchemaEntry("ifcaheadorbehind",NULL )
-,		SchemaEntry("ifcsimplevalue",NULL )
-,		SchemaEntry("ifcsensortypeenum",NULL )
-,		SchemaEntry("ifcderivedunitenum",NULL )
-,		SchemaEntry("ifcsizeselect",NULL )
-,		SchemaEntry("ifctransportelementtypeenum",NULL )
-,		SchemaEntry("ifcinventorytypeenum",NULL )
-,		SchemaEntry("ifctextdecoration",NULL )
-,		SchemaEntry("ifcdirectionsenseenum",NULL )
-,		SchemaEntry("ifcductfittingtypeenum",NULL )
-,		SchemaEntry("ifcdocumentstatusenum",NULL )
-,		SchemaEntry("ifcslabtypeenum",NULL )
-,		SchemaEntry("ifcdoorstyleconstructionenum",NULL )
-,		SchemaEntry("ifcvolumemeasure",NULL )
-,		SchemaEntry("ifcinductancemeasure",NULL )
-,		SchemaEntry("ifccurtainwalltypeenum",NULL )
-,		SchemaEntry("ifcsiunitname",NULL )
-,		SchemaEntry("ifcspecularexponent",NULL )
-,		SchemaEntry("ifcsoundpressuremeasure",NULL )
-,		SchemaEntry("ifcanalysistheorytypeenum",NULL )
-,		SchemaEntry("ifcgasterminaltypeenum",NULL )
-,		SchemaEntry("ifcyearnumber",NULL )
-,		SchemaEntry("ifcmodulusofelasticitymeasure",NULL )
-,		SchemaEntry("ifcchangeactionenum",NULL )
-,		SchemaEntry("ifcdampertypeenum",NULL )
-,		SchemaEntry("ifcevaporatortypeenum",NULL )
-,		SchemaEntry("ifcionconcentrationmeasure",NULL )
-,		SchemaEntry("ifcductsegmenttypeenum",NULL )
-,		SchemaEntry("ifcprotectivedevicetypeenum",NULL )
-,		SchemaEntry("ifcabsorbeddosemeasure",NULL )
-,		SchemaEntry("ifcmassperlengthmeasure",NULL )
-,		SchemaEntry("ifctextfontname",NULL )
-,		SchemaEntry("ifcorientationselect",NULL )
-,		SchemaEntry("ifcilluminancemeasure",NULL )
-,		SchemaEntry("ifcfiresuppressionterminaltypeenum",NULL )
-,		SchemaEntry("ifcfontstyle",NULL )
-,		SchemaEntry("ifcmomentofinertiameasure",NULL )
-,		SchemaEntry("ifcmodulusofsubgradereactionmeasure",NULL )
-,		SchemaEntry("ifccomplexnumber",NULL )
-,		SchemaEntry("ifchumidifiertypeenum",NULL )
-,		SchemaEntry("ifcpresentationstyleselect",NULL )
-,		SchemaEntry("ifcthermaltransmittancemeasure",NULL )
-,		SchemaEntry("ifcribplatedirectionenum",NULL )
-,		SchemaEntry("ifcclassificationnotationselect",NULL )
-,		SchemaEntry("ifcminuteinhour",NULL )
-,		SchemaEntry("ifcinternalorexternalenum",NULL )
-,		SchemaEntry("ifcrotationalfrequencymeasure",NULL )
-,		SchemaEntry("ifcsanitaryterminaltypeenum",NULL )
-,		SchemaEntry("ifcsymbolstyleselect",NULL )
-,		SchemaEntry("ifcelementcompositionenum",NULL )
-,		SchemaEntry("ifctextpath",NULL )
-,		SchemaEntry("ifcpowermeasure",NULL )
-,		SchemaEntry("ifcsurfacestyleelementselect",NULL )
-,		SchemaEntry("ifcresourceconsumptionenum",NULL )
-,		SchemaEntry("ifcelectriccapacitancemeasure",NULL )
-,		SchemaEntry("ifclayersetdirectionenum",NULL )
-,		SchemaEntry("ifcrailingtypeenum",NULL )
-,		SchemaEntry("ifcobjectiveenum",NULL )
-,		SchemaEntry("ifcdocumentselect",NULL )
-,		SchemaEntry("ifcmodulusoflinearsubgradereactionmeasure",NULL )
-,		SchemaEntry("ifcthermaladmittancemeasure",NULL )
-,		SchemaEntry("ifctransitioncode",NULL )
-,		SchemaEntry("ifcconnectiontypeenum",NULL )
-,		SchemaEntry("ifcmonetarymeasure",NULL )
-,		SchemaEntry("ifcstackterminaltypeenum",NULL )
-,		SchemaEntry("ifccolour",NULL )
-,		SchemaEntry("ifctext",NULL )
-,		SchemaEntry("ifccontextdependentmeasure",NULL )
-,		SchemaEntry("ifcthermalconductivitymeasure",NULL )
-,		SchemaEntry("ifcprojectedortruelengthenum",NULL )
-,		SchemaEntry("ifcpressuremeasure",NULL )
-,		SchemaEntry("ifcmoisturediffusivitymeasure",NULL )
-,		SchemaEntry("ifcbooleanoperator",NULL )
-,		SchemaEntry("ifcpropertysourceenum",NULL )
-,		SchemaEntry("ifctimestamp",NULL )
-,		SchemaEntry("ifcmaterialselect",NULL )
-,		SchemaEntry("ifcgloballyuniqueid",NULL )
-,		SchemaEntry("ifcreflectancemethodenum",NULL )
-,		SchemaEntry("ifcvaporpermeabilitymeasure",NULL )
-,		SchemaEntry("ifctimeseriesscheduletypeenum",NULL )
-,		SchemaEntry("ifclinearmomentmeasure",NULL )
-,		SchemaEntry("ifcgeometricsetselect",NULL )
-,		SchemaEntry("ifcsectionmodulusmeasure",NULL )
-,		SchemaEntry("ifcbsplinecurveform",NULL )
-,		SchemaEntry("ifcdimensionextentusage",NULL )
-,		SchemaEntry("ifcthermalexpansioncoefficientmeasure",NULL )
-,		SchemaEntry("ifchourinday",NULL )
-,		SchemaEntry("ifclinearvelocitymeasure",NULL )
-,		SchemaEntry("ifctorquemeasure",NULL )
-,		SchemaEntry("ifctemperaturegradientmeasure",NULL )
-,		SchemaEntry("ifcfillstyleselect",NULL )
-,		SchemaEntry("ifcelectricchargemeasure",NULL )
-,		SchemaEntry("ifcheatexchangertypeenum",NULL )
-,		SchemaEntry("ifcelectriccurrentenum",NULL )
-,		SchemaEntry("ifcdaylightsavinghour",NULL )
-,		SchemaEntry("ifcshell",NULL )
-,		SchemaEntry("ifcdoseequivalentmeasure",NULL )
-,		SchemaEntry("ifcprojectordertypeenum",NULL )
-,		SchemaEntry("ifcderivedmeasurevalue",NULL )
-,		SchemaEntry("ifclightdistributioncurveenum",NULL )
-,		SchemaEntry("ifcwarpingmomentmeasure",NULL )
-,		SchemaEntry("ifcmembertypeenum",NULL )
-,		SchemaEntry("ifcsoundpowermeasure",NULL )
-,		SchemaEntry("ifctextalignment",NULL )
-,		SchemaEntry("ifccurveoredgecurve",NULL )
-,		SchemaEntry("ifcmassflowratemeasure",NULL )
-,		SchemaEntry("ifcisothermalmoisturecapacitymeasure",NULL )
-,		SchemaEntry("ifccsgselect",NULL )
-,		SchemaEntry("ifccoolingtowertypeenum",NULL )
-,		SchemaEntry("ifcmassmeasure",NULL )
-,		SchemaEntry("ifcpileconstructionenum",NULL )
-,		SchemaEntry("ifcdoorstyleoperationenum",NULL )
-,		SchemaEntry("ifcflowdirectionenum",NULL )
-,		SchemaEntry("ifcthermalloadsourceenum",NULL )
-,		SchemaEntry("ifclengthmeasure",NULL )
-,		SchemaEntry("ifcconstraintenum",NULL )
-,		SchemaEntry("ifcaxis2placement",NULL )
-,		SchemaEntry("ifcloadgrouptypeenum",NULL )
-,		SchemaEntry("ifcvalue",NULL )
-,		SchemaEntry("ifcreinforcingbarsurfaceenum",NULL )
-,		SchemaEntry("ifcprojectorderrecordtypeenum",NULL )
-,		SchemaEntry("ifcdatetimeselect",NULL )
-,		SchemaEntry("ifcstructuralsurfacetypeenum",NULL )
-,		SchemaEntry("ifcpermeablecoveringoperationenum",NULL )
-,		SchemaEntry("ifcfontweight",NULL )
-,		SchemaEntry("ifcphmeasure",NULL )
-,		SchemaEntry("ifcdescriptivemeasure",NULL )
-,		SchemaEntry("ifccurvestylefontselect",NULL )
-,		SchemaEntry("ifcunit",NULL )
-,		SchemaEntry("ifchatchlinedistanceselect",NULL )
-,		SchemaEntry("ifctextstyleselect",NULL )
-,		SchemaEntry("ifcmetricvalueselect",NULL )
-,		SchemaEntry("ifcvectorordirection",NULL )
-,		SchemaEntry("ifcassemblyplaceenum",NULL )
-,		SchemaEntry("ifcairterminaltypeenum",NULL )
-,		SchemaEntry("ifccoveringtypeenum",NULL )
-,		SchemaEntry("ifcplanarforcemeasure",NULL )
-,		SchemaEntry("ifcvalvetypeenum",NULL )
-,		SchemaEntry("ifcalarmtypeenum",NULL )
-,		SchemaEntry("ifcdynamicviscositymeasure",NULL )
-,		SchemaEntry("ifccurrencyenum",NULL )
-,		SchemaEntry("ifcmodulusofrotationalsubgradereactionmeasure",NULL )
-,		SchemaEntry("ifccablecarrierfittingtypeenum",NULL )
-,		SchemaEntry("ifcboolean",NULL )
-,		SchemaEntry("ifcactionsourcetypeenum",NULL )
-,		SchemaEntry("ifcstructuralactivityassignmentselect",NULL )
-,		SchemaEntry("ifcdistributionchamberelementtypeenum",NULL )
-,		SchemaEntry("ifcevaporativecoolertypeenum",NULL )
-,		SchemaEntry("ifcmagneticfluxdensitymeasure",NULL )
-,		SchemaEntry("ifclightdistributiondatasourceselect",NULL )
-,		SchemaEntry("ifctubebundletypeenum",NULL )
-,		SchemaEntry("ifcaccelerationmeasure",NULL )
-,		SchemaEntry("ifcboilertypeenum",NULL )
-,		SchemaEntry("ifcramptypeenum",NULL )
-,		SchemaEntry("ifcluminousintensitydistributionmeasure",NULL )
-,		SchemaEntry("ifctrimmingpreference",NULL )
-,		SchemaEntry("ifcspecificheatcapacitymeasure",NULL )
-,		SchemaEntry("ifcamountofsubstancemeasure",NULL )
-,		SchemaEntry("ifcroleenum",NULL )
-,		SchemaEntry("ifcdocumentconfidentialityenum",NULL )
-,		SchemaEntry("ifcfrequencymeasure",NULL )
-,		SchemaEntry("ifcsectiontypeenum",NULL )
-,		SchemaEntry("ifcelementassemblytypeenum",NULL )
-,		SchemaEntry("ifcfootingtypeenum",NULL )
-,		SchemaEntry("ifclayereditem",NULL )
-,		SchemaEntry("ifccablesegmenttypeenum",NULL )
-,		SchemaEntry("ifcdefinedsymbolselect",NULL )
-,		SchemaEntry("ifcbuildingelementproxytypeenum",NULL )
-,		SchemaEntry("ifcelectricgeneratortypeenum",NULL )
-,		SchemaEntry("ifcrotationalstiffnessmeasure",NULL )
-,		SchemaEntry("ifcspaceheatertypeenum",NULL )
-,		SchemaEntry("ifcareameasure",NULL )
-,		SchemaEntry("ifclabel",NULL )
-,		SchemaEntry("ifccostscheduletypeenum",NULL )
-,		SchemaEntry("ifcswitchingdevicetypeenum",NULL )
-,		SchemaEntry("ifcelectrictimecontroltypeenum",NULL )
-,		SchemaEntry("ifcfiltertypeenum",NULL )
-,		SchemaEntry("ifcpositivelengthmeasure",NULL )
-,		SchemaEntry("ifcnullstyle",NULL )
-,		SchemaEntry("ifcconditioncriterionselect",NULL )
-,		SchemaEntry("ifcshearmodulusmeasure",NULL )
-,		SchemaEntry("ifcnormalisedratiomeasure",NULL )
-,		SchemaEntry("ifcdoorpaneloperationenum",NULL )
-,		SchemaEntry("ifcpointorvertexpoint",NULL )
-,		SchemaEntry("ifcrooftypeenum",NULL )
-,		SchemaEntry("ifccountmeasure",NULL )
-,		SchemaEntry("ifcelectricconductancemeasure",NULL )
-,		SchemaEntry("ifcproceduretypeenum",NULL )
-,		SchemaEntry("ifcflowinstrumenttypeenum",NULL )
-,		SchemaEntry("ifcelectricmotortypeenum",NULL )
-,		SchemaEntry("ifcsurfaceside",NULL )
-,		SchemaEntry("ifcstructuralcurvetypeenum",NULL )
-,		SchemaEntry("ifccondensertypeenum",NULL )
-,		SchemaEntry("ifclinearstiffnessmeasure",NULL )
-,		SchemaEntry("ifcunitenum",NULL )
-,		SchemaEntry("ifcoccupanttypeenum",NULL )
-,		SchemaEntry("ifcthermalloadtypeenum",NULL )
-,		SchemaEntry("ifcreinforcingbarroleenum",NULL )
-,		SchemaEntry("ifcbenchmarkenum",NULL )
-,		SchemaEntry("ifcpositiveplaneanglemeasure",NULL )
-,		SchemaEntry("ifctexttransformation",NULL )
-,		SchemaEntry("ifcdraughtingcalloutelement",NULL )
-,		SchemaEntry("ifcratiomeasure",NULL )
-,		SchemaEntry("ifcsolidanglemeasure",NULL )
-,		SchemaEntry("ifcpipesegmenttypeenum",NULL )
-,		SchemaEntry("ifccablecarriersegmenttypeenum",NULL )
-,		SchemaEntry("ifccolourorfactor",NULL )
-,		SchemaEntry("ifcidentifier",NULL )
-,		SchemaEntry("ifctendontypeenum",NULL )
-,		SchemaEntry("ifccontrollertypeenum",NULL )
-,		SchemaEntry("ifcradioactivitymeasure",NULL )
-,		SchemaEntry("ifctimemeasure",NULL )
-,		SchemaEntry("ifcpumptypeenum",NULL )
-,		SchemaEntry("ifcelectricheatertypeenum",NULL )
-,		SchemaEntry("ifcbeamtypeenum",NULL )
-,		SchemaEntry("ifcstateenum",NULL )
-,		SchemaEntry("ifcsiprefix",NULL )
-,		SchemaEntry("ifcnumericmeasure",NULL )
-,		SchemaEntry("ifcoutlettypeenum",NULL )
-,		SchemaEntry("ifccompoundplaneanglemeasure",NULL )
-,		SchemaEntry("ifcservicelifefactortypeenum",NULL )
-,		SchemaEntry("ifclogicaloperatorenum",NULL )
-,		SchemaEntry("ifcbooleanoperand",NULL )
-,		SchemaEntry("ifcobjectreferenceselect",NULL )
-,		SchemaEntry("ifccooledbeamtypeenum",NULL )
-,		SchemaEntry("ifcductsilencertypeenum",NULL )
-,		SchemaEntry("ifcsectionalareaintegralmeasure",NULL )
-,		SchemaEntry("ifcfontvariant",NULL )
-,		SchemaEntry("ifcvolumetricflowratemeasure",NULL )
-,		SchemaEntry("ifcplatetypeenum",NULL )
-,		SchemaEntry("ifcenvironmentalimpactcategoryenum",NULL )
-,		SchemaEntry("ifcvibrationisolatortypeenum",NULL )
-,		SchemaEntry("ifcthermodynamictemperaturemeasure",NULL )
-,		SchemaEntry("ifcrotationalmassmeasure",NULL )
-,		SchemaEntry("ifcsecondinminute",NULL )
-,		SchemaEntry("ifcdayinmonthnumber",NULL )
-,		SchemaEntry("ifcdimensioncount",NULL )
-,		SchemaEntry("ifcwindowstyleoperationenum",NULL )
-,		SchemaEntry("ifcthermalresistancemeasure",NULL )
-,		SchemaEntry("ifcmeasurevalue",NULL )
-,		SchemaEntry("ifcwindowpaneloperationenum",NULL )
-,		SchemaEntry("ifcchillertypeenum",NULL )
-,		SchemaEntry("ifcpositiveratiomeasure",NULL )
-,		SchemaEntry("ifcinteger",NULL )
-,		SchemaEntry("ifclogical",NULL )
-,		SchemaEntry("ifcjunctionboxtypeenum",NULL )
-,		SchemaEntry("ifcaddresstypeenum",NULL )
-,		SchemaEntry("ifcwasteterminaltypeenum",NULL )
-,		SchemaEntry("ifctrimmingselect",NULL )
-,		SchemaEntry("ifclightemissionsourceenum",NULL )
-,		SchemaEntry("ifcsoundscaleenum",NULL )
-,		SchemaEntry("ifcluminousfluxmeasure",NULL )
-,		SchemaEntry("ifcelectricresistancemeasure",NULL )
-,		SchemaEntry("ifcintegercountratemeasure",NULL )
-,		SchemaEntry("ifcphysicalorvirtualenum",NULL )
-,		SchemaEntry("ifcmolecularweightmeasure",NULL )
-,		SchemaEntry("ifcprofiletypeenum",NULL )
-,		SchemaEntry("ifcboxalignment",NULL )
-,		SchemaEntry("ifcglobalorlocalenum",NULL )
-,		SchemaEntry("ifcspecularroughness",NULL )
-,		SchemaEntry("ifclamptypeenum",NULL )
-,		SchemaEntry("ifcpiletypeenum",NULL )
-,		SchemaEntry("ifcelectriccurrentmeasure",NULL )
-,		SchemaEntry("ifcfantypeenum",NULL )
-,		SchemaEntry("ifcsurfaceorfacesurface",NULL )
-,		SchemaEntry("ifcpipefittingtypeenum",NULL )
-,		SchemaEntry("ifctanktypeenum",NULL )
-,		SchemaEntry("ifccurvefontorscaledcurvefontselect",NULL )
-,		SchemaEntry("ifcwindowstyleconstructionenum",NULL )
-,		SchemaEntry("ifcairterminalboxtypeenum",NULL )
-,		SchemaEntry("ifcstairflighttypeenum",NULL )
-,		SchemaEntry("ifcluminousintensitymeasure",NULL )
-,		SchemaEntry("ifcmotorconnectiontypeenum",NULL )
-,		SchemaEntry("ifcplaneanglemeasure",NULL )
-,		SchemaEntry("ifcactuatortypeenum",NULL )
-,		SchemaEntry("ifccolumntypeenum",NULL )
-,		SchemaEntry("ifctextfontselect",NULL )
-,		SchemaEntry("ifcdoorpanelpositionenum",NULL )
-,		SchemaEntry("ifccoiltypeenum",NULL )
-,		SchemaEntry("ifcangularvelocitymeasure",NULL )
-,		SchemaEntry("ifcanalysismodeltypeenum",NULL )
-,		SchemaEntry("ifclibraryselect",NULL )
-,		SchemaEntry("ifcforcemeasure",NULL )
-,		SchemaEntry("ifcfillareastyletileshapeselect",NULL )
-,		SchemaEntry("ifcelectricappliancetypeenum",NULL )
-,		SchemaEntry("ifcsurfacetextureenum",NULL )
-,		SchemaEntry("ifccharacterstyleselect",NULL )
-,		SchemaEntry("ifcenergymeasure",NULL )
-,		SchemaEntry("ifcreal",NULL )
-,		SchemaEntry("ifccompressortypeenum",NULL )
-,		SchemaEntry("ifcelectricdistributionpointfunctionenum",NULL )
+		SchemaEntry("ifcstairtypeenum",nullptr )
+,		SchemaEntry("ifcspacetypeenum",nullptr )
+,		SchemaEntry("ifcwalltypeenum",nullptr )
+,		SchemaEntry("ifcmonthinyearnumber",nullptr )
+,		SchemaEntry("ifcheatfluxdensitymeasure",nullptr )
+,		SchemaEntry("ifckinematicviscositymeasure",nullptr )
+,		SchemaEntry("ifcsequenceenum",nullptr )
+,		SchemaEntry("ifcairtoairheatrecoverytypeenum",nullptr )
+,		SchemaEntry("ifcactorselect",nullptr )
+,		SchemaEntry("ifctransformertypeenum",nullptr )
+,		SchemaEntry("ifcunitaryequipmenttypeenum",nullptr )
+,		SchemaEntry("ifcelectricflowstoragedevicetypeenum",nullptr )
+,		SchemaEntry("ifcenergysequenceenum",nullptr )
+,		SchemaEntry("ifcworkcontroltypeenum",nullptr )
+,		SchemaEntry("ifccurvaturemeasure",nullptr )
+,		SchemaEntry("ifcparametervalue",nullptr )
+,		SchemaEntry("ifcappliedvalueselect",nullptr )
+,		SchemaEntry("ifcwarpingconstantmeasure",nullptr )
+,		SchemaEntry("ifcarithmeticoperatorenum",nullptr )
+,		SchemaEntry("ifclinearforcemeasure",nullptr )
+,		SchemaEntry("ifcwindowpanelpositionenum",nullptr )
+,		SchemaEntry("ifcflowmetertypeenum",nullptr )
+,		SchemaEntry("ifcrampflighttypeenum",nullptr )
+,		SchemaEntry("ifcspecularhighlightselect",nullptr )
+,		SchemaEntry("ifcactiontypeenum",nullptr )
+,		SchemaEntry("ifcgeometricprojectionenum",nullptr )
+,		SchemaEntry("ifctimeseriesdatatypeenum",nullptr )
+,		SchemaEntry("ifcmagneticfluxmeasure",nullptr )
+,		SchemaEntry("ifcobjecttypeenum",nullptr )
+,		SchemaEntry("ifcdataoriginenum",nullptr )
+,		SchemaEntry("ifcmassdensitymeasure",nullptr )
+,		SchemaEntry("ifclightfixturetypeenum",nullptr )
+,		SchemaEntry("ifcservicelifetypeenum",nullptr )
+,		SchemaEntry("ifcelectricvoltagemeasure",nullptr )
+,		SchemaEntry("ifcheatingvaluemeasure",nullptr )
+,		SchemaEntry("ifcpresentabletext",nullptr )
+,		SchemaEntry("ifcaheadorbehind",nullptr )
+,		SchemaEntry("ifcsimplevalue",nullptr )
+,		SchemaEntry("ifcsensortypeenum",nullptr )
+,		SchemaEntry("ifcderivedunitenum",nullptr )
+,		SchemaEntry("ifcsizeselect",nullptr )
+,		SchemaEntry("ifctransportelementtypeenum",nullptr )
+,		SchemaEntry("ifcinventorytypeenum",nullptr )
+,		SchemaEntry("ifctextdecoration",nullptr )
+,		SchemaEntry("ifcdirectionsenseenum",nullptr )
+,		SchemaEntry("ifcductfittingtypeenum",nullptr )
+,		SchemaEntry("ifcdocumentstatusenum",nullptr )
+,		SchemaEntry("ifcslabtypeenum",nullptr )
+,		SchemaEntry("ifcdoorstyleconstructionenum",nullptr )
+,		SchemaEntry("ifcvolumemeasure",nullptr )
+,		SchemaEntry("ifcinductancemeasure",nullptr )
+,		SchemaEntry("ifccurtainwalltypeenum",nullptr )
+,		SchemaEntry("ifcsiunitname",nullptr )
+,		SchemaEntry("ifcspecularexponent",nullptr )
+,		SchemaEntry("ifcsoundpressuremeasure",nullptr )
+,		SchemaEntry("ifcanalysistheorytypeenum",nullptr )
+,		SchemaEntry("ifcgasterminaltypeenum",nullptr )
+,		SchemaEntry("ifcyearnumber",nullptr )
+,		SchemaEntry("ifcmodulusofelasticitymeasure",nullptr )
+,		SchemaEntry("ifcchangeactionenum",nullptr )
+,		SchemaEntry("ifcdampertypeenum",nullptr )
+,		SchemaEntry("ifcevaporatortypeenum",nullptr )
+,		SchemaEntry("ifcionconcentrationmeasure",nullptr )
+,		SchemaEntry("ifcductsegmenttypeenum",nullptr )
+,		SchemaEntry("ifcprotectivedevicetypeenum",nullptr )
+,		SchemaEntry("ifcabsorbeddosemeasure",nullptr )
+,		SchemaEntry("ifcmassperlengthmeasure",nullptr )
+,		SchemaEntry("ifctextfontname",nullptr )
+,		SchemaEntry("ifcorientationselect",nullptr )
+,		SchemaEntry("ifcilluminancemeasure",nullptr )
+,		SchemaEntry("ifcfiresuppressionterminaltypeenum",nullptr )
+,		SchemaEntry("ifcfontstyle",nullptr )
+,		SchemaEntry("ifcmomentofinertiameasure",nullptr )
+,		SchemaEntry("ifcmodulusofsubgradereactionmeasure",nullptr )
+,		SchemaEntry("ifccomplexnumber",nullptr )
+,		SchemaEntry("ifchumidifiertypeenum",nullptr )
+,		SchemaEntry("ifcpresentationstyleselect",nullptr )
+,		SchemaEntry("ifcthermaltransmittancemeasure",nullptr )
+,		SchemaEntry("ifcribplatedirectionenum",nullptr )
+,		SchemaEntry("ifcclassificationnotationselect",nullptr )
+,		SchemaEntry("ifcminuteinhour",nullptr )
+,		SchemaEntry("ifcinternalorexternalenum",nullptr )
+,		SchemaEntry("ifcrotationalfrequencymeasure",nullptr )
+,		SchemaEntry("ifcsanitaryterminaltypeenum",nullptr )
+,		SchemaEntry("ifcsymbolstyleselect",nullptr )
+,		SchemaEntry("ifcelementcompositionenum",nullptr )
+,		SchemaEntry("ifctextpath",nullptr )
+,		SchemaEntry("ifcpowermeasure",nullptr )
+,		SchemaEntry("ifcsurfacestyleelementselect",nullptr )
+,		SchemaEntry("ifcresourceconsumptionenum",nullptr )
+,		SchemaEntry("ifcelectriccapacitancemeasure",nullptr )
+,		SchemaEntry("ifclayersetdirectionenum",nullptr )
+,		SchemaEntry("ifcrailingtypeenum",nullptr )
+,		SchemaEntry("ifcobjectiveenum",nullptr )
+,		SchemaEntry("ifcdocumentselect",nullptr )
+,		SchemaEntry("ifcmodulusoflinearsubgradereactionmeasure",nullptr )
+,		SchemaEntry("ifcthermaladmittancemeasure",nullptr )
+,		SchemaEntry("ifctransitioncode",nullptr )
+,		SchemaEntry("ifcconnectiontypeenum",nullptr )
+,		SchemaEntry("ifcmonetarymeasure",nullptr )
+,		SchemaEntry("ifcstackterminaltypeenum",nullptr )
+,		SchemaEntry("ifccolour",nullptr )
+,		SchemaEntry("ifctext",nullptr )
+,		SchemaEntry("ifccontextdependentmeasure",nullptr )
+,		SchemaEntry("ifcthermalconductivitymeasure",nullptr )
+,		SchemaEntry("ifcprojectedortruelengthenum",nullptr )
+,		SchemaEntry("ifcpressuremeasure",nullptr )
+,		SchemaEntry("ifcmoisturediffusivitymeasure",nullptr )
+,		SchemaEntry("ifcbooleanoperator",nullptr )
+,		SchemaEntry("ifcpropertysourceenum",nullptr )
+,		SchemaEntry("ifctimestamp",nullptr )
+,		SchemaEntry("ifcmaterialselect",nullptr )
+,		SchemaEntry("ifcgloballyuniqueid",nullptr )
+,		SchemaEntry("ifcreflectancemethodenum",nullptr )
+,		SchemaEntry("ifcvaporpermeabilitymeasure",nullptr )
+,		SchemaEntry("ifctimeseriesscheduletypeenum",nullptr )
+,		SchemaEntry("ifclinearmomentmeasure",nullptr )
+,		SchemaEntry("ifcgeometricsetselect",nullptr )
+,		SchemaEntry("ifcsectionmodulusmeasure",nullptr )
+,		SchemaEntry("ifcbsplinecurveform",nullptr )
+,		SchemaEntry("ifcdimensionextentusage",nullptr )
+,		SchemaEntry("ifcthermalexpansioncoefficientmeasure",nullptr )
+,		SchemaEntry("ifchourinday",nullptr )
+,		SchemaEntry("ifclinearvelocitymeasure",nullptr )
+,		SchemaEntry("ifctorquemeasure",nullptr )
+,		SchemaEntry("ifctemperaturegradientmeasure",nullptr )
+,		SchemaEntry("ifcfillstyleselect",nullptr )
+,		SchemaEntry("ifcelectricchargemeasure",nullptr )
+,		SchemaEntry("ifcheatexchangertypeenum",nullptr )
+,		SchemaEntry("ifcelectriccurrentenum",nullptr )
+,		SchemaEntry("ifcdaylightsavinghour",nullptr )
+,		SchemaEntry("ifcshell",nullptr )
+,		SchemaEntry("ifcdoseequivalentmeasure",nullptr )
+,		SchemaEntry("ifcprojectordertypeenum",nullptr )
+,		SchemaEntry("ifcderivedmeasurevalue",nullptr )
+,		SchemaEntry("ifclightdistributioncurveenum",nullptr )
+,		SchemaEntry("ifcwarpingmomentmeasure",nullptr )
+,		SchemaEntry("ifcmembertypeenum",nullptr )
+,		SchemaEntry("ifcsoundpowermeasure",nullptr )
+,		SchemaEntry("ifctextalignment",nullptr )
+,		SchemaEntry("ifccurveoredgecurve",nullptr )
+,		SchemaEntry("ifcmassflowratemeasure",nullptr )
+,		SchemaEntry("ifcisothermalmoisturecapacitymeasure",nullptr )
+,		SchemaEntry("ifccsgselect",nullptr )
+,		SchemaEntry("ifccoolingtowertypeenum",nullptr )
+,		SchemaEntry("ifcmassmeasure",nullptr )
+,		SchemaEntry("ifcpileconstructionenum",nullptr )
+,		SchemaEntry("ifcdoorstyleoperationenum",nullptr )
+,		SchemaEntry("ifcflowdirectionenum",nullptr )
+,		SchemaEntry("ifcthermalloadsourceenum",nullptr )
+,		SchemaEntry("ifclengthmeasure",nullptr )
+,		SchemaEntry("ifcconstraintenum",nullptr )
+,		SchemaEntry("ifcaxis2placement",nullptr )
+,		SchemaEntry("ifcloadgrouptypeenum",nullptr )
+,		SchemaEntry("ifcvalue",nullptr )
+,		SchemaEntry("ifcreinforcingbarsurfaceenum",nullptr )
+,		SchemaEntry("ifcprojectorderrecordtypeenum",nullptr )
+,		SchemaEntry("ifcdatetimeselect",nullptr )
+,		SchemaEntry("ifcstructuralsurfacetypeenum",nullptr )
+,		SchemaEntry("ifcpermeablecoveringoperationenum",nullptr )
+,		SchemaEntry("ifcfontweight",nullptr )
+,		SchemaEntry("ifcphmeasure",nullptr )
+,		SchemaEntry("ifcdescriptivemeasure",nullptr )
+,		SchemaEntry("ifccurvestylefontselect",nullptr )
+,		SchemaEntry("ifcunit",nullptr )
+,		SchemaEntry("ifchatchlinedistanceselect",nullptr )
+,		SchemaEntry("ifctextstyleselect",nullptr )
+,		SchemaEntry("ifcmetricvalueselect",nullptr )
+,		SchemaEntry("ifcvectorordirection",nullptr )
+,		SchemaEntry("ifcassemblyplaceenum",nullptr )
+,		SchemaEntry("ifcairterminaltypeenum",nullptr )
+,		SchemaEntry("ifccoveringtypeenum",nullptr )
+,		SchemaEntry("ifcplanarforcemeasure",nullptr )
+,		SchemaEntry("ifcvalvetypeenum",nullptr )
+,		SchemaEntry("ifcalarmtypeenum",nullptr )
+,		SchemaEntry("ifcdynamicviscositymeasure",nullptr )
+,		SchemaEntry("ifccurrencyenum",nullptr )
+,		SchemaEntry("ifcmodulusofrotationalsubgradereactionmeasure",nullptr )
+,		SchemaEntry("ifccablecarrierfittingtypeenum",nullptr )
+,		SchemaEntry("ifcboolean",nullptr )
+,		SchemaEntry("ifcactionsourcetypeenum",nullptr )
+,		SchemaEntry("ifcstructuralactivityassignmentselect",nullptr )
+,		SchemaEntry("ifcdistributionchamberelementtypeenum",nullptr )
+,		SchemaEntry("ifcevaporativecoolertypeenum",nullptr )
+,		SchemaEntry("ifcmagneticfluxdensitymeasure",nullptr )
+,		SchemaEntry("ifclightdistributiondatasourceselect",nullptr )
+,		SchemaEntry("ifctubebundletypeenum",nullptr )
+,		SchemaEntry("ifcaccelerationmeasure",nullptr )
+,		SchemaEntry("ifcboilertypeenum",nullptr )
+,		SchemaEntry("ifcramptypeenum",nullptr )
+,		SchemaEntry("ifcluminousintensitydistributionmeasure",nullptr )
+,		SchemaEntry("ifctrimmingpreference",nullptr )
+,		SchemaEntry("ifcspecificheatcapacitymeasure",nullptr )
+,		SchemaEntry("ifcamountofsubstancemeasure",nullptr )
+,		SchemaEntry("ifcroleenum",nullptr )
+,		SchemaEntry("ifcdocumentconfidentialityenum",nullptr )
+,		SchemaEntry("ifcfrequencymeasure",nullptr )
+,		SchemaEntry("ifcsectiontypeenum",nullptr )
+,		SchemaEntry("ifcelementassemblytypeenum",nullptr )
+,		SchemaEntry("ifcfootingtypeenum",nullptr )
+,		SchemaEntry("ifclayereditem",nullptr )
+,		SchemaEntry("ifccablesegmenttypeenum",nullptr )
+,		SchemaEntry("ifcdefinedsymbolselect",nullptr )
+,		SchemaEntry("ifcbuildingelementproxytypeenum",nullptr )
+,		SchemaEntry("ifcelectricgeneratortypeenum",nullptr )
+,		SchemaEntry("ifcrotationalstiffnessmeasure",nullptr )
+,		SchemaEntry("ifcspaceheatertypeenum",nullptr )
+,		SchemaEntry("ifcareameasure",nullptr )
+,		SchemaEntry("ifclabel",nullptr )
+,		SchemaEntry("ifccostscheduletypeenum",nullptr )
+,		SchemaEntry("ifcswitchingdevicetypeenum",nullptr )
+,		SchemaEntry("ifcelectrictimecontroltypeenum",nullptr )
+,		SchemaEntry("ifcfiltertypeenum",nullptr )
+,		SchemaEntry("ifcpositivelengthmeasure",nullptr )
+,		SchemaEntry("ifcnullstyle",nullptr )
+,		SchemaEntry("ifcconditioncriterionselect",nullptr )
+,		SchemaEntry("ifcshearmodulusmeasure",nullptr )
+,		SchemaEntry("ifcnormalisedratiomeasure",nullptr )
+,		SchemaEntry("ifcdoorpaneloperationenum",nullptr )
+,		SchemaEntry("ifcpointorvertexpoint",nullptr )
+,		SchemaEntry("ifcrooftypeenum",nullptr )
+,		SchemaEntry("ifccountmeasure",nullptr )
+,		SchemaEntry("ifcelectricconductancemeasure",nullptr )
+,		SchemaEntry("ifcproceduretypeenum",nullptr )
+,		SchemaEntry("ifcflowinstrumenttypeenum",nullptr )
+,		SchemaEntry("ifcelectricmotortypeenum",nullptr )
+,		SchemaEntry("ifcsurfaceside",nullptr )
+,		SchemaEntry("ifcstructuralcurvetypeenum",nullptr )
+,		SchemaEntry("ifccondensertypeenum",nullptr )
+,		SchemaEntry("ifclinearstiffnessmeasure",nullptr )
+,		SchemaEntry("ifcunitenum",nullptr )
+,		SchemaEntry("ifcoccupanttypeenum",nullptr )
+,		SchemaEntry("ifcthermalloadtypeenum",nullptr )
+,		SchemaEntry("ifcreinforcingbarroleenum",nullptr )
+,		SchemaEntry("ifcbenchmarkenum",nullptr )
+,		SchemaEntry("ifcpositiveplaneanglemeasure",nullptr )
+,		SchemaEntry("ifctexttransformation",nullptr )
+,		SchemaEntry("ifcdraughtingcalloutelement",nullptr )
+,		SchemaEntry("ifcratiomeasure",nullptr )
+,		SchemaEntry("ifcsolidanglemeasure",nullptr )
+,		SchemaEntry("ifcpipesegmenttypeenum",nullptr )
+,		SchemaEntry("ifccablecarriersegmenttypeenum",nullptr )
+,		SchemaEntry("ifccolourorfactor",nullptr )
+,		SchemaEntry("ifcidentifier",nullptr )
+,		SchemaEntry("ifctendontypeenum",nullptr )
+,		SchemaEntry("ifccontrollertypeenum",nullptr )
+,		SchemaEntry("ifcradioactivitymeasure",nullptr )
+,		SchemaEntry("ifctimemeasure",nullptr )
+,		SchemaEntry("ifcpumptypeenum",nullptr )
+,		SchemaEntry("ifcelectricheatertypeenum",nullptr )
+,		SchemaEntry("ifcbeamtypeenum",nullptr )
+,		SchemaEntry("ifcstateenum",nullptr )
+,		SchemaEntry("ifcsiprefix",nullptr )
+,		SchemaEntry("ifcnumericmeasure",nullptr )
+,		SchemaEntry("ifcoutlettypeenum",nullptr )
+,		SchemaEntry("ifccompoundplaneanglemeasure",nullptr )
+,		SchemaEntry("ifcservicelifefactortypeenum",nullptr )
+,		SchemaEntry("ifclogicaloperatorenum",nullptr )
+,		SchemaEntry("ifcbooleanoperand",nullptr )
+,		SchemaEntry("ifcobjectreferenceselect",nullptr )
+,		SchemaEntry("ifccooledbeamtypeenum",nullptr )
+,		SchemaEntry("ifcductsilencertypeenum",nullptr )
+,		SchemaEntry("ifcsectionalareaintegralmeasure",nullptr )
+,		SchemaEntry("ifcfontvariant",nullptr )
+,		SchemaEntry("ifcvolumetricflowratemeasure",nullptr )
+,		SchemaEntry("ifcplatetypeenum",nullptr )
+,		SchemaEntry("ifcenvironmentalimpactcategoryenum",nullptr )
+,		SchemaEntry("ifcvibrationisolatortypeenum",nullptr )
+,		SchemaEntry("ifcthermodynamictemperaturemeasure",nullptr )
+,		SchemaEntry("ifcrotationalmassmeasure",nullptr )
+,		SchemaEntry("ifcsecondinminute",nullptr )
+,		SchemaEntry("ifcdayinmonthnumber",nullptr )
+,		SchemaEntry("ifcdimensioncount",nullptr )
+,		SchemaEntry("ifcwindowstyleoperationenum",nullptr )
+,		SchemaEntry("ifcthermalresistancemeasure",nullptr )
+,		SchemaEntry("ifcmeasurevalue",nullptr )
+,		SchemaEntry("ifcwindowpaneloperationenum",nullptr )
+,		SchemaEntry("ifcchillertypeenum",nullptr )
+,		SchemaEntry("ifcpositiveratiomeasure",nullptr )
+,		SchemaEntry("ifcinteger",nullptr )
+,		SchemaEntry("ifclogical",nullptr )
+,		SchemaEntry("ifcjunctionboxtypeenum",nullptr )
+,		SchemaEntry("ifcaddresstypeenum",nullptr )
+,		SchemaEntry("ifcwasteterminaltypeenum",nullptr )
+,		SchemaEntry("ifctrimmingselect",nullptr )
+,		SchemaEntry("ifclightemissionsourceenum",nullptr )
+,		SchemaEntry("ifcsoundscaleenum",nullptr )
+,		SchemaEntry("ifcluminousfluxmeasure",nullptr )
+,		SchemaEntry("ifcelectricresistancemeasure",nullptr )
+,		SchemaEntry("ifcintegercountratemeasure",nullptr )
+,		SchemaEntry("ifcphysicalorvirtualenum",nullptr )
+,		SchemaEntry("ifcmolecularweightmeasure",nullptr )
+,		SchemaEntry("ifcprofiletypeenum",nullptr )
+,		SchemaEntry("ifcboxalignment",nullptr )
+,		SchemaEntry("ifcglobalorlocalenum",nullptr )
+,		SchemaEntry("ifcspecularroughness",nullptr )
+,		SchemaEntry("ifclamptypeenum",nullptr )
+,		SchemaEntry("ifcpiletypeenum",nullptr )
+,		SchemaEntry("ifcelectriccurrentmeasure",nullptr )
+,		SchemaEntry("ifcfantypeenum",nullptr )
+,		SchemaEntry("ifcsurfaceorfacesurface",nullptr )
+,		SchemaEntry("ifcpipefittingtypeenum",nullptr )
+,		SchemaEntry("ifctanktypeenum",nullptr )
+,		SchemaEntry("ifccurvefontorscaledcurvefontselect",nullptr )
+,		SchemaEntry("ifcwindowstyleconstructionenum",nullptr )
+,		SchemaEntry("ifcairterminalboxtypeenum",nullptr )
+,		SchemaEntry("ifcstairflighttypeenum",nullptr )
+,		SchemaEntry("ifcluminousintensitymeasure",nullptr )
+,		SchemaEntry("ifcmotorconnectiontypeenum",nullptr )
+,		SchemaEntry("ifcplaneanglemeasure",nullptr )
+,		SchemaEntry("ifcactuatortypeenum",nullptr )
+,		SchemaEntry("ifccolumntypeenum",nullptr )
+,		SchemaEntry("ifctextfontselect",nullptr )
+,		SchemaEntry("ifcdoorpanelpositionenum",nullptr )
+,		SchemaEntry("ifccoiltypeenum",nullptr )
+,		SchemaEntry("ifcangularvelocitymeasure",nullptr )
+,		SchemaEntry("ifcanalysismodeltypeenum",nullptr )
+,		SchemaEntry("ifclibraryselect",nullptr )
+,		SchemaEntry("ifcforcemeasure",nullptr )
+,		SchemaEntry("ifcfillareastyletileshapeselect",nullptr )
+,		SchemaEntry("ifcelectricappliancetypeenum",nullptr )
+,		SchemaEntry("ifcsurfacetextureenum",nullptr )
+,		SchemaEntry("ifccharacterstyleselect",nullptr )
+,		SchemaEntry("ifcenergymeasure",nullptr )
+,		SchemaEntry("ifcreal",nullptr )
+,		SchemaEntry("ifccompressortypeenum",nullptr )
+,		SchemaEntry("ifcelectricdistributionpointfunctionenum",nullptr )
 ,		SchemaEntry("ifcroot",&STEP::ObjectHelper<IfcRoot,4>::Construct )
 ,		SchemaEntry("ifcroot",&STEP::ObjectHelper<IfcRoot,4>::Construct )
 ,		SchemaEntry("ifcobjectdefinition",&STEP::ObjectHelper<IfcObjectDefinition,0>::Construct )
 ,		SchemaEntry("ifcobjectdefinition",&STEP::ObjectHelper<IfcObjectDefinition,0>::Construct )
 ,		SchemaEntry("ifctypeobject",&STEP::ObjectHelper<IfcTypeObject,2>::Construct )
 ,		SchemaEntry("ifctypeobject",&STEP::ObjectHelper<IfcTypeObject,2>::Construct )

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

@@ -71,7 +71,7 @@ aiMesh* TempMesh::ToMesh()
     ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(),mVertcnt.end(),size_t(0)));
     ai_assert(mVerts.size() == std::accumulate(mVertcnt.begin(),mVertcnt.end(),size_t(0)));
 
 
     if (mVerts.empty()) {
     if (mVerts.empty()) {
-        return NULL;
+        return nullptr;
     }
     }
 
 
     std::unique_ptr<aiMesh> mesh(new aiMesh());
     std::unique_ptr<aiMesh> mesh(new aiMesh());
@@ -162,7 +162,7 @@ void TempMesh::RemoveDegenerates()
     }
     }
 
 
     if(drop) {
     if(drop) {
-        IFCImporter::LogDebug("removing degenerate faces");
+        IFCImporter::LogVerboseDebug("removing degenerate faces");
     }
     }
 }
 }
 
 
@@ -437,7 +437,7 @@ void TempMesh::RemoveAdjacentDuplicates() {
         base += cnt;
         base += cnt;
     }
     }
     if(drop) {
     if(drop) {
-        IFCImporter::LogDebug("removing duplicate vertices");
+        IFCImporter::LogVerboseDebug("removing duplicate vertices");
     }
     }
 }
 }
 
 

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

@@ -201,7 +201,7 @@ struct ConversionData
 
 
     struct MeshCacheIndex {
     struct MeshCacheIndex {
         const IFC::Schema_2x3::IfcRepresentationItem* item; unsigned int matindex;
         const IFC::Schema_2x3::IfcRepresentationItem* item; unsigned int matindex;
-        MeshCacheIndex() : item(NULL), matindex(0) { }
+        MeshCacheIndex() : item(nullptr), matindex(0) { }
         MeshCacheIndex(const IFC::Schema_2x3::IfcRepresentationItem* i, unsigned int mi) : item(i), matindex(mi) { }
         MeshCacheIndex(const IFC::Schema_2x3::IfcRepresentationItem* i, unsigned int mi) : item(i), matindex(mi) { }
         bool operator == (const MeshCacheIndex& o) const { return item == o.item && matindex == o.matindex; }
         bool operator == (const MeshCacheIndex& o) const { return item == o.item && matindex == o.matindex; }
         bool operator < (const MeshCacheIndex& o) const { return item < o.item || (item == o.item && matindex < o.matindex); }
         bool operator < (const MeshCacheIndex& o) const { return item < o.item || (item == o.item && matindex < o.matindex); }

Різницю між файлами не показано, бо вона завелика
+ 365 - 397
code/AssetLib/Irr/IRRLoader.cpp


+ 3 - 2
code/AssetLib/Irr/IRRMeshLoader.cpp

@@ -139,8 +139,9 @@ void IRRMeshImporter::InternReadFile( const std::string& pFile,
     std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
     std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
 
 
     // Check whether we can read from the file
     // Check whether we can read from the file
-    if( file.get() == NULL)
-        throw DeadlyImportError( "Failed to open IRRMESH file " + pFile + "");
+    if (file.get() == nullptr) {
+        throw DeadlyImportError("Failed to open IRRMESH file " + pFile + ".");
+    }
 
 
     // Construct the irrXML parser
     // Construct the irrXML parser
     CIrrXML_IOStreamReader st(file.get());
     CIrrXML_IOStreamReader st(file.get());

+ 2 - 2
code/AssetLib/LWO/LWOAnimation.cpp

@@ -538,11 +538,11 @@ void AnimResolver::GetKeys(std::vector<aiVectorKey> &out,
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Extract animation channel
 // Extract animation channel
 void AnimResolver::ExtractAnimChannel(aiNodeAnim **out, unsigned int /*= 0*/) {
 void AnimResolver::ExtractAnimChannel(aiNodeAnim **out, unsigned int /*= 0*/) {
-    *out = NULL;
+    *out = nullptr;
 
 
     //FIXME: crashes if more than one component is animated at different timings, to be resolved.
     //FIXME: crashes if more than one component is animated at different timings, to be resolved.
 
 
-    // If we have no envelopes, return NULL
+    // If we have no envelopes, return nullptr
     if (envelopes.empty()) {
     if (envelopes.empty()) {
         return;
         return;
     }
     }

+ 2 - 2
code/AssetLib/LWO/LWOAnimation.h

@@ -211,7 +211,7 @@ public:
     // ------------------------------------------------------------------
     // ------------------------------------------------------------------
     /** @brief Extract a node animation channel
     /** @brief Extract a node animation channel
      *  @param out Receives a pointer to a newly allocated node anim.
      *  @param out Receives a pointer to a newly allocated node anim.
-     *    If there's just one keyframe defined, *out is set to NULL and
+     *    If there's just one keyframe defined, *out is set to nullptr and
      *    no animation channel is computed.
      *    no animation channel is computed.
      *  @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
      *  @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
      */
      */
@@ -261,7 +261,7 @@ protected:
      *  @param envl_y Y-component envelope
      *  @param envl_y Y-component envelope
      *  @param envl_z Z-component envelope
      *  @param envl_z Z-component envelope
      *  @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
      *  @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags.
-     *  @note Up to two input envelopes may be NULL
+     *  @note Up to two input envelopes may be nullptr
      */
      */
     void GetKeys(std::vector<aiVectorKey>& out,
     void GetKeys(std::vector<aiVectorKey>& out,
         LWO::Envelope* envl_x,
         LWO::Envelope* envl_x,

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

@@ -255,7 +255,7 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
 
 
     mSurfaces->push_back( LWO::Surface () );
     mSurfaces->push_back( LWO::Surface () );
     LWO::Surface& surf = mSurfaces->back();
     LWO::Surface& surf = mSurfaces->back();
-    LWO::Texture* pTex = NULL;
+    LWO::Texture *pTex = nullptr;
 
 
     GetS0(surf.mName,size);
     GetS0(surf.mName,size);
     bool running = true;
     bool running = true;

+ 2 - 2
code/AssetLib/LWO/LWOLoader.cpp

@@ -422,7 +422,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
                     // So we use a separate implementation.
                     // So we use a separate implementation.
                     ComputeNormals(mesh, smoothingGroups, _mSurfaces[j]);
                     ComputeNormals(mesh, smoothingGroups, _mSurfaces[j]);
                 } else {
                 } else {
-                    ASSIMP_LOG_DEBUG("LWO2: No need to compute normals, they're already there");
+                    ASSIMP_LOG_VERBOSE_DEBUG("LWO2: No need to compute normals, they're already there");
                 }
                 }
                 ++p;
                 ++p;
             }
             }
@@ -917,7 +917,7 @@ inline void CreateNewEntry(std::vector<T> &list, unsigned int srcIdx) {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry *base, unsigned int numRead,
 inline void LWOImporter::DoRecursiveVMAPAssignment(VMapEntry *base, unsigned int numRead,
         unsigned int idx, float *data) {
         unsigned int idx, float *data) {
-    ai_assert(NULL != data);
+    ai_assert(nullptr != data);
     LWO::ReferrerList &refList = mCurLayer->mPointReferrers;
     LWO::ReferrerList &refList = mCurLayer->mPointReferrers;
     unsigned int i;
     unsigned int i;
 
 

+ 1 - 1
code/AssetLib/LWO/LWOLoader.h

@@ -305,7 +305,7 @@ private:
     /** Add children to a node
     /** Add children to a node
      *  @param node Node to become a father
      *  @param node Node to become a father
      *  @param parent Index of the node
      *  @param parent Index of the node
-     *  @param apcNodes Flat list of nodes - used nodes are set to NULL.
+     *  @param apcNodes Flat list of nodes - used nodes are set to nullptr.
     */
     */
     void AddChildren(aiNode* node, uint16_t parent,
     void AddChildren(aiNode* node, uint16_t parent,
         std::vector<aiNode*>& apcNodes);
         std::vector<aiNode*>& apcNodes);

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

@@ -79,7 +79,7 @@ inline aiTextureMapMode GetMapMode(LWO::Texture::Wrap in) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTextureType type) {
 bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTextureType type) {
-    ai_assert(NULL != pcMat);
+    ai_assert(nullptr != pcMat);
 
 
     unsigned int cur = 0, temp = 0;
     unsigned int cur = 0, temp = 0;
     aiString s;
     aiString s;
@@ -154,7 +154,7 @@ bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTex
                 static_assert(sizeof(aiUVTransform) / sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5");
                 static_assert(sizeof(aiUVTransform) / sizeof(ai_real) == 5, "sizeof(aiUVTransform)/sizeof(ai_real) == 5");
                 pcMat->AddProperty(&trafo, 1, AI_MATKEY_UVTRANSFORM(type, cur));
                 pcMat->AddProperty(&trafo, 1, AI_MATKEY_UVTRANSFORM(type, cur));
             }
             }
-            ASSIMP_LOG_DEBUG("LWO2: Setting up non-UV mapping");
+            ASSIMP_LOG_VERBOSE_DEBUG("LWO2: Setting up non-UV mapping");
         }
         }
 
 
         // The older LWOB format does not use indirect references to clips.
         // The older LWOB format does not use indirect references to clips.
@@ -603,7 +603,7 @@ void LWOImporter::LoadLWO2TextureBlock(LE_NCONST IFF::SubChunkHeader *head, unsi
     }
     }
 
 
     // get the destination channel
     // get the destination channel
-    TextureList *listRef = NULL;
+    TextureList *listRef = nullptr;
     switch (tex.type) {
     switch (tex.type) {
         case AI_LWO_COLR:
         case AI_LWO_COLR:
             listRef = &surf.mColorTextures;
             listRef = &surf.mColorTextures;

+ 4 - 4
code/AssetLib/LWS/LWSLoader.cpp

@@ -101,7 +101,7 @@ void LWS::Element::Parse(const char *&buffer) {
         SkipSpaces(&buffer);
         SkipSpaces(&buffer);
 
 
         if (children.back().tokens[0] == "Plugin") {
         if (children.back().tokens[0] == "Plugin") {
-            ASSIMP_LOG_DEBUG("LWS: Skipping over plugin-specific data");
+            ASSIMP_LOG_VERBOSE_DEBUG("LWS: Skipping over plugin-specific data");
 
 
             // strange stuff inside Plugin/Endplugin blocks. Needn't
             // strange stuff inside Plugin/Endplugin blocks. Needn't
             // follow LWS syntax, so we skip over it
             // follow LWS syntax, so we skip over it
@@ -342,7 +342,7 @@ void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vector<Attachm
     if (src.type == LWS::NodeDesc::OBJECT) {
     if (src.type == LWS::NodeDesc::OBJECT) {
 
 
         // If the object is from an external file, get it
         // If the object is from an external file, get it
-        aiScene *obj = NULL;
+        aiScene *obj = nullptr;
         if (src.path.length()) {
         if (src.path.length()) {
             obj = batch.GetImport(src.id);
             obj = batch.GetImport(src.id);
             if (!obj) {
             if (!obj) {
@@ -359,7 +359,7 @@ void LWSImporter::BuildGraph(aiNode *nd, LWS::NodeDesc &src, std::vector<Attachm
 
 
                     //Remove first node from obj (the old pivot), reset transform of second node (the mesh node)
                     //Remove first node from obj (the old pivot), reset transform of second node (the mesh node)
                     aiNode *newRootNode = obj->mRootNode->mChildren[0];
                     aiNode *newRootNode = obj->mRootNode->mChildren[0];
-                    obj->mRootNode->mChildren[0] = NULL;
+                    obj->mRootNode->mChildren[0] = nullptr;
                     delete obj->mRootNode;
                     delete obj->mRootNode;
 
 
                     obj->mRootNode = newRootNode;
                     obj->mRootNode = newRootNode;
@@ -600,7 +600,7 @@ void LWSImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
                 d.number = cur_object++;
                 d.number = cur_object++;
             }
             }
             std::string path = FindLWOFile(c);
             std::string path = FindLWOFile(c);
-            d.id = batch.AddLoadRequest(path, 0, NULL);
+            d.id = batch.AddLoadRequest(path, 0, nullptr);
 
 
             d.path = path;
             d.path = path;
             nodes.push_back(d);
             nodes.push_back(d);

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

@@ -84,7 +84,19 @@ public:
  */
  */
 struct NodeDesc {
 struct NodeDesc {
     NodeDesc() :
     NodeDesc() :
-            type(), id(), number(0), parent(0), name(""), isPivotSet(false), lightColor(1.f, 1.f, 1.f), lightIntensity(1.f), lightType(0), lightFalloffType(0), lightConeAngle(45.f), lightEdgeAngle(), parent_resolved(NULL) {}
+            type(),
+            id(),
+            number(0),
+            parent(0),
+            name(""),
+            isPivotSet(false),
+            lightColor(1.f, 1.f, 1.f),
+            lightIntensity(1.f),
+            lightType(0),
+            lightFalloffType(0),
+            lightConeAngle(45.f),
+            lightEdgeAngle(),
+            parent_resolved(nullptr) {}
 
 
     enum {
     enum {
 
 

+ 4 - 4
code/AssetLib/M3D/M3DExporter.cpp

@@ -181,7 +181,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
             }
             }
             m3d->material[mi].name = SafeStr(name, true);
             m3d->material[mi].name = SafeStr(name, true);
             m3d->material[mi].numprop = 0;
             m3d->material[mi].numprop = 0;
-            m3d->material[mi].prop = NULL;
+            m3d->material[mi].prop = nullptr;
             // iterate through the material property table and see what we got
             // iterate through the material property table and see what we got
             for (k = 0; k < 15; k++) {
             for (k = 0; k < 15; k++) {
                 unsigned int j;
                 unsigned int j;
@@ -229,8 +229,8 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
                 }
                 }
                 if (aiTxProps[k].pKey &&
                 if (aiTxProps[k].pKey &&
                         mat->GetTexture((aiTextureType)aiTxProps[k].type,
                         mat->GetTexture((aiTextureType)aiTxProps[k].type,
-                                aiTxProps[k].index, &name, NULL, NULL, NULL,
-                                NULL, NULL) == AI_SUCCESS) {
+                                aiTxProps[k].index, &name, nullptr, nullptr, nullptr,
+                                nullptr, nullptr) == AI_SUCCESS) {
                     unsigned int i;
                     unsigned int i;
                     for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++)
                     for (j = name.length - 1; j > 0 && name.data[j] != '.'; j++)
                         ;
                         ;
@@ -259,7 +259,7 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
                         m3d->texture[i].name = fn;
                         m3d->texture[i].name = fn;
                         m3d->texture[i].w = 0;
                         m3d->texture[i].w = 0;
                         m3d->texture[i].h = 0;
                         m3d->texture[i].h = 0;
-                        m3d->texture[i].d = NULL;
+                        m3d->texture[i].d = nullptr;
                     }
                     }
                     addProp(&m3d->material[mi],
                     addProp(&m3d->material[mi],
                             m3d_propertytypes[k].id + 128, i);
                             m3d_propertytypes[k].id + 128, i);

+ 4 - 2
code/AssetLib/M3D/M3DImporter.cpp

@@ -618,8 +618,10 @@ aiColor4D M3DImporter::mkColor(uint32_t c) {
 void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) {
 void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned int posid, unsigned int orientid) {
     ai_assert(m != nullptr);
     ai_assert(m != nullptr);
     ai_assert(m3d);
     ai_assert(m3d);
-    ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex);
-    ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex);
+    ai_assert(posid != M3D_UNDEF);
+    ai_assert(posid < m3d->numvertex);
+    ai_assert(orientid != M3D_UNDEF);
+    ai_assert(orientid < m3d->numvertex);
     if (!m3d->numvertex || !m3d->vertex)
     if (!m3d->numvertex || !m3d->vertex)
         return;
         return;
     m3dv_t *p = &m3d->vertex[posid];
     m3dv_t *p = &m3d->vertex[posid];

+ 12 - 12
code/AssetLib/M3D/M3DMaterials.h

@@ -71,14 +71,14 @@ static const aiMatProp aiProps[] = {
     { AI_MATKEY_OPACITY },                                      /* m3dp_d */
     { AI_MATKEY_OPACITY },                                      /* m3dp_d */
     { AI_MATKEY_SHADING_MODEL },                                /* m3dp_il */
     { AI_MATKEY_SHADING_MODEL },                                /* m3dp_il */
 
 
-    { NULL, 0, 0 },                                             /* m3dp_Pr */
+    { nullptr, 0, 0 },                                          /* m3dp_Pr */
     { AI_MATKEY_REFLECTIVITY },                                 /* m3dp_Pm */
     { AI_MATKEY_REFLECTIVITY },                                 /* m3dp_Pm */
-    { NULL, 0, 0 },                                             /* m3dp_Ps */
+    { nullptr, 0, 0 },                                          /* m3dp_Ps */
     { AI_MATKEY_REFRACTI },                                     /* m3dp_Ni */
     { AI_MATKEY_REFRACTI },                                     /* m3dp_Ni */
-    { NULL, 0, 0 },                                             /* m3dp_Nt */
-    { NULL, 0, 0 },
-    { NULL, 0, 0 },
-    { NULL, 0, 0 }
+    { nullptr, 0, 0 },                                          /* m3dp_Nt */
+    { nullptr, 0, 0 },
+    { nullptr, 0, 0 },
+    { nullptr, 0, 0 }
 };
 };
 
 
 /* --- Texture Map Properties ---   !!!!! must match m3d_propertytypes !!!!! */
 /* --- Texture Map Properties ---   !!!!! must match m3d_propertytypes !!!!! */
@@ -88,19 +88,19 @@ static const aiMatProp aiTxProps[] = {
     { AI_MATKEY_TEXTURE_SPECULAR(0) },                       /* m3dp_map_Ks */
     { AI_MATKEY_TEXTURE_SPECULAR(0) },                       /* m3dp_map_Ks */
     { AI_MATKEY_TEXTURE_SHININESS(0) },                      /* m3dp_map_Ns */
     { AI_MATKEY_TEXTURE_SHININESS(0) },                      /* m3dp_map_Ns */
     { AI_MATKEY_TEXTURE_EMISSIVE(0) },                       /* m3dp_map_Ke */
     { AI_MATKEY_TEXTURE_EMISSIVE(0) },                       /* m3dp_map_Ke */
-    { NULL, 0, 0 },                                          /* m3dp_map_Tf */
+    { nullptr, 0, 0 },                                       /* m3dp_map_Tf */
     { AI_MATKEY_TEXTURE_HEIGHT(0) },                         /* m3dp_bump */
     { AI_MATKEY_TEXTURE_HEIGHT(0) },                         /* m3dp_bump */
     { AI_MATKEY_TEXTURE_OPACITY(0) },                        /* m3dp_map_d */
     { AI_MATKEY_TEXTURE_OPACITY(0) },                        /* m3dp_map_d */
     { AI_MATKEY_TEXTURE_NORMALS(0) },                        /* m3dp_map_N */
     { AI_MATKEY_TEXTURE_NORMALS(0) },                        /* m3dp_map_N */
 
 
     { AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE_ROUGHNESS,0) },/* m3dp_map_Pr */
     { AI_MATKEY_TEXTURE(aiTextureType_DIFFUSE_ROUGHNESS,0) },/* m3dp_map_Pr */
     { AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) },        /* m3dp_map_Pm */
     { AI_MATKEY_TEXTURE(aiTextureType_METALNESS,0) },        /* m3dp_map_Pm */
-    { NULL, 0, 0 },                                          /* m3dp_map_Ps */
+    { nullptr, 0, 0 },                                       /* m3dp_map_Ps */
     { AI_MATKEY_TEXTURE(aiTextureType_REFLECTION,0) },       /* m3dp_map_Ni */
     { AI_MATKEY_TEXTURE(aiTextureType_REFLECTION,0) },       /* m3dp_map_Ni */
-    { NULL, 0, 0 },                                          /* m3dp_map_Nt */
-    { NULL, 0, 0 },
-    { NULL, 0, 0 },
-    { NULL, 0, 0 }
+    { nullptr, 0, 0 },                                       /* m3dp_map_Nt */
+    { nullptr, 0, 0 },
+    { nullptr, 0, 0 },
+    { nullptr, 0, 0 }
 };
 };
 
 
 #endif // AI_M3DMATERIALS_H_INC
 #endif // AI_M3DMATERIALS_H_INC

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

@@ -72,7 +72,7 @@ unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) {
     std::unique_ptr<Assimp::IOStream> pStream(
     std::unique_ptr<Assimp::IOStream> pStream(
             (reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
             (reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
     size_t fileSize = 0;
     size_t fileSize = 0;
-    unsigned char *data = NULL;
+    unsigned char *data = nullptr;
     // sometimes pStream is nullptr in a single-threaded scenario too for some reason
     // sometimes pStream is nullptr in a single-threaded scenario too for some reason
     // (should be an empty object returning nothing I guess)
     // (should be an empty object returning nothing I guess)
     if (pStream) {
     if (pStream) {

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

@@ -5071,7 +5071,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
             ptr += sprintf(ptr, "\r\n");
             ptr += sprintf(ptr, "\r\n");
         }
         }
         /* mathematical shapes face */
         /* mathematical shapes face */
-        if (model->numshape && model->numshape && !(flags & M3D_EXP_NOFACE)) {
+        if (model->numshape !(flags & M3D_EXP_NOFACE)) {
             for (j = 0; j < model->numshape; j++) {
             for (j = 0; j < model->numshape; j++) {
                 sn = _m3d_safestr(model->shape[j].name, 0);
                 sn = _m3d_safestr(model->shape[j].name, 0);
                 if (!sn) {
                 if (!sn) {

+ 6 - 5
code/AssetLib/MD2/MD2Loader.cpp

@@ -221,20 +221,21 @@ void MD2Importer::InternReadFile( const std::string& pFile,
     std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
     std::unique_ptr<IOStream> file( pIOHandler->Open( pFile));
 
 
     // Check whether we can read from the file
     // Check whether we can read from the file
-    if( file.get() == NULL)
-        throw DeadlyImportError( "Failed to open MD2 file " + pFile + "");
+    if (file.get() == nullptr) {
+        throw DeadlyImportError("Failed to open MD2 file " + pFile + "");
+    }
 
 
     // check whether the md3 file is large enough to contain
     // check whether the md3 file is large enough to contain
     // at least the file header
     // at least the file header
     fileSize = (unsigned int)file->FileSize();
     fileSize = (unsigned int)file->FileSize();
-    if( fileSize < sizeof(MD2::Header))
-        throw DeadlyImportError( "MD2 File is too small");
+    if (fileSize < sizeof(MD2::Header)) {
+        throw DeadlyImportError("MD2 File is too small");
+    }
 
 
     std::vector<uint8_t> mBuffer2(fileSize);
     std::vector<uint8_t> mBuffer2(fileSize);
     file->Read(&mBuffer2[0], 1, fileSize);
     file->Read(&mBuffer2[0], 1, fileSize);
     mBuffer = &mBuffer2[0];
     mBuffer = &mBuffer2[0];
 
 
-
     m_pcHeader = (BE_NCONST MD2::Header*)mBuffer;
     m_pcHeader = (BE_NCONST MD2::Header*)mBuffer;
 
 
 #ifdef AI_BUILD_BIG_ENDIAN
 #ifdef AI_BUILD_BIG_ENDIAN

Різницю між файлами не показано, бо вона завелика
+ 235 - 272
code/AssetLib/MD3/MD3Loader.cpp


+ 87 - 71
code/AssetLib/MD5/MD5Loader.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2020, assimp team
 Copyright (c) 2006-2020, assimp team
 
 
-
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -82,7 +80,15 @@ static const aiImporterDesc desc = {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 MD5Importer::MD5Importer() :
 MD5Importer::MD5Importer() :
-        mIOHandler(nullptr), mBuffer(), fileSize(), iLineNumber(), pScene(), bHadMD5Mesh(), bHadMD5Anim(), bHadMD5Camera(), configNoAutoLoad(false) {
+        mIOHandler(nullptr),
+        mBuffer(),
+        mFileSize(),
+        mLineNumber(),
+        mScene(),
+        mHadMD5Mesh(),
+        mHadMD5Anim(),
+        mHadMD5Camera(),
+        mCconfigNoAutoLoad(false) {
     // empty
     // empty
 }
 }
 
 
@@ -106,6 +112,7 @@ bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
         const char *tokens[] = { "MD5Version" };
         const char *tokens[] = { "MD5Version" };
         return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
         return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
     }
     }
+
     return false;
     return false;
 }
 }
 
 
@@ -119,16 +126,15 @@ const aiImporterDesc *MD5Importer::GetInfo() const {
 // Setup import properties
 // Setup import properties
 void MD5Importer::SetupProperties(const Importer *pImp) {
 void MD5Importer::SetupProperties(const Importer *pImp) {
     // AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD
     // AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD
-    configNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0));
+    mCconfigNoAutoLoad = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_MD5_NO_ANIM_AUTOLOAD, 0));
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
 // Imports the given file into the given scene structure.
-void MD5Importer::InternReadFile(const std::string &pFile,
-        aiScene *_pScene, IOSystem *pIOHandler) {
+void MD5Importer::InternReadFile(const std::string &pFile, aiScene *_pScene, IOSystem *pIOHandler) {
     mIOHandler = pIOHandler;
     mIOHandler = pIOHandler;
-    pScene = _pScene;
-    bHadMD5Mesh = bHadMD5Anim = bHadMD5Camera = false;
+    mScene = _pScene;
+    mHadMD5Mesh = mHadMD5Anim = mHadMD5Camera = false;
 
 
     // remove the file extension
     // remove the file extension
     const std::string::size_type pos = pFile.find_last_of('.');
     const std::string::size_type pos = pFile.find_last_of('.');
@@ -138,7 +144,7 @@ void MD5Importer::InternReadFile(const std::string &pFile,
     try {
     try {
         if (extension == "md5camera") {
         if (extension == "md5camera") {
             LoadMD5CameraFile();
             LoadMD5CameraFile();
-        } else if (configNoAutoLoad || extension == "md5anim") {
+        } else if (mCconfigNoAutoLoad || extension == "md5anim") {
             // determine file extension and process just *one* file
             // determine file extension and process just *one* file
             if (extension.length() == 0) {
             if (extension.length() == 0) {
                 throw DeadlyImportError("Failure, need file extension to determine MD5 part type");
                 throw DeadlyImportError("Failure, need file extension to determine MD5 part type");
@@ -158,17 +164,17 @@ void MD5Importer::InternReadFile(const std::string &pFile,
     }
     }
 
 
     // make sure we have at least one file
     // make sure we have at least one file
-    if (!bHadMD5Mesh && !bHadMD5Anim && !bHadMD5Camera) {
+    if (!mHadMD5Mesh && !mHadMD5Anim && !mHadMD5Camera) {
         throw DeadlyImportError("Failed to read valid contents out of this MD5* file");
         throw DeadlyImportError("Failed to read valid contents out of this MD5* file");
     }
     }
 
 
     // Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system
     // Now rotate the whole scene 90 degrees around the x axis to match our internal coordinate system
-    pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f,
+    mScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f,
             0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
             0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
 
 
     // the output scene wouldn't pass the validation without this flag
     // the output scene wouldn't pass the validation without this flag
-    if (!bHadMD5Mesh) {
-        pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
+    if (!mHadMD5Mesh) {
+        mScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
     }
     }
 
 
     // clean the instance -- the BaseImporter instance may be reused later.
     // clean the instance -- the BaseImporter instance may be reused later.
@@ -181,17 +187,17 @@ void MD5Importer::LoadFileIntoMemory(IOStream *file) {
     // unload the previous buffer, if any
     // unload the previous buffer, if any
     UnloadFileFromMemory();
     UnloadFileFromMemory();
 
 
-    ai_assert(NULL != file);
-    fileSize = (unsigned int)file->FileSize();
-    ai_assert(fileSize);
+    ai_assert(nullptr != file);
+    mFileSize = (unsigned int)file->FileSize();
+    ai_assert(mFileSize);
 
 
     // allocate storage and copy the contents of the file to a memory buffer
     // allocate storage and copy the contents of the file to a memory buffer
-    mBuffer = new char[fileSize + 1];
-    file->Read((void *)mBuffer, 1, fileSize);
-    iLineNumber = 1;
+    mBuffer = new char[mFileSize + 1];
+    file->Read((void *)mBuffer, 1, mFileSize);
+    mLineNumber = 1;
 
 
     // append a terminal 0
     // append a terminal 0
-    mBuffer[fileSize] = '\0';
+    mBuffer[mFileSize] = '\0';
 
 
     // now remove all line comments from the file
     // now remove all line comments from the file
     CommentRemover::RemoveLineComments("//", mBuffer, ' ');
     CommentRemover::RemoveLineComments("//", mBuffer, ' ');
@@ -202,8 +208,8 @@ void MD5Importer::LoadFileIntoMemory(IOStream *file) {
 void MD5Importer::UnloadFileFromMemory() {
 void MD5Importer::UnloadFileFromMemory() {
     // delete the file buffer
     // delete the file buffer
     delete[] mBuffer;
     delete[] mBuffer;
-    mBuffer = NULL;
-    fileSize = 0;
+    mBuffer = nullptr;
+    mFileSize = 0;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -243,7 +249,8 @@ void MD5Importer::MakeDataUnique(MD5::MeshDesc &meshSrc) {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Recursive node graph construction from a MD5MESH
 // Recursive node graph construction from a MD5MESH
 void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones) {
 void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &bones) {
-    ai_assert(NULL != piParent && !piParent->mNumChildren);
+    ai_assert(nullptr != piParent);
+    ai_assert(!piParent->mNumChildren);
 
 
     // First find out how many children we'll have
     // First find out how many children we'll have
     for (int i = 0; i < (int)bones.size(); ++i) {
     for (int i = 0; i < (int)bones.size(); ++i) {
@@ -293,7 +300,8 @@ void MD5Importer::AttachChilds_Mesh(int iParentID, aiNode *piParent, BoneList &b
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Recursive node graph construction from a MD5ANIM
 // Recursive node graph construction from a MD5ANIM
 void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneList &bones, const aiNodeAnim **node_anims) {
 void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneList &bones, const aiNodeAnim **node_anims) {
-    ai_assert(NULL != piParent && !piParent->mNumChildren);
+    ai_assert(nullptr != piParent);
+    ai_assert(!piParent->mNumChildren);
 
 
     // First find out how many children we'll have
     // First find out how many children we'll have
     for (int i = 0; i < (int)bones.size(); ++i) {
     for (int i = 0; i < (int)bones.size(); ++i) {
@@ -332,37 +340,37 @@ void MD5Importer::AttachChilds_Anim(int iParentID, aiNode *piParent, AnimBoneLis
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Load a MD5MESH file
 // Load a MD5MESH file
 void MD5Importer::LoadMD5MeshFile() {
 void MD5Importer::LoadMD5MeshFile() {
-    std::string pFile = mFile + "md5mesh";
-    std::unique_ptr<IOStream> file(mIOHandler->Open(pFile, "rb"));
+    std::string filename = mFile + "md5mesh";
+    std::unique_ptr<IOStream> file(mIOHandler->Open(filename, "rb"));
 
 
     // Check whether we can read from the file
     // Check whether we can read from the file
     if (file.get() == nullptr || !file->FileSize()) {
     if (file.get() == nullptr || !file->FileSize()) {
-        ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + pFile);
+        ASSIMP_LOG_WARN("Failed to access MD5MESH file: " + filename);
         return;
         return;
     }
     }
-    bHadMD5Mesh = true;
+    mHadMD5Mesh = true;
     LoadFileIntoMemory(file.get());
     LoadFileIntoMemory(file.get());
 
 
     // now construct a parser and parse the file
     // now construct a parser and parse the file
-    MD5::MD5Parser parser(mBuffer, fileSize);
+    MD5::MD5Parser parser(mBuffer, mFileSize);
 
 
     // load the mesh information from it
     // load the mesh information from it
     MD5::MD5MeshParser meshParser(parser.mSections);
     MD5::MD5MeshParser meshParser(parser.mSections);
 
 
     // create the bone hierarchy - first the root node and dummy nodes for all meshes
     // create the bone hierarchy - first the root node and dummy nodes for all meshes
-    pScene->mRootNode = new aiNode("<MD5_Root>");
-    pScene->mRootNode->mNumChildren = 2;
-    pScene->mRootNode->mChildren = new aiNode *[2];
+    mScene->mRootNode = new aiNode("<MD5_Root>");
+    mScene->mRootNode->mNumChildren = 2;
+    mScene->mRootNode->mChildren = new aiNode *[2];
 
 
     // build the hierarchy from the MD5MESH file
     // build the hierarchy from the MD5MESH file
-    aiNode *pcNode = pScene->mRootNode->mChildren[1] = new aiNode();
+    aiNode *pcNode = mScene->mRootNode->mChildren[1] = new aiNode();
     pcNode->mName.Set("<MD5_Hierarchy>");
     pcNode->mName.Set("<MD5_Hierarchy>");
-    pcNode->mParent = pScene->mRootNode;
+    pcNode->mParent = mScene->mRootNode;
     AttachChilds_Mesh(-1, pcNode, meshParser.mJoints);
     AttachChilds_Mesh(-1, pcNode, meshParser.mJoints);
 
 
-    pcNode = pScene->mRootNode->mChildren[0] = new aiNode();
+    pcNode = mScene->mRootNode->mChildren[0] = new aiNode();
     pcNode->mName.Set("<MD5_Mesh>");
     pcNode->mName.Set("<MD5_Mesh>");
-    pcNode->mParent = pScene->mRootNode;
+    pcNode->mParent = mScene->mRootNode;
 
 
 #if 0
 #if 0
     if (pScene->mRootNode->mChildren[1]->mNumChildren) /* start at the right hierarchy level */
     if (pScene->mRootNode->mChildren[1]->mNumChildren) /* start at the right hierarchy level */
@@ -371,28 +379,31 @@ void MD5Importer::LoadMD5MeshFile() {
 
 
     // FIX: MD5 files exported from Blender can have empty meshes
     // FIX: MD5 files exported from Blender can have empty meshes
     for (std::vector<MD5::MeshDesc>::const_iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) {
     for (std::vector<MD5::MeshDesc>::const_iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) {
-        if (!(*it).mFaces.empty() && !(*it).mVertices.empty())
-            ++pScene->mNumMaterials;
+        if (!(*it).mFaces.empty() && !(*it).mVertices.empty()) {
+            ++mScene->mNumMaterials;
+        }
     }
     }
 
 
     // generate all meshes
     // generate all meshes
-    pScene->mNumMeshes = pScene->mNumMaterials;
-    pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
-    pScene->mMaterials = new aiMaterial *[pScene->mNumMeshes];
+    mScene->mNumMeshes = mScene->mNumMaterials;
+    mScene->mMeshes = new aiMesh *[mScene->mNumMeshes];
+    mScene->mMaterials = new aiMaterial *[mScene->mNumMeshes];
 
 
     //  storage for node mesh indices
     //  storage for node mesh indices
-    pcNode->mNumMeshes = pScene->mNumMeshes;
+    pcNode->mNumMeshes = mScene->mNumMeshes;
     pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
     pcNode->mMeshes = new unsigned int[pcNode->mNumMeshes];
-    for (unsigned int m = 0; m < pcNode->mNumMeshes; ++m)
+    for (unsigned int m = 0; m < pcNode->mNumMeshes; ++m) {
         pcNode->mMeshes[m] = m;
         pcNode->mMeshes[m] = m;
+    }
 
 
     unsigned int n = 0;
     unsigned int n = 0;
     for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) {
     for (std::vector<MD5::MeshDesc>::iterator it = meshParser.mMeshes.begin(), end = meshParser.mMeshes.end(); it != end; ++it) {
         MD5::MeshDesc &meshSrc = *it;
         MD5::MeshDesc &meshSrc = *it;
-        if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty())
+        if (meshSrc.mFaces.empty() || meshSrc.mVertices.empty()) {
             continue;
             continue;
+        }
 
 
-        aiMesh *mesh = pScene->mMeshes[n] = new aiMesh();
+        aiMesh *mesh = mScene->mMeshes[n] = new aiMesh();
         mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
         mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
 
 
         // generate unique vertices in our internal verbose format
         // generate unique vertices in our internal verbose format
@@ -422,17 +433,19 @@ void MD5Importer::LoadMD5MeshFile() {
             for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) {
             for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) {
                 MD5::WeightDesc &weightDesc = meshSrc.mWeights[w];
                 MD5::WeightDesc &weightDesc = meshSrc.mWeights[w];
                 /* FIX for some invalid exporters */
                 /* FIX for some invalid exporters */
-                if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON))
+                if (!(weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON)) {
                     ++piCount[weightDesc.mBone];
                     ++piCount[weightDesc.mBone];
+                }
             }
             }
         }
         }
 
 
         // check how many we will need
         // check how many we will need
-        for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p)
+        for (unsigned int p = 0; p < meshParser.mJoints.size(); ++p) {
             if (piCount[p]) mesh->mNumBones++;
             if (piCount[p]) mesh->mNumBones++;
+        }
 
 
-        if (mesh->mNumBones) // just for safety
-        {
+        // just for safety
+        if (mesh->mNumBones) {
             mesh->mBones = new aiBone *[mesh->mNumBones];
             mesh->mBones = new aiBone *[mesh->mNumBones];
             for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) {
             for (unsigned int q = 0, h = 0; q < meshParser.mJoints.size(); ++q) {
                 if (!piCount[q]) continue;
                 if (!piCount[q]) continue;
@@ -457,8 +470,9 @@ void MD5Importer::LoadMD5MeshFile() {
 
 
                 // there are models which have weights which don't sum to 1 ...
                 // there are models which have weights which don't sum to 1 ...
                 ai_real fSum = 0.0;
                 ai_real fSum = 0.0;
-                for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w)
+                for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) {
                     fSum += meshSrc.mWeights[w].mWeight;
                     fSum += meshSrc.mWeights[w].mWeight;
+                }
                 if (!fSum) {
                 if (!fSum) {
                     ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0");
                     ASSIMP_LOG_ERROR("MD5MESH: The sum of all vertex bone weights is 0");
                     continue;
                     continue;
@@ -466,11 +480,12 @@ void MD5Importer::LoadMD5MeshFile() {
 
 
                 // process bone weights
                 // process bone weights
                 for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) {
                 for (unsigned int jub = (*iter).mFirstWeight, w = jub; w < jub + (*iter).mNumWeights; ++w) {
-                    if (w >= meshSrc.mWeights.size())
+                    if (w >= meshSrc.mWeights.size()) {
                         throw DeadlyImportError("MD5MESH: Invalid weight index");
                         throw DeadlyImportError("MD5MESH: Invalid weight index");
+                    }
 
 
                     MD5::WeightDesc &weightDesc = meshSrc.mWeights[w];
                     MD5::WeightDesc &weightDesc = meshSrc.mWeights[w];
-                    if (weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) {
+                    if (weightDesc.mWeight < AI_MD5_WEIGHT_EPSILON && weightDesc.mWeight >= -AI_MD5_WEIGHT_EPSILON) { 
                         continue;
                         continue;
                     }
                     }
 
 
@@ -504,12 +519,12 @@ void MD5Importer::LoadMD5MeshFile() {
         for (unsigned int c = 0; c < mesh->mNumFaces; ++c) {
         for (unsigned int c = 0; c < mesh->mNumFaces; ++c) {
             mesh->mFaces[c].mNumIndices = 3;
             mesh->mFaces[c].mNumIndices = 3;
             mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices;
             mesh->mFaces[c].mIndices = meshSrc.mFaces[c].mIndices;
-            meshSrc.mFaces[c].mIndices = NULL;
+            meshSrc.mFaces[c].mIndices = nullptr;
         }
         }
 
 
         // generate a material for the mesh
         // generate a material for the mesh
         aiMaterial *mat = new aiMaterial();
         aiMaterial *mat = new aiMaterial();
-        pScene->mMaterials[n] = mat;
+        mScene->mMaterials[n] = mat;
 
 
         // insert the typical doom3 textures:
         // insert the typical doom3 textures:
         // nnn_local.tga  - normal map
         // nnn_local.tga  - normal map
@@ -555,10 +570,11 @@ void MD5Importer::LoadMD5AnimFile() {
         ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile);
         ASSIMP_LOG_WARN("Failed to read MD5ANIM file: " + pFile);
         return;
         return;
     }
     }
+
     LoadFileIntoMemory(file.get());
     LoadFileIntoMemory(file.get());
 
 
     // parse the basic file structure
     // parse the basic file structure
-    MD5::MD5Parser parser(mBuffer, fileSize);
+    MD5::MD5Parser parser(mBuffer, mFileSize);
 
 
     // load the animation information from the parse tree
     // load the animation information from the parse tree
     MD5::MD5AnimParser animParser(parser.mSections);
     MD5::MD5AnimParser animParser(parser.mSections);
@@ -568,10 +584,10 @@ void MD5Importer::LoadMD5AnimFile() {
             animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) {
             animParser.mBaseFrames.size() != animParser.mAnimatedBones.size()) {
         ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded");
         ASSIMP_LOG_ERROR("MD5ANIM: No frames or animated bones loaded");
     } else {
     } else {
-        bHadMD5Anim = true;
+        mHadMD5Anim = true;
 
 
-        pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations = 1];
-        aiAnimation *anim = pScene->mAnimations[0] = new aiAnimation();
+        mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations = 1];
+        aiAnimation *anim = mScene->mAnimations[0] = new aiAnimation();
         anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size();
         anim->mNumChannels = (unsigned int)animParser.mAnimatedBones.size();
         anim->mChannels = new aiNodeAnim *[anim->mNumChannels];
         anim->mChannels = new aiNodeAnim *[anim->mNumChannels];
         for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
         for (unsigned int i = 0; i < anim->mNumChannels; ++i) {
@@ -637,15 +653,15 @@ void MD5Importer::LoadMD5AnimFile() {
 
 
         // If we didn't build the hierarchy yet (== we didn't load a MD5MESH),
         // If we didn't build the hierarchy yet (== we didn't load a MD5MESH),
         // construct it now from the data given in the MD5ANIM.
         // construct it now from the data given in the MD5ANIM.
-        if (!pScene->mRootNode) {
-            pScene->mRootNode = new aiNode();
-            pScene->mRootNode->mName.Set("<MD5_Hierarchy>");
+        if (!mScene->mRootNode) {
+            mScene->mRootNode = new aiNode();
+            mScene->mRootNode->mName.Set("<MD5_Hierarchy>");
 
 
-            AttachChilds_Anim(-1, pScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels);
+            AttachChilds_Anim(-1, mScene->mRootNode, animParser.mAnimatedBones, (const aiNodeAnim **)anim->mChannels);
 
 
             // Call SkeletonMeshBuilder to construct a mesh to represent the shape
             // Call SkeletonMeshBuilder to construct a mesh to represent the shape
-            if (pScene->mRootNode->mNumChildren) {
-                SkeletonMeshBuilder skeleton_maker(pScene, pScene->mRootNode->mChildren[0]);
+            if (mScene->mRootNode->mNumChildren) {
+                SkeletonMeshBuilder skeleton_maker(mScene, mScene->mRootNode->mChildren[0]);
             }
             }
         }
         }
     }
     }
@@ -661,11 +677,11 @@ void MD5Importer::LoadMD5CameraFile() {
     if (!file.get() || !file->FileSize()) {
     if (!file.get() || !file->FileSize()) {
         throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile);
         throw DeadlyImportError("Failed to read MD5CAMERA file: " + pFile);
     }
     }
-    bHadMD5Camera = true;
+    mHadMD5Camera = true;
     LoadFileIntoMemory(file.get());
     LoadFileIntoMemory(file.get());
 
 
     // parse the basic file structure
     // parse the basic file structure
-    MD5::MD5Parser parser(mBuffer, fileSize);
+    MD5::MD5Parser parser(mBuffer, mFileSize);
 
 
     // load the camera animation data from the parse tree
     // load the camera animation data from the parse tree
     MD5::MD5CameraParser cameraParser(parser.mSections);
     MD5::MD5CameraParser cameraParser(parser.mSections);
@@ -679,14 +695,14 @@ void MD5Importer::LoadMD5CameraFile() {
 
 
     // Construct output graph - a simple root with a dummy child.
     // Construct output graph - a simple root with a dummy child.
     // The root node performs the coordinate system conversion
     // The root node performs the coordinate system conversion
-    aiNode *root = pScene->mRootNode = new aiNode("<MD5CameraRoot>");
+    aiNode *root = mScene->mRootNode = new aiNode("<MD5CameraRoot>");
     root->mChildren = new aiNode *[root->mNumChildren = 1];
     root->mChildren = new aiNode *[root->mNumChildren = 1];
     root->mChildren[0] = new aiNode("<MD5Camera>");
     root->mChildren[0] = new aiNode("<MD5Camera>");
     root->mChildren[0]->mParent = root;
     root->mChildren[0]->mParent = root;
 
 
     // ... but with one camera assigned to it
     // ... but with one camera assigned to it
-    pScene->mCameras = new aiCamera *[pScene->mNumCameras = 1];
-    aiCamera *cam = pScene->mCameras[0] = new aiCamera();
+    mScene->mCameras = new aiCamera *[mScene->mNumCameras = 1];
+    aiCamera *cam = mScene->mCameras[0] = new aiCamera();
     cam->mName = "<MD5Camera>";
     cam->mName = "<MD5Camera>";
 
 
     // FIXME: Fov is currently set to the first frame's value
     // FIXME: Fov is currently set to the first frame's value
@@ -703,8 +719,8 @@ void MD5Importer::LoadMD5CameraFile() {
             cuts.push_back(static_cast<unsigned int>(frames.size() - 1));
             cuts.push_back(static_cast<unsigned int>(frames.size() - 1));
     }
     }
 
 
-    pScene->mNumAnimations = static_cast<unsigned int>(cuts.size() - 1);
-    aiAnimation **tmp = pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations];
+    mScene->mNumAnimations = static_cast<unsigned int>(cuts.size() - 1);
+    aiAnimation **tmp = mScene->mAnimations = new aiAnimation *[mScene->mNumAnimations];
     for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) {
     for (std::vector<unsigned int>::const_iterator it = cuts.begin(); it != cuts.end() - 1; ++it) {
 
 
         aiAnimation *anim = *tmp++ = new aiAnimation();
         aiAnimation *anim = *tmp++ = new aiAnimation();

+ 7 - 8
code/AssetLib/MD5/MD5Loader.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2020, assimp team
 Copyright (c) 2006-2020, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -156,25 +155,25 @@ protected:
     char *mBuffer;
     char *mBuffer;
 
 
     /** Size of the file */
     /** Size of the file */
-    unsigned int fileSize;
+    unsigned int mFileSize;
 
 
     /** Current line number. For debugging purposes */
     /** Current line number. For debugging purposes */
-    unsigned int iLineNumber;
+    unsigned int mLineNumber;
 
 
     /** Scene to be filled */
     /** Scene to be filled */
-    aiScene *pScene;
+    aiScene *mScene;
 
 
     /** true if a MD5MESH file has already been parsed */
     /** true if a MD5MESH file has already been parsed */
-    bool bHadMD5Mesh;
+    bool mHadMD5Mesh;
 
 
     /** true if a MD5ANIM file has already been parsed */
     /** true if a MD5ANIM file has already been parsed */
-    bool bHadMD5Anim;
+    bool mHadMD5Anim;
 
 
     /** true if a MD5CAMERA file has already been parsed */
     /** true if a MD5CAMERA file has already been parsed */
-    bool bHadMD5Camera;
+    bool mHadMD5Camera;
 
 
     /** configuration option: prevent anim autoload */
     /** configuration option: prevent anim autoload */
-    bool configNoAutoLoad;
+    bool mCconfigNoAutoLoad;
 };
 };
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp

+ 164 - 179
code/AssetLib/MD5/MD5Parser.cpp

@@ -45,25 +45,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the MD5 parser class
  *  @brief Implementation of the MD5 parser class
  */
  */
 
 
-
 // internal headers
 // internal headers
 #include "AssetLib/MD5/MD5Loader.h"
 #include "AssetLib/MD5/MD5Loader.h"
 #include "Material/MaterialSystem.h"
 #include "Material/MaterialSystem.h"
 
 
-#include <assimp/fast_atof.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/StringComparison.h>
 #include <assimp/StringComparison.h>
-#include <assimp/DefaultLogger.hpp>
+#include <assimp/fast_atof.h>
 #include <assimp/mesh.h>
 #include <assimp/mesh.h>
+#include <assimp/DefaultLogger.hpp>
 
 
 using namespace Assimp;
 using namespace Assimp;
 using namespace Assimp::MD5;
 using namespace Assimp::MD5;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Parse the segment structure fo a MD5 file
 // Parse the segment structure fo a MD5 file
-MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
-{
-    ai_assert(NULL != _buffer && 0 != _fileSize);
+MD5Parser::MD5Parser(char *_buffer, unsigned int _fileSize) {
+    ai_assert(nullptr != _buffer);
+    ai_assert(0 != _fileSize);
 
 
     buffer = _buffer;
     buffer = _buffer;
     fileSize = _fileSize;
     fileSize = _fileSize;
@@ -78,48 +77,45 @@ MD5Parser::MD5Parser(char* _buffer, unsigned int _fileSize )
     bool running = true;
     bool running = true;
     while (running) {
     while (running) {
         mSections.push_back(Section());
         mSections.push_back(Section());
-        Section& sec = mSections.back();
-        if(!ParseSection(sec))  {
+        Section &sec = mSections.back();
+        if (!ParseSection(sec)) {
             break;
             break;
         }
         }
     }
     }
 
 
-    if ( !DefaultLogger::isNullLogger())    {
+    if (!DefaultLogger::isNullLogger()) {
         char szBuffer[128]; // should be sufficiently large
         char szBuffer[128]; // should be sufficiently large
-        ::ai_snprintf(szBuffer,128,"MD5Parser end. Parsed %i sections",(int)mSections.size());
+        ::ai_snprintf(szBuffer, 128, "MD5Parser end. Parsed %i sections", (int)mSections.size());
         ASSIMP_LOG_DEBUG(szBuffer);
         ASSIMP_LOG_DEBUG(szBuffer);
     }
     }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Report error to the log stream
 // Report error to the log stream
-/*static*/ AI_WONT_RETURN void MD5Parser::ReportError (const char* error, unsigned int line)
-{
+/*static*/ AI_WONT_RETURN void MD5Parser::ReportError(const char *error, unsigned int line) {
     char szBuffer[1024];
     char szBuffer[1024];
-    ::ai_snprintf(szBuffer, 1024, "[MD5] Line %u: %s",line,error);
+    ::ai_snprintf(szBuffer, 1024, "[MD5] Line %u: %s", line, error);
     throw DeadlyImportError(szBuffer);
     throw DeadlyImportError(szBuffer);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Report warning to the log stream
 // Report warning to the log stream
-/*static*/ void MD5Parser::ReportWarning (const char* warn, unsigned int line)
-{
+/*static*/ void MD5Parser::ReportWarning(const char *warn, unsigned int line) {
     char szBuffer[1024];
     char szBuffer[1024];
-    ::sprintf(szBuffer,"[MD5] Line %u: %s",line,warn);
+    ::sprintf(szBuffer, "[MD5] Line %u: %s", line, warn);
     ASSIMP_LOG_WARN(szBuffer);
     ASSIMP_LOG_WARN(szBuffer);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Parse and validate the MD5 header
 // Parse and validate the MD5 header
-void MD5Parser::ParseHeader()
-{
+void MD5Parser::ParseHeader() {
     // parse and validate the file version
     // parse and validate the file version
     SkipSpaces();
     SkipSpaces();
-    if (!TokenMatch(buffer,"MD5Version",10))    {
+    if (!TokenMatch(buffer, "MD5Version", 10)) {
         ReportError("Invalid MD5 file: MD5Version tag has not been found");
         ReportError("Invalid MD5 file: MD5Version tag has not been found");
     }
     }
     SkipSpaces();
     SkipSpaces();
-    unsigned int iVer = ::strtoul10(buffer,(const char**)&buffer);
+    unsigned int iVer = ::strtoul10(buffer, (const char **)&buffer);
     if (10 != iVer) {
     if (10 != iVer) {
         ReportError("MD5 version tag is unknown (10 is expected)");
         ReportError("MD5 version tag is unknown (10 is expected)");
     }
     }
@@ -127,23 +123,24 @@ void MD5Parser::ParseHeader()
 
 
     // print the command line options to the console
     // print the command line options to the console
     // FIX: can break the log length limit, so we need to be careful
     // FIX: can break the log length limit, so we need to be careful
-    char* sz = buffer;
-    while (!IsLineEnd( *buffer++));
-    ASSIMP_LOG_INFO(std::string(sz,std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer-sz))));
+    char *sz = buffer;
+    while (!IsLineEnd(*buffer++))
+        ;
+    ASSIMP_LOG_INFO(std::string(sz, std::min((uintptr_t)MAX_LOG_MESSAGE_LENGTH, (uintptr_t)(buffer - sz))));
     SkipSpacesAndLineEnd();
     SkipSpacesAndLineEnd();
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Recursive MD5 parsing function
 // Recursive MD5 parsing function
-bool MD5Parser::ParseSection(Section& out)
-{
+bool MD5Parser::ParseSection(Section &out) {
     // store the current line number for use in error messages
     // store the current line number for use in error messages
     out.iLineNumber = lineNumber;
     out.iLineNumber = lineNumber;
 
 
     // first parse the name of the section
     // first parse the name of the section
-    char* sz = buffer;
-    while (!IsSpaceOrNewLine( *buffer))buffer++;
-    out.mName = std::string(sz,(uintptr_t)(buffer-sz));
+    char *sz = buffer;
+    while (!IsSpaceOrNewLine(*buffer))
+        buffer++;
+    out.mName = std::string(sz, (uintptr_t)(buffer - sz));
     SkipSpaces();
     SkipSpaces();
 
 
     bool running = true;
     bool running = true;
@@ -152,8 +149,7 @@ bool MD5Parser::ParseSection(Section& out)
             // it is a normal section so read all lines
             // it is a normal section so read all lines
             buffer++;
             buffer++;
             bool run = true;
             bool run = true;
-            while (run)
-            {
+            while (run) {
                 if (!SkipSpacesAndLineEnd()) {
                 if (!SkipSpacesAndLineEnd()) {
                     return false; // seems this was the last section
                     return false; // seems this was the last section
                 }
                 }
@@ -163,25 +159,26 @@ bool MD5Parser::ParseSection(Section& out)
                 }
                 }
 
 
                 out.mElements.push_back(Element());
                 out.mElements.push_back(Element());
-                Element& elem = out.mElements.back();
+                Element &elem = out.mElements.back();
 
 
                 elem.iLineNumber = lineNumber;
                 elem.iLineNumber = lineNumber;
                 elem.szStart = buffer;
                 elem.szStart = buffer;
 
 
                 // terminate the line with zero
                 // terminate the line with zero
-                while (!IsLineEnd( *buffer))buffer++;
+                while (!IsLineEnd(*buffer))
+                    buffer++;
                 if (*buffer) {
                 if (*buffer) {
                     ++lineNumber;
                     ++lineNumber;
                     *buffer++ = '\0';
                     *buffer++ = '\0';
                 }
                 }
             }
             }
             break;
             break;
-        }
-        else if (!IsSpaceOrNewLine(*buffer))    {
+        } else if (!IsSpaceOrNewLine(*buffer)) {
             // it is an element at global scope. Parse its value and go on
             // it is an element at global scope. Parse its value and go on
             sz = buffer;
             sz = buffer;
-            while (!IsSpaceOrNewLine( *buffer++));
-            out.mGlobalValue = std::string(sz,(uintptr_t)(buffer-sz));
+            while (!IsSpaceOrNewLine(*buffer++))
+                ;
+            out.mGlobalValue = std::string(sz, (uintptr_t)(buffer - sz));
             continue;
             continue;
         }
         }
         break;
         break;
@@ -193,161 +190,161 @@ bool MD5Parser::ParseSection(Section& out)
 // Some dirty macros just because they're so funny and easy to debug
 // Some dirty macros just because they're so funny and easy to debug
 
 
 // skip all spaces ... handle EOL correctly
 // skip all spaces ... handle EOL correctly
-#define AI_MD5_SKIP_SPACES()  if(!SkipSpaces(&sz)) \
-    MD5Parser::ReportWarning("Unexpected end of line",elem.iLineNumber);
-
-	// read a triple float in brackets: (1.0 1.0 1.0)
-#define AI_MD5_READ_TRIPLE(vec) \
-    AI_MD5_SKIP_SPACES(); \
-    if ('(' != *sz++) \
-        MD5Parser::ReportWarning("Unexpected token: ( was expected",elem.iLineNumber); \
-    AI_MD5_SKIP_SPACES(); \
-    sz = fast_atoreal_move<float>(sz,(float&)vec.x); \
-    AI_MD5_SKIP_SPACES(); \
-    sz = fast_atoreal_move<float>(sz,(float&)vec.y); \
-    AI_MD5_SKIP_SPACES(); \
-    sz = fast_atoreal_move<float>(sz,(float&)vec.z); \
-    AI_MD5_SKIP_SPACES(); \
-    if (')' != *sz++) \
-        MD5Parser::ReportWarning("Unexpected token: ) was expected",elem.iLineNumber);
-
-	// parse a string, enclosed in quotation marks or not
-#define AI_MD5_PARSE_STRING(out) \
-    bool bQuota = (*sz == '\"'); \
-    const char* szStart = sz; \
-    while (!IsSpaceOrNewLine(*sz))++sz; \
-    const char* szEnd = sz; \
-    if (bQuota) { \
-        szStart++; \
-        if ('\"' != *(szEnd-=1)) { \
+#define AI_MD5_SKIP_SPACES() \
+    if (!SkipSpaces(&sz))    \
+        MD5Parser::ReportWarning("Unexpected end of line", elem.iLineNumber);
+
+// read a triple float in brackets: (1.0 1.0 1.0)
+#define AI_MD5_READ_TRIPLE(vec)                                                         \
+    AI_MD5_SKIP_SPACES();                                                               \
+    if ('(' != *sz++)                                                                   \
+        MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber); \
+    AI_MD5_SKIP_SPACES();                                                               \
+    sz = fast_atoreal_move<float>(sz, (float &)vec.x);                                  \
+    AI_MD5_SKIP_SPACES();                                                               \
+    sz = fast_atoreal_move<float>(sz, (float &)vec.y);                                  \
+    AI_MD5_SKIP_SPACES();                                                               \
+    sz = fast_atoreal_move<float>(sz, (float &)vec.z);                                  \
+    AI_MD5_SKIP_SPACES();                                                               \
+    if (')' != *sz++)                                                                   \
+        MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber);
+
+// parse a string, enclosed in quotation marks or not
+#define AI_MD5_PARSE_STRING(out)                                                   \
+    bool bQuota = (*sz == '\"');                                                   \
+    const char *szStart = sz;                                                      \
+    while (!IsSpaceOrNewLine(*sz))                                                 \
+        ++sz;                                                                      \
+    const char *szEnd = sz;                                                        \
+    if (bQuota) {                                                                  \
+        szStart++;                                                                 \
+        if ('\"' != *(szEnd -= 1)) {                                               \
             MD5Parser::ReportWarning("Expected closing quotation marks in string", \
             MD5Parser::ReportWarning("Expected closing quotation marks in string", \
-                elem.iLineNumber); \
-            continue; \
-        } \
-    } \
-    out.length = (size_t)(szEnd - szStart); \
-    ::memcpy(out.data,szStart,out.length); \
+                    elem.iLineNumber);                                             \
+            continue;                                                              \
+        }                                                                          \
+    }                                                                              \
+    out.length = (size_t)(szEnd - szStart);                                        \
+    ::memcpy(out.data, szStart, out.length);                                       \
     out.data[out.length] = '\0';
     out.data[out.length] = '\0';
 
 
-	// parse a string, enclosed in quotation marks
-#define AI_MD5_PARSE_STRING_IN_QUOTATION(out) \
-	while('\"'!=*sz)++sz; \
-    const char* szStart = ++sz; \
-	while('\"'!=*sz)++sz; \
-    const char* szEnd = (sz++); \
-    out.length = (ai_uint32) (szEnd - szStart); \
-    ::memcpy(out.data,szStart,out.length); \
+// parse a string, enclosed in quotation marks
+#define AI_MD5_PARSE_STRING_IN_QUOTATION(out)  \
+    while ('\"' != *sz)                        \
+        ++sz;                                  \
+    const char *szStart = ++sz;                \
+    while ('\"' != *sz)                        \
+        ++sz;                                  \
+    const char *szEnd = (sz++);                \
+    out.length = (ai_uint32)(szEnd - szStart); \
+    ::memcpy(out.data, szStart, out.length);   \
     out.data[out.length] = '\0';
     out.data[out.length] = '\0';
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // .MD5MESH parsing function
 // .MD5MESH parsing function
-MD5MeshParser::MD5MeshParser(SectionList& mSections)
-{
+MD5MeshParser::MD5MeshParser(SectionList &mSections) {
     ASSIMP_LOG_DEBUG("MD5MeshParser begin");
     ASSIMP_LOG_DEBUG("MD5MeshParser begin");
 
 
     // now parse all sections
     // now parse all sections
-    for (SectionList::const_iterator iter =  mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter){
-        if ( (*iter).mName == "numMeshes")  {
+    for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) {
+        if ((*iter).mName == "numMeshes") {
             mMeshes.reserve(::strtoul10((*iter).mGlobalValue.c_str()));
             mMeshes.reserve(::strtoul10((*iter).mGlobalValue.c_str()));
-        }
-        else if ( (*iter).mName == "numJoints") {
+        } else if ((*iter).mName == "numJoints") {
             mJoints.reserve(::strtoul10((*iter).mGlobalValue.c_str()));
             mJoints.reserve(::strtoul10((*iter).mGlobalValue.c_str()));
-        }
-        else if ((*iter).mName == "joints") {
+        } else if ((*iter).mName == "joints") {
             // "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 )
             // "origin" -1 ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000000 0.707107 )
-            for (const auto & elem : (*iter).mElements){
+            for (const auto &elem : (*iter).mElements) {
                 mJoints.push_back(BoneDesc());
                 mJoints.push_back(BoneDesc());
-                BoneDesc& desc = mJoints.back();
-				
-                const char* sz = elem.szStart;
-				AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName);
+                BoneDesc &desc = mJoints.back();
+
+                const char *sz = elem.szStart;
+                AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName);
                 AI_MD5_SKIP_SPACES();
                 AI_MD5_SKIP_SPACES();
 
 
                 // negative values, at least -1, is allowed here
                 // negative values, at least -1, is allowed here
-                desc.mParentIndex = (int)strtol10(sz,&sz);
+                desc.mParentIndex = (int)strtol10(sz, &sz);
 
 
                 AI_MD5_READ_TRIPLE(desc.mPositionXYZ);
                 AI_MD5_READ_TRIPLE(desc.mPositionXYZ);
                 AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there
                 AI_MD5_READ_TRIPLE(desc.mRotationQuat); // normalized quaternion, so w is not there
             }
             }
-        }
-        else if ((*iter).mName == "mesh")   {
+        } else if ((*iter).mName == "mesh") {
             mMeshes.push_back(MeshDesc());
             mMeshes.push_back(MeshDesc());
-            MeshDesc& desc = mMeshes.back();
+            MeshDesc &desc = mMeshes.back();
 
 
-            for (const auto & elem : (*iter).mElements){
-                const char* sz = elem.szStart;
+            for (const auto &elem : (*iter).mElements) {
+                const char *sz = elem.szStart;
 
 
                 // shader attribute
                 // shader attribute
-                if (TokenMatch(sz,"shader",6))  {
+                if (TokenMatch(sz, "shader", 6)) {
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mShader);
                     AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mShader);
                 }
                 }
                 // numverts attribute
                 // numverts attribute
-                else if (TokenMatch(sz,"numverts",8))   {
+                else if (TokenMatch(sz, "numverts", 8)) {
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
                     desc.mVertices.resize(strtoul10(sz));
                     desc.mVertices.resize(strtoul10(sz));
                 }
                 }
                 // numtris attribute
                 // numtris attribute
-                else if (TokenMatch(sz,"numtris",7))    {
+                else if (TokenMatch(sz, "numtris", 7)) {
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
                     desc.mFaces.resize(strtoul10(sz));
                     desc.mFaces.resize(strtoul10(sz));
                 }
                 }
                 // numweights attribute
                 // numweights attribute
-                else if (TokenMatch(sz,"numweights",10))    {
+                else if (TokenMatch(sz, "numweights", 10)) {
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
                     desc.mWeights.resize(strtoul10(sz));
                     desc.mWeights.resize(strtoul10(sz));
                 }
                 }
                 // vert attribute
                 // vert attribute
                 // "vert 0 ( 0.394531 0.513672 ) 0 1"
                 // "vert 0 ( 0.394531 0.513672 ) 0 1"
-                else if (TokenMatch(sz,"vert",4))   {
+                else if (TokenMatch(sz, "vert", 4)) {
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
-                    const unsigned int idx = ::strtoul10(sz,&sz);
+                    const unsigned int idx = ::strtoul10(sz, &sz);
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
                     if (idx >= desc.mVertices.size())
                     if (idx >= desc.mVertices.size())
-                        desc.mVertices.resize(idx+1);
+                        desc.mVertices.resize(idx + 1);
 
 
-                    VertexDesc& vert = desc.mVertices[idx];
+                    VertexDesc &vert = desc.mVertices[idx];
                     if ('(' != *sz++)
                     if ('(' != *sz++)
-                        MD5Parser::ReportWarning("Unexpected token: ( was expected",elem.iLineNumber);
+                        MD5Parser::ReportWarning("Unexpected token: ( was expected", elem.iLineNumber);
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
-                    sz = fast_atoreal_move<float>(sz,(float&)vert.mUV.x);
+                    sz = fast_atoreal_move<float>(sz, (float &)vert.mUV.x);
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
-                    sz = fast_atoreal_move<float>(sz,(float&)vert.mUV.y);
+                    sz = fast_atoreal_move<float>(sz, (float &)vert.mUV.y);
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
                     if (')' != *sz++)
                     if (')' != *sz++)
-                        MD5Parser::ReportWarning("Unexpected token: ) was expected",elem.iLineNumber);
+                        MD5Parser::ReportWarning("Unexpected token: ) was expected", elem.iLineNumber);
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
-                    vert.mFirstWeight = ::strtoul10(sz,&sz);
+                    vert.mFirstWeight = ::strtoul10(sz, &sz);
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
-                    vert.mNumWeights = ::strtoul10(sz,&sz);
+                    vert.mNumWeights = ::strtoul10(sz, &sz);
                 }
                 }
                 // tri attribute
                 // tri attribute
                 // "tri 0 15 13 12"
                 // "tri 0 15 13 12"
-                else if (TokenMatch(sz,"tri",3)) {
+                else if (TokenMatch(sz, "tri", 3)) {
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
-                    const unsigned int idx = strtoul10(sz,&sz);
+                    const unsigned int idx = strtoul10(sz, &sz);
                     if (idx >= desc.mFaces.size())
                     if (idx >= desc.mFaces.size())
-                        desc.mFaces.resize(idx+1);
+                        desc.mFaces.resize(idx + 1);
 
 
-                    aiFace& face = desc.mFaces[idx];
+                    aiFace &face = desc.mFaces[idx];
                     face.mIndices = new unsigned int[face.mNumIndices = 3];
                     face.mIndices = new unsigned int[face.mNumIndices = 3];
-                    for (unsigned int i = 0; i < 3;++i) {
+                    for (unsigned int i = 0; i < 3; ++i) {
                         AI_MD5_SKIP_SPACES();
                         AI_MD5_SKIP_SPACES();
-                        face.mIndices[i] = strtoul10(sz,&sz);
+                        face.mIndices[i] = strtoul10(sz, &sz);
                     }
                     }
                 }
                 }
                 // weight attribute
                 // weight attribute
                 // "weight 362 5 0.500000 ( -3.553583 11.893474 9.719339 )"
                 // "weight 362 5 0.500000 ( -3.553583 11.893474 9.719339 )"
-                else if (TokenMatch(sz,"weight",6)) {
+                else if (TokenMatch(sz, "weight", 6)) {
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
-                    const unsigned int idx = strtoul10(sz,&sz);
+                    const unsigned int idx = strtoul10(sz, &sz);
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
                     if (idx >= desc.mWeights.size())
                     if (idx >= desc.mWeights.size())
-                        desc.mWeights.resize(idx+1);
+                        desc.mWeights.resize(idx + 1);
 
 
-                    WeightDesc& weight = desc.mWeights[idx];
-                    weight.mBone = strtoul10(sz,&sz);
+                    WeightDesc &weight = desc.mWeights[idx];
+                    weight.mBone = strtoul10(sz, &sz);
                     AI_MD5_SKIP_SPACES();
                     AI_MD5_SKIP_SPACES();
-                    sz = fast_atoreal_move<float>(sz,weight.mWeight);
+                    sz = fast_atoreal_move<float>(sz, weight.mWeight);
                     AI_MD5_READ_TRIPLE(weight.vOffsetPosition);
                     AI_MD5_READ_TRIPLE(weight.vOffsetPosition);
                 }
                 }
             }
             }
@@ -358,57 +355,54 @@ MD5MeshParser::MD5MeshParser(SectionList& mSections)
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // .MD5ANIM parsing function
 // .MD5ANIM parsing function
-MD5AnimParser::MD5AnimParser(SectionList& mSections)
-{
+MD5AnimParser::MD5AnimParser(SectionList &mSections) {
     ASSIMP_LOG_DEBUG("MD5AnimParser begin");
     ASSIMP_LOG_DEBUG("MD5AnimParser begin");
 
 
     fFrameRate = 24.0f;
     fFrameRate = 24.0f;
     mNumAnimatedComponents = UINT_MAX;
     mNumAnimatedComponents = UINT_MAX;
-    for (SectionList::const_iterator iter =  mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) {
-        if ((*iter).mName == "hierarchy")   {
+    for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) {
+        if ((*iter).mName == "hierarchy") {
             // "sheath" 0 63 6
             // "sheath" 0 63 6
-            for (const auto & elem : (*iter).mElements) {
-                mAnimatedBones.push_back ( AnimBoneDesc () );
-                AnimBoneDesc& desc = mAnimatedBones.back();
+            for (const auto &elem : (*iter).mElements) {
+                mAnimatedBones.push_back(AnimBoneDesc());
+                AnimBoneDesc &desc = mAnimatedBones.back();
 
 
-                const char* sz = elem.szStart;
+                const char *sz = elem.szStart;
                 AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName);
                 AI_MD5_PARSE_STRING_IN_QUOTATION(desc.mName);
                 AI_MD5_SKIP_SPACES();
                 AI_MD5_SKIP_SPACES();
 
 
                 // parent index - negative values are allowed (at least -1)
                 // parent index - negative values are allowed (at least -1)
-                desc.mParentIndex = ::strtol10(sz,&sz);
+                desc.mParentIndex = ::strtol10(sz, &sz);
 
 
                 // flags (highest is 2^6-1)
                 // flags (highest is 2^6-1)
                 AI_MD5_SKIP_SPACES();
                 AI_MD5_SKIP_SPACES();
-                if(63 < (desc.iFlags = ::strtoul10(sz,&sz))){
-                    MD5Parser::ReportWarning("Invalid flag combination in hierarchy section",elem.iLineNumber);
+                if (63 < (desc.iFlags = ::strtoul10(sz, &sz))) {
+                    MD5Parser::ReportWarning("Invalid flag combination in hierarchy section", elem.iLineNumber);
                 }
                 }
                 AI_MD5_SKIP_SPACES();
                 AI_MD5_SKIP_SPACES();
 
 
                 // index of the first animation keyframe component for this joint
                 // index of the first animation keyframe component for this joint
-                desc.iFirstKeyIndex = ::strtoul10(sz,&sz);
+                desc.iFirstKeyIndex = ::strtoul10(sz, &sz);
             }
             }
-        }
-        else if((*iter).mName == "baseframe")   {
+        } else if ((*iter).mName == "baseframe") {
             // ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000242 0.707107 )
             // ( -0.000000 0.016430 -0.006044 ) ( 0.707107 0.000242 0.707107 )
-            for (const auto & elem : (*iter).mElements) {
-                const char* sz = elem.szStart;
+            for (const auto &elem : (*iter).mElements) {
+                const char *sz = elem.szStart;
 
 
-                mBaseFrames.push_back ( BaseFrameDesc () );
-                BaseFrameDesc& desc = mBaseFrames.back();
+                mBaseFrames.push_back(BaseFrameDesc());
+                BaseFrameDesc &desc = mBaseFrames.back();
 
 
                 AI_MD5_READ_TRIPLE(desc.vPositionXYZ);
                 AI_MD5_READ_TRIPLE(desc.vPositionXYZ);
                 AI_MD5_READ_TRIPLE(desc.vRotationQuat);
                 AI_MD5_READ_TRIPLE(desc.vRotationQuat);
             }
             }
-        }
-        else if((*iter).mName ==  "frame")  {
+        } else if ((*iter).mName == "frame") {
             if (!(*iter).mGlobalValue.length()) {
             if (!(*iter).mGlobalValue.length()) {
-                MD5Parser::ReportWarning("A frame section must have a frame index",(*iter).iLineNumber);
+                MD5Parser::ReportWarning("A frame section must have a frame index", (*iter).iLineNumber);
                 continue;
                 continue;
             }
             }
 
 
-            mFrames.push_back ( FrameDesc () );
-            FrameDesc& desc = mFrames.back();
+            mFrames.push_back(FrameDesc());
+            FrameDesc &desc = mFrames.back();
             desc.iIndex = strtoul10((*iter).mGlobalValue.c_str());
             desc.iIndex = strtoul10((*iter).mGlobalValue.c_str());
 
 
             // we do already know how much storage we will presumably need
             // we do already know how much storage we will presumably need
@@ -417,31 +411,28 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections)
             }
             }
 
 
             // now read all elements (continuous list of floats)
             // now read all elements (continuous list of floats)
-            for (const auto & elem : (*iter).mElements){
-                const char* sz = elem.szStart;
-                while (SkipSpacesAndLineEnd(&sz))   {
-                    float f;sz = fast_atoreal_move<float>(sz,f);
+            for (const auto &elem : (*iter).mElements) {
+                const char *sz = elem.szStart;
+                while (SkipSpacesAndLineEnd(&sz)) {
+                    float f;
+                    sz = fast_atoreal_move<float>(sz, f);
                     desc.mValues.push_back(f);
                     desc.mValues.push_back(f);
                 }
                 }
             }
             }
-        }
-        else if((*iter).mName == "numFrames")   {
+        } else if ((*iter).mName == "numFrames") {
             mFrames.reserve(strtoul10((*iter).mGlobalValue.c_str()));
             mFrames.reserve(strtoul10((*iter).mGlobalValue.c_str()));
-        }
-        else if((*iter).mName == "numJoints")   {
+        } else if ((*iter).mName == "numJoints") {
             const unsigned int num = strtoul10((*iter).mGlobalValue.c_str());
             const unsigned int num = strtoul10((*iter).mGlobalValue.c_str());
             mAnimatedBones.reserve(num);
             mAnimatedBones.reserve(num);
 
 
             // try to guess the number of animated components if that element is not given
             // try to guess the number of animated components if that element is not given
-            if (UINT_MAX  == mNumAnimatedComponents) {
+            if (UINT_MAX == mNumAnimatedComponents) {
                 mNumAnimatedComponents = num * 6;
                 mNumAnimatedComponents = num * 6;
             }
             }
-        }
-        else if((*iter).mName == "numAnimatedComponents")   {
-            mAnimatedBones.reserve( strtoul10((*iter).mGlobalValue.c_str()));
-        }
-        else if((*iter).mName == "frameRate")   {
-            fast_atoreal_move<float>((*iter).mGlobalValue.c_str(),fFrameRate);
+        } else if ((*iter).mName == "numAnimatedComponents") {
+            mAnimatedBones.reserve(strtoul10((*iter).mGlobalValue.c_str()));
+        } else if ((*iter).mName == "frameRate") {
+            fast_atoreal_move<float>((*iter).mGlobalValue.c_str(), fFrameRate);
         }
         }
     }
     }
     ASSIMP_LOG_DEBUG("MD5AnimParser end");
     ASSIMP_LOG_DEBUG("MD5AnimParser end");
@@ -449,32 +440,27 @@ MD5AnimParser::MD5AnimParser(SectionList& mSections)
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // .MD5CAMERA parsing function
 // .MD5CAMERA parsing function
-MD5CameraParser::MD5CameraParser(SectionList& mSections)
-{
+MD5CameraParser::MD5CameraParser(SectionList &mSections) {
     ASSIMP_LOG_DEBUG("MD5CameraParser begin");
     ASSIMP_LOG_DEBUG("MD5CameraParser begin");
     fFrameRate = 24.0f;
     fFrameRate = 24.0f;
 
 
-    for (SectionList::const_iterator iter =  mSections.begin(), iterEnd = mSections.end();iter != iterEnd;++iter) {
-        if ((*iter).mName == "numFrames")   {
+    for (SectionList::const_iterator iter = mSections.begin(), iterEnd = mSections.end(); iter != iterEnd; ++iter) {
+        if ((*iter).mName == "numFrames") {
             frames.reserve(strtoul10((*iter).mGlobalValue.c_str()));
             frames.reserve(strtoul10((*iter).mGlobalValue.c_str()));
-        }
-        else if ((*iter).mName == "frameRate")  {
-            fFrameRate = fast_atof ((*iter).mGlobalValue.c_str());
-        }
-        else if ((*iter).mName == "numCuts")    {
+        } else if ((*iter).mName == "frameRate") {
+            fFrameRate = fast_atof((*iter).mGlobalValue.c_str());
+        } else if ((*iter).mName == "numCuts") {
             cuts.reserve(strtoul10((*iter).mGlobalValue.c_str()));
             cuts.reserve(strtoul10((*iter).mGlobalValue.c_str()));
-        }
-        else if ((*iter).mName == "cuts")   {
-            for (const auto & elem : (*iter).mElements){
-                cuts.push_back(strtoul10(elem.szStart)+1);
+        } else if ((*iter).mName == "cuts") {
+            for (const auto &elem : (*iter).mElements) {
+                cuts.push_back(strtoul10(elem.szStart) + 1);
             }
             }
-        }
-        else if ((*iter).mName == "camera") {
-            for (const auto & elem : (*iter).mElements){
-                const char* sz = elem.szStart;
+        } else if ((*iter).mName == "camera") {
+            for (const auto &elem : (*iter).mElements) {
+                const char *sz = elem.szStart;
 
 
                 frames.push_back(CameraAnimFrameDesc());
                 frames.push_back(CameraAnimFrameDesc());
-                CameraAnimFrameDesc& cur = frames.back();
+                CameraAnimFrameDesc &cur = frames.back();
                 AI_MD5_READ_TRIPLE(cur.vPositionXYZ);
                 AI_MD5_READ_TRIPLE(cur.vPositionXYZ);
                 AI_MD5_READ_TRIPLE(cur.vRotationQuat);
                 AI_MD5_READ_TRIPLE(cur.vRotationQuat);
                 AI_MD5_SKIP_SPACES();
                 AI_MD5_SKIP_SPACES();
@@ -484,4 +470,3 @@ MD5CameraParser::MD5CameraParser(SectionList& mSections)
     }
     }
     ASSIMP_LOG_DEBUG("MD5CameraParser end");
     ASSIMP_LOG_DEBUG("MD5CameraParser end");
 }
 }
-

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

@@ -267,7 +267,7 @@ void MDCImporter::InternReadFile(
 
 
     // necessary that we don't crash if an exception occurs
     // necessary that we don't crash if an exception occurs
     for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
     for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
-        pScene->mMeshes[i] = NULL;
+        pScene->mMeshes[i] = nullptr;
     }
     }
 
 
     // now read all surfaces
     // now read all surfaces
@@ -347,8 +347,8 @@ void MDCImporter::InternReadFile(
 
 
 #endif
 #endif
 
 
-        const MDC::CompressedVertex *pcCVerts = NULL;
-        int16_t *mdcCompVert = NULL;
+        const MDC::CompressedVertex *pcCVerts = nullptr;
+        int16_t *mdcCompVert = nullptr;
 
 
         // access compressed frames for large frame numbers, but never for the first
         // access compressed frames for large frame numbers, but never for the first
         if (this->configFrameID && pcSurface->ulNumCompFrames > 0) {
         if (this->configFrameID && pcSurface->ulNumCompFrames > 0) {
@@ -359,7 +359,7 @@ void MDCImporter::InternReadFile(
                                                            pcSurface->ulOffsetCompVerts) +
                                                            pcSurface->ulOffsetCompVerts) +
                            *mdcCompVert * pcSurface->ulNumVertices;
                            *mdcCompVert * pcSurface->ulNumVertices;
             } else
             } else
-                mdcCompVert = NULL;
+                mdcCompVert = nullptr;
         }
         }
 
 
         // copy all faces
         // copy all faces

+ 1 - 1
code/AssetLib/MDL/HalfLife/HL1MDLLoader.cpp

@@ -829,7 +829,7 @@ void HL1MDLLoader::read_meshes() {
                         }
                         }
                     } else {
                     } else {
                         for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) {
                         for (int faceIdx = 0; faceIdx < num_faces; ++faceIdx) {
-                            if (i & 1) {
+                            if (faceIdx & 1) {
                                 // Preserve winding order.
                                 // Preserve winding order.
                                 mesh_faces.push_back(HL1MeshFace{
                                 mesh_faces.push_back(HL1MeshFace{
                                         tricmds[faceIdx + 1],
                                         tricmds[faceIdx + 1],

+ 4 - 2
code/AssetLib/MDL/HalfLife/HL1MDLLoader.h

@@ -222,12 +222,14 @@ void HL1MDLLoader::load_file_into_buffer(const std::string &file_path, unsigned
 
 
     std::unique_ptr<IOStream> file(io_->Open(file_path));
     std::unique_ptr<IOStream> file(io_->Open(file_path));
 
 
-    if (file.get() == NULL)
+    if (file.get() == nullptr) {
         throw DeadlyImportError("Failed to open MDL file " + DefaultIOSystem::fileName(file_path) + ".");
         throw DeadlyImportError("Failed to open MDL file " + DefaultIOSystem::fileName(file_path) + ".");
+    }
 
 
     const size_t file_size = file->FileSize();
     const size_t file_size = file->FileSize();
-    if (file_size < sizeof(MDLFileHeader))
+    if (file_size < sizeof(MDLFileHeader)) {
         throw DeadlyImportError("MDL file is too small.");
         throw DeadlyImportError("MDL file is too small.");
+    }
 
 
     buffer = new unsigned char[1 + file_size];
     buffer = new unsigned char[1 + file_size];
     file->Read((void *)buffer, 1, file_size);
     file->Read((void *)buffer, 1, file_size);

+ 23 - 20
code/AssetLib/MDL/MDLLoader.cpp

@@ -278,7 +278,7 @@ void MDLImporter::SizeCheck(const void *szPos) {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Just for debugging purposes
 // Just for debugging purposes
 void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int iLine) {
 void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int iLine) {
-    ai_assert(NULL != szFile);
+    ai_assert(nullptr != szFile);
     if (!szPos || (const unsigned char *)szPos > mBuffer + iFileSize) {
     if (!szPos || (const unsigned char *)szPos > mBuffer + iFileSize) {
         // remove a directory if there is one
         // remove a directory if there is one
         const char *szFilePtr = ::strrchr(szFile, '\\');
         const char *szFilePtr = ::strrchr(szFile, '\\');
@@ -304,7 +304,7 @@ void MDLImporter::SizeCheck(const void *szPos, const char *szFile, unsigned int
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Validate a quake file header
 // Validate a quake file header
 void MDLImporter::ValidateHeader_Quake1(const MDL::Header *pcHeader) {
 void MDLImporter::ValidateHeader_Quake1(const MDL::Header *pcHeader) {
-    // some values may not be NULL
+    // some values may not be nullptr
     if (!pcHeader->num_frames)
     if (!pcHeader->num_frames)
         throw DeadlyImportError("[Quake 1 MDL] There are no frames in the file");
         throw DeadlyImportError("[Quake 1 MDL] There are no frames in the file");
 
 
@@ -359,7 +359,7 @@ void FlipQuakeHeader(BE_NCONST MDL::Header *pcHeader) {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Read a Quake 1 file
 // Read a Quake 1 file
 void MDLImporter::InternReadFile_Quake1() {
 void MDLImporter::InternReadFile_Quake1() {
-    ai_assert(NULL != pScene);
+    ai_assert(nullptr != pScene);
 
 
     BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer;
     BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer;
 
 
@@ -548,7 +548,7 @@ void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1() {
             delete pScene->mTextures[0];
             delete pScene->mTextures[0];
             delete[] pScene->mTextures;
             delete[] pScene->mTextures;
 
 
-            pScene->mTextures = NULL;
+            pScene->mTextures = nullptr;
             pScene->mNumTextures = 0;
             pScene->mNumTextures = 0;
         } else {
         } else {
             clr.b = clr.a = clr.g = clr.r = 1.0f;
             clr.b = clr.a = clr.g = clr.r = 1.0f;
@@ -572,7 +572,7 @@ void MDLImporter::SetupMaterialProperties_3DGS_MDL5_Quake1() {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Read a MDL 3,4,5 file
 // Read a MDL 3,4,5 file
 void MDLImporter::InternReadFile_3DGS_MDL345() {
 void MDLImporter::InternReadFile_3DGS_MDL345() {
-    ai_assert(NULL != pScene);
+    ai_assert(nullptr != pScene);
 
 
     // the header of MDL 3/4/5 is nearly identical to the original Quake1 header
     // the header of MDL 3/4/5 is nearly identical to the original Quake1 header
     BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer;
     BE_NCONST MDL::Header *pcHeader = (BE_NCONST MDL::Header *)this->mBuffer;
@@ -791,7 +791,7 @@ void MDLImporter::ImportUVCoordinate_3DGS_MDL345(
         aiVector3D &vOut,
         aiVector3D &vOut,
         const MDL::TexCoord_MDL3 *pcSrc,
         const MDL::TexCoord_MDL3 *pcSrc,
         unsigned int iIndex) {
         unsigned int iIndex) {
-    ai_assert(NULL != pcSrc);
+    ai_assert(nullptr != pcSrc);
     const MDL::Header *const pcHeader = (const MDL::Header *)this->mBuffer;
     const MDL::Header *const pcHeader = (const MDL::Header *)this->mBuffer;
 
 
     // validate UV indices
     // validate UV indices
@@ -860,7 +860,7 @@ void MDLImporter::CalculateUVCoordinates_MDL5() {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Validate the header of a MDL7 file
 // Validate the header of a MDL7 file
 void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7 *pcHeader) {
 void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7 *pcHeader) {
-    ai_assert(NULL != pcHeader);
+    ai_assert(nullptr != pcHeader);
 
 
     // There are some fixed sizes ...
     // There are some fixed sizes ...
     if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) {
     if (sizeof(MDL::ColorValue_MDL7) != pcHeader->colorvalue_stc_size) {
@@ -887,7 +887,7 @@ void MDLImporter::ValidateHeader_3DGS_MDL7(const MDL::Header_MDL7 *pcHeader) {
 void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones) {
 void MDLImporter::CalcAbsBoneMatrices_3DGS_MDL7(MDL::IntBone_MDL7 **apcOutBones) {
     const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7 *)this->mBuffer;
     const MDL::Header_MDL7 *pcHeader = (const MDL::Header_MDL7 *)this->mBuffer;
     const MDL::Bone_MDL7 *pcBones = (const MDL::Bone_MDL7 *)(pcHeader + 1);
     const MDL::Bone_MDL7 *pcBones = (const MDL::Bone_MDL7 *)(pcHeader + 1);
-    ai_assert(NULL != apcOutBones);
+    ai_assert(nullptr != apcOutBones);
 
 
     // first find the bone that has NO parent, calculate the
     // first find the bone that has NO parent, calculate the
     // animation matrix for it, then go on and search for the next parent
     // animation matrix for it, then go on and search for the next parent
@@ -979,7 +979,7 @@ MDL::IntBone_MDL7 **MDLImporter::LoadBones_3DGS_MDL7() {
                 AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size &&
                 AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_32_CHARS != pcHeader->bone_stc_size &&
                 AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size) {
                 AI_MDL7_BONE_STRUCT_SIZE__NAME_IS_NOT_THERE != pcHeader->bone_stc_size) {
             ASSIMP_LOG_WARN("Unknown size of bone data structure");
             ASSIMP_LOG_WARN("Unknown size of bone data structure");
-            return NULL;
+            return nullptr;
         }
         }
 
 
         MDL::IntBone_MDL7 **apcBonesOut = new MDL::IntBone_MDL7 *[pcHeader->bones_num];
         MDL::IntBone_MDL7 **apcBonesOut = new MDL::IntBone_MDL7 *[pcHeader->bones_num];
@@ -990,7 +990,7 @@ MDL::IntBone_MDL7 **MDLImporter::LoadBones_3DGS_MDL7() {
         CalcAbsBoneMatrices_3DGS_MDL7(apcBonesOut);
         CalcAbsBoneMatrices_3DGS_MDL7(apcBonesOut);
         return apcBonesOut;
         return apcBonesOut;
     }
     }
-    return NULL;
+    return nullptr;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -1014,7 +1014,7 @@ void MDLImporter::ReadFaces_3DGS_MDL7(const MDL::IntGroupInfo_MDL7 &groupInfo,
             unsigned int iIndex = pcGroupTris->v_index[c];
             unsigned int iIndex = pcGroupTris->v_index[c];
             if (iIndex > (unsigned int)groupInfo.pcGroup->numverts) {
             if (iIndex > (unsigned int)groupInfo.pcGroup->numverts) {
                 // (we might need to read this section a second time - to process frame vertices correctly)
                 // (we might need to read this section a second time - to process frame vertices correctly)
-                pcGroupTris->v_index[c] = (uint16_t) (iIndex = groupInfo.pcGroup->numverts - 1 );
+                pcGroupTris->v_index[c] = (uint16_t)(iIndex = groupInfo.pcGroup->numverts - 1);
                 ASSIMP_LOG_WARN("Index overflow in MDL7 vertex list");
                 ASSIMP_LOG_WARN("Index overflow in MDL7 vertex list");
             }
             }
 
 
@@ -1337,7 +1337,7 @@ void MDLImporter::SortByMaterials_3DGS_MDL7(
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Read a MDL7 file
 // Read a MDL7 file
 void MDLImporter::InternReadFile_3DGS_MDL7() {
 void MDLImporter::InternReadFile_3DGS_MDL7() {
-    ai_assert(NULL != pScene);
+    ai_assert(nullptr != pScene);
 
 
     MDL::IntSharedData_MDL7 sharedData;
     MDL::IntSharedData_MDL7 sharedData;
 
 
@@ -1368,7 +1368,7 @@ void MDLImporter::InternReadFile_3DGS_MDL7() {
 
 
     // load all bones (they are shared by all groups, so
     // load all bones (they are shared by all groups, so
     // we'll need to add them to all groups/meshes later)
     // we'll need to add them to all groups/meshes later)
-    // apcBonesOut is a list of all bones or NULL if they could not been loaded
+    // apcBonesOut is a list of all bones or nullptr if they could not been loaded
     szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size;
     szCurrent += pcHeader->bones_num * pcHeader->bone_stc_size;
     sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
     sharedData.apcOutBones = this->LoadBones_3DGS_MDL7();
 
 
@@ -1558,9 +1558,9 @@ void MDLImporter::InternReadFile_3DGS_MDL7() {
     if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) {
     if (1 == pScene->mRootNode->mNumChildren && !sharedData.apcOutBones) {
         aiNode *pcOldRoot = this->pScene->mRootNode;
         aiNode *pcOldRoot = this->pScene->mRootNode;
         pScene->mRootNode = pcOldRoot->mChildren[0];
         pScene->mRootNode = pcOldRoot->mChildren[0];
-        pcOldRoot->mChildren[0] = NULL;
+        pcOldRoot->mChildren[0] = nullptr;
         delete pcOldRoot;
         delete pcOldRoot;
-        pScene->mRootNode->mParent = NULL;
+        pScene->mRootNode->mParent = nullptr;
     } else
     } else
         pScene->mRootNode->mName.Set("<mesh_root>");
         pScene->mRootNode->mName.Set("<mesh_root>");
 
 
@@ -1665,7 +1665,8 @@ void MDLImporter::ParseBoneTrafoKeys_3DGS_MDL7(
 // Attach bones to the output nodegraph
 // Attach bones to the output nodegraph
 void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7 **apcBones,
 void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7 **apcBones,
         aiNode *pcParent, uint16_t iParentIndex) {
         aiNode *pcParent, uint16_t iParentIndex) {
-    ai_assert(NULL != apcBones && NULL != pcParent);
+    ai_assert(nullptr != apcBones);
+    ai_assert(nullptr != pcParent);
 
 
     // get a pointer to the header ...
     // get a pointer to the header ...
     const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)this->mBuffer;
     const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)this->mBuffer;
@@ -1696,7 +1697,7 @@ void MDLImporter::AddBonesToNodeGraph_3DGS_MDL7(const MDL::IntBone_MDL7 **apcBon
 // Build output animations
 // Build output animations
 void MDLImporter::BuildOutputAnims_3DGS_MDL7(
 void MDLImporter::BuildOutputAnims_3DGS_MDL7(
         const MDL::IntBone_MDL7 **apcBonesOut) {
         const MDL::IntBone_MDL7 **apcBonesOut) {
-    ai_assert(NULL != apcBonesOut);
+    ai_assert(nullptr != apcBonesOut);
     const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)mBuffer;
     const MDL::Header_MDL7 *const pcHeader = (const MDL::Header_MDL7 *)mBuffer;
 
 
     // one animation ...
     // one animation ...
@@ -1755,8 +1756,8 @@ void MDLImporter::BuildOutputAnims_3DGS_MDL7(
 void MDLImporter::AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo,
 void MDLImporter::AddAnimationBoneTrafoKey_3DGS_MDL7(unsigned int iTrafo,
         const MDL::BoneTransform_MDL7 *pcBoneTransforms,
         const MDL::BoneTransform_MDL7 *pcBoneTransforms,
         MDL::IntBone_MDL7 **apcBonesOut) {
         MDL::IntBone_MDL7 **apcBonesOut) {
-    ai_assert(NULL != pcBoneTransforms);
-    ai_assert(NULL != apcBonesOut);
+    ai_assert(nullptr != pcBoneTransforms);
+    ai_assert(nullptr != apcBonesOut);
 
 
     // first .. get the transformation matrix
     // first .. get the transformation matrix
     aiMatrix4x4 mTransform;
     aiMatrix4x4 mTransform;
@@ -1920,7 +1921,9 @@ void MDLImporter::JoinSkins_3DGS_MDL7(
         aiMaterial *pcMat1,
         aiMaterial *pcMat1,
         aiMaterial *pcMat2,
         aiMaterial *pcMat2,
         aiMaterial *pcMatOut) {
         aiMaterial *pcMatOut) {
-    ai_assert(NULL != pcMat1 && NULL != pcMat2 && NULL != pcMatOut);
+    ai_assert(nullptr != pcMat1);
+    ai_assert(nullptr != pcMat2);
+    ai_assert(nullptr != pcMatOut);
 
 
     // first create a full copy of the first skin property set
     // first create a full copy of the first skin property set
     // and assign it to the output material
     // and assign it to the output material

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

@@ -320,7 +320,7 @@ protected:
     /** Load the bone list of a MDL7 file
     /** Load the bone list of a MDL7 file
      * \return If the bones could be loaded successfully, a valid
      * \return If the bones could be loaded successfully, a valid
      *   array containing pointers to a temporary bone
      *   array containing pointers to a temporary bone
-     *   representation. NULL if the bones could not be loaded.
+     *   representation. nullptr if the bones could not be loaded.
      */
      */
     MDL::IntBone_MDL7** LoadBones_3DGS_MDL7();
     MDL::IntBone_MDL7** LoadBones_3DGS_MDL7();
 
 

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

@@ -364,7 +364,7 @@ void MDLImporter::ParseTextureColorData(const unsigned char *szData,
 void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char *szData,
 void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char *szData,
         unsigned int iType,
         unsigned int iType,
         unsigned int *piSkip) {
         unsigned int *piSkip) {
-    ai_assert(NULL != piSkip);
+    ai_assert(nullptr != piSkip);
     bool bNoRead = *piSkip == UINT_MAX;
     bool bNoRead = *piSkip == UINT_MAX;
 
 
     // allocate a new texture object
     // allocate a new texture object
@@ -428,7 +428,7 @@ void MDLImporter::CreateTexture_3DGS_MDL5(const unsigned char *szData,
             delete[] pc;
             delete[] pc;
         }
         }
     } else {
     } else {
-        pcNew->pcData = NULL;
+        pcNew->pcData = nullptr;
         delete pcNew;
         delete pcNew;
     }
     }
     return;
     return;

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

@@ -134,7 +134,7 @@ void MMDImporter::InternReadFile(const std::string &file, aiScene *pScene,
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void MMDImporter::CreateDataFromImport(const pmx::PmxModel *pModel,
 void MMDImporter::CreateDataFromImport(const pmx::PmxModel *pModel,
         aiScene *pScene) {
         aiScene *pScene) {
-    if (pModel == NULL) {
+    if (pModel == nullptr) {
         return;
         return;
     }
     }
 
 

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

@@ -93,4 +93,4 @@ private:
 
 
 } // Namespace Assimp
 } // Namespace Assimp
 
 
-#endif
+#endif

+ 1 - 1
code/AssetLib/MMD/MMDPmdParser.h

@@ -131,7 +131,7 @@ namespace pmd
 			stream->read((char*) &index_count, sizeof(uint32_t));
 			stream->read((char*) &index_count, sizeof(uint32_t));
 			stream->read((char*) &buffer, sizeof(char) * 20);
 			stream->read((char*) &buffer, sizeof(char) * 20);
 			char* pstar = strchr(buffer, '*');
 			char* pstar = strchr(buffer, '*');
-			if (NULL == pstar)
+            if (nullptr == pstar)
 			{
 			{
 				texture_filename = std::string(buffer);
 				texture_filename = std::string(buffer);
 				sphere_filename.clear();
 				sphere_filename.clear();

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

@@ -657,7 +657,7 @@ void MS3DImporter::InternReadFile( const std::string& pFile,
         }
         }
         // fixup to pass the validation if not a single animation channel is non-trivial
         // fixup to pass the validation if not a single animation channel is non-trivial
         if (!anim->mNumChannels) {
         if (!anim->mNumChannels) {
-            anim->mChannels = NULL;
+            anim->mChannels = nullptr;
         }
         }
     }
     }
 }
 }

+ 12 - 12
code/AssetLib/NFF/NFFLoader.cpp

@@ -154,7 +154,7 @@ void NFFImporter::LoadNFF2MaterialTable(std::vector<ShadingInfo> &output,
         return;
         return;
     }
     }
 
 
-    ShadingInfo *curShader = NULL;
+    ShadingInfo *curShader = nullptr;
 
 
     // No read the file line per line
     // No read the file line per line
     char line[4096];
     char line[4096];
@@ -238,9 +238,9 @@ void NFFImporter::InternReadFile(const std::string &pFile,
 
 
     bool hasCam = false;
     bool hasCam = false;
 
 
-    MeshInfo *currentMeshWithNormals = NULL;
-    MeshInfo *currentMesh = NULL;
-    MeshInfo *currentMeshWithUVCoords = NULL;
+    MeshInfo *currentMeshWithNormals = nullptr;
+    MeshInfo *currentMesh = nullptr;
+    MeshInfo *currentMeshWithUVCoords = nullptr;
 
 
     ShadingInfo s; // current material info
     ShadingInfo s; // current material info
 
 
@@ -542,7 +542,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
                     // search the list of all shaders we have for this object whether
                     // search the list of all shaders we have for this object whether
                     // there is an identical one. In this case, we append our mesh
                     // there is an identical one. In this case, we append our mesh
                     // data to it.
                     // data to it.
-                    MeshInfo *mesh = NULL;
+                    MeshInfo *mesh = nullptr;
                     for (std::vector<MeshInfo>::iterator it = meshes.begin() + objStart, end = meshes.end();
                     for (std::vector<MeshInfo>::iterator it = meshes.begin() + objStart, end = meshes.end();
                             it != end; ++it) {
                             it != end; ++it) {
                         if ((*it).shader == shader && (*it).matIndex == matIdx) {
                         if ((*it).shader == shader && (*it).matIndex == matIdx) {
@@ -603,11 +603,11 @@ void NFFImporter::InternReadFile(const std::string &pFile,
         while (GetNextLine(buffer, line)) {
         while (GetNextLine(buffer, line)) {
             sz = line;
             sz = line;
             if ('p' == line[0] || TokenMatch(sz, "tpp", 3)) {
             if ('p' == line[0] || TokenMatch(sz, "tpp", 3)) {
-                MeshInfo *out = NULL;
+                MeshInfo *out = nullptr;
 
 
                 // 'tpp' - texture polygon patch primitive
                 // 'tpp' - texture polygon patch primitive
                 if ('t' == line[0]) {
                 if ('t' == line[0]) {
-                    currentMeshWithUVCoords = NULL;
+                    currentMeshWithUVCoords = nullptr;
                     for (auto &mesh : meshesWithUVCoords) {
                     for (auto &mesh : meshesWithUVCoords) {
                         if (mesh.shader == s) {
                         if (mesh.shader == s) {
                             currentMeshWithUVCoords = &mesh;
                             currentMeshWithUVCoords = &mesh;
@@ -624,7 +624,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
                 }
                 }
                 // 'pp' - polygon patch primitive
                 // 'pp' - polygon patch primitive
                 else if ('p' == line[1]) {
                 else if ('p' == line[1]) {
-                    currentMeshWithNormals = NULL;
+                    currentMeshWithNormals = nullptr;
                     for (auto &mesh : meshesWithNormals) {
                     for (auto &mesh : meshesWithNormals) {
                         if (mesh.shader == s) {
                         if (mesh.shader == s) {
                             currentMeshWithNormals = &mesh;
                             currentMeshWithNormals = &mesh;
@@ -642,7 +642,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
                 }
                 }
                 // 'p' - polygon primitive
                 // 'p' - polygon primitive
                 else {
                 else {
-                    currentMesh = NULL;
+                    currentMesh = nullptr;
                     for (auto &mesh : meshes) {
                     for (auto &mesh : meshes) {
                         if (mesh.shader == s) {
                         if (mesh.shader == s) {
                             currentMesh = &mesh;
                             currentMesh = &mesh;
@@ -969,8 +969,8 @@ void NFFImporter::InternReadFile(const std::string &pFile,
     root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int)lights.size();
     root->mNumChildren = numNamed + (hasCam ? 1 : 0) + (unsigned int)lights.size();
     root->mNumMeshes = pScene->mNumMeshes - numNamed;
     root->mNumMeshes = pScene->mNumMeshes - numNamed;
 
 
-    aiNode **ppcChildren = NULL;
-    unsigned int *pMeshes = NULL;
+    aiNode **ppcChildren = nullptr;
+    unsigned int *pMeshes = nullptr;
     if (root->mNumMeshes)
     if (root->mNumMeshes)
         pMeshes = root->mMeshes = new unsigned int[root->mNumMeshes];
         pMeshes = root->mMeshes = new unsigned int[root->mNumMeshes];
     if (root->mNumChildren)
     if (root->mNumChildren)
@@ -1037,7 +1037,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
         mesh->mNumFaces = (unsigned int)src.faces.size();
         mesh->mNumFaces = (unsigned int)src.faces.size();
 
 
         // Generate sub nodes for named meshes
         // Generate sub nodes for named meshes
-        if (src.name[0] && NULL != ppcChildren) {
+        if (src.name[0] && nullptr != ppcChildren) {
             aiNode *const node = *ppcChildren = new aiNode();
             aiNode *const node = *ppcChildren = new aiNode();
             node->mParent = root;
             node->mParent = root;
             node->mNumMeshes = 1;
             node->mNumMeshes = 1;

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

@@ -70,14 +70,14 @@ void ExportSceneObj(const char* pFile,IOSystem* pIOSystem, const aiScene* pScene
     // we're still here - export successfully completed. Write both the main OBJ file and the material script
     // we're still here - export successfully completed. Write both the main OBJ file and the material script
     {
     {
         std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
         std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
-        if(outfile == NULL) {
+        if (outfile == nullptr) {
             throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
             throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
         }
         }
         outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
         outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
     }
     }
     {
     {
         std::unique_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
         std::unique_ptr<IOStream> outfile (pIOSystem->Open(exporter.GetMaterialLibFileName(),"wt"));
-        if(outfile == NULL) {
+        if (outfile == nullptr) {
             throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
             throw DeadlyExportError("could not open output .mtl file: " + std::string(exporter.GetMaterialLibFileName()));
         }
         }
         outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
         outfile->Write( exporter.mOutputMat.str().c_str(), static_cast<size_t>(exporter.mOutputMat.tellp()),1);
@@ -97,7 +97,7 @@ void ExportSceneObjNoMtl(const char* pFile,IOSystem* pIOSystem, const aiScene* p
     // we're still here - export successfully completed. Write both the main OBJ file and the material script
     // we're still here - export successfully completed. Write both the main OBJ file and the material script
     {
     {
         std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
         std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
-        if(outfile == NULL) {
+        if (outfile == nullptr) {
             throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
             throw DeadlyExportError("could not open output .obj file: " + std::string(pFile));
         }
         }
         outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);
         outfile->Write( exporter.mOutput.str().c_str(), static_cast<size_t>(exporter.mOutput.tellp()),1);

+ 15 - 11
code/AssetLib/Obj/ObjFileData.h

@@ -41,12 +41,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #pragma once
 #pragma once
 #ifndef OBJ_FILEDATA_H_INC
 #ifndef OBJ_FILEDATA_H_INC
-#    define OBJ_FILEDATA_H_INC
+#define OBJ_FILEDATA_H_INC
 
 
-#    include <assimp/mesh.h>
-#    include <assimp/types.h>
-#    include <map>
-#    include <vector>
+#include <assimp/mesh.h>
+#include <assimp/types.h>
+#include <map>
+#include <vector>
 
 
 namespace Assimp {
 namespace Assimp {
 namespace ObjFile {
 namespace ObjFile {
@@ -215,7 +215,11 @@ struct Mesh {
 
 
     /// Constructor
     /// Constructor
     explicit Mesh(const std::string &name) :
     explicit Mesh(const std::string &name) :
-            m_name(name), m_pMaterial(NULL), m_uiNumIndices(0), m_uiMaterialIndex(NoMaterial), m_hasNormals(false) {
+            m_name(name),
+            m_pMaterial(nullptr),
+            m_uiNumIndices(0),
+            m_uiMaterialIndex(NoMaterial),
+            m_hasNormals(false) {
         memset(m_uiUVCoordinates, 0, sizeof(unsigned int) * AI_MAX_NUMBER_OF_TEXTURECOORDS);
         memset(m_uiUVCoordinates, 0, sizeof(unsigned int) * AI_MAX_NUMBER_OF_TEXTURECOORDS);
     }
     }
 
 
@@ -275,13 +279,13 @@ struct Model {
     //! \brief  The default class constructor
     //! \brief  The default class constructor
     Model() :
     Model() :
             m_ModelName(""),
             m_ModelName(""),
-            m_pCurrent(NULL),
-            m_pCurrentMaterial(NULL),
-            m_pDefaultMaterial(NULL),
-            m_pGroupFaceIDs(NULL),
+            m_pCurrent(nullptr),
+            m_pCurrentMaterial(nullptr),
+            m_pDefaultMaterial(nullptr),
+            m_pGroupFaceIDs(nullptr),
             m_strActiveGroup(""),
             m_strActiveGroup(""),
             m_TextureCoordDim(0),
             m_TextureCoordDim(0),
-            m_pCurrentMesh(NULL) {
+            m_pCurrentMesh(nullptr) {
         // empty
         // empty
     }
     }
 
 

+ 15 - 15
code/AssetLib/Obj/ObjFileImporter.cpp

@@ -252,9 +252,9 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model *pModel, aiScene
 aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject,
 aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile::Object *pObject,
         aiNode *pParent, aiScene *pScene,
         aiNode *pParent, aiScene *pScene,
         std::vector<aiMesh *> &MeshArray) {
         std::vector<aiMesh *> &MeshArray) {
-    ai_assert(NULL != pModel);
-    if (NULL == pObject) {
-        return NULL;
+    ai_assert(nullptr != pModel);
+    if (nullptr == pObject) {
+        return nullptr;
     }
     }
 
 
     // Store older mesh size to be able to computes mesh offsets for new mesh instances
     // Store older mesh size to be able to computes mesh offsets for new mesh instances
@@ -264,7 +264,7 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
     pNode->mName = pObject->m_strObjName;
     pNode->mName = pObject->m_strObjName;
 
 
     // If we have a parent node, store it
     // If we have a parent node, store it
-    ai_assert(NULL != pParent);
+    ai_assert(nullptr != pParent);
     appendChildToParentNode(pParent, pNode);
     appendChildToParentNode(pParent, pNode);
 
 
     for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) {
     for (size_t i = 0; i < pObject->m_Meshes.size(); ++i) {
@@ -308,20 +308,20 @@ aiNode *ObjFileImporter::createNodes(const ObjFile::Model *pModel, const ObjFile
 //  Create topology data
 //  Create topology data
 aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData, unsigned int meshIndex) {
 aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjFile::Object *pData, unsigned int meshIndex) {
     // Checking preconditions
     // Checking preconditions
-    ai_assert(NULL != pModel);
+    ai_assert(nullptr != pModel);
 
 
-    if (NULL == pData) {
-        return NULL;
+    if (nullptr == pData) {
+        return nullptr;
     }
     }
 
 
     // Create faces
     // Create faces
     ObjFile::Mesh *pObjMesh = pModel->m_Meshes[meshIndex];
     ObjFile::Mesh *pObjMesh = pModel->m_Meshes[meshIndex];
     if (!pObjMesh) {
     if (!pObjMesh) {
-        return NULL;
+        return nullptr;
     }
     }
 
 
     if (pObjMesh->m_Faces.empty()) {
     if (pObjMesh->m_Faces.empty()) {
-        return NULL;
+        return nullptr;
     }
     }
 
 
     std::unique_ptr<aiMesh> pMesh(new aiMesh);
     std::unique_ptr<aiMesh> pMesh(new aiMesh);
@@ -331,7 +331,7 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
 
 
     for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
     for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
         ObjFile::Face *const inp = pObjMesh->m_Faces[index];
         ObjFile::Face *const inp = pObjMesh->m_Faces[index];
-        ai_assert(NULL != inp);
+        ai_assert(nullptr != inp);
 
 
         if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
         if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
             pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size() - 1);
             pMesh->mNumFaces += static_cast<unsigned int>(inp->m_vertices.size() - 1);
@@ -400,7 +400,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
         aiMesh *pMesh,
         aiMesh *pMesh,
         unsigned int numIndices) {
         unsigned int numIndices) {
     // Checking preconditions
     // Checking preconditions
-    ai_assert(NULL != pCurrentObject);
+    ai_assert(nullptr != pCurrentObject);
 
 
     // Break, if no faces are stored in object
     // Break, if no faces are stored in object
     if (pCurrentObject->m_Meshes.empty())
     if (pCurrentObject->m_Meshes.empty())
@@ -408,7 +408,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
 
 
     // Get current mesh
     // Get current mesh
     ObjFile::Mesh *pObjMesh = pModel->m_Meshes[uiMeshIndex];
     ObjFile::Mesh *pObjMesh = pModel->m_Meshes[uiMeshIndex];
-    if (NULL == pObjMesh || pObjMesh->m_uiNumIndices < 1) {
+    if (nullptr == pObjMesh || pObjMesh->m_uiNumIndices < 1) {
         return;
         return;
     }
     }
 
 
@@ -561,7 +561,7 @@ void ObjFileImporter::addTextureMappingModeProperty(aiMaterial *mat, aiTextureTy
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //  Creates the material
 //  Creates the material
 void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pScene) {
 void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pScene) {
-    if (NULL == pScene) {
+    if (nullptr == pScene) {
         return;
         return;
     }
     }
 
 
@@ -717,8 +717,8 @@ void ObjFileImporter::createMaterials(const ObjFile::Model *pModel, aiScene *pSc
 //  Appends this node to the parent node
 //  Appends this node to the parent node
 void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild) {
 void ObjFileImporter::appendChildToParentNode(aiNode *pParent, aiNode *pChild) {
     // Checking preconditions
     // Checking preconditions
-    ai_assert(NULL != pParent);
-    ai_assert(NULL != pChild);
+    ai_assert(nullptr != pParent);
+    ai_assert(nullptr != pChild);
 
 
     // Assign parent to child
     // Assign parent to child
     pChild->mParent = pParent;
     pChild->mParent = pParent;

Деякі файли не було показано, через те що забагато файлів було змінено