Просмотр исходного кода

Merge remote-tracking branch 'upstream/master'

RichardTea 5 лет назад
Родитель
Сommit
a52b66f10d
100 измененных файлов с 3764 добавлено и 3040 удалено
  1. 1 1
      .github/FUNDING.yml
  2. 47 20
      .github/workflows/ccpp.yml
  3. 29 29
      CMakeLists.txt
  4. 2 4
      assimp.pc.in
  5. 12 15
      assimpTargets-debug.cmake.in
  6. 12 13
      assimpTargets-release.cmake.in
  7. 1 14
      assimpTargets.cmake.in
  8. 0 3
      code/3DS/3DSConverter.cpp
  9. 45 23
      code/3DS/3DSHelper.h
  10. 5 11
      code/3DS/3DSLoader.cpp
  11. 1 5
      code/3DS/3DSLoader.h
  12. 26 14
      code/3MF/D3MFExporter.cpp
  13. 2 2
      code/ASE/ASEParser.cpp
  14. 4 0
      code/Assjson/cencode.c
  15. 1 1
      code/Assxml/AssxmlExporter.cpp
  16. 1 1
      code/Blender/BlenderBMesh.cpp
  17. 1 1
      code/Blender/BlenderLoader.cpp
  18. 3 3
      code/CApi/AssimpCExport.cpp
  19. 8 0
      code/CMakeLists.txt
  20. 1 1
      code/CSM/CSMLoader.cpp
  21. 226 263
      code/Common/Assimp.cpp
  22. 32 3
      code/Common/Exporter.cpp
  23. 12 13
      code/Common/SceneCombiner.cpp
  24. 117 134
      code/Common/SpatialSort.cpp
  25. 18 24
      code/FBX/FBXImportSettings.h
  26. 0 1
      code/FBX/FBXImporter.cpp
  27. 20 23
      code/FBX/FBXImporter.h
  28. 1 0
      code/Irr/IRRLoader.cpp
  29. 41 36
      code/M3D/M3DExporter.cpp
  30. 53 52
      code/M3D/M3DWrapper.cpp
  31. 23 17
      code/M3D/m3d.h
  32. 1 1
      code/Material/MaterialSystem.cpp
  33. 57 66
      code/PostProcessing/LimitBoneWeightsProcess.cpp
  34. 1 1
      code/Q3BSP/Q3BSPFileImporter.cpp
  35. 1 1
      code/SMD/SMDLoader.cpp
  36. 66 82
      code/Terragen/TerragenLoader.cpp
  37. 18 24
      code/Terragen/TerragenLoader.h
  38. 212 141
      code/Unreal/UnrealLoader.cpp
  39. 12 117
      code/Unreal/UnrealLoader.h
  40. 1 1
      code/XGL/XGLLoader.cpp
  41. 6 1
      code/glTF/glTFAsset.h
  42. 17 3
      code/glTF2/glTF2Asset.h
  43. 38 12
      code/glTF2/glTF2Asset.inl
  44. 4 0
      code/glTF2/glTF2Importer.cpp
  45. 5 1
      contrib/irrXML/CMakeLists.txt
  46. 20 33
      contrib/irrXML/CXMLReaderImpl.h
  47. 139 0
      contrib/irrXML/fast_atof.h
  48. 2 1
      contrib/irrXML/irrArray.h
  49. 4 7
      contrib/irrXML/irrString.h
  50. 4 11
      contrib/irrXML/irrTypes.h
  51. 2 6
      contrib/irrXML/irrXML.cpp
  52. 11 17
      contrib/irrXML/irrXML.h
  53. 28 13
      include/assimp/MathFunctions.h
  54. 164 0
      include/assimp/SmallVector.h
  55. 24 28
      include/assimp/SpatialSort.h
  56. 84 86
      include/assimp/StreamReader.h
  57. 17 0
      include/assimp/StringUtils.h
  58. 17 6
      include/assimp/camera.h
  59. 155 145
      include/assimp/metadata.h
  60. 4 4
      packaging/windows-innosetup/script_x64.iss
  61. 4 4
      packaging/windows-innosetup/script_x86.iss
  62. 12 6
      samples/SimpleOpenGL/CMakeLists.txt
  63. 72 12
      samples/SimpleOpenGL/Sample_SimpleOpenGL.c
  64. 24 24
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h
  65. 27 27
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp
  66. 6 6
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h
  67. 31 31
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp
  68. 1 2
      samples/SimpleTexturedOpenGL/CMakeLists.txt
  69. 0 1
      samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/include/boost_includes.h
  70. 66 64
      samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp
  71. 14 0
      test/CMakeLists.txt
  72. BIN
      test/models/TER/RealisticTerrain.ter
  73. 25 0
      test/models/glTF2/RecursiveNodes/RecursiveNodes.gltf
  74. 151 0
      test/unit/AssimpAPITest_aiMatrix3x3.cpp
  75. 259 0
      test/unit/AssimpAPITest_aiMatrix4x4.cpp
  76. 135 0
      test/unit/AssimpAPITest_aiQuaternion.cpp
  77. 140 0
      test/unit/AssimpAPITest_aiVector2D.cpp
  78. 185 0
      test/unit/AssimpAPITest_aiVector3D.cpp
  79. 93 0
      test/unit/Common/uiScene.cpp
  80. 84 0
      test/unit/Common/utSpatialSort.cpp
  81. 76 0
      test/unit/ImportExport/Assxml/utAssxmlImportExport.cpp
  82. 66 0
      test/unit/ImportExport/IRR/utIrrImportExport.cpp
  83. 64 0
      test/unit/ImportExport/RAW/utRAWImportExport.cpp
  84. 60 0
      test/unit/ImportExport/Terragen/utTerragenImportExport.cpp
  85. 0 1
      test/unit/ImportExport/utCOBImportExport.cpp
  86. 0 1
      test/unit/ImportExport/utOFFImportExport.cpp
  87. 0 1
      test/unit/ImportExport/utOgreImportExport.cpp
  88. 0 1
      test/unit/ImportExport/utQ3BSPFileImportExport.cpp
  89. 56 0
      test/unit/MathTest.cpp
  90. 103 0
      test/unit/MathTest.h
  91. 82 0
      test/unit/RandomNumberGeneration.h
  92. 0 1
      test/unit/ut3DSImportExport.cpp
  93. 0 1
      test/unit/utAMFImportExport.cpp
  94. 0 1
      test/unit/utASEImportExport.cpp
  95. 0 1
      test/unit/utArmaturePopulate.cpp
  96. 0 1
      test/unit/utAssbinImportExport.cpp
  97. 0 1
      test/unit/utB3DImportExport.cpp
  98. 0 1
      test/unit/utDXFImporterExporter.cpp
  99. 4 1
      test/unit/utFBXImporterExporter.cpp
  100. 65 1316
      test/unit/utImporter.cpp

+ 1 - 1
.github/FUNDING.yml

@@ -1,2 +1,2 @@
 patreon: assimp
 patreon: assimp
-Paypal: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4
+custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4

+ 47 - 20
.github/workflows/ccpp.yml

@@ -7,26 +7,53 @@ on:
     branches: [ master ]
     branches: [ master ]
 
 
 jobs:
 jobs:
-  linux:
-    runs-on: ubuntu-latest
-    
+  job:
+    name: ${{ matrix.os }}-${{ matrix.cxx }}-build-and-test
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        name: [ubuntu-gcc, macos-clang, windows-msvc, ubuntu-clang]
+        # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux.
+        include:
+          - name: windows-msvc
+            os: windows-latest
+            cxx: cl.exe
+            cc: cl.exe
+          - name: ubuntu-clang
+            os: ubuntu-latest
+            cxx: clang++
+            cc: clang
+          - name: macos-clang
+            os: macos-latest
+            cxx: clang++
+            cc: clang
+          - name: ubuntu-gcc
+            os: ubuntu-latest
+            cxx: g++
+            cc: gcc
+
     steps:
     steps:
-    - uses: actions/checkout@v1
-    - name: configure
-      run: cmake CMakeLists.txt
-    - name: build
-      run: cmake --build .
-    - name: test
-      run: cd bin && ./unit
-  
-  mac:
-    runs-on: macos-latest
+    - uses: actions/checkout@v2
     
     
-    steps:
-    - uses: actions/checkout@v1
-    - name: configure
-      run: cmake CMakeLists.txt
-    - name: build
-      run: cmake --build .
+    - uses: lukka/get-cmake@latest
+    
+    - uses: ilammy/msvc-dev-cmd@v1
+    
+    - uses: lukka/set-shell-env@v1
+      with:
+        CXX: ${{ matrix.cxx }}
+        CC: ${{ matrix.cc }}
+    
+    - name: configure and build
+      uses: lukka/run-cmake@v2
+      with:
+        cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
+        cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
+        cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release'
+        buildWithCMakeArgs: '-- -v'
+        buildDirectory: '${{ github.workspace }}/build/'
+        
     - name: test
     - name: test
-      run: cd bin && ./unit
+      run: cd build/bin && ./unit
+      shell: bash

+ 29 - 29
CMakeLists.txt

@@ -108,10 +108,6 @@ OPTION ( ASSIMP_ERROR_MAX
   "Enable all warnings."
   "Enable all warnings."
   OFF
   OFF
 )
 )
-OPTION ( ASSIMP_WERROR
-  "Treat warnings as errors."
-  OFF
-)
 OPTION ( ASSIMP_ASAN
 OPTION ( ASSIMP_ASAN
   "Enable AddressSanitizer."
   "Enable AddressSanitizer."
   OFF
   OFF
@@ -243,14 +239,14 @@ IF( UNIX )
   INCLUDE(GNUInstallDirs)
   INCLUDE(GNUInstallDirs)
 ENDIF()
 ENDIF()
 
 
-# Grouped compiler settings
+# Grouped compiler settings ########################################
 IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
 IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
   IF(NOT ASSIMP_HUNTER_ENABLED)
   IF(NOT ASSIMP_HUNTER_ENABLED)
-    SET(CMAKE_CXX_FLAGS "-fPIC -std=c++0x ${CMAKE_CXX_FLAGS}")
-    SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
+    SET(CMAKE_CXX_STANDARD 11)
+    SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
   ENDIF()
   ENDIF()
   # hide all not-exported symbols
   # hide all not-exported symbols
-  SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
+  SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
   SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
   SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
   SET(LIBSTDC++_LIBRARIES -lstdc++)
   SET(LIBSTDC++_LIBRARIES -lstdc++)
 ELSEIF(MSVC)
 ELSEIF(MSVC)
@@ -263,10 +259,10 @@ ELSEIF(MSVC)
   SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
   SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
 ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
 ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
   IF(NOT ASSIMP_HUNTER_ENABLED)
   IF(NOT ASSIMP_HUNTER_ENABLED)
-    SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
-    SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
+    SET(CMAKE_CXX_STANDARD 11)
+    SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
   ENDIF()
   ENDIF()
-  SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
+  SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
   SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
   SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
 ELSEIF( CMAKE_COMPILER_IS_MINGW )
 ELSEIF( CMAKE_COMPILER_IS_MINGW )
   IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
   IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
@@ -311,16 +307,6 @@ IF (ASSIMP_ERROR_MAX)
   ENDIF()
   ENDIF()
 ENDIF()
 ENDIF()
 
 
-IF (ASSIMP_WERROR)
-  MESSAGE(STATUS "Treating warnings as errors")
-  IF (MSVC)
-    ADD_COMPILE_OPTIONS(/WX)
-  ELSE()
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
-    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
-  ENDIF()
-ENDIF()
-
 IF (ASSIMP_ASAN)
 IF (ASSIMP_ASAN)
   MESSAGE(STATUS "AddressSanitizer enabled")
   MESSAGE(STATUS "AddressSanitizer enabled")
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
@@ -350,14 +336,6 @@ ELSE()
   SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
   SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
 ENDIF ()
 ENDIF ()
 
 
-# Cache these to allow the user to override them manually.
-SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE STRING
-  "Path the built library files are installed to." )
-SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE STRING
-  "Path the header files are installed to." )
-SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE STRING
-  "Path the tool executables are installed to." )
-
 get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
 get_cmake_property(is_multi_config GENERATOR_IS_MULTI_CONFIG)
 
 
 IF (ASSIMP_INJECT_DEBUG_POSTFIX AND (is_multi_config OR CMAKE_BUILD_TYPE STREQUAL "Debug"))
 IF (ASSIMP_INJECT_DEBUG_POSTFIX AND (is_multi_config OR CMAKE_BUILD_TYPE STREQUAL "Debug"))
@@ -417,6 +395,28 @@ ELSE()
   else()
   else()
     set(BUILD_LIB_TYPE STATIC)
     set(BUILD_LIB_TYPE STATIC)
   endif()
   endif()
+
+  IF( UNIX )
+    # Use GNUInstallDirs for Unix predefined directories
+    INCLUDE(GNUInstallDirs)
+
+    SET( ASSIMP_LIB_INSTALL_DIR ${CMAKE_INSTALL_LIBDIR})
+    SET( ASSIMP_INCLUDE_INSTALL_DIR ${CMAKE_INSTALL_INCLUDEDIR})
+    SET( ASSIMP_BIN_INSTALL_DIR ${CMAKE_INSTALL_BINDIR})
+  ELSE()
+    # Cache these to allow the user to override them on non-Unix platforms
+    SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE STRING
+      "Path the built library files are installed to." )
+    SET( ASSIMP_INCLUDE_INSTALL_DIR "include" CACHE STRING
+      "Path the header files are installed to." )
+    SET( ASSIMP_BIN_INSTALL_DIR "bin" CACHE STRING
+      "Path the tool executables are installed to." )
+
+    SET(CMAKE_INSTALL_FULL_INCLUDEDIR ${CMAKE_INSTALL_PREFIX}/${ASSIMP_INCLUDE_INSTALL_DIR})
+    SET(CMAKE_INSTALL_FULL_LIBDIR ${CMAKE_INSTALL_PREFIX}/${ASSIMP_LIB_INSTALL_DIR})
+    SET(CMAKE_INSTALL_FULL_BINDIR ${CMAKE_INSTALL_PREFIX}/${ASSIMP_BIN_INSTALL_DIR})
+  ENDIF()
+
   CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in"         "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
   CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in"         "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
   CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets.cmake.in"         "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake" @ONLY IMMEDIATE)
   CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimpTargets.cmake.in"         "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake" @ONLY IMMEDIATE)
   IF (is_multi_config)
   IF (is_multi_config)

+ 2 - 4
assimp.pc.in

@@ -1,7 +1,5 @@
-prefix=@CMAKE_INSTALL_PREFIX@
-exec_prefix=@CMAKE_INSTALL_PREFIX@/
-libdir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_LIB_INSTALL_DIR@
-includedir=@CMAKE_INSTALL_PREFIX@/@ASSIMP_INCLUDE_INSTALL_DIR@
+libdir=@CMAKE_INSTALL_FULL_LIBDIR@
+includedir=@CMAKE_INSTALL_FULL_INCLUDEDIR@
 
 
 Name: @CMAKE_PROJECT_NAME@
 Name: @CMAKE_PROJECT_NAME@
 Description: Import various well-known 3D model formats in an uniform manner.
 Description: Import various well-known 3D model formats in an uniform manner.

+ 12 - 15
assimpTargets-debug.cmake.in

@@ -7,6 +7,8 @@ set(CMAKE_IMPORT_FILE_VERSION 1)
 
 
 set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@)
 set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@)
 
 
+get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)
+
 if(MSVC)
 if(MSVC)
   if(MSVC_TOOLSET_VERSION)
   if(MSVC_TOOLSET_VERSION)
     set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
     set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
@@ -35,8 +37,6 @@ if(MSVC)
   endif()
   endif()
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
 
 
-  file(TO_NATIVE_PATH "${_IMPORT_PREFIX}" _IMPORT_PREFIX)
-
   if(ASSIMP_BUILD_SHARED_LIBS)
   if(ASSIMP_BUILD_SHARED_LIBS)
     set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@")
     set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@")
     set(importLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@")
     set(importLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_IMPORT_LIBRARY_SUFFIX@")
@@ -44,22 +44,22 @@ if(MSVC)
     # Import target "assimp::assimp" for configuration "Debug"
     # Import target "assimp::assimp" for configuration "Debug"
     set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
     set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS DEBUG)
     set_target_properties(assimp::assimp PROPERTIES
     set_target_properties(assimp::assimp PROPERTIES
-      IMPORTED_IMPLIB_DEBUG "${_IMPORT_PREFIX}/lib/${importLibraryName}"
-      IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/bin/${sharedLibraryName}"
+      IMPORTED_IMPLIB_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${importLibraryName}"
+      IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_BINDIR@/${sharedLibraryName}"
     )
     )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
-    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${importLibraryName}")
-    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" )
+    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${importLibraryName}")
+    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_BINDIR@/${sharedLibraryName}" )
   else()
   else()
     set(staticLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@")
     set(staticLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_STATIC_LIBRARY_SUFFIX@")
 
 
     # Import target "assimp::assimp" for configuration "Debug"
     # Import target "assimp::assimp" for configuration "Debug"
     set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS 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 "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
+      IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
     )
     )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
-    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}")
+    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}")
   endif()
   endif()
 
 
 else()
 else()
@@ -75,23 +75,20 @@ else()
     endif()
     endif()
     set_target_properties(assimp::assimp PROPERTIES
     set_target_properties(assimp::assimp PROPERTIES
       IMPORTED_SONAME_DEBUG "${sharedLibraryName}"
       IMPORTED_SONAME_DEBUG "${sharedLibraryName}"
-      IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${sharedLibraryName}"
+      IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}"
     )
     )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
-    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${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@")
     set_target_properties(assimp::assimp PROPERTIES
     set_target_properties(assimp::assimp PROPERTIES
-      IMPORTED_LOCATION_DEBUG "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
+      IMPORTED_LOCATION_DEBUG "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
     )
     )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
-    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}" )
+    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}" )
   endif()
   endif()
 endif()
 endif()
 
 
-
-
-
 # Commands beyond this point should not need to know the version.
 # Commands beyond this point should not need to know the version.
 set(CMAKE_IMPORT_FILE_VERSION)
 set(CMAKE_IMPORT_FILE_VERSION)
 
 

+ 12 - 13
assimpTargets-release.cmake.in

@@ -7,6 +7,8 @@ set(CMAKE_IMPORT_FILE_VERSION 1)
 
 
 set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@)
 set(ASSIMP_BUILD_SHARED_LIBS @BUILD_SHARED_LIBS@)
 
 
+get_property(LIB64 GLOBAL PROPERTY FIND_LIBRARY_USE_LIB64_PATHS)
+
 if(MSVC)
 if(MSVC)
   if(MSVC_TOOLSET_VERSION)
   if(MSVC_TOOLSET_VERSION)
     set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
     set(MSVC_PREFIX "vc${MSVC_TOOLSET_VERSION}")
@@ -34,8 +36,6 @@ if(MSVC)
     endif()
     endif()
   endif()
   endif()
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
-  	
-  file(TO_NATIVE_PATH "${_IMPORT_PREFIX}" _IMPORT_PREFIX)
 
 
   if(ASSIMP_BUILD_SHARED_LIBS)
   if(ASSIMP_BUILD_SHARED_LIBS)
     set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@")
     set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@")
@@ -44,22 +44,22 @@ if(MSVC)
     # Import target "assimp::assimp" for configuration "Release"
     # Import target "assimp::assimp" for configuration "Release"
     set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
     set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS RELEASE)
     set_target_properties(assimp::assimp PROPERTIES
     set_target_properties(assimp::assimp PROPERTIES
-      IMPORTED_IMPLIB_RELEASE "${_IMPORT_PREFIX}/lib/${importLibraryName}"
-      IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/bin/${sharedLibraryName}"
+      IMPORTED_IMPLIB_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${importLibraryName}"
+      IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_BINDIR@/${sharedLibraryName}"
     )
     )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
-    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${importLibraryName}")
-    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/bin/${sharedLibraryName}" )
+    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${importLibraryName}")
+    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_BINDIR@/${sharedLibraryName}" )
   else()
   else()
     set(staticLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@")
     set(staticLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_STATIC_LIBRARY_SUFFIX@")
 
 
     # Import target "assimp::assimp" for configuration "Release"
     # Import target "assimp::assimp" for configuration "Release"
     set_property(TARGET assimp::assimp APPEND PROPERTY IMPORTED_CONFIGURATIONS 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 "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
+      IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
     )
     )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
-    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}")
+    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}")
   endif()
   endif()
 
 
 else()
 else()
@@ -75,18 +75,17 @@ else()
     endif()
     endif()
     set_target_properties(assimp::assimp PROPERTIES
     set_target_properties(assimp::assimp PROPERTIES
       IMPORTED_SONAME_RELEASE "${sharedLibraryName}"
       IMPORTED_SONAME_RELEASE "${sharedLibraryName}"
-
-      IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${sharedLibraryName}"
+      IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${sharedLibraryName}"
     )
     )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
-    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${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@")
     set_target_properties(assimp::assimp PROPERTIES
     set_target_properties(assimp::assimp PROPERTIES
-      IMPORTED_LOCATION_RELEASE "${_IMPORT_PREFIX}/lib/${staticLibraryName}"
+      IMPORTED_LOCATION_RELEASE "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}"
     )
     )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
     list(APPEND _IMPORT_CHECK_TARGETS assimp::assimp )
-    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "${_IMPORT_PREFIX}/lib/${staticLibraryName}" )
+    list(APPEND _IMPORT_CHECK_FILES_FOR_assimp::assimp "@CMAKE_INSTALL_FULL_LIBDIR@/${staticLibraryName}" )
   endif()
   endif()
 endif()
 endif()
 
 

+ 1 - 14
assimpTargets.cmake.in

@@ -43,23 +43,13 @@ unset(_targetsDefined)
 unset(_targetsNotDefined)
 unset(_targetsNotDefined)
 unset(_expectedTargets)
 unset(_expectedTargets)
 
 
-
-# Compute the installation prefix relative to this file.
-get_filename_component(_IMPORT_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
-get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
-get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
-get_filename_component(_IMPORT_PREFIX "${_IMPORT_PREFIX}" PATH)
-if(_IMPORT_PREFIX STREQUAL "/")
-  set(_IMPORT_PREFIX "")
-endif()
-
 # Create imported target assimp::assimp
 # Create imported target assimp::assimp
 add_library(assimp::assimp @BUILD_LIB_TYPE@ IMPORTED)
 add_library(assimp::assimp @BUILD_LIB_TYPE@ IMPORTED)
 
 
 set_target_properties(assimp::assimp PROPERTIES
 set_target_properties(assimp::assimp PROPERTIES
   COMPATIBLE_INTERFACE_STRING "assimp_MAJOR_VERSION"
   COMPATIBLE_INTERFACE_STRING "assimp_MAJOR_VERSION"
   INTERFACE_assimp_MAJOR_VERSION "1"
   INTERFACE_assimp_MAJOR_VERSION "1"
-  INTERFACE_INCLUDE_DIRECTORIES "${_IMPORT_PREFIX}/include;${_IMPORT_PREFIX}/include"
+  INTERFACE_INCLUDE_DIRECTORIES "@CMAKE_INSTALL_FULL_INCLUDEDIR@"
   #INTERFACE_LINK_LIBRARIES "TxtUtils::TxtUtils;MealyMachine::MealyMachine"
   #INTERFACE_LINK_LIBRARIES "TxtUtils::TxtUtils;MealyMachine::MealyMachine"
 )
 )
 
 
@@ -74,9 +64,6 @@ foreach(f ${CONFIG_FILES})
   include(${f})
   include(${f})
 endforeach()
 endforeach()
 
 
-# Cleanup temporary variables.
-set(_IMPORT_PREFIX)
-
 # Loop over all imported files and verify that they actually exist
 # Loop over all imported files and verify that they actually exist
 foreach(target ${_IMPORT_CHECK_TARGETS} )
 foreach(target ${_IMPORT_CHECK_TARGETS} )
   foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )
   foreach(file ${_IMPORT_CHECK_FILES_FOR_${target}} )

+ 0 - 3
code/3DS/3DSConverter.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,7 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 /** @file Implementation of the 3ds importer class */
 /** @file Implementation of the 3ds importer class */
 
 
-
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 
 // internal headers
 // internal headers

+ 45 - 23
code/3DS/3DSHelper.h

@@ -322,7 +322,7 @@ struct Face : public FaceWithSmoothingGroup {
 };
 };
 
 
 #ifdef _WIN32
 #ifdef _WIN32
-#    pragma warning(disable : 4315)
+#pragma warning(disable : 4315)
 #endif
 #endif
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -441,30 +441,52 @@ struct Material {
         // empty
         // empty
     }
     }
 
 
-    Material(const Material &other) = default;
-    Material &operator=(const Material &other) = default;
+    Material(const Material &other) :
+            mName(other.mName),
+            mDiffuse(other.mDiffuse),
+            mSpecularExponent(other.mSpecularExponent),
+            mShininessStrength(other.mShininessStrength),
+            mSpecular(other.mSpecular),
+            mAmbient(other.mAmbient),
+            mShading(other.mShading),
+            mTransparency(other.mTransparency),
+            sTexDiffuse(other.sTexDiffuse),
+            sTexOpacity(other.sTexOpacity),
+            sTexSpecular(other.sTexSpecular),
+            sTexReflective(other.sTexReflective),
+            sTexBump(other.sTexBump),
+            sTexEmissive(other.sTexEmissive),
+            sTexShininess(other.sTexShininess),
+            mBumpHeight(other.mBumpHeight),
+            mEmissive(other.mEmissive),
+            sTexAmbient(other.sTexAmbient),
+            mTwoSided(other.mTwoSided) {
+        // empty
+
+    }
 
 
     //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
     //! 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
     }
     }
 
 
     Material &operator=(Material &&other) AI_NO_EXCEPT {
     Material &operator=(Material &&other) AI_NO_EXCEPT {

+ 5 - 11
code/3DS/3DSLoader.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,
@@ -72,7 +70,6 @@ static const aiImporterDesc desc = {
 	"3ds prj"
 	"3ds prj"
 };
 };
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Begins a new parsing block
 // Begins a new parsing block
 // - Reads the current chunk and validates it
 // - Reads the current chunk and validates it
@@ -141,15 +138,13 @@ bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandle
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Loader registry entry
 // Loader registry entry
-const aiImporterDesc* Discreet3DSImporter::GetInfo () const
-{
+const aiImporterDesc* Discreet3DSImporter::GetInfo () const {
     return &desc;
     return &desc;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Setup configuration properties
 // Setup configuration properties
-void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/)
-{
+void Discreet3DSImporter::SetupProperties(const Importer* /*pImp*/) {
     // nothing to be done for the moment
     // nothing to be done for the moment
 }
 }
 
 
@@ -200,7 +195,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
         ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh);
         ComputeNormalsWithSmoothingsGroups<D3DS::Face>(mesh);
     }
     }
 
 
-    // Replace all occurences of the default material with a
+    // Replace all occurrences of the default material with a
     // valid material. Generate it if no material containing
     // valid material. Generate it if no material containing
     // DEFAULT in its name has been found in the file
     // DEFAULT in its name has been found in the file
     ReplaceDefaultMaterial();
     ReplaceDefaultMaterial();
@@ -227,8 +222,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Applies a master-scaling factor to the imported scene
 // Applies a master-scaling factor to the imported scene
-void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene)
-{
+void Discreet3DSImporter::ApplyMasterScale(aiScene* pScene) {
     // There are some 3DS files with a zero scaling factor
     // There are some 3DS files with a zero scaling factor
     if (!mMasterScale)mMasterScale = 1.0f;
     if (!mMasterScale)mMasterScale = 1.0f;
     else mMasterScale = 1.0f / mMasterScale;
     else mMasterScale = 1.0f / mMasterScale;
@@ -1084,7 +1078,7 @@ void Discreet3DSImporter::ParseMeshChunk()
         mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd);
         mMesh.mFaceMaterials.resize(mMesh.mFaces.size(),0xcdcdcdcd);
 
 
         // Larger 3DS files could have multiple FACE chunks here
         // Larger 3DS files could have multiple FACE chunks here
-        chunkSize = stream->GetRemainingSizeToLimit();
+        chunkSize = (int)stream->GetRemainingSizeToLimit();
         if ( chunkSize > (int) sizeof(Discreet3DS::Chunk ) )
         if ( chunkSize > (int) sizeof(Discreet3DS::Chunk ) )
             ParseFaceChunk();
             ParseFaceChunk();
         }
         }

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

@@ -65,15 +65,11 @@ using namespace D3DS;
 // ---------------------------------------------------------------------------------
 // ---------------------------------------------------------------------------------
 /** Importer class for 3D Studio r3 and r4 3DS files
 /** Importer class for 3D Studio r3 and r4 3DS files
  */
  */
-class Discreet3DSImporter : public BaseImporter
-{
+class Discreet3DSImporter : public BaseImporter {
 public:
 public:
-
     Discreet3DSImporter();
     Discreet3DSImporter();
     ~Discreet3DSImporter();
     ~Discreet3DSImporter();
 
 
-public:
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.
     /** Returns whether the class can handle the format of the given file.
      * See BaseImporter::CanRead() for details.
      * See BaseImporter::CanRead() for details.

+ 26 - 14
code/3MF/D3MFExporter.cpp

@@ -181,7 +181,7 @@ bool D3MFExporter::export3DModel() {
 
 
     writeHeader();
     writeHeader();
     mModelOutput << "<" << XmlTag::model << " " << XmlTag::model_unit << "=\"millimeter\""
     mModelOutput << "<" << XmlTag::model << " " << XmlTag::model_unit << "=\"millimeter\""
-            << "xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">"
+            << " xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">"
             << std::endl;
             << std::endl;
     mModelOutput << "<" << XmlTag::resources << ">";
     mModelOutput << "<" << XmlTag::resources << ">";
     mModelOutput << std::endl;
     mModelOutput << std::endl;
@@ -212,7 +212,7 @@ bool D3MFExporter::export3DModel() {
 }
 }
 
 
 void D3MFExporter::writeHeader() {
 void D3MFExporter::writeHeader() {
-    mModelOutput << "<?xml version=\"1.0\" encoding=\"UTF - 8\"?>";
+    mModelOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
     mModelOutput << std::endl;
     mModelOutput << std::endl;
 }
 }
 
 
@@ -254,16 +254,28 @@ void D3MFExporter::writeBaseMaterials() {
         if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) {
         if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) {
             hexDiffuseColor.clear();
             hexDiffuseColor.clear();
             tmp.clear();
             tmp.clear();
-            hexDiffuseColor = "#";
-            
-            tmp = DecimalToHexa( (ai_real) color.r );
-            hexDiffuseColor += tmp;
-            tmp = DecimalToHexa((ai_real)color.g);
-            hexDiffuseColor += tmp;
-            tmp = DecimalToHexa((ai_real)color.b);
-            hexDiffuseColor += tmp;
-            tmp = DecimalToHexa((ai_real)color.a);
-            hexDiffuseColor += tmp;
+            // rgbs %
+    		if(color.r <= 1 && color.g <= 1 && color.b <= 1 && color.a <= 1){
+    	
+    			 hexDiffuseColor = Rgba2Hex(
+    			 	(int)((ai_real)color.r)*255,
+    			 	(int)((ai_real)color.g)*255,
+    			 	(int)((ai_real)color.b)*255,
+    			 	(int)((ai_real)color.a)*255,
+    			 	true
+    			 );
+    			 
+    		}else{
+    			hexDiffuseColor = "#";
+            	tmp = DecimalToHexa( (ai_real) color.r );
+            	hexDiffuseColor += tmp;
+            	tmp = DecimalToHexa((ai_real)color.g);
+            	hexDiffuseColor += tmp;
+            	tmp = DecimalToHexa((ai_real)color.b);
+            	hexDiffuseColor += tmp;
+            	tmp = DecimalToHexa((ai_real)color.a);
+            	hexDiffuseColor += tmp;
+    		}
         } else {
         } else {
             hexDiffuseColor = "#FFFFFFFF";
             hexDiffuseColor = "#FFFFFFFF";
         }
         }
@@ -284,7 +296,7 @@ void D3MFExporter::writeObjects() {
         if ( nullptr == currentNode ) {
         if ( nullptr == currentNode ) {
             continue;
             continue;
         }
         }
-        mModelOutput << "<" << XmlTag::object << " id=\"" << currentNode->mName.C_Str() << "\" type=\"model\">";
+        mModelOutput << "<" << XmlTag::object << " id=\"" << i + 2 << "\" type=\"model\">";
         mModelOutput << std::endl;
         mModelOutput << std::endl;
         for ( unsigned int j = 0; j < currentNode->mNumMeshes; ++j ) {
         for ( unsigned int j = 0; j < currentNode->mNumMeshes; ++j ) {
             aiMesh *currentMesh = mScene->mMeshes[ currentNode->mMeshes[ j ] ];
             aiMesh *currentMesh = mScene->mMeshes[ currentNode->mMeshes[ j ] ];
@@ -348,7 +360,7 @@ void D3MFExporter::writeBuild() {
     mModelOutput << "<" << XmlTag::build << ">" << std::endl;
     mModelOutput << "<" << XmlTag::build << ">" << std::endl;
 
 
     for ( size_t i = 0; i < mBuildItems.size(); ++i ) {
     for ( size_t i = 0; i < mBuildItems.size(); ++i ) {
-        mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 1 << "\"/>";
+        mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>";
         mModelOutput << std::endl;
         mModelOutput << std::endl;
     }
     }
     mModelOutput << "</" << XmlTag::build << ">";
     mModelOutput << "</" << XmlTag::build << ">";

+ 2 - 2
code/ASE/ASEParser.cpp

@@ -142,11 +142,11 @@ void Parser::LogWarning(const char* szWarn)
 {
 {
     ai_assert(NULL != szWarn);
     ai_assert(NULL != szWarn);
 
 
-    char szTemp[1024];
+    char szTemp[2048];
 #if _MSC_VER >= 1400
 #if _MSC_VER >= 1400
     sprintf_s(szTemp, "Line %u: %s",iLineNumber,szWarn);
     sprintf_s(szTemp, "Line %u: %s",iLineNumber,szWarn);
 #else
 #else
-    ai_snprintf(szTemp,1024,"Line %u: %s",iLineNumber,szWarn);
+    ai_snprintf(szTemp,sizeof(szTemp),"Line %u: %s",iLineNumber,szWarn);
 #endif
 #endif
 
 
     // output the warning to the logger ...
     // output the warning to the logger ...

+ 4 - 0
code/Assjson/cencode.c

@@ -9,6 +9,9 @@ For details, see http://sourceforge.net/projects/libb64
 
 
 const int CHARS_PER_LINE = 72;
 const int CHARS_PER_LINE = 72;
 
 
+#pragma warning(push)
+#pragma warning(disable : 4244)
+
 void base64_init_encodestate(base64_encodestate* state_in)
 void base64_init_encodestate(base64_encodestate* state_in)
 {
 {
 	state_in->step = step_A;
 	state_in->step = step_A;
@@ -107,3 +110,4 @@ int base64_encode_blockend(char* code_out, base64_encodestate* state_in)
 	return (int)(codechar - code_out);
 	return (int)(codechar - code_out);
 }
 }
 
 
+#pragma warning(pop)

+ 1 - 1
code/Assxml/AssxmlExporter.cpp

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

+ 1 - 1
code/Blender/BlenderBMesh.cpp

@@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Conversion of Blender's new BMesh stuff
  *  @brief Conversion of Blender's new BMesh stuff
  */
  */
 
 
-
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 
 
 #include "BlenderDNA.h"
 #include "BlenderDNA.h"
@@ -181,6 +180,7 @@ void BlenderBMeshConverter::AddFace( int v1, int v2, int v3, int v4 )
     face.v2 = v2;
     face.v2 = v2;
     face.v3 = v3;
     face.v3 = v3;
     face.v4 = v4;
     face.v4 = v4;
+    face.flag = 0;
     // TODO - Work out how materials work
     // TODO - Work out how materials work
     face.mat_nr = 0;
     face.mat_nr = 0;
     triMesh->mface.push_back( face );
     triMesh->mface.push_back( face );

+ 1 - 1
code/Blender/BlenderLoader.cpp

@@ -206,7 +206,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
         inflateInit2(&zstream, 16+MAX_WBITS);
         inflateInit2(&zstream, 16+MAX_WBITS);
 
 
         zstream.next_in   = reinterpret_cast<Bytef*>( reader->GetPtr() );
         zstream.next_in   = reinterpret_cast<Bytef*>( reader->GetPtr() );
-        zstream.avail_in  = reader->GetRemainingSize();
+        zstream.avail_in  = (uInt) reader->GetRemainingSize();
 
 
         size_t total = 0l;
         size_t total = 0l;
 
 

+ 3 - 3
code/CApi/AssimpCExport.cpp

@@ -73,11 +73,11 @@ ASSIMP_API const aiExportFormatDesc* aiGetExportFormatDescription( size_t index)
 
 
     aiExportFormatDesc *desc = new aiExportFormatDesc;
     aiExportFormatDesc *desc = new aiExportFormatDesc;
     desc->description = new char[ strlen( orig->description ) + 1 ]();
     desc->description = new char[ strlen( orig->description ) + 1 ]();
-    ::strncpy( (char*) desc->description, orig->description, strlen( orig->description ) );
+    ::memcpy( (char*) desc->description, orig->description, strlen( orig->description ) );
     desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ]();
     desc->fileExtension = new char[ strlen( orig->fileExtension ) + 1 ]();
-    ::strncpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) );
+    ::memcpy( ( char* ) desc->fileExtension, orig->fileExtension, strlen( orig->fileExtension ) );
     desc->id = new char[ strlen( orig->id ) + 1 ]();
     desc->id = new char[ strlen( orig->id ) + 1 ]();
-    ::strncpy( ( char* ) desc->id, orig->id, strlen( orig->id ) );
+    ::memcpy( ( char* ) desc->id, orig->id, strlen( orig->id ) );
 
 
     return desc;
     return desc;
 }
 }

+ 8 - 0
code/CMakeLists.txt

@@ -121,6 +121,7 @@ SET( PUBLIC_HEADERS
   ${HEADER_PATH}/GenericProperty.h
   ${HEADER_PATH}/GenericProperty.h
   ${HEADER_PATH}/SpatialSort.h
   ${HEADER_PATH}/SpatialSort.h
   ${HEADER_PATH}/SkeletonMeshBuilder.h
   ${HEADER_PATH}/SkeletonMeshBuilder.h
+  ${HEADER_PATH}/SmallVector.h
   ${HEADER_PATH}/SmoothingGroups.h
   ${HEADER_PATH}/SmoothingGroups.h
   ${HEADER_PATH}/SmoothingGroups.inl
   ${HEADER_PATH}/SmoothingGroups.inl
   ${HEADER_PATH}/StandardShapes.h
   ${HEADER_PATH}/StandardShapes.h
@@ -1133,6 +1134,13 @@ ENDIF ()
 ADD_LIBRARY( assimp ${assimp_src} )
 ADD_LIBRARY( assimp ${assimp_src} )
 ADD_LIBRARY(assimp::assimp ALIAS assimp)
 ADD_LIBRARY(assimp::assimp ALIAS assimp)
 
 
+# enable warnings as errors ########################################
+IF (MSVC)
+  TARGET_COMPILE_OPTIONS(assimp PRIVATE /WX)
+ELSE()
+  TARGET_COMPILE_OPTIONS(assimp PRIVATE -Werror)
+ENDIF()
+
 TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
 TARGET_INCLUDE_DIRECTORIES ( assimp PUBLIC
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
   $<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/../include>
   $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>
   $<BUILD_INTERFACE:${CMAKE_CURRENT_BINARY_DIR}/../include>

+ 1 - 1
code/CSM/CSMLoader.cpp

@@ -178,7 +178,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
                         *ot++ = *buffer++;
                         *ot++ = *buffer++;
 
 
                     *ot = '\0';
                     *ot = '\0';
-                    nda->mNodeName.length = (ai_uint32)(ot-nda->mNodeName.data);
+                    nda->mNodeName.length = static_cast<ai_uint32>(ot-nda->mNodeName.data);
                 }
                 }
 
 
                 anim->mNumChannels = static_cast<unsigned int>(anims_temp.size());
                 anim->mNumChannels = static_cast<unsigned int>(anims_temp.size());

Разница между файлами не показана из-за своего большого размера
+ 226 - 263
code/Common/Assimp.cpp


+ 32 - 3
code/Common/Exporter.cpp

@@ -83,32 +83,61 @@ namespace Assimp {
 void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
 void GetPostProcessingStepInstanceList(std::vector< BaseProcess* >& out);
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-// Exporter worker function prototypes. Should not be necessary to #ifndef them, it's just a prototype
-// do not use const, because some exporter need to convert the scene temporary
+// Exporter worker function prototypes. Do not use const, because some exporter need to convert 
+// the scene temporary
+#ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
 void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneCollada(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_X_EXPORTER
 void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneXFile(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_STEP_EXPORTER
 void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneStep(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_OBJ_EXPORTER
 void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneObj(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneObjNoMtl(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneObjNoMtl(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_STL_EXPORTER
 void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneSTL(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneSTLBinary(const char*,IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_PLY_EXPORTER
 void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportScenePly(const char*,IOSystem*, const aiScene*, const ExportProperties*);
 void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportScenePlyBinary(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
 void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportScene3DS(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
 void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneGLTF(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneGLB(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneGLTF2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
 void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
 void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_X3D_EXPORTER
 void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
 void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
 void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
 void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
+#endif
+#ifndef ASSIMP_BUILD_NO_M3D_EXPORTER
 void ExportSceneM3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneM3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneM3DA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneM3DA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+#endif
+#ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER
 void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*);
 void ExportAssimp2Json(const char* , IOSystem*, const aiScene* , const Assimp::ExportProperties*);
-
+#endif
 
 
 static void setupExporterArray(std::vector<Exporter::ExportFormatEntry> &exporters) {
 static void setupExporterArray(std::vector<Exporter::ExportFormatEntry> &exporters) {
 #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
 #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER

+ 12 - 13
code/Common/SceneCombiner.cpp

@@ -979,7 +979,7 @@ void GetArrayCopy(Type*& dest, ai_uint num ) {
 
 
     dest = new Type[num];
     dest = new Type[num];
     ::memcpy(dest, old, sizeof(Type) * num);
     ::memcpy(dest, old, sizeof(Type) * num);
-}
+    }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) {
 void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) {
@@ -994,8 +994,7 @@ void SceneCombiner::CopySceneFlat(aiScene** _dest,const aiScene* src) {
     } else {
     } else {
         *_dest = new aiScene();
         *_dest = new aiScene();
     }
     }
-
-    ::memcpy(*_dest,src,sizeof(aiScene));
+    CopyScene(_dest, src, false);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -1066,7 +1065,7 @@ void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) {
     aiMesh* dest = *_dest = new aiMesh();
     aiMesh* dest = *_dest = new aiMesh();
 
 
     // get a flat copy
     // get a flat copy
-    ::memcpy(dest,src,sizeof(aiMesh));
+    *dest = *src;
 
 
     // and reallocate all arrays
     // and reallocate all arrays
     GetArrayCopy( dest->mVertices,   dest->mNumVertices );
     GetArrayCopy( dest->mVertices,   dest->mNumVertices );
@@ -1105,7 +1104,7 @@ void SceneCombiner::Copy(aiAnimMesh** _dest, const aiAnimMesh* src) {
     aiAnimMesh* dest = *_dest = new aiAnimMesh();
     aiAnimMesh* dest = *_dest = new aiAnimMesh();
 
 
     // get a flat copy
     // get a flat copy
-    ::memcpy(dest, src, sizeof(aiAnimMesh));
+    *dest = *src;
 
 
     // and reallocate all arrays
     // and reallocate all arrays
     GetArrayCopy(dest->mVertices, dest->mNumVertices);
     GetArrayCopy(dest->mVertices, dest->mNumVertices);
@@ -1162,7 +1161,7 @@ void SceneCombiner::Copy(aiTexture** _dest, const aiTexture* src) {
     aiTexture* dest = *_dest = new aiTexture();
     aiTexture* dest = *_dest = new aiTexture();
 
 
     // get a flat copy
     // get a flat copy
-    ::memcpy(dest,src,sizeof(aiTexture));
+    *dest = *src;
 
 
     // and reallocate all arrays. We must do it manually here
     // and reallocate all arrays. We must do it manually here
     const char* old = (const char*)dest->pcData;
     const char* old = (const char*)dest->pcData;
@@ -1192,7 +1191,7 @@ void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) {
     aiAnimation* dest = *_dest = new aiAnimation();
     aiAnimation* dest = *_dest = new aiAnimation();
 
 
     // get a flat copy
     // get a flat copy
-    ::memcpy(dest,src,sizeof(aiAnimation));
+    *dest = *src;
 
 
     // and reallocate all arrays
     // and reallocate all arrays
     CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
     CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
@@ -1208,7 +1207,7 @@ void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) {
     aiNodeAnim* dest = *_dest = new aiNodeAnim();
     aiNodeAnim* dest = *_dest = new aiNodeAnim();
 
 
     // get a flat copy
     // get a flat copy
-    ::memcpy(dest,src,sizeof(aiNodeAnim));
+    *dest = *src;
 
 
     // and reallocate all arrays
     // and reallocate all arrays
     GetArrayCopy( dest->mPositionKeys, dest->mNumPositionKeys );
     GetArrayCopy( dest->mPositionKeys, dest->mNumPositionKeys );
@@ -1224,7 +1223,7 @@ void SceneCombiner::Copy(aiMeshMorphAnim** _dest, const aiMeshMorphAnim* src) {
     aiMeshMorphAnim* dest = *_dest = new aiMeshMorphAnim();
     aiMeshMorphAnim* dest = *_dest = new aiMeshMorphAnim();
 
 
     // get a flat copy
     // get a flat copy
-    ::memcpy(dest,src,sizeof(aiMeshMorphAnim));
+    *dest = *src;
 
 
     // and reallocate all arrays
     // and reallocate all arrays
     GetArrayCopy( dest->mKeys, dest->mNumKeys );
     GetArrayCopy( dest->mKeys, dest->mNumKeys );
@@ -1245,7 +1244,7 @@ void SceneCombiner::Copy( aiCamera** _dest,const  aiCamera* src) {
     aiCamera* dest = *_dest = new aiCamera();
     aiCamera* dest = *_dest = new aiCamera();
 
 
     // get a flat copy, that's already OK
     // get a flat copy, that's already OK
-    ::memcpy(dest,src,sizeof(aiCamera));
+    *dest = *src;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -1257,7 +1256,7 @@ void SceneCombiner::Copy(aiLight** _dest, const aiLight* src) {
     aiLight* dest = *_dest = new aiLight();
     aiLight* dest = *_dest = new aiLight();
 
 
     // get a flat copy, that's already OK
     // get a flat copy, that's already OK
-    ::memcpy(dest,src,sizeof(aiLight));
+    *dest = *src;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -1269,7 +1268,7 @@ void SceneCombiner::Copy(aiBone** _dest, const aiBone* src) {
     aiBone* dest = *_dest = new aiBone();
     aiBone* dest = *_dest = new aiBone();
 
 
     // get a flat copy
     // get a flat copy
-    ::memcpy(dest,src,sizeof(aiBone));
+    *dest = *src;
 
 
     // and reallocate all arrays
     // and reallocate all arrays
     GetArrayCopy( dest->mWeights, dest->mNumWeights );
     GetArrayCopy( dest->mWeights, dest->mNumWeights );
@@ -1283,7 +1282,7 @@ void SceneCombiner::Copy     (aiNode** _dest, const aiNode* src)
     aiNode* dest = *_dest = new aiNode();
     aiNode* dest = *_dest = new aiNode();
 
 
     // get a flat copy
     // get a flat copy
-    ::memcpy(dest,src,sizeof(aiNode));
+    *dest = *src;
 
 
     if (src->mMetaData) {
     if (src->mMetaData) {
         Copy(&dest->mMetaData, src->mMetaData);
         Copy(&dest->mMetaData, src->mMetaData);

+ 117 - 134
code/Common/SpatialSort.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,
@@ -50,71 +48,60 @@ using namespace Assimp;
 
 
 // CHAR_BIT seems to be defined under MVSC, but not under GCC. Pray that the correct value is 8.
 // CHAR_BIT seems to be defined under MVSC, but not under GCC. Pray that the correct value is 8.
 #ifndef CHAR_BIT
 #ifndef CHAR_BIT
-#   define CHAR_BIT 8
+#define CHAR_BIT 8
 #endif
 #endif
 
 
-#ifdef _WIN32
-#    pragma warning(disable : 4127)  
-#endif // _WIN32
+const aiVector3D PlaneInit(0.8523f, 0.34321f, 0.5736f);
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructs a spatially sorted representation from the given position array.
 // Constructs a spatially sorted representation from the given position array.
-SpatialSort::SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
-    unsigned int pElementOffset)
-
-    // define the reference plane. We choose some arbitrary vector away from all basic axises
-    // in the hope that no model spreads all its vertices along this plane.
-    : mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
-{
+// define the reference plane. We choose some arbitrary vector away from all basic axises
+// in the hope that no model spreads all its vertices along this plane.
+SpatialSort::SpatialSort(const aiVector3D *pPositions, unsigned int pNumPositions, unsigned int pElementOffset) :
+        mPlaneNormal(PlaneInit) {
     mPlaneNormal.Normalize();
     mPlaneNormal.Normalize();
-    Fill(pPositions,pNumPositions,pElementOffset);
+    Fill(pPositions, pNumPositions, pElementOffset);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-SpatialSort :: SpatialSort()
-: mPlaneNormal(0.8523f, 0.34321f, 0.5736f)
-{
+SpatialSort::SpatialSort() :
+        mPlaneNormal(PlaneInit) {
     mPlaneNormal.Normalize();
     mPlaneNormal.Normalize();
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor
 // Destructor
-SpatialSort::~SpatialSort()
-{
-    // nothing to do here, everything destructs automatically
+SpatialSort::~SpatialSort() {
+    // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void SpatialSort::Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
-    unsigned int pElementOffset,
-    bool pFinalize /*= true */)
-{
+void SpatialSort::Fill(const aiVector3D *pPositions, unsigned int pNumPositions,
+        unsigned int pElementOffset,
+        bool pFinalize /*= true */) {
     mPositions.clear();
     mPositions.clear();
-    Append(pPositions,pNumPositions,pElementOffset,pFinalize);
+    Append(pPositions, pNumPositions, pElementOffset, pFinalize);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void SpatialSort :: Finalize()
-{
-    std::sort( mPositions.begin(), mPositions.end());
+void SpatialSort::Finalize() {
+    std::sort(mPositions.begin(), mPositions.end());
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositions,
-    unsigned int pElementOffset,
-    bool pFinalize /*= true */)
-{
+void SpatialSort::Append(const aiVector3D *pPositions, unsigned int pNumPositions,
+        unsigned int pElementOffset,
+        bool pFinalize /*= true */) {
     // store references to all given positions along with their distance to the reference plane
     // store references to all given positions along with their distance to the reference plane
     const size_t initial = mPositions.size();
     const size_t initial = mPositions.size();
-    mPositions.reserve(initial + (pFinalize?pNumPositions:pNumPositions*2));
-    for( unsigned int a = 0; a < pNumPositions; a++)
-    {
-        const char* tempPointer = reinterpret_cast<const char*> (pPositions);
-        const aiVector3D* vec   = reinterpret_cast<const aiVector3D*> (tempPointer + a * pElementOffset);
+    mPositions.reserve(initial + (pFinalize ? pNumPositions : pNumPositions * 2));
+    for (unsigned int a = 0; a < pNumPositions; a++) {
+        const char *tempPointer = reinterpret_cast<const char *>(pPositions);
+        const aiVector3D *vec = reinterpret_cast<const aiVector3D *>(tempPointer + a * pElementOffset);
 
 
         // store position by index and distance
         // store position by index and distance
         ai_real distance = *vec * mPlaneNormal;
         ai_real distance = *vec * mPlaneNormal;
-        mPositions.push_back( Entry( static_cast<unsigned int>(a+initial), *vec, distance));
+        mPositions.push_back(Entry(static_cast<unsigned int>(a + initial), *vec, distance));
     }
     }
 
 
     if (pFinalize) {
     if (pFinalize) {
@@ -125,9 +112,8 @@ void SpatialSort::Append( const aiVector3D* pPositions, unsigned int pNumPositio
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns an iterator for all positions close to the given position.
 // Returns an iterator for all positions close to the given position.
-void SpatialSort::FindPositions( const aiVector3D& pPosition,
-    ai_real pRadius, std::vector<unsigned int>& poResults) const
-{
+void SpatialSort::FindPositions(const aiVector3D &pPosition,
+        ai_real pRadius, std::vector<unsigned int> &poResults) const {
     const ai_real dist = pPosition * mPlaneNormal;
     const ai_real dist = pPosition * mPlaneNormal;
     const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
     const ai_real minDist = dist - pRadius, maxDist = dist + pRadius;
 
 
@@ -135,19 +121,18 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
     poResults.clear();
     poResults.clear();
 
 
     // quick check for positions outside the range
     // quick check for positions outside the range
-    if( mPositions.size() == 0)
+    if (mPositions.size() == 0)
         return;
         return;
-    if( maxDist < mPositions.front().mDistance)
+    if (maxDist < mPositions.front().mDistance)
         return;
         return;
-    if( minDist > mPositions.back().mDistance)
+    if (minDist > mPositions.back().mDistance)
         return;
         return;
 
 
     // do a binary search for the minimal distance to start the iteration there
     // do a binary search for the minimal distance to start the iteration there
     unsigned int index = (unsigned int)mPositions.size() / 2;
     unsigned int index = (unsigned int)mPositions.size() / 2;
     unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
     unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
-    while( binaryStepSize > 1)
-    {
-        if( mPositions[index].mDistance < minDist)
+    while (binaryStepSize > 1) {
+        if (mPositions[index].mDistance < minDist)
             index += binaryStepSize;
             index += binaryStepSize;
         else
         else
             index -= binaryStepSize;
             index -= binaryStepSize;
@@ -157,21 +142,20 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
 
 
     // depending on the direction of the last step we need to single step a bit back or forth
     // depending on the direction of the last step we need to single step a bit back or forth
     // to find the actual beginning element of the range
     // to find the actual beginning element of the range
-    while( index > 0 && mPositions[index].mDistance > minDist)
+    while (index > 0 && mPositions[index].mDistance > minDist)
         index--;
         index--;
-    while( index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
+    while (index < (mPositions.size() - 1) && mPositions[index].mDistance < minDist)
         index++;
         index++;
 
 
     // Mow start iterating from there until the first position lays outside of the distance range.
     // Mow start iterating from there until the first position lays outside of the distance range.
     // Add all positions inside the distance range within the given radius to the result aray
     // Add all positions inside the distance range within the given radius to the result aray
     std::vector<Entry>::const_iterator it = mPositions.begin() + index;
     std::vector<Entry>::const_iterator it = mPositions.begin() + index;
-    const ai_real pSquared = pRadius*pRadius;
-    while( it->mDistance < maxDist)
-    {
-        if( (it->mPosition - pPosition).SquareLength() < pSquared)
-            poResults.push_back( it->mIndex);
+    const ai_real pSquared = pRadius * pRadius;
+    while (it->mDistance < maxDist) {
+        if ((it->mPosition - pPosition).SquareLength() < pSquared)
+            poResults.push_back(it->mIndex);
         ++it;
         ++it;
-        if( it == mPositions.end())
+        if (it == mPositions.end())
             break;
             break;
     }
     }
 
 
@@ -180,70 +164,74 @@ void SpatialSort::FindPositions( const aiVector3D& pPosition,
 
 
 namespace {
 namespace {
 
 
-    // Binary, signed-integer representation of a single-precision floating-point value.
-    // IEEE 754 says: "If two floating-point numbers in the same format are ordered then they are
-    //  ordered the same way when their bits are reinterpreted as sign-magnitude integers."
-    // This allows us to convert all floating-point numbers to signed integers of arbitrary size
-    //  and then use them to work with ULPs (Units in the Last Place, for high-precision
-    //  computations) or to compare them (integer comparisons are faster than floating-point
-    //  comparisons on many platforms).
-    typedef ai_int BinFloat;
-
-    // --------------------------------------------------------------------------------------------
-    // Converts the bit pattern of a floating-point number to its signed integer representation.
-    BinFloat ToBinary( const ai_real & pValue) {
-
-        // If this assertion fails, signed int is not big enough to store a float on your platform.
-        //  Please correct the declaration of BinFloat a few lines above - but do it in a portable,
-        //  #ifdef'd manner!
-        static_assert( sizeof(BinFloat) >= sizeof(ai_real), "sizeof(BinFloat) >= sizeof(ai_real)");
-
-        #if defined( _MSC_VER)
-            // If this assertion fails, Visual C++ has finally moved to ILP64. This means that this
-            //  code has just become legacy code! Find out the current value of _MSC_VER and modify
-            //  the #if above so it evaluates false on the current and all upcoming VC versions (or
-            //  on the current platform, if LP64 or LLP64 are still used on other platforms).
-            static_assert( sizeof(BinFloat) == sizeof(ai_real), "sizeof(BinFloat) == sizeof(ai_real)");
-
-            // This works best on Visual C++, but other compilers have their problems with it.
-            const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
-        #else
-            // On many compilers, reinterpreting a float address as an integer causes aliasing
-            // problems. This is an ugly but more or less safe way of doing it.
-            union {
-                ai_real     asFloat;
-                BinFloat    asBin;
-            } conversion;
-            conversion.asBin    = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float)
-            conversion.asFloat  = pValue;
-            const BinFloat binValue = conversion.asBin;
-        #endif
-
-        // floating-point numbers are of sign-magnitude format, so find out what signed number
-        //  representation we must convert negative values to.
-        // See http://en.wikipedia.org/wiki/Signed_number_representations.
-
-        // Two's complement?
-        if( (-42 == (~42 + 1)) && (binValue & 0x80000000))
-            return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
-        // One's complement?
-        else if ( (-42 == ~42) && (binValue & 0x80000000))
-            return BinFloat(-0) - binValue;
-        // Sign-magnitude?
-        else if( (-42 == (42 | (-0))) && (binValue & 0x80000000)) // -0 = 1000... binary
-            return binValue;
-        else
-            return binValue;
-    }
+// Binary, signed-integer representation of a single-precision floating-point value.
+// IEEE 754 says: "If two floating-point numbers in the same format are ordered then they are
+//  ordered the same way when their bits are reinterpreted as sign-magnitude integers."
+// This allows us to convert all floating-point numbers to signed integers of arbitrary size
+//  and then use them to work with ULPs (Units in the Last Place, for high-precision
+//  computations) or to compare them (integer comparisons are faster than floating-point
+//  comparisons on many platforms).
+typedef ai_int BinFloat;
+
+// --------------------------------------------------------------------------------------------
+// Converts the bit pattern of a floating-point number to its signed integer representation.
+BinFloat ToBinary(const ai_real &pValue) {
+
+    // If this assertion fails, signed int is not big enough to store a float on your platform.
+    //  Please correct the declaration of BinFloat a few lines above - but do it in a portable,
+    //  #ifdef'd manner!
+    static_assert(sizeof(BinFloat) >= sizeof(ai_real), "sizeof(BinFloat) >= sizeof(ai_real)");
+
+#if defined(_MSC_VER)
+    // If this assertion fails, Visual C++ has finally moved to ILP64. This means that this
+    //  code has just become legacy code! Find out the current value of _MSC_VER and modify
+    //  the #if above so it evaluates false on the current and all upcoming VC versions (or
+    //  on the current platform, if LP64 or LLP64 are still used on other platforms).
+    static_assert(sizeof(BinFloat) == sizeof(ai_real), "sizeof(BinFloat) == sizeof(ai_real)");
+
+    // This works best on Visual C++, but other compilers have their problems with it.
+    const BinFloat binValue = reinterpret_cast<BinFloat const &>(pValue);
+    //::memcpy(&binValue, &pValue, sizeof(pValue));
+    //return binValue;
+#else
+    // On many compilers, reinterpreting a float address as an integer causes aliasing
+    // problems. This is an ugly but more or less safe way of doing it.
+    union {
+        ai_real asFloat;
+        BinFloat asBin;
+    } conversion;
+    conversion.asBin = 0; // zero empty space in case sizeof(BinFloat) > sizeof(float)
+    conversion.asFloat = pValue;
+    const BinFloat binValue = conversion.asBin;
+#endif
+
+    // floating-point numbers are of sign-magnitude format, so find out what signed number
+    //  representation we must convert negative values to.
+    // See http://en.wikipedia.org/wiki/Signed_number_representations.
+
+    // Two's complement?
+    bool DefaultValue = ((-42 == (~42 + 1)) && (binValue & 0x80000000));
+    bool OneComplement = ((-42 == ~42) && (binValue & 0x80000000));
+    bool SignedMagnitude = ((-42 == (42 | (-0))) && (binValue & 0x80000000));
+
+    if (DefaultValue)
+        return BinFloat(1 << (CHAR_BIT * sizeof(BinFloat) - 1)) - binValue;
+    // One's complement?
+    else if (OneComplement)
+        return BinFloat(-0) - binValue;
+    // Sign-magnitude?
+    else if (SignedMagnitude) // -0 = 1000... binary
+        return binValue;
+    else
+        return binValue;
+}
 
 
 } // namespace
 } // namespace
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Fills an array with indices of all positions identical to the given position. In opposite to
 // Fills an array with indices of all positions identical to the given position. In opposite to
 // FindPositions(), not an epsilon is used but a (very low) tolerance of four floating-point units.
 // FindPositions(), not an epsilon is used but a (very low) tolerance of four floating-point units.
-void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
-    std::vector<unsigned int>& poResults) const
-{
+void SpatialSort::FindIdenticalPositions(const aiVector3D &pPosition, std::vector<unsigned int> &poResults) const {
     // Epsilons have a huge disadvantage: they are of constant precision, while floating-point
     // Epsilons have a huge disadvantage: they are of constant precision, while floating-point
     //  values are of log2 precision. If you apply e=0.01 to 100, the epsilon is rather small, but
     //  values are of log2 precision. If you apply e=0.01 to 100, the epsilon is rather small, but
     //  if you apply it to 0.001, it is enormous.
     //  if you apply it to 0.001, it is enormous.
@@ -269,20 +257,19 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
 
 
     // Convert the plane distance to its signed integer representation so the ULPs tolerance can be
     // Convert the plane distance to its signed integer representation so the ULPs tolerance can be
     //  applied. For some reason, VC won't optimize two calls of the bit pattern conversion.
     //  applied. For some reason, VC won't optimize two calls of the bit pattern conversion.
-    const BinFloat minDistBinary = ToBinary( pPosition * mPlaneNormal) - distanceToleranceInULPs;
+    const BinFloat minDistBinary = ToBinary(pPosition * mPlaneNormal) - distanceToleranceInULPs;
     const BinFloat maxDistBinary = minDistBinary + 2 * distanceToleranceInULPs;
     const BinFloat maxDistBinary = minDistBinary + 2 * distanceToleranceInULPs;
 
 
     // clear the array in this strange fashion because a simple clear() would also deallocate
     // clear the array in this strange fashion because a simple clear() would also deallocate
     // the array which we want to avoid
     // the array which we want to avoid
-    poResults.resize( 0 );
+    poResults.resize(0);
 
 
     // do a binary search for the minimal distance to start the iteration there
     // do a binary search for the minimal distance to start the iteration there
     unsigned int index = (unsigned int)mPositions.size() / 2;
     unsigned int index = (unsigned int)mPositions.size() / 2;
     unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
     unsigned int binaryStepSize = (unsigned int)mPositions.size() / 4;
-    while( binaryStepSize > 1)
-    {
+    while (binaryStepSize > 1) {
         // Ugly, but conditional jumps are faster with integers than with floats
         // Ugly, but conditional jumps are faster with integers than with floats
-        if( minDistBinary > ToBinary(mPositions[index].mDistance))
+        if (minDistBinary > ToBinary(mPositions[index].mDistance))
             index += binaryStepSize;
             index += binaryStepSize;
         else
         else
             index -= binaryStepSize;
             index -= binaryStepSize;
@@ -292,20 +279,19 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
 
 
     // depending on the direction of the last step we need to single step a bit back or forth
     // depending on the direction of the last step we need to single step a bit back or forth
     // to find the actual beginning element of the range
     // to find the actual beginning element of the range
-    while( index > 0 && minDistBinary < ToBinary(mPositions[index].mDistance) )
+    while (index > 0 && minDistBinary < ToBinary(mPositions[index].mDistance))
         index--;
         index--;
-    while( index < (mPositions.size() - 1) && minDistBinary > ToBinary(mPositions[index].mDistance))
+    while (index < (mPositions.size() - 1) && minDistBinary > ToBinary(mPositions[index].mDistance))
         index++;
         index++;
 
 
     // Now start iterating from there until the first position lays outside of the distance range.
     // Now start iterating from there until the first position lays outside of the distance range.
     // Add all positions inside the distance range within the tolerance to the result array
     // Add all positions inside the distance range within the tolerance to the result array
     std::vector<Entry>::const_iterator it = mPositions.begin() + index;
     std::vector<Entry>::const_iterator it = mPositions.begin() + index;
-    while( ToBinary(it->mDistance) < maxDistBinary)
-    {
-        if( distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength()))
+    while (ToBinary(it->mDistance) < maxDistBinary) {
+        if (distance3DToleranceInULPs >= ToBinary((it->mPosition - pPosition).SquareLength()))
             poResults.push_back(it->mIndex);
             poResults.push_back(it->mIndex);
         ++it;
         ++it;
-        if( it == mPositions.end())
+        if (it == mPositions.end())
             break;
             break;
     }
     }
 
 
@@ -313,22 +299,19 @@ void SpatialSort::FindIdenticalPositions( const aiVector3D& pPosition,
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill, ai_real pRadius) const
-{
-    fill.resize(mPositions.size(),UINT_MAX);
+unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int> &fill, ai_real pRadius) const {
+    fill.resize(mPositions.size(), UINT_MAX);
     ai_real dist, maxDist;
     ai_real dist, maxDist;
 
 
-    unsigned int t=0;
-    const ai_real pSquared = pRadius*pRadius;
+    unsigned int t = 0;
+    const ai_real pSquared = pRadius * pRadius;
     for (size_t i = 0; i < mPositions.size();) {
     for (size_t i = 0; i < mPositions.size();) {
         dist = mPositions[i].mPosition * mPlaneNormal;
         dist = mPositions[i].mPosition * mPlaneNormal;
         maxDist = dist + pRadius;
         maxDist = dist + pRadius;
 
 
         fill[mPositions[i].mIndex] = t;
         fill[mPositions[i].mIndex] = t;
-        const aiVector3D& oldpos = mPositions[i].mPosition;
-        for (++i; i < fill.size() && mPositions[i].mDistance < maxDist
-            && (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i)
-        {
+        const aiVector3D &oldpos = mPositions[i].mPosition;
+        for (++i; i < fill.size() && mPositions[i].mDistance < maxDist && (mPositions[i].mPosition - oldpos).SquareLength() < pSquared; ++i) {
             fill[mPositions[i].mIndex] = t;
             fill[mPositions[i].mIndex] = t;
         }
         }
         ++t;
         ++t;
@@ -338,7 +321,7 @@ unsigned int SpatialSort::GenerateMappingTable(std::vector<unsigned int>& fill,
 
 
     // debug invariant: mPositions[i].mIndex values must range from 0 to mPositions.size()-1
     // debug invariant: mPositions[i].mIndex values must range from 0 to mPositions.size()-1
     for (size_t i = 0; i < fill.size(); ++i) {
     for (size_t i = 0; i < fill.size(); ++i) {
-        ai_assert(fill[i]<mPositions.size());
+        ai_assert(fill[i] < mPositions.size());
     }
     }
 
 
 #endif
 #endif

+ 18 - 24
code/FBX/FBXImportSettings.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,
@@ -50,27 +49,25 @@ namespace Assimp {
 namespace FBX {
 namespace FBX {
 
 
 /** FBX import settings, parts of which are publicly accessible via their corresponding AI_CONFIG constants */
 /** FBX import settings, parts of which are publicly accessible via their corresponding AI_CONFIG constants */
-struct ImportSettings
-{
-    ImportSettings()
-    : strictMode(true)
-    , readAllLayers(true)
-    , readAllMaterials(false)
-    , readMaterials(true)
-    , readTextures(true)
-    , readCameras(true)
-    , readLights(true)
-    , readAnimations(true)
-    , readWeights(true)
-    , preservePivots(true)
-    , optimizeEmptyAnimationCurves(true)
-    , useLegacyEmbeddedTextureNaming(false)
-    , removeEmptyBones( true )
-    , convertToMeters( false ) {
+struct ImportSettings {
+    ImportSettings() :
+            strictMode(true),
+            readAllLayers(true),
+            readAllMaterials(false),
+            readMaterials(true),
+            readTextures(true),
+            readCameras(true),
+            readLights(true),
+            readAnimations(true),
+            readWeights(true),
+            preservePivots(true),
+            optimizeEmptyAnimationCurves(true),
+            useLegacyEmbeddedTextureNaming(false),
+            removeEmptyBones(true),
+            convertToMeters(false) {
         // empty
         // empty
     }
     }
 
 
-
     /** enable strict mode:
     /** enable strict mode:
      *   - only accept fbx 2012, 2013 files
      *   - only accept fbx 2012, 2013 files
      *   - on the slightest error, give up.
      *   - on the slightest error, give up.
@@ -94,7 +91,6 @@ struct ImportSettings
      *  This bit is ignored unless readMaterials=true*/
      *  This bit is ignored unless readMaterials=true*/
     bool readAllMaterials;
     bool readAllMaterials;
 
 
-
     /** import materials (true) or skip them and assign a default
     /** import materials (true) or skip them and assign a default
      *  material. The default value is true.*/
      *  material. The default value is true.*/
     bool readMaterials;
     bool readMaterials;
@@ -156,9 +152,7 @@ struct ImportSettings
     bool convertToMeters;
     bool convertToMeters;
 };
 };
 
 
-
-} // !FBX
-} // !Assimp
+} // namespace FBX
+} // namespace Assimp
 
 
 #endif
 #endif
-

+ 0 - 1
code/FBX/FBXImporter.cpp

@@ -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,

+ 20 - 23
code/FBX/FBXImporter.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,
@@ -51,45 +50,44 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "FBXImportSettings.h"
 #include "FBXImportSettings.h"
 
 
-namespace Assimp    {
+namespace Assimp {
 
 
 // TinyFormatter.h
 // TinyFormatter.h
 namespace Formatter {
 namespace Formatter {
-    template <typename T,typename TR, typename A> class basic_formatter;
-    typedef class basic_formatter< char, std::char_traits<char>, std::allocator<char> > format;
-}
 
 
-// -------------------------------------------------------------------------------------------
-/** Load the Autodesk FBX file format.
+template <typename T, typename TR, typename A>
+class basic_formatter;
 
 
- See http://en.wikipedia.org/wiki/FBX
-*/
+typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format;
+
+} // namespace Formatter
+
+// -------------------------------------------------------------------------------------------
+/// Loads the Autodesk FBX file format.
+///
+/// See http://en.wikipedia.org/wiki/FBX
 // -------------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------------
-class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter>
-{
+class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
 public:
 public:
     FBXImporter();
     FBXImporter();
     virtual ~FBXImporter();
     virtual ~FBXImporter();
 
 
     // --------------------
     // --------------------
-    bool CanRead( const std::string& pFile,
-        IOSystem* pIOHandler,
-        bool checkSig
-    ) const;
+    bool CanRead(const std::string &pFile,
+            IOSystem *pIOHandler,
+            bool checkSig) const;
 
 
 protected:
 protected:
-
     // --------------------
     // --------------------
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc *GetInfo() const;
 
 
     // --------------------
     // --------------------
-    void SetupProperties(const Importer* pImp);
+    void SetupProperties(const Importer *pImp);
 
 
     // --------------------
     // --------------------
-    void InternReadFile( const std::string& pFile,
-        aiScene* pScene,
-        IOSystem* pIOHandler
-    );
+    void InternReadFile(const std::string &pFile,
+            aiScene *pScene,
+            IOSystem *pIOHandler);
 
 
 private:
 private:
     FBX::ImportSettings settings;
     FBX::ImportSettings settings;
@@ -97,4 +95,3 @@ private:
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp
 #endif // !INCLUDED_AI_FBX_IMPORTER_H
 #endif // !INCLUDED_AI_FBX_IMPORTER_H
-

+ 1 - 0
code/Irr/IRRLoader.cpp

@@ -1483,6 +1483,7 @@ void IRRImporter::InternReadFile( const std::string& pFile,
      */
      */
 
 
     delete root;
     delete root;
+	delete reader;
 }
 }
 
 
 #endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER
 #endif // !! ASSIMP_BUILD_NO_IRR_IMPORTER

+ 41 - 36
code/M3D/M3DExporter.cpp

@@ -189,42 +189,42 @@ M3D_INDEX addMaterial(const Assimp::M3DWrapper &m3d, const aiMaterial *mat) {
                     continue;
                     continue;
                 if (aiProps[k].pKey) {
                 if (aiProps[k].pKey) {
                     switch (m3d_propertytypes[k].format) {
                     switch (m3d_propertytypes[k].format) {
-                        case m3dpf_color:
-                            if (mat->Get(aiProps[k].pKey, aiProps[k].type,
-                                        aiProps[k].index, c) == AI_SUCCESS)
-                                addProp(&m3d->material[mi],
-                                        m3d_propertytypes[k].id, mkColor(&c));
-                            break;
-                        case m3dpf_float:
-                            if (mat->Get(aiProps[k].pKey, aiProps[k].type,
-                                        aiProps[k].index, f) == AI_SUCCESS)
-                                addProp(&m3d->material[mi],
-                                        m3d_propertytypes[k].id,
-                                        /* not (uint32_t)f, because we don't want to convert
+                    case m3dpf_color:
+                        if (mat->Get(aiProps[k].pKey, aiProps[k].type,
+                                    aiProps[k].index, c) == AI_SUCCESS)
+                            addProp(&m3d->material[mi],
+                                    m3d_propertytypes[k].id, mkColor(&c));
+                        break;
+                    case m3dpf_float:
+                        if (mat->Get(aiProps[k].pKey, aiProps[k].type,
+                                    aiProps[k].index, f) == AI_SUCCESS)
+                            addProp(&m3d->material[mi],
+                                    m3d_propertytypes[k].id,
+                                    /* not (uint32_t)f, because we don't want to convert
                                          * it, we want to see it as 32 bits of memory */
                                          * it, we want to see it as 32 bits of memory */
-                                        *((uint32_t *)&f));
-                            break;
-                        case m3dpf_uint8:
-                            if (mat->Get(aiProps[k].pKey, aiProps[k].type,
-                                        aiProps[k].index, j) == AI_SUCCESS) {
-                                // special conversion for illumination model property
-                                if (m3d_propertytypes[k].id == m3dp_il) {
-                                    switch (j) {
-                                        case aiShadingMode_NoShading: j = 0; break;
-                                        case aiShadingMode_Phong: j = 2; break;
-                                        default: j = 1; break;
-                                    }
+                                    *((uint32_t *)&f));
+                        break;
+                    case m3dpf_uint8:
+                        if (mat->Get(aiProps[k].pKey, aiProps[k].type,
+                                    aiProps[k].index, j) == AI_SUCCESS) {
+                            // special conversion for illumination model property
+                            if (m3d_propertytypes[k].id == m3dp_il) {
+                                switch (j) {
+                                case aiShadingMode_NoShading: j = 0; break;
+                                case aiShadingMode_Phong: j = 2; break;
+                                default: j = 1; break;
                                 }
                                 }
-                                addProp(&m3d->material[mi],
-                                        m3d_propertytypes[k].id, j);
                             }
                             }
-                            break;
-                        default:
-                            if (mat->Get(aiProps[k].pKey, aiProps[k].type,
-                                        aiProps[k].index, j) == AI_SUCCESS)
-                                addProp(&m3d->material[mi],
-                                        m3d_propertytypes[k].id, j);
-                            break;
+                            addProp(&m3d->material[mi],
+                                    m3d_propertytypes[k].id, j);
+                        }
+                        break;
+                    default:
+                        if (mat->Get(aiProps[k].pKey, aiProps[k].type,
+                                    aiProps[k].index, j) == AI_SUCCESS)
+                            addProp(&m3d->material[mi],
+                                    m3d_propertytypes[k].id, j);
+                        break;
                     }
                     }
                 }
                 }
                 if (aiTxProps[k].pKey &&
                 if (aiTxProps[k].pKey &&
@@ -292,8 +292,8 @@ void ExportSceneM3D(
 // Prototyped and registered in Exporter.cpp
 // Prototyped and registered in Exporter.cpp
 void ExportSceneM3DA(
 void ExportSceneM3DA(
         const char *,
         const char *,
-        IOSystem*,
-        const aiScene*,
+        IOSystem *,
+        const aiScene *,
         const ExportProperties *
         const ExportProperties *
 
 
 ) {
 ) {
@@ -312,7 +312,9 @@ void ExportSceneM3DA(
 M3DExporter::M3DExporter(const aiScene *pScene, const ExportProperties *pProperties) :
 M3DExporter::M3DExporter(const aiScene *pScene, const ExportProperties *pProperties) :
         mScene(pScene),
         mScene(pScene),
         mProperties(pProperties),
         mProperties(pProperties),
-        outfile() {}
+        outfile() {
+    // empty
+}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void M3DExporter::doExport(
 void M3DExporter::doExport(
@@ -352,6 +354,9 @@ void M3DExporter::doExport(
     // explicitly release file pointer,
     // explicitly release file pointer,
     // so we don't have to rely on class destruction.
     // so we don't have to rely on class destruction.
     outfile.reset();
     outfile.reset();
+
+    M3D_FREE(m3d->name);
+    m3d->name = nullptr;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 53 - 52
code/M3D/M3DWrapper.cpp

@@ -50,15 +50,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #ifdef ASSIMP_USE_M3D_READFILECB
 #ifdef ASSIMP_USE_M3D_READFILECB
 
 
-# if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
-#  define threadlocal thread_local
-# else
-#  if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
-#   define threadlocal __declspec(thread)
-#  else
-#   define threadlocal
-#  endif
-# endif
+#if (__cplusplus >= 201103L) || !defined(_MSC_VER) || (_MSC_VER >= 1900) // C++11 and MSVC 2015 onwards
+#define threadlocal thread_local
+#else
+#if defined(_MSC_VER) && (_MSC_VER >= 1800) // there's an alternative for MSVC 2013
+#define threadlocal __declspec(thread)
+#else
+#define threadlocal
+#endif
+#endif
 
 
 extern "C" {
 extern "C" {
 
 
@@ -66,37 +66,37 @@ extern "C" {
 threadlocal void *m3dimporter_pIOHandler;
 threadlocal void *m3dimporter_pIOHandler;
 
 
 unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) {
 unsigned char *m3dimporter_readfile(char *fn, unsigned int *size) {
-	ai_assert(nullptr != fn);
-	ai_assert(nullptr != size);
-	std::string file(fn);
-	std::unique_ptr<Assimp::IOStream> pStream(
-			(reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
-	size_t fileSize = 0;
-	unsigned char *data = NULL;
-	// sometimes pStream is nullptr in a single-threaded scenario too for some reason
-	// (should be an empty object returning nothing I guess)
-	if (pStream) {
-		fileSize = pStream->FileSize();
-		// should be allocated with malloc(), because the library will call free() to deallocate
-		data = (unsigned char *)malloc(fileSize);
-		if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) {
-			pStream.reset();
-			*size = 0;
-			// don't throw a deadly exception, it's not fatal if we can't read an external asset
-			return nullptr;
-		}
-		pStream.reset();
-	}
-	*size = (int)fileSize;
-	return data;
+    ai_assert(nullptr != fn);
+    ai_assert(nullptr != size);
+    std::string file(fn);
+    std::unique_ptr<Assimp::IOStream> pStream(
+            (reinterpret_cast<Assimp::IOSystem *>(m3dimporter_pIOHandler))->Open(file, "rb"));
+    size_t fileSize = 0;
+    unsigned char *data = NULL;
+    // sometimes pStream is nullptr in a single-threaded scenario too for some reason
+    // (should be an empty object returning nothing I guess)
+    if (pStream) {
+        fileSize = pStream->FileSize();
+        // should be allocated with malloc(), because the library will call free() to deallocate
+        data = (unsigned char *)malloc(fileSize);
+        if (!data || !pStream.get() || !fileSize || fileSize != pStream->Read(data, 1, fileSize)) {
+            pStream.reset();
+            *size = 0;
+            // don't throw a deadly exception, it's not fatal if we can't read an external asset
+            return nullptr;
+        }
+        pStream.reset();
+    }
+    *size = (int)fileSize;
+    return data;
 }
 }
 }
 }
 #endif
 #endif
 
 
 namespace Assimp {
 namespace Assimp {
 M3DWrapper::M3DWrapper() {
 M3DWrapper::M3DWrapper() {
-	// use malloc() here because m3d_free() will call free()
-	m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t));
+    // use malloc() here because m3d_free() will call free()
+    m3d_ = (m3d_t *)calloc(1, sizeof(m3d_t));
 }
 }
 
 
 M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer) {
 M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &buffer) {
@@ -105,41 +105,42 @@ M3DWrapper::M3DWrapper(IOSystem *pIOHandler, const std::vector<unsigned char> &b
     }
     }
 
 
 #ifdef ASSIMP_USE_M3D_READFILECB
 #ifdef ASSIMP_USE_M3D_READFILECB
-	// pass this IOHandler to the C callback in a thread-local pointer
-	m3dimporter_pIOHandler = pIOHandler;
-	m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
-	// Clear the C callback
-	m3dimporter_pIOHandler = nullptr;
+    // pass this IOHandler to the C callback in a thread-local pointer
+    m3dimporter_pIOHandler = pIOHandler;
+    m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), m3dimporter_readfile, free, nullptr);
+    // Clear the C callback
+    m3dimporter_pIOHandler = nullptr;
 #else
 #else
-	m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
+    m3d_ = m3d_load(const_cast<unsigned char *>(buffer.data()), nullptr, nullptr, nullptr);
 #endif
 #endif
 }
 }
 
 
 M3DWrapper::~M3DWrapper() {
 M3DWrapper::~M3DWrapper() {
-	reset();
+    reset();
 }
 }
 
 
 void M3DWrapper::reset() {
 void M3DWrapper::reset() {
-	ClearSave();
-	if (m3d_)
-		m3d_free(m3d_);
-	m3d_ = nullptr;
+    ClearSave();
+    if (m3d_) {
+        m3d_free(m3d_);
+    }
+    m3d_ = nullptr;
 }
 }
 
 
 unsigned char *M3DWrapper::Save(int quality, int flags, unsigned int &size) {
 unsigned char *M3DWrapper::Save(int quality, int flags, unsigned int &size) {
 #if (!(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER))
 #if (!(ASSIMP_BUILD_NO_EXPORT || ASSIMP_BUILD_NO_M3D_EXPORTER))
-	ClearSave();
-	saved_output_ = m3d_save(m3d_, quality, flags, &size);
-	return saved_output_;
+    ClearSave();
+    saved_output_ = m3d_save(m3d_, quality, flags, &size);
+    return saved_output_;
 #else
 #else
-	return nullptr;
+    return nullptr;
 #endif
 #endif
 }
 }
 
 
 void M3DWrapper::ClearSave() {
 void M3DWrapper::ClearSave() {
-	if (saved_output_)
-		M3D_FREE(saved_output_);
-	saved_output_ = nullptr;
+    if (saved_output_)
+        M3D_FREE(saved_output_);
+    saved_output_ = nullptr;
 }
 }
 } // namespace Assimp
 } // namespace Assimp
 
 

+ 23 - 17
code/M3D/m3d.h

@@ -1556,7 +1556,7 @@ static int _m3dstbi__create_png_image(_m3dstbi__png *a, unsigned char *image_dat
     return 1;
     return 1;
 }
 }
 
 
-static int _m3dstbi__compute_transparency(_m3dstbi__png *z, unsigned char tc[3], int out_n) {
+static int _m3dstbi__compute_transparency(_m3dstbi__png *z, unsigned char* tc, int out_n) {
     _m3dstbi__context *s = z->s;
     _m3dstbi__context *s = z->s;
     _m3dstbi__uint32 i, pixel_count = s->img_x * s->img_y;
     _m3dstbi__uint32 i, pixel_count = s->img_x * s->img_y;
     unsigned char *p = z->out;
     unsigned char *p = z->out;
@@ -1639,7 +1639,7 @@ static int _m3dstbi__expand_png_palette(_m3dstbi__png *a, unsigned char *palette
 
 
 static int _m3dstbi__parse_png_file(_m3dstbi__png *z, int scan, int req_comp) {
 static int _m3dstbi__parse_png_file(_m3dstbi__png *z, int scan, int req_comp) {
     unsigned char palette[1024], pal_img_n = 0;
     unsigned char palette[1024], pal_img_n = 0;
-    unsigned char has_trans = 0, tc[3];
+    unsigned char has_trans = 0, tc[3] = {};
     _m3dstbi__uint16 tc16[3];
     _m3dstbi__uint16 tc16[3];
     _m3dstbi__uint32 ioff = 0, idata_limit = 0, i, pal_len = 0;
     _m3dstbi__uint32 ioff = 0, idata_limit = 0, i, pal_len = 0;
     int first = 1, k, interlace = 0, color = 0;
     int first = 1, k, interlace = 0, color = 0;
@@ -4350,7 +4350,7 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
     M3D_INDEX last, *vrtxidx = NULL, *mtrlidx = NULL, *tmapidx = NULL, *skinidx = NULL;
     M3D_INDEX last, *vrtxidx = NULL, *mtrlidx = NULL, *tmapidx = NULL, *skinidx = NULL;
     uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, maxvrtx = 0, numtmap = 0, maxtmap = 0, numproc = 0;
     uint32_t idx, numcmap = 0, *cmap = NULL, numvrtx = 0, maxvrtx = 0, numtmap = 0, maxtmap = 0, numproc = 0;
     uint32_t numskin = 0, maxskin = 0, numstr = 0, maxt = 0, maxbone = 0, numgrp = 0, maxgrp = 0, *grpidx = NULL;
     uint32_t numskin = 0, maxskin = 0, numstr = 0, maxt = 0, maxbone = 0, numgrp = 0, maxgrp = 0, *grpidx = NULL;
-    uint8_t *opa;
+    uint8_t *opa = nullptr;
     m3dcd_t *cd;
     m3dcd_t *cd;
     m3dc_t *cmd;
     m3dc_t *cmd;
     m3dstr_t *str = NULL;
     m3dstr_t *str = NULL;
@@ -5440,13 +5440,13 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
                         out += 2;
                         out += 2;
                         break;
                         break;
                     case 4:
                     case 4:
-                        *((float *)out) = vrtx[i].data.x;
+                        memcpy(out, &vrtx[i].data.x, sizeof(float));
                         out += 4;
                         out += 4;
-                        *((float *)out) = vrtx[i].data.y;
+                        memcpy(out, &vrtx[i].data.y, sizeof(float));
                         out += 4;
                         out += 4;
-                        *((float *)out) = vrtx[i].data.z;
+                        memcpy(out, &vrtx[i].data.z, sizeof(float));
                         out += 4;
                         out += 4;
-                        *((float *)out) = vrtx[i].data.w;
+                        memcpy(out, &vrtx[i].data.w, sizeof(float));
                         out += 4;
                         out += 4;
                         break;
                         break;
                     case 8:
                     case 8:
@@ -5474,9 +5474,11 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
                 }
                 }
                 out = _m3d_addidx(out, sk_s, vrtx[i].data.skinid);
                 out = _m3d_addidx(out, sk_s, vrtx[i].data.skinid);
             }
             }
-            *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
+            uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
+            memcpy(length, &v, sizeof(uint32_t));
+            //*length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
             out = NULL;
             out = NULL;
-            len += *length;
+            len += v;
         }
         }
         /* bones chunk */
         /* bones chunk */
         if (model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) {
         if (model->numbone && model->bone && !(flags & M3D_EXP_NOBONE)) {
@@ -5660,8 +5662,9 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
                         out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.normal[j]]);
                         out = _m3d_addidx(out, vi_s, vrtxidx[face[i].data.normal[j]]);
                 }
                 }
             }
             }
-            *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
-            len += *length;
+            uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
+            memcpy(length, &v, sizeof(uint32_t));
+            len += v;
             out = NULL;
             out = NULL;
         }
         }
         /* mathematical shapes face */
         /* mathematical shapes face */
@@ -5721,8 +5724,9 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
                         }
                         }
                     }
                     }
                 }
                 }
-                *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
-                len += *length;
+                uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
+                memcpy( length, &v, sizeof(uint32_t));
+                len += v;
                 out = NULL;
                 out = NULL;
             }
             }
         }
         }
@@ -5765,8 +5769,9 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
                 out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].text));
                 out = _m3d_addidx(out, si_s, _m3d_stridx(str, numstr, model->label[l].text));
             }
             }
             if (length) {
             if (length) {
-                *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
-                len += *length;
+                uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
+                memcpy( length, &v, sizeof(uint32_t));                
+                len += v;
             }
             }
             out = NULL;
             out = NULL;
             sn = sl = NULL;
             sn = sl = NULL;
@@ -5796,8 +5801,9 @@ unsigned char *m3d_save(m3d_t *model, int quality, int flags, unsigned int *size
                         out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].ori]);
                         out = _m3d_addidx(out, vi_s, vrtxidx[a->frame[i].transform[k].ori]);
                     }
                     }
                 }
                 }
-                *length = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
-                len += *length;
+                uint32_t v = (uint32_t)((uintptr_t)out - (uintptr_t)((uint8_t *)h + len));
+                memcpy( length, &v, sizeof(uint32_t));                
+                len += v;
                 out = NULL;
                 out = NULL;
             }
             }
         }
         }

+ 1 - 1
code/Material/MaterialSystem.cpp

@@ -503,7 +503,7 @@ aiReturn aiMaterial::AddBinaryProperty (const void* pInput,
     pcNew->mData = new char[pSizeInBytes];
     pcNew->mData = new char[pSizeInBytes];
     memcpy (pcNew->mData,pInput,pSizeInBytes);
     memcpy (pcNew->mData,pInput,pSizeInBytes);
 
 
-    pcNew->mKey.length = (ai_uint32)::strlen(pKey);
+    pcNew->mKey.length = static_cast<ai_uint32>( ::strlen(pKey) );
     ai_assert ( MAXLEN > pcNew->mKey.length);
     ai_assert ( MAXLEN > pcNew->mKey.length);
     strcpy( pcNew->mKey.data, pKey );
     strcpy( pcNew->mKey.data, pKey );
 
 

+ 57 - 66
code/PostProcessing/LimitBoneWeightsProcess.cpp

@@ -44,6 +44,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 
 
 #include "LimitBoneWeightsProcess.h"
 #include "LimitBoneWeightsProcess.h"
+#include <assimp/SmallVector.h>
 #include <assimp/StringUtils.h>
 #include <assimp/StringUtils.h>
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
@@ -52,7 +53,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 using namespace Assimp;
 using namespace Assimp;
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 LimitBoneWeightsProcess::LimitBoneWeightsProcess()
 LimitBoneWeightsProcess::LimitBoneWeightsProcess()
@@ -76,10 +76,12 @@ bool LimitBoneWeightsProcess::IsActive( unsigned int pFlags) const
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Executes the post processing step on the given imported data.
 // Executes the post processing step on the given imported data.
-void LimitBoneWeightsProcess::Execute( aiScene* pScene) {
+void LimitBoneWeightsProcess::Execute( aiScene* pScene)
+{
     ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
     ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess begin");
-    for (unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
-        ProcessMesh(pScene->mMeshes[a]);
+
+    for (unsigned int m = 0; m < pScene->mNumMeshes; ++m) {
+        ProcessMesh(pScene->mMeshes[m]);
     }
     }
 
 
     ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess end");
     ASSIMP_LOG_DEBUG("LimitBoneWeightsProcess end");
@@ -95,107 +97,96 @@ void LimitBoneWeightsProcess::SetupProperties(const Importer* pImp)
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Unites identical vertices in the given mesh
 // Unites identical vertices in the given mesh
-void LimitBoneWeightsProcess::ProcessMesh( aiMesh* pMesh)
+void LimitBoneWeightsProcess::ProcessMesh(aiMesh* pMesh)
 {
 {
-    if( !pMesh->HasBones())
+    if (!pMesh->HasBones())
         return;
         return;
 
 
     // collect all bone weights per vertex
     // collect all bone weights per vertex
-    typedef std::vector< std::vector< Weight > > WeightsPerVertex;
-    WeightsPerVertex vertexWeights( pMesh->mNumVertices);
+    typedef SmallVector<Weight,8> VertexWeightArray;
+    typedef std::vector<VertexWeightArray> WeightsPerVertex;
+    WeightsPerVertex vertexWeights(pMesh->mNumVertices);
+    size_t maxVertexWeights = 0;
 
 
-    // collect all weights per vertex
-    for( unsigned int a = 0; a < pMesh->mNumBones; a++)
+    for (unsigned int b = 0; b < pMesh->mNumBones; ++b)
     {
     {
-        const aiBone* bone = pMesh->mBones[a];
-        for( unsigned int b = 0; b < bone->mNumWeights; b++)
+        const aiBone* bone = pMesh->mBones[b];
+        for (unsigned int w = 0; w < bone->mNumWeights; ++w)
         {
         {
-            const aiVertexWeight& w = bone->mWeights[b];
-            vertexWeights[w.mVertexId].push_back( Weight( a, w.mWeight));
+            const aiVertexWeight& vw = bone->mWeights[w];
+            vertexWeights[vw.mVertexId].push_back(Weight(b, vw.mWeight));
+            maxVertexWeights = std::max(maxVertexWeights, vertexWeights[vw.mVertexId].size());
         }
         }
     }
     }
 
 
+    if (maxVertexWeights <= mMaxWeights)
+        return;
+
     unsigned int removed = 0, old_bones = pMesh->mNumBones;
     unsigned int removed = 0, old_bones = pMesh->mNumBones;
 
 
     // now cut the weight count if it exceeds the maximum
     // now cut the weight count if it exceeds the maximum
-    bool bChanged = false;
-    for( WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
+    for (WeightsPerVertex::iterator vit = vertexWeights.begin(); vit != vertexWeights.end(); ++vit)
     {
     {
-        if( vit->size() <= mMaxWeights)
+        if (vit->size() <= mMaxWeights)
             continue;
             continue;
 
 
-        bChanged = true;
-
         // more than the defined maximum -> first sort by weight in descending order. That's
         // more than the defined maximum -> first sort by weight in descending order. That's
         // why we defined the < operator in such a weird way.
         // why we defined the < operator in such a weird way.
-        std::sort( vit->begin(), vit->end());
+        std::sort(vit->begin(), vit->end());
 
 
         // now kill everything beyond the maximum count
         // now kill everything beyond the maximum count
         unsigned int m = static_cast<unsigned int>(vit->size());
         unsigned int m = static_cast<unsigned int>(vit->size());
-        vit->erase( vit->begin() + mMaxWeights, vit->end());
-        removed += static_cast<unsigned int>(m-vit->size());
+        vit->resize(mMaxWeights);
+        removed += static_cast<unsigned int>(m - vit->size());
 
 
         // and renormalize the weights
         // and renormalize the weights
         float sum = 0.0f;
         float sum = 0.0f;
-        for( std::vector<Weight>::const_iterator it = vit->begin(); it != vit->end(); ++it ) {
+        for(const Weight* it = vit->begin(); it != vit->end(); ++it) {
             sum += it->mWeight;
             sum += it->mWeight;
         }
         }
-        if( 0.0f != sum ) {
+        if (0.0f != sum) {
             const float invSum = 1.0f / sum;
             const float invSum = 1.0f / sum;
-            for( std::vector<Weight>::iterator it = vit->begin(); it != vit->end(); ++it ) {
+            for(Weight* it = vit->begin(); it != vit->end(); ++it) {
                 it->mWeight *= invSum;
                 it->mWeight *= invSum;
             }
             }
         }
         }
     }
     }
 
 
-    if (bChanged)   {
-        // rebuild the vertex weight array for all bones
-        typedef std::vector< std::vector< aiVertexWeight > > WeightsPerBone;
-        WeightsPerBone boneWeights( pMesh->mNumBones);
-        for( unsigned int a = 0; a < vertexWeights.size(); a++)
+    // clear weight count for all bone
+    for (unsigned int a = 0; a < pMesh->mNumBones; ++a)
+    {
+        pMesh->mBones[a]->mNumWeights = 0;
+    }
+
+    // rebuild the vertex weight array for all bones
+    for (unsigned int a = 0; a < vertexWeights.size(); ++a)
+    {
+        const VertexWeightArray& vw = vertexWeights[a];
+        for (const Weight* it = vw.begin(); it != vw.end(); ++it)
         {
         {
-            const std::vector<Weight>& vw = vertexWeights[a];
-            for( std::vector<Weight>::const_iterator it = vw.begin(); it != vw.end(); ++it)
-                boneWeights[it->mBone].push_back( aiVertexWeight( a, it->mWeight));
+            aiBone* bone = pMesh->mBones[it->mBone];
+            bone->mWeights[bone->mNumWeights++] = aiVertexWeight(a, it->mWeight);
         }
         }
+    }
 
 
-        // and finally copy the vertex weight list over to the mesh's bones
-        std::vector<bool> abNoNeed(pMesh->mNumBones,false);
-        bChanged = false;
+    // remove empty bones
+    unsigned int writeBone = 0;
 
 
-        for( unsigned int a = 0; a < pMesh->mNumBones; a++)
+    for (unsigned int readBone = 0; readBone< pMesh->mNumBones; ++readBone)
+    {
+        aiBone* bone = pMesh->mBones[readBone];
+        if (bone->mNumWeights > 0)
         {
         {
-            const std::vector<aiVertexWeight>& bw = boneWeights[a];
-            aiBone* bone = pMesh->mBones[a];
-
-            if ( bw.empty() )
-            {
-                abNoNeed[a] = bChanged = true;
-                continue;
-            }
-
-            // copy the weight list. should always be less weights than before, so we don't need a new allocation
-            ai_assert( bw.size() <= bone->mNumWeights);
-            bone->mNumWeights = static_cast<unsigned int>( bw.size() );
-            ::memcpy( bone->mWeights, &bw[0], bw.size() * sizeof( aiVertexWeight));
+            pMesh->mBones[writeBone++] = bone;
         }
         }
-
-        if (bChanged)   {
-            // the number of new bones is smaller than before, so we can reuse the old array
-            aiBone** ppcCur = pMesh->mBones;aiBone** ppcSrc = ppcCur;
-
-            for (std::vector<bool>::const_iterator iter  = abNoNeed.begin();iter != abNoNeed.end()  ;++iter)    {
-                if (*iter)  {
-                    delete *ppcSrc;
-                    --pMesh->mNumBones;
-                }
-                else *ppcCur++ = *ppcSrc;
-                ++ppcSrc;
-            }
+        else
+        {
+            delete bone;
         }
         }
+    }
+    pMesh->mNumBones = writeBone;
 
 
-        if (!DefaultLogger::isNullLogger()) {
-            ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones );
-        }
+    if (!DefaultLogger::isNullLogger()) {
+        ASSIMP_LOG_INFO_F("Removed ", removed, " weights. Input bones: ", old_bones, ". Output bones: ", pMesh->mNumBones);
     }
     }
 }
 }

+ 1 - 1
code/Q3BSP/Q3BSPFileImporter.cpp

@@ -617,7 +617,7 @@ bool Q3BSPFileImporter::importTextureFromArchive( const Q3BSP::Q3BSPModel *model
             // We'll leave it up to the user to figure out which extension the file has.
             // We'll leave it up to the user to figure out which extension the file has.
             aiString name;
             aiString name;
             strncpy( name.data, pTexture->strName, sizeof name.data );
             strncpy( name.data, pTexture->strName, sizeof name.data );
-            name.length = (ai_uint32)strlen( name.data );
+            name.length = static_cast<ai_uint32>(strlen( name.data ));
             pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
             pMatHelper->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) );
         }
         }
     }
     }

+ 1 - 1
code/SMD/SMDLoader.cpp

@@ -616,7 +616,7 @@ void SMDImporter::CreateOutputMaterials() {
         if (aszTextures[iMat].length())
         if (aszTextures[iMat].length())
         {
         {
             ::strncpy(szName.data, aszTextures[iMat].c_str(),MAXLEN-1);
             ::strncpy(szName.data, aszTextures[iMat].c_str(),MAXLEN-1);
-            szName.length = (ai_uint32)aszTextures[iMat].length();
+            szName.length = static_cast<ai_uint32>( aszTextures[iMat].length() );
             pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
             pcMat->AddProperty(&szName,AI_MATKEY_TEXTURE_DIFFUSE(0));
         }
         }
     }
     }

+ 66 - 82
code/Terragen/TerragenLoader.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,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 /** @file Implementation of the Terragen importer class */
 /** @file Implementation of the Terragen importer class */
 
 
-
-
 #ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
 #ifndef ASSIMP_BUILD_NO_TERRAGEN_IMPORTER
 
 
 #include "TerragenLoader.h"
 #include "TerragenLoader.h"
 #include <assimp/StreamReader.h>
 #include <assimp/StreamReader.h>
-#include <assimp/Importer.hpp>
-#include <assimp/IOSystem.hpp>
+#include <assimp/importerdesc.h>
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
-#include <assimp/importerdesc.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/Importer.hpp>
 
 
 using namespace Assimp;
 using namespace Assimp;
 
 
@@ -72,78 +68,72 @@ static const aiImporterDesc desc = {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
-TerragenImporter::TerragenImporter()
-: configComputeUVs (false)
-{}
+TerragenImporter::TerragenImporter() :
+        configComputeUVs(false) {}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-TerragenImporter::~TerragenImporter()
-{}
+TerragenImporter::~TerragenImporter() {}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // 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 TerragenImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
-{
+bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
     // check file extension
     // check file extension
     std::string extension = GetExtension(pFile);
     std::string extension = GetExtension(pFile);
 
 
-    if( extension == "ter")
+    if (extension == "ter")
         return true;
         return true;
 
 
-    if(  !extension.length() || checkSig)   {
+    if (!extension.length() || checkSig) {
         /*  If CanRead() is called in order to check whether we
         /*  If CanRead() is called in order to check whether we
          *  support a specific file extension in general pIOHandler
          *  support a specific file extension in general pIOHandler
          *  might be NULL and it's our duty to return true here.
          *  might be NULL and it's our duty to return true here.
          */
          */
-        if (!pIOHandler)return true;
-        const char* tokens[] = {"terragen"};
-        return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
+        if (!pIOHandler) return true;
+        const char *tokens[] = { "terragen" };
+        return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
     }
     }
     return false;
     return false;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Build a string of all file extensions supported
 // Build a string of all file extensions supported
-const aiImporterDesc* TerragenImporter::GetInfo () const
-{
+const aiImporterDesc *TerragenImporter::GetInfo() const {
     return &desc;
     return &desc;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Setup import properties
 // Setup import properties
-void TerragenImporter::SetupProperties(const Importer* pImp)
-{
+void TerragenImporter::SetupProperties(const Importer *pImp) {
     // AI_CONFIG_IMPORT_TER_MAKE_UVS
     // AI_CONFIG_IMPORT_TER_MAKE_UVS
-    configComputeUVs = ( 0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS,0) );
+    configComputeUVs = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_TER_MAKE_UVS, 0));
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
 // Imports the given file into the given scene structure.
-void TerragenImporter::InternReadFile( const std::string& pFile,
-    aiScene* pScene, IOSystem* pIOHandler)
-{
-    IOStream* file = pIOHandler->Open( pFile, "rb");
+void TerragenImporter::InternReadFile(const std::string &pFile,
+        aiScene *pScene, IOSystem *pIOHandler) {
+    IOStream *file = pIOHandler->Open(pFile, "rb");
 
 
     // Check whether we can read from the file
     // Check whether we can read from the file
-    if( file == NULL)
-        throw DeadlyImportError( "Failed to open TERRAGEN TERRAIN file " + pFile + ".");
+    if (file == NULL)
+        throw DeadlyImportError("Failed to open TERRAGEN TERRAIN file " + pFile + ".");
 
 
     // Construct a stream reader to read all data in the correct endianness
     // Construct a stream reader to read all data in the correct endianness
     StreamReaderLE reader(file);
     StreamReaderLE reader(file);
-    if(reader.GetRemainingSize() < 16)
-        throw DeadlyImportError( "TER: file is too small" );
+    if (reader.GetRemainingSize() < 16)
+        throw DeadlyImportError("TER: file is too small");
 
 
     // Check for the existence of the two magic strings 'TERRAGEN' and 'TERRAIN '
     // Check for the existence of the two magic strings 'TERRAGEN' and 'TERRAIN '
-    if (::strncmp((const char*)reader.GetPtr(),AI_TERR_BASE_STRING,8))
-        throw DeadlyImportError( "TER: Magic string \'TERRAGEN\' not found" );
+    if (::strncmp((const char *)reader.GetPtr(), AI_TERR_BASE_STRING, 8))
+        throw DeadlyImportError("TER: Magic string \'TERRAGEN\' not found");
 
 
-    if (::strncmp((const char*)reader.GetPtr()+8,AI_TERR_TERRAIN_STRING,8))
-        throw DeadlyImportError( "TER: Magic string \'TERRAIN\' not found" );
+    if (::strncmp((const char *)reader.GetPtr() + 8, AI_TERR_TERRAIN_STRING, 8))
+        throw DeadlyImportError("TER: Magic string \'TERRAIN\' not found");
 
 
-    unsigned int x = 0,y = 0,mode = 0;
+    unsigned int x = 0, y = 0, mode = 0;
 
 
-    aiNode* root = pScene->mRootNode = new aiNode();
+    aiNode *root = pScene->mRootNode = new aiNode();
     root->mName.Set("<TERRAGEN.TERRAIN>");
     root->mName.Set("<TERRAGEN.TERRAIN>");
 
 
     // Default scaling is 30
     // Default scaling is 30
@@ -151,104 +141,98 @@ void TerragenImporter::InternReadFile( const std::string& pFile,
 
 
     // Now read all chunks until we're finished or an EOF marker is encountered
     // Now read all chunks until we're finished or an EOF marker is encountered
     reader.IncPtr(16);
     reader.IncPtr(16);
-    while (reader.GetRemainingSize() >= 4)
-    {
-        const char* head = (const char*)reader.GetPtr();
+    while (reader.GetRemainingSize() >= 4) {
+        const char *head = (const char *)reader.GetPtr();
         reader.IncPtr(4);
         reader.IncPtr(4);
 
 
         // EOF, break in every case
         // EOF, break in every case
-        if (!::strncmp(head,AI_TERR_EOF_STRING,4))
+        if (!::strncmp(head, AI_TERR_EOF_STRING, 4))
             break;
             break;
 
 
         // Number of x-data points
         // Number of x-data points
-        if (!::strncmp(head,AI_TERR_CHUNK_XPTS,4))
-        {
+        if (!::strncmp(head, AI_TERR_CHUNK_XPTS, 4)) {
             x = (uint16_t)reader.GetI2();
             x = (uint16_t)reader.GetI2();
         }
         }
         // Number of y-data points
         // Number of y-data points
-        else if (!::strncmp(head,AI_TERR_CHUNK_YPTS,4))
-        {
+        else if (!::strncmp(head, AI_TERR_CHUNK_YPTS, 4)) {
             y = (uint16_t)reader.GetI2();
             y = (uint16_t)reader.GetI2();
         }
         }
         // Squared terrains width-1.
         // Squared terrains width-1.
-        else if (!::strncmp(head,AI_TERR_CHUNK_SIZE,4))
-        {
-            x = y = (uint16_t)reader.GetI2()+1;
+        else if (!::strncmp(head, AI_TERR_CHUNK_SIZE, 4)) {
+            x = y = (uint16_t)reader.GetI2() + 1;
         }
         }
         // terrain scaling
         // terrain scaling
-        else if (!::strncmp(head,AI_TERR_CHUNK_SCAL,4))
-        {
+        else if (!::strncmp(head, AI_TERR_CHUNK_SCAL, 4)) {
             root->mTransformation.a1 = reader.GetF4();
             root->mTransformation.a1 = reader.GetF4();
             root->mTransformation.b2 = reader.GetF4();
             root->mTransformation.b2 = reader.GetF4();
             root->mTransformation.c3 = reader.GetF4();
             root->mTransformation.c3 = reader.GetF4();
         }
         }
         // mapping == 1: earth radius
         // mapping == 1: earth radius
-        else if (!::strncmp(head,AI_TERR_CHUNK_CRAD,4))
-        {
+        else if (!::strncmp(head, AI_TERR_CHUNK_CRAD, 4)) {
             reader.GetF4();
             reader.GetF4();
         }
         }
         // mapping mode
         // mapping mode
-        else if (!::strncmp(head,AI_TERR_CHUNK_CRVM,4))
-        {
+        else if (!::strncmp(head, AI_TERR_CHUNK_CRVM, 4)) {
             mode = reader.GetI1();
             mode = reader.GetI1();
             if (0 != mode)
             if (0 != mode)
                 ASSIMP_LOG_ERROR("TER: Unsupported mapping mode, a flat terrain is returned");
                 ASSIMP_LOG_ERROR("TER: Unsupported mapping mode, a flat terrain is returned");
         }
         }
         // actual terrain data
         // actual terrain data
-        else if (!::strncmp(head,AI_TERR_CHUNK_ALTW,4))
-        {
-            float hscale  = (float)reader.GetI2()  / 65536;
+        else if (!::strncmp(head, AI_TERR_CHUNK_ALTW, 4)) {
+            float hscale = (float)reader.GetI2() / 65536;
             float bheight = (float)reader.GetI2();
             float bheight = (float)reader.GetI2();
 
 
-            if (!hscale)hscale = 1;
+            if (!hscale) hscale = 1;
 
 
             // Ensure we have enough data
             // Ensure we have enough data
-            if (reader.GetRemainingSize() < x*y*2)
+            if (reader.GetRemainingSize() < x * y * 2)
                 throw DeadlyImportError("TER: ALTW chunk is too small");
                 throw DeadlyImportError("TER: ALTW chunk is too small");
 
 
             if (x <= 1 || y <= 1)
             if (x <= 1 || y <= 1)
                 throw DeadlyImportError("TER: Invalid terrain size");
                 throw DeadlyImportError("TER: Invalid terrain size");
 
 
             // Allocate the output mesh
             // Allocate the output mesh
-            pScene->mMeshes = new aiMesh*[pScene->mNumMeshes = 1];
-            aiMesh* m = pScene->mMeshes[0] = new aiMesh();
+            pScene->mMeshes = new aiMesh *[pScene->mNumMeshes = 1];
+            aiMesh *m = pScene->mMeshes[0] = new aiMesh();
 
 
             // We return quads
             // We return quads
-            aiFace* f = m->mFaces = new aiFace[m->mNumFaces = (x-1)*(y-1)];
-            aiVector3D* pv = m->mVertices = new aiVector3D[m->mNumVertices = m->mNumFaces*4];
+            aiFace *f = m->mFaces = new aiFace[m->mNumFaces = (x - 1) * (y - 1)];
+            aiVector3D *pv = m->mVertices = new aiVector3D[m->mNumVertices = m->mNumFaces * 4];
 
 
-            aiVector3D *uv( NULL );
-            float step_y( 0.0f ), step_x( 0.0f );
+            aiVector3D *uv(NULL);
+            float step_y(0.0f), step_x(0.0f);
             if (configComputeUVs) {
             if (configComputeUVs) {
                 uv = m->mTextureCoords[0] = new aiVector3D[m->mNumVertices];
                 uv = m->mTextureCoords[0] = new aiVector3D[m->mNumVertices];
-                step_y = 1.f/y;
-                step_x = 1.f/x;
+                step_y = 1.f / y;
+                step_x = 1.f / x;
             }
             }
-            const int16_t* data = (const int16_t*)reader.GetPtr();
+            const int16_t *data = (const int16_t *)reader.GetPtr();
 
 
-            for (unsigned int yy = 0, t = 0; yy < y-1;++yy) {
-                for (unsigned int xx = 0; xx < x-1;++xx,++f)    {
+            for (unsigned int yy = 0, t = 0; yy < y - 1; ++yy) {
+                for (unsigned int xx = 0; xx < x - 1; ++xx, ++f) {
 
 
                     // make verts
                     // make verts
                     const float fy = (float)yy, fx = (float)xx;
                     const float fy = (float)yy, fx = (float)xx;
-                    unsigned tmp,tmp2;
-                    *pv++ = aiVector3D(fx,fy,    (float)data[(tmp2=x*yy)    + xx] * hscale + bheight);
-                    *pv++ = aiVector3D(fx,fy+1,  (float)data[(tmp=x*(yy+1)) + xx] * hscale + bheight);
-                    *pv++ = aiVector3D(fx+1,fy+1,(float)data[tmp  + xx+1]         * hscale + bheight);
-                    *pv++ = aiVector3D(fx+1,fy,  (float)data[tmp2 + xx+1]         * hscale + bheight);
+                    unsigned tmp, tmp2;
+                    *pv++ = aiVector3D(fx, fy, (float)data[(tmp2 = x * yy) + xx] * hscale + bheight);
+                    *pv++ = aiVector3D(fx, fy + 1, (float)data[(tmp = x * (yy + 1)) + xx] * hscale + bheight);
+                    *pv++ = aiVector3D(fx + 1, fy + 1, (float)data[tmp + xx + 1] * hscale + bheight);
+                    *pv++ = aiVector3D(fx + 1, fy, (float)data[tmp2 + xx + 1] * hscale + bheight);
 
 
                     // also make texture coordinates, if necessary
                     // also make texture coordinates, if necessary
                     if (configComputeUVs) {
                     if (configComputeUVs) {
-                        *uv++ = aiVector3D( step_x*xx,     step_y*yy,     0.f );
-                        *uv++ = aiVector3D( step_x*xx,     step_y*(yy+1), 0.f );
-                        *uv++ = aiVector3D( step_x*(xx+1), step_y*(yy+1), 0.f );
-                        *uv++ = aiVector3D( step_x*(xx+1), step_y*yy,     0.f );
+                        *uv++ = aiVector3D(step_x * xx, step_y * yy, 0.f);
+                        *uv++ = aiVector3D(step_x * xx, step_y * (yy + 1), 0.f);
+                        *uv++ = aiVector3D(step_x * (xx + 1), step_y * (yy + 1), 0.f);
+                        *uv++ = aiVector3D(step_x * (xx + 1), step_y * yy, 0.f);
                     }
                     }
 
 
                     // make indices
                     // make indices
                     f->mIndices = new unsigned int[f->mNumIndices = 4];
                     f->mIndices = new unsigned int[f->mNumIndices = 4];
-                    for (unsigned int i = 0; i < 4;++i)
-                        f->mIndices[i] = t++;
+                    for (unsigned int i = 0; i < 4; ++i) {
+                        f->mIndices[i] = t;
+                        t++;
+                    }
                 }
                 }
             }
             }
 
 

+ 18 - 24
code/Terragen/TerragenLoader.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,
@@ -47,21 +46,21 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_TERRAGEN_TERRAIN_LOADER_H
 #define INCLUDED_AI_TERRAGEN_TERRAIN_LOADER_H
 
 
 #include <assimp/BaseImporter.h>
 #include <assimp/BaseImporter.h>
-namespace Assimp    {
+namespace Assimp {
 
 
 // Magic strings
 // Magic strings
-#define AI_TERR_BASE_STRING         "TERRAGEN"
-#define AI_TERR_TERRAIN_STRING      "TERRAIN "
-#define AI_TERR_EOF_STRING          "EOF "
+#define AI_TERR_BASE_STRING "TERRAGEN"
+#define AI_TERR_TERRAIN_STRING "TERRAIN "
+#define AI_TERR_EOF_STRING "EOF "
 
 
 // Chunka
 // Chunka
-#define AI_TERR_CHUNK_XPTS          "XPTS"
-#define AI_TERR_CHUNK_YPTS          "YPTS"
-#define AI_TERR_CHUNK_SIZE          "SIZE"
-#define AI_TERR_CHUNK_SCAL          "SCAL"
-#define AI_TERR_CHUNK_CRAD          "CRAD"
-#define AI_TERR_CHUNK_CRVM          "CRVM"
-#define AI_TERR_CHUNK_ALTW          "ALTW"
+#define AI_TERR_CHUNK_XPTS "XPTS"
+#define AI_TERR_CHUNK_YPTS "YPTS"
+#define AI_TERR_CHUNK_SIZE "SIZE"
+#define AI_TERR_CHUNK_SCAL "SCAL"
+#define AI_TERR_CHUNK_CRAD "CRAD"
+#define AI_TERR_CHUNK_CRVM "CRVM"
+#define AI_TERR_CHUNK_ALTW "ALTW"
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** @brief Importer class to load Terragen (0.9) terrain files.
 /** @brief Importer class to load Terragen (0.9) terrain files.
@@ -69,33 +68,28 @@ namespace Assimp    {
  *  The loader is basing on the information found here:
  *  The loader is basing on the information found here:
  *  http://www.planetside.co.uk/terragen/dev/tgterrain.html#chunks
  *  http://www.planetside.co.uk/terragen/dev/tgterrain.html#chunks
 */
 */
-class TerragenImporter : public BaseImporter
-{
+class TerragenImporter : public BaseImporter {
 public:
 public:
     TerragenImporter();
     TerragenImporter();
     ~TerragenImporter();
     ~TerragenImporter();
 
 
-
 public:
 public:
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
-    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
+            bool checkSig) const;
 
 
 protected:
 protected:
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
-    const aiImporterDesc* GetInfo () const;
+    const aiImporterDesc *GetInfo() const;
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
-    void InternReadFile( const std::string& pFile, aiScene* pScene,
-        IOSystem* pIOHandler);
+    void InternReadFile(const std::string &pFile, aiScene *pScene,
+            IOSystem *pIOHandler);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
-    void SetupProperties(const Importer* pImp);
+    void SetupProperties(const Importer *pImp);
 
 
 private:
 private:
-
     bool configComputeUVs;
     bool configComputeUVs;
 
 
 }; //! class TerragenImporter
 }; //! class TerragenImporter

+ 212 - 141
code/Unreal/UnrealLoader.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,
@@ -48,26 +46,112 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *    http://local.wasp.uwa.edu.au/~pbourke/dataformats/unreal/
  *    http://local.wasp.uwa.edu.au/~pbourke/dataformats/unreal/
  */
  */
 
 
-
-
 #ifndef ASSIMP_BUILD_NO_3D_IMPORTER
 #ifndef ASSIMP_BUILD_NO_3D_IMPORTER
 
 
 #include "Unreal/UnrealLoader.h"
 #include "Unreal/UnrealLoader.h"
 #include "PostProcessing/ConvertToLHProcess.h"
 #include "PostProcessing/ConvertToLHProcess.h"
 
 
-#include <assimp/StreamReader.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/ParsingUtils.h>
+#include <assimp/StreamReader.h>
 #include <assimp/fast_atof.h>
 #include <assimp/fast_atof.h>
-#include <assimp/Importer.hpp>
+#include <assimp/importerdesc.h>
+#include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
-#include <assimp/scene.h>
-#include <assimp/importerdesc.h>
+#include <assimp/Importer.hpp>
 
 
+#include <stdint.h>
 #include <memory>
 #include <memory>
 
 
 using namespace Assimp;
 using namespace Assimp;
 
 
+namespace Unreal {
+
+/*
+    0 = Normal one-sided
+    1 = Normal two-sided
+    2 = Translucent two-sided
+    3 = Masked two-sided
+    4 = Modulation blended two-sided
+    8 = Placeholder triangle for weapon positioning (invisible)
+    */
+enum MeshFlags {
+    MF_NORMAL_OS = 0,
+    MF_NORMAL_TS = 1,
+    MF_NORMAL_TRANS_TS = 2,
+    MF_NORMAL_MASKED_TS = 3,
+    MF_NORMAL_MOD_TS = 4,
+    MF_WEAPON_PLACEHOLDER = 8
+};
+
+// a single triangle
+struct Triangle {
+    uint16_t mVertex[3]; // Vertex indices
+    char mType; // James' Mesh Type
+    char mColor; // Color for flat and Gourand Shaded
+    unsigned char mTex[3][2]; // Texture UV coordinates
+    unsigned char mTextureNum; // Source texture offset
+    char mFlags; // Unreal Mesh Flags (unused)
+    unsigned int matIndex;
+};
+
+// temporary representation for a material
+struct TempMat {
+    TempMat() :
+            type(MF_NORMAL_OS), tex(), numFaces(0) {}
+
+    explicit TempMat(const Triangle &in) :
+            type((Unreal::MeshFlags)in.mType), tex(in.mTextureNum), numFaces(0) {}
+
+    // type of mesh
+    Unreal::MeshFlags type;
+
+    // index of texture
+    unsigned int tex;
+
+    // number of faces using us
+    unsigned int numFaces;
+
+    // for std::find
+    bool operator==(const TempMat &o) {
+        return (tex == o.tex && type == o.type);
+    }
+};
+
+struct Vertex {
+    int32_t X : 11;
+    int32_t Y : 11;
+    int32_t Z : 10;
+};
+
+// UNREAL vertex compression
+inline void CompressVertex(const aiVector3D &v, uint32_t &out) {
+    union {
+        Vertex n;
+        int32_t t;
+    };
+    t = 0;
+    n.X = (int32_t)v.x;
+    n.Y = (int32_t)v.y;
+    n.Z = (int32_t)v.z;
+    ::memcpy(&out, &t, sizeof(int32_t));
+}
+
+// UNREAL vertex decompression
+inline void DecompressVertex(aiVector3D &v, int32_t in) {
+    union {
+        Vertex n;
+        int32_t i;
+    };
+    i = in;
+
+    v.x = (float)n.X;
+    v.y = (float)n.Y;
+    v.z = (float)n.Z;
+}
+
+} // end namespace Unreal
+
 static const aiImporterDesc desc = {
 static const aiImporterDesc desc = {
     "Unreal Mesh Importer",
     "Unreal Mesh Importer",
     "",
     "",
@@ -81,79 +165,70 @@ static const aiImporterDesc desc = {
     "3d uc"
     "3d uc"
 };
 };
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
-UnrealImporter::UnrealImporter()
-:   configFrameID   (0)
-,   configHandleFlags (true)
-{}
+UnrealImporter::UnrealImporter() :
+        mConfigFrameID(0), mConfigHandleFlags(true) {}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-UnrealImporter::~UnrealImporter()
-{}
+UnrealImporter::~UnrealImporter() {}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // 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 UnrealImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
-{
-    return  SimpleExtensionCheck(pFile,"3d","uc");
+bool UnrealImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
+    return SimpleExtensionCheck(pFile, "3d", "uc");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Build a string of all file extensions supported
 // Build a string of all file extensions supported
-const aiImporterDesc* UnrealImporter::GetInfo () const
-{
+const aiImporterDesc *UnrealImporter::GetInfo() const {
     return &desc;
     return &desc;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Setup configuration properties for the loader
 // Setup configuration properties for the loader
-void UnrealImporter::SetupProperties(const Importer* pImp)
-{
+void UnrealImporter::SetupProperties(const Importer *pImp) {
     // The
     // The
     // AI_CONFIG_IMPORT_UNREAL_KEYFRAME option overrides the
     // AI_CONFIG_IMPORT_UNREAL_KEYFRAME option overrides the
     // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
     // AI_CONFIG_IMPORT_GLOBAL_KEYFRAME option.
-    configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_KEYFRAME,-1);
-    if(static_cast<unsigned int>(-1) == configFrameID)  {
-        configFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME,0);
+    mConfigFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_KEYFRAME, -1);
+    if (static_cast<unsigned int>(-1) == mConfigFrameID) {
+        mConfigFrameID = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_GLOBAL_KEYFRAME, 0);
     }
     }
 
 
     // AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS, default is true
     // AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS, default is true
-    configHandleFlags = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS,1));
+    mConfigHandleFlags = (0 != pImp->GetPropertyInteger(AI_CONFIG_IMPORT_UNREAL_HANDLE_FLAGS, 1));
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
 // Imports the given file into the given scene structure.
-void UnrealImporter::InternReadFile( const std::string& pFile,
-    aiScene* pScene, IOSystem* pIOHandler)
-{
+void UnrealImporter::InternReadFile(const std::string &pFile,
+        aiScene *pScene, IOSystem *pIOHandler) {
     // For any of the 3 files being passed get the three correct paths
     // For any of the 3 files being passed get the three correct paths
     // First of all, determine file extension
     // First of all, determine file extension
     std::string::size_type pos = pFile.find_last_of('.');
     std::string::size_type pos = pFile.find_last_of('.');
     std::string extension = GetExtension(pFile);
     std::string extension = GetExtension(pFile);
 
 
-    std::string d_path,a_path,uc_path;
-    if (extension == "3d")      {
+    std::string d_path, a_path, uc_path;
+    if (extension == "3d") {
         // jjjj_d.3d
         // jjjj_d.3d
         // jjjj_a.3d
         // jjjj_a.3d
         pos = pFile.find_last_of('_');
         pos = pFile.find_last_of('_');
         if (std::string::npos == pos) {
         if (std::string::npos == pos) {
             throw DeadlyImportError("UNREAL: Unexpected naming scheme");
             throw DeadlyImportError("UNREAL: Unexpected naming scheme");
         }
         }
-        extension = pFile.substr(0,pos);
-    }
-    else {
-        extension = pFile.substr(0,pos);
+        extension = pFile.substr(0, pos);
+    } else {
+        extension = pFile.substr(0, pos);
     }
     }
 
 
     // build proper paths
     // build proper paths
-    d_path  = extension+"_d.3d";
-    a_path  = extension+"_a.3d";
-    uc_path = extension+".uc";
+    d_path = extension + "_d.3d";
+    a_path = extension + "_a.3d";
+    uc_path = extension + ".uc";
 
 
-    ASSIMP_LOG_DEBUG_F( "UNREAL: data file is ", d_path);
+    ASSIMP_LOG_DEBUG_F("UNREAL: data file is ", d_path);
     ASSIMP_LOG_DEBUG_F("UNREAL: aniv file is ", a_path);
     ASSIMP_LOG_DEBUG_F("UNREAL: aniv file is ", a_path);
     ASSIMP_LOG_DEBUG_F("UNREAL: uc file is ", uc_path);
     ASSIMP_LOG_DEBUG_F("UNREAL: uc file is ", uc_path);
 
 
@@ -174,11 +249,11 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
 
 
     // collect triangles
     // collect triangles
     std::vector<Unreal::Triangle> triangles(numTris);
     std::vector<Unreal::Triangle> triangles(numTris);
-    for (auto & tri : triangles) {
-        for (unsigned int i = 0; i < 3;++i) {
+    for (auto &tri : triangles) {
+        for (unsigned int i = 0; i < 3; ++i) {
 
 
             tri.mVertex[i] = d_reader.GetI2();
             tri.mVertex[i] = d_reader.GetI2();
-            if (tri.mVertex[i] >= numTris)  {
+            if (tri.mVertex[i] >= numTris) {
                 ASSIMP_LOG_WARN("UNREAL: vertex index out of range");
                 ASSIMP_LOG_WARN("UNREAL: vertex index out of range");
                 tri.mVertex[i] = 0;
                 tri.mVertex[i] = 0;
             }
             }
@@ -186,7 +261,7 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
         tri.mType = d_reader.GetI1();
         tri.mType = d_reader.GetI1();
 
 
         // handle mesh flagss?
         // handle mesh flagss?
-        if (configHandleFlags)
+        if (mConfigHandleFlags)
             tri.mType = Unreal::MF_NORMAL_OS;
             tri.mType = Unreal::MF_NORMAL_OS;
         else {
         else {
             // ignore MOD and MASKED for the moment, treat them as two-sided
             // ignore MOD and MASKED for the moment, treat them as two-sided
@@ -195,12 +270,12 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
         }
         }
         d_reader.IncPtr(1);
         d_reader.IncPtr(1);
 
 
-        for (unsigned int i = 0; i < 3;++i)
-            for (unsigned int i2 = 0; i2 < 2;++i2)
+        for (unsigned int i = 0; i < 3; ++i)
+            for (unsigned int i2 = 0; i2 < 2; ++i2)
                 tri.mTex[i][i2] = d_reader.GetI1();
                 tri.mTex[i][i2] = d_reader.GetI1();
 
 
         tri.mTextureNum = d_reader.GetI1();
         tri.mTextureNum = d_reader.GetI1();
-        maxTexIdx = std::max(maxTexIdx,(unsigned int)tri.mTextureNum);
+        maxTexIdx = std::max(maxTexIdx, (unsigned int)tri.mTextureNum);
         d_reader.IncPtr(1);
         d_reader.IncPtr(1);
     }
     }
 
 
@@ -211,63 +286,64 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
 
 
     // read number of frames
     // read number of frames
     const uint32_t numFrames = a_reader.GetI2();
     const uint32_t numFrames = a_reader.GetI2();
-    if (configFrameID >= numFrames) {
+    if (mConfigFrameID >= numFrames) {
         throw DeadlyImportError("UNREAL: The requested frame does not exist");
         throw DeadlyImportError("UNREAL: The requested frame does not exist");
     }
     }
 
 
     uint32_t st = a_reader.GetI2();
     uint32_t st = a_reader.GetI2();
-    if (st != numVert*4u)
+    if (st != numVert * 4u)
         throw DeadlyImportError("UNREAL: Unexpected aniv file length");
         throw DeadlyImportError("UNREAL: Unexpected aniv file length");
 
 
     // skip to our frame
     // skip to our frame
-    a_reader.IncPtr(configFrameID *numVert*4);
+    a_reader.IncPtr(mConfigFrameID * numVert * 4);
 
 
     // collect vertices
     // collect vertices
     std::vector<aiVector3D> vertices(numVert);
     std::vector<aiVector3D> vertices(numVert);
-    for (auto &vertex : vertices)    {
+    for (auto &vertex : vertices) {
         int32_t val = a_reader.GetI4();
         int32_t val = a_reader.GetI4();
-        Unreal::DecompressVertex(vertex ,val);
+        Unreal::DecompressVertex(vertex, val);
     }
     }
 
 
     // list of textures.
     // list of textures.
-    std::vector< std::pair<unsigned int, std::string> > textures;
+    std::vector<std::pair<unsigned int, std::string>> textures;
 
 
     // allocate the output scene
     // allocate the output scene
-    aiNode* nd = pScene->mRootNode = new aiNode();
+    aiNode *nd = pScene->mRootNode = new aiNode();
     nd->mName.Set("<UnrealRoot>");
     nd->mName.Set("<UnrealRoot>");
 
 
     // we can live without the uc file if necessary
     // we can live without the uc file if necessary
-    std::unique_ptr<IOStream> pb (pIOHandler->Open(uc_path));
-    if (pb.get())   {
+    std::unique_ptr<IOStream> pb(pIOHandler->Open(uc_path));
+    if (pb.get()) {
 
 
         std::vector<char> _data;
         std::vector<char> _data;
-        TextFileToBuffer(pb.get(),_data);
-        const char* data = &_data[0];
+        TextFileToBuffer(pb.get(), _data);
+        const char *data = &_data[0];
 
 
-        std::vector< std::pair< std::string,std::string > > tempTextures;
+        std::vector<std::pair<std::string, std::string>> tempTextures;
 
 
         // do a quick search in the UC file for some known, usually texture-related, tags
         // do a quick search in the UC file for some known, usually texture-related, tags
-        for (;*data;++data) {
-            if (TokenMatchI(data,"#exec",5))    {
+        for (; *data; ++data) {
+            if (TokenMatchI(data, "#exec", 5)) {
                 SkipSpacesAndLineEnd(&data);
                 SkipSpacesAndLineEnd(&data);
 
 
                 // #exec TEXTURE IMPORT [...] NAME=jjjjj [...] FILE=jjjj.pcx [...]
                 // #exec TEXTURE IMPORT [...] NAME=jjjjj [...] FILE=jjjj.pcx [...]
-                if (TokenMatchI(data,"TEXTURE",7))  {
+                if (TokenMatchI(data, "TEXTURE", 7)) {
                     SkipSpacesAndLineEnd(&data);
                     SkipSpacesAndLineEnd(&data);
 
 
-                    if (TokenMatchI(data,"IMPORT",6))   {
-                        tempTextures.push_back(std::pair< std::string,std::string >());
-                        std::pair< std::string,std::string >& me = tempTextures.back();
-                        for (;!IsLineEnd(*data);++data) {
-                            if (!::ASSIMP_strincmp(data,"NAME=",5)) {
-                                const char *d = data+=5;
-                                for (;!IsSpaceOrNewLine(*data);++data);
-                                me.first = std::string(d,(size_t)(data-d));
-                            }
-                            else if (!::ASSIMP_strincmp(data,"FILE=",5))    {
-                                const char *d = data+=5;
-                                for (;!IsSpaceOrNewLine(*data);++data);
-                                me.second = std::string(d,(size_t)(data-d));
+                    if (TokenMatchI(data, "IMPORT", 6)) {
+                        tempTextures.push_back(std::pair<std::string, std::string>());
+                        std::pair<std::string, std::string> &me = tempTextures.back();
+                        for (; !IsLineEnd(*data); ++data) {
+                            if (!::ASSIMP_strincmp(data, "NAME=", 5)) {
+                                const char *d = data += 5;
+                                for (; !IsSpaceOrNewLine(*data); ++data)
+                                    ;
+                                me.first = std::string(d, (size_t)(data - d));
+                            } else if (!::ASSIMP_strincmp(data, "FILE=", 5)) {
+                                const char *d = data += 5;
+                                for (; !IsSpaceOrNewLine(*data); ++data)
+                                    ;
+                                me.second = std::string(d, (size_t)(data - d));
                             }
                             }
                         }
                         }
                         if (!me.first.length() || !me.second.length())
                         if (!me.first.length() || !me.second.length())
@@ -276,65 +352,61 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
                 }
                 }
                 // #exec MESHMAP SETTEXTURE MESHMAP=box NUM=1 TEXTURE=Jtex1
                 // #exec MESHMAP SETTEXTURE MESHMAP=box NUM=1 TEXTURE=Jtex1
                 // #exec MESHMAP SCALE MESHMAP=box X=0.1 Y=0.1 Z=0.2
                 // #exec MESHMAP SCALE MESHMAP=box X=0.1 Y=0.1 Z=0.2
-                else if (TokenMatchI(data,"MESHMAP",7)) {
+                else if (TokenMatchI(data, "MESHMAP", 7)) {
                     SkipSpacesAndLineEnd(&data);
                     SkipSpacesAndLineEnd(&data);
 
 
-                    if (TokenMatchI(data,"SETTEXTURE",10)) {
+                    if (TokenMatchI(data, "SETTEXTURE", 10)) {
 
 
                         textures.push_back(std::pair<unsigned int, std::string>());
                         textures.push_back(std::pair<unsigned int, std::string>());
-                        std::pair<unsigned int, std::string>& me = textures.back();
+                        std::pair<unsigned int, std::string> &me = textures.back();
 
 
-                        for (;!IsLineEnd(*data);++data) {
-                            if (!::ASSIMP_strincmp(data,"NUM=",4))  {
+                        for (; !IsLineEnd(*data); ++data) {
+                            if (!::ASSIMP_strincmp(data, "NUM=", 4)) {
                                 data += 4;
                                 data += 4;
-                                me.first = strtoul10(data,&data);
-                            }
-                            else if (!::ASSIMP_strincmp(data,"TEXTURE=",8)) {
+                                me.first = strtoul10(data, &data);
+                            } else if (!::ASSIMP_strincmp(data, "TEXTURE=", 8)) {
                                 data += 8;
                                 data += 8;
                                 const char *d = data;
                                 const char *d = data;
-                                for (;!IsSpaceOrNewLine(*data);++data);
-                                me.second = std::string(d,(size_t)(data-d));
+                                for (; !IsSpaceOrNewLine(*data); ++data)
+                                    ;
+                                me.second = std::string(d, (size_t)(data - d));
 
 
                                 // try to find matching path names, doesn't care if we don't find them
                                 // try to find matching path names, doesn't care if we don't find them
-                                for (std::vector< std::pair< std::string,std::string > >::const_iterator it = tempTextures.begin();
-                                     it != tempTextures.end(); ++it)    {
-                                    if ((*it).first == me.second)   {
+                                for (std::vector<std::pair<std::string, std::string>>::const_iterator it = tempTextures.begin();
+                                        it != tempTextures.end(); ++it) {
+                                    if ((*it).first == me.second) {
                                         me.second = (*it).second;
                                         me.second = (*it).second;
                                         break;
                                         break;
                                     }
                                     }
                                 }
                                 }
                             }
                             }
                         }
                         }
-                    }
-                    else if (TokenMatchI(data,"SCALE",5)) {
-
-                        for (;!IsLineEnd(*data);++data) {
-                            if (data[0] == 'X' && data[1] == '=')   {
-                                data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.a1);
-                            }
-                            else if (data[0] == 'Y' && data[1] == '=')  {
-                                data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.b2);
-                            }
-                            else if (data[0] == 'Z' && data[1] == '=')  {
-                                data = fast_atoreal_move<float>(data+2,(float&)nd->mTransformation.c3);
+                    } else if (TokenMatchI(data, "SCALE", 5)) {
+
+                        for (; !IsLineEnd(*data); ++data) {
+                            if (data[0] == 'X' && data[1] == '=') {
+                                data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.a1);
+                            } else if (data[0] == 'Y' && data[1] == '=') {
+                                data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.b2);
+                            } else if (data[0] == 'Z' && data[1] == '=') {
+                                data = fast_atoreal_move<float>(data + 2, (float &)nd->mTransformation.c3);
                             }
                             }
                         }
                         }
                     }
                     }
                 }
                 }
             }
             }
         }
         }
-    }
-    else    {
+    } else {
         ASSIMP_LOG_ERROR("Unable to open .uc file");
         ASSIMP_LOG_ERROR("Unable to open .uc file");
     }
     }
 
 
     std::vector<Unreal::TempMat> materials;
     std::vector<Unreal::TempMat> materials;
-    materials.reserve(textures.size()*2+5);
+    materials.reserve(textures.size() * 2 + 5);
 
 
     // find out how many output meshes and materials we'll have and build material indices
     // find out how many output meshes and materials we'll have and build material indices
-	for (Unreal::Triangle &tri : triangles) {
+    for (Unreal::Triangle &tri : triangles) {
         Unreal::TempMat mat(tri);
         Unreal::TempMat mat(tri);
-        std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
+        std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(), materials.end(), mat);
         if (nt == materials.end()) {
         if (nt == materials.end()) {
             // add material
             // add material
             tri.matIndex = static_cast<unsigned int>(materials.size());
             tri.matIndex = static_cast<unsigned int>(materials.size());
@@ -342,9 +414,8 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
             materials.push_back(mat);
             materials.push_back(mat);
 
 
             ++pScene->mNumMeshes;
             ++pScene->mNumMeshes;
-        }
-        else {
-            tri.matIndex = static_cast<unsigned int>(nt-materials.begin());
+        } else {
+            tri.matIndex = static_cast<unsigned int>(nt - materials.begin());
             ++nt->numFaces;
             ++nt->numFaces;
         }
         }
     }
     }
@@ -354,65 +425,65 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
     }
     }
 
 
     // allocate meshes and bind them to the node graph
     // allocate meshes and bind them to the node graph
-    pScene->mMeshes = new aiMesh*[pScene->mNumMeshes];
-    pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials = pScene->mNumMeshes];
+    pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
+    pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials = pScene->mNumMeshes];
 
 
-    nd->mNumMeshes  = pScene->mNumMeshes;
+    nd->mNumMeshes = pScene->mNumMeshes;
     nd->mMeshes = new unsigned int[nd->mNumMeshes];
     nd->mMeshes = new unsigned int[nd->mNumMeshes];
-    for (unsigned int i = 0; i < pScene->mNumMeshes;++i) {
-        aiMesh* m = pScene->mMeshes[i] =  new aiMesh();
+    for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+        aiMesh *m = pScene->mMeshes[i] = new aiMesh();
         m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
         m->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
 
 
         const unsigned int num = materials[i].numFaces;
         const unsigned int num = materials[i].numFaces;
-        m->mFaces            = new aiFace     [num];
-        m->mVertices         = new aiVector3D [num*3];
-        m->mTextureCoords[0] = new aiVector3D [num*3];
+        m->mFaces = new aiFace[num];
+        m->mVertices = new aiVector3D[num * 3];
+        m->mTextureCoords[0] = new aiVector3D[num * 3];
 
 
         nd->mMeshes[i] = i;
         nd->mMeshes[i] = i;
 
 
         // create materials, too
         // create materials, too
-        aiMaterial* mat = new aiMaterial();
+        aiMaterial *mat = new aiMaterial();
         pScene->mMaterials[i] = mat;
         pScene->mMaterials[i] = mat;
 
 
         // all white by default - texture rulez
         // all white by default - texture rulez
-        aiColor3D color(1.f,1.f,1.f);
+        aiColor3D color(1.f, 1.f, 1.f);
 
 
         aiString s;
         aiString s;
-        ::ai_snprintf( s.data, MAXLEN, "mat%u_tx%u_",i,materials[i].tex );
+        ::ai_snprintf(s.data, MAXLEN, "mat%u_tx%u_", i, materials[i].tex);
 
 
         // set the two-sided flag
         // set the two-sided flag
         if (materials[i].type == Unreal::MF_NORMAL_TS) {
         if (materials[i].type == Unreal::MF_NORMAL_TS) {
             const int twosided = 1;
             const int twosided = 1;
-            mat->AddProperty(&twosided,1,AI_MATKEY_TWOSIDED);
-            ::strcat(s.data,"ts_");
-        }
-        else ::strcat(s.data,"os_");
+            mat->AddProperty(&twosided, 1, AI_MATKEY_TWOSIDED);
+            ::strcat(s.data, "ts_");
+        } else
+            ::strcat(s.data, "os_");
 
 
         // make TRANS faces 90% opaque that RemRedundantMaterials won't catch us
         // make TRANS faces 90% opaque that RemRedundantMaterials won't catch us
-        if (materials[i].type == Unreal::MF_NORMAL_TRANS_TS)    {
+        if (materials[i].type == Unreal::MF_NORMAL_TRANS_TS) {
             const float opac = 0.9f;
             const float opac = 0.9f;
-            mat->AddProperty(&opac,1,AI_MATKEY_OPACITY);
-            ::strcat(s.data,"tran_");
-        }
-        else ::strcat(s.data,"opaq_");
+            mat->AddProperty(&opac, 1, AI_MATKEY_OPACITY);
+            ::strcat(s.data, "tran_");
+        } else
+            ::strcat(s.data, "opaq_");
 
 
         // a special name for the weapon attachment point
         // a special name for the weapon attachment point
         if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) {
         if (materials[i].type == Unreal::MF_WEAPON_PLACEHOLDER) {
-            s.length = ::ai_snprintf( s.data, MAXLEN, "$WeaponTag$" );
-            color = aiColor3D(0.f,0.f,0.f);
+            s.length = ::ai_snprintf(s.data, MAXLEN, "$WeaponTag$");
+            color = aiColor3D(0.f, 0.f, 0.f);
         }
         }
 
 
         // set color and name
         // set color and name
-        mat->AddProperty(&color,1,AI_MATKEY_COLOR_DIFFUSE);
-        s.length = (ai_uint32)::strlen(s.data);
-        mat->AddProperty(&s,AI_MATKEY_NAME);
+        mat->AddProperty(&color, 1, AI_MATKEY_COLOR_DIFFUSE);
+        s.length = static_cast<ai_uint32>(::strlen(s.data));
+        mat->AddProperty(&s, AI_MATKEY_NAME);
 
 
         // set texture, if any
         // set texture, if any
         const unsigned int tex = materials[i].tex;
         const unsigned int tex = materials[i].tex;
-        for (std::vector< std::pair< unsigned int, std::string > >::const_iterator it = textures.begin();it != textures.end();++it) {
+        for (std::vector<std::pair<unsigned int, std::string>>::const_iterator it = textures.begin(); it != textures.end(); ++it) {
             if ((*it).first == tex) {
             if ((*it).first == tex) {
                 s.Set((*it).second);
                 s.Set((*it).second);
-                mat->AddProperty(&s,AI_MATKEY_TEXTURE_DIFFUSE(0));
+                mat->AddProperty(&s, AI_MATKEY_TEXTURE_DIFFUSE(0));
                 break;
                 break;
             }
             }
         }
         }
@@ -421,17 +492,17 @@ void UnrealImporter::InternReadFile( const std::string& pFile,
     // fill them.
     // fill them.
     for (const Unreal::Triangle &tri : triangles) {
     for (const Unreal::Triangle &tri : triangles) {
         Unreal::TempMat mat(tri);
         Unreal::TempMat mat(tri);
-        std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(),materials.end(),mat);
+        std::vector<Unreal::TempMat>::iterator nt = std::find(materials.begin(), materials.end(), mat);
 
 
-        aiMesh* mesh = pScene->mMeshes[nt-materials.begin()];
-        aiFace& f    = mesh->mFaces[mesh->mNumFaces++];
-        f.mIndices   = new unsigned int[f.mNumIndices = 3];
+        aiMesh *mesh = pScene->mMeshes[nt - materials.begin()];
+        aiFace &f = mesh->mFaces[mesh->mNumFaces++];
+        f.mIndices = new unsigned int[f.mNumIndices = 3];
 
 
-        for (unsigned int i = 0; i < 3;++i,mesh->mNumVertices++) {
+        for (unsigned int i = 0; i < 3; ++i, mesh->mNumVertices++) {
             f.mIndices[i] = mesh->mNumVertices;
             f.mIndices[i] = mesh->mNumVertices;
 
 
-            mesh->mVertices[mesh->mNumVertices] = vertices[ tri.mVertex[i] ];
-            mesh->mTextureCoords[0][mesh->mNumVertices] = aiVector3D( tri.mTex[i][0] / 255.f, 1.f - tri.mTex[i][1] / 255.f, 0.f);
+            mesh->mVertices[mesh->mNumVertices] = vertices[tri.mVertex[i]];
+            mesh->mTextureCoords[0][mesh->mNumVertices] = aiVector3D(tri.mTex[i][0] / 255.f, 1.f - tri.mTex[i][1] / 255.f, 0.f);
         }
         }
     }
     }
 
 

+ 12 - 117
code/Unreal/UnrealLoader.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,
@@ -47,161 +46,57 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_3D_LOADER_H
 #define INCLUDED_AI_3D_LOADER_H
 
 
 #include <assimp/BaseImporter.h>
 #include <assimp/BaseImporter.h>
-#include <stdint.h>
-
-namespace Assimp    {
-namespace Unreal {
-
-    /*
-    0 = Normal one-sided
-    1 = Normal two-sided
-    2 = Translucent two-sided
-    3 = Masked two-sided
-    4 = Modulation blended two-sided
-    8 = Placeholder triangle for weapon positioning (invisible)
-    */
-enum MeshFlags {
-    MF_NORMAL_OS            = 0,
-    MF_NORMAL_TS            = 1,
-    MF_NORMAL_TRANS_TS      = 2,
-    MF_NORMAL_MASKED_TS     = 3,
-    MF_NORMAL_MOD_TS        = 4,
-    MF_WEAPON_PLACEHOLDER   = 8
-};
-
-    // a single triangle
-struct Triangle {
-   uint16_t mVertex[3];       // Vertex indices
-   char mType;                // James' Mesh Type
-   char mColor;               // Color for flat and Gourand Shaded
-   unsigned char mTex[3][2];  // Texture UV coordinates
-   unsigned char mTextureNum; // Source texture offset
-   char mFlags;               // Unreal Mesh Flags (unused)
-
-   unsigned int matIndex;
-};
-
-// temporary representation for a material
-struct TempMat  {
-    TempMat()
-        :   type()
-        ,   tex()
-        ,   numFaces    (0)
-    {}
-
-    explicit TempMat(const Triangle& in)
-        :   type        ((Unreal::MeshFlags)in.mType)
-        ,   tex         (in.mTextureNum)
-        ,   numFaces    (0)
-    {}
-
-    // type of mesh
-    Unreal::MeshFlags type;
-
-    // index of texture
-    unsigned int tex;
-
-    // number of faces using us
-    unsigned int numFaces;
-
-    // for std::find
-    bool operator == (const TempMat& o )    {
-        return (tex == o.tex && type == o.type);
-    }
-};
-
-struct Vertex
-{
-    int32_t X : 11;
-    int32_t Y : 11;
-    int32_t Z : 10;
-};
-
-    // UNREAL vertex compression
-inline void CompressVertex(const aiVector3D& v, uint32_t& out)
-{
-    union {
-        Vertex n;
-        int32_t t;
-    };
-    n.X = (int32_t)v.x;
-    n.Y = (int32_t)v.y;
-    n.Z = (int32_t)v.z;
-    ::memcpy( &out, &t, sizeof(int32_t));
-    //out = t;
-}
-
-    // UNREAL vertex decompression
-inline void DecompressVertex(aiVector3D& v, int32_t in)
-{
-    union {
-        Vertex n;
-        int32_t i;
-    };
-    i = in;
-
-    v.x = (float)n.X;
-    v.y = (float)n.Y;
-    v.z = (float)n.Z;
-}
-
-} // end namespace Unreal
+
+namespace Assimp {
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 /** @brief Importer class to load UNREAL files (*.3d)
 /** @brief Importer class to load UNREAL files (*.3d)
 */
 */
-class UnrealImporter : public BaseImporter
-{
+class UnrealImporter : public BaseImporter {
 public:
 public:
     UnrealImporter();
     UnrealImporter();
     ~UnrealImporter();
     ~UnrealImporter();
 
 
-
-public:
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** @brief Returns whether we can handle the format of the given file
     /** @brief Returns whether we can handle the format of the given file
      *
      *
      *  See BaseImporter::CanRead() for details.
      *  See BaseImporter::CanRead() for details.
      **/
      **/
-    bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
-        bool checkSig) const;
+    bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
+            bool checkSig) const;
 
 
 protected:
 protected:
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** @brief Called by Importer::GetExtensionList()
     /** @brief Called by Importer::GetExtensionList()
      *
      *
      * See #BaseImporter::GetInfo for the details
      * See #BaseImporter::GetInfo for the details
      */
      */
-    const aiImporterDesc* GetInfo () const;
-
+    const aiImporterDesc *GetInfo() const;
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** @brief Setup properties for the importer
     /** @brief Setup properties for the importer
      *
      *
      * See BaseImporter::SetupProperties() for details
      * See BaseImporter::SetupProperties() for details
      */
      */
-    void SetupProperties(const Importer* pImp);
-
+    void SetupProperties(const Importer *pImp);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** @brief Imports the given file into the given scene structure.
     /** @brief Imports the given file into the given scene structure.
      *
      *
      * See BaseImporter::InternReadFile() for details
      * See BaseImporter::InternReadFile() for details
      */
      */
-    void InternReadFile( const std::string& pFile, aiScene* pScene,
-        IOSystem* pIOHandler);
+    void InternReadFile(const std::string &pFile, aiScene *pScene,
+            IOSystem *pIOHandler);
 
 
 private:
 private:
-
     //! frame to be loaded
     //! frame to be loaded
-    uint32_t configFrameID;
+    uint32_t mConfigFrameID;
 
 
     //! process surface flags
     //! process surface flags
-    bool configHandleFlags;
+    bool mConfigHandleFlags;
 
 
 }; // !class UnrealImporter
 }; // !class UnrealImporter
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp
+
 #endif // AI_UNREALIMPORTER_H_INC
 #endif // AI_UNREALIMPORTER_H_INC

+ 1 - 1
code/XGL/XGLLoader.cpp

@@ -176,7 +176,7 @@ void XGLImporter::InternReadFile( const std::string& pFile,
         raw_reader->IncPtr(2);
         raw_reader->IncPtr(2);
 
 
         zstream.next_in   = reinterpret_cast<Bytef*>( raw_reader->GetPtr() );
         zstream.next_in   = reinterpret_cast<Bytef*>( raw_reader->GetPtr() );
-        zstream.avail_in  = raw_reader->GetRemainingSize();
+        zstream.avail_in  = (uInt) raw_reader->GetRemainingSize();
 
 
         size_t total = 0l;
         size_t total = 0l;
 
 

+ 6 - 1
code/glTF/glTFAsset.h

@@ -382,7 +382,12 @@ namespace glTF
         {
         {
             friend struct Accessor;
             friend struct Accessor;
 
 
-            Accessor& accessor;
+        // This field is reported as not used, making it protectd is the easiest way to work around it without going to the bottom of what the problem is:
+        // ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field]
+        protected:
+            Accessor &accessor;
+
+        private:
             uint8_t* data;
             uint8_t* data;
             size_t elemSize, stride;
             size_t elemSize, stride;
 
 

+ 17 - 3
code/glTF2/glTF2Asset.h

@@ -58,6 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <algorithm>
 #include <algorithm>
 #include <list>
 #include <list>
 #include <map>
 #include <map>
+#include <set>
 #include <stdexcept>
 #include <stdexcept>
 #include <string>
 #include <string>
 #include <vector>
 #include <vector>
@@ -81,14 +82,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
 #define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
 #else
 #else
 #define gltf_unordered_map map
 #define gltf_unordered_map map
+#define gltf_unordered_set set
 #endif
 #endif
 
 
 #ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
 #ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
 #include <unordered_map>
 #include <unordered_map>
+#include <unordered_set>
 #if _MSC_VER > 1600
 #if _MSC_VER > 1600
 #define gltf_unordered_map unordered_map
 #define gltf_unordered_map unordered_map
+#define gltf_unordered_set unordered_set
 #else
 #else
 #define gltf_unordered_map tr1::unordered_map
 #define gltf_unordered_map tr1::unordered_map
+#define gltf_unordered_set tr1::unordered_set
 #endif
 #endif
 #endif
 #endif
 
 
@@ -375,8 +380,8 @@ struct Accessor : public Object {
 
 
     inline uint8_t *GetPointer();
     inline uint8_t *GetPointer();
 
 
-    template <class T>
-    bool ExtractData(T *&outData);
+    template<class T>
+    void ExtractData(T *&outData);
 
 
     void WriteData(size_t count, const void *src_buffer, size_t src_stride);
     void WriteData(size_t count, const void *src_buffer, size_t src_stride);
 
 
@@ -384,12 +389,18 @@ struct Accessor : public Object {
     class Indexer {
     class Indexer {
         friend struct Accessor;
         friend struct Accessor;
 
 
+    // This field is reported as not used, making it protectd is the easiest way to work around it without going to the bottom of what the problem is:
+    // ../code/glTF2/glTF2Asset.h:392:19: error: private field 'accessor' is not used [-Werror,-Wunused-private-field]
+    protected:
         Accessor &accessor;
         Accessor &accessor;
+
+    private:
         uint8_t *data;
         uint8_t *data;
         size_t elemSize, stride;
         size_t elemSize, stride;
 
 
         Indexer(Accessor &acc);
         Indexer(Accessor &acc);
-
+    
+        
     public:
     public:
         //! Accesses the i-th value as defined by the accessor
         //! Accesses the i-th value as defined by the accessor
         template <class T>
         template <class T>
@@ -720,6 +731,7 @@ struct Mesh : public Object {
     std::vector<Primitive> primitives;
     std::vector<Primitive> primitives;
 
 
     std::vector<float> weights;
     std::vector<float> weights;
+    std::vector<std::string> targetNames;
 
 
     Mesh() {}
     Mesh() {}
 
 
@@ -874,6 +886,8 @@ class LazyDict : public LazyDictBase {
     Value *mDict; //! JSON dictionary object
     Value *mDict; //! JSON dictionary object
     Asset &mAsset; //! The asset instance
     Asset &mAsset; //! The asset instance
 
 
+    std::gltf_unordered_set<unsigned int> mRecursiveReferenceCheck;  //! Used by Retrieve to prevent recursive lookups
+
     void AttachToDocument(Document &doc);
     void AttachToDocument(Document &doc);
     void DetachFromDocument();
     void DetachFromDocument();
 
 

+ 38 - 12
code/glTF2/glTF2Asset.inl

@@ -280,6 +280,11 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
         throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object");
         throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" is not a JSON object");
     }
     }
 
 
+    if (mRecursiveReferenceCheck.find(i) != mRecursiveReferenceCheck.end()) {
+        throw DeadlyImportError("GLTF: Object at index \"" + to_string(i) + "\" has recursive reference to itself");
+    }
+    mRecursiveReferenceCheck.insert(i);
+
     // Unique ptr prevents memory leak in case of Read throws an exception
     // Unique ptr prevents memory leak in case of Read throws an exception
     auto inst = std::unique_ptr<T>(new T());
     auto inst = std::unique_ptr<T>(new T());
     inst->id = std::string(mDictId) + "_" + to_string(i);
     inst->id = std::string(mDictId) + "_" + to_string(i);
@@ -287,7 +292,9 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
     ReadMember(obj, "name", inst->name);
     ReadMember(obj, "name", inst->name);
     inst->Read(obj, mAsset);
     inst->Read(obj, mAsset);
 
 
-    return Add(inst.release());
+    Ref<T> result = Add(inst.release());
+    mRecursiveReferenceCheck.erase(i);
+    return result;
 }
 }
 
 
 template <class T>
 template <class T>
@@ -508,18 +515,23 @@ inline size_t Buffer::AppendData(uint8_t *data, size_t length) {
 }
 }
 
 
 inline void Buffer::Grow(size_t amount) {
 inline void Buffer::Grow(size_t amount) {
-    if (amount <= 0) return;
+    if (amount <= 0) {
+        return;
+    }
+    
+    // Capacity is big enough
     if (capacity >= byteLength + amount) {
     if (capacity >= byteLength + amount) {
         byteLength += amount;
         byteLength += amount;
         return;
         return;
     }
     }
 
 
-    // Shift operation is standard way to divide integer by 2, it doesn't cast it to float back and forth, also works for odd numbers,
-    // originally it would look like: static_cast<size_t>(capacity * 1.5f)
-    capacity = std::max(capacity + (capacity >> 1), byteLength + amount);
+    // Just allocate data which we need
+    capacity = byteLength + amount;
 
 
     uint8_t *b = new uint8_t[capacity];
     uint8_t *b = new uint8_t[capacity];
-    if (mData) memcpy(b, mData.get(), byteLength);
+    if (nullptr != mData) {
+        memcpy(b, mData.get(), byteLength);
+    }
     mData.reset(b, std::default_delete<uint8_t[]>());
     mData.reset(b, std::default_delete<uint8_t[]>());
     byteLength += amount;
     byteLength += amount;
 }
 }
@@ -608,10 +620,13 @@ inline void CopyData(size_t count,
 }
 }
 } // namespace
 } // namespace
 
 
-template <class T>
-bool Accessor::ExtractData(T *&outData) {
-    uint8_t *data = GetPointer();
-    if (!data) return false;
+template<class T>
+void Accessor::ExtractData(T *&outData)
+{
+    uint8_t* data = GetPointer();
+    if (!data) {
+        throw DeadlyImportError("GLTF: data is NULL");
+    }
 
 
     const size_t elemSize = GetElementSize();
     const size_t elemSize = GetElementSize();
     const size_t totalSize = elemSize * count;
     const size_t totalSize = elemSize * count;
@@ -631,8 +646,6 @@ bool Accessor::ExtractData(T *&outData) {
             memcpy(outData + i, data + i * stride, elemSize);
             memcpy(outData + i, data + i * stride, elemSize);
         }
         }
     }
     }
-
-    return true;
 }
 }
 
 
 inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t src_stride) {
 inline void Accessor::WriteData(size_t _count, const void *src_buffer, size_t src_stride) {
@@ -1021,6 +1034,19 @@ inline void Mesh::Read(Value &pJSON_Object, Asset &pAsset_Root) {
             }
             }
         }
         }
     }
     }
+
+    Value *extras = FindObject(pJSON_Object, "extras");
+    if (nullptr != extras ) {
+        if (Value* curTargetNames = FindArray(*extras, "targetNames")) {
+            this->targetNames.resize(curTargetNames->Size());
+            for (unsigned int i = 0; i < curTargetNames->Size(); ++i) {
+                Value& targetNameValue = (*curTargetNames)[i];
+                if (targetNameValue.IsString()) {
+                    this->targetNames[i] = targetNameValue.GetString();
+                }
+            }
+        }
+    }
 }
 }
 
 
 inline void Camera::Read(Value &obj, Asset & /*r*/) {
 inline void Camera::Read(Value &obj, Asset & /*r*/) {

+ 4 - 0
code/glTF2/glTF2Importer.cpp

@@ -472,6 +472,9 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
 					if (mesh.weights.size() > i) {
 					if (mesh.weights.size() > i) {
 						aiAnimMesh.mWeight = mesh.weights[i];
 						aiAnimMesh.mWeight = mesh.weights[i];
 					}
 					}
+					if (mesh.targetNames.size() > i) {
+						aiAnimMesh.mName = mesh.targetNames[i];
+					}
 				}
 				}
 			}
 			}
 
 
@@ -680,6 +683,7 @@ void glTF2Importer::ImportCameras(glTF2::Asset &r) {
 			aicam->mClipPlaneFar = cam.cameraProperties.ortographic.zfar;
 			aicam->mClipPlaneFar = cam.cameraProperties.ortographic.zfar;
 			aicam->mClipPlaneNear = cam.cameraProperties.ortographic.znear;
 			aicam->mClipPlaneNear = cam.cameraProperties.ortographic.znear;
 			aicam->mHorizontalFOV = 0.0;
 			aicam->mHorizontalFOV = 0.0;
+			aicam->mOrthographicWidth = cam.cameraProperties.ortographic.xmag;
 			aicam->mAspect = 1.0f;
 			aicam->mAspect = 1.0f;
 			if (0.f != cam.cameraProperties.ortographic.ymag) {
 			if (0.f != cam.cameraProperties.ortographic.ymag) {
 				aicam->mAspect = cam.cameraProperties.ortographic.xmag / cam.cameraProperties.ortographic.ymag;
 				aicam->mAspect = cam.cameraProperties.ortographic.xmag / cam.cameraProperties.ortographic.ymag;

+ 5 - 1
contrib/irrXML/CMakeLists.txt

@@ -15,7 +15,11 @@ if ( MSVC )
 endif ( MSVC )
 endif ( MSVC )
 
 
 IF(CMAKE_SYSTEM_NAME MATCHES "(Darwin|FreeBSD)")
 IF(CMAKE_SYSTEM_NAME MATCHES "(Darwin|FreeBSD)")
-  add_library(IrrXML ${IrrXML_SRCS})
+  IF(APPLE)
+    add_library(IrrXML STATIC ${IrrXML_SRCS})
+  ELSE()
+    add_library(IrrXML ${IrrXML_SRCS})
+  ENDIF()
 ELSE()
 ELSE()
   add_library(IrrXML STATIC ${IrrXML_SRCS})
   add_library(IrrXML STATIC ${IrrXML_SRCS})
 ENDIF()
 ENDIF()

+ 20 - 33
contrib/irrXML/CXMLReaderImpl.h

@@ -8,16 +8,7 @@
 #include "irrXML.h"
 #include "irrXML.h"
 #include "irrString.h"
 #include "irrString.h"
 #include "irrArray.h"
 #include "irrArray.h"
-
-#include <cassert>
-#include <stdlib.h>    
-#include <cctype>
-#include <cstdint>
-//using namespace Assimp;
-
-// For locale independent number conversion
-#include <sstream>
-#include <locale>
+#include "fast_atof.h"
 
 
 #ifdef _DEBUG
 #ifdef _DEBUG
 #define IRR_DEBUGPRINT(x) printf((x));
 #define IRR_DEBUGPRINT(x) printf((x));
@@ -37,14 +28,23 @@ template<class char_type, class superclass>
 class CXMLReaderImpl : public IIrrXMLReader<char_type, superclass>
 class CXMLReaderImpl : public IIrrXMLReader<char_type, superclass>
 {
 {
 public:
 public:
-
 	//! Constructor
 	//! Constructor
-	CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true)
-		: TextData(0), P(0), TextBegin(0), TextSize(0), CurrentNodeType(EXN_NONE),
-		SourceFormat(ETF_ASCII), TargetFormat(ETF_ASCII)
-	{
-		if (!callback)
+	CXMLReaderImpl(IFileReadCallBack* callback, bool deleteCallBack = true) 
+	: TextData(0)
+	, P(0)
+	, TextBegin(0)
+	, TextSize(0)
+	, CurrentNodeType(EXN_NONE)
+	, SourceFormat(ETF_ASCII)
+	, TargetFormat(ETF_ASCII)
+	, NodeName ()
+	, EmptyString()
+	, IsEmptyElement(false)
+	, SpecialCharacters()
+	, Attributes() {
+		if (!callback) {
 			return;
 			return;
+		}
 
 
 		storeTargetFormat();
 		storeTargetFormat();
 
 
@@ -168,8 +168,7 @@ public:
 			return 0;
 			return 0;
 
 
 		core::stringc c = attr->Value.c_str();
 		core::stringc c = attr->Value.c_str();
-        return static_cast<float>(atof(c.c_str()));
-        //return fast_atof(c.c_str());
+		return core::fast_atof(c.c_str());
 	}
 	}
 
 
 
 
@@ -181,11 +180,7 @@ public:
 			return 0;
 			return 0;
 
 
 		core::stringc c = attrvalue;
 		core::stringc c = attrvalue;
-		std::istringstream sstr(c.c_str());
-		sstr.imbue(std::locale("C")); // Locale free number convert
-		float fNum;
-		sstr >> fNum;
-		return fNum;
+		return core::fast_atof(c.c_str());
 	}
 	}
 
 
 
 
@@ -228,7 +223,7 @@ private:
 	{
 	{
 		char_type* start = P;
 		char_type* start = P;
 
 
-		// move forward until '<' found
+		// more forward until '<' found
 		while(*P != L'<' && *P)
 		while(*P != L'<' && *P)
 			++P;
 			++P;
 
 
@@ -438,10 +433,6 @@ private:
 		while(*P != L'>')
 		while(*P != L'>')
 			++P;
 			++P;
 
 
-    // remove trailing whitespace, if any
-    while( std::isspace( P[-1]))
-      --P;
-
 		NodeName = core::string<char_type>(pBeginClose, (int)(P - pBeginClose));
 		NodeName = core::string<char_type>(pBeginClose, (int)(P - pBeginClose));
 		++P;
 		++P;
 	}
 	}
@@ -676,12 +667,8 @@ private:
 
 
 			TextData = new char_type[sizeWithoutHeader];
 			TextData = new char_type[sizeWithoutHeader];
 
 
-			// MSVC debugger complains here about loss of data ...
-			size_t numShift = sizeof( char_type) * 8;
-			assert(numShift < 64);
-			const src_char_type cc = (src_char_type)(((uint64_t(1u) << numShift) - 1));
 			for (int i=0; i<sizeWithoutHeader; ++i)
 			for (int i=0; i<sizeWithoutHeader; ++i)
-				TextData[i] = char_type( source[i] & cc); 
+				TextData[i] = (char_type)source[i];
 
 
 			TextBegin = TextData;
 			TextBegin = TextData;
 			TextSize = sizeWithoutHeader;
 			TextSize = sizeWithoutHeader;

+ 139 - 0
contrib/irrXML/fast_atof.h

@@ -0,0 +1,139 @@
+// Copyright (C) 2002-2005 Nikolaus Gebhardt
+// This file is part of the "Irrlicht Engine" and the "irrXML" project.
+// For conditions of distribution and use, see copyright notice in irrlicht.h and irrXML.h
+
+#ifndef __FAST_A_TO_F_H_INCLUDED__
+#define __FAST_A_TO_F_H_INCLUDED__
+
+#include <stdlib.h>
+#include <math.h>
+
+namespace irr
+{
+namespace core
+{
+
+const float fast_atof_table[] =	{
+										0.f,
+										0.1f,
+										0.01f,
+										0.001f,
+										0.0001f,
+										0.00001f,
+										0.000001f,
+										0.0000001f,
+										0.00000001f,
+										0.000000001f,
+										0.0000000001f,
+										0.00000000001f,
+										0.000000000001f,
+										0.0000000000001f,
+										0.00000000000001f,
+										0.000000000000001f
+									};
+
+//! Provides a fast function for converting a string into a float,
+//! about 6 times faster than atof in win32.
+// If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
+inline char* fast_atof_move(char* c, float& out)
+{
+	bool inv = false;
+	char *t;
+	float f;
+
+	if (*c=='-')
+	{
+		c++;
+		inv = true;
+	}
+
+	f = (float)strtol(c, &t, 10);
+
+	c = t;
+
+	if (*c == '.')
+	{
+		c++;
+
+		float pl = (float)strtol(c, &t, 10);
+		pl *= fast_atof_table[t-c];
+
+		f += pl;
+
+		c = t;
+
+		if (*c == 'e')
+		{
+			++c;
+			float exp = (float)strtol(c, &t, 10);
+			f *= (float)pow(10.0f, exp);
+			c = t;
+		}
+	}
+
+	if (inv)
+		f *= -1.0f;
+	
+	out = f;
+	return c;
+}
+
+//! Provides a fast function for converting a string into a float,
+//! about 6 times faster than atof in win32.
+// If you find any bugs, please send them to me, niko (at) irrlicht3d.org.
+inline const char* fast_atof_move_const(const char* c, float& out)
+{
+	bool inv = false;
+	char *t;
+	float f;
+
+	if (*c=='-')
+	{
+		c++;
+		inv = true;
+	}
+
+	f = (float)strtol(c, &t, 10);
+
+	c = t;
+
+	if (*c == '.')
+	{
+		c++;
+
+		float pl = (float)strtol(c, &t, 10);
+		pl *= fast_atof_table[t-c];
+
+		f += pl;
+
+		c = t;
+
+		if (*c == 'e') 
+		{ 
+			++c; 
+			f32 exp = (f32)strtol(c, &t, 10); 
+			f *= (f32)powf(10.0f, exp); 
+			c = t; 
+		}
+	}
+
+	if (inv)
+		f *= -1.0f;
+	
+	out = f;
+	return c;
+}
+
+
+inline float fast_atof(const char* c)
+{
+	float ret;
+	fast_atof_move_const(c, ret);
+	return ret;
+}
+
+} // end namespace core
+}// end namespace irr
+
+#endif
+

+ 2 - 1
contrib/irrXML/irrArray.h

@@ -21,7 +21,8 @@ class array
 {
 {
 
 
 public:
 public:
-	array() 
+
+	array()
 		: data(0), allocated(0), used(0),
 		: data(0), allocated(0), used(0),
 			free_when_destroyed(true), is_sorted(true)
 			free_when_destroyed(true), is_sorted(true)
 	{
 	{

+ 4 - 7
contrib/irrXML/irrString.h

@@ -29,7 +29,7 @@ public:
 
 
 	//! Default constructor
 	//! Default constructor
 	string()
 	string()
-	: array(0), allocated(1), used(1)
+	: array(0), allocated(1), used(1) 
 	{
 	{
 		array = new T[1];
 		array = new T[1];
 		array[0] = 0x0;
 		array[0] = 0x0;
@@ -39,7 +39,7 @@ public:
 
 
 	//! Constructor
 	//! Constructor
 	string(const string<T>& other)
 	string(const string<T>& other)
-	: array(0), allocated(0), used(0)
+	:  array(0), allocated(0), used(0)
 	{
 	{
 		*this = other;
 		*this = other;
 	}
 	}
@@ -47,7 +47,7 @@ public:
 
 
 	//! Constructs a string from an int
 	//! Constructs a string from an int
 	string(int number)
 	string(int number)
-	: array(0), allocated(0), used(0)
+	: array(0), allocated(0), used(0) 
 	{
 	{
 		// store if negative and make positive
 		// store if negative and make positive
 
 
@@ -117,7 +117,7 @@ public:
 	//! Constructor for unicode and ascii strings
 	//! Constructor for unicode and ascii strings
 	template <class B>
 	template <class B>
 	string(const B* c)
 	string(const B* c)
-	: array(0),allocated(0), used(0)
+	: array(0), allocated(0), used(0)
 	{
 	{
 		*this = c;
 		*this = c;
 	}
 	}
@@ -635,9 +635,6 @@ private:
 		s32 amount = used < new_size ? used : new_size;
 		s32 amount = used < new_size ? used : new_size;
 		for (s32 i=0; i<amount; ++i)
 		for (s32 i=0; i<amount; ++i)
 			array[i] = old_array[i];
 			array[i] = old_array[i];
-
-		if (allocated < used)
-			used = allocated;
 		
 		
 		delete [] old_array;
 		delete [] old_array;
 	}
 	}

+ 4 - 11
contrib/irrXML/irrTypes.h

@@ -79,13 +79,8 @@ typedef unsigned short wchar_t;
 #endif // microsoft compiler
 #endif // microsoft compiler
 
 
 //! define a break macro for debugging only in Win32 mode.
 //! define a break macro for debugging only in Win32 mode.
-// WORKAROUND (assimp): remove __asm
-#if defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG)
-#if defined(_M_IX86)
-#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) /*if (_CONDITION_) {_asm int 3}*/
-#else
-#define _IRR_DEBUG_BREAK_IF( _CONDITION_ )
-#endif
+#if !defined(_WIN64) && defined(WIN32) && defined(_MSC_VER) && defined(_DEBUG)
+#define _IRR_DEBUG_BREAK_IF( _CONDITION_ ) if (_CONDITION_) {_asm int 3}
 #else 
 #else 
 #define _IRR_DEBUG_BREAK_IF( _CONDITION_ )
 #define _IRR_DEBUG_BREAK_IF( _CONDITION_ )
 #endif
 #endif
@@ -96,10 +91,8 @@ When you call unmanaged code that returns a bool type value of false from manage
 the return value may appear as true. See 
 the return value may appear as true. See 
 http://support.microsoft.com/default.aspx?kbid=823071 for details. 
 http://support.microsoft.com/default.aspx?kbid=823071 for details. 
 Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/
 Compiler version defines: VC6.0 : 1200, VC7.0 : 1300, VC7.1 : 1310, VC8.0 : 1400*/
-
-// WORKAROUND (assimp): remove __asm 
-#if defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400)
-#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX /*__asm mov eax,100*/
+#if !defined(_WIN64) && defined(WIN32) && defined(_MSC_VER) && (_MSC_VER > 1299) && (_MSC_VER < 1400)
+#define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX __asm mov eax,100
 #else
 #else
 #define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX
 #define _IRR_IMPLEMENT_MANAGED_MARSHALLING_BUGFIX
 #endif // _IRR_MANAGED_MARSHALLING_BUGFIX
 #endif // _IRR_MANAGED_MARSHALLING_BUGFIX

+ 2 - 6
contrib/irrXML/irrXML.cpp

@@ -2,14 +2,10 @@
 // This file is part of the "Irrlicht Engine" and the "irrXML" project.
 // This file is part of the "Irrlicht Engine" and the "irrXML" project.
 // For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
 // For conditions of distribution and use, see copyright notice in irrlicht.h and/or irrXML.h
 
 
-// Need to include Assimp, too. We're using Assimp's version of fast_atof
-// so we need stdint.h. But no PCH.
-
-
 #include "irrXML.h"
 #include "irrXML.h"
 #include "irrString.h"
 #include "irrString.h"
 #include "irrArray.h"
 #include "irrArray.h"
-//#include <assimp/fast_atof.h>
+#include "fast_atof.h"
 #include "CXMLReaderImpl.h"
 #include "CXMLReaderImpl.h"
 
 
 namespace irr
 namespace irr
@@ -18,7 +14,7 @@ namespace io
 {
 {
 
 
 //! Implementation of the file read callback for ordinary files
 //! Implementation of the file read callback for ordinary files
-class IRRXML_API CFileReadCallBack : public IFileReadCallBack
+class CFileReadCallBack : public IFileReadCallBack
 {
 {
 public:
 public:
 
 

+ 11 - 17
contrib/irrXML/irrXML.h

@@ -7,12 +7,6 @@
 
 
 #include <stdio.h>
 #include <stdio.h>
 
 
-#ifdef _WIN32
-#   define IRRXML_API __declspec(dllexport)
-#else
-#   define IRRXML_API __attribute__ ((visibility("default")))
-#endif // _WIN32
-
 /** \mainpage irrXML 1.2 API documentation
 /** \mainpage irrXML 1.2 API documentation
  <div align="center"><img src="logobig.png" ></div>
  <div align="center"><img src="logobig.png" ></div>
 
 
@@ -178,7 +172,7 @@ namespace io
 		ETF_UTF32_BE,
 		ETF_UTF32_BE,
 
 
 		//! UTF-32 format, little endian
 		//! UTF-32 format, little endian
-		ETF_UTF32_LE
+		ETF_UTF32_LE,
 	};
 	};
 
 
 
 
@@ -215,7 +209,7 @@ namespace io
 	two methods to read your data and give a pointer to an instance of
 	two methods to read your data and give a pointer to an instance of
 	your implementation when calling createIrrXMLReader(), 
 	your implementation when calling createIrrXMLReader(), 
 	createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */
 	createIrrXMLReaderUTF16() or createIrrXMLReaderUTF32() */
-	class IRRXML_API IFileReadCallBack
+	class IFileReadCallBack
 	{
 	{
 	public:
 	public:
 
 
@@ -415,7 +409,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
 	and the file could not be opened. */
-    IRRXML_API IrrXMLReader* createIrrXMLReader(const char* filename);
+	IrrXMLReader* createIrrXMLReader(const char* filename);
 
 
 	//! Creates an instance of an UFT-8 or ASCII character xml parser.
 	//! Creates an instance of an UFT-8 or ASCII character xml parser.
 	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can 
 	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can 
@@ -427,7 +421,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
 	and the file could not be opened. */
-    IRRXML_API IrrXMLReader* createIrrXMLReader(FILE* file);
+	IrrXMLReader* createIrrXMLReader(FILE* file);
 
 
 	//! Creates an instance of an UFT-8 or ASCII character xml parser. 
 	//! Creates an instance of an UFT-8 or ASCII character xml parser. 
 	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can 
 	/** This means that all character data will be returned in 8 bit ASCII or UTF-8. The file to read can 
@@ -440,7 +434,7 @@ namespace io
 	 \return Returns a pointer to the created xml parser. This pointer should be 
 	 \return Returns a pointer to the created xml parser. This pointer should be 
 	 deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	 deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	 and the file could not be opened. */
 	 and the file could not be opened. */
-    IRRXML_API IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback);
+	IrrXMLReader* createIrrXMLReader(IFileReadCallBack* callback);
 
 
 	//! Creates an instance of an UFT-16 xml parser. 
 	//! Creates an instance of an UFT-16 xml parser. 
 	/** This means that
 	/** This means that
@@ -452,7 +446,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
 	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename);
+	IrrXMLReaderUTF16* createIrrXMLReaderUTF16(const char* filename);
 
 
 	//! Creates an instance of an UFT-16 xml parser. 
 	//! Creates an instance of an UFT-16 xml parser. 
 	/** This means that all character data will be returned in UTF-16. The file to read can 
 	/** This means that all character data will be returned in UTF-16. The file to read can 
@@ -464,7 +458,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
 	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file);
+	IrrXMLReaderUTF16* createIrrXMLReaderUTF16(FILE* file);
 
 
 	//! Creates an instance of an UFT-16 xml parser. 
 	//! Creates an instance of an UFT-16 xml parser. 
 	/** This means that all character data will be returned in UTF-16. The file to read can 
 	/** This means that all character data will be returned in UTF-16. The file to read can 
@@ -477,7 +471,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
 	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback);
+	IrrXMLReaderUTF16* createIrrXMLReaderUTF16(IFileReadCallBack* callback);
 
 
 
 
 	//! Creates an instance of an UFT-32 xml parser. 
 	//! Creates an instance of an UFT-32 xml parser. 
@@ -489,7 +483,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
 	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename);
+	IrrXMLReaderUTF32* createIrrXMLReaderUTF32(const char* filename);
 
 
 	//! Creates an instance of an UFT-32 xml parser. 
 	//! Creates an instance of an UFT-32 xml parser. 
 	/** This means that all character data will be returned in UTF-32. The file to read can 
 	/** This means that all character data will be returned in UTF-32. The file to read can 
@@ -501,7 +495,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
 	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file);
+	IrrXMLReaderUTF32* createIrrXMLReaderUTF32(FILE* file);
 
 
 	//! Creates an instance of an UFT-32 xml parser. 
 	//! Creates an instance of an UFT-32 xml parser. 
 	/** This means that
 	/** This means that
@@ -515,7 +509,7 @@ namespace io
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	\return Returns a pointer to the created xml parser. This pointer should be 
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	deleted using 'delete' after no longer needed. Returns 0 if an error occured
 	and the file could not be opened. */
 	and the file could not be opened. */
-    IRRXML_API IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback);
+	IrrXMLReaderUTF32* createIrrXMLReaderUTF32(IFileReadCallBack* callback);
 	
 	
 
 
 	/*! \file irrxml.h
 	/*! \file irrxml.h

+ 28 - 13
include/assimp/MathFunctions.h

@@ -55,36 +55,51 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace Assimp {
 namespace Math {
 namespace Math {
 
 
-// TODO: use binary GCD for unsigned integers ....
-template < typename IntegerType >
-inline
-IntegerType gcd( IntegerType a, IntegerType b ) {
+/// @brief  Will return the greatest common divisor.
+/// @param  a   [in] Value a.
+/// @param  b   [in] Value b.
+/// @return The greatest common divisor.
+template <typename IntegerType>
+inline IntegerType gcd( IntegerType a, IntegerType b ) {
 	const IntegerType zero = (IntegerType)0;
 	const IntegerType zero = (IntegerType)0;
 	while ( true ) {
 	while ( true ) {
-		if ( a == zero )
+		if ( a == zero ) {
 			return b;
 			return b;
+        }
 		b %= a;
 		b %= a;
 
 
-		if ( b == zero )
+		if ( b == zero ) {
 			return a;
 			return a;
+        }
 		a %= b;
 		a %= b;
 	}
 	}
 }
 }
 
 
+/// @brief  Will return the greatest common divisor.
+/// @param  a   [in] Value a.
+/// @param  b   [in] Value b.
+/// @return The greatest common divisor.
 template < typename IntegerType >
 template < typename IntegerType >
-inline
-IntegerType lcm( IntegerType a, IntegerType b ) {
+inline IntegerType lcm( IntegerType a, IntegerType b ) {
 	const IntegerType t = gcd (a,b);
 	const IntegerType t = gcd (a,b);
-	if (!t)
+	if (!t) {
         return t;
         return t;
+    }
 	return a / t * b;
 	return a / t * b;
 }
 }
-
+/// @brief  Will return the smallest epsilon-value for the requested type. 
+/// @return The numercical limit epsilon depending on its type.
 template<class T>
 template<class T>
-inline
-T getEpsilon() {
+inline T getEpsilon() {
     return std::numeric_limits<T>::epsilon();
     return std::numeric_limits<T>::epsilon();
 }
 }
 
 
+/// @brief  Will return the constant PI for the requested type.
+/// @return Pi
+template<class T>
+inline T PI() {
+    return static_cast<T>(3.14159265358979323846);
 }
 }
-}
+
+} // namespace Math
+} // namespace Assimp

+ 164 - 0
include/assimp/SmallVector.h

@@ -0,0 +1,164 @@
+/*
+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 Defines small vector with inplace storage.
+Based on CppCon 2016: Chandler Carruth "High Performance Code 201: Hybrid Data Structures" */
+
+#pragma once
+#ifndef AI_SMALLVECTOR_H_INC
+#define AI_SMALLVECTOR_H_INC
+
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
+namespace Assimp {
+
+// --------------------------------------------------------------------------------------------
+/// @brief Small vector with inplace storage. 
+///
+/// Reduces heap allocations when list is shorter. It uses a small array for a dedicated size.
+/// When the growing gets bigger than this small cache a dynamic growing algorithm will be 
+/// used.
+// --------------------------------------------------------------------------------------------
+template<typename T, unsigned int Capacity>
+class SmallVector {
+public:
+    /// @brief  The default class constructor.
+    SmallVector() : 
+            mStorage(mInplaceStorage),
+            mSize(0),
+            mCapacity(Capacity) {
+        // empty
+    }
+
+    /// @brief  The class destructor.
+    ~SmallVector() {
+        if (mStorage != mInplaceStorage) {
+            delete [] mStorage;
+        }
+    }
+
+    /// @brief  Will push a new item. The capacity will grow in case of a too small capacity.
+    /// @param  item    [in] The item to push at the end of the vector.
+    void push_back(const T& item) {
+        if (mSize < mCapacity) {
+            mStorage[mSize++] = item;
+            return;
+        }
+        
+        push_back_and_grow(item);
+    }
+
+    /// @brief  Will resize the vector.
+    /// @param  newSize     [in] The new size.
+    void resize(size_t newSize) {
+        if (newSize > mCapacity) {
+            grow(newSize);
+        }
+        mSize = newSize;
+    }
+
+    /// @brief  Returns the current size of the vector.
+    /// @return The current size.
+    size_t size() const {
+        return mSize;
+    }
+
+    /// @brief  Returns a pointer to the first item.
+    /// @return The first item as a pointer.
+    T* begin() {
+        return mStorage;
+    }
+
+    /// @brief  Returns a pointer to the end.
+    /// @return The end as a pointer.
+    T* end() {
+        return &mStorage[mSize];
+    }
+
+    /// @brief  Returns a const pointer to the first item.
+    /// @return The first item as a const pointer.
+    T* begin() const {
+        return mStorage;
+    }
+
+    /// @brief  Returns a const pointer to the end.
+    /// @return The end as a const pointer.
+    T* end() const {
+        return &mStorage[mSize];
+    }
+
+    SmallVector(const SmallVector &) = delete;
+    SmallVector(SmallVector &&) = delete;
+    SmallVector &operator = (const SmallVector &) = delete;
+    SmallVector &operator = (SmallVector &&) = delete;
+
+private:
+    void grow( size_t newCapacity) {
+        T* oldStorage = mStorage;
+        T* newStorage = new T[newCapacity];
+
+        std::memcpy(newStorage, oldStorage, mSize * sizeof(T));
+
+        mStorage = newStorage;
+        mCapacity = newCapacity;
+
+        if (oldStorage != mInplaceStorage) {
+            delete [] oldStorage;
+        }
+    }
+
+    void push_back_and_grow(const T& item) {
+        grow(mCapacity + Capacity);
+
+        mStorage[mSize++] = item;
+    }
+
+    T* mStorage;
+    size_t mSize;
+    size_t mCapacity;
+    T mInplaceStorage[Capacity];
+};
+
+} // end namespace Assimp
+
+#endif // !! AI_SMALLVECTOR_H_INC

+ 24 - 28
include/assimp/SpatialSort.h

@@ -46,11 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_SPATIALSORT_H_INC
 #define AI_SPATIALSORT_H_INC
 
 
 #ifdef __GNUC__
 #ifdef __GNUC__
-#   pragma GCC system_header
+#pragma GCC system_header
 #endif
 #endif
 
 
-#include <vector>
 #include <assimp/types.h>
 #include <assimp/types.h>
+#include <vector>
 
 
 namespace Assimp {
 namespace Assimp {
 
 
@@ -62,10 +62,8 @@ namespace Assimp {
  * time, with O(n) worst case complexity when all vertices lay on the plane. The plane is chosen
  * time, with O(n) worst case complexity when all vertices lay on the plane. The plane is chosen
  * so that it avoids common planes in usual data sets. */
  * so that it avoids common planes in usual data sets. */
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-class ASSIMP_API SpatialSort
-{
+class ASSIMP_API SpatialSort {
 public:
 public:
-
     SpatialSort();
     SpatialSort();
 
 
     // ------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------
@@ -76,14 +74,12 @@ public:
      * @param pNumPositions Number of vectors to expect in that array.
      * @param pNumPositions Number of vectors to expect in that array.
      * @param pElementOffset Offset in bytes from the beginning of one vector in memory
      * @param pElementOffset Offset in bytes from the beginning of one vector in memory
      *   to the beginning of the next vector. */
      *   to the beginning of the next vector. */
-    SpatialSort( const aiVector3D* pPositions, unsigned int pNumPositions,
-        unsigned int pElementOffset);
+    SpatialSort(const aiVector3D *pPositions, unsigned int pNumPositions,
+            unsigned int pElementOffset);
 
 
     /** Destructor */
     /** Destructor */
     ~SpatialSort();
     ~SpatialSort();
 
 
-public:
-
     // ------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------
     /** Sets the input data for the SpatialSort. This replaces existing data, if any.
     /** Sets the input data for the SpatialSort. This replaces existing data, if any.
      *  The new data receives new indices in ascending order.
      *  The new data receives new indices in ascending order.
@@ -97,17 +93,15 @@ public:
      *   required in order to use #FindPosition() or #GenerateMappingTable().
      *   required in order to use #FindPosition() or #GenerateMappingTable().
      *   If you don't finalize yet, you can use #Append() to add data from
      *   If you don't finalize yet, you can use #Append() to add data from
      *   other sources.*/
      *   other sources.*/
-    void Fill( const aiVector3D* pPositions, unsigned int pNumPositions,
-        unsigned int pElementOffset,
-        bool pFinalize = true);
-
+    void Fill(const aiVector3D *pPositions, unsigned int pNumPositions,
+            unsigned int pElementOffset,
+            bool pFinalize = true);
 
 
     // ------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------
     /** Same as #Fill(), except the method appends to existing data in the #SpatialSort. */
     /** Same as #Fill(), except the method appends to existing data in the #SpatialSort. */
-    void Append( const aiVector3D* pPositions, unsigned int pNumPositions,
-        unsigned int pElementOffset,
-        bool pFinalize = true);
-
+    void Append(const aiVector3D *pPositions, unsigned int pNumPositions,
+            unsigned int pElementOffset,
+            bool pFinalize = true);
 
 
     // ------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------
     /** Finalize the spatial hash data structure. This can be useful after
     /** Finalize the spatial hash data structure. This can be useful after
@@ -123,8 +117,8 @@ public:
      * @param poResults The container to store the indices of the found positions.
      * @param poResults The container to store the indices of the found positions.
      *   Will be emptied by the call so it may contain anything.
      *   Will be emptied by the call so it may contain anything.
      * @return An iterator to iterate over all vertices in the given area.*/
      * @return An iterator to iterate over all vertices in the given area.*/
-    void FindPositions( const aiVector3D& pPosition, ai_real pRadius,
-        std::vector<unsigned int>& poResults) const;
+    void FindPositions(const aiVector3D &pPosition, ai_real pRadius,
+            std::vector<unsigned int> &poResults) const;
 
 
     // ------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------
     /** Fills an array with indices of all positions identical to the given position. In
     /** Fills an array with indices of all positions identical to the given position. In
@@ -133,8 +127,8 @@ public:
      * @param pPosition The position to look for vertices.
      * @param pPosition The position to look for vertices.
      * @param poResults The container to store the indices of the found positions.
      * @param poResults The container to store the indices of the found positions.
      *   Will be emptied by the call so it may contain anything.*/
      *   Will be emptied by the call so it may contain anything.*/
-    void FindIdenticalPositions( const aiVector3D& pPosition,
-        std::vector<unsigned int>& poResults) const;
+    void FindIdenticalPositions(const aiVector3D &pPosition,
+            std::vector<unsigned int> &poResults) const;
 
 
     // ------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------
     /** Compute a table that maps each vertex ID referring to a spatially close
     /** Compute a table that maps each vertex ID referring to a spatially close
@@ -144,8 +138,8 @@ public:
      * @param pRadius Maximal distance from the position a vertex may have to
      * @param pRadius Maximal distance from the position a vertex may have to
      *   be counted in.
      *   be counted in.
      *  @return Number of unique vertices (n).  */
      *  @return Number of unique vertices (n).  */
-    unsigned int GenerateMappingTable(std::vector<unsigned int>& fill,
-        ai_real pRadius) const;
+    unsigned int GenerateMappingTable(std::vector<unsigned int> &fill,
+            ai_real pRadius) const;
 
 
 protected:
 protected:
     /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
     /** Normal of the sorting plane, normalized. The center is always at (0, 0, 0) */
@@ -159,15 +153,17 @@ protected:
         ai_real mDistance; ///< Distance of this vertex to the sorting plane
         ai_real mDistance; ///< Distance of this vertex to the sorting plane
 
 
         Entry() AI_NO_EXCEPT
         Entry() AI_NO_EXCEPT
-        : mIndex( 999999999 ), mPosition(), mDistance( 99999. ) {
-            // empty        
+                : mIndex(999999999),
+                  mPosition(),
+                  mDistance(99999.) {
+            // empty
         }
         }
-        Entry( unsigned int pIndex, const aiVector3D& pPosition, ai_real pDistance)
-        : mIndex( pIndex), mPosition( pPosition), mDistance( pDistance) {
+        Entry(unsigned int pIndex, const aiVector3D &pPosition, ai_real pDistance) :
+                mIndex(pIndex), mPosition(pPosition), mDistance(pDistance) {
             // empty
             // empty
         }
         }
 
 
-        bool operator < (const Entry& e) const { return mDistance < e.mDistance; }
+        bool operator<(const Entry &e) const { return mDistance < e.mDistance; }
     };
     };
 
 
     // all positions, sorted by distance to the sorting plane
     // all positions, sorted by distance to the sorting plane

+ 84 - 86
include/assimp/StreamReader.h

@@ -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,
@@ -49,13 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_STREAMREADER_H_INCLUDED
 #define AI_STREAMREADER_H_INCLUDED
 
 
 #ifdef __GNUC__
 #ifdef __GNUC__
-#   pragma GCC system_header
+#pragma GCC system_header
 #endif
 #endif
 
 
-#include <assimp/IOStream.hpp>
-#include <assimp/Defines.h>
 #include <assimp/ByteSwapper.h>
 #include <assimp/ByteSwapper.h>
+#include <assimp/Defines.h>
 #include <assimp/Exceptional.h>
 #include <assimp/Exceptional.h>
+#include <assimp/IOStream.hpp>
 
 
 #include <memory>
 #include <memory>
 
 
@@ -74,10 +72,8 @@ namespace Assimp {
 template <bool SwapEndianess = false, bool RuntimeSwitch = false>
 template <bool SwapEndianess = false, bool RuntimeSwitch = false>
 class StreamReader {
 class StreamReader {
 public:
 public:
-    // FIXME: use these data types throughout the whole library,
-    // then change them to 64 bit values :-)
-    using diff = int;
-    using pos  = unsigned int;
+    using diff = size_t;
+    using pos = size_t;
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     /** Construction from a given stream with a well-defined endianness.
     /** Construction from a given stream with a well-defined endianness.
@@ -91,40 +87,45 @@ public:
      *    stream is in little endian byte order. Otherwise the
      *    stream is in little endian byte order. Otherwise the
      *    endianness information is contained in the @c SwapEndianess
      *    endianness information is contained in the @c SwapEndianess
      *    template parameter and this parameter is meaningless.  */
      *    template parameter and this parameter is meaningless.  */
-    StreamReader(std::shared_ptr<IOStream> stream, bool le = false)
-        : stream(stream)
-        , le(le)
-    {
+    StreamReader(std::shared_ptr<IOStream> stream, bool le = false) :
+            mStream(stream),
+            mBuffer(nullptr),
+            mCurrent(nullptr),
+            mEnd(nullptr),
+            mLimit(nullptr),
+            mLe(le) {
         ai_assert(stream);
         ai_assert(stream);
         InternBegin();
         InternBegin();
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
-    StreamReader(IOStream* stream, bool le = false)
-        : stream(std::shared_ptr<IOStream>(stream))
-        , le(le)
-    {
-        ai_assert(stream);
+    StreamReader(IOStream *stream, bool le = false) :
+            mStream(std::shared_ptr<IOStream>(stream)),
+            mBuffer(nullptr),
+            mCurrent(nullptr),
+            mEnd(nullptr),
+            mLimit(nullptr),
+            mLe(le) {
+        ai_assert(nullptr != stream);
         InternBegin();
         InternBegin();
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     ~StreamReader() {
     ~StreamReader() {
-        delete[] buffer;
+        delete[] mBuffer;
     }
     }
 
 
     // deprecated, use overloaded operator>> instead
     // deprecated, use overloaded operator>> instead
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
-    /** Read a float from the stream  */
-    float GetF4()
-    {
+    /// Read a float from the stream.
+    float GetF4() {
         return Get<float>();
         return Get<float>();
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
-    /** Read a double from the stream  */
-    double GetF8()  {
+    /// Read a double from the stream.
+    double GetF8() {
         return Get<double>();
         return Get<double>();
     }
     }
 
 
@@ -136,7 +137,7 @@ public:
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     /** Read a signed 8 bit integer from the stream */
     /** Read a signed 8 bit integer from the stream */
-    int8_t GetI1()  {
+    int8_t GetI1() {
         return Get<int8_t>();
         return Get<int8_t>();
     }
     }
 
 
@@ -154,55 +155,55 @@ public:
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     /** Read a unsigned 16 bit integer from the stream */
     /** Read a unsigned 16 bit integer from the stream */
-    uint16_t GetU2()    {
+    uint16_t GetU2() {
         return Get<uint16_t>();
         return Get<uint16_t>();
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
-    /** Read a unsigned 8 bit integer from the stream */
+    /// Read a unsigned 8 bit integer from the stream
     uint8_t GetU1() {
     uint8_t GetU1() {
         return Get<uint8_t>();
         return Get<uint8_t>();
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
-    /** Read an unsigned 32 bit integer from the stream */
-    uint32_t GetU4()    {
+    /// Read an unsigned 32 bit integer from the stream
+    uint32_t GetU4() {
         return Get<uint32_t>();
         return Get<uint32_t>();
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
-    /** Read a unsigned 64 bit integer from the stream */
-    uint64_t GetU8()    {
+    /// Read a unsigned 64 bit integer from the stream
+    uint64_t GetU8() {
         return Get<uint64_t>();
         return Get<uint64_t>();
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
-    /** Get the remaining stream size (to the end of the stream) */
-    unsigned int GetRemainingSize() const {
-        return (unsigned int)(end - current);
+    /// Get the remaining stream size (to the end of the stream)
+    size_t GetRemainingSize() const {
+        return (unsigned int)(mEnd - mCurrent);
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     /** Get the remaining stream size (to the current read limit). The
     /** Get the remaining stream size (to the current read limit). The
      *  return value is the remaining size of the stream if no custom
      *  return value is the remaining size of the stream if no custom
      *  read limit has been set. */
      *  read limit has been set. */
-    unsigned int GetRemainingSizeToLimit() const {
-        return (unsigned int)(limit - current);
+    size_t GetRemainingSizeToLimit() const {
+        return (unsigned int)(mLimit - mCurrent);
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     /** Increase the file pointer (relative seeking)  */
     /** Increase the file pointer (relative seeking)  */
-    void IncPtr(intptr_t plus)    {
-        current += plus;
-        if (current > limit) {
+    void IncPtr(intptr_t plus) {
+        mCurrent += plus;
+        if (mCurrent > mLimit) {
             throw DeadlyImportError("End of file or read limit was reached");
             throw DeadlyImportError("End of file or read limit was reached");
         }
         }
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     /** Get the current file pointer */
     /** Get the current file pointer */
-    int8_t* GetPtr() const  {
-        return current;
+    int8_t *GetPtr() const {
+        return mCurrent;
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
@@ -211,9 +212,9 @@ public:
      *  large chunks of data at once.
      *  large chunks of data at once.
      *  @param p The new pointer, which is validated against the size
      *  @param p The new pointer, which is validated against the size
      *    limit and buffer boundaries. */
      *    limit and buffer boundaries. */
-    void SetPtr(int8_t* p)  {
-        current = p;
-        if (current > limit || current < buffer) {
+    void SetPtr(int8_t *p) {
+        mCurrent = p;
+        if (mCurrent > mLimit || mCurrent < mBuffer) {
             throw DeadlyImportError("End of file or read limit was reached");
             throw DeadlyImportError("End of file or read limit was reached");
         }
         }
     }
     }
@@ -222,21 +223,20 @@ public:
     /** Copy n bytes to an external buffer
     /** Copy n bytes to an external buffer
      *  @param out Destination for copying
      *  @param out Destination for copying
      *  @param bytes Number of bytes to copy */
      *  @param bytes Number of bytes to copy */
-    void CopyAndAdvance(void* out, size_t bytes)    {
-        int8_t* ur = GetPtr();
-        SetPtr(ur+bytes); // fire exception if eof
+    void CopyAndAdvance(void *out, size_t bytes) {
+        int8_t *ur = GetPtr();
+        SetPtr(ur + bytes); // fire exception if eof
 
 
-        ::memcpy(out,ur,bytes);
+        ::memcpy(out, ur, bytes);
     }
     }
 
 
-    // ---------------------------------------------------------------------
-    /** Get the current offset from the beginning of the file */
-    int GetCurrentPos() const   {
-        return (unsigned int)(current - buffer);
+    /// @brief Get the current offset from the beginning of the file
+    int GetCurrentPos() const {
+        return (unsigned int)(mCurrent - mBuffer);
     }
     }
 
 
     void SetCurrentPos(size_t pos) {
     void SetCurrentPos(size_t pos) {
-        SetPtr(buffer + pos);
+        SetPtr(mBuffer + pos);
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
@@ -246,15 +246,15 @@ public:
      *    the beginning of the file. Specifying UINT_MAX
      *    the beginning of the file. Specifying UINT_MAX
      *    resets the limit to the original end of the stream.
      *    resets the limit to the original end of the stream.
      *  Returns the previously set limit. */
      *  Returns the previously set limit. */
-    unsigned int SetReadLimit(unsigned int _limit)  {
+    unsigned int SetReadLimit(unsigned int _limit) {
         unsigned int prev = GetReadLimit();
         unsigned int prev = GetReadLimit();
         if (UINT_MAX == _limit) {
         if (UINT_MAX == _limit) {
-            limit = end;
+            mLimit = mEnd;
             return prev;
             return prev;
         }
         }
 
 
-        limit = buffer + _limit;
-        if (limit > end) {
+        mLimit = mBuffer + _limit;
+        if (mLimit > mEnd) {
             throw DeadlyImportError("StreamReader: Invalid read limit");
             throw DeadlyImportError("StreamReader: Invalid read limit");
         }
         }
         return prev;
         return prev;
@@ -263,21 +263,21 @@ public:
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     /** Get the current read limit in bytes. Reading over this limit
     /** Get the current read limit in bytes. Reading over this limit
      *  accidentally raises an exception.  */
      *  accidentally raises an exception.  */
-    unsigned int GetReadLimit() const    {
-        return (unsigned int)(limit - buffer);
+    unsigned int GetReadLimit() const {
+        return (unsigned int)(mLimit - mBuffer);
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     /** Skip to the read limit in bytes. Reading over this limit
     /** Skip to the read limit in bytes. Reading over this limit
      *  accidentally raises an exception. */
      *  accidentally raises an exception. */
-    void SkipToReadLimit()  {
-        current = limit;
+    void SkipToReadLimit() {
+        mCurrent = mLimit;
     }
     }
 
 
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     /** overload operator>> and allow chaining of >> ops. */
     /** overload operator>> and allow chaining of >> ops. */
     template <typename T>
     template <typename T>
-    StreamReader& operator >> (T& f) {
+    StreamReader &operator>>(T &f) {
         f = Get<T>();
         f = Get<T>();
         return *this;
         return *this;
     }
     }
@@ -286,14 +286,14 @@ public:
     /** Generic read method. ByteSwap::Swap(T*) *must* be defined */
     /** Generic read method. ByteSwap::Swap(T*) *must* be defined */
     template <typename T>
     template <typename T>
     T Get() {
     T Get() {
-        if ( current + sizeof(T) > limit) {
+        if (mCurrent + sizeof(T) > mLimit) {
             throw DeadlyImportError("End of file or stream limit was reached");
             throw DeadlyImportError("End of file or stream limit was reached");
         }
         }
 
 
         T f;
         T f;
-        ::memcpy (&f, current, sizeof(T));
-        Intern::Getter<SwapEndianess,T,RuntimeSwitch>() (&f,le);
-        current += sizeof(T);
+        ::memcpy(&f, mCurrent, sizeof(T));
+        Intern::Getter<SwapEndianess, T, RuntimeSwitch>()(&f, mLe);
+        mCurrent += sizeof(T);
 
 
         return f;
         return f;
     }
     }
@@ -301,46 +301,44 @@ public:
 private:
 private:
     // ---------------------------------------------------------------------
     // ---------------------------------------------------------------------
     void InternBegin() {
     void InternBegin() {
-        if (!stream) {
-            // in case someone wonders: StreamReader is frequently invoked with
-            // no prior validation whether the input stream is valid. Since
-            // no one bothers changing the error message, this message here
-            // is passed down to the caller and 'unable to open file'
-            // simply describes best what happened.
+        if (nullptr == mStream) {
             throw DeadlyImportError("StreamReader: Unable to open file");
             throw DeadlyImportError("StreamReader: Unable to open file");
         }
         }
 
 
-        const size_t s = stream->FileSize() - stream->Tell();
-        if (!s) {
+        const size_t filesize = mStream->FileSize() - mStream->Tell();
+        if (0 == filesize) {
             throw DeadlyImportError("StreamReader: File is empty or EOF is already reached");
             throw DeadlyImportError("StreamReader: File is empty or EOF is already reached");
         }
         }
 
 
-        current = buffer = new int8_t[s];
-        const size_t read = stream->Read(current,1,s);
+        mCurrent = mBuffer = new int8_t[filesize];
+        const size_t read = mStream->Read(mCurrent, 1, filesize);
         // (read < s) can only happen if the stream was opened in text mode, in which case FileSize() is not reliable
         // (read < s) can only happen if the stream was opened in text mode, in which case FileSize() is not reliable
-        ai_assert(read <= s);
-        end = limit = &buffer[read-1] + 1;
+        ai_assert(read <= filesize);
+        mEnd = mLimit = &mBuffer[read - 1] + 1;
     }
     }
 
 
 private:
 private:
-    std::shared_ptr<IOStream> stream;
-    int8_t *buffer, *current, *end, *limit;
-    bool le;
+    std::shared_ptr<IOStream> mStream;
+    int8_t *mBuffer;
+    int8_t *mCurrent;
+    int8_t *mEnd;
+    int8_t *mLimit;
+    bool mLe;
 };
 };
 
 
 // --------------------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------------------
 // `static` StreamReaders. Their byte order is fixed and they might be a little bit faster.
 // `static` StreamReaders. Their byte order is fixed and they might be a little bit faster.
 #ifdef AI_BUILD_BIG_ENDIAN
 #ifdef AI_BUILD_BIG_ENDIAN
-    typedef StreamReader<true>  StreamReaderLE;
-    typedef StreamReader<false> StreamReaderBE;
+typedef StreamReader<true> StreamReaderLE;
+typedef StreamReader<false> StreamReaderBE;
 #else
 #else
-    typedef StreamReader<true>  StreamReaderBE;
-    typedef StreamReader<false> StreamReaderLE;
+typedef StreamReader<true> StreamReaderBE;
+typedef StreamReader<false> StreamReaderLE;
 #endif
 #endif
 
 
 // `dynamic` StreamReader. The byte order of the input data is specified in the
 // `dynamic` StreamReader. The byte order of the input data is specified in the
 // c'tor. This involves runtime branching and might be a little bit slower.
 // c'tor. This involves runtime branching and might be a little bit slower.
-typedef StreamReader<true,true> StreamReaderAny;
+typedef StreamReader<true, true> StreamReaderAny;
 
 
 } // end namespace Assimp
 } // end namespace Assimp
 
 

+ 17 - 0
include/assimp/StringUtils.h

@@ -145,4 +145,21 @@ std::string DecimalToHexa( T toConvert ) {
     return result;
     return result;
 }
 }
 
 
+///	@brief	translate RGBA to String
+///	@param	r   aiColor.r
+///	@param	g   aiColor.g
+///	@param	b   aiColor.b
+///	@param	a   aiColor.a
+///	@param	with_head   # 
+///	@return	The hexadecimal string, is empty in case of an error.
+AI_FORCE_INLINE std::string Rgba2Hex(int r, int g, int b, int a, bool with_head) {
+	std::stringstream ss;
+	if (with_head) {
+		ss << "#";
+    }
+	ss << std::hex << (r << 24 | g << 16 | b << 8 | a);
+	
+    return ss.str();
+}
+
 #endif // INCLUDED_AI_STRINGUTILS_H
 #endif // INCLUDED_AI_STRINGUTILS_H

+ 17 - 6
include/assimp/camera.h

@@ -171,15 +171,26 @@ struct aiCamera
      */
      */
     float mAspect;
     float mAspect;
 
 
+    /** Half horizontal orthographic width, in scene units.
+     *
+     *  The orthographic width specifies the half width of the
+     *  orthographic view box. If non-zero the camera is
+     *  orthographic and the mAspect should define to the
+     *  ratio between the orthographic width and height
+     *  and mHorizontalFOV should be set to 0.
+     *  The default value is 0 (not orthographic).
+     */
+    float mOrthographicWidth;
 #ifdef __cplusplus
 #ifdef __cplusplus
 
 
     aiCamera() AI_NO_EXCEPT
     aiCamera() AI_NO_EXCEPT
-        : mUp               (0.f,1.f,0.f)
-        , mLookAt           (0.f,0.f,1.f)
-        , mHorizontalFOV    (0.25f * (float)AI_MATH_PI)
-        , mClipPlaneNear    (0.1f)
-        , mClipPlaneFar     (1000.f)
-        , mAspect           (0.f)
+        : mUp                (0.f,1.f,0.f)
+        , mLookAt            (0.f,0.f,1.f)
+        , mHorizontalFOV     (0.25f * (float)AI_MATH_PI)
+        , mClipPlaneNear     (0.1f)
+        , mClipPlaneFar      (1000.f)
+        , mAspect            (0.f)
+        , mOrthographicWidth (0.f)
     {}
     {}
 
 
     /** @brief Get a *right-handed* camera matrix from me
     /** @brief Get a *right-handed* camera matrix from me

+ 155 - 145
include/assimp/metadata.h

@@ -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,
@@ -49,29 +47,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_METADATA_H_INC
 #define AI_METADATA_H_INC
 
 
 #ifdef __GNUC__
 #ifdef __GNUC__
-#   pragma GCC system_header
+#pragma GCC system_header
 #endif
 #endif
 
 
 #if defined(_MSC_VER) && (_MSC_VER <= 1500)
 #if defined(_MSC_VER) && (_MSC_VER <= 1500)
-#  include "Compiler/pstdint.h"
+#include "Compiler/pstdint.h"
 #else
 #else
-#  include <stdint.h>
+#include <stdint.h>
 #endif
 #endif
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 /**
 /**
   * Enum used to distinguish data types
   * Enum used to distinguish data types
   */
   */
- // -------------------------------------------------------------------------------
+// -------------------------------------------------------------------------------
 typedef enum aiMetadataType {
 typedef enum aiMetadataType {
-    AI_BOOL       = 0,
-    AI_INT32      = 1,
-    AI_UINT64     = 2,
-    AI_FLOAT      = 3,
-    AI_DOUBLE     = 4,
-    AI_AISTRING   = 5,
+    AI_BOOL = 0,
+    AI_INT32 = 1,
+    AI_UINT64 = 2,
+    AI_FLOAT = 3,
+    AI_DOUBLE = 4,
+    AI_AISTRING = 5,
     AI_AIVECTOR3D = 6,
     AI_AIVECTOR3D = 6,
-    AI_META_MAX   = 7,
+    AI_META_MAX = 7,
 
 
 #ifndef SWIG
 #ifndef SWIG
     FORCE_32BIT = INT_MAX
     FORCE_32BIT = INT_MAX
@@ -84,10 +82,10 @@ typedef enum aiMetadataType {
   *
   *
   * The type field uniquely identifies the underlying type of the data field
   * The type field uniquely identifies the underlying type of the data field
   */
   */
- // -------------------------------------------------------------------------------
+// -------------------------------------------------------------------------------
 struct aiMetadataEntry {
 struct aiMetadataEntry {
     aiMetadataType mType;
     aiMetadataType mType;
-    void* mData;
+    void *mData;
 };
 };
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
@@ -98,15 +96,29 @@ struct aiMetadataEntry {
 /**
 /**
   * Helper functions to get the aiType enum entry for a type
   * Helper functions to get the aiType enum entry for a type
   */
   */
- // -------------------------------------------------------------------------------
+// -------------------------------------------------------------------------------
 
 
-inline aiMetadataType GetAiType( bool )       { return AI_BOOL; }
-inline aiMetadataType GetAiType( int32_t )    { return AI_INT32; }
-inline aiMetadataType GetAiType( uint64_t )   { return AI_UINT64; }
-inline aiMetadataType GetAiType( float )      { return AI_FLOAT; }
-inline aiMetadataType GetAiType( double )     { return AI_DOUBLE; }
-inline aiMetadataType GetAiType( const aiString & )   { return AI_AISTRING; }
-inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
+inline aiMetadataType GetAiType(bool) {
+    return AI_BOOL;
+}
+inline aiMetadataType GetAiType(int32_t) {
+    return AI_INT32;
+}
+inline aiMetadataType GetAiType(uint64_t) {
+    return AI_UINT64;
+}
+inline aiMetadataType GetAiType(float) {
+    return AI_FLOAT;
+}
+inline aiMetadataType GetAiType(double) {
+    return AI_DOUBLE;
+}
+inline aiMetadataType GetAiType(const aiString &) {
+    return AI_AISTRING;
+}
+inline aiMetadataType GetAiType(const aiVector3D &) {
+    return AI_AIVECTOR3D;
+}
 
 
 #endif // __cplusplus
 #endif // __cplusplus
 
 
@@ -116,17 +128,17 @@ inline aiMetadataType GetAiType( const aiVector3D & ) { return AI_AIVECTOR3D; }
   *
   *
   * Metadata is a key-value store using string keys and values.
   * Metadata is a key-value store using string keys and values.
   */
   */
- // -------------------------------------------------------------------------------
+// -------------------------------------------------------------------------------
 struct aiMetadata {
 struct aiMetadata {
     /** Length of the mKeys and mValues arrays, respectively */
     /** Length of the mKeys and mValues arrays, respectively */
     unsigned int mNumProperties;
     unsigned int mNumProperties;
 
 
     /** Arrays of keys, may not be NULL. Entries in this array may not be NULL as well. */
     /** Arrays of keys, may not be NULL. Entries in this array may not be NULL as well. */
-    C_STRUCT aiString* mKeys;
+    C_STRUCT aiString *mKeys;
 
 
     /** Arrays of values, may not be NULL. Entries in this array may be NULL if the
     /** Arrays of values, may not be NULL. Entries in this array may be NULL if the
       * corresponding property key has no assigned value. */
       * corresponding property key has no assigned value. */
-    C_STRUCT aiMetadataEntry* mValues;
+    C_STRUCT aiMetadataEntry *mValues;
 
 
 #ifdef __cplusplus
 #ifdef __cplusplus
 
 
@@ -134,71 +146,62 @@ struct aiMetadata {
      *  @brief  The default constructor, set all members to zero by default.
      *  @brief  The default constructor, set all members to zero by default.
      */
      */
     aiMetadata() AI_NO_EXCEPT
     aiMetadata() AI_NO_EXCEPT
-    : mNumProperties(0)
-    , mKeys(nullptr)
-    , mValues(nullptr) {
+            : mNumProperties(0),
+              mKeys(nullptr),
+              mValues(nullptr) {
         // empty
         // empty
     }
     }
 
 
-    aiMetadata( const aiMetadata &rhs )
-    : mNumProperties( rhs.mNumProperties )
-    , mKeys( nullptr )
-    , mValues( nullptr ) {
-        mKeys = new aiString[ mNumProperties ];
-        for ( size_t i = 0; i < static_cast<size_t>( mNumProperties ); ++i ) {
-            mKeys[ i ] = rhs.mKeys[ i ];
+    aiMetadata(const aiMetadata &rhs) :
+            mNumProperties(rhs.mNumProperties), mKeys(nullptr), mValues(nullptr) {
+        mKeys = new aiString[mNumProperties];
+        for (size_t i = 0; i < static_cast<size_t>(mNumProperties); ++i) {
+            mKeys[i] = rhs.mKeys[i];
         }
         }
-        mValues = new aiMetadataEntry[ mNumProperties ];
-        for ( size_t i = 0; i < static_cast<size_t>(mNumProperties); ++i ) {
-            mValues[ i ].mType = rhs.mValues[ i ].mType;
-            switch ( rhs.mValues[ i ].mType ) {
+        mValues = new aiMetadataEntry[mNumProperties];
+        for (size_t i = 0; i < static_cast<size_t>(mNumProperties); ++i) {
+            mValues[i].mType = rhs.mValues[i].mType;
+            switch (rhs.mValues[i].mType) {
             case AI_BOOL:
             case AI_BOOL:
-                mValues[ i ].mData = new bool;
-                ::memcpy( mValues[ i ].mData, rhs.mValues[ i ].mData, sizeof(bool) );
+                mValues[i].mData = new bool;
+                ::memcpy(mValues[i].mData, rhs.mValues[i].mData, sizeof(bool));
                 break;
                 break;
             case AI_INT32: {
             case AI_INT32: {
                 int32_t v;
                 int32_t v;
-                ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( int32_t ) );
-                mValues[ i ].mData = new int32_t( v );
-                }
-                break;
+                ::memcpy(&v, rhs.mValues[i].mData, sizeof(int32_t));
+                mValues[i].mData = new int32_t(v);
+            } break;
             case AI_UINT64: {
             case AI_UINT64: {
-                    uint64_t v;
-                    ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( uint64_t ) );
-                    mValues[ i ].mData = new  uint64_t( v );
-                }
-                break;
+                uint64_t v;
+                ::memcpy(&v, rhs.mValues[i].mData, sizeof(uint64_t));
+                mValues[i].mData = new uint64_t(v);
+            } break;
             case AI_FLOAT: {
             case AI_FLOAT: {
-                    float v;
-                    ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( float ) );
-                    mValues[ i ].mData = new float( v );
-                }
-                break;
+                float v;
+                ::memcpy(&v, rhs.mValues[i].mData, sizeof(float));
+                mValues[i].mData = new float(v);
+            } break;
             case AI_DOUBLE: {
             case AI_DOUBLE: {
-                    double v;
-                    ::memcpy( &v, rhs.mValues[ i ].mData, sizeof( double ) );
-                    mValues[ i ].mData = new double( v );
-                }
-                break;
+                double v;
+                ::memcpy(&v, rhs.mValues[i].mData, sizeof(double));
+                mValues[i].mData = new double(v);
+            } break;
             case AI_AISTRING: {
             case AI_AISTRING: {
-                    aiString v;
-                    rhs.Get<aiString>( mKeys[ i ], v );
-                    mValues[ i ].mData = new aiString( v );
-                }
-                break;
+                aiString v;
+                rhs.Get<aiString>(mKeys[i], v);
+                mValues[i].mData = new aiString(v);
+            } break;
             case AI_AIVECTOR3D: {
             case AI_AIVECTOR3D: {
-                    aiVector3D v;
-                    rhs.Get<aiVector3D>( mKeys[ i ], v );
-                    mValues[ i ].mData = new aiVector3D( v );
-                }
-                break;
+                aiVector3D v;
+                rhs.Get<aiVector3D>(mKeys[i], v);
+                mValues[i].mData = new aiVector3D(v);
+            } break;
 #ifndef SWIG
 #ifndef SWIG
             case FORCE_32BIT:
             case FORCE_32BIT:
 #endif
 #endif
             default:
             default:
                 break;
                 break;
             }
             }
-
         }
         }
     }
     }
 
 
@@ -206,33 +209,33 @@ struct aiMetadata {
      *  @brief The destructor.
      *  @brief The destructor.
      */
      */
     ~aiMetadata() {
     ~aiMetadata() {
-        delete [] mKeys;
+        delete[] mKeys;
         mKeys = nullptr;
         mKeys = nullptr;
         if (mValues) {
         if (mValues) {
             // Delete each metadata entry
             // Delete each metadata entry
-            for (unsigned i=0; i<mNumProperties; ++i) {
-                void* data = mValues[i].mData;
+            for (unsigned i = 0; i < mNumProperties; ++i) {
+                void *data = mValues[i].mData;
                 switch (mValues[i].mType) {
                 switch (mValues[i].mType) {
                 case AI_BOOL:
                 case AI_BOOL:
-                    delete static_cast< bool* >( data );
+                    delete static_cast<bool *>(data);
                     break;
                     break;
                 case AI_INT32:
                 case AI_INT32:
-                    delete static_cast< int32_t* >( data );
+                    delete static_cast<int32_t *>(data);
                     break;
                     break;
                 case AI_UINT64:
                 case AI_UINT64:
-                    delete static_cast< uint64_t* >( data );
+                    delete static_cast<uint64_t *>(data);
                     break;
                     break;
                 case AI_FLOAT:
                 case AI_FLOAT:
-                    delete static_cast< float* >( data );
+                    delete static_cast<float *>(data);
                     break;
                     break;
                 case AI_DOUBLE:
                 case AI_DOUBLE:
-                    delete static_cast< double* >( data );
+                    delete static_cast<double *>(data);
                     break;
                     break;
                 case AI_AISTRING:
                 case AI_AISTRING:
-                    delete static_cast< aiString* >( data );
+                    delete static_cast<aiString *>(data);
                     break;
                     break;
                 case AI_AIVECTOR3D:
                 case AI_AIVECTOR3D:
-                    delete static_cast< aiVector3D* >( data );
+                    delete static_cast<aiVector3D *>(data);
                     break;
                     break;
 #ifndef SWIG
 #ifndef SWIG
                 case FORCE_32BIT:
                 case FORCE_32BIT:
@@ -243,7 +246,7 @@ struct aiMetadata {
             }
             }
 
 
             // Delete the metadata array
             // Delete the metadata array
-            delete [] mValues;
+            delete[] mValues;
             mValues = nullptr;
             mValues = nullptr;
         }
         }
     }
     }
@@ -252,16 +255,15 @@ struct aiMetadata {
      *  @brief Allocates property fields + keys.
      *  @brief Allocates property fields + keys.
      *  @param  numProperties   Number of requested properties.
      *  @param  numProperties   Number of requested properties.
      */
      */
-    static inline
-    aiMetadata *Alloc( unsigned int numProperties ) {
-        if ( 0 == numProperties ) {
+    static inline aiMetadata *Alloc(unsigned int numProperties) {
+        if (0 == numProperties) {
             return nullptr;
             return nullptr;
         }
         }
 
 
         aiMetadata *data = new aiMetadata;
         aiMetadata *data = new aiMetadata;
         data->mNumProperties = numProperties;
         data->mNumProperties = numProperties;
-        data->mKeys = new aiString[ data->mNumProperties ]();
-        data->mValues = new aiMetadataEntry[ data->mNumProperties ]();
+        data->mKeys = new aiString[data->mNumProperties]();
+        data->mValues = new aiMetadataEntry[data->mNumProperties]();
 
 
         return data;
         return data;
     }
     }
@@ -269,44 +271,40 @@ struct aiMetadata {
     /**
     /**
      *  @brief Deallocates property fields + keys.
      *  @brief Deallocates property fields + keys.
      */
      */
-    static inline
-    void Dealloc( aiMetadata *metadata ) {
+    static inline void Dealloc(aiMetadata *metadata) {
         delete metadata;
         delete metadata;
     }
     }
 
 
-	template<typename T>
-	inline
-    void Add(const std::string& key, const T& value) {
-		aiString* new_keys = new aiString[mNumProperties + 1];
-		aiMetadataEntry* new_values = new aiMetadataEntry[mNumProperties + 1];
+    template <typename T>
+    inline void Add(const std::string &key, const T &value) {
+        aiString *new_keys = new aiString[mNumProperties + 1];
+        aiMetadataEntry *new_values = new aiMetadataEntry[mNumProperties + 1];
 
 
-		for(unsigned int i = 0; i < mNumProperties; ++i)
-		{
-			new_keys[i] = mKeys[i];
-			new_values[i] = mValues[i];
-		}
+        for (unsigned int i = 0; i < mNumProperties; ++i) {
+            new_keys[i] = mKeys[i];
+            new_values[i] = mValues[i];
+        }
 
 
-		delete[] mKeys;
-		delete[] mValues;
+        delete[] mKeys;
+        delete[] mValues;
 
 
-		mKeys = new_keys;
-		mValues = new_values;
+        mKeys = new_keys;
+        mValues = new_values;
 
 
-		mNumProperties++;
+        mNumProperties++;
 
 
-		Set(mNumProperties - 1, key, value);
-	}
+        Set(mNumProperties - 1, key, value);
+    }
 
 
-    template<typename T>
-    inline 
-    bool Set( unsigned index, const std::string& key, const T& value ) {
+    template <typename T>
+    inline bool Set(unsigned index, const std::string &key, const T &value) {
         // In range assertion
         // In range assertion
-        if ( index >= mNumProperties ) {
+        if (index >= mNumProperties) {
             return false;
             return false;
         }
         }
 
 
         // Ensure that we have a valid key.
         // Ensure that we have a valid key.
-        if ( key.empty() ) {
+        if (key.empty()) {
             return false;
             return false;
         }
         }
 
 
@@ -321,73 +319,86 @@ struct aiMetadata {
         return true;
         return true;
     }
     }
 
 
-    template<typename T>
-    inline 
-    bool Get( unsigned index, T& value ) const {
+    template <typename T>
+    inline bool Set( const std::string &key, const T &value ) {
+        if (key.empty()) {
+            return false;
+        }
+
+        bool result = false;
+        for (unsigned int i = 0; i < mNumProperties; ++i) {
+            if (key == mKeys[i].C_Str()) {
+                Set(i, key, value);
+                result = true;
+                break;
+            }
+        }
+
+        return result;
+    }
+
+    template <typename T>
+    inline bool Get(unsigned index, T &value) const {
         // In range assertion
         // In range assertion
-        if ( index >= mNumProperties ) {
+        if (index >= mNumProperties) {
             return false;
             return false;
         }
         }
 
 
         // Return false if the output data type does
         // Return false if the output data type does
         // not match the found value's data type
         // not match the found value's data type
-        if ( GetAiType( value ) != mValues[ index ].mType ) {
+        if (GetAiType(value) != mValues[index].mType) {
             return false;
             return false;
         }
         }
 
 
         // Otherwise, output the found value and
         // Otherwise, output the found value and
         // return true
         // return true
-        value = *static_cast<T*>(mValues[index].mData);
+        value = *static_cast<T *>(mValues[index].mData);
 
 
         return true;
         return true;
     }
     }
 
 
-    template<typename T>
-    inline 
-    bool Get( const aiString& key, T& value ) const {
+    template <typename T>
+    inline bool Get(const aiString &key, T &value) const {
         // Search for the given key
         // Search for the given key
-        for ( unsigned int i = 0; i < mNumProperties; ++i ) {
-            if ( mKeys[ i ] == key ) {
-                return Get( i, value );
+        for (unsigned int i = 0; i < mNumProperties; ++i) {
+            if (mKeys[i] == key) {
+                return Get(i, value);
             }
             }
         }
         }
         return false;
         return false;
     }
     }
 
 
-    template<typename T>
-    inline
-    bool Get( const std::string& key, T& value ) const {
+    template <typename T>
+    inline bool Get(const std::string &key, T &value) const {
         return Get(aiString(key), value);
         return Get(aiString(key), value);
     }
     }
 
 
-	/// Return metadata entry for analyzing it by user.
-	/// \param [in] pIndex - index of the entry.
-	/// \param [out] pKey - pointer to the key value.
-	/// \param [out] pEntry - pointer to the entry: type and value.
-	/// \return false - if pIndex is out of range, else - true.
-	inline
-    bool Get(size_t index, const aiString*& key, const aiMetadataEntry*& entry) const {
-        if ( index >= mNumProperties ) {
+    /// Return metadata entry for analyzing it by user.
+    /// \param [in] pIndex - index of the entry.
+    /// \param [out] pKey - pointer to the key value.
+    /// \param [out] pEntry - pointer to the entry: type and value.
+    /// \return false - if pIndex is out of range, else - true.
+    inline bool Get(size_t index, const aiString *&key, const aiMetadataEntry *&entry) const {
+        if (index >= mNumProperties) {
             return false;
             return false;
         }
         }
 
 
-		key = &mKeys[index];
-		entry = &mValues[index];
+        key = &mKeys[index];
+        entry = &mValues[index];
 
 
-		return true;
-	}
+        return true;
+    }
 
 
     /// Check whether there is a metadata entry for the given key.
     /// Check whether there is a metadata entry for the given key.
     /// \param [in] Key - the key value value to check for.
     /// \param [in] Key - the key value value to check for.
-    inline
-    bool HasKey(const char* key) {
-        if ( nullptr == key ) {
+    inline bool HasKey(const char *key) {
+        if (nullptr == key) {
             return false;
             return false;
         }
         }
-        
+
         // Search for the given key
         // Search for the given key
         for (unsigned int i = 0; i < mNumProperties; ++i) {
         for (unsigned int i = 0; i < mNumProperties; ++i) {
-            if ( 0 == strncmp(mKeys[i].C_Str(), key, mKeys[i].length ) ) {
+            if (0 == strncmp(mKeys[i].C_Str(), key, mKeys[i].length)) {
                 return true;
                 return true;
             }
             }
         }
         }
@@ -395,7 +406,6 @@ struct aiMetadata {
     }
     }
 
 
 #endif // __cplusplus
 #endif // __cplusplus
-
 };
 };
 
 
 #endif // AI_METADATA_H_INC
 #endif // AI_METADATA_H_INC

+ 4 - 4
packaging/windows-innosetup/script_x64.iss

@@ -2,7 +2,7 @@
 
 
 [Setup]
 [Setup]
 AppName=Open Asset Import Library - SDK
 AppName=Open Asset Import Library - SDK
-AppVerName=Open Asset Import Library - SDK (v5.0.0)
+AppVerName=Open Asset Import Library - SDK (v5.0.1)
 DefaultDirName={pf}\Assimp
 DefaultDirName={pf}\Assimp
 DefaultGroupName=Assimp
 DefaultGroupName=Assimp
 UninstallDisplayIcon={app}\bin\x64\assimp.exe
 UninstallDisplayIcon={app}\bin\x64\assimp.exe
@@ -12,9 +12,9 @@ SetupIconFile=..\..\tools\shared\assimp_tools_icon.ico
 WizardImageFile=compiler:WizModernImage-IS.BMP
 WizardImageFile=compiler:WizModernImage-IS.BMP
 WizardSmallImageFile=compiler:WizModernSmallImage-IS.BMP
 WizardSmallImageFile=compiler:WizModernSmallImage-IS.BMP
 LicenseFile=License.rtf
 LicenseFile=License.rtf
-OutputBaseFileName=assimp-sdk-5.0.0-setup
-VersionInfoVersion=5.0.0.0
-VersionInfoTextVersion=5.0.0
+OutputBaseFileName=assimp-sdk-5.0.1-setup
+VersionInfoVersion=5.0.1.0
+VersionInfoTextVersion=5.0.1
 VersionInfoCompany=Assimp Development Team
 VersionInfoCompany=Assimp Development Team
 ArchitecturesInstallIn64BitMode=x64
 ArchitecturesInstallIn64BitMode=x64
 
 

+ 4 - 4
packaging/windows-innosetup/script_x86.iss

@@ -2,7 +2,7 @@
 
 
 [Setup]
 [Setup]
 AppName=Open Asset Import Library - SDK
 AppName=Open Asset Import Library - SDK
-AppVerName=Open Asset Import Library - SDK (v5.0.0)
+AppVerName=Open Asset Import Library - SDK (v5.0.1)
 DefaultDirName={pf}\Assimp
 DefaultDirName={pf}\Assimp
 DefaultGroupName=Assimp
 DefaultGroupName=Assimp
 UninstallDisplayIcon={app}\bin\x86\assimp.exe
 UninstallDisplayIcon={app}\bin\x86\assimp.exe
@@ -12,9 +12,9 @@ SetupIconFile=..\..\tools\shared\assimp_tools_icon.ico
 WizardImageFile=compiler:WizModernImage-IS.BMP
 WizardImageFile=compiler:WizModernImage-IS.BMP
 WizardSmallImageFile=compiler:WizModernSmallImage-IS.BMP
 WizardSmallImageFile=compiler:WizModernSmallImage-IS.BMP
 LicenseFile=License.rtf
 LicenseFile=License.rtf
-OutputBaseFileName=assimp-sdk-5.0.0-setup
-VersionInfoVersion=4.1.0.0
-VersionInfoTextVersion=4.1.0
+OutputBaseFileName=assimp-sdk-5.0.1-setup
+VersionInfoVersion=5.0.1.0
+VersionInfoTextVersion=5.0.1
 VersionInfoCompany=Assimp Development Team
 VersionInfoCompany=Assimp Development Team
 ;ArchitecturesInstallIn64BitMode=x64
 ;ArchitecturesInstallIn64BitMode=x64
 
 

+ 12 - 6
samples/SimpleOpenGL/CMakeLists.txt

@@ -1,3 +1,5 @@
+SET(SAMPLE_PROJECT_NAME assimp_simpleogl)
+
 FIND_PACKAGE(OpenGL)
 FIND_PACKAGE(OpenGL)
 FIND_PACKAGE(GLUT)
 FIND_PACKAGE(GLUT)
 IF ( MSVC )
 IF ( MSVC )
@@ -16,6 +18,10 @@ IF ( NOT GLUT_FOUND )
   ENDIF ()
   ENDIF ()
 ENDIF ()
 ENDIF ()
 
 
+# Used for usage and error messages in the program.
+ADD_COMPILE_DEFINITIONS(ASSIMP_VERSION="${ASSIMP_VERSION}")
+ADD_COMPILE_DEFINITIONS(PROJECT_NAME="${SAMPLE_PROJECT_NAME}")
+
 if ( MSVC )
 if ( MSVC )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
@@ -34,17 +40,17 @@ LINK_DIRECTORIES(
   ${Assimp_BINARY_DIR}/lib
   ${Assimp_BINARY_DIR}/lib
 )
 )
 
 
-ADD_EXECUTABLE( assimp_simpleogl
+ADD_EXECUTABLE( ${SAMPLE_PROJECT_NAME}
   Sample_SimpleOpenGL.c
   Sample_SimpleOpenGL.c
 )
 )
 
 
-SET_PROPERTY(TARGET assimp_simpleogl PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
+SET_PROPERTY(TARGET ${SAMPLE_PROJECT_NAME} PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
 
 
-TARGET_LINK_LIBRARIES( assimp_simpleogl assimp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${M_LIB} )
-SET_TARGET_PROPERTIES( assimp_simpleogl PROPERTIES
-  OUTPUT_NAME assimp_simpleogl
+TARGET_LINK_LIBRARIES( ${SAMPLE_PROJECT_NAME} assimp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} ${M_LIB} )
+SET_TARGET_PROPERTIES( ${SAMPLE_PROJECT_NAME} PROPERTIES
+  OUTPUT_NAME ${SAMPLE_PROJECT_NAME}
 )
 )
 
 
-INSTALL( TARGETS assimp_simpleogl
+INSTALL( TARGETS ${SAMPLE_PROJECT_NAME}
   DESTINATION "${ASSIMP_BIN_INSTALL_DIR}" COMPONENT assimp-dev
   DESTINATION "${ASSIMP_BIN_INSTALL_DIR}" COMPONENT assimp-dev
 )
 )

+ 72 - 12
samples/SimpleOpenGL/Sample_SimpleOpenGL.c

@@ -15,9 +15,9 @@
 #include <stdio.h>
 #include <stdio.h>
 
 
 #ifdef __APPLE__
 #ifdef __APPLE__
-#include <glut.h>
+#include <freeglut.h>
 #else
 #else
-#include <GL/glut.h>
+#include <GL/freeglut.h>
 #endif
 #endif
 
 
 /* assimp include files. These three are usually needed. */
 /* assimp include files. These three are usually needed. */
@@ -25,6 +25,39 @@
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>
 
 
+#define COMMAND_USAGE "--usage"
+
+/* ---------------------------------------------------------------------------- */
+inline static void print_run_command(const char* command_name) {
+	printf("Run '%s %s' for more information.\n", 
+		PROJECT_NAME, command_name);
+}
+
+/* ---------------------------------------------------------------------------- */
+inline static void print_error(const char* msg) {
+	printf("ERROR: %s\n", msg);
+}
+
+#define NEW_LINE "\n"
+#define DOUBLE_NEW_LINE NEW_LINE NEW_LINE
+
+/* ---------------------------------------------------------------------------- */
+inline static void print_usage() {
+	static const char* usage_format = 
+		"Usage: "
+		PROJECT_NAME
+		" <file>"	 DOUBLE_NEW_LINE
+		"where:"	 DOUBLE_NEW_LINE
+		"  %-10s %s" DOUBLE_NEW_LINE
+		"options:"	 DOUBLE_NEW_LINE
+		"  %-10s %s" DOUBLE_NEW_LINE;
+	printf(usage_format,
+		// where
+		"file", "The input model file to load.",
+		// options
+		COMMAND_USAGE, "Display usage.");
+}
+
 /* the global Assimp scene object */
 /* the global Assimp scene object */
 const C_STRUCT aiScene* scene = NULL;
 const C_STRUCT aiScene* scene = NULL;
 GLuint scene_list = 0;
 GLuint scene_list = 0;
@@ -245,7 +278,7 @@ void do_motion (void)
 	static int frames = 0;
 	static int frames = 0;
 
 
 	int time = glutGet(GLUT_ELAPSED_TIME);
 	int time = glutGet(GLUT_ELAPSED_TIME);
-	angle += (time-prev_time)*0.01;
+	angle += static_cast<float>((time-prev_time)*0.01);
 	prev_time = time;
 	prev_time = time;
 
 
 	frames += 1;
 	frames += 1;
@@ -324,12 +357,42 @@ int loadasset (const char* path)
 /* ---------------------------------------------------------------------------- */
 /* ---------------------------------------------------------------------------- */
 int main(int argc, char **argv)
 int main(int argc, char **argv)
 {
 {
+	const char* model_file = NULL;
 	C_STRUCT aiLogStream stream;
 	C_STRUCT aiLogStream stream;
 
 
+	if (argc < 2) {
+		print_error("No input model file specifed.");
+		print_run_command(COMMAND_USAGE);
+		return EXIT_FAILURE;
+	}
+
+	// Find and execute available commands entered by the user.
+	for (int i = 1; i < argc; ++i) {
+		if (!strncmp(argv[i], COMMAND_USAGE, strlen(COMMAND_USAGE))) {
+			print_usage();
+			return EXIT_SUCCESS;
+		}
+	}
+
+	// Check and validate the specified model file extension.
+	model_file = argv[1];
+	const char* extension = strchr(model_file, '.');
+	if (!extension) {
+		print_error("Please provide a file with a valid extension.");
+		return EXIT_FAILURE;
+	}
+
+	if (AI_FALSE == aiIsExtensionSupported(extension)) {
+		print_error("The specified model file extension is currently "
+			"unsupported in Assimp " ASSIMP_VERSION ".");
+		return EXIT_FAILURE;
+	}
+
 	glutInitWindowSize(900,600);
 	glutInitWindowSize(900,600);
 	glutInitWindowPosition(100,100);
 	glutInitWindowPosition(100,100);
 	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
 	glutInitDisplayMode(GLUT_RGB | GLUT_DOUBLE | GLUT_DEPTH);
 	glutInit(&argc, argv);
 	glutInit(&argc, argv);
+	glutSetOption(GLUT_ACTION_ON_WINDOW_CLOSE, GLUT_ACTION_GLUTMAINLOOP_RETURNS);
 
 
 	glutCreateWindow("Assimp - Very simple OpenGL sample");
 	glutCreateWindow("Assimp - Very simple OpenGL sample");
 	glutDisplayFunc(display);
 	glutDisplayFunc(display);
@@ -346,14 +409,11 @@ int main(int argc, char **argv)
 	stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt");
 	stream = aiGetPredefinedLogStream(aiDefaultLogStream_FILE,"assimp_log.txt");
 	aiAttachLogStream(&stream);
 	aiAttachLogStream(&stream);
 
 
-	/* the model name can be specified on the command line. If none
-	  is specified, we try to locate one of the more expressive test
-	  models from the repository (/models-nonbsd may be missing in
-	  some distributions so we need a fallback from /models!). */
-	if( 0 != loadasset( argc >= 2 ? argv[1] : "../../test/models-nonbsd/X/dwarf.x")) {
-		if( argc != 1 || (0 != loadasset( "../../../../test/models-nonbsd/X/dwarf.x") && 0 != loadasset( "../../test/models/X/Testwuson.X"))) {
-			return -1;
-		}
+	// Load the model file.
+	if(0 != loadasset(model_file)) {
+		print_error("Failed to load model. Please ensure that the specified file exists.");
+		aiDetachAllLogStreams();
+		return EXIT_FAILURE;
 	}
 	}
 
 
 	glClearColor(0.1f,0.1f,0.1f,1.f);
 	glClearColor(0.1f,0.1f,0.1f,1.f);
@@ -384,5 +444,5 @@ int main(int argc, char **argv)
 	   again. This will definitely release the last resources allocated
 	   again. This will definitely release the last resources allocated
 	   by Assimp.*/
 	   by Assimp.*/
 	aiDetachAllLogStreams();
 	aiDetachAllLogStreams();
-	return 0;
+	return EXIT_SUCCESS;
 }
 }

+ 24 - 24
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h

@@ -31,40 +31,40 @@ struct Texture {
 
 
 class Mesh {
 class Mesh {
 public:
 public:
-    std::vector<VERTEX> vertices;
-    std::vector<UINT> indices;
-    std::vector<Texture> textures;
-    ID3D11Device *dev;
+    std::vector<VERTEX> vertices_;
+    std::vector<UINT> indices_;
+    std::vector<Texture> textures_;
+    ID3D11Device *dev_;
 
 
     Mesh(ID3D11Device *dev, const std::vector<VERTEX>& vertices, const std::vector<UINT>& indices, const std::vector<Texture>& textures) :
     Mesh(ID3D11Device *dev, const std::vector<VERTEX>& vertices, const std::vector<UINT>& indices, const std::vector<Texture>& textures) :
-            vertices(vertices),
-            indices(indices),
-            textures(textures),
-            dev(dev),
-            VertexBuffer(nullptr),
-            IndexBuffer(nullptr) {
-        this->setupMesh(this->dev);
+            vertices_(vertices),
+            indices_(indices),
+            textures_(textures),
+            dev_(dev),
+            VertexBuffer_(nullptr),
+            IndexBuffer_(nullptr) {
+        this->setupMesh(this->dev_);
     }
     }
 
 
     void Draw(ID3D11DeviceContext *devcon) {
     void Draw(ID3D11DeviceContext *devcon) {
         UINT stride = sizeof(VERTEX);
         UINT stride = sizeof(VERTEX);
         UINT offset = 0;
         UINT offset = 0;
 
 
-        devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
-        devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
+        devcon->IASetVertexBuffers(0, 1, &VertexBuffer_, &stride, &offset);
+        devcon->IASetIndexBuffer(IndexBuffer_, DXGI_FORMAT_R32_UINT, 0);
 
 
-        devcon->PSSetShaderResources(0, 1, &textures[0].texture);
+        devcon->PSSetShaderResources(0, 1, &textures_[0].texture);
 
 
-        devcon->DrawIndexed(static_cast<UINT>(indices.size()), 0, 0);
+        devcon->DrawIndexed(static_cast<UINT>(indices_.size()), 0, 0);
     }
     }
 
 
     void Close() {
     void Close() {
-        SafeRelease(VertexBuffer);
-        SafeRelease(IndexBuffer);
+        SafeRelease(VertexBuffer_);
+        SafeRelease(IndexBuffer_);
     }
     }
 private:
 private:
     // Render data
     // Render data
-    ID3D11Buffer *VertexBuffer, *IndexBuffer;
+    ID3D11Buffer *VertexBuffer_, *IndexBuffer_;
 
 
     // Functions
     // Functions
     // Initializes all the buffer objects/arrays
     // Initializes all the buffer objects/arrays
@@ -73,15 +73,15 @@ private:
 
 
         D3D11_BUFFER_DESC vbd;
         D3D11_BUFFER_DESC vbd;
         vbd.Usage = D3D11_USAGE_IMMUTABLE;
         vbd.Usage = D3D11_USAGE_IMMUTABLE;
-        vbd.ByteWidth = static_cast<UINT>(sizeof(VERTEX) * vertices.size());
+        vbd.ByteWidth = static_cast<UINT>(sizeof(VERTEX) * vertices_.size());
         vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
         vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
         vbd.CPUAccessFlags = 0;
         vbd.CPUAccessFlags = 0;
         vbd.MiscFlags = 0;
         vbd.MiscFlags = 0;
 
 
         D3D11_SUBRESOURCE_DATA initData;
         D3D11_SUBRESOURCE_DATA initData;
-        initData.pSysMem = &vertices[0];
+        initData.pSysMem = &vertices_[0];
 
 
-        hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer);
+        hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer_);
         if (FAILED(hr)) {
         if (FAILED(hr)) {
             Close();
             Close();
             throw std::runtime_error("Failed to create vertex buffer.");
             throw std::runtime_error("Failed to create vertex buffer.");
@@ -89,14 +89,14 @@ private:
 
 
         D3D11_BUFFER_DESC ibd;
         D3D11_BUFFER_DESC ibd;
         ibd.Usage = D3D11_USAGE_IMMUTABLE;
         ibd.Usage = D3D11_USAGE_IMMUTABLE;
-        ibd.ByteWidth = static_cast<UINT>(sizeof(UINT) * indices.size());
+        ibd.ByteWidth = static_cast<UINT>(sizeof(UINT) * indices_.size());
         ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
         ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
         ibd.CPUAccessFlags = 0;
         ibd.CPUAccessFlags = 0;
         ibd.MiscFlags = 0;
         ibd.MiscFlags = 0;
 
 
-        initData.pSysMem = &indices[0];
+        initData.pSysMem = &indices_[0];
 
 
-        hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer);
+        hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer_);
         if (FAILED(hr)) {
         if (FAILED(hr)) {
             Close();
             Close();
             throw std::runtime_error("Failed to create index buffer.");
             throw std::runtime_error("Failed to create index buffer.");

+ 27 - 27
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp

@@ -1,12 +1,12 @@
 #include "ModelLoader.h"
 #include "ModelLoader.h"
 
 
 ModelLoader::ModelLoader() : 
 ModelLoader::ModelLoader() : 
-        dev(nullptr),
-        devcon(nullptr),
-        meshes(),
-        directory(),
-        textures_loaded(),
-        hwnd(nullptr) {
+        dev_(nullptr),
+        devcon_(nullptr),
+        meshes_(),
+        directory_(),
+        textures_loaded_(),
+        hwnd_(nullptr) {
     // empty
     // empty
 }
 }
 
 
@@ -22,14 +22,14 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc
 		aiProcess_Triangulate |
 		aiProcess_Triangulate |
 		aiProcess_ConvertToLeftHanded);
 		aiProcess_ConvertToLeftHanded);
 
 
-	if (pScene == NULL)
+	if (pScene == nullptr)
 		return false;
 		return false;
 
 
-	this->directory = filename.substr(0, filename.find_last_of("/\\"));
+	this->directory_ = filename.substr(0, filename.find_last_of("/\\"));
 
 
-	this->dev = dev;
-	this->devcon = devcon;
-	this->hwnd = hwnd;
+	this->dev_ = dev;
+	this->devcon_ = devcon;
+	this->hwnd_ = hwnd;
 
 
 	processNode(pScene->mRootNode, pScene);
 	processNode(pScene->mRootNode, pScene);
 
 
@@ -37,8 +37,8 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc
 }
 }
 
 
 void ModelLoader::Draw(ID3D11DeviceContext * devcon) {
 void ModelLoader::Draw(ID3D11DeviceContext * devcon) {
-	for (int i = 0; i < meshes.size(); ++i ) {
-		meshes[i].Draw(devcon);
+	for (size_t i = 0; i < meshes_.size(); ++i ) {
+		meshes_[i].Draw(devcon);
 	}
 	}
 }
 }
 
 
@@ -88,7 +88,7 @@ Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) {
 		textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
 		textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
 	}
 	}
 
 
-	return Mesh(dev, vertices, indices, textures);
+	return Mesh(dev_, vertices, indices, textures);
 }
 }
 
 
 std::vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, std::string typeName, const aiScene * scene) {
 std::vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, std::string typeName, const aiScene * scene) {
@@ -98,9 +98,9 @@ std::vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextu
 		mat->GetTexture(type, i, &str);
 		mat->GetTexture(type, i, &str);
 		// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
 		// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
 		bool skip = false;
 		bool skip = false;
-		for (UINT j = 0; j < textures_loaded.size(); j++) {
-			if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0) {
-				textures.push_back(textures_loaded[j]);
+		for (UINT j = 0; j < textures_loaded_.size(); j++) {
+			if (std::strcmp(textures_loaded_[j].path.c_str(), str.C_Str()) == 0) {
+				textures.push_back(textures_loaded_[j]);
 				skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
 				skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
 				break;
 				break;
 			}
 			}
@@ -113,34 +113,34 @@ std::vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextu
 				texture.texture = getTextureFromModel(scene, textureindex);
 				texture.texture = getTextureFromModel(scene, textureindex);
 			} else {
 			} else {
 				std::string filename = std::string(str.C_Str());
 				std::string filename = std::string(str.C_Str());
-				filename = directory + '/' + filename;
+				filename = directory_ + '/' + filename;
 				std::wstring filenamews = std::wstring(filename.begin(), filename.end());
 				std::wstring filenamews = std::wstring(filename.begin(), filename.end());
-				hr = CreateWICTextureFromFile(dev, devcon, filenamews.c_str(), nullptr, &texture.texture);
+				hr = CreateWICTextureFromFile(dev_, devcon_, filenamews.c_str(), nullptr, &texture.texture);
 				if (FAILED(hr))
 				if (FAILED(hr))
-					MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
+					MessageBox(hwnd_, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
 			}
 			}
 			texture.type = typeName;
 			texture.type = typeName;
 			texture.path = str.C_Str();
 			texture.path = str.C_Str();
 			textures.push_back(texture);
 			textures.push_back(texture);
-			this->textures_loaded.push_back(texture);  // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
+			this->textures_loaded_.push_back(texture);  // Store it as texture loaded for entire model, to ensure we won't unnecesery load duplicate textures.
 		}
 		}
 	}
 	}
 	return textures;
 	return textures;
 }
 }
 
 
 void ModelLoader::Close() {
 void ModelLoader::Close() {
-	for (auto& t : textures_loaded)
+	for (auto& t : textures_loaded_)
 		t.Release();
 		t.Release();
 
 
-	for (int i = 0; i < meshes.size(); i++) {
-		meshes[i].Close();
+	for (size_t i = 0; i < meshes_.size(); i++) {
+		meshes_[i].Close();
 	}
 	}
 }
 }
 
 
 void ModelLoader::processNode(aiNode * node, const aiScene * scene) {
 void ModelLoader::processNode(aiNode * node, const aiScene * scene) {
 	for (UINT i = 0; i < node->mNumMeshes; i++) {
 	for (UINT i = 0; i < node->mNumMeshes; i++) {
 		aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
 		aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
-		meshes.push_back(this->processMesh(mesh, scene));
+		meshes_.push_back(this->processMesh(mesh, scene));
 	}
 	}
 
 
 	for (UINT i = 0; i < node->mNumChildren; i++) {
 	for (UINT i = 0; i < node->mNumChildren; i++) {
@@ -179,9 +179,9 @@ ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scen
 
 
 	int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth);
 	int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth);
 
 
-	hr = CreateWICTextureFromMemory(dev, devcon, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture);
+	hr = CreateWICTextureFromMemory(dev_, devcon_, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture);
 	if (FAILED(hr))
 	if (FAILED(hr))
-		MessageBox(hwnd, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
+		MessageBox(hwnd_, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);
 
 
 	return texture;
 	return texture;
 }
 }

+ 6 - 6
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h

@@ -25,12 +25,12 @@ public:
 
 
 	void Close();
 	void Close();
 private:
 private:
-	ID3D11Device *dev;
-	ID3D11DeviceContext *devcon;
-	std::vector<Mesh> meshes;
-	std::string directory;
-	std::vector<Texture> textures_loaded;
-	HWND hwnd;
+	ID3D11Device *dev_;
+	ID3D11DeviceContext *devcon_;
+	std::vector<Mesh> meshes_;
+	std::string directory_;
+	std::vector<Texture> textures_loaded_;
+	HWND hwnd_;
 
 
 	void processNode(aiNode* node, const aiScene* scene);
 	void processNode(aiNode* node, const aiScene* scene);
 	Mesh processMesh(aiMesh* mesh, const aiScene* scene);
 	Mesh processMesh(aiMesh* mesh, const aiScene* scene);

+ 31 - 31
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp

@@ -56,7 +56,7 @@ const char g_szClassName[] = "directxWindowClass";
 static std::string g_ModelPath;
 static std::string g_ModelPath;
 
 
 UINT width, height;
 UINT width, height;
-HWND hwnd = nullptr;
+HWND g_hwnd = nullptr;
 
 
 // ------------------------------------------------------------
 // ------------------------------------------------------------
 //                        DirectX Variables
 //                        DirectX Variables
@@ -120,13 +120,13 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 	return 0;
 	return 0;
 }
 }
 
 
-int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-	LPWSTR lpCmdLine, int nCmdShow)
+int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/,
+	LPWSTR /*lpCmdLine*/, int nCmdShow)
 {
 {
 	int argc;
 	int argc;
 	LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
 	LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
 	if (!argv) {
 	if (!argv) {
-		MessageBox(NULL, 
+		MessageBox(nullptr, 
 			TEXT("An error occured while reading command line arguments."),
 			TEXT("An error occured while reading command line arguments."),
 			TEXT("Error!"),
 			TEXT("Error!"),
 			MB_ICONERROR | MB_OK);
 			MB_ICONERROR | MB_OK);
@@ -143,7 +143,7 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 
 
 	// Ensure that a model file has been specified.
 	// Ensure that a model file has been specified.
 	if (argc < 2) {
 	if (argc < 2) {
-		MessageBox(NULL, 
+		MessageBox(nullptr, 
 			TEXT("No model file specified. The program will now close."), 
 			TEXT("No model file specified. The program will now close."), 
 			TEXT("Error!"),
 			TEXT("Error!"),
 			MB_ICONERROR | MB_OK);
 			MB_ICONERROR | MB_OK);
@@ -165,16 +165,16 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 	wc.cbClsExtra = 0;
 	wc.cbClsExtra = 0;
 	wc.cbWndExtra = 0;
 	wc.cbWndExtra = 0;
 	wc.hInstance = hInstance;
 	wc.hInstance = hInstance;
-	wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
-	wc.hCursor = LoadCursor(NULL, IDC_ARROW);
-	wc.hbrBackground = NULL;
-	wc.lpszMenuName = NULL;
+	wc.hIcon = LoadIcon(nullptr, IDI_APPLICATION);
+	wc.hCursor = LoadCursor(nullptr, IDC_ARROW);
+	wc.hbrBackground = nullptr;
+	wc.lpszMenuName = nullptr;
 	wc.lpszClassName = g_szClassName;
 	wc.lpszClassName = g_szClassName;
-	wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
+	wc.hIconSm = LoadIcon(nullptr, IDI_APPLICATION);
 
 
 	if (!RegisterClassEx(&wc))
 	if (!RegisterClassEx(&wc))
 	{
 	{
-		MessageBox(NULL, "Window Registration Failed!", "Error!",
+		MessageBox(nullptr, "Window Registration Failed!", "Error!",
 			MB_ICONEXCLAMATION | MB_OK);
 			MB_ICONEXCLAMATION | MB_OK);
 		return 0;
 		return 0;
 	}
 	}
@@ -182,35 +182,35 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 	RECT wr = { 0,0, SCREEN_WIDTH, SCREEN_HEIGHT };
 	RECT wr = { 0,0, SCREEN_WIDTH, SCREEN_HEIGHT };
 	AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
 	AdjustWindowRect(&wr, WS_OVERLAPPEDWINDOW, FALSE);
 
 
-	hwnd = CreateWindowEx(
+	g_hwnd = CreateWindowEx(
 		WS_EX_CLIENTEDGE,
 		WS_EX_CLIENTEDGE,
 		g_szClassName,
 		g_szClassName,
 		" Simple Textured Directx11 Sample ",
 		" Simple Textured Directx11 Sample ",
 		WS_OVERLAPPEDWINDOW,
 		WS_OVERLAPPEDWINDOW,
 		CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top,
 		CW_USEDEFAULT, CW_USEDEFAULT, wr.right - wr.left, wr.bottom - wr.top,
-		NULL, NULL, hInstance, NULL
+		nullptr, nullptr, hInstance, nullptr
 	);
 	);
 
 
-	if (hwnd == NULL)
+	if (g_hwnd == nullptr)
 	{
 	{
-		MessageBox(NULL, "Window Creation Failed!", "Error!",
+		MessageBox(nullptr, "Window Creation Failed!", "Error!",
 			MB_ICONEXCLAMATION | MB_OK);
 			MB_ICONEXCLAMATION | MB_OK);
 		return 0;
 		return 0;
 	}
 	}
 
 
-	ShowWindow(hwnd, nCmdShow);
-	UpdateWindow(hwnd);
+	ShowWindow(g_hwnd, nCmdShow);
+	UpdateWindow(g_hwnd);
 
 
 	width = wr.right - wr.left;
 	width = wr.right - wr.left;
 	height = wr.bottom - wr.top;
 	height = wr.bottom - wr.top;
 
 
 	try {
 	try {
-		InitD3D(hInstance, hwnd);
+		InitD3D(hInstance, g_hwnd);
 
 
 		while (true)
 		while (true)
 		{
 		{
 
 
-			if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+			if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
 			{
 			{
 				TranslateMessage(&msg);
 				TranslateMessage(&msg);
 				DispatchMessage(&msg);
 				DispatchMessage(&msg);
@@ -225,17 +225,17 @@ int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 		CleanD3D();
 		CleanD3D();
 		return static_cast<int>(msg.wParam);
 		return static_cast<int>(msg.wParam);
 	} catch (const std::exception& e) {
 	} catch (const std::exception& e) {
-		MessageBox(hwnd, e.what(), TEXT("Error!"), MB_ICONERROR | MB_OK);
+		MessageBox(g_hwnd, e.what(), TEXT("Error!"), MB_ICONERROR | MB_OK);
 		CleanD3D();
 		CleanD3D();
 		return EXIT_FAILURE;
 		return EXIT_FAILURE;
 	} catch (...) {
 	} catch (...) {
-		MessageBox(hwnd, TEXT("Caught an unknown exception."), TEXT("Error!"), MB_ICONERROR | MB_OK);
+		MessageBox(g_hwnd, TEXT("Caught an unknown exception."), TEXT("Error!"), MB_ICONERROR | MB_OK);
 		CleanD3D();
 		CleanD3D();
 		return EXIT_FAILURE;
 		return EXIT_FAILURE;
 	}
 	}
 }
 }
 
 
-void InitD3D(HINSTANCE hinstance, HWND hWnd)
+void InitD3D(HINSTANCE /*hinstance*/, HWND hWnd)
 {
 {
 	HRESULT hr;
 	HRESULT hr;
 
 
@@ -362,7 +362,7 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 	}
 	}
 
 
 	// Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut
 	// Note this tutorial doesn't handle full-screen swapchains so we block the ALT+ENTER shortcut
-	dxgiFactory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
+	dxgiFactory->MakeWindowAssociation(g_hwnd, DXGI_MWA_NO_ALT_ENTER);
 
 
 	dxgiFactory->Release();
 	dxgiFactory->Release();
 
 
@@ -372,7 +372,7 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 	ID3D11Texture2D *pBackBuffer;
 	ID3D11Texture2D *pBackBuffer;
 	swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
 	swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
 
 
-	dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
+	dev->CreateRenderTargetView(pBackBuffer, nullptr, &backbuffer);
 	pBackBuffer->Release();
 	pBackBuffer->Release();
 
 
 	D3D11_TEXTURE2D_DESC descDepth;
 	D3D11_TEXTURE2D_DESC descDepth;
@@ -440,7 +440,7 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 void CleanD3D(void)
 void CleanD3D(void)
 {
 {
 	if (swapchain)
 	if (swapchain)
-		swapchain->SetFullscreenState(FALSE, NULL);
+		swapchain->SetFullscreenState(FALSE, nullptr);
 
 
 	if (ourModel) {
 	if (ourModel) {
 		ourModel->Close();
 		ourModel->Close();
@@ -513,8 +513,8 @@ void InitPipeline()
 	if(FAILED(CompileShaderFromFile(SHADER_PATH PIXEL_SHADER_FILE, 0, "main", "ps_4_0", &PS)))
 	if(FAILED(CompileShaderFromFile(SHADER_PATH PIXEL_SHADER_FILE, 0, "main", "ps_4_0", &PS)))
 		Throwanerror(UTFConverter(L"Failed to compile shader from file " PIXEL_SHADER_FILE).c_str());
 		Throwanerror(UTFConverter(L"Failed to compile shader from file " PIXEL_SHADER_FILE).c_str());
 
 
-	dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
-	dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
+	dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), nullptr, &pVS);
+	dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), nullptr, &pPS);
 
 
 	D3D11_INPUT_ELEMENT_DESC ied[] =
 	D3D11_INPUT_ELEMENT_DESC ied[] =
 	{
 	{
@@ -564,7 +564,7 @@ void InitGraphics()
 	m_View = XMMatrixLookAtLH(Eye, At, Up);
 	m_View = XMMatrixLookAtLH(Eye, At, Up);
 
 
 	ourModel = new ModelLoader;
 	ourModel = new ModelLoader;
-	if (!ourModel->Load(hwnd, dev, devcon, g_ModelPath))
+	if (!ourModel->Load(g_hwnd, dev, devcon, g_ModelPath))
 		Throwanerror("Model couldn't be loaded");
 		Throwanerror("Model couldn't be loaded");
 }
 }
 
 
@@ -576,16 +576,16 @@ HRESULT	CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefine
 	compileFlags |= D3DCOMPILE_DEBUG;
 	compileFlags |= D3DCOMPILE_DEBUG;
 #endif
 #endif
 
 
-	ID3DBlob* pErrorBlob = NULL;
+	ID3DBlob* pErrorBlob = nullptr;
 
 
 	HRESULT result = D3DCompileFromFile(pFileName, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntryPoint, pShaderModel, compileFlags, 0, ppBytecodeBlob, &pErrorBlob);
 	HRESULT result = D3DCompileFromFile(pFileName, pDefines, D3D_COMPILE_STANDARD_FILE_INCLUDE, pEntryPoint, pShaderModel, compileFlags, 0, ppBytecodeBlob, &pErrorBlob);
 	if (FAILED(result))
 	if (FAILED(result))
 	{
 	{
-		if (pErrorBlob != NULL)
+		if (pErrorBlob != nullptr)
 			OutputDebugStringA((LPCSTR)pErrorBlob->GetBufferPointer());
 			OutputDebugStringA((LPCSTR)pErrorBlob->GetBufferPointer());
 	}
 	}
 
 
-	if (pErrorBlob != NULL)
+	if (pErrorBlob != nullptr)
 		pErrorBlob->Release();
 		pErrorBlob->Release();
 
 
 	return result;
 	return result;

+ 1 - 2
samples/SimpleTexturedOpenGL/CMakeLists.txt

@@ -17,7 +17,6 @@ if ( MSVC )
 endif ()
 endif ()
 
 
 INCLUDE_DIRECTORIES(
 INCLUDE_DIRECTORIES(
-  ${Assimp_SOURCE_DIR}/include
   ${Assimp_SOURCE_DIR}/code
   ${Assimp_SOURCE_DIR}/code
   ${OPENGL_INCLUDE_DIR}
   ${OPENGL_INCLUDE_DIR}
   ${GLUT_INCLUDE_DIR}
   ${GLUT_INCLUDE_DIR}
@@ -30,7 +29,6 @@ LINK_DIRECTORIES(
 )
 )
 
 
 ADD_EXECUTABLE( assimp_simpletexturedogl WIN32
 ADD_EXECUTABLE( assimp_simpletexturedogl WIN32
-  SimpleTexturedOpenGL/include/boost_includes.h
   SimpleTexturedOpenGL/src/model_loading.cpp
   SimpleTexturedOpenGL/src/model_loading.cpp
   ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp
   ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp
   ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h
   ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h
@@ -47,3 +45,4 @@ SET_TARGET_PROPERTIES( assimp_simpletexturedogl PROPERTIES
 INSTALL( TARGETS assimp_simpletexturedogl
 INSTALL( TARGETS assimp_simpletexturedogl
   DESTINATION "${ASSIMP_BIN_INSTALL_DIR}" COMPONENT assimp-dev
   DESTINATION "${ASSIMP_BIN_INSTALL_DIR}" COMPONENT assimp-dev
 )
 )
+

+ 0 - 1
samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/include/boost_includes.h

@@ -1 +0,0 @@
-#include <boost/lexical_cast.hpp>

+ 66 - 64
samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp

@@ -18,8 +18,10 @@
 #include <GL/gl.h>
 #include <GL/gl.h>
 #include <GL/glu.h>
 #include <GL/glu.h>
 
 
+#pragma warning(disable: 4100) // Disable warning 'unreferenced formal parameter'
 #define STB_IMAGE_IMPLEMENTATION
 #define STB_IMAGE_IMPLEMENTATION
 #include "contrib/stb_image/stb_image.h"
 #include "contrib/stb_image/stb_image.h"
+#pragma warning(default: 4100) // Enable warning 'unreferenced formal parameter'
 
 
 #include <fstream>
 #include <fstream>
 
 
@@ -38,10 +40,10 @@
 // The default hard-coded path. Can be overridden by supplying a path through the command line.
 // The default hard-coded path. Can be overridden by supplying a path through the command line.
 static std::string modelpath = "../../test/models/OBJ/spider.obj";
 static std::string modelpath = "../../test/models/OBJ/spider.obj";
 
 
-HGLRC		hRC=NULL;			// Permanent Rendering Context
-HDC			hDC=NULL;			// Private GDI Device Context
-HWND		hWnd=NULL;			// Holds Window Handle
-HINSTANCE	hInstance;	// Holds The Instance Of The Application
+HGLRC       hRC=nullptr;            // Permanent Rendering Context
+HDC         hDC=nullptr;            // Private GDI Device Context
+HWND        g_hWnd=nullptr;         // Holds Window Handle
+HINSTANCE   g_hInstance=nullptr;    // Holds The Instance Of The Application
 
 
 bool		keys[256];			// Array used for Keyboard Routine;
 bool		keys[256];			// Array used for Keyboard Routine;
 bool		active=TRUE;		// Window Active Flag Set To TRUE by Default
 bool		active=TRUE;		// Window Active Flag Set To TRUE by Default
@@ -64,7 +66,7 @@ GLfloat LightPosition[]= { 0.0f, 0.0f, 15.0f, 1.0f };
 
 
 
 
 // the global Assimp scene object
 // the global Assimp scene object
-const aiScene* scene = NULL;
+const aiScene* g_scene = nullptr;
 GLuint scene_list = 0;
 GLuint scene_list = 0;
 aiVector3D scene_min, scene_max, scene_center;
 aiVector3D scene_min, scene_max, scene_center;
 
 
@@ -122,15 +124,15 @@ bool Import3DFromFile( const std::string& pFile)
 	}
 	}
 	else
 	else
 	{
 	{
-		MessageBox(NULL, UTFConverter("Couldn't open file: " + pFile).c_wstr() , TEXT("ERROR"), MB_OK | MB_ICONEXCLAMATION);
+		MessageBox(nullptr, UTFConverter("Couldn't open file: " + pFile).c_wstr() , TEXT("ERROR"), MB_OK | MB_ICONEXCLAMATION);
 		logInfo( importer.GetErrorString());
 		logInfo( importer.GetErrorString());
 		return false;
 		return false;
 	}
 	}
 
 
-	scene = importer.ReadFile( pFile, aiProcessPreset_TargetRealtime_Quality);
+	g_scene = importer.ReadFile(pFile, aiProcessPreset_TargetRealtime_Quality);
 
 
 	// If the import failed, report it
 	// If the import failed, report it
-	if( !scene)
+	if(!g_scene)
 	{
 	{
 		logInfo( importer.GetErrorString());
 		logInfo( importer.GetErrorString());
 		return false;
 		return false;
@@ -179,7 +181,7 @@ void freeTextureIds()
 	if (textureIds)
 	if (textureIds)
 	{
 	{
 		delete[] textureIds;
 		delete[] textureIds;
-		textureIds = NULL;
+		textureIds = nullptr;
 	}
 	}
 }
 }
 
 
@@ -215,7 +217,7 @@ int LoadGLTextures(const aiScene* scene)
 		while (texFound == AI_SUCCESS)
 		while (texFound == AI_SUCCESS)
 		{
 		{
 			texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path);
 			texFound = scene->mMaterials[m]->GetTexture(aiTextureType_DIFFUSE, texIndex, &path);
-			textureIdMap[path.data] = NULL; //fill map with textures, pointers still NULL yet
+			textureIdMap[path.data] = nullptr; //fill map with textures, pointers still NULL yet
 			texIndex++;
 			texIndex++;
 		}
 		}
 	}
 	}
@@ -283,7 +285,7 @@ int LoadGLTextures(const aiScene* scene)
 		else
 		else
 		{
 		{
 			/* Error occurred */
 			/* Error occurred */
-			MessageBox(NULL, UTFConverter("Couldn't load Image: " + fileloc).c_wstr(), TEXT("ERROR"), MB_OK | MB_ICONEXCLAMATION);
+			MessageBox(nullptr, UTFConverter("Couldn't load Image: " + fileloc).c_wstr(), TEXT("ERROR"), MB_OK | MB_ICONEXCLAMATION);
 		}
 		}
 	}
 	}
     // Because we have already copied image data into texture data  we can release memory used by image.
     // Because we have already copied image data into texture data  we can release memory used by image.
@@ -299,7 +301,7 @@ int LoadGLTextures(const aiScene* scene)
 // All Setup For OpenGL goes here
 // All Setup For OpenGL goes here
 int InitGL()
 int InitGL()
 {
 {
-	if (!LoadGLTextures(scene))
+	if (!LoadGLTextures(g_scene))
 	{
 	{
 		return FALSE;
 		return FALSE;
 	}
 	}
@@ -440,12 +442,12 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float
 	// draw all meshes assigned to this node
 	// draw all meshes assigned to this node
 	for (; n < nd->mNumMeshes; ++n)
 	for (; n < nd->mNumMeshes; ++n)
 	{
 	{
-		const struct aiMesh* mesh = scene->mMeshes[nd->mMeshes[n]];
+		const struct aiMesh* mesh = sc->mMeshes[nd->mMeshes[n]];
 
 
 		apply_material(sc->mMaterials[mesh->mMaterialIndex]);
 		apply_material(sc->mMaterials[mesh->mMaterialIndex]);
 
 
 
 
-		if(mesh->mNormals == NULL)
+		if(mesh->mNormals == nullptr)
 		{
 		{
 			glDisable(GL_LIGHTING);
 			glDisable(GL_LIGHTING);
 		}
 		}
@@ -454,7 +456,7 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float
 			glEnable(GL_LIGHTING);
 			glEnable(GL_LIGHTING);
 		}
 		}
 
 
-		if(mesh->mColors[0] != NULL)
+		if(mesh->mColors[0] != nullptr)
 		{
 		{
 			glEnable(GL_COLOR_MATERIAL);
 			glEnable(GL_COLOR_MATERIAL);
 		}
 		}
@@ -480,9 +482,9 @@ void recursive_render (const struct aiScene *sc, const struct aiNode* nd, float
 			for(i = 0; i < face->mNumIndices; i++)		// go through all vertices in face
 			for(i = 0; i < face->mNumIndices; i++)		// go through all vertices in face
 			{
 			{
 				int vertexIndex = face->mIndices[i];	// get group index for current index
 				int vertexIndex = face->mIndices[i];	// get group index for current index
-				if(mesh->mColors[0] != NULL)
+				if(mesh->mColors[0] != nullptr)
 					Color4f(&mesh->mColors[0][vertexIndex]);
 					Color4f(&mesh->mColors[0][vertexIndex]);
-				if(mesh->mNormals != NULL)
+				if(mesh->mNormals != nullptr)
 
 
 					if(mesh->HasTextureCoords(0))		//HasTextureCoords(texture_coordinates_set)
 					if(mesh->HasTextureCoords(0))		//HasTextureCoords(texture_coordinates_set)
 					{
 					{
@@ -527,7 +529,7 @@ int DrawGLScene()				//Here's where we do all the drawing
 	glRotatef(yrot, 0.0f, 1.0f, 0.0f);
 	glRotatef(yrot, 0.0f, 1.0f, 0.0f);
 	glRotatef(zrot, 0.0f, 0.0f, 1.0f);
 	glRotatef(zrot, 0.0f, 0.0f, 1.0f);
 
 
-	drawAiScene(scene);
+	drawAiScene(g_scene);
 
 
 	//xrot+=0.3f;
 	//xrot+=0.3f;
 	yrot+=0.2f;
 	yrot+=0.2f;
@@ -541,50 +543,50 @@ void KillGLWindow()			// Properly Kill The Window
 {
 {
 	if (fullscreen)					// Are We In Fullscreen Mode?
 	if (fullscreen)					// Are We In Fullscreen Mode?
 	{
 	{
-		ChangeDisplaySettings(NULL, 0);		// If So Switch Back To The Desktop
+		ChangeDisplaySettings(nullptr, 0);	// If So Switch Back To The Desktop
 		ShowCursor(TRUE);					// Show Mouse Pointer
 		ShowCursor(TRUE);					// Show Mouse Pointer
 	}
 	}
 
 
 	if (hRC)					// Do We Have A Rendering Context?
 	if (hRC)					// Do We Have A Rendering Context?
 	{
 	{
-		if (!wglMakeCurrent(NULL, NULL))	// Are We Able To Release The DC And RC Contexts?
+		if (!wglMakeCurrent(nullptr, nullptr))	// Are We Able To Release The DC And RC Contexts?
 		{
 		{
-			MessageBox(NULL, TEXT("Release Of DC And RC Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
+			MessageBox(nullptr, TEXT("Release Of DC And RC Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
 		}
 		}
 
 
 		if (!wglDeleteContext(hRC))			// Are We Able To Delete The RC?
 		if (!wglDeleteContext(hRC))			// Are We Able To Delete The RC?
 		{
 		{
-			MessageBox(NULL, TEXT("Release Rendering Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
+			MessageBox(nullptr, TEXT("Release Rendering Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
 		}
 		}
-		hRC = NULL;
+		hRC = nullptr;
 	}
 	}
 
 
 	if (hDC)
 	if (hDC)
 	{
 	{
-		if (!ReleaseDC(hWnd, hDC)) // Are We able to Release The DC?
-			MessageBox(NULL, TEXT("Release Device Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
-		hDC = NULL;
+		if (!ReleaseDC(g_hWnd, hDC)) // Are We able to Release The DC?
+			MessageBox(nullptr, TEXT("Release Device Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
+		hDC = nullptr;
 	}
 	}
 
 
-	if (hWnd)
+	if (g_hWnd)
 	{
 	{
-		if (!DestroyWindow(hWnd)) // Are We Able To Destroy The Window
-			MessageBox(NULL, TEXT("Could Not Release hWnd."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
-		hWnd = NULL;
+		if (!DestroyWindow(g_hWnd)) // Are We Able To Destroy The Window
+			MessageBox(nullptr, TEXT("Could Not Release hWnd."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
+		g_hWnd = nullptr;
 	} 
 	} 
 
 
-	if (hInstance)
+	if (g_hInstance)
 	{
 	{
-		if (!UnregisterClass(TEXT("OpenGL"), hInstance)) // Are We Able To Unregister Class
-			MessageBox(NULL, TEXT("Could Not Unregister Class."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
-		hInstance = NULL;
+		if (!UnregisterClass(TEXT("OpenGL"), g_hInstance)) // Are We Able To Unregister Class
+			MessageBox(nullptr, TEXT("Could Not Unregister Class."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
+		g_hInstance = nullptr;
 	}
 	}
 }
 }
 
 
 GLboolean abortGLInit(const char* abortMessage)
 GLboolean abortGLInit(const char* abortMessage)
 {
 {
 	KillGLWindow();									// Reset Display
 	KillGLWindow();									// Reset Display
-	MessageBox(NULL, UTFConverter(abortMessage).c_wstr(), TEXT("ERROR"), MB_OK|MB_ICONEXCLAMATION);
+	MessageBox(nullptr, UTFConverter(abortMessage).c_wstr(), TEXT("ERROR"), MB_OK|MB_ICONEXCLAMATION);
 	return FALSE;									// quit and return False
 	return FALSE;									// quit and return False
 }
 }
 
 
@@ -602,21 +604,21 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 
 
 	fullscreen = fullscreenflag;
 	fullscreen = fullscreenflag;
 
 
-	hInstance = GetModuleHandle(NULL);	// Grab An Instance For Our Window
+	g_hInstance = GetModuleHandle(nullptr);	// Grab An Instance For Our Window
 	wc.style		= CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window
 	wc.style		= CS_HREDRAW | CS_VREDRAW | CS_OWNDC; // Redraw On Move, And Own DC For Window
 	wc.lpfnWndProc	= (WNDPROC) WndProc;		// WndProc handles Messages
 	wc.lpfnWndProc	= (WNDPROC) WndProc;		// WndProc handles Messages
 	wc.cbClsExtra	= 0;	// No Extra Window Data
 	wc.cbClsExtra	= 0;	// No Extra Window Data
 	wc.cbWndExtra	= 0;	// No Extra Window Data
 	wc.cbWndExtra	= 0;	// No Extra Window Data
-	wc.hInstance	= hInstance;
-	wc.hIcon		= LoadIcon(NULL, IDI_WINLOGO);	// Load The Default Icon
-	wc.hCursor		= LoadCursor(NULL, IDC_ARROW);	// Load the default arrow
-	wc.hbrBackground= NULL;							// No Background required for OpenGL
-	wc.lpszMenuName	= NULL;							// No Menu
+	wc.hInstance	= g_hInstance;
+	wc.hIcon		= LoadIcon(nullptr, IDI_WINLOGO);	// Load The Default Icon
+	wc.hCursor		= LoadCursor(nullptr, IDC_ARROW);	// Load the default arrow
+	wc.hbrBackground= nullptr;						// No Background required for OpenGL
+	wc.lpszMenuName	= nullptr;						// No Menu
 	wc.lpszClassName= TEXT("OpenGL");		        // Class Name
 	wc.lpszClassName= TEXT("OpenGL");		        // Class Name
 
 
 	if (!RegisterClass(&wc))
 	if (!RegisterClass(&wc))
 	{
 	{
-		MessageBox(NULL, TEXT("Failed to register the window class"), TEXT("ERROR"), MB_OK | MB_ICONEXCLAMATION);
+		MessageBox(nullptr, TEXT("Failed to register the window class"), TEXT("ERROR"), MB_OK | MB_ICONEXCLAMATION);
 		return FALSE;		//exit and return false
 		return FALSE;		//exit and return false
 	}
 	}
 
 
@@ -634,14 +636,14 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 		if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
 		if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
 		{
 		{
 			// If The Mode Fails, Offer Two Options.  Quit Or Run In A Window.
 			// If The Mode Fails, Offer Two Options.  Quit Or Run In A Window.
-			if (MessageBox(NULL,TEXT("The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?"),TEXT("NeHe GL"),MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
+			if (MessageBox(nullptr,TEXT("The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?"),TEXT("NeHe GL"),MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
 			{
 			{
 				fullscreen = FALSE;		// Select Windowed Mode (Fullscreen = FALSE)
 				fullscreen = FALSE;		// Select Windowed Mode (Fullscreen = FALSE)
 			}
 			}
 			else
 			else
 			{
 			{
 				//Popup Messagebox: Closing
 				//Popup Messagebox: Closing
-				MessageBox(NULL, TEXT("Program will close now."), TEXT("ERROR"), MB_OK|MB_ICONSTOP);
+				MessageBox(nullptr, TEXT("Program will close now."), TEXT("ERROR"), MB_OK|MB_ICONSTOP);
 				return FALSE; //exit, return false
 				return FALSE; //exit, return false
 			}
 			}
 		}
 		}
@@ -661,7 +663,7 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 
 
 	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requestes Size
 	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requestes Size
 
 
-	if (!(hWnd=CreateWindowEx(	dwExStyle,						// Extended Style For The Window
+	if (nullptr == (g_hWnd=CreateWindowEx(dwExStyle,			// Extended Style For The Window
 								TEXT("OpenGL"),						// Class Name
 								TEXT("OpenGL"),						// Class Name
 								UTFConverter(title).c_wstr(),							// Window Title
 								UTFConverter(title).c_wstr(),							// Window Title
 								WS_CLIPSIBLINGS |				// Required Window Style
 								WS_CLIPSIBLINGS |				// Required Window Style
@@ -670,10 +672,10 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 								0, 0,							// Window Position
 								0, 0,							// Window Position
 								WindowRect.right-WindowRect.left, // Calc adjusted Window Width
 								WindowRect.right-WindowRect.left, // Calc adjusted Window Width
 								WindowRect.bottom-WindowRect.top, // Calc adjustes Window Height
 								WindowRect.bottom-WindowRect.top, // Calc adjustes Window Height
-								NULL,							// No Parent Window
-								NULL,							// No Menu
-								hInstance,						// Instance
-								NULL )))						// Don't pass anything To WM_CREATE
+								nullptr,						// No Parent Window
+								nullptr,						// No Menu
+								g_hInstance,					// Instance
+								nullptr )))						// Don't pass anything To WM_CREATE
 	{
 	{
 		abortGLInit("Window Creation Error.");
 		abortGLInit("Window Creation Error.");
 		return FALSE;
 		return FALSE;
@@ -701,13 +703,13 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 		0, 0, 0											// Layer Masks Ignored
 		0, 0, 0											// Layer Masks Ignored
 	};
 	};
 
 
-	if (!(hDC=GetDC(hWnd)))								// Did we get the Device Context?
+	if (nullptr == (hDC=GetDC(g_hWnd)))					// Did we get the Device Context?
 	{
 	{
 		abortGLInit("Can't Create A GL Device Context.");
 		abortGLInit("Can't Create A GL Device Context.");
 		return FALSE;
 		return FALSE;
 	}
 	}
 
 
-	if (!(PixelFormat=ChoosePixelFormat(hDC, &pfd)))	// Did We Find a matching pixel Format?
+	if (0 == (PixelFormat=ChoosePixelFormat(hDC, &pfd))) // Did We Find a matching pixel Format?
 	{
 	{
 		abortGLInit("Can't Find Suitable PixelFormat");
 		abortGLInit("Can't Find Suitable PixelFormat");
 		return FALSE;
 		return FALSE;
@@ -719,7 +721,7 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 		return FALSE;
 		return FALSE;
 	}
 	}
 
 
-	if (!(hRC=wglCreateContext(hDC)))
+	if (nullptr == (hRC=wglCreateContext(hDC))) 
 	{
 	{
 		abortGLInit("Can't Create A GL Rendering Context.");
 		abortGLInit("Can't Create A GL Rendering Context.");
 		return FALSE;
 		return FALSE;
@@ -733,9 +735,9 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 
 
 	//// *** everything okay ***
 	//// *** everything okay ***
 
 
-	ShowWindow(hWnd, SW_SHOW);		// Show The Window
-	SetForegroundWindow(hWnd);		// Slightly Higher Prio
-	SetFocus(hWnd);					// Sets Keyboard Focus To The Window
+	ShowWindow(g_hWnd, SW_SHOW);	// Show The Window
+	SetForegroundWindow(g_hWnd);	// Slightly Higher Prio
+	SetFocus(g_hWnd);				// Sets Keyboard Focus To The Window
 	ReSizeGLScene(width, height);	// Set Up Our Perspective GL Screen
 	ReSizeGLScene(width, height);	// Set Up Our Perspective GL Screen
 
 
 	if (!InitGL())
 	if (!InitGL())
@@ -753,7 +755,7 @@ void cleanup()
 
 
 	destroyAILogger();
 	destroyAILogger();
 
 
-	if (hWnd)
+	if (g_hWnd)
 		KillGLWindow();
 		KillGLWindow();
 };
 };
 
 
@@ -818,12 +820,12 @@ LRESULT CALLBACK WndProc(HWND hWnd,				// Handles for this Window
 	return DefWindowProc(hWnd, uMsg, wParam, lParam);
 	return DefWindowProc(hWnd, uMsg, wParam, lParam);
 }
 }
 
 
-int WINAPI WinMain( HINSTANCE hInstance,         // The instance
-				   HINSTANCE hPrevInstance,      // Previous instance
-				   LPSTR lpCmdLine,              // Command Line Parameters
-				   int nShowCmd )                // Window Show State
+int WINAPI WinMain( HINSTANCE /*hInstance*/,     // The instance
+				   HINSTANCE /*hPrevInstance*/,  // Previous instance
+				   LPSTR /*lpCmdLine*/,          // Command Line Parameters
+				   int /*nShowCmd*/ )            // Window Show State
 {
 {
-	MSG msg;
+	MSG msg = {};
 	BOOL done=FALSE;
 	BOOL done=FALSE;
 
 
 	createAILogger();
 	createAILogger();
@@ -832,7 +834,7 @@ int WINAPI WinMain( HINSTANCE hInstance,         // The instance
 	// Check the command line for an override file path.
 	// Check the command line for an override file path.
 	int argc;
 	int argc;
 	LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
 	LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
-	if (argv != NULL && argc > 1)
+	if (argv != nullptr && argc > 1)
 	{
 	{
 		std::wstring modelpathW(argv[1]);
 		std::wstring modelpathW(argv[1]);
 		modelpath = UTFConverter(modelpathW).str();
 		modelpath = UTFConverter(modelpathW).str();
@@ -846,7 +848,7 @@ int WINAPI WinMain( HINSTANCE hInstance,         // The instance
 
 
 	logInfo("=============== Post Import ====================");
 	logInfo("=============== Post Import ====================");
 
 
-	if (MessageBox(NULL, TEXT("Would You Like To Run In Fullscreen Mode?"), TEXT("Start Fullscreen?"), MB_YESNO|MB_ICONEXCLAMATION)==IDNO)
+	if (MessageBox(nullptr, TEXT("Would You Like To Run In Fullscreen Mode?"), TEXT("Start Fullscreen?"), MB_YESNO|MB_ICONEXCLAMATION)==IDNO)
 	{
 	{
 		fullscreen=FALSE;
 		fullscreen=FALSE;
 	}
 	}
@@ -859,7 +861,7 @@ int WINAPI WinMain( HINSTANCE hInstance,         // The instance
 
 
 	while(!done)	// Game Loop
 	while(!done)	// Game Loop
 	{
 	{
-		if (PeekMessage(&msg, NULL, 0,0, PM_REMOVE))
+		if (PeekMessage(&msg, nullptr, 0,0, PM_REMOVE))
 		{
 		{
 			if (msg.message==WM_QUIT)
 			if (msg.message==WM_QUIT)
 			{
 			{

+ 14 - 0
test/CMakeLists.txt

@@ -61,6 +61,14 @@ SET( COMMON
   unit/utIssues.cpp
   unit/utIssues.cpp
   unit/utAnim.cpp
   unit/utAnim.cpp
   unit/AssimpAPITest.cpp
   unit/AssimpAPITest.cpp
+  unit/AssimpAPITest_aiMatrix3x3.cpp
+  unit/AssimpAPITest_aiMatrix4x4.cpp
+  unit/AssimpAPITest_aiQuaternion.cpp
+  unit/AssimpAPITest_aiVector2D.cpp
+  unit/AssimpAPITest_aiVector3D.cpp
+  unit/MathTest.cpp
+  unit/MathTest.h
+  unit/RandomNumberGeneration.h
   unit/utBatchLoader.cpp
   unit/utBatchLoader.cpp
   unit/utDefaultIOStream.cpp
   unit/utDefaultIOStream.cpp
   unit/utFastAtof.cpp
   unit/utFastAtof.cpp
@@ -76,10 +84,13 @@ SET( COMMON
   unit/utProfiler.cpp
   unit/utProfiler.cpp
   unit/utSharedPPData.cpp
   unit/utSharedPPData.cpp
   unit/utStringUtils.cpp
   unit/utStringUtils.cpp
+  unit/Common/uiScene.cpp
   unit/Common/utLineSplitter.cpp
   unit/Common/utLineSplitter.cpp
+  unit/Common/utSpatialSort.cpp
 )
 )
 
 
 SET( IMPORTERS
 SET( IMPORTERS
+  unit/ImportExport/Assxml/utAssxmlImportExport.cpp
   unit/utLWSImportExport.cpp
   unit/utLWSImportExport.cpp
   unit/utLWOImportExport.cpp
   unit/utLWOImportExport.cpp
   unit/utSMDImportExport.cpp
   unit/utSMDImportExport.cpp
@@ -136,6 +147,9 @@ SET( IMPORTERS
   unit/ImportExport/MDL/utMDLImporter_HL1_ImportSettings.cpp
   unit/ImportExport/MDL/utMDLImporter_HL1_ImportSettings.cpp
   unit/ImportExport/MDL/utMDLImporter_HL1_Materials.cpp
   unit/ImportExport/MDL/utMDLImporter_HL1_Materials.cpp
   unit/ImportExport/MDL/utMDLImporter_HL1_Nodes.cpp
   unit/ImportExport/MDL/utMDLImporter_HL1_Nodes.cpp
+  #unit/ImportExport/IRR/utIrrImportExport.cpp
+  unit/ImportExport/RAW/utRAWImportExport.cpp
+  unit/ImportExport/Terragen/utTerragenImportExport.cpp
 )
 )
 
 
 SET( MATERIAL
 SET( MATERIAL

BIN
test/models/TER/RealisticTerrain.ter


+ 25 - 0
test/models/glTF2/RecursiveNodes/RecursiveNodes.gltf

@@ -0,0 +1,25 @@
+{
+    "asset": {
+        "version": "2.0"
+    },
+    "scene": 0,
+    "scenes": [
+        {
+            "nodes": [
+                0
+            ]
+        }
+    ],
+    "nodes": [
+        {
+            "children": [
+                1
+            ]
+        },
+        {
+            "children": [
+                0
+            ]
+        }
+    ]
+}

+ 151 - 0
test/unit/AssimpAPITest_aiMatrix3x3.cpp

@@ -0,0 +1,151 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+#include "UnitTestPCH.h"
+#include "MathTest.h"
+
+using namespace Assimp;
+
+class AssimpAPITest_aiMatrix3x3 : public AssimpMathTest {
+protected:
+    virtual void SetUp() {
+        result_c = result_cpp = aiMatrix3x3();
+    }
+
+    aiMatrix3x3 result_c, result_cpp;
+};
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiIdentityMatrix3Test) {
+    // Force a non-identity matrix.
+    result_c = aiMatrix3x3(0,0,0,0,0,0,0,0,0);
+    aiIdentityMatrix3(&result_c);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMatrix3FromMatrix4Test) {
+    const auto m = random_mat4();
+    result_cpp = aiMatrix3x3(m);
+    aiMatrix3FromMatrix4(&result_c, &m);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMatrix3FromQuaternionTest) {
+    const auto q = random_quat();
+    result_cpp = q.GetMatrix();
+    aiMatrix3FromQuaternion(&result_c, &q);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMatrix3AreEqualTest) {
+    result_c = result_cpp = random_mat3();
+    EXPECT_EQ(result_cpp == result_c,
+        (bool)aiMatrix3AreEqual(&result_cpp, &result_c));
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMatrix3AreEqualEpsilonTest) {
+    result_c = result_cpp = random_mat3();
+    EXPECT_EQ(result_cpp.Equal(result_c, Epsilon),
+        (bool)aiMatrix3AreEqualEpsilon(&result_cpp, &result_c, Epsilon));
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMultiplyMatrix3Test) {
+    const auto m = random_mat3();
+    result_c = result_cpp = random_mat3();
+    result_cpp *= m;
+    aiMultiplyMatrix3(&result_c, &m);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiTransposeMatrix3Test) {
+    result_c = result_cpp = random_mat3();
+    result_cpp.Transpose();
+    aiTransposeMatrix3(&result_c);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMatrix3InverseTest) {
+    // Use a predetermined matrix to prevent arbitrary
+    // cases where it could have a null determinant.
+    result_c = result_cpp = aiMatrix3x3(
+        5, 2, 7,
+        4, 6, 9,
+        1, 8, 3);
+    result_cpp.Inverse();
+    aiMatrix3Inverse(&result_c);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMatrix3DeterminantTest) {
+    result_c = result_cpp = random_mat3();
+    EXPECT_EQ(result_cpp.Determinant(),
+        aiMatrix3Determinant(&result_c));
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMatrix3RotationZTest) {
+    const float angle(RandPI.next());
+    aiMatrix3x3::RotationZ(angle, result_cpp);
+    aiMatrix3RotationZ(&result_c, angle);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMatrix3FromRotationAroundAxisTest) {
+    const float angle(RandPI.next());
+    const auto axis = random_unit_vec3();
+    aiMatrix3x3::Rotation(angle, axis, result_cpp);
+    aiMatrix3FromRotationAroundAxis(&result_c, &axis, angle);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMatrix3TranslationTest) {
+    const auto axis = random_vec2();
+    aiMatrix3x3::Translation(axis, result_cpp);
+    aiMatrix3Translation(&result_c, &axis);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix3x3, aiMatrix3FromToTest) {
+    // Use predetermined vectors to prevent running into division by zero.
+    const auto from = aiVector3D(1,2,1).Normalize(), to = aiVector3D(-1,1,1).Normalize();
+    aiMatrix3x3::FromToMatrix(from, to, result_cpp);
+    aiMatrix3FromTo(&result_c, &from, &to);
+    EXPECT_EQ(result_cpp, result_c);
+}

+ 259 - 0
test/unit/AssimpAPITest_aiMatrix4x4.cpp

@@ -0,0 +1,259 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+#include "UnitTestPCH.h"
+#include "MathTest.h"
+
+using namespace Assimp;
+
+class AssimpAPITest_aiMatrix4x4 : public AssimpMathTest {
+protected:
+    virtual void SetUp() {
+        result_c = result_cpp = aiMatrix4x4();
+    }
+
+    /* Generates a predetermined transformation matrix to use
+       for the aiDecompose functions to prevent running into
+       division by zero. */
+    aiMatrix4x4 get_predetermined_transformation_matrix_for_decomposition() const {
+        aiMatrix4x4 t, r;
+        aiMatrix4x4::Translation(aiVector3D(14,-25,-8), t);
+        aiMatrix4x4::Rotation(Math::PI<float>() / 4.0f, aiVector3D(1).Normalize(), r);
+        return t * r;
+    }
+
+    aiMatrix4x4 result_c, result_cpp;
+};
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiIdentityMatrix4Test) {
+    // Force a non-identity matrix.
+    result_c = aiMatrix4x4(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);
+    aiIdentityMatrix4(&result_c);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4FromMatrix3Test) {
+    aiMatrix3x3 m = random_mat3();
+    result_cpp = aiMatrix4x4(m);
+    aiMatrix4FromMatrix3(&result_c, &m);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4FromScalingQuaternionPositionTest) {
+    const aiVector3D s = random_vec3();
+    const aiQuaternion q = random_quat();
+    const aiVector3D t = random_vec3();
+    result_cpp = aiMatrix4x4(s, q, t);
+    aiMatrix4FromScalingQuaternionPosition(&result_c, &s, &q, &t);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4AddTest) {
+    const aiMatrix4x4 temp = random_mat4();
+    result_c = result_cpp = random_mat4();
+    result_cpp = result_cpp + temp;
+    aiMatrix4Add(&result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4AreEqualTest) {
+    result_c = result_cpp = random_mat4();
+    EXPECT_EQ(result_cpp == result_c,
+        (bool)aiMatrix4AreEqual(&result_cpp, &result_c));
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4AreEqualEpsilonTest) {
+    result_c = result_cpp = random_mat4();
+    EXPECT_EQ(result_cpp.Equal(result_c, Epsilon),
+        (bool)aiMatrix4AreEqualEpsilon(&result_cpp, &result_c, Epsilon));
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMultiplyMatrix4Test) {
+    const auto m = random_mat4();
+    result_c = result_cpp = random_mat4();
+    result_cpp *= m;
+    aiMultiplyMatrix4(&result_c, &m);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiTransposeMatrix4Test) {
+    result_c = result_cpp = random_mat4();
+    result_cpp.Transpose();
+    aiTransposeMatrix4(&result_c);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4InverseTest) {
+    // Use a predetermined matrix to prevent arbitrary
+    // cases where it could have a null determinant.
+    result_c = result_cpp = aiMatrix4x4(
+        6, 10, 15, 3,
+        14, 2, 12, 8,
+        9, 13, 5, 16,
+        4, 7, 11, 1);
+    result_cpp.Inverse();
+    aiMatrix4Inverse(&result_c);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4DeterminantTest) {
+    result_c = result_cpp = random_mat4();
+    EXPECT_EQ(result_cpp.Determinant(),
+        aiMatrix4Determinant(&result_c));
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4IsIdentityTest) {
+    EXPECT_EQ(result_cpp.IsIdentity(),
+        (bool)aiMatrix4IsIdentity(&result_c));
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiDecomposeMatrixTest) {
+    aiVector3D scaling_c, scaling_cpp,
+        position_c, position_cpp;
+    aiQuaternion rotation_c, rotation_cpp;
+
+    result_c = result_cpp = get_predetermined_transformation_matrix_for_decomposition();
+    result_cpp.Decompose(scaling_cpp, rotation_cpp, position_cpp);
+    aiDecomposeMatrix(&result_c, &scaling_c, &rotation_c, &position_c);
+    EXPECT_EQ(scaling_cpp, scaling_c);
+    EXPECT_EQ(position_cpp, position_c);
+    EXPECT_EQ(rotation_cpp, rotation_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4DecomposeIntoScalingEulerAnglesPositionTest) {
+    aiVector3D scaling_c, scaling_cpp,
+        rotation_c, rotation_cpp,
+        position_c, position_cpp;
+
+    result_c = result_cpp = get_predetermined_transformation_matrix_for_decomposition();
+    result_cpp.Decompose(scaling_cpp, rotation_cpp, position_cpp);
+    aiMatrix4DecomposeIntoScalingEulerAnglesPosition(&result_c, &scaling_c, &rotation_c, &position_c);
+    EXPECT_EQ(scaling_cpp, scaling_c);
+    EXPECT_EQ(position_cpp, position_c);
+    EXPECT_EQ(rotation_cpp, rotation_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4DecomposeIntoScalingAxisAnglePositionTest) {
+    aiVector3D scaling_c, scaling_cpp,
+        axis_c, axis_cpp,
+        position_c, position_cpp;
+    float angle_c, angle_cpp;
+
+    result_c = result_cpp = get_predetermined_transformation_matrix_for_decomposition();
+    result_cpp.Decompose(scaling_cpp, axis_cpp, angle_cpp, position_cpp);
+    aiMatrix4DecomposeIntoScalingAxisAnglePosition(&result_c, &scaling_c, &axis_c, &angle_c, &position_c);
+    EXPECT_EQ(scaling_cpp, scaling_c);
+    EXPECT_EQ(axis_cpp, axis_c);
+    EXPECT_EQ(angle_cpp, angle_c);
+    EXPECT_EQ(position_cpp, position_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4DecomposeNoScalingTest) {
+    aiVector3D position_c, position_cpp;
+    aiQuaternion rotation_c, rotation_cpp;
+
+    result_c = result_cpp = get_predetermined_transformation_matrix_for_decomposition();
+    result_cpp.DecomposeNoScaling(rotation_cpp, position_cpp);
+    aiMatrix4DecomposeNoScaling(&result_c, &rotation_c, &position_c);
+    EXPECT_EQ(position_cpp, position_c);
+    EXPECT_EQ(rotation_cpp, rotation_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4FromEulerAnglesTest) {
+    const float x(RandPI.next()),
+        y(RandPI.next()),
+        z(RandPI.next());
+    result_cpp.FromEulerAnglesXYZ(x, y, z);
+    aiMatrix4FromEulerAngles(&result_c, x, y, z);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4RotationXTest) {
+    const float angle(RandPI.next());
+    aiMatrix4x4::RotationX(angle, result_cpp);
+    aiMatrix4RotationX(&result_c, angle);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4RotationYTest) {
+    const float angle(RandPI.next());
+    aiMatrix4x4::RotationY(angle, result_cpp);
+    aiMatrix4RotationY(&result_c, angle);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4RotationZTest) {
+    const float angle(RandPI.next());
+    aiMatrix4x4::RotationZ(angle, result_cpp);
+    aiMatrix4RotationZ(&result_c, angle);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4FromRotationAroundAxisTest) {
+    const float angle(RandPI.next());
+    const auto axis = random_unit_vec3();
+    aiMatrix4x4::Rotation(angle, axis, result_cpp);
+    aiMatrix4FromRotationAroundAxis(&result_c, &axis, angle);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4TranslationTest) {
+    const auto axis = random_vec3();
+    aiMatrix4x4::Translation(axis, result_cpp);
+    aiMatrix4Translation(&result_c, &axis);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4ScalingTest) {
+    const auto scaling = random_vec3();
+    aiMatrix4x4::Scaling(scaling, result_cpp);
+    aiMatrix4Scaling(&result_c, &scaling);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiMatrix4x4, aiMatrix4FromToTest) {
+    // Use predetermined vectors to prevent running into division by zero.
+    const auto from = aiVector3D(1,2,1).Normalize(), to = aiVector3D(-1,1,1).Normalize();
+    aiMatrix4x4::FromToMatrix(from, to, result_cpp);
+    aiMatrix4FromTo(&result_c, &from, &to);
+    EXPECT_EQ(result_cpp, result_c);
+}

+ 135 - 0
test/unit/AssimpAPITest_aiQuaternion.cpp

@@ -0,0 +1,135 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+#include "UnitTestPCH.h"
+#include "MathTest.h"
+
+using namespace Assimp;
+
+class AssimpAPITest_aiQuaternion : public AssimpMathTest {
+protected:
+    virtual void SetUp() {
+        result_c = result_cpp = aiQuaternion();
+    }
+
+    aiQuaternion result_c, result_cpp;
+};
+
+TEST_F(AssimpAPITest_aiQuaternion, aiCreateQuaternionFromMatrixTest) {
+    // Use a predetermined transformation matrix
+    // to prevent running into division by zero.
+    aiMatrix3x3 m, r;
+    aiMatrix3x3::Translation(aiVector2D(14,-25), m);
+    aiMatrix3x3::RotationZ(Math::PI<float>() / 4.0f, r);
+    m = m * r;
+
+    result_cpp = aiQuaternion(m);
+    aiCreateQuaternionFromMatrix(&result_c, &m);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionFromEulerAnglesTest) {
+    const float x(RandPI.next()),
+        y(RandPI.next()),
+        z(RandPI.next());
+    result_cpp = aiQuaternion(x, y, z);
+    aiQuaternionFromEulerAngles(&result_c, x, y, z);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionFromAxisAngleTest) {
+    const float angle(RandPI.next());
+    const aiVector3D axis(random_unit_vec3());
+    result_cpp = aiQuaternion(axis, angle);
+    aiQuaternionFromAxisAngle(&result_c, &axis, angle);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionFromNormalizedQuaternionTest) {
+    const auto qvec3 = random_unit_vec3();
+    result_cpp = aiQuaternion(qvec3);
+    aiQuaternionFromNormalizedQuaternion(&result_c, &qvec3);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionAreEqualTest) {
+    result_c = result_cpp = random_quat();
+    EXPECT_EQ(result_cpp == result_c,
+        (bool)aiQuaternionAreEqual(&result_cpp, &result_c));
+}
+
+TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionAreEqualEpsilonTest) {
+    result_c = result_cpp = random_quat();
+    EXPECT_EQ(result_cpp.Equal(result_c, Epsilon),
+        (bool)aiQuaternionAreEqualEpsilon(&result_cpp, &result_c, Epsilon));
+}
+
+TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionNormalizeTest) {
+    result_c = result_cpp = random_quat();
+    aiQuaternionNormalize(&result_c);
+    EXPECT_EQ(result_cpp.Normalize(), result_c);
+}
+
+TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionConjugateTest) {
+    result_c = result_cpp = random_quat();
+    aiQuaternionConjugate(&result_c);
+    EXPECT_EQ(result_cpp.Conjugate(), result_c);
+}
+
+TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionMultiplyTest) {
+    const aiQuaternion temp = random_quat();
+    result_c = result_cpp = random_quat();
+    result_cpp = result_cpp * temp;
+    aiQuaternionMultiply(&result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiQuaternion, aiQuaternionInterpolateTest) {
+    // Use predetermined quaternions to prevent division by zero
+    // during slerp calculations.
+    const float INTERPOLATION(0.5f);
+    const auto q1 = aiQuaternion(aiVector3D(-1,1,1).Normalize(), Math::PI<float>() / 4.0f);
+    const auto q2 = aiQuaternion(aiVector3D(1,2,1).Normalize(), Math::PI<float>() / 2.0f);
+    aiQuaternion::Interpolate(result_cpp, q1, q2, INTERPOLATION);
+    aiQuaternionInterpolate(&result_c, &q1, &q2, INTERPOLATION);
+    EXPECT_EQ(result_cpp, result_c);
+}

+ 140 - 0
test/unit/AssimpAPITest_aiVector2D.cpp

@@ -0,0 +1,140 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+#include "UnitTestPCH.h"
+#include "MathTest.h"
+
+using namespace Assimp;
+
+class AssimpAPITest_aiVector2D : public AssimpMathTest {
+protected:
+    virtual void SetUp() {
+        result_c = result_cpp = aiVector2D();
+        temp = random_vec2(); // Generates a random 2D vector != null vector.
+    }
+
+    aiVector2D result_c, result_cpp, temp;
+};
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2AreEqualTest) {
+    result_c = result_cpp = random_vec2();
+    EXPECT_EQ(result_cpp == result_c,
+        (bool)aiVector2AreEqual(&result_cpp, &result_c));
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2AreEqualEpsilonTest) {
+    result_c = result_cpp = random_vec2();
+    EXPECT_EQ(result_cpp.Equal(result_c, Epsilon),
+        (bool)aiVector2AreEqualEpsilon(&result_cpp, &result_c, Epsilon));
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2AddTest) {
+    result_c = result_cpp = random_vec2();
+    result_cpp += temp;
+    aiVector2Add(&result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2SubtractTest) {
+    result_c = result_cpp = random_vec2();
+    result_cpp -= temp;
+    aiVector2Subtract(&result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2ScaleTest) {
+    const float FACTOR = RandNonZero.next();
+    result_c = result_cpp = random_vec2();
+    result_cpp *= FACTOR;
+    aiVector2Scale(&result_c, FACTOR);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2SymMulTest) {
+    result_c = result_cpp = random_vec2();
+    result_cpp = result_cpp.SymMul(temp);
+    aiVector2SymMul(&result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2DivideByScalarTest) {
+    const float DIVISOR = RandNonZero.next();
+    result_c = result_cpp = random_vec2();
+    result_cpp /= DIVISOR;
+    aiVector2DivideByScalar(&result_c, DIVISOR);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2DivideByVectorTest) {
+    result_c = result_cpp = random_vec2();
+    result_cpp = result_cpp / temp;
+    aiVector2DivideByVector(&result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2LengthTest) {
+    result_c = result_cpp = random_vec2();
+    EXPECT_EQ(result_cpp.Length(), aiVector2Length(&result_c));
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2SquareLengthTest) {
+    result_c = result_cpp = random_vec2();
+    EXPECT_EQ(result_cpp.SquareLength(), aiVector2SquareLength(&result_c));
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2NegateTest) {
+    result_c = result_cpp = random_vec2();
+    aiVector2Negate(&result_c);
+    EXPECT_EQ(-result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2DotProductTest) {
+    result_c = result_cpp = random_vec2();
+    EXPECT_EQ(result_cpp * result_c,
+        aiVector2DotProduct(&result_cpp, &result_c));
+}
+
+TEST_F(AssimpAPITest_aiVector2D, aiVector2NormalizeTest) {
+    result_c = result_cpp = random_vec2();
+    aiVector2Normalize(&result_c);
+    EXPECT_EQ(result_cpp.Normalize(), result_c);
+}

+ 185 - 0
test/unit/AssimpAPITest_aiVector3D.cpp

@@ -0,0 +1,185 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+#include "UnitTestPCH.h"
+#include "MathTest.h"
+
+using namespace Assimp;
+
+class AssimpAPITest_aiVector3D : public AssimpMathTest {
+protected:
+    virtual void SetUp() {
+        result_c = result_cpp = aiVector3D();
+        temp = random_vec3(); // Generates a random 3D vector != null vector.
+    }
+
+    aiVector3D result_c, result_cpp, temp;
+};
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3AreEqualTest) {
+    result_c = result_cpp = random_vec3();
+    EXPECT_EQ(result_cpp == result_c,
+        (bool)aiVector3AreEqual(&result_cpp, &result_c));
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3AreEqualEpsilonTest) {
+    result_c = result_cpp = random_vec3();
+    EXPECT_EQ(result_cpp.Equal(result_c, Epsilon),
+        (bool)aiVector3AreEqualEpsilon(&result_cpp, &result_c, Epsilon));
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3LessThanTest) {
+    result_c = result_cpp = random_vec3();
+    EXPECT_EQ(result_cpp < temp,
+        (bool)aiVector3LessThan(&result_c, &temp));
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3AddTest) {
+    result_c = result_cpp = random_vec3();
+    result_cpp += temp;
+    aiVector3Add(&result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3SubtractTest) {
+    result_c = result_cpp = random_vec3();
+    result_cpp -= temp;
+    aiVector3Subtract(&result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3ScaleTest) {
+    const float FACTOR = RandNonZero.next();
+    result_c = result_cpp = random_vec3();
+    result_cpp *= FACTOR;
+    aiVector3Scale(&result_c, FACTOR);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3SymMulTest) {
+    result_c = result_cpp = random_vec3();
+    result_cpp = result_cpp.SymMul(temp);
+    aiVector3SymMul(&result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3DivideByScalarTest) {
+    const float DIVISOR = RandNonZero.next();
+    result_c = result_cpp = random_vec3();
+    result_cpp /= DIVISOR;
+    aiVector3DivideByScalar(&result_c, DIVISOR);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3DivideByVectorTest) {
+    result_c = result_cpp = random_vec3();
+    result_cpp = result_cpp / temp;
+    aiVector3DivideByVector(&result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3LengthTest) {
+    result_c = result_cpp = random_vec3();
+    EXPECT_EQ(result_cpp.Length(), aiVector3Length(&result_c));
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3SquareLengthTest) {
+    result_c = result_cpp = random_vec3();
+    EXPECT_EQ(result_cpp.SquareLength(), aiVector3SquareLength(&result_c));
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3NegateTest) {
+    result_c = result_cpp = random_vec3();
+    aiVector3Negate(&result_c);
+    EXPECT_EQ(-result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3DotProductTest) {
+    result_c = result_cpp = random_vec3();
+    EXPECT_EQ(result_cpp * result_c,
+        aiVector3DotProduct(&result_cpp, &result_c));
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3CrossProductTest) {
+    result_c = result_cpp = random_vec3();
+    result_cpp = result_cpp ^ temp;
+    aiVector3CrossProduct(&result_c, &result_c, &temp);
+    EXPECT_EQ(result_cpp, result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3NormalizeTest) {
+    result_c = result_cpp = random_vec3();
+    aiVector3Normalize(&result_c);
+    EXPECT_EQ(result_cpp.Normalize(), result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3NormalizeSafeTest) {
+    result_c = result_cpp = random_vec3();
+    aiVector3NormalizeSafe(&result_c);
+    EXPECT_EQ(result_cpp.NormalizeSafe(), result_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiVector3RotateByQuaternionTest) {
+    aiVector3D v_c, v_cpp;
+    v_c = v_cpp = random_vec3();
+    const auto q = random_quat();
+    aiVector3RotateByQuaternion(&v_c, &q);
+    EXPECT_EQ(q.Rotate(v_cpp), v_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiTransformVecByMatrix3Test) {
+    const auto m = random_mat3();
+    aiVector3D v_c, v_cpp;
+    v_c = v_cpp = random_vec3();
+    v_cpp *= m;
+    aiTransformVecByMatrix3(&v_c, &m);
+    EXPECT_EQ(v_cpp, v_c);
+}
+
+TEST_F(AssimpAPITest_aiVector3D, aiTransformVecByMatrix4Test) {
+    const auto m = random_mat4();
+    aiVector3D v_c, v_cpp;
+    v_c = v_cpp = random_vec3();
+    v_cpp *= m;
+    aiTransformVecByMatrix4(&v_c, &m);
+    EXPECT_EQ(v_cpp, v_c);
+}

+ 93 - 0
test/unit/Common/uiScene.cpp

@@ -0,0 +1,93 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+
+#include "UnitTestPCH.h"
+
+#include <assimp/scene.h>
+
+
+using namespace Assimp;
+
+class utScene : public ::testing::Test {
+protected:
+	aiScene *scene;
+
+    void SetUp() override {
+		scene = new aiScene;
+    }
+
+    void TearDown() override {
+		delete scene;
+		scene = nullptr;
+    }
+};
+
+TEST_F(utScene, findNodeTest) {
+	scene->mRootNode = new aiNode();
+	scene->mRootNode->mName.Set("test");
+	aiNode *child = new aiNode;
+	child->mName.Set("child");
+	scene->mRootNode->addChildren(1, &child);
+	aiNode *found = scene->mRootNode->FindNode("child");
+	EXPECT_EQ(child, found);
+}
+
+TEST_F(utScene, sceneHasContentTest) {
+    EXPECT_FALSE(scene->HasAnimations());
+	EXPECT_FALSE(scene->HasMaterials());
+	EXPECT_FALSE(scene->HasMeshes());
+	EXPECT_FALSE(scene->HasCameras());
+	EXPECT_FALSE(scene->HasLights());
+	EXPECT_FALSE(scene->HasTextures());
+}
+
+TEST_F(utScene, getShortFilenameTest) {
+	std::string long_filename1 = "foo_bar/name";
+    const char *name1 = scene->GetShortFilename(long_filename1.c_str());
+	EXPECT_NE(nullptr, name1);
+
+    std::string long_filename2 = "foo_bar\\name";
+    const char *name2 = scene->GetShortFilename(long_filename2.c_str());
+	EXPECT_NE(nullptr, name2);
+}
+
+TEST_F(utScene, getEmbeddedTextureTest) {
+}

+ 84 - 0
test/unit/Common/utSpatialSort.cpp

@@ -0,0 +1,84 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+#include "UnitTestPCH.h"
+
+#include <assimp/SpatialSort.h>
+
+using namespace Assimp;
+
+class utSpatialSort : public ::testing::Test {
+public
+        :
+    aiVector3D *vecs;
+
+protected:
+    void SetUp() override {
+        ::srand(static_cast<unsigned>(time(0)));
+        vecs = new aiVector3D[100];
+        for (size_t i = 0; i < 100; ++i) {
+            vecs[i].x = static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / 100));
+            vecs[i].y = static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / 100));
+            vecs[i].z = static_cast<float>(rand()) / (static_cast<float>(RAND_MAX / 100));
+        }
+    }
+
+    void TearDown() override {
+        delete[] vecs;
+    }
+};
+
+TEST_F( utSpatialSort, findIdenticalsTest ) {
+    SpatialSort sSort;
+    sSort.Fill(vecs, 100, sizeof(aiVector3D));
+
+    std::vector<unsigned int> indices;
+    sSort.FindIdenticalPositions(vecs[0], indices);
+    EXPECT_EQ(1u, indices.size());
+}
+
+TEST_F(utSpatialSort, findPositionsTest) {
+    SpatialSort sSort;
+    sSort.Fill(vecs, 100, sizeof(aiVector3D));
+
+    std::vector<unsigned int> indices;
+    sSort.FindPositions(vecs[0], 0.01f, indices);
+    EXPECT_EQ(1u, indices.size());
+}

+ 76 - 0
test/unit/ImportExport/Assxml/utAssxmlImportExport.cpp

@@ -0,0 +1,76 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2019, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#include "AbstractImportExportBase.h"
+#include "SceneDiffer.h"
+#include "UnitTestPCH.h"
+
+#include <assimp/postprocess.h>
+#include <assimp/Importer.hpp>
+#include <assimp/Exporter.hpp>
+
+using namespace Assimp;
+
+class utAssxmlImportExport : public AbstractImportExportBase {
+public:
+	bool importerTest() override {
+		return true;
+    }
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+	bool exporterTest() override {
+		Assimp::Importer importer;
+		const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OBJ/spider.obj", aiProcess_ValidateDataStructure);
+		EXPECT_NE(scene, nullptr );
+
+        ::Assimp::Exporter exporter;
+		return AI_SUCCESS == exporter.Export(scene, "assxml", ASSIMP_TEST_MODELS_DIR "/OBJ/spider_out.assxml");
+    }
+#endif
+};
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+
+TEST_F(utAssxmlImportExport, exportAssxmlTest) {
+	EXPECT_TRUE(exporterTest());
+}
+
+#endif

+ 66 - 0
test/unit/ImportExport/IRR/utIrrImportExport.cpp

@@ -0,0 +1,66 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+#include "AbstractImportExportBase.h"
+#include "UnitTestPCH.h"
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/Importer.hpp>
+
+using namespace Assimp;
+
+class utIrrImportExport : public AbstractImportExportBase {
+public:
+	virtual bool importerTest() {
+		Assimp::Importer importer;
+		const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/IRR/box.irr", aiProcess_ValidateDataStructure);
+		return nullptr != scene;
+	}
+};
+
+TEST_F(utIrrImportExport, importSimpleIrrTest) {
+	EXPECT_TRUE(importerTest());
+}
+
+TEST_F(utIrrImportExport, importSGIrrTest) {
+	Assimp::Importer importer;
+	const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/IRR/dawfInCellar_SameHierarchy.irr", aiProcess_ValidateDataStructure);
+	EXPECT_NE( nullptr,scene);
+}

+ 64 - 0
test/unit/ImportExport/RAW/utRAWImportExport.cpp

@@ -0,0 +1,64 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+#include "AbstractImportExportBase.h"
+#include "UnitTestPCH.h"
+#include <assimp/postprocess.h>
+#include <assimp/scene.h>
+#include <assimp/Importer.hpp>
+
+using namespace Assimp;
+
+class utRAWImportExport : public AbstractImportExportBase {
+public:
+    virtual bool importerTest() {
+        Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/RAW/Wuson.raw", aiProcess_ValidateDataStructure);
+#ifndef ASSIMP_BUILD_NO_RAW_IMPORTER
+        return nullptr != scene;
+#else
+        return nullptr == scene;
+#endif
+    }
+};
+
+TEST_F(utRAWImportExport, importSimpleRAWTest) {
+    EXPECT_TRUE(importerTest());
+}

+ 60 - 0
test/unit/ImportExport/Terragen/utTerragenImportExport.cpp

@@ -0,0 +1,60 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+
+#include "AbstractImportExportBase.h"
+#include "UnitTestPCH.h"
+
+#include <assimp/postprocess.h>
+#include <assimp/Importer.hpp>
+
+class utTerragenImportExport : public AbstractImportExportBase {
+public:
+    virtual bool importerTest() {
+        /*Assimp::Importer importer;
+        const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/TER/RealisticTerrain.ter", aiProcess_ValidateDataStructure);
+        return nullptr != scene;*/
+        return true;
+    }
+};
+
+TEST_F(utTerragenImportExport, importX3DFromFileTest) {
+    EXPECT_TRUE(importerTest());
+}

+ 0 - 1
test/unit/ImportExport/utCOBImportExport.cpp

@@ -39,7 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 */
 */
 
 
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 
 
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>

+ 0 - 1
test/unit/ImportExport/utOFFImportExport.cpp

@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>
 #include <assimp/scene.h>
 #include <assimp/scene.h>

+ 0 - 1
test/unit/ImportExport/utOgreImportExport.cpp

@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 
 
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>

+ 0 - 1
test/unit/ImportExport/utQ3BSPFileImportExport.cpp

@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 
 
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>

+ 56 - 0
test/unit/MathTest.cpp

@@ -0,0 +1,56 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+#include "MathTest.h"
+
+namespace Assimp {
+
+// Initialize epsilon value.
+const float AssimpMathTest::Epsilon = Math::getEpsilon<float>();
+
+// Initialize with an interval of [1,100].
+RandomUniformFloatGenerator AssimpMathTest::RandNonZero(1.0f, 100.0f);
+
+// Initialize with an interval of [-PI,PI] inclusively.
+RandomUniformFloatGenerator AssimpMathTest::RandPI(-Math::PI<float>(), Math::PI<float>());
+
+}

+ 103 - 0
test/unit/MathTest.h

@@ -0,0 +1,103 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+
+#ifndef ASSIMP_MATH_TEST_H
+#define ASSIMP_MATH_TEST_H
+
+#include "UnitTestPCH.h"
+#include <assimp/types.h>
+#include "RandomNumberGeneration.h"
+
+namespace Assimp {
+
+/** Custom test class providing several math related utilities. */
+class AssimpMathTest : public ::testing::Test {
+public:
+    /** Return a random non-null 2D vector. */
+    inline static aiVector2D random_vec2() {
+        return aiVector2D(RandNonZero.next(), RandNonZero.next());
+    }
+
+    /** Return a random non-null 3D vector. */
+    inline static aiVector3D random_vec3() {
+        return aiVector3D(RandNonZero.next(), RandNonZero.next(),RandNonZero.next());
+    }
+
+    /** Return a random unit 3D vector. */
+    inline static aiVector3D random_unit_vec3() {
+        return random_vec3().NormalizeSafe();
+    }
+
+    /** Return a quaternion with random orientation and
+      * rotation angle around axis. */
+    inline static aiQuaternion random_quat() {
+        return aiQuaternion(random_unit_vec3(), RandPI.next());
+    }
+
+    /** Return a random non-null 3x3 matrix. */
+    inline static aiMatrix3x3 random_mat3() {
+        return aiMatrix3x3(
+            RandNonZero.next(), RandNonZero.next(),RandNonZero.next(),
+            RandNonZero.next(), RandNonZero.next(),RandNonZero.next(),
+            RandNonZero.next(), RandNonZero.next(),RandNonZero.next());
+    }
+
+    /** Return a random non-null 4x4 matrix. */
+    inline static aiMatrix4x4 random_mat4() {
+        return aiMatrix4x4(
+            RandNonZero.next(), RandNonZero.next(),RandNonZero.next(), RandNonZero.next(),
+            RandNonZero.next(), RandNonZero.next(),RandNonZero.next(), RandNonZero.next(),
+            RandNonZero.next(), RandNonZero.next(),RandNonZero.next(), RandNonZero.next(),
+            RandNonZero.next(), RandNonZero.next(),RandNonZero.next(), RandNonZero.next());
+    }
+
+    /** Epsilon value to use in tests. */
+    static const float Epsilon;
+
+    /** Random number generators. */
+    static RandomUniformFloatGenerator RandNonZero, RandPI;
+};
+
+}
+
+#endif // ASSIMP_MATH_TEST_H

+ 82 - 0
test/unit/RandomNumberGeneration.h

@@ -0,0 +1,82 @@
+/*
+---------------------------------------------------------------------------
+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.
+---------------------------------------------------------------------------
+*/
+
+#ifndef ASSIMP_RANDOM_NUMBER_GENERATION_H
+#define ASSIMP_RANDOM_NUMBER_GENERATION_H
+
+#include <random>
+
+namespace Assimp {
+
+/** Helper class to use for generating pseudo-random
+ *  real numbers, with a uniform distribution. */
+template<typename T>
+class RandomUniformRealGenerator {
+public:
+    RandomUniformRealGenerator() :
+            dist_(),
+            rd_(), 
+            re_(rd_())  {
+        // empty
+    }
+    
+    RandomUniformRealGenerator(T min, T max) :
+            dist_(min, max),
+            rd_(),
+            re_(rd_())  {
+        // empty
+    }
+
+    inline T next() {
+        return dist_(re_);
+    }
+
+private:
+    std::uniform_real_distribution<T> dist_;
+    std::random_device rd_;
+    std::default_random_engine re_;
+};
+
+using RandomUniformFloatGenerator = RandomUniformRealGenerator<float>;
+
+}
+
+#endif // ASSIMP_RANDOM_NUMBER_GENERATION_H

+ 0 - 1
test/unit/ut3DSImportExport.cpp

@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 
 
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>

+ 0 - 1
test/unit/utAMFImportExport.cpp

@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 
 
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>

+ 0 - 1
test/unit/utASEImportExport.cpp

@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 
 
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>

+ 0 - 1
test/unit/utArmaturePopulate.cpp

@@ -42,7 +42,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 
 
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 
 
 #include <assimp/material.h>
 #include <assimp/material.h>
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>

+ 0 - 1
test/unit/utAssbinImportExport.cpp

@@ -39,7 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 */
 */
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>
 #include <assimp/Exporter.hpp>
 #include <assimp/Exporter.hpp>

+ 0 - 1
test/unit/utB3DImportExport.cpp

@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 
 
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>

+ 0 - 1
test/unit/utDXFImporterExporter.cpp

@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 
 
 #include <assimp/postprocess.h>
 #include <assimp/postprocess.h>

+ 4 - 1
test/unit/utFBXImporterExporter.cpp

@@ -40,7 +40,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 #include "AbstractImportExportBase.h"
 #include "AbstractImportExportBase.h"
-#include "SceneDiffer.h"
 #include "UnitTestPCH.h"
 #include "UnitTestPCH.h"
 
 
 #include <assimp/commonMetaData.h>
 #include <assimp/commonMetaData.h>
@@ -214,6 +213,10 @@ TEST_F(utFBXImporterExporter, importUnitScaleFactor) {
     double factor(0.0);
     double factor(0.0);
     scene->mMetaData->Get("UnitScaleFactor", factor);
     scene->mMetaData->Get("UnitScaleFactor", factor);
     EXPECT_DOUBLE_EQ(500.0, factor);
     EXPECT_DOUBLE_EQ(500.0, factor);
+
+    scene->mMetaData->Set("UnitScaleFactor", factor * 2);
+    scene->mMetaData->Get("UnitScaleFactor", factor);
+    EXPECT_DOUBLE_EQ(1000.0, factor);
 }
 }
 
 
 TEST_F(utFBXImporterExporter, importEmbeddedAsciiTest) {
 TEST_F(utFBXImporterExporter, importEmbeddedAsciiTest) {

+ 65 - 1316
test/unit/utImporter.cpp

@@ -51,1335 +51,84 @@ using namespace ::std;
 using namespace ::Assimp;
 using namespace ::Assimp;
 
 
 class ImporterTest : public ::testing::Test {
 class ImporterTest : public ::testing::Test {
-public:
-    virtual void SetUp() {
+protected:
+    void SetUp() override {
         pImp = new Importer();
         pImp = new Importer();
     }
     }
 
 
-    virtual void TearDown() {
+    void TearDown() override {
         delete pImp;
         delete pImp;
     }
     }
 
 
-protected:
     Importer *pImp;
     Importer *pImp;
 };
 };
 
 
 #define InputData_BLOCK_SIZE 1310
 #define InputData_BLOCK_SIZE 1310
 
 
+// clang-format off
 // test data for Importer::ReadFileFromMemory() - ./test/3DS/CameraRollAnim.3ds
 // test data for Importer::ReadFileFromMemory() - ./test/3DS/CameraRollAnim.3ds
 static unsigned char InputData_abRawBlock[1310] = {
 static unsigned char InputData_abRawBlock[1310] = {
-    77,
-    77,
-    30,
-    5,
-    0,
-    0,
-    2,
-    0,
-    10,
-    0,
-    0,
-    0,
-    3,
-    0,
-    0,
-    0,
-    61,
-    61,
-    91,
-    3,
-    0,
-    0,
-    62,
-    61,
-    10,
-    0,
-    0,
-    0,
-    3,
-    0,
-    0,
-    0,
-    0,
-    1,
-    10,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    64,
-    254,
-    2,
-    0,
-    0,
-    66,
-    111,
-    120,
-    48,
-    49,
-    0,
-    0,
-    65,
-    242,
-    2,
-    0,
-    0,
-    16,
-    65,
-    64,
-    1,
-    0,
-    0,
-    26,
-    0,
-    102,
-    74,
-    198,
-    193,
-    102,
-    74,
-    198,
-    193,
-    0,
-    0,
-    0,
-    0,
-    205,
-    121,
-    55,
-    66,
-    102,
-    74,
-    198,
-    193,
-    0,
-    0,
-    0,
-    0,
-    102,
-    74,
-    198,
-    193,
-    138,
-    157,
-    184,
-    65,
-    0,
-    0,
-    0,
-    0,
-    205,
-    121,
-    55,
-    66,
-    138,
-    157,
-    184,
-    65,
-    0,
-    0,
-    0,
-    0,
-    102,
-    74,
-    198,
-    193,
-    102,
-    74,
-    198,
-    193,
-    90,
-    252,
-    26,
-    66,
-    205,
-    121,
-    55,
-    66,
-    102,
-    74,
-    198,
-    193,
-    90,
-    252,
-    26,
-    66,
-    102,
-    74,
-    198,
-    193,
-    138,
-    157,
-    184,
-    65,
-    90,
-    252,
-    26,
-    66,
-    205,
-    121,
-    55,
-    66,
-    138,
-    157,
-    184,
-    65,
-    90,
-    252,
-    26,
-    66,
-    102,
-    74,
-    198,
-    193,
-    102,
-    74,
-    198,
-    193,
-    0,
-    0,
-    0,
-    0,
-    205,
-    121,
-    55,
-    66,
-    102,
-    74,
-    198,
-    193,
-    0,
-    0,
-    0,
-    0,
-    205,
-    121,
-    55,
-    66,
-    102,
-    74,
-    198,
-    193,
-    90,
-    252,
-    26,
-    66,
-    205,
-    121,
-    55,
-    66,
-    102,
-    74,
-    198,
-    193,
-    90,
-    252,
-    26,
-    66,
-    102,
-    74,
-    198,
-    193,
-    102,
-    74,
-    198,
-    193,
-    90,
-    252,
-    26,
-    66,
-    102,
-    74,
-    198,
-    193,
-    102,
-    74,
-    198,
-    193,
-    0,
-    0,
-    0,
-    0,
-    205,
-    121,
-    55,
-    66,
-    138,
-    157,
-    184,
-    65,
-    0,
-    0,
-    0,
-    0,
-    205,
-    121,
-    55,
-    66,
-    102,
-    74,
-    198,
-    193,
-    90,
-    252,
-    26,
-    66,
-    205,
-    121,
-    55,
-    66,
-    138,
-    157,
-    184,
-    65,
-    0,
-    0,
-    0,
-    0,
-    102,
-    74,
-    198,
-    193,
-    138,
-    157,
-    184,
-    65,
-    0,
-    0,
-    0,
-    0,
-    102,
-    74,
-    198,
-    193,
-    138,
-    157,
-    184,
-    65,
-    90,
-    252,
-    26,
-    66,
-    102,
-    74,
-    198,
-    193,
-    138,
-    157,
-    184,
-    65,
-    90,
-    252,
-    26,
-    66,
-    205,
-    121,
-    55,
-    66,
-    138,
-    157,
-    184,
-    65,
-    90,
-    252,
-    26,
-    66,
-    205,
-    121,
-    55,
-    66,
-    138,
-    157,
-    184,
-    65,
-    0,
-    0,
-    0,
-    0,
-    102,
-    74,
-    198,
-    193,
-    138,
-    157,
-    184,
-    65,
-    0,
-    0,
-    0,
-    0,
-    102,
-    74,
-    198,
-    193,
-    102,
-    74,
-    198,
-    193,
-    90,
-    252,
-    26,
-    66,
-    102,
-    74,
-    198,
-    193,
-    102,
-    74,
-    198,
-    193,
-    90,
-    252,
-    26,
-    66,
-    102,
-    74,
-    198,
-    193,
-    138,
-    157,
-    184,
-    65,
-    0,
-    0,
-    0,
-    0,
-    64,
-    65,
-    216,
-    0,
-    0,
-    0,
-    26,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    96,
-    65,
-    54,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    53,
-    169,
-    40,
-    65,
-    176,
-    205,
-    90,
-    191,
-    0,
-    0,
-    0,
-    0,
-    32,
-    65,
-    158,
-    0,
-    0,
-    0,
-    12,
-    0,
-    0,
-    0,
-    2,
-    0,
-    3,
-    0,
-    6,
-    0,
-    3,
-    0,
-    1,
-    0,
-    0,
-    0,
-    6,
-    0,
-    4,
-    0,
-    5,
-    0,
-    7,
-    0,
-    6,
-    0,
-    7,
-    0,
-    6,
-    0,
-    4,
-    0,
-    6,
-    0,
-    8,
-    0,
-    9,
-    0,
-    10,
-    0,
-    6,
-    0,
-    11,
-    0,
-    12,
-    0,
-    13,
-    0,
-    6,
-    0,
-    1,
-    0,
-    14,
-    0,
-    7,
-    0,
-    6,
-    0,
-    7,
-    0,
-    15,
-    0,
-    1,
-    0,
-    6,
-    0,
-    16,
-    0,
-    17,
-    0,
-    18,
-    0,
-    6,
-    0,
-    19,
-    0,
-    20,
-    0,
-    21,
-    0,
-    6,
-    0,
-    22,
-    0,
-    0,
-    0,
-    23,
-    0,
-    6,
-    0,
-    24,
-    0,
-    6,
-    0,
-    25,
-    0,
-    6,
-    0,
-    80,
-    65,
-    54,
-    0,
-    0,
-    0,
-    2,
-    0,
-    0,
-    0,
-    2,
-    0,
-    0,
-    0,
-    4,
-    0,
-    0,
-    0,
-    4,
-    0,
-    0,
-    0,
-    8,
-    0,
-    0,
-    0,
-    8,
-    0,
-    0,
-    0,
-    16,
-    0,
-    0,
-    0,
-    16,
-    0,
-    0,
-    0,
-    32,
-    0,
-    0,
-    0,
-    32,
-    0,
-    0,
-    0,
-    64,
-    0,
-    0,
-    0,
-    64,
-    0,
-    0,
-    0,
-    0,
-    64,
-    67,
-    0,
-    0,
-    0,
-    67,
-    97,
-    109,
-    101,
-    114,
-    97,
-    48,
-    49,
-    0,
-    0,
-    71,
-    52,
-    0,
-    0,
-    0,
-    189,
-    19,
-    25,
-    195,
-    136,
-    104,
-    81,
-    64,
-    147,
-    56,
-    182,
-    65,
-    96,
-    233,
-    20,
-    194,
-    67,
-    196,
-    97,
-    190,
-    147,
-    56,
-    182,
-    65,
-    0,
-    0,
-    0,
-    0,
-    85,
-    85,
-    85,
-    66,
-    32,
-    71,
-    14,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    122,
-    68,
-    0,
-    176,
-    179,
-    1,
-    0,
-    0,
-    10,
-    176,
-    21,
-    0,
-    0,
-    0,
-    5,
-    0,
-    77,
-    65,
-    88,
-    83,
-    67,
-    69,
-    78,
-    69,
-    0,
-    44,
-    1,
-    0,
-    0,
-    8,
-    176,
-    14,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    44,
-    1,
-    0,
-    0,
-    9,
-    176,
-    10,
-    0,
-    0,
-    0,
-    128,
-    2,
-    0,
-    0,
-    2,
-    176,
-    168,
-    0,
-    0,
-    0,
-    48,
-    176,
-    8,
-    0,
-    0,
-    0,
-    0,
-    0,
-    16,
-    176,
-    18,
-    0,
-    0,
-    0,
-    66,
-    111,
-    120,
-    48,
-    49,
-    0,
-    0,
-    64,
-    0,
-    0,
-    255,
-    255,
-    19,
-    176,
-    18,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    0,
-    0,
-    0,
-    128,
-    0,
-    0,
-    0,
-    128,
-    32,
-    176,
-    38,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    1,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    53,
-    169,
-    40,
-    65,
-    176,
-    205,
-    90,
-    191,
-    0,
-    0,
-    0,
-    0,
-    33,
-    176,
-    42,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    1,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    34,
-    176,
-    38,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    1,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    0,
-    0,
-    128,
-    63,
-    3,
-    176,
-    143,
-    0,
-    0,
-    0,
-    48,
-    176,
-    8,
-    0,
-    0,
-    0,
-    1,
-    0,
-    16,
-    176,
-    21,
-    0,
-    0,
-    0,
-    67,
-    97,
-    109,
-    101,
-    114,
-    97,
-    48,
-    49,
-    0,
-    0,
-    64,
-    0,
-    0,
-    255,
-    255,
-    32,
-    176,
-    38,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    1,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    189,
-    19,
-    25,
-    195,
-    136,
-    104,
-    81,
-    64,
-    147,
-    56,
-    182,
-    65,
-    35,
-    176,
-    30,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    1,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    52,
-    66,
-    36,
-    176,
-    40,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    120,
-    0,
-    0,
-    0,
-    2,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    120,
-    13,
-    90,
-    189,
-    120,
-    0,
-    0,
-    0,
-    0,
-    0,
-    99,
-    156,
-    154,
-    194,
-    4,
-    176,
-    73,
-    0,
-    0,
-    0,
-    48,
-    176,
-    8,
-    0,
-    0,
-    0,
-    2,
-    0,
-    16,
-    176,
-    21,
-    0,
-    0,
-    0,
-    67,
-    97,
-    109,
-    101,
-    114,
-    97,
-    48,
-    49,
-    0,
-    0,
-    64,
-    0,
-    0,
-    255,
-    255,
-    32,
-    176,
-    38,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    1,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    0,
-    96,
-    233,
-    20,
-    194,
-    67,
-    196,
-    97,
-    190,
-    147,
-    56,
-    182,
-    65,
-};
-
+     77, 77, 30,  5,  0,  0,  2,  0, 10,  0,  0,  0,  3,  0,  0,  0, 61, 61, 91,  3,  0,  0,
+     62, 61, 10,  0,  0,  0,  3,  0,  0,  0,  0,  1, 10,  0,  0,  0,  0,  0,128, 63,  0, 64,
+    254,  2,  0,  0, 66,111,120, 48, 49,  0,  0, 65,242,  2,  0,  0, 16, 65, 64,  1,  0,  0,
+     26,  0,102, 74,198,193,102, 74,198,193,  0,  0,  0,  0,205,121, 55, 66,102, 74,198,193,
+      0,  0,  0,  0,102, 74,198,193,138,157,184, 65,  0,  0,  0,  0,205,121, 55, 66,138,157,
+    184, 65,  0,  0,  0,  0,102, 74,198,193,102, 74,198,193, 90,252, 26, 66,205,121, 55, 66,
+    102, 74,198,193, 90,252, 26, 66,102, 74,198,193,138,157,184, 65, 90,252, 26, 66,205,121,
+     55, 66,138,157,184, 65, 90,252, 26, 66,102, 74,198,193,102, 74,198,193,  0,  0,  0,  0,
+    205,121, 55, 66,102, 74,198,193,  0,  0,  0,  0,205,121, 55, 66,102, 74,198,193, 90,252,
+    26,  66,205,121, 55, 66,102, 74,198,193, 90,252, 26, 66,102, 74,198,193,102, 74,198,193,
+    90, 252, 26, 66,102, 74,198,193,102, 74,198,193,  0,  0,  0,  0,205,121, 55, 66,138,157,
+    184, 65,  0,  0,  0,  0,205,121, 55, 66,102, 74,198,193, 90,252, 26, 66,205,121, 55, 66,
+    138,157,184, 65,  0,  0,  0,  0,102, 74,198,193,138,157,184, 65,  0,  0,  0,  0,102, 74,
+    198,193,138,157,184, 65, 90,252, 26, 66,102, 74,198,193,138,157,184, 65, 90,252, 26, 66,
+    205,121, 55, 66,138,157,184, 65, 90,252, 26, 66,205,121, 55, 66,138,157,184, 65,  0,  0,
+      0,  0,102, 74,198,193,138,157,184, 65,  0,  0,  0,  0,102, 74,198,193,102, 74,198,193,
+     90,252, 26, 66,102, 74,198,193,102, 74,198,193, 90,252, 26, 66,102, 74,198,193,138,157,
+    184, 65,  0,  0,  0,  0, 64, 65,216,  0,  0,  0, 26,  0,  0,  0,128, 63,  0,  0,  0,  0,
+      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,128, 63,  0,  0,128, 63,  0,  0,  0,  0,  0,  0,
+    128, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,128, 63,  0,  0,  0,  0,  0,  0,  0,  0,
+      0,  0,128, 63,  0,  0,128, 63,  0,  0,128, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+    128, 63,  0,  0,  0,  0,  0,  0,128, 63,  0,  0,128, 63,  0,  0,128, 63,  0,  0,128, 63,
+      0,  0,  0,  0,  0,  0,128, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,128, 63,  0,  0,
+      0,  0,  0,  0,  0,  0,  0,  0,128, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,128, 63,
+      0,  0,  0,  0,  0,  0,128, 63,  0,  0,128, 63,  0,  0,128, 63,  0,  0,128, 63,  0,  0,
+      0,  0,  0,  0,128, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+      0,  0,128, 63,  0,  0,128, 63,  0,  0,128, 63,  0,  0,128, 63,  0,  0,  0,  0,  0,  0,
+      0,  0, 96, 65, 54,  0,  0,  0,  0,  0,128, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+      0,  0,  0,  0,128, 63,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,128, 63,
+     53,169, 40, 65,176,205, 90,191,  0,  0,  0,  0, 32, 65,158,  0,  0,  0, 12,  0,  0,  0,
+      2,  0,  3,  0,  6,  0,  3,  0,  1,  0,  0,  0,  6,  0,  4,  0,  5,  0,  7,  0,  6,  0,
+      7,  0,  6,  0,  4,  0,  6,  0,  8,  0,  9,  0, 10,  0,  6,  0, 11,  0, 12,  0, 13,  0,
+      6,  0,  1,  0, 14,  0,  7,  0,  6,  0,  7,  0, 15,  0,  1,  0,  6,  0, 16,  0, 17,  0,
+     18,  0,  6,  0, 19,  0, 20,  0, 21,  0,  6,  0, 22,  0,  0,  0, 23,  0,  6,  0, 24,  0,
+      6,  0, 25,  0,  6,  0, 80, 65, 54,  0,  0,  0,  2,  0,  0,  0,  2,  0,  0,  0,  4,  0,
+      0,  0,  4,  0,  0,  0,  8,  0,  0,  0,  8,  0,  0,  0, 16,  0,  0,  0, 16,  0,  0,  0,
+     32,  0,  0,  0, 32,  0,  0,  0, 64,  0,  0,  0, 64,  0,  0,  0,  0, 64, 67,  0,  0,  0,
+     67, 97,109,101,114, 97, 48, 49,  0,  0, 71, 52,  0,  0,  0,189, 19, 25,195,136,104, 81,
+     64,147, 56,182, 65, 96,233, 20,194, 67,196, 97,190,147, 56,182, 65,  0,  0,  0,  0, 85,
+     85, 85, 66, 32, 71, 14,  0,  0,  0,  0,  0,  0,  0,  0,  0,122, 68,  0,176,179,  1,  0,
+      0, 10,176, 21,  0,  0,  0,  5,  0, 77, 65, 88, 83, 67, 69, 78, 69,  0, 44,  1,  0,  0,
+      8,176, 14,  0,  0,  0,  0,  0,  0,  0, 44,  1,  0,  0,  9,176, 10,  0,  0,  0,128,  2,
+      0,  0,  2,176,168,  0,  0,  0, 48,176,  8,  0,  0,  0,  0,  0, 16,176, 18,  0,  0,  0,
+     66,111,120, 48, 49,  0,  0, 64,  0,  0,255,255, 19,176, 18,  0,  0,  0,  0,  0,  0,128,
+      0,  0,  0,128,  0,  0,  0,128, 32,176, 38,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+      0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0, 53,169, 40, 65,176,205, 90,191,  0,  0,
+      0,  0, 33,176, 42,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,
+      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+     34,176, 38,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,
+      0,  0,  0,  0,  0,  0,128, 63,  0,  0,128, 63,  0,  0,128, 63,  3,176,143,  0,  0,  0,
+     48,176,  8,  0,  0,  0,  1,  0, 16,176, 21,  0,  0,  0, 67, 97,109,101,114, 97, 48, 49,
+      0,  0, 64,  0,  0,255,255, 32,176, 38,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+      0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,189, 19, 25,195,136,104, 81, 64,147, 56,182,
+     65, 35,176, 30,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,
+      0,  0,  0,  0,  0,  0,  0, 52, 66, 36,176, 40,  0,  0,  0,  0,  0,  0,  0,  0,  0,120,
+      0,  0,  0,  2,  0,  0,  0,  0,  0,  0,  0,  0,  0,120, 13, 90,189,120,  0,  0,  0,  0,
+      0, 99,156,154,194,  4,176, 73,  0,  0,  0, 48,176,  8,  0,  0,  0,  2,  0, 16,176, 21,
+      0,  0,  0, 67, 97,109,101,114, 97, 48, 49,  0,  0, 64,  0,  0,255,255, 32,176, 38,  0,
+      0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  1,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+     96,233, 20,194, 67,196, 97,190,147, 56,182, 65 };
+// clang-format on
 #define AIUT_DEF_ERROR_TEXT "sorry, this is a test"
 #define AIUT_DEF_ERROR_TEXT "sorry, this is a test"
 
 
 static const aiImporterDesc desc = {
 static const aiImporterDesc desc = {

Некоторые файлы не были показаны из-за большого количества измененных файлов