瀏覽代碼

Merge pull request #2 from assimp/master

Updating to latest version from origin
Tomas Mariancik 6 年之前
父節點
當前提交
d8979cbc1f
共有 100 個文件被更改,包括 1499 次插入1233 次删除
  1. 2 1
      .travis.sh
  2. 26 0
      BUILDBINARIES_EXAMPLE.bat
  3. 21 7
      Build.md
  4. 12 16
      CMakeLists.txt
  5. 1 1
      Readme.md
  6. 7 2
      appveyor.yml
  7. 5 1
      assimpTargets-debug.cmake.in
  8. 5 1
      assimpTargets-release.cmake.in
  9. 7 3
      cmake-modules/Findassimp.cmake
  10. 0 2
      code/3DS/3DSLoader.cpp
  11. 1 1
      code/AMF/AMFImporter.cpp
  12. 13 13
      code/AMF/AMFImporter_Postprocess.cpp
  13. 4 1
      code/CMakeLists.txt
  14. 4 3
      code/Collada/ColladaExporter.cpp
  15. 2 2
      code/Collada/ColladaLoader.cpp
  16. 1 1
      code/Collada/ColladaLoader.h
  17. 25 2
      code/Common/BaseImporter.cpp
  18. 60 101
      code/Common/DefaultIOSystem.cpp
  19. 5 30
      code/Common/Exporter.cpp
  20. 50 0
      code/Common/SceneCombiner.cpp
  21. 2 2
      code/Common/Version.cpp
  22. 23 49
      code/FBX/FBXConverter.cpp
  23. 2 17
      code/FBX/FBXConverter.h
  24. 1 5
      code/FBX/FBXExportProperty.cpp
  25. 85 37
      code/FBX/FBXExporter.cpp
  26. 1 1
      code/FBX/FBXExporter.h
  27. 8 9
      code/FBX/FBXImporter.cpp
  28. 3 4
      code/Importer/IFC/IFCCurve.cpp
  29. 1 1
      code/Importer/IFC/IFCGeometry.cpp
  30. 3 3
      code/Importer/IFC/IFCOpenings.cpp
  31. 0 1
      code/Irr/IRRMeshLoader.cpp
  32. 1 1
      code/MD2/MD2Loader.cpp
  33. 2 1
      code/MD5/MD5Loader.cpp
  34. 1 1
      code/MD5/MD5Parser.cpp
  35. 16 26
      code/MDL/MDLLoader.cpp
  36. 1 17
      code/MDL/MDLLoader.h
  37. 1 18
      code/Material/MaterialSystem.cpp
  38. 1 4
      code/Obj/ObjFileImporter.cpp
  39. 2 2
      code/Obj/ObjFileParser.cpp
  40. 0 1
      code/Ply/PlyLoader.cpp
  41. 3 3
      code/PostProcessing/ComputeUVMappingProcess.cpp
  42. 0 1
      code/PostProcessing/FindInvalidDataProcess.cpp
  43. 29 0
      code/PostProcessing/MakeVerboseFormat.cpp
  44. 7 0
      code/PostProcessing/MakeVerboseFormat.h
  45. 59 4
      code/PostProcessing/ValidateDataStructure.cpp
  46. 8 0
      code/PostProcessing/ValidateDataStructure.h
  47. 3 3
      code/X/XFileParser.cpp
  48. 1 1
      code/X3D/X3DExporter.cpp
  49. 30 30
      code/X3D/X3DImporter.cpp
  50. 3 3
      code/X3D/X3DImporter_Geometry2D.cpp
  51. 7 7
      code/X3D/X3DImporter_Geometry3D.cpp
  52. 1 1
      code/X3D/X3DImporter_Networking.cpp
  53. 40 40
      code/X3D/X3DImporter_Postprocess.cpp
  54. 6 6
      code/X3D/X3DImporter_Rendering.cpp
  55. 1 1
      code/X3D/X3DImporter_Texturing.cpp
  56. 8 61
      code/glTF/glTFAsset.h
  57. 10 192
      code/glTF/glTFAsset.inl
  58. 5 3
      code/glTF/glTFAssetWriter.inl
  59. 193 0
      code/glTF/glTFCommon.cpp
  60. 248 0
      code/glTF/glTFCommon.h
  61. 4 1
      code/glTF/glTFExporter.cpp
  62. 24 58
      code/glTF/glTFImporter.cpp
  63. 9 60
      code/glTF2/glTF2Asset.h
  64. 9 194
      code/glTF2/glTF2Asset.inl
  65. 1 1
      code/glTF2/glTF2AssetWriter.inl
  66. 125 20
      code/glTF2/glTF2Importer.cpp
  67. 4 4
      contrib/gtest/test/gtest-param-test_test.cc
  68. 1 1
      contrib/irrXML/irrXML.h
  69. 11 9
      include/assimp/BaseImporter.h
  70. 5 1
      include/assimp/Bitmap.h
  71. 5 0
      include/assimp/ByteSwapper.h
  72. 12 2
      include/assimp/CreateAnimMesh.h
  73. 9 10
      include/assimp/DefaultIOStream.h
  74. 5 0
      include/assimp/DefaultIOSystem.h
  75. 9 0
      include/assimp/Defines.h
  76. 13 10
      include/assimp/Exceptional.h
  77. 4 0
      include/assimp/Exporter.hpp
  78. 6 1
      include/assimp/GenericProperty.h
  79. 5 1
      include/assimp/Hash.h
  80. 8 4
      include/assimp/IOStream.hpp
  81. 25 18
      include/assimp/IOStreamBuffer.h
  82. 4 0
      include/assimp/IOSystem.hpp
  83. 4 0
      include/assimp/Importer.hpp
  84. 20 16
      include/assimp/LineSplitter.h
  85. 5 0
      include/assimp/LogAux.h
  86. 0 49
      include/assimp/Macros.h
  87. 23 10
      include/assimp/MathFunctions.h
  88. 6 0
      include/assimp/MemoryIOWrapper.h
  89. 7 2
      include/assimp/ParsingUtils.h
  90. 9 5
      include/assimp/Profiler.h
  91. 6 2
      include/assimp/ProgressHandler.hpp
  92. 5 3
      include/assimp/RemoveComments.h
  93. 5 0
      include/assimp/SGSpatialSort.h
  94. 10 1
      include/assimp/SceneCombiner.h
  95. 5 0
      include/assimp/SkeletonMeshBuilder.h
  96. 6 0
      include/assimp/SmoothingGroups.h
  97. 5 2
      include/assimp/SmoothingGroups.inl
  98. 5 0
      include/assimp/SpatialSort.h
  99. 6 1
      include/assimp/StandardShapes.h
  100. 7 3
      include/assimp/StreamReader.h

+ 2 - 1
.travis.sh

@@ -7,7 +7,8 @@
 #
 #
 function generate() {
 function generate() {
     OPTIONS="-DASSIMP_WERROR=ON"
     OPTIONS="-DASSIMP_WERROR=ON"
-
+    OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=NO"
+    
     if [ "$DISABLE_EXPORTERS" = "YES" ] ; then
     if [ "$DISABLE_EXPORTERS" = "YES" ] ; then
         OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=YES"
         OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=YES"
     else
     else

+ 26 - 0
BUILDBINARIES_EXAMPLE.bat

@@ -0,0 +1,26 @@
+:: This is an example file to generate binaries using Windows Operating System
+:: This script is configured to be executed from the source directory
+
+:: Compiled binaries will be placed in BINARIES_DIR\code\CONFIG
+
+:: NOTE
+:: The build process will generate a config.h file that is placed in BINARIES_DIR\include
+:: This file must be merged with SOURCE_DIR\include
+:: You should write yourself a script that copies the files where you want them.
+:: Also see: https://github.com/assimp/assimp/pull/2646
+
+SET SOURCE_DIR=.
+
+:: For generators see "cmake --help"
+SET GENERATOR=Visual Studio 15 2017
+
+SET BINARIES_DIR="./BINARIES/Win32"
+cmake CMakeLists.txt -G "%GENERATOR%" -S %SOURCE_DIR% -B %BINARIES_DIR%
+cmake --build %BINARIES_DIR% --config release
+
+SET BINARIES_DIR="./BINARIES/x64"
+cmake CMakeLists.txt -G "%GENERATOR% Win64" -S %SOURCE_DIR% -B %BINARIES_DIR%
+cmake --build %BINARIES_DIR% --config debug
+cmake --build %BINARIES_DIR% --config release
+
+PAUSE

+ 21 - 7
Build.md

@@ -1,17 +1,31 @@
 # Build Instructions
 # Build Instructions
-## Install CMake
+
+## Build on all platforms using vcpkg
+You can download and install assimp using the [vcpkg](https://github.com/Microsoft/vcpkg/) dependency manager:
+```bash
+    git clone https://github.com/Microsoft/vcpkg.git
+    cd vcpkg
+    ./bootstrap-vcpkg.sh
+    ./vcpkg integrate install
+    vcpkg install assimp
+```
+The assimp port in vcpkg is kept up to date by Microsoft team members and community contributors. If the version is out of date, please [create an issue or pull request](https://github.com/Microsoft/vcpkg) on the vcpkg repository.
+
+## Manual build instructions
+
+### Install CMake
 Asset-Importer-Lib can be build for a lot of different platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ or for linux install it via
 Asset-Importer-Lib can be build for a lot of different platforms. We are using cmake to generate the build environment for these via cmake. So you have to make sure that you have a working cmake-installation on your system. You can download it at https://cmake.org/ or for linux install it via
 ```bash
 ```bash
 sudo apt-get install cmake
 sudo apt-get install cmake
 ```
 ```
 
 
-## Get the source
+### Get the source
 Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via:
 Make sure you have a working git-installation. Open a command prompt and clone the Asset-Importer-Lib via:
 ```bash
 ```bash
 git clone https://github.com/assimp/assimp.git
 git clone https://github.com/assimp/assimp.git
 ```
 ```
 
 
-## Build instructions for Windows with Visual-Studio
+### Build instructions for Windows with Visual-Studio
 
 
 First you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/
 First you have to install Visual-Studio on your windows-system. You can get the Community-Version for free here: https://visualstudio.microsoft.com/de/downloads/
 To generate the build environment for your IDE open a command prompt, navigate to your repo and type:
 To generate the build environment for your IDE open a command prompt, navigate to your repo and type:
@@ -20,10 +34,10 @@ cmake CMakeLists.txt
 ```
 ```
 This will generate the project files for the visual studio. All dependencies used to build Asset-IMporter-Lib shall be part of the repo. If you want to use you own zlib.installation this is possible as well. Check the options for it.
 This will generate the project files for the visual studio. All dependencies used to build Asset-IMporter-Lib shall be part of the repo. If you want to use you own zlib.installation this is possible as well. Check the options for it.
 
 
-## Build instructions for Windows with UWP
+### Build instructions for Windows with UWP
 See <https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app>
 See <https://stackoverflow.com/questions/40803170/cmake-uwp-using-cmake-to-build-universal-windows-app>
 
 
-## Build instructions for Linux / Unix
+### Build instructions for Linux / Unix
 Open a terminal and got to your repository. You can generate the makefiles and build the library via:
 Open a terminal and got to your repository. You can generate the makefiles and build the library via:
 
 
 ```bash
 ```bash
@@ -34,7 +48,7 @@ The option -j descripes the number of parallel processes for the build. In this
 
 
 If you want to use a IDE for linux you can try QTCreator for instance. 
 If you want to use a IDE for linux you can try QTCreator for instance. 
 
 
-## Build instructions for MinGW
+### Build instructions for MinGW
  Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag 
  Older versions of MinGW's compiler (e.g. 5.1.0) do not support the -mbig_obj flag 
 required to compile some of assimp's files, especially for debug builds.
 required to compile some of assimp's files, especially for debug builds.
 Version 7.3.0 of g++-mingw-w64 & gcc-mingw-w64 appears to work.
 Version 7.3.0 of g++-mingw-w64 & gcc-mingw-w64 appears to work.
@@ -50,7 +64,7 @@ The following toolchain may or may not be helpful for building assimp using MinG
 
 
 Besides the toolchain, compilation should be the same as for Linux / Unix.
 Besides the toolchain, compilation should be the same as for Linux / Unix.
 
 
-## CMake build options
+### CMake build options
 The cmake-build-environment provides options to configure the build. The following options can be used:
 The cmake-build-environment provides options to configure the build. The following options can be used:
 - **BUILD_SHARED_LIBS ( default ON )**: Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib.
 - **BUILD_SHARED_LIBS ( default ON )**: Generation of shared libs ( dll for windows, so for Linux ). Set this to OFF to get a static lib.
 - **BUILD_FRAMEWORK ( default OFF, MacOnly)**: Build package as Mac OS X Framework bundle
 - **BUILD_FRAMEWORK ( default OFF, MacOnly)**: Build package as Mac OS X Framework bundle

+ 12 - 16
CMakeLists.txt

@@ -253,7 +253,7 @@ ELSEIF(MSVC)
   IF(MSVC12)
   IF(MSVC12)
     ADD_COMPILE_OPTIONS(/wd4351)
     ADD_COMPILE_OPTIONS(/wd4351)
   ENDIF()
   ENDIF()
-  SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2")
+  SET(CMAKE_CXX_FLAGS_DEBUG "/D_DEBUG /MDd /Ob2 /DEBUG:FULL /Zi")
 ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
 ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
   IF(NOT HUNTER_ENABLED)
   IF(NOT HUNTER_ENABLED)
     SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
     SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
@@ -271,22 +271,20 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW )
     SET(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
     SET(CMAKE_CXX_FLAGS "-std=c++11 ${CMAKE_CXX_FLAGS}")
     SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
     SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
   ENDIF()
   ENDIF()
-  SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj ${CMAKE_CXX_FLAGS}")
+  SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long -Wa,-mbig-obj -O3 ${CMAKE_CXX_FLAGS}")
   SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
   SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
   ADD_DEFINITIONS( -U__STRICT_ANSI__ )
   ADD_DEFINITIONS( -U__STRICT_ANSI__ )
 ENDIF()
 ENDIF()
 
 
 IF ( IOS AND NOT HUNTER_ENABLED)
 IF ( IOS AND NOT HUNTER_ENABLED)
-
-IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
-  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og")
-  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -Og")
-ELSE()
-  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
-  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
-  # Experimental for pdb generation
-ENDIF()
-
+  IF (CMAKE_BUILD_TYPE STREQUAL "Debug")
+    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -Og")
+    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -Og")
+  ELSE()
+    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fembed-bitcode -O3")
+    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
+    # Experimental for pdb generation
+  ENDIF()
 ENDIF( IOS AND NOT HUNTER_ENABLED)
 ENDIF( IOS AND NOT HUNTER_ENABLED)
 
 
 IF (ASSIMP_COVERALLS)
 IF (ASSIMP_COVERALLS)
@@ -559,17 +557,15 @@ ENDIF(NOT HUNTER_ENABLED)
 
 
 ADD_SUBDIRECTORY( code/ )
 ADD_SUBDIRECTORY( code/ )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
+  # The viewer for windows only
   IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
   IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
     OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
     OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
     IF ( ASSIMP_BUILD_ASSIMP_VIEW )
     IF ( ASSIMP_BUILD_ASSIMP_VIEW )
       ADD_SUBDIRECTORY( tools/assimp_view/ )
       ADD_SUBDIRECTORY( tools/assimp_view/ )
     ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW )
     ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW )
   ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
   ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
-
+  # Te command line tool
   ADD_SUBDIRECTORY( tools/assimp_cmd/ )
   ADD_SUBDIRECTORY( tools/assimp_cmd/ )
-IF (NOT IOS)
-  ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
-ENDIF (NOT IOS)
 ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 
 
 IF ( ASSIMP_BUILD_SAMPLES)
 IF ( ASSIMP_BUILD_SAMPLES)

+ 1 - 1
Readme.md

@@ -120,7 +120,7 @@ __Exporters__:
 - FBX ( experimental )
 - FBX ( experimental )
 
 
 ### Building ###
 ### Building ###
-Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
+Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file. We are available in vcpkg, and our build system is CMake; if you used CMake before there is a good chance you know what to do.
 
 
 ### Ports ###
 ### Ports ###
 * [Android](port/AndroidJNI/README.md)
 * [Android](port/AndroidJNI/README.md)

+ 7 - 2
appveyor.yml

@@ -16,6 +16,8 @@ matrix:
 image:
 image:
   - Visual Studio 2015
   - Visual Studio 2015
   - Visual Studio 2017
   - Visual Studio 2017
+  - Visual Studio 2019
+  - MinGW  
     
     
 platform:
 platform:
   - Win32
   - Win32
@@ -26,10 +28,13 @@ configuration: Release
 install:
 install:
   - set PATH=C:\Ruby24-x64\bin;%PATH%
   - set PATH=C:\Ruby24-x64\bin;%PATH%
   - set CMAKE_DEFINES -DASSIMP_WERROR=ON
   - set CMAKE_DEFINES -DASSIMP_WERROR=ON
+  - if [%COMPILER%]==[MinGW] set PATH=C:\MinGW\bin;%PATH%
   - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
   - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
   - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
   - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
-  - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
-  - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" .
+  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2019" set CMAKE_GENERATOR_NAME=Visual Studio 16 2019
+  - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%" -A %platform% .
+  # Rename sh.exe as sh.exe in PATH interferes with MinGW
+  - rename "C:\Program Files\Git\usr\bin\sh.exe" "sh2.exe"
   - set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
   - set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
   - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe
   - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe
   - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe
   - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe

+ 5 - 1
assimpTargets-debug.cmake.in

@@ -63,7 +63,11 @@ if(MSVC)
 else()
 else()
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the assimp libraries" )
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the assimp libraries" )
   if(ASSIMP_BUILD_SHARED_LIBS)
   if(ASSIMP_BUILD_SHARED_LIBS)
-    set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
+    if(APPLE)
+        set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@.@ASSIMP_VERSION_MAJOR@@CMAKE_SHARED_LIBRARY_SUFFIX@")
+    else(APPLE)
+        set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
+    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 "${_IMPORT_PREFIX}/lib/${sharedLibraryName}"

+ 5 - 1
assimpTargets-release.cmake.in

@@ -63,7 +63,11 @@ if(MSVC)
 else()
 else()
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the assimp libraries" )
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the assimp libraries" )
   if(ASSIMP_BUILD_SHARED_LIBS)
   if(ASSIMP_BUILD_SHARED_LIBS)
-    set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
+    if(APPLE)
+        set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}.@ASSIMP_VERSION_MAJOR@@CMAKE_SHARED_LIBRARY_SUFFIX@")
+    else(APPLE)
+        set(sharedLibraryName "libassimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@.@ASSIMP_VERSION_MAJOR@")
+    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 "${_IMPORT_PREFIX}/lib/${sharedLibraryName}"

+ 7 - 3
cmake-modules/Findassimp.cmake

@@ -54,14 +54,18 @@ else(WIN32)
 
 
 	find_path(
 	find_path(
 	  assimp_INCLUDE_DIRS
 	  assimp_INCLUDE_DIRS
-	  NAMES postprocess.h scene.h version.h config.h cimport.h
-	  PATHS /usr/local/include/
+	  NAMES assimp/postprocess.h assimp/scene.h assimp/version.h assimp/config.h assimp/cimport.h
+	  PATHS /usr/local/include
+	  PATHS /usr/include/
+
 	)
 	)
 
 
 	find_library(
 	find_library(
 	  assimp_LIBRARIES
 	  assimp_LIBRARIES
 	  NAMES assimp
 	  NAMES assimp
 	  PATHS /usr/local/lib/
 	  PATHS /usr/local/lib/
+	  PATHS /usr/lib64/
+	  PATHS /usr/lib/
 	)
 	)
 
 
 	if (assimp_INCLUDE_DIRS AND assimp_LIBRARIES)
 	if (assimp_INCLUDE_DIRS AND assimp_LIBRARIES)
@@ -78,4 +82,4 @@ else(WIN32)
 	  endif (assimp_FIND_REQUIRED)
 	  endif (assimp_FIND_REQUIRED)
 	endif (assimp_FOUND)
 	endif (assimp_FOUND)
 	
 	
-endif(WIN32)
+endif(WIN32)

+ 0 - 2
code/3DS/3DSLoader.cpp

@@ -50,9 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 #ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 
-// internal headers
 #include "3DSLoader.h"
 #include "3DSLoader.h"
-#include <assimp/Macros.h>
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>

+ 1 - 1
code/AMF/AMFImporter.cpp

@@ -83,7 +83,7 @@ void AMFImporter::Clear()
 	mMaterial_Converted.clear();
 	mMaterial_Converted.clear();
 	mTexture_Converted.clear();
 	mTexture_Converted.clear();
 	// Delete all elements
 	// Delete all elements
-	if(mNodeElement_List.size())
+	if(!mNodeElement_List.empty())
 	{
 	{
 		for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; }
 		for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; }
 
 

+ 13 - 13
code/AMF/AMFImporter_Postprocess.cpp

@@ -66,7 +66,7 @@ aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*
     aiColor4D tcol;
     aiColor4D tcol;
 
 
 	// Check if stored data are supported.
 	// Check if stored data are supported.
-	if(Composition.size() != 0)
+	if(!Composition.empty())
 	{
 	{
 		throw DeadlyImportError("IME. GetColor for composition");
 		throw DeadlyImportError("IME. GetColor for composition");
 	}
 	}
@@ -321,7 +321,7 @@ void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace
     };
     };
 
 
 	pOutputList_Separated.clear();
 	pOutputList_Separated.clear();
-	if(pInputList.size() == 0) return;
+	if(pInputList.empty()) return;
 
 
 	do
 	do
 	{
 	{
@@ -334,19 +334,19 @@ void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace
 			{
 			{
 				auto it_old = it;
 				auto it_old = it;
 
 
-				it++;
+				++it;
 				face_list_cur.push_back(*it_old);
 				face_list_cur.push_back(*it_old);
 				pInputList.erase(it_old);
 				pInputList.erase(it_old);
 			}
 			}
 			else
 			else
 			{
 			{
-				it++;
+				++it;
 			}
 			}
 		}
 		}
 
 
-		if(face_list_cur.size() > 0) pOutputList_Separated.push_back(face_list_cur);
+		if(!face_list_cur.empty()) pOutputList_Separated.push_back(face_list_cur);
 
 
-	} while(pInputList.size() > 0);
+	} while(!pInputList.empty());
 }
 }
 
 
 void AMFImporter::Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& metadataList, aiNode& sceneNode) const
 void AMFImporter::Postprocess_AddMetadata(const std::list<CAMFImporter_NodeElement_Metadata*>& metadataList, aiNode& sceneNode) const
@@ -712,7 +712,7 @@ std::list<unsigned int> mesh_idx;
 	}// for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
 	}// for(const CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
 
 
 	// if meshes was created then assign new indices with current aiNode
 	// if meshes was created then assign new indices with current aiNode
-	if(mesh_idx.size() > 0)
+	if(!mesh_idx.empty())
 	{
 	{
 		std::list<unsigned int>::const_iterator mit = mesh_idx.begin();
 		std::list<unsigned int>::const_iterator mit = mesh_idx.begin();
 
 
@@ -787,7 +787,7 @@ std::list<aiNode*> ch_node;
 	}// for(const CAMFImporter_NodeElement* ne: pConstellation.Child)
 	}// for(const CAMFImporter_NodeElement* ne: pConstellation.Child)
 
 
 	// copy found aiNode's as children
 	// copy found aiNode's as children
-	if(ch_node.size() == 0) throw DeadlyImportError("<constellation> must have at least one <instance>.");
+	if(ch_node.empty()) throw DeadlyImportError("<constellation> must have at least one <instance>.");
 
 
 	size_t ch_idx = 0;
 	size_t ch_idx = 0;
 
 
@@ -883,13 +883,13 @@ nl_clean_loop:
 	if(node_list.size() > 1)
 	if(node_list.size() > 1)
 	{
 	{
 		// walk through all nodes
 		// walk through all nodes
-		for(std::list<aiNode*>::iterator nl_it = node_list.begin(); nl_it != node_list.end(); nl_it++)
+		for(std::list<aiNode*>::iterator nl_it = node_list.begin(); nl_it != node_list.end(); ++nl_it)
 		{
 		{
 			// and try to find them in another top nodes.
 			// and try to find them in another top nodes.
 			std::list<aiNode*>::const_iterator next_it = nl_it;
 			std::list<aiNode*>::const_iterator next_it = nl_it;
 
 
-			next_it++;
-			for(; next_it != node_list.end(); next_it++)
+			++next_it;
+			for(; next_it != node_list.end(); ++next_it)
 			{
 			{
 				if((*next_it)->FindNode((*nl_it)->mName) != nullptr)
 				if((*next_it)->FindNode((*nl_it)->mName) != nullptr)
 				{
 				{
@@ -907,7 +907,7 @@ nl_clean_loop:
 	//
 	//
 	//
 	//
 	// Nodes
 	// Nodes
-	if(node_list.size() > 0)
+	if(!node_list.empty())
 	{
 	{
 		std::list<aiNode*>::const_iterator nl_it = node_list.begin();
 		std::list<aiNode*>::const_iterator nl_it = node_list.begin();
 
 
@@ -924,7 +924,7 @@ nl_clean_loop:
 
 
 	//
 	//
 	// Meshes
 	// Meshes
-	if(mesh_list.size() > 0)
+	if(!mesh_list.empty())
 	{
 	{
 		std::list<aiMesh*>::const_iterator ml_it = mesh_list.begin();
 		std::list<aiMesh*>::const_iterator ml_it = mesh_list.begin();
 
 

+ 4 - 1
code/CMakeLists.txt

@@ -137,7 +137,6 @@ SET( PUBLIC_HEADERS
   ${HEADER_PATH}/irrXMLWrapper.h
   ${HEADER_PATH}/irrXMLWrapper.h
   ${HEADER_PATH}/BlobIOSystem.h
   ${HEADER_PATH}/BlobIOSystem.h
   ${HEADER_PATH}/MathFunctions.h
   ${HEADER_PATH}/MathFunctions.h
-  ${HEADER_PATH}/Macros.h
   ${HEADER_PATH}/Exceptional.h
   ${HEADER_PATH}/Exceptional.h
   ${HEADER_PATH}/ByteSwapper.h
   ${HEADER_PATH}/ByteSwapper.h
 )
 )
@@ -766,6 +765,8 @@ ADD_ASSIMP_EXPORTER( X3D
 )
 )
 
 
 ADD_ASSIMP_IMPORTER( GLTF
 ADD_ASSIMP_IMPORTER( GLTF
+  glTF/glTFCommon.h
+  glTF/glTFCommon.cpp
   glTF/glTFAsset.h
   glTF/glTFAsset.h
   glTF/glTFAsset.inl
   glTF/glTFAsset.inl
   glTF/glTFAssetWriter.h
   glTF/glTFAssetWriter.h
@@ -1057,6 +1058,8 @@ MESSAGE(STATUS "Disabled importer formats:${ASSIMP_IMPORTERS_DISABLED}")
 MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}")
 MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}")
 MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}")
 MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}")
 
 
+SOURCE_GROUP( include\\assimp    FILES ${PUBLIC_HEADERS} )
+
 SET( assimp_src
 SET( assimp_src
   # Assimp Files
   # Assimp Files
   ${Core_SRCS}
   ${Core_SRCS}

+ 4 - 3
code/Collada/ColladaExporter.cpp

@@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include "ColladaExporter.h"
 #include "ColladaExporter.h"
 #include <assimp/Bitmap.h>
 #include <assimp/Bitmap.h>
+#include <assimp/MathFunctions.h>
 #include <assimp/fast_atof.h>
 #include <assimp/fast_atof.h>
 #include <assimp/SceneCombiner.h>
 #include <assimp/SceneCombiner.h>
 #include <assimp/StringUtils.h>
 #include <assimp/StringUtils.h>
@@ -155,7 +156,7 @@ void ColladaExporter::WriteFile() {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Writes the asset header
 // Writes the asset header
 void ColladaExporter::WriteHeader() {
 void ColladaExporter::WriteHeader() {
-    static const ai_real epsilon = ai_real( 0.00001 );
+    static const ai_real epsilon = Math::getEpsilon<ai_real>();
     static const aiQuaternion x_rot(aiMatrix3x3(
     static const aiQuaternion x_rot(aiMatrix3x3(
         0, -1,  0,
         0, -1,  0,
         1,  0,  0,
         1,  0,  0,
@@ -317,7 +318,7 @@ void ColladaExporter::WriteTextures() {
 
 
             std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint);
             std::string name = mFile + "_texture_" + (i < 1000 ? "0" : "") + (i < 100 ? "0" : "") + (i < 10 ? "0" : "") + str + "." + ((const char*) texture->achFormatHint);
 
 
-            std::unique_ptr<IOStream> outfile(mIOSystem->Open(mPath + name, "wb"));
+            std::unique_ptr<IOStream> outfile(mIOSystem->Open(mPath + mIOSystem->getOsSeparator() + name, "wb"));
             if(outfile == NULL) {
             if(outfile == NULL) {
                 throw DeadlyExportError("could not open output texture file: " + mPath + name);
                 throw DeadlyExportError("could not open output texture file: " + mPath + name);
             }
             }
@@ -1671,4 +1672,4 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
 }
 }
 
 
 #endif
 #endif
-#endif
+#endif

+ 2 - 2
code/Collada/ColladaLoader.cpp

@@ -588,7 +588,7 @@ void ColladaLoader::BuildMeshesForNode(const ColladaParser& pParser, const Colla
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Find mesh from either meshes or morph target meshes
 // Find mesh from either meshes or morph target meshes
-aiMesh *ColladaLoader::findMesh(std::string meshid) {
+aiMesh *ColladaLoader::findMesh(const std::string& meshid) {
     for (unsigned int i = 0; i < mMeshes.size(); ++i) {
     for (unsigned int i = 0; i < mMeshes.size(); ++i) {
         if (std::string(mMeshes[i]->mName.data) == meshid) {
         if (std::string(mMeshes[i]->mName.data) == meshid) {
             return mMeshes[i];
             return mMeshes[i];
@@ -688,7 +688,7 @@ aiMesh* ColladaLoader::CreateMesh(const ColladaParser& pParser, const Collada::M
     Collada::MorphMethod method = Collada::Normalized;
     Collada::MorphMethod method = Collada::Normalized;
 
 
     for (std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin();
     for (std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin();
-        it != pParser.mControllerLibrary.end(); it++) {
+        it != pParser.mControllerLibrary.end(); ++it) {
         const Collada::Controller &c = it->second;
         const Collada::Controller &c = it->second;
         const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, c.mMeshId);
         const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, c.mMeshId);
 
 

+ 1 - 1
code/Collada/ColladaLoader.h

@@ -120,7 +120,7 @@ protected:
     void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode,
     void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode,
         aiNode* pTarget);
         aiNode* pTarget);
 		
 		
-    aiMesh *findMesh(std::string meshid);
+    aiMesh *findMesh(const std::string& meshid);
 
 
     /** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */
     /** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */
     aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
     aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,

+ 25 - 2
code/Common/BaseImporter.cpp

@@ -76,9 +76,25 @@ BaseImporter::~BaseImporter() {
     // nothing to do here
     // nothing to do here
 }
 }
 
 
+void BaseImporter::UpdateImporterScale( Importer* pImp )
+{
+    ai_assert(pImp != nullptr);
+    ai_assert(importerScale != 0.0);
+    ai_assert(fileScale != 0.0);
+
+    double activeScale = importerScale * fileScale;
+
+    // Set active scaling
+    pImp->SetPropertyFloat( AI_CONFIG_APP_SCALE_KEY, static_cast<float>( activeScale) );
+
+    ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale );
+}
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Imports the given file and returns the imported data.
 // Imports the given file and returns the imported data.
-aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) {
+aiScene* BaseImporter::ReadFile(Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) {
+
+
     m_progress = pImp->GetProgressHandler();
     m_progress = pImp->GetProgressHandler();
     if (nullptr == m_progress) {
     if (nullptr == m_progress) {
         return nullptr;
         return nullptr;
@@ -100,6 +116,11 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile,
     {
     {
         InternReadFile( pFile, sc.get(), &filter);
         InternReadFile( pFile, sc.get(), &filter);
 
 
+        // Calculate import scale hook - required because pImp not available anywhere else
+        // passes scale into ScaleProcess
+        UpdateImporterScale(pImp);
+
+
     } catch( const std::exception& err )    {
     } catch( const std::exception& err )    {
         // extract error description
         // extract error description
         m_ErrorText = err.what();
         m_ErrorText = err.what();
@@ -112,7 +133,7 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile,
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void BaseImporter::SetupProperties(const Importer* /*pImp*/)
+void BaseImporter::SetupProperties(const Importer* pImp)
 {
 {
     // the default implementation does nothing
     // the default implementation does nothing
 }
 }
@@ -588,6 +609,8 @@ aiScene* BatchLoader::GetImport( unsigned int which )
     return nullptr;
     return nullptr;
 }
 }
 
 
+
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void BatchLoader::LoadAll()
 void BatchLoader::LoadAll()
 {
 {

+ 60 - 101
code/Common/DefaultIOSystem.cpp

@@ -61,83 +61,66 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 using namespace Assimp;
 using namespace Assimp;
 
 
-// maximum path length
-// XXX http://insanecoding.blogspot.com/2007/11/pathmax-simply-isnt.html
-#ifdef PATH_MAX
-#   define PATHLIMIT PATH_MAX
-#else
-#   define PATHLIMIT 4096
+#ifdef _WIN32
+static std::wstring Utf8ToWide(const char* in)
+{
+    int size = MultiByteToWideChar(CP_UTF8, 0, in, -1, nullptr, 0);
+    // size includes terminating null; std::wstring adds null automatically
+    std::wstring out(static_cast<size_t>(size) - 1, L'\0');
+    MultiByteToWideChar(CP_UTF8, 0, in, -1, &out[0], size);
+    return out;
+}
+
+static std::string WideToUtf8(const wchar_t* in)
+{
+    int size = WideCharToMultiByte(CP_UTF8, 0, in, -1, nullptr, 0, nullptr, nullptr);
+    // size includes terminating null; std::string adds null automatically
+    std::string out(static_cast<size_t>(size) - 1, '\0');
+    WideCharToMultiByte(CP_UTF8, 0, in, -1, &out[0], size, nullptr, nullptr);
+    return out;
+}
 #endif
 #endif
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Tests for the existence of a file at the given path.
 // Tests for the existence of a file at the given path.
-bool DefaultIOSystem::Exists( const char* pFile) const
+bool DefaultIOSystem::Exists(const char* pFile) const
 {
 {
 #ifdef _WIN32
 #ifdef _WIN32
-    wchar_t fileName16[PATHLIMIT];
-
-#ifndef WindowsStore
-    bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
-    if (isUnicode) {
-
-        MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
-        struct __stat64 filestat;
-        if (0 != _wstat64(fileName16, &filestat)) {
-            return false;
-        }
-    } else {
-#endif
-        FILE* file = ::fopen(pFile, "rb");
-        if (!file)
-            return false;
-
-        ::fclose(file);
-#ifndef WindowsStore
+    struct __stat64 filestat;
+    if (_wstat64(Utf8ToWide(pFile).c_str(), &filestat) != 0) {
+        return false;
     }
     }
-#endif
 #else
 #else
-    FILE* file = ::fopen( pFile, "rb");
-    if( !file)
+    FILE* file = ::fopen(pFile, "rb");
+    if (!file)
         return false;
         return false;
 
 
-    ::fclose( file);
+    ::fclose(file);
 #endif
 #endif
     return true;
     return true;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Open a new file with a given path.
 // Open a new file with a given path.
-IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
+IOStream* DefaultIOSystem::Open(const char* strFile, const char* strMode)
 {
 {
-    ai_assert(NULL != strFile);
-    ai_assert(NULL != strMode);
+    ai_assert(strFile != nullptr);
+    ai_assert(strMode != nullptr);
     FILE* file;
     FILE* file;
 #ifdef _WIN32
 #ifdef _WIN32
-    wchar_t fileName16[PATHLIMIT];
-#ifndef WindowsStore
-    bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
-    if (isUnicode) {
-        MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
-        std::string mode8(strMode);
-        file = ::_wfopen(fileName16, std::wstring(mode8.begin(), mode8.end()).c_str());
-    } else {
-#endif
-        file = ::fopen(strFile, strMode);
-#ifndef WindowsStore
-    }
-#endif
+    file = ::_wfopen(Utf8ToWide(strFile).c_str(), Utf8ToWide(strMode).c_str());
 #else
 #else
     file = ::fopen(strFile, strMode);
     file = ::fopen(strFile, strMode);
 #endif
 #endif
-    if (nullptr == file)
+    if (!file)
         return nullptr;
         return nullptr;
 
 
-    return new DefaultIOStream(file, (std::string) strFile);
+    return new DefaultIOStream(file, strFile);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Closes the given file and releases all resources associated with it.
 // Closes the given file and releases all resources associated with it.
-void DefaultIOSystem::Close( IOStream* pFile)
+void DefaultIOSystem::Close(IOStream* pFile)
 {
 {
     delete pFile;
     delete pFile;
 }
 }
@@ -155,78 +138,56 @@ char DefaultIOSystem::getOsSeparator() const
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // IOSystem default implementation (ComparePaths isn't a pure virtual function)
 // IOSystem default implementation (ComparePaths isn't a pure virtual function)
-bool IOSystem::ComparePaths (const char* one, const char* second) const
+bool IOSystem::ComparePaths(const char* one, const char* second) const
 {
 {
-    return !ASSIMP_stricmp(one,second);
+    return !ASSIMP_stricmp(one, second);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Convert a relative path into an absolute path
 // Convert a relative path into an absolute path
-inline static void MakeAbsolutePath (const char* in, char* _out)
+inline static std::string MakeAbsolutePath(const char* in)
 {
 {
-    ai_assert(in && _out);
-#if defined( _MSC_VER ) || defined( __MINGW32__ )
-#ifndef WindowsStore
-    bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0;
-    if (isUnicode) {
-        wchar_t out16[PATHLIMIT];
-        wchar_t in16[PATHLIMIT];
-        MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, in, -1, out16, PATHLIMIT);
-        wchar_t* ret = ::_wfullpath(out16, in16, PATHLIMIT);
-        if (ret) {
-            WideCharToMultiByte(CP_UTF8, MB_PRECOMPOSED, out16, -1, _out, PATHLIMIT, nullptr, nullptr);
-        }
-        if (!ret) {
-            // preserve the input path, maybe someone else is able to fix
-            // the path before it is accessed (e.g. our file system filter)
-            ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
-            strcpy(_out, in);
-        }
-
-    } else {
-#endif
-        char* ret = :: _fullpath(_out, in, PATHLIMIT);
-        if (!ret) {
-            // preserve the input path, maybe someone else is able to fix
-            // the path before it is accessed (e.g. our file system filter)
-            ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
-            strcpy(_out, in);
-        }
-#ifndef WindowsStore
+    ai_assert(in);
+    std::string out;
+#ifdef _WIN32
+    wchar_t* ret = ::_wfullpath(nullptr, Utf8ToWide(in).c_str(), 0);
+    if (ret) {
+        out = WideToUtf8(ret);
+        free(ret);
     }
     }
-#endif
 #else
 #else
-    // use realpath
-    char* ret = realpath(in, _out);
-    if(!ret) {
+    char* ret = realpath(in, nullptr);
+    if (ret) {
+        out = ret;
+        free(ret);
+    }
+#endif
+    if (!ret) {
         // preserve the input path, maybe someone else is able to fix
         // preserve the input path, maybe someone else is able to fix
         // the path before it is accessed (e.g. our file system filter)
         // the path before it is accessed (e.g. our file system filter)
         ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
         ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
-        strcpy(_out,in);
+        out = in;
     }
     }
-#endif
+    return out;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // DefaultIOSystem's more specialized implementation
 // DefaultIOSystem's more specialized implementation
-bool DefaultIOSystem::ComparePaths (const char* one, const char* second) const
+bool DefaultIOSystem::ComparePaths(const char* one, const char* second) const
 {
 {
     // chances are quite good both paths are formatted identically,
     // chances are quite good both paths are formatted identically,
     // so we can hopefully return here already
     // so we can hopefully return here already
-    if( !ASSIMP_stricmp(one,second) )
+    if (!ASSIMP_stricmp(one, second))
         return true;
         return true;
 
 
-    char temp1[PATHLIMIT];
-    char temp2[PATHLIMIT];
-
-    MakeAbsolutePath (one, temp1);
-    MakeAbsolutePath (second, temp2);
+    std::string temp1 = MakeAbsolutePath(one);
+    std::string temp2 = MakeAbsolutePath(second);
 
 
-    return !ASSIMP_stricmp(temp1,temp2);
+    return !ASSIMP_stricmp(temp1, temp2);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-std::string DefaultIOSystem::fileName( const std::string &path )
+std::string DefaultIOSystem::fileName(const std::string& path)
 {
 {
     std::string ret = path;
     std::string ret = path;
     std::size_t last = ret.find_last_of("\\/");
     std::size_t last = ret.find_last_of("\\/");
@@ -235,16 +196,16 @@ std::string DefaultIOSystem::fileName( const std::string &path )
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-std::string DefaultIOSystem::completeBaseName( const std::string &path )
+std::string DefaultIOSystem::completeBaseName(const std::string& path)
 {
 {
     std::string ret = fileName(path);
     std::string ret = fileName(path);
     std::size_t pos = ret.find_last_of('.');
     std::size_t pos = ret.find_last_of('.');
-    if(pos != ret.npos) ret = ret.substr(0, pos);
+    if (pos != std::string::npos) ret = ret.substr(0, pos);
     return ret;
     return ret;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-std::string DefaultIOSystem::absolutePath( const std::string &path )
+std::string DefaultIOSystem::absolutePath(const std::string& path)
 {
 {
     std::string ret = path;
     std::string ret = path;
     std::size_t last = ret.find_last_of("\\/");
     std::size_t last = ret.find_last_of("\\/");
@@ -253,5 +214,3 @@ std::string DefaultIOSystem::absolutePath( const std::string &path )
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-
-#undef PATHLIMIT

+ 5 - 30
code/Common/Exporter.cpp

@@ -315,34 +315,6 @@ const aiExportDataBlob* Exporter::ExportToBlob( const aiScene* pScene, const cha
     return pimpl->blob;
     return pimpl->blob;
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-bool IsVerboseFormat(const aiMesh* mesh) {
-    // avoid slow vector<bool> specialization
-    std::vector<unsigned int> seen(mesh->mNumVertices,0);
-    for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
-        const aiFace& f = mesh->mFaces[i];
-        for(unsigned int j = 0; j < f.mNumIndices; ++j) {
-            if(++seen[f.mIndices[j]] == 2) {
-                // found a duplicate index
-                return false;
-            }
-        }
-    }
-
-    return true;
-}
-
-// ------------------------------------------------------------------------------------------------
-bool IsVerboseFormat(const aiScene* pScene) {
-    for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
-        if(!IsVerboseFormat(pScene->mMeshes[i])) {
-            return false;
-        }
-    }
-
-    return true;
-}
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
 aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
         unsigned int pPreprocessing, const ExportProperties* pProperties) {
         unsigned int pPreprocessing, const ExportProperties* pProperties) {
@@ -352,7 +324,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
     // format. They will likely not be aware that there is a flag in the scene to indicate
     // format. They will likely not be aware that there is a flag in the scene to indicate
     // this, however. To avoid surprises and bug reports, we check for duplicates in
     // this, however. To avoid surprises and bug reports, we check for duplicates in
     // meshes upfront.
     // meshes upfront.
-    const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || IsVerboseFormat(pScene);
+    const bool is_verbose_format = !(pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT) || MakeVerboseFormatProcess::IsVerboseFormat(pScene);
 
 
     pimpl->mProgressHandler->UpdateFileWrite(0, 4);
     pimpl->mProgressHandler->UpdateFileWrite(0, 4);
 
 
@@ -472,7 +444,10 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
                 }
                 }
 
 
                 ExportProperties emptyProperties;  // Never pass NULL ExportProperties so Exporters don't have to worry.
                 ExportProperties emptyProperties;  // Never pass NULL ExportProperties so Exporters don't have to worry.
-                exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProperties ? pProperties : &emptyProperties);
+                ExportProperties* pProp = pProperties ? (ExportProperties*)pProperties : &emptyProperties;
+                                pProp->SetPropertyBool("bJoinIdenticalVertices", must_join_again);
+                                exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp);
+                exp.mExportFunction(pPath,pimpl->mIOSystem.get(),scenecopy.get(), pProp);
 
 
                 pimpl->mProgressHandler->UpdateFileWrite(4, 4);
                 pimpl->mProgressHandler->UpdateFileWrite(4, 4);
             } catch (DeadlyExportError& err) {
             } catch (DeadlyExportError& err) {

+ 50 - 0
code/Common/SceneCombiner.cpp

@@ -1091,6 +1091,35 @@ void SceneCombiner::Copy( aiMesh** _dest, const aiMesh* src ) {
         aiFace& f = dest->mFaces[i];
         aiFace& f = dest->mFaces[i];
         GetArrayCopy(f.mIndices,f.mNumIndices);
         GetArrayCopy(f.mIndices,f.mNumIndices);
     }
     }
+
+    // make a deep copy of all blend shapes
+    CopyPtrArray(dest->mAnimMeshes, dest->mAnimMeshes, dest->mNumAnimMeshes);
+}
+
+// ------------------------------------------------------------------------------------------------
+void SceneCombiner::Copy(aiAnimMesh** _dest, const aiAnimMesh* src) {
+    if (nullptr == _dest || nullptr == src) {
+        return;
+    }
+
+    aiAnimMesh* dest = *_dest = new aiAnimMesh();
+
+    // get a flat copy
+    ::memcpy(dest, src, sizeof(aiAnimMesh));
+
+    // and reallocate all arrays
+    GetArrayCopy(dest->mVertices, dest->mNumVertices);
+    GetArrayCopy(dest->mNormals, dest->mNumVertices);
+    GetArrayCopy(dest->mTangents, dest->mNumVertices);
+    GetArrayCopy(dest->mBitangents, dest->mNumVertices);
+
+    unsigned int n = 0;
+    while (dest->HasTextureCoords(n))
+        GetArrayCopy(dest->mTextureCoords[n++], dest->mNumVertices);
+
+    n = 0;
+    while (dest->HasVertexColors(n))
+        GetArrayCopy(dest->mColors[n++], dest->mNumVertices);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -1167,6 +1196,7 @@ void SceneCombiner::Copy( aiAnimation** _dest, const aiAnimation* src ) {
 
 
     // and reallocate all arrays
     // and reallocate all arrays
     CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
     CopyPtrArray( dest->mChannels, src->mChannels, dest->mNumChannels );
+    CopyPtrArray( dest->mMorphMeshChannels, src->mMorphMeshChannels, dest->mNumMorphMeshChannels );
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -1186,6 +1216,26 @@ void SceneCombiner::Copy(aiNodeAnim** _dest, const aiNodeAnim* src) {
     GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys );
     GetArrayCopy( dest->mRotationKeys, dest->mNumRotationKeys );
 }
 }
 
 
+void SceneCombiner::Copy(aiMeshMorphAnim** _dest, const aiMeshMorphAnim* src) {
+    if ( nullptr == _dest || nullptr == src ) {
+        return;
+    }
+
+    aiMeshMorphAnim* dest = *_dest = new aiMeshMorphAnim();
+
+    // get a flat copy
+    ::memcpy(dest,src,sizeof(aiMeshMorphAnim));
+
+    // and reallocate all arrays
+    GetArrayCopy( dest->mKeys, dest->mNumKeys );
+    for (ai_uint i = 0; i < dest->mNumKeys;++i) {
+        dest->mKeys[i].mValues = new unsigned int[dest->mKeys[i].mNumValuesAndWeights];
+        dest->mKeys[i].mWeights = new double[dest->mKeys[i].mNumValuesAndWeights];
+        ::memcpy(dest->mKeys[i].mValues, src->mKeys[i].mValues, dest->mKeys[i].mNumValuesAndWeights * sizeof(unsigned int));
+        ::memcpy(dest->mKeys[i].mWeights, src->mKeys[i].mWeights, dest->mKeys[i].mNumValuesAndWeights * sizeof(double));
+    }
+}
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void SceneCombiner::Copy( aiCamera** _dest,const  aiCamera* src) {
 void SceneCombiner::Copy( aiCamera** _dest,const  aiCamera* src) {
     if ( nullptr == _dest || nullptr == src ) {
     if ( nullptr == _dest || nullptr == src ) {

+ 2 - 2
code/Common/Version.cpp

@@ -46,8 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include "ScenePrivate.h"
 #include "ScenePrivate.h"
 
 
-static const unsigned int MajorVersion = 4;
-static const unsigned int MinorVersion = 1;
+static const unsigned int MajorVersion = 5;
+static const unsigned int MinorVersion = 0;
 
 
 // --------------------------------------------------------------------------------
 // --------------------------------------------------------------------------------
 // Legal information string - don't remove this.
 // Legal information string - don't remove this.

+ 23 - 49
code/FBX/FBXConverter.cpp

@@ -55,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "FBXImporter.h"
 #include "FBXImporter.h"
 
 
 #include <assimp/StringComparison.h>
 #include <assimp/StringComparison.h>
+#include <assimp/MathFunctions.h>
 
 
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 
 
@@ -78,7 +79,7 @@ namespace Assimp {
 
 
 #define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
 #define CONVERT_FBX_TIME(time) static_cast<double>(time) / 46186158000L
 
 
-        FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit )
+        FBXConverter::FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones )
         : defaultMaterialIndex()
         : defaultMaterialIndex()
         , lights()
         , lights()
         , cameras()
         , cameras()
@@ -90,8 +91,7 @@ namespace Assimp {
         , mNodeNames()
         , mNodeNames()
         , anim_fps()
         , anim_fps()
         , out(out)
         , out(out)
-        , doc(doc)
-        , mCurrentUnit(FbxUnit::cm) {
+        , doc(doc) {
             // animations need to be converted first since this will
             // animations need to be converted first since this will
             // populate the node_anim_chain_bits map, which is needed
             // populate the node_anim_chain_bits map, which is needed
             // to determine which nodes need to be generated.
             // to determine which nodes need to be generated.
@@ -119,7 +119,6 @@ namespace Assimp {
 
 
             ConvertGlobalSettings();
             ConvertGlobalSettings();
             TransferDataToScene();
             TransferDataToScene();
-            ConvertToUnitScale(unit);
 
 
             // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE
             // if we didn't read any meshes set the AI_SCENE_FLAGS_INCOMPLETE
             // to make sure the scene passes assimp's validation. FBX files
             // to make sure the scene passes assimp's validation. FBX files
@@ -555,7 +554,7 @@ namespace Assimp {
                 return;
                 return;
             }
             }
 
 
-            const float angle_epsilon = 1e-6f;
+            const float angle_epsilon = Math::getEpsilon<float>();
 
 
             out = aiMatrix4x4();
             out = aiMatrix4x4();
 
 
@@ -696,7 +695,7 @@ namespace Assimp {
             std::fill_n(chain, static_cast<unsigned int>(TransformationComp_MAXIMUM), aiMatrix4x4());
             std::fill_n(chain, static_cast<unsigned int>(TransformationComp_MAXIMUM), aiMatrix4x4());
 
 
             // generate transformation matrices for all the different transformation components
             // generate transformation matrices for all the different transformation components
-            const float zero_epsilon = 1e-6f;
+            const float zero_epsilon = Math::getEpsilon<float>();
             const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
             const aiVector3D all_ones(1.0f, 1.0f, 1.0f);
 
 
             const aiVector3D& PreRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
             const aiVector3D& PreRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
@@ -2003,6 +2002,21 @@ namespace Assimp {
             TrySetTextureProperties(out_mat, textures, "Maya|SpecularTexture", aiTextureType_SPECULAR, mesh);
             TrySetTextureProperties(out_mat, textures, "Maya|SpecularTexture", aiTextureType_SPECULAR, mesh);
             TrySetTextureProperties(out_mat, textures, "Maya|FalloffTexture", aiTextureType_OPACITY, mesh);
             TrySetTextureProperties(out_mat, textures, "Maya|FalloffTexture", aiTextureType_OPACITY, mesh);
             TrySetTextureProperties(out_mat, textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh);
             TrySetTextureProperties(out_mat, textures, "Maya|ReflectionMapTexture", aiTextureType_REFLECTION, mesh);
+            
+            // Maya PBR
+            TrySetTextureProperties(out_mat, textures, "Maya|baseColor|file", aiTextureType_BASE_COLOR, mesh);
+            TrySetTextureProperties(out_mat, textures, "Maya|normalCamera|file", aiTextureType_NORMAL_CAMERA, mesh);
+            TrySetTextureProperties(out_mat, textures, "Maya|emissionColor|file", aiTextureType_EMISSION_COLOR, mesh);
+            TrySetTextureProperties(out_mat, textures, "Maya|metalness|file", aiTextureType_METALNESS, mesh);
+            TrySetTextureProperties(out_mat, textures, "Maya|diffuseRoughness|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
+            
+            // Maya stingray
+            TrySetTextureProperties(out_mat, textures, "Maya|TEX_color_map|file", aiTextureType_BASE_COLOR, mesh);
+            TrySetTextureProperties(out_mat, textures, "Maya|TEX_normal_map|file", aiTextureType_NORMAL_CAMERA, mesh);
+            TrySetTextureProperties(out_mat, textures, "Maya|TEX_emissive_map|file", aiTextureType_EMISSION_COLOR, mesh);
+            TrySetTextureProperties(out_mat, textures, "Maya|TEX_metallic_map|file", aiTextureType_METALNESS, mesh);
+            TrySetTextureProperties(out_mat, textures, "Maya|TEX_roughness_map|file", aiTextureType_DIFFUSE_ROUGHNESS, mesh);
+            TrySetTextureProperties(out_mat, textures, "Maya|TEX_ao_map|file", aiTextureType_AMBIENT_OCCLUSION, mesh);            
         }
         }
 
 
         void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh)
         void FBXConverter::SetTextureProperties(aiMaterial* out_mat, const LayeredTextureMap& layeredTextures, const MeshGeometry* const mesh)
@@ -2954,7 +2968,7 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
                 TransformationCompDefaultValue(comp)
                 TransformationCompDefaultValue(comp)
                 );
                 );
 
 
-            const float epsilon = 1e-6f;
+            const float epsilon = Math::getEpsilon<float>();
             return (dyn_val - static_val).SquareLength() < epsilon;
             return (dyn_val - static_val).SquareLength() < epsilon;
         }
         }
 
 
@@ -3537,46 +3551,6 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
             out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate());
             out->mMetaData->Set(14, "CustomFrameRate", doc.GlobalSettings().CustomFrameRate());
         }
         }
 
 
-        void FBXConverter::ConvertToUnitScale( FbxUnit unit ) {
-            if (mCurrentUnit == unit) {
-                return;
-            }
-
-            ai_real scale = 1.0;
-            if (mCurrentUnit == FbxUnit::cm) {
-                if (unit == FbxUnit::m) {
-                    scale = (ai_real)0.01;
-                } else if (unit == FbxUnit::km) {
-                    scale = (ai_real)0.00001;
-                }
-            } else if (mCurrentUnit == FbxUnit::m) {
-                if (unit == FbxUnit::cm) {
-                    scale = (ai_real)100.0;
-                } else if (unit == FbxUnit::km) {
-                    scale = (ai_real)0.001;
-                }
-            } else if (mCurrentUnit == FbxUnit::km) {
-                if (unit == FbxUnit::cm) {
-                    scale = (ai_real)100000.0;
-                } else if (unit == FbxUnit::m) {
-                    scale = (ai_real)1000.0;
-                }
-            }
-            
-            for (auto mesh : meshes) {
-                if (nullptr == mesh) {
-                    continue;
-                }
-
-                if (mesh->HasPositions()) {
-                    for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
-                        aiVector3D &pos = mesh->mVertices[i];
-                        pos *= scale;
-                    }
-                }
-            }
-        }
-
         void FBXConverter::TransferDataToScene()
         void FBXConverter::TransferDataToScene()
         {
         {
             ai_assert(!out->mMeshes);
             ai_assert(!out->mMeshes);
@@ -3630,9 +3604,9 @@ void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTa
         }
         }
 
 
         // ------------------------------------------------------------------------------------------------
         // ------------------------------------------------------------------------------------------------
-        void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit)
+        void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones)
         {
         {
-            FBXConverter converter(out, doc, removeEmptyBones, unit);
+            FBXConverter converter(out, doc, removeEmptyBones);
         }
         }
 
 
     } // !FBX
     } // !FBX

+ 2 - 17
code/FBX/FBXConverter.h

@@ -76,23 +76,13 @@ namespace Assimp {
 namespace FBX {
 namespace FBX {
 
 
 class Document;
 class Document;
-
-enum class FbxUnit {
-    cm = 0,
-    m,
-    km,
-    NumUnits,
-
-    Undefined
-};
-
 /** 
 /** 
  *  Convert a FBX #Document to #aiScene
  *  Convert a FBX #Document to #aiScene
  *  @param out Empty scene to be populated
  *  @param out Empty scene to be populated
  *  @param doc Parsed FBX document
  *  @param doc Parsed FBX document
  *  @param removeEmptyBones Will remove bones, which do not have any references to vertices.
  *  @param removeEmptyBones Will remove bones, which do not have any references to vertices.
  */
  */
-void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit);
+void ConvertToAssimpScene(aiScene* out, const Document& doc, bool removeEmptyBones);
 
 
 /** Dummy class to encapsulate the conversion process */
 /** Dummy class to encapsulate the conversion process */
 class FBXConverter {
 class FBXConverter {
@@ -123,7 +113,7 @@ public:
     };
     };
 
 
 public:
 public:
-    FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones, FbxUnit unit);
+    FBXConverter(aiScene* out, const Document& doc, bool removeEmptyBones);
     ~FBXConverter();
     ~FBXConverter();
 
 
 private:
 private:
@@ -430,10 +420,6 @@ private:
 
 
     void ConvertGlobalSettings();
     void ConvertGlobalSettings();
 
 
-    // ------------------------------------------------------------------------------------------------
-    //  Will perform the conversion from a given unit to the requested unit.
-    void ConvertToUnitScale(FbxUnit unit);
-
     // ------------------------------------------------------------------------------------------------
     // ------------------------------------------------------------------------------------------------
     // copy generated meshes, animations, lights, cameras and textures to the output scene
     // copy generated meshes, animations, lights, cameras and textures to the output scene
     void TransferDataToScene();
     void TransferDataToScene();
@@ -470,7 +456,6 @@ private:
 
 
     aiScene* const out;
     aiScene* const out;
     const FBX::Document& doc;
     const FBX::Document& doc;
-    FbxUnit mCurrentUnit;
 };
 };
 
 
 }
 }

+ 1 - 5
code/FBX/FBXExportProperty.cpp

@@ -59,11 +59,7 @@ namespace FBX {
 
 
 FBXExportProperty::FBXExportProperty(bool v)
 FBXExportProperty::FBXExportProperty(bool v)
 : type('C')
 : type('C')
-, data(1) {
-    data = {
-        uint8_t(v)
-    };
-}
+, data(1, uint8_t(v)) {}
 
 
 FBXExportProperty::FBXExportProperty(int16_t v)
 FBXExportProperty::FBXExportProperty(int16_t v)
 : type('Y')
 : type('Y')

+ 85 - 37
code/FBX/FBXExporter.cpp

@@ -67,6 +67,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <vector>
 #include <vector>
 #include <array>
 #include <array>
 #include <unordered_set>
 #include <unordered_set>
+#include <numeric>
 
 
 // RESOURCES:
 // RESOURCES:
 // https://code.blender.org/2013/08/fbx-binary-file-format-specification/
 // https://code.blender.org/2013/08/fbx-binary-file-format-specification/
@@ -1005,6 +1006,9 @@ void FBXExporter::WriteObjects ()
     object_node.EndProperties(outstream, binary, indent);
     object_node.EndProperties(outstream, binary, indent);
     object_node.BeginChildren(outstream, binary, indent);
     object_node.BeginChildren(outstream, binary, indent);
 
 
+    bool bJoinIdenticalVertices = mProperties->GetPropertyBool("bJoinIdenticalVertices", true);
+    std::vector<std::vector<int32_t>> vVertexIndice;//save vertex_indices as it is needed later
+
     // geometry (aiMesh)
     // geometry (aiMesh)
     mesh_uids.clear();
     mesh_uids.clear();
     indent = 1;
     indent = 1;
@@ -1031,21 +1035,35 @@ void FBXExporter::WriteObjects ()
         std::vector<int32_t> vertex_indices;
         std::vector<int32_t> vertex_indices;
         // map of vertex value to its index in the data vector
         // map of vertex value to its index in the data vector
         std::map<aiVector3D,size_t> index_by_vertex_value;
         std::map<aiVector3D,size_t> index_by_vertex_value;
-        int32_t index = 0;
-        for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
-            aiVector3D vtx = m->mVertices[vi];
-            auto elem = index_by_vertex_value.find(vtx);
-            if (elem == index_by_vertex_value.end()) {
-                vertex_indices.push_back(index);
-                index_by_vertex_value[vtx] = index;
-                flattened_vertices.push_back(vtx[0]);
-                flattened_vertices.push_back(vtx[1]);
-                flattened_vertices.push_back(vtx[2]);
-                ++index;
-            } else {
-                vertex_indices.push_back(int32_t(elem->second));
+        if(bJoinIdenticalVertices){
+            int32_t index = 0;
+            for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
+                aiVector3D vtx = m->mVertices[vi];
+                auto elem = index_by_vertex_value.find(vtx);
+                if (elem == index_by_vertex_value.end()) {
+                    vertex_indices.push_back(index);
+                    index_by_vertex_value[vtx] = index;
+                    flattened_vertices.push_back(vtx[0]);
+                    flattened_vertices.push_back(vtx[1]);
+                    flattened_vertices.push_back(vtx[2]);
+                    ++index;
+                } else {
+                    vertex_indices.push_back(int32_t(elem->second));
+                }
+            }
+        }
+        else { // do not join vertex, respect the export flag
+            vertex_indices.resize(m->mNumVertices);
+            std::iota(vertex_indices.begin(), vertex_indices.end(), 0);
+            for(unsigned int v = 0; v < m->mNumVertices; ++ v) {
+                aiVector3D vtx = m->mVertices[v];
+                flattened_vertices.push_back(vtx.x);
+                flattened_vertices.push_back(vtx.y);
+                flattened_vertices.push_back(vtx.z);
             }
             }
         }
         }
+        vVertexIndice.push_back(vertex_indices);
+
         FBX::Node::WritePropertyNode(
         FBX::Node::WritePropertyNode(
             "Vertices", flattened_vertices, outstream, binary, indent
             "Vertices", flattened_vertices, outstream, binary, indent
         );
         );
@@ -1116,6 +1134,51 @@ void FBXExporter::WriteObjects ()
             normals.End(outstream, binary, indent, true);
             normals.End(outstream, binary, indent, true);
         }
         }
 
 
+        // colors, if any
+        // TODO only one color channel currently
+        const int32_t colorChannelIndex = 0;
+        if (m->HasVertexColors(colorChannelIndex)) {
+            FBX::Node vertexcolors("LayerElementColor", int32_t(colorChannelIndex));
+            vertexcolors.Begin(outstream, binary, indent);
+            vertexcolors.DumpProperties(outstream, binary, indent);
+            vertexcolors.EndProperties(outstream, binary, indent);
+            vertexcolors.BeginChildren(outstream, binary, indent);
+            indent = 3;
+            FBX::Node::WritePropertyNode(
+                "Version", int32_t(101), outstream, binary, indent
+            );
+            char layerName[8];
+            sprintf(layerName, "COLOR_%d", colorChannelIndex);
+            FBX::Node::WritePropertyNode(
+                "Name", (const char*)layerName, outstream, binary, indent
+            );
+            FBX::Node::WritePropertyNode(
+                "MappingInformationType", "ByPolygonVertex",
+                outstream, binary, indent
+            );
+            FBX::Node::WritePropertyNode(
+                "ReferenceInformationType", "Direct",
+                outstream, binary, indent
+            );
+            std::vector<double> color_data;
+            color_data.reserve(4 * polygon_data.size());
+            for (size_t fi = 0; fi < m->mNumFaces; ++fi) {
+                const aiFace &f = m->mFaces[fi];
+                for (size_t pvi = 0; pvi < f.mNumIndices; ++pvi) {
+                    const aiColor4D &c = m->mColors[colorChannelIndex][f.mIndices[pvi]];
+                    color_data.push_back(c.r);
+                    color_data.push_back(c.g);
+                    color_data.push_back(c.b);
+                    color_data.push_back(c.a);
+                }
+            }
+            FBX::Node::WritePropertyNode(
+                "Colors", color_data, outstream, binary, indent
+            );
+            indent = 2;
+            vertexcolors.End(outstream, binary, indent, true);
+        }
+        
         // uvs, if any
         // uvs, if any
         for (size_t uvi = 0; uvi < m->GetNumUVChannels(); ++uvi) {
         for (size_t uvi = 0; uvi < m->GetNumUVChannels(); ++uvi) {
             if (m->mNumUVComponents[uvi] > 2) {
             if (m->mNumUVComponents[uvi] > 2) {
@@ -1209,6 +1272,11 @@ void FBXExporter::WriteObjects ()
         le.AddChild("Type", "LayerElementNormal");
         le.AddChild("Type", "LayerElementNormal");
         le.AddChild("TypedIndex", int32_t(0));
         le.AddChild("TypedIndex", int32_t(0));
         layer.AddChild(le);
         layer.AddChild(le);
+        // TODO only 1 color channel currently
+        le = FBX::Node("LayerElement");
+        le.AddChild("Type", "LayerElementColor");
+        le.AddChild("TypedIndex", int32_t(0));
+        layer.AddChild(le);
         le = FBX::Node("LayerElement");
         le = FBX::Node("LayerElement");
         le.AddChild("Type", "LayerElementMaterial");
         le.AddChild("Type", "LayerElementMaterial");
         le.AddChild("TypedIndex", int32_t(0));
         le.AddChild("TypedIndex", int32_t(0));
@@ -1221,7 +1289,7 @@ void FBXExporter::WriteObjects ()
 
 
         for(unsigned int lr = 1; lr < m->GetNumUVChannels(); ++ lr)
         for(unsigned int lr = 1; lr < m->GetNumUVChannels(); ++ lr)
         {
         {
-            FBX::Node layerExtra("Layer", int32_t(1));
+            FBX::Node layerExtra("Layer", int32_t(lr));
             layerExtra.AddChild("Version", int32_t(100));
             layerExtra.AddChild("Version", int32_t(100));
             FBX::Node leExtra("LayerElement");
             FBX::Node leExtra("LayerElement");
             leExtra.AddChild("Type", "LayerElementUV");
             leExtra.AddChild("Type", "LayerElementUV");
@@ -1748,28 +1816,8 @@ void FBXExporter::WriteObjects ()
         // connect it
         // connect it
         connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
         connections.emplace_back("C", "OO", deformer_uid, mesh_uids[mi]);
 
 
-        // we will be indexing by vertex...
-        // but there might be a different number of "vertices"
-        // between assimp and our output FBX.
-        // this code is cut-and-pasted from the geometry section above...
-        // ideally this should not be so.
-        // ---
-        // index of original vertex in vertex data vector
-        std::vector<int32_t> vertex_indices;
-        // map of vertex value to its index in the data vector
-        std::map<aiVector3D,size_t> index_by_vertex_value;
-        int32_t index = 0;
-        for (size_t vi = 0; vi < m->mNumVertices; ++vi) {
-            aiVector3D vtx = m->mVertices[vi];
-            auto elem = index_by_vertex_value.find(vtx);
-            if (elem == index_by_vertex_value.end()) {
-                vertex_indices.push_back(index);
-                index_by_vertex_value[vtx] = index;
-                ++index;
-            } else {
-                vertex_indices.push_back(int32_t(elem->second));
-            }
-        }
+        //computed before
+        std::vector<int32_t>& vertex_indices = vVertexIndice[mi];
 
 
         // TODO, FIXME: this won't work if anything is not in the bind pose.
         // TODO, FIXME: this won't work if anything is not in the bind pose.
         // for now if such a situation is detected, we throw an exception.
         // for now if such a situation is detected, we throw an exception.
@@ -2435,7 +2483,7 @@ void FBXExporter::WriteModelNodes(
 void FBXExporter::WriteAnimationCurveNode(
 void FBXExporter::WriteAnimationCurveNode(
     StreamWriterLE& outstream,
     StreamWriterLE& outstream,
     int64_t uid,
     int64_t uid,
-    std::string name, // "T", "R", or "S"
+    const std::string& name, // "T", "R", or "S"
     aiVector3D default_value,
     aiVector3D default_value,
     std::string property_name, // "Lcl Translation" etc
     std::string property_name, // "Lcl Translation" etc
     int64_t layer_uid,
     int64_t layer_uid,

+ 1 - 1
code/FBX/FBXExporter.h

@@ -156,7 +156,7 @@ namespace Assimp
         void WriteAnimationCurveNode(
         void WriteAnimationCurveNode(
             StreamWriterLE& outstream,
             StreamWriterLE& outstream,
             int64_t uid,
             int64_t uid,
-            std::string name, // "T", "R", or "S"
+            const std::string& name, // "T", "R", or "S"
             aiVector3D default_value,
             aiVector3D default_value,
             std::string property_name, // "Lcl Translation" etc
             std::string property_name, // "Lcl Translation" etc
             int64_t animation_layer_uid,
             int64_t animation_layer_uid,

+ 8 - 9
code/FBX/FBXImporter.cpp

@@ -185,16 +185,15 @@ void FBXImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
         // take the raw parse-tree and convert it to a FBX DOM
         // take the raw parse-tree and convert it to a FBX DOM
         Document doc(parser,settings);
         Document doc(parser,settings);
 
 
-        FbxUnit unit(FbxUnit::cm);
-        if (settings.convertToMeters) {
-            unit = FbxUnit::m;
-        }
-
         // convert the FBX DOM to aiScene
         // convert the FBX DOM to aiScene
-        ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones, unit);
-        
-        // units is relative to CM :) we need it in meters for assimp
-        SetFileScale( doc.GlobalSettings().UnitScaleFactor() * 0.01f);
+        ConvertToAssimpScene(pScene, doc, settings.removeEmptyBones);
+
+        // size relative to cm
+        float size_relative_to_cm = doc.GlobalSettings().UnitScaleFactor();
+
+        // Set FBX file scale is relative to CM must be converted to M for
+        // assimp universal format (M)
+        SetFileScale( size_relative_to_cm * 0.01f);
 
 
         std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
         std::for_each(tokens.begin(),tokens.end(),Util::delete_fun<Token>());
     }
     }

+ 3 - 4
code/Importer/IFC/IFCCurve.cpp

@@ -311,10 +311,9 @@ class TrimmedCurve : public BoundedCurve {
 public:
 public:
     // --------------------------------------------------
     // --------------------------------------------------
     TrimmedCurve(const Schema_2x3::IfcTrimmedCurve& entity, ConversionData& conv)
     TrimmedCurve(const Schema_2x3::IfcTrimmedCurve& entity, ConversionData& conv)
-        : BoundedCurve(entity,conv)
+        : BoundedCurve(entity,conv),
+          base(std::shared_ptr<const Curve>(Curve::Convert(entity.BasisCurve,conv)))
     {
     {
-        base = std::shared_ptr<const Curve>(Curve::Convert(entity.BasisCurve,conv));
-
         typedef std::shared_ptr<const STEP::EXPRESS::DataType> Entry;
         typedef std::shared_ptr<const STEP::EXPRESS::DataType> Entry;
 
 
         // for some reason, trimmed curves can either specify a parametric value
         // for some reason, trimmed curves can either specify a parametric value
@@ -500,7 +499,7 @@ bool Curve::InRange(IfcFloat u) const {
     if (IsClosed()) {
     if (IsClosed()) {
         return true;
         return true;
     }
     }
-    const IfcFloat epsilon = 1e-5;
+    const IfcFloat epsilon = Math::getEpsilon<float>();
     return u - range.first > -epsilon && range.second - u > -epsilon;
     return u - range.first > -epsilon && range.second - u > -epsilon;
 }
 }
 #endif
 #endif

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

@@ -128,7 +128,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
         outer_polygon_it = begin + master_bounds;
         outer_polygon_it = begin + master_bounds;
     }
     }
     else {
     else {
-        for(iit = begin; iit != end; iit++) {
+        for(iit = begin; iit != end; ++iit) {
             // find the polygon with the largest area and take it as the outer bound.
             // find the polygon with the largest area and take it as the outer bound.
             IfcVector3& n = normals[std::distance(begin,iit)];
             IfcVector3& n = normals[std::distance(begin,iit)];
             const IfcFloat area = n.SquareLength();
             const IfcFloat area = n.SquareLength();

+ 3 - 3
code/Importer/IFC/IFCOpenings.cpp

@@ -593,7 +593,7 @@ typedef std::vector<std::pair<
 bool BoundingBoxesAdjacent(const BoundingBox& bb, const BoundingBox& ibb)
 bool BoundingBoxesAdjacent(const BoundingBox& bb, const BoundingBox& ibb)
 {
 {
     // TODO: I'm pretty sure there is a much more compact way to check this
     // TODO: I'm pretty sure there is a much more compact way to check this
-    const IfcFloat epsilon = 1e-5f;
+    const IfcFloat epsilon = Math::getEpsilon<float>();
     return  (std::fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) ||
     return  (std::fabs(bb.second.x - ibb.first.x) < epsilon && bb.first.y <= ibb.second.y && bb.second.y >= ibb.first.y) ||
         (std::fabs(bb.first.x - ibb.second.x) < epsilon && ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) ||
         (std::fabs(bb.first.x - ibb.second.x) < epsilon && ibb.first.y <= bb.second.y && ibb.second.y >= bb.first.y) ||
         (std::fabs(bb.second.y - ibb.first.y) < epsilon && bb.first.x <= ibb.second.x && bb.second.x >= ibb.first.x) ||
         (std::fabs(bb.second.y - ibb.first.y) < epsilon && bb.first.x <= ibb.second.x && bb.second.x >= ibb.first.x) ||
@@ -681,7 +681,7 @@ bool IntersectingLineSegments(const IfcVector2& n0, const IfcVector2& n1,
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void FindAdjacentContours(ContourVector::iterator current, const ContourVector& contours)
 void FindAdjacentContours(ContourVector::iterator current, const ContourVector& contours)
 {
 {
-    const IfcFloat sqlen_epsilon = static_cast<IfcFloat>(1e-8);
+    const IfcFloat sqlen_epsilon = static_cast<IfcFloat>(Math::getEpsilon<float>());
     const BoundingBox& bb = (*current).bb;
     const BoundingBox& bb = (*current).bb;
 
 
     // What is to be done here is to populate the skip lists for the contour
     // What is to be done here is to populate the skip lists for the contour
@@ -758,7 +758,7 @@ void FindAdjacentContours(ContourVector::iterator current, const ContourVector&
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 AI_FORCE_INLINE bool LikelyBorder(const IfcVector2& vdelta)
 AI_FORCE_INLINE bool LikelyBorder(const IfcVector2& vdelta)
 {
 {
-    const IfcFloat dot_point_epsilon = static_cast<IfcFloat>(1e-5);
+    const IfcFloat dot_point_epsilon = static_cast<IfcFloat>(Math::getEpsilon<float>());
     return std::fabs(vdelta.x * vdelta.y) < dot_point_epsilon;
     return std::fabs(vdelta.x * vdelta.y) < dot_point_epsilon;
 }
 }
 
 

+ 0 - 1
code/Irr/IRRMeshLoader.cpp

@@ -57,7 +57,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/material.h>
 #include <assimp/material.h>
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include <assimp/importerdesc.h>
 #include <assimp/importerdesc.h>
-#include <assimp/Macros.h>
 
 
 using namespace Assimp;
 using namespace Assimp;
 using namespace irr;
 using namespace irr;

+ 1 - 1
code/MD2/MD2Loader.cpp

@@ -344,7 +344,7 @@ void MD2Importer::InternReadFile( const std::string& pFile,
         if (pcSkins->name[0])
         if (pcSkins->name[0])
         {
         {
             aiString szString;
             aiString szString;
-            const size_t iLen = ::strlen(pcSkins->name);
+            const ai_uint32 iLen = (ai_uint32) ::strlen(pcSkins->name);
             ::memcpy(szString.data,pcSkins->name,iLen);
             ::memcpy(szString.data,pcSkins->name,iLen);
             szString.data[iLen] = '\0';
             szString.data[iLen] = '\0';
             szString.length = iLen;
             szString.length = iLen;

+ 2 - 1
code/MD5/MD5Loader.cpp

@@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "MD5Loader.h"
 #include "MD5Loader.h"
 #include <assimp/StringComparison.h>
 #include <assimp/StringComparison.h>
 #include <assimp/fast_atof.h>
 #include <assimp/fast_atof.h>
+#include <assimp/MathFunctions.h>
 #include <assimp/SkeletonMeshBuilder.h>
 #include <assimp/SkeletonMeshBuilder.h>
 #include <assimp/Importer.hpp>
 #include <assimp/Importer.hpp>
 #include <assimp/scene.h>
 #include <assimp/scene.h>
@@ -64,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 using namespace Assimp;
 using namespace Assimp;
 
 
 // Minimum weight value. Weights inside [-n ... n] are ignored
 // Minimum weight value. Weights inside [-n ... n] are ignored
-#define AI_MD5_WEIGHT_EPSILON 1e-5f
+#define AI_MD5_WEIGHT_EPSILON Math::getEpsilon<float>()
 
 
 
 
 static const aiImporterDesc desc = {
 static const aiImporterDesc desc = {

+ 1 - 1
code/MD5/MD5Parser.cpp

@@ -235,7 +235,7 @@ bool MD5Parser::ParseSection(Section& out)
     const char* szStart = ++sz; \
     const char* szStart = ++sz; \
 	while('\"'!=*sz)++sz; \
 	while('\"'!=*sz)++sz; \
     const char* szEnd = (sz++); \
     const char* szEnd = (sz++); \
-    out.length = (size_t)(szEnd - szStart); \
+    out.length = (ai_uint32) (szEnd - szStart); \
     ::memcpy(out.data,szStart,out.length); \
     ::memcpy(out.data,szStart,out.length); \
     out.data[out.length] = '\0';
     out.data[out.length] = '\0';
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 16 - 26
code/MDL/MDLLoader.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2019, assimp team
 Copyright (c) 2006-2019, 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,
@@ -54,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "MDL/MDLDefaultColorMap.h"
 #include "MDL/MDLDefaultColorMap.h"
 #include "MD2/MD2FileData.h"
 #include "MD2/MD2FileData.h"
 
 
-#include <assimp/Macros.h>
 #include <assimp/qnan.h>
 #include <assimp/qnan.h>
 #include <assimp/StringUtils.h>
 #include <assimp/StringUtils.h>
 #include <assimp/Importer.hpp>
 #include <assimp/Importer.hpp>
@@ -94,23 +91,24 @@ static const aiImporterDesc desc = {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 MDLImporter::MDLImporter()
 MDLImporter::MDLImporter()
-    : configFrameID(),
-    mBuffer(),
-    iGSFileVersion(),
-    pIOHandler(),
-    pScene(),
-    iFileSize()
-{}
+: configFrameID()
+, mBuffer()
+, iGSFileVersion()
+, pIOHandler()
+, pScene()
+, iFileSize() {
+    // empty
+}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-MDLImporter::~MDLImporter()
-{}
+MDLImporter::~MDLImporter() {
+    // empty
+}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // 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 MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
-{
+bool MDLImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
     const std::string extension = GetExtension(pFile);
     const std::string extension = GetExtension(pFile);
 
 
     // if check for extension is not enough, check for the magic tokens
     // if check for extension is not enough, check for the magic tokens
@@ -404,23 +402,15 @@ void MDLImporter::InternReadFile_Quake1() {
 
 
     // now get a pointer to the first frame in the file
     // now get a pointer to the first frame in the file
     BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent;
     BE_NCONST MDL::Frame* pcFrames = (BE_NCONST MDL::Frame*)szCurrent;
-    BE_NCONST MDL::SimpleFrame* pcFirstFrame;
+    MDL::SimpleFrame* pcFirstFrame;
 
 
     if (0 == pcFrames->type) {
     if (0 == pcFrames->type) {
         // get address of single frame
         // get address of single frame
-        pcFirstFrame = &pcFrames->frame;
+        pcFirstFrame =( MDL::SimpleFrame*) &pcFrames->frame;
     } else {
     } else {
         // get the first frame in the group
         // get the first frame in the group
-
-#if 1
-        // FIXME: the cast is wrong and cause a warning on clang 5.0
-        // disable this code for now, fix it later
-        ai_assert(false && "Bad pointer cast");
-        pcFirstFrame = nullptr; // Workaround: msvc++ C4703 error
-#else
-        BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*)pcFrames;
-        pcFirstFrame = (BE_NCONST MDL::SimpleFrame*)(&pcFrames2->time + pcFrames->type);
-#endif
+        BE_NCONST MDL::GroupFrame* pcFrames2 = (BE_NCONST MDL::GroupFrame*) pcFrames;
+        pcFirstFrame = &(pcFrames2->frames[0]);
     }
     }
     BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
     BE_NCONST MDL::Vertex* pcVertices = (BE_NCONST MDL::Vertex*) ((pcFirstFrame->name) + sizeof(pcFirstFrame->name));
     VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts));
     VALIDATE_FILE_SIZE((const unsigned char*)(pcVertices + pcHeader->num_verts));

+ 1 - 17
code/MDL/MDLLoader.h

@@ -89,16 +89,12 @@ public:
     MDLImporter();
     MDLImporter();
     ~MDLImporter();
     ~MDLImporter();
 
 
-
-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.  */
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
         bool checkSig) const;
         bool checkSig) const;
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Called prior to ReadFile().
     /** Called prior to ReadFile().
     * The function is a request to the importer to update its configuration
     * The function is a request to the importer to update its configuration
@@ -107,8 +103,6 @@ public:
     void SetupProperties(const Importer* pImp);
     void SetupProperties(const Importer* pImp);
 
 
 protected:
 protected:
-
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Return importer meta information.
     /** Return importer meta information.
      * See #BaseImporter::GetInfo for the details
      * See #BaseImporter::GetInfo for the details
@@ -122,8 +116,6 @@ protected:
     void InternReadFile( const std::string& pFile, aiScene* pScene,
     void InternReadFile( const std::string& pFile, aiScene* pScene,
         IOSystem* pIOHandler);
         IOSystem* pIOHandler);
 
 
-protected:
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Import a quake 1 MDL file (IDPO)
     /** Import a quake 1 MDL file (IDPO)
     */
     */
@@ -154,7 +146,6 @@ protected:
     void SizeCheck(const void* szPos);
     void SizeCheck(const void* szPos);
     void SizeCheck(const void* szPos, const char* szFile, unsigned int iLine);
     void SizeCheck(const void* szPos, const char* szFile, unsigned int iLine);
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Validate the header data structure of a game studio MDL7 file
     /** Validate the header data structure of a game studio MDL7 file
      * \param pcHeader Input header to be validated
      * \param pcHeader Input header to be validated
@@ -167,7 +158,6 @@ protected:
      */
      */
     void ValidateHeader_Quake1(const MDL::Header* pcHeader);
     void ValidateHeader_Quake1(const MDL::Header* pcHeader);
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Try to load a  palette from the current directory (colormap.lmp)
     /** Try to load a  palette from the current directory (colormap.lmp)
      *  If it is not found the default palette of Quake1 is returned
      *  If it is not found the default palette of Quake1 is returned
@@ -179,9 +169,8 @@ protected:
      */
      */
     void FreePalette(const unsigned char* pszColorMap);
     void FreePalette(const unsigned char* pszColorMap);
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
-    /** Load a paletized texture from the file and convert it to 32bpp
+    /** Load a palletized texture from the file and convert it to 32bpp
     */
     */
     void CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData);
     void CreateTextureARGB8_3DGS_MDL3(const unsigned char* szData);
 
 
@@ -195,7 +184,6 @@ protected:
         unsigned int iType,
         unsigned int iType,
         unsigned int* piSkip);
         unsigned int* piSkip);
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Used to load textures from MDL5
     /** Used to load textures from MDL5
      * \param szData Input data
      * \param szData Input data
@@ -206,7 +194,6 @@ protected:
         unsigned int iType,
         unsigned int iType,
         unsigned int* piSkip);
         unsigned int* piSkip);
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Checks whether a texture can be replaced with a single color
     /** Checks whether a texture can be replaced with a single color
      * This is useful for all file formats before MDL7 (all those
      * This is useful for all file formats before MDL7 (all those
@@ -218,14 +205,12 @@ protected:
     */
     */
     aiColor4D ReplaceTextureWithColor(const aiTexture* pcTexture);
     aiColor4D ReplaceTextureWithColor(const aiTexture* pcTexture);
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Converts the absolute texture coordinates in MDL5 files to
     /** Converts the absolute texture coordinates in MDL5 files to
      *  relative in a range between 0 and 1
      *  relative in a range between 0 and 1
     */
     */
     void CalculateUVCoordinates_MDL5();
     void CalculateUVCoordinates_MDL5();
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Read an UV coordinate from the file. If the file format is not
     /** Read an UV coordinate from the file. If the file format is not
      * MDL5, the function calculates relative texture coordinates
      * MDL5, the function calculates relative texture coordinates
@@ -245,7 +230,6 @@ protected:
      */
      */
     void SetupMaterialProperties_3DGS_MDL5_Quake1( );
     void SetupMaterialProperties_3DGS_MDL5_Quake1( );
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Parse a skin lump in a MDL7/HMP7 file with all of its features
     /** Parse a skin lump in a MDL7/HMP7 file with all of its features
      *  variant 1: Current cursor position is the beginning of the skin header
      *  variant 1: Current cursor position is the beginning of the skin header

+ 1 - 18
code/Material/MaterialSystem.cpp

@@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/types.h>
 #include <assimp/types.h>
 #include <assimp/material.h>
 #include <assimp/material.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
-#include <assimp/Macros.h>
 
 
 using namespace Assimp;
 using namespace Assimp;
 
 
@@ -545,23 +544,7 @@ aiReturn aiMaterial::AddProperty (const aiString* pInput,
     unsigned int type,
     unsigned int type,
     unsigned int index)
     unsigned int index)
 {
 {
-    // We don't want to add the whole buffer .. write a 32 bit length
-    // prefix followed by the zero-terminated UTF8 string.
-    // (HACK) I don't want to break the ABI now, but we definitely
-    // ought to change aiString::mLength to uint32_t one day.
-    if (sizeof(size_t) == 8) {
-        aiString copy = *pInput;
-        uint32_t* s = reinterpret_cast<uint32_t*>(&copy.length);
-        s[1] = static_cast<uint32_t>(pInput->length);
-
-        return AddBinaryProperty(s+1,
-            static_cast<unsigned int>(pInput->length+1+4),
-            pKey,
-            type,
-            index,
-            aiPTI_String);
-    }
-    ai_assert(sizeof(size_t)==4);
+    ai_assert(sizeof(ai_uint32)==4);
     return AddBinaryProperty(pInput,
     return AddBinaryProperty(pInput,
         static_cast<unsigned int>(pInput->length+1+4),
         static_cast<unsigned int>(pInput->length+1+4),
         pKey,
         pKey,

+ 1 - 4
code/Obj/ObjFileImporter.cpp

@@ -79,10 +79,7 @@ using namespace std;
 ObjFileImporter::ObjFileImporter()
 ObjFileImporter::ObjFileImporter()
 : m_Buffer()
 : m_Buffer()
 , m_pRootObject( nullptr )
 , m_pRootObject( nullptr )
-, m_strAbsPath( "" ) {
-    DefaultIOSystem io;
-    m_strAbsPath = io.getOsSeparator();
-}
+, m_strAbsPath( std::string(1, DefaultIOSystem().getOsSeparator()) ) {}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //  Destructor.
 //  Destructor.

+ 2 - 2
code/Obj/ObjFileParser.cpp

@@ -244,8 +244,8 @@ void ObjFileParser::copyNextWord(char *pBuffer, size_t length) {
     size_t index = 0;
     size_t index = 0;
     m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
     m_DataIt = getNextWord<DataArrayIt>(m_DataIt, m_DataItEnd);
     if ( *m_DataIt == '\\' ) {
     if ( *m_DataIt == '\\' ) {
-        m_DataIt++;
-        m_DataIt++;
+        ++m_DataIt;
+        ++m_DataIt;
         m_DataIt = getNextWord<DataArrayIt>( m_DataIt, m_DataItEnd );
         m_DataIt = getNextWord<DataArrayIt>( m_DataIt, m_DataItEnd );
     }
     }
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {
     while( m_DataIt != m_DataItEnd && !IsSpaceOrNewLine( *m_DataIt ) ) {

+ 0 - 1
code/Ply/PlyLoader.cpp

@@ -49,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // internal headers
 // internal headers
 #include "PlyLoader.h"
 #include "PlyLoader.h"
 #include <assimp/IOStreamBuffer.h>
 #include <assimp/IOStreamBuffer.h>
-#include <assimp/Macros.h>
 #include <memory>
 #include <memory>
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/scene.h>
 #include <assimp/scene.h>

+ 3 - 3
code/PostProcessing/ComputeUVMappingProcess.cpp

@@ -354,12 +354,12 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
     }
     }
     else if (axis * base_axis_z >= angle_epsilon)   {
     else if (axis * base_axis_z >= angle_epsilon)   {
         FindMeshCenter(mesh, center, min, max);
         FindMeshCenter(mesh, center, min, max);
-        diffu = max.y - min.y;
-        diffv = max.z - min.z;
+        diffu = max.x - min.x;
+        diffv = max.y - min.y;
 
 
         for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
         for (unsigned int pnt = 0; pnt < mesh->mNumVertices;++pnt)  {
             const aiVector3D& pos = mesh->mVertices[pnt];
             const aiVector3D& pos = mesh->mVertices[pnt];
-            out[pnt].Set((pos.y - min.y) / diffu,(pos.x - min.x) / diffv,0.0);
+            out[pnt].Set((pos.x - min.x) / diffu,(pos.y - min.y) / diffv,0.0);
         }
         }
     }
     }
     // slower code path in case the mapping axis is not one of the coordinate system axes
     // slower code path in case the mapping axis is not one of the coordinate system axes

+ 0 - 1
code/PostProcessing/FindInvalidDataProcess.cpp

@@ -52,7 +52,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "FindInvalidDataProcess.h"
 #include "FindInvalidDataProcess.h"
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
 
 
-#include <assimp/Macros.h>
 #include <assimp/Exceptional.h>
 #include <assimp/Exceptional.h>
 #include <assimp/qnan.h>
 #include <assimp/qnan.h>
 
 

+ 29 - 0
code/PostProcessing/MakeVerboseFormat.cpp

@@ -224,3 +224,32 @@ bool MakeVerboseFormatProcess::MakeVerboseFormat(aiMesh* pcMesh)
     }
     }
     return (pcMesh->mNumVertices != iOldNumVertices);
     return (pcMesh->mNumVertices != iOldNumVertices);
 }
 }
+
+
+// ------------------------------------------------------------------------------------------------
+bool IsMeshInVerboseFormat(const aiMesh* mesh) {
+    // avoid slow vector<bool> specialization
+    std::vector<unsigned int> seen(mesh->mNumVertices,0);
+    for(unsigned int i = 0; i < mesh->mNumFaces; ++i) {
+        const aiFace& f = mesh->mFaces[i];
+        for(unsigned int j = 0; j < f.mNumIndices; ++j) {
+            if(++seen[f.mIndices[j]] == 2) {
+                // found a duplicate index
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
+// ------------------------------------------------------------------------------------------------
+bool MakeVerboseFormatProcess::IsVerboseFormat(const aiScene* pScene) {
+    for(unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
+        if(!IsMeshInVerboseFormat(pScene->mMeshes[i])) {
+            return false;
+        }
+    }
+
+    return true;
+}

+ 7 - 0
code/PostProcessing/MakeVerboseFormat.h

@@ -94,6 +94,13 @@ public:
     * @param pScene The imported data to work at. */
     * @param pScene The imported data to work at. */
     void Execute( aiScene* pScene);
     void Execute( aiScene* pScene);
 
 
+public:
+
+    // -------------------------------------------------------------------
+    /** Checks whether the scene is already in verbose format.
+    * @param pScene The data to check. 
+    * @return true if the scene is already in verbose format. */
+    static bool IsVerboseFormat(const aiScene* pScene);
 
 
 private:
 private:
 
 

+ 59 - 4
code/PostProcessing/ValidateDataStructure.cpp

@@ -538,13 +538,17 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
 {
 {
     Validate(&pAnimation->mName);
     Validate(&pAnimation->mName);
 
 
-    // validate all materials
-    if (pAnimation->mNumChannels)
+    // validate all animations
+    if (pAnimation->mNumChannels || pAnimation->mNumMorphMeshChannels)
     {
     {
-        if (!pAnimation->mChannels) {
+        if (!pAnimation->mChannels && pAnimation->mNumChannels) {
             ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)",
             ReportError("aiAnimation::mChannels is NULL (aiAnimation::mNumChannels is %i)",
                 pAnimation->mNumChannels);
                 pAnimation->mNumChannels);
         }
         }
+        if (!pAnimation->mMorphMeshChannels && pAnimation->mNumMorphMeshChannels) {
+            ReportError("aiAnimation::mMorphMeshChannels is NULL (aiAnimation::mNumMorphMeshChannels is %i)",
+                pAnimation->mNumMorphMeshChannels);
+        }
         for (unsigned int i = 0; i < pAnimation->mNumChannels;++i)
         for (unsigned int i = 0; i < pAnimation->mNumChannels;++i)
         {
         {
             if (!pAnimation->mChannels[i])
             if (!pAnimation->mChannels[i])
@@ -554,6 +558,15 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation)
             }
             }
             Validate(pAnimation, pAnimation->mChannels[i]);
             Validate(pAnimation, pAnimation->mChannels[i]);
         }
         }
+        for (unsigned int i = 0; i < pAnimation->mNumMorphMeshChannels;++i)
+        {
+            if (!pAnimation->mMorphMeshChannels[i])
+            {
+                ReportError("aiAnimation::mMorphMeshChannels[%i] is NULL (aiAnimation::mNumMorphMeshChannels is %i)",
+                    i, pAnimation->mNumMorphMeshChannels);
+            }
+            Validate(pAnimation, pAnimation->mMorphMeshChannels[i]);
+        }
     }
     }
     else {
     else {
     	ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
     	ReportError("aiAnimation::mNumChannels is 0. At least one node animation channel must be there.");
@@ -903,6 +916,48 @@ void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
     }
     }
 }
 }
 
 
+void ValidateDSProcess::Validate( const aiAnimation* pAnimation,
+     const aiMeshMorphAnim* pMeshMorphAnim)
+{
+    Validate(&pMeshMorphAnim->mName);
+
+    if (!pMeshMorphAnim->mNumKeys) {
+        ReportError("Empty mesh morph animation channel");
+    }
+
+    // otherwise check whether one of the keys exceeds the total duration of the animation
+    if (pMeshMorphAnim->mNumKeys)
+    {
+        if (!pMeshMorphAnim->mKeys)
+        {
+            ReportError("aiMeshMorphAnim::mKeys is NULL (aiMeshMorphAnim::mNumKeys is %i)",
+                pMeshMorphAnim->mNumKeys);
+        }
+        double dLast = -10e10;
+        for (unsigned int i = 0; i < pMeshMorphAnim->mNumKeys;++i)
+        {
+            // ScenePreprocessor will compute the duration if still the default value
+            // (Aramis) Add small epsilon, comparison tended to fail if max_time == duration,
+            //  seems to be due the compilers register usage/width.
+            if (pAnimation->mDuration > 0. && pMeshMorphAnim->mKeys[i].mTime > pAnimation->mDuration+0.001)
+            {
+                ReportError("aiMeshMorphAnim::mKeys[%i].mTime (%.5f) is larger "
+                    "than aiAnimation::mDuration (which is %.5f)",i,
+                    (float)pMeshMorphAnim->mKeys[i].mTime,
+                    (float)pAnimation->mDuration);
+            }
+            if (i && pMeshMorphAnim->mKeys[i].mTime <= dLast)
+            {
+                ReportWarning("aiMeshMorphAnim::mKeys[%i].mTime (%.5f) is smaller "
+                    "than aiMeshMorphAnim::mKeys[%i] (which is %.5f)",i,
+                    (float)pMeshMorphAnim->mKeys[i].mTime,
+                    i-1, (float)dLast);
+            }
+            dLast = pMeshMorphAnim->mKeys[i].mTime;
+        }
+    }
+}
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void ValidateDSProcess::Validate( const aiNode* pNode)
 void ValidateDSProcess::Validate( const aiNode* pNode)
 {
 {
@@ -958,7 +1013,7 @@ void ValidateDSProcess::Validate( const aiString* pString)
 {
 {
     if (pString->length > MAXLEN)
     if (pString->length > MAXLEN)
     {
     {
-        ReportError("aiString::length is too large (%lu, maximum is %lu)",
+        ReportError("aiString::length is too large (%u, maximum is %lu)",
             pString->length,MAXLEN);
             pString->length,MAXLEN);
     }
     }
     const char* sz = pString->data;
     const char* sz = pString->data;

+ 8 - 0
code/PostProcessing/ValidateDataStructure.h

@@ -55,6 +55,7 @@ struct aiBone;
 struct aiMesh;
 struct aiMesh;
 struct aiAnimation;
 struct aiAnimation;
 struct aiNodeAnim;
 struct aiNodeAnim;
+struct aiMeshMorphAnim;
 struct aiTexture;
 struct aiTexture;
 struct aiMaterial;
 struct aiMaterial;
 struct aiNode;
 struct aiNode;
@@ -150,6 +151,13 @@ protected:
     void Validate( const aiAnimation* pAnimation,
     void Validate( const aiAnimation* pAnimation,
         const aiNodeAnim* pBoneAnim);
         const aiNodeAnim* pBoneAnim);
 
 
+    /** Validates a mesh morph animation channel.
+     * @param pAnimation Input animation.
+     * @param pMeshMorphAnim Mesh morph animation channel.
+     * */
+    void Validate( const aiAnimation* pAnimation,
+        const aiMeshMorphAnim* pMeshMorphAnim);
+
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Validates a node and all of its subnodes
     /** Validates a node and all of its subnodes
      * @param Node Input node*/
      * @param Node Input node*/

+ 3 - 3
code/X/XFileParser.cpp

@@ -596,11 +596,11 @@ void XFileParser::ParseDataObjectMeshNormals( Mesh* pMesh)
     // do not crah when no face definitions are there
     // do not crah when no face definitions are there
     if (numFaces > 0) {
     if (numFaces > 0) {
         // normal face creation
         // normal face creation
-        pMesh->mNormFaces.resize( pMesh->mNormFaces.size() + numFaces );
+        pMesh->mNormFaces.resize( numFaces );
         for( unsigned int a = 0; a < numFaces; ++a ) {
         for( unsigned int a = 0; a < numFaces; ++a ) {
             unsigned int numIndices = ReadInt();
             unsigned int numIndices = ReadInt();
-            pMesh->mNormFaces.push_back( Face() );
-            Face& face = pMesh->mNormFaces.back();
+            pMesh->mNormFaces[a] = Face();
+            Face& face = pMesh->mNormFaces[a];
             for( unsigned int b = 0; b < numIndices; ++b ) {
             for( unsigned int b = 0; b < numIndices; ++b ) {
                 face.mIndices.push_back( ReadInt());
                 face.mIndices.push_back( ReadInt());
             }
             }

+ 1 - 1
code/X3D/X3DExporter.cpp

@@ -68,7 +68,7 @@ aiMatrix4x4 out_matr;
 	}
 	}
 
 
 	// multiplicate all matrices in reverse order
 	// multiplicate all matrices in reverse order
-	for(std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); rit++) out_matr = out_matr * (*rit);
+	for(std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); ++rit) out_matr = out_matr * (*rit);
 
 
 	return out_matr;
 	return out_matr;
 }
 }

+ 30 - 30
code/X3D/X3DImporter.cpp

@@ -136,8 +136,8 @@ X3DImporter::~X3DImporter() {
 void X3DImporter::Clear() {
 void X3DImporter::Clear() {
 	NodeElement_Cur = nullptr;
 	NodeElement_Cur = nullptr;
 	// Delete all elements
 	// Delete all elements
-	if(NodeElement_List.size()) {
-        for ( std::list<CX3DImporter_NodeElement*>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); it++ ) {
+	if(!NodeElement_List.empty()) {
+        for ( std::list<CX3DImporter_NodeElement*>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); ++it ) {
             delete *it;
             delete *it;
         }
         }
 		NodeElement_List.clear();
 		NodeElement_List.clear();
@@ -151,7 +151,7 @@ void X3DImporter::Clear() {
 
 
 bool X3DImporter::FindNodeElement_FromRoot(const std::string& pID, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement)
 bool X3DImporter::FindNodeElement_FromRoot(const std::string& pID, const CX3DImporter_NodeElement::EType pType, CX3DImporter_NodeElement** pElement)
 {
 {
-	for(std::list<CX3DImporter_NodeElement*>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); it++)
+	for(std::list<CX3DImporter_NodeElement*>::iterator it = NodeElement_List.begin(); it != NodeElement_List.end(); ++it)
 	{
 	{
 		if(((*it)->Type == pType) && ((*it)->ID == pID))
 		if(((*it)->Type == pType) && ((*it)->ID == pID))
 		{
 		{
@@ -182,7 +182,7 @@ bool X3DImporter::FindNodeElement_FromNode(CX3DImporter_NodeElement* pStartNode,
 	}// if((pStartNode->Type() == pType) && (pStartNode->ID() == pID))
 	}// if((pStartNode->Type() == pType) && (pStartNode->ID() == pID))
 
 
 	// Check childs of pStartNode.
 	// Check childs of pStartNode.
-	for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = pStartNode->Child.begin(); ch_it != pStartNode->Child.end(); ch_it++)
+	for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = pStartNode->Child.begin(); ch_it != pStartNode->Child.end(); ++ch_it)
 	{
 	{
 		found = FindNodeElement_FromNode(*ch_it, pID, pType, pElement);
 		found = FindNodeElement_FromNode(*ch_it, pID, pType, pElement);
         if ( found )
         if ( found )
@@ -614,10 +614,10 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrCol3f(const int pAttrIdx, std::ve
 
 
 	XML_ReadNode_GetAttrVal_AsListCol3f(pAttrIdx, tlist);// read as list
 	XML_ReadNode_GetAttrVal_AsListCol3f(pAttrIdx, tlist);// read as list
 	// and copy to array
 	// and copy to array
-	if(tlist.size() > 0)
+	if(!tlist.empty())
 	{
 	{
 		pValue.reserve(tlist.size());
 		pValue.reserve(tlist.size());
-		for(std::list<aiColor3D>::iterator it = tlist.begin(); it != tlist.end(); it++) pValue.push_back(*it);
+		for(std::list<aiColor3D>::iterator it = tlist.begin(); it != tlist.end(); ++it) pValue.push_back(*it);
 	}
 	}
 }
 }
 
 
@@ -647,10 +647,10 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrCol4f(const int pAttrIdx, std::ve
 
 
 	XML_ReadNode_GetAttrVal_AsListCol4f(pAttrIdx, tlist);// read as list
 	XML_ReadNode_GetAttrVal_AsListCol4f(pAttrIdx, tlist);// read as list
 	// and copy to array
 	// and copy to array
-	if(tlist.size() > 0)
+	if(!tlist.empty())
 	{
 	{
 		pValue.reserve(tlist.size());
 		pValue.reserve(tlist.size());
-        for ( std::list<aiColor4D>::iterator it = tlist.begin(); it != tlist.end(); it++ )
+        for ( std::list<aiColor4D>::iterator it = tlist.begin(); it != tlist.end(); ++it )
         {
         {
             pValue.push_back( *it );
             pValue.push_back( *it );
         }
         }
@@ -684,10 +684,10 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrVec2f(const int pAttrIdx, std::ve
 
 
 	XML_ReadNode_GetAttrVal_AsListVec2f(pAttrIdx, tlist);// read as list
 	XML_ReadNode_GetAttrVal_AsListVec2f(pAttrIdx, tlist);// read as list
 	// and copy to array
 	// and copy to array
-	if(tlist.size() > 0)
+	if(!tlist.empty())
 	{
 	{
 		pValue.reserve(tlist.size());
 		pValue.reserve(tlist.size());
-        for ( std::list<aiVector2D>::iterator it = tlist.begin(); it != tlist.end(); it++ )
+        for ( std::list<aiVector2D>::iterator it = tlist.begin(); it != tlist.end(); ++it )
         {
         {
             pValue.push_back( *it );
             pValue.push_back( *it );
         }
         }
@@ -722,10 +722,10 @@ void X3DImporter::XML_ReadNode_GetAttrVal_AsArrVec3f(const int pAttrIdx, std::ve
 
 
 	XML_ReadNode_GetAttrVal_AsListVec3f(pAttrIdx, tlist);// read as list
 	XML_ReadNode_GetAttrVal_AsListVec3f(pAttrIdx, tlist);// read as list
 	// and copy to array
 	// and copy to array
-	if(tlist.size() > 0)
+	if(!tlist.empty())
 	{
 	{
 		pValue.reserve(tlist.size());
 		pValue.reserve(tlist.size());
-        for ( std::list<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); it++ )
+        for ( std::list<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); ++it )
         {
         {
             pValue.push_back( *it );
             pValue.push_back( *it );
         }
         }
@@ -823,7 +823,7 @@ void X3DImporter::GeometryHelper_Extend_PointToLine(const std::list<aiVector3D>&
     std::list<aiVector3D>::const_iterator pit = pPoint.begin();
     std::list<aiVector3D>::const_iterator pit = pPoint.begin();
     std::list<aiVector3D>::const_iterator pit_last = pPoint.end();
     std::list<aiVector3D>::const_iterator pit_last = pPoint.end();
 
 
-	pit_last--;
+	--pit_last;
 
 
     if ( pPoint.size() < 2 )
     if ( pPoint.size() < 2 )
     {
     {
@@ -837,7 +837,7 @@ void X3DImporter::GeometryHelper_Extend_PointToLine(const std::list<aiVector3D>&
 	{
 	{
 		pLine.push_back(*pit);// second point of previous line
 		pLine.push_back(*pit);// second point of previous line
 		pLine.push_back(*pit);// first point of next line
 		pLine.push_back(*pit);// first point of next line
-		pit++;
+		++pit;
 	}
 	}
 	// add last point of last line
 	// add last point of last line
 	pLine.push_back(*pit);
 	pLine.push_back(*pit);
@@ -855,7 +855,7 @@ void X3DImporter::GeometryHelper_Extend_PolylineIdxToLineIdx(const std::list<int
 		{
 		{
 			std::list<int32_t>::const_iterator plit_next;
 			std::list<int32_t>::const_iterator plit_next;
 
 
-			plit_next = plit, plit_next++;
+			plit_next = plit, ++plit_next;
 			pLineCoordIdx.push_back(*plit);// second point of previous line.
 			pLineCoordIdx.push_back(*plit);// second point of previous line.
 			pLineCoordIdx.push_back(-1);// delimiter
 			pLineCoordIdx.push_back(-1);// delimiter
 			if((*plit_next == (-1)) || (plit_next == pPolylineCoordIdx.end())) break;// current polyline is finished
 			if((*plit_next == (-1)) || (plit_next == pPolylineCoordIdx.end())) break;// current polyline is finished
@@ -910,7 +910,7 @@ void X3DImporter::GeometryHelper_CoordIdxStr2FacesArr(const std::vector<int32_t>
 	pFaces.reserve(f_data.size() / 3);
 	pFaces.reserve(f_data.size() / 3);
 	inds.reserve(4);
 	inds.reserve(4);
     //PrintVectorSet("build. ci", pCoordIdx);
     //PrintVectorSet("build. ci", pCoordIdx);
-	for(std::vector<int32_t>::iterator it = f_data.begin(); it != f_data.end(); it++)
+	for(std::vector<int32_t>::iterator it = f_data.begin(); it != f_data.end(); ++it)
 	{
 	{
 		// when face is got count how many indices in it.
 		// when face is got count how many indices in it.
 		if(*it == (-1))
 		if(*it == (-1))
@@ -957,7 +957,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor3D
 std::list<aiColor4D> tcol;
 std::list<aiColor4D> tcol;
 
 
 	// create RGBA array from RGB.
 	// create RGBA array from RGB.
-	for(std::list<aiColor3D>::const_iterator it = pColors.begin(); it != pColors.end(); it++) tcol.push_back(aiColor4D((*it).r, (*it).g, (*it).b, 1));
+	for(std::list<aiColor3D>::const_iterator it = pColors.begin(); it != pColors.end(); ++it) tcol.push_back(aiColor4D((*it).r, (*it).g, (*it).b, 1));
 
 
 	// call existing function for adding RGBA colors
 	// call existing function for adding RGBA colors
 	MeshGeometry_AddColor(pMesh, tcol, pColorPerVertex);
 	MeshGeometry_AddColor(pMesh, tcol, pColorPerVertex);
@@ -997,7 +997,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::list<aiColor4D
                 pMesh.mColors[ 0 ][ pMesh.mFaces[ fi ].mIndices[ vi ] ] = *col_it;
                 pMesh.mColors[ 0 ][ pMesh.mFaces[ fi ].mIndices[ vi ] ] = *col_it;
             }
             }
 
 
-			col_it++;
+			++col_it;
 		}
 		}
 	}// if(pColorPerVertex) else
 	}// if(pColorPerVertex) else
 }
 }
@@ -1008,7 +1008,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t
     std::list<aiColor4D> tcol;
     std::list<aiColor4D> tcol;
 
 
 	// create RGBA array from RGB.
 	// create RGBA array from RGB.
-    for ( std::list<aiColor3D>::const_iterator it = pColors.begin(); it != pColors.end(); it++ )
+    for ( std::list<aiColor3D>::const_iterator it = pColors.begin(); it != pColors.end(); ++it )
     {
     {
         tcol.push_back( aiColor4D( ( *it ).r, ( *it ).g, ( *it ).b, 1 ) );
         tcol.push_back( aiColor4D( ( *it ).r, ( *it ).g, ( *it ).b, 1 ) );
     }
     }
@@ -1031,7 +1031,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t
 
 
 	// copy list to array because we are need indexed access to colors.
 	// copy list to array because we are need indexed access to colors.
 	col_arr_copy.reserve(pColors.size());
 	col_arr_copy.reserve(pColors.size());
-    for ( std::list<aiColor4D>::const_iterator it = pColors.begin(); it != pColors.end(); it++ )
+    for ( std::list<aiColor4D>::const_iterator it = pColors.begin(); it != pColors.end(); ++it )
     {
     {
         col_arr_copy.push_back( *it );
         col_arr_copy.push_back( *it );
     }
     }
@@ -1048,7 +1048,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t
 			}
 			}
 			// create list with colors for every vertex.
 			// create list with colors for every vertex.
 			col_tgt_arr.resize(pMesh.mNumVertices);
 			col_tgt_arr.resize(pMesh.mNumVertices);
-			for(std::vector<int32_t>::const_iterator colidx_it = pColorIdx.begin(), coordidx_it = pCoordIdx.begin(); colidx_it != pColorIdx.end(); colidx_it++, coordidx_it++)
+			for(std::vector<int32_t>::const_iterator colidx_it = pColorIdx.begin(), coordidx_it = pCoordIdx.begin(); colidx_it != pColorIdx.end(); ++colidx_it, ++coordidx_it)
 			{
 			{
                 if ( *colidx_it == ( -1 ) )
                 if ( *colidx_it == ( -1 ) )
                 {
                 {
@@ -1121,7 +1121,7 @@ void X3DImporter::MeshGeometry_AddColor(aiMesh& pMesh, const std::vector<int32_t
 	}// if(pColorPerVertex) else
 	}// if(pColorPerVertex) else
 
 
 	// copy array to list for calling function that add colors.
 	// copy array to list for calling function that add colors.
-	for(std::vector<aiColor4D>::const_iterator it = col_tgt_arr.begin(); it != col_tgt_arr.end(); it++) col_tgt_list.push_back(*it);
+	for(std::vector<aiColor4D>::const_iterator it = col_tgt_arr.begin(); it != col_tgt_arr.end(); ++it) col_tgt_list.push_back(*it);
 	// add prepared colors list to mesh.
 	// add prepared colors list to mesh.
 	MeshGeometry_AddColor(pMesh, col_tgt_list, pColorPerVertex);
 	MeshGeometry_AddColor(pMesh, col_tgt_list, pColorPerVertex);
 }
 }
@@ -1134,7 +1134,7 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector<int32_
 
 
 	// copy list to array because we are need indexed access to normals.
 	// copy list to array because we are need indexed access to normals.
 	norm_arr_copy.reserve(pNormals.size());
 	norm_arr_copy.reserve(pNormals.size());
-    for ( std::list<aiVector3D>::const_iterator it = pNormals.begin(); it != pNormals.end(); it++ )
+    for ( std::list<aiVector3D>::const_iterator it = pNormals.begin(); it != pNormals.end(); ++it )
     {
     {
         norm_arr_copy.push_back( *it );
         norm_arr_copy.push_back( *it );
     }
     }
@@ -1147,7 +1147,7 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::vector<int32_
 			if(pNormalIdx.size() != pCoordIdx.size()) throw DeadlyImportError("Normals and Coords inidces count must be equal.");
 			if(pNormalIdx.size() != pCoordIdx.size()) throw DeadlyImportError("Normals and Coords inidces count must be equal.");
 
 
 			tind.reserve(pNormalIdx.size());
 			tind.reserve(pNormalIdx.size());
-			for(std::vector<int32_t>::const_iterator it = pNormalIdx.begin(); it != pNormalIdx.end(); it++)
+			for(std::vector<int32_t>::const_iterator it = pNormalIdx.begin(); it != pNormalIdx.end(); ++it)
 			{
 			{
 				if(*it != (-1)) tind.push_back(*it);
 				if(*it != (-1)) tind.push_back(*it);
 			}
 			}
@@ -1227,7 +1227,7 @@ void X3DImporter::MeshGeometry_AddNormal(aiMesh& pMesh, const std::list<aiVector
 			// apply color to all vertices of face
 			// apply color to all vertices of face
 			for(size_t vi = 0, vi_e = pMesh.mFaces[fi].mNumIndices; vi < vi_e; vi++) pMesh.mNormals[pMesh.mFaces[fi].mIndices[vi]] = *norm_it;
 			for(size_t vi = 0, vi_e = pMesh.mFaces[fi].mNumIndices; vi < vi_e; vi++) pMesh.mNormals[pMesh.mFaces[fi].mIndices[vi]] = *norm_it;
 
 
-			norm_it++;
+			++norm_it;
 		}
 		}
 	}// if(pNormalPerVertex) else
 	}// if(pNormalPerVertex) else
 }
 }
@@ -1241,7 +1241,7 @@ void X3DImporter::MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::vector<int3
 
 
 	// copy list to array because we are need indexed access to normals.
 	// copy list to array because we are need indexed access to normals.
 	texcoord_arr_copy.reserve(pTexCoords.size());
 	texcoord_arr_copy.reserve(pTexCoords.size());
-	for(std::list<aiVector2D>::const_iterator it = pTexCoords.begin(); it != pTexCoords.end(); it++)
+	for(std::list<aiVector2D>::const_iterator it = pTexCoords.begin(); it != pTexCoords.end(); ++it)
 	{
 	{
 		texcoord_arr_copy.push_back(aiVector3D((*it).x, (*it).y, 0));
 		texcoord_arr_copy.push_back(aiVector3D((*it).x, (*it).y, 0));
 	}
 	}
@@ -1291,7 +1291,7 @@ void X3DImporter::MeshGeometry_AddTexCoord(aiMesh& pMesh, const std::list<aiVect
 
 
 	// copy list to array because we are need convert aiVector2D to aiVector3D and also get indexed access as a bonus.
 	// copy list to array because we are need convert aiVector2D to aiVector3D and also get indexed access as a bonus.
 	tc_arr_copy.reserve(pTexCoords.size());
 	tc_arr_copy.reserve(pTexCoords.size());
-    for ( std::list<aiVector2D>::const_iterator it = pTexCoords.begin(); it != pTexCoords.end(); it++ )
+    for ( std::list<aiVector2D>::const_iterator it = pTexCoords.begin(); it != pTexCoords.end(); ++it )
     {
     {
         tc_arr_copy.push_back( aiVector3D( ( *it ).x, ( *it ).y, 0 ) );
         tc_arr_copy.push_back( aiVector3D( ( *it ).x, ( *it ).y, 0 ) );
     }
     }
@@ -1699,7 +1699,7 @@ void X3DImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
 		// create nodes tree
 		// create nodes tree
 		Postprocess_BuildNode(*NodeElement_Cur, *pScene->mRootNode, mesh_list, mat_list, light_list);
 		Postprocess_BuildNode(*NodeElement_Cur, *pScene->mRootNode, mesh_list, mat_list, light_list);
 		// copy needed data to scene
 		// copy needed data to scene
-		if(mesh_list.size() > 0)
+		if(!mesh_list.empty())
 		{
 		{
 			std::list<aiMesh*>::const_iterator it = mesh_list.begin();
 			std::list<aiMesh*>::const_iterator it = mesh_list.begin();
 
 
@@ -1708,7 +1708,7 @@ void X3DImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
 			for(size_t i = 0; i < pScene->mNumMeshes; i++) pScene->mMeshes[i] = *it++;
 			for(size_t i = 0; i < pScene->mNumMeshes; i++) pScene->mMeshes[i] = *it++;
 		}
 		}
 
 
-		if(mat_list.size() > 0)
+		if(!mat_list.empty())
 		{
 		{
 			std::list<aiMaterial*>::const_iterator it = mat_list.begin();
 			std::list<aiMaterial*>::const_iterator it = mat_list.begin();
 
 
@@ -1717,7 +1717,7 @@ void X3DImporter::InternReadFile(const std::string& pFile, aiScene* pScene, IOSy
 			for(size_t i = 0; i < pScene->mNumMaterials; i++) pScene->mMaterials[i] = *it++;
 			for(size_t i = 0; i < pScene->mNumMaterials; i++) pScene->mMaterials[i] = *it++;
 		}
 		}
 
 
-		if(light_list.size() > 0)
+		if(!light_list.empty())
 		{
 		{
 			std::list<aiLight*>::const_iterator it = light_list.begin();
 			std::list<aiLight*>::const_iterator it = light_list.begin();
 
 

+ 3 - 3
code/X3D/X3DImporter_Geometry2D.cpp

@@ -356,7 +356,7 @@ void X3DImporter::ParseNode_Geometry2D_Polyline2D()
 		std::list<aiVector3D> tlist;
 		std::list<aiVector3D> tlist;
 
 
 		// convert vec2 to vec3
 		// convert vec2 to vec3
-		for(std::list<aiVector2D>::iterator it2 = lineSegments.begin(); it2 != lineSegments.end(); it2++) tlist.push_back(aiVector3D(it2->x, it2->y, 0));
+		for(std::list<aiVector2D>::iterator it2 = lineSegments.begin(); it2 != lineSegments.end(); ++it2) tlist.push_back(aiVector3D(it2->x, it2->y, 0));
 
 
 		// convert point set to line set
 		// convert point set to line set
 		GeometryHelper_Extend_PointToLine(tlist, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);
 		GeometryHelper_Extend_PointToLine(tlist, ((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices);
@@ -399,7 +399,7 @@ void X3DImporter::ParseNode_Geometry2D_Polypoint2D()
 		if(!def.empty()) ne->ID = def;
 		if(!def.empty()) ne->ID = def;
 
 
 		// convert vec2 to vec3
 		// convert vec2 to vec3
-		for(std::list<aiVector2D>::iterator it2 = point.begin(); it2 != point.end(); it2++)
+		for(std::list<aiVector2D>::iterator it2 = point.begin(); it2 != point.end(); ++it2)
 		{
 		{
 			((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
 			((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
 		}
 		}
@@ -500,7 +500,7 @@ void X3DImporter::ParseNode_Geometry2D_TriangleSet2D()
 		if(!def.empty()) ne->ID = def;
 		if(!def.empty()) ne->ID = def;
 
 
 		// convert vec2 to vec3
 		// convert vec2 to vec3
-		for(std::list<aiVector2D>::iterator it2 = vertices.begin(); it2 != vertices.end(); it2++)
+		for(std::list<aiVector2D>::iterator it2 = vertices.begin(); it2 != vertices.end(); ++it2)
 		{
 		{
 			((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
 			((CX3DImporter_NodeElement_Geometry2D*)ne)->Vertices.push_back(aiVector3D(it2->x, it2->y, 0));
 		}
 		}

+ 7 - 7
code/X3D/X3DImporter_Geometry3D.cpp

@@ -153,11 +153,11 @@ void X3DImporter::ParseNode_Geometry3D_Cone()
 		{
 		{
 			StandardShapes::MakeCircle(bottomRadius, tess, tvec);
 			StandardShapes::MakeCircle(bottomRadius, tess, tvec);
 			height = -(height / 2);
 			height = -(height / 2);
-			for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); it++) it->y = height;// y - because circle made in oXZ.
+			for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it) it->y = height;// y - because circle made in oXZ.
 		}
 		}
 
 
 		// copy data from temp array
 		// copy data from temp array
-		for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); it++) ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices.push_back(*it);
+		for(std::vector<aiVector3D>::iterator it = tvec.begin(); it != tvec.end(); ++it) ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices.push_back(*it);
 
 
 		((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
 		((CX3DImporter_NodeElement_Geometry3D*)ne)->Solid = solid;
 		((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
 		((CX3DImporter_NodeElement_Geometry3D*)ne)->NumIndices = 3;
@@ -226,11 +226,11 @@ void X3DImporter::ParseNode_Geometry3D_Cylinder()
 		// copy data from temp arrays
 		// copy data from temp arrays
 		std::list<aiVector3D>& vlist = ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices;// just short alias.
 		std::list<aiVector3D>& vlist = ((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices;// just short alias.
 
 
-		for(std::vector<aiVector3D>::iterator it = tside.begin(); it != tside.end(); it++) vlist.push_back(*it);
+		for(std::vector<aiVector3D>::iterator it = tside.begin(); it != tside.end(); ++it) vlist.push_back(*it);
 
 
 		if(top)
 		if(top)
 		{
 		{
-			for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); it++)
+			for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it)
 			{
 			{
 				(*it).y = height;// y - because circle made in oXZ.
 				(*it).y = height;// y - because circle made in oXZ.
 				vlist.push_back(*it);
 				vlist.push_back(*it);
@@ -239,7 +239,7 @@ void X3DImporter::ParseNode_Geometry3D_Cylinder()
 
 
 		if(bottom)
 		if(bottom)
 		{
 		{
-			for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); it++)
+			for(std::vector<aiVector3D>::iterator it = tcir.begin(); it != tcir.end(); ++it)
 			{
 			{
 				(*it).y = -height;// y - because circle made in oXZ.
 				(*it).y = -height;// y - because circle made in oXZ.
 				vlist.push_back(*it);
 				vlist.push_back(*it);
@@ -336,7 +336,7 @@ void X3DImporter::ParseNode_Geometry3D_ElevationGrid()
 					aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi);
 					aiVector3D tvec(xSpacing * xi, *he_it, zSpacing * zi);
 
 
 					grid_alias.Vertices.push_back(tvec);
 					grid_alias.Vertices.push_back(tvec);
-					he_it++;
+					++he_it;
 				}
 				}
 			}
 			}
 		}// END: create grid vertices list
 		}// END: create grid vertices list
@@ -977,7 +977,7 @@ void X3DImporter::ParseNode_Geometry3D_Sphere()
 
 
 		StandardShapes::MakeSphere(tess, tlist);
 		StandardShapes::MakeSphere(tess, tlist);
 		// copy data from temp array and apply scale
 		// copy data from temp array and apply scale
-		for(std::vector<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); it++)
+		for(std::vector<aiVector3D>::iterator it = tlist.begin(); it != tlist.end(); ++it)
 		{
 		{
 			((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices.push_back(*it * radius);
 			((CX3DImporter_NodeElement_Geometry3D*)ne)->Vertices.push_back(*it * radius);
 		}
 		}

+ 1 - 1
code/X3D/X3DImporter_Networking.cpp

@@ -93,7 +93,7 @@ void X3DImporter::ParseNode_Networking_Inline()
 		// at this place new group mode created and made current, so we can name it.
 		// at this place new group mode created and made current, so we can name it.
 		if(!def.empty()) NodeElement_Cur->ID = def;
 		if(!def.empty()) NodeElement_Cur->ID = def;
 
 
-		if(load && (url.size() > 0))
+		if(load && !url.empty())
 		{
 		{
 			std::string full_path = mpIOHandler->CurrentDirectory() + url.front();
 			std::string full_path = mpIOHandler->CurrentDirectory() + url.front();
 
 

+ 40 - 40
code/X3D/X3DImporter_Postprocess.cpp

@@ -81,7 +81,7 @@ aiMatrix4x4 X3DImporter::PostprocessHelper_Matrix_GlobalToCurrent() const
 	}
 	}
 
 
 	// multiplicate all matrices in reverse order
 	// multiplicate all matrices in reverse order
-	for(std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); rit++) out_matr = out_matr * (*rit);
+	for(std::list<aiMatrix4x4>::reverse_iterator rit = matr.rbegin(); rit != matr.rend(); ++rit) out_matr = out_matr * (*rit);
 
 
 	return out_matr;
 	return out_matr;
 }
 }
@@ -89,7 +89,7 @@ aiMatrix4x4 X3DImporter::PostprocessHelper_Matrix_GlobalToCurrent() const
 void X3DImporter::PostprocessHelper_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, std::list<CX3DImporter_NodeElement*>& pList) const
 void X3DImporter::PostprocessHelper_CollectMetadata(const CX3DImporter_NodeElement& pNodeElement, std::list<CX3DImporter_NodeElement*>& pList) const
 {
 {
 	// walk through childs and find for metadata.
 	// walk through childs and find for metadata.
-	for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
+	for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); ++el_it)
 	{
 	{
 		if(((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaBoolean) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaDouble) ||
 		if(((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaBoolean) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaDouble) ||
 			((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaFloat) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaInteger) ||
 			((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaFloat) || ((*el_it)->Type == CX3DImporter_NodeElement::ENET_MetaInteger) ||
@@ -194,7 +194,7 @@ void X3DImporter::Postprocess_BuildMaterial(const CX3DImporter_NodeElement& pNod
 	aiMaterial& taimat = **pMaterial;// creating alias for convenience.
 	aiMaterial& taimat = **pMaterial;// creating alias for convenience.
 
 
 	// at this point pNodeElement point to <Appearance> node. Walk through childs and add all stored data.
 	// at this point pNodeElement point to <Appearance> node. Walk through childs and add all stored data.
-	for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); el_it++)
+	for(std::list<CX3DImporter_NodeElement*>::const_iterator el_it = pNodeElement.Child.begin(); el_it != pNodeElement.Child.end(); ++el_it)
 	{
 	{
 		if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material)
 		if((*el_it)->Type == CX3DImporter_NodeElement::ENET_Material)
 		{
 		{
@@ -255,7 +255,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		std::vector<aiVector3D> tarr;
 		std::vector<aiVector3D> tarr;
 
 
 		tarr.reserve(tnemesh.Vertices.size());
 		tarr.reserve(tnemesh.Vertices.size());
-		for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); it++) tarr.push_back(*it);
+		for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); ++it) tarr.push_back(*it);
 		*pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices));// create mesh from vertices using Assimp help.
 		*pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices));// create mesh from vertices using Assimp help.
 
 
 		return;// mesh is build, nothing to do anymore.
 		return;// mesh is build, nothing to do anymore.
@@ -273,7 +273,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		std::vector<aiVector3D> tarr;
 		std::vector<aiVector3D> tarr;
 
 
 		tarr.reserve(tnemesh.Vertices.size());
 		tarr.reserve(tnemesh.Vertices.size());
-		for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); it++) tarr.push_back(*it);
+		for(std::list<aiVector3D>::iterator it = tnemesh.Vertices.begin(); it != tnemesh.Vertices.end(); ++it) tarr.push_back(*it);
 
 
 		*pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices));// create mesh from vertices using Assimp help.
 		*pMesh = StandardShapes::MakeMesh(tarr, static_cast<unsigned int>(tnemesh.NumIndices));// create mesh from vertices using Assimp help.
 
 
@@ -289,7 +289,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		// at first create mesh from existing vertices.
 		// at first create mesh from existing vertices.
 		*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIdx, tnemesh.Vertices);
 		*pMesh = GeometryHelper_MakeMesh(tnemesh.CoordIdx, tnemesh.Vertices);
 		// copy additional information from children
 		// copy additional information from children
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
 				MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
 				MeshGeometry_AddColor(**pMesh, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
@@ -301,7 +301,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 				MeshGeometry_AddTexCoord(**pMesh, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
 				MeshGeometry_AddTexCoord(**pMesh, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
 			else
 			else
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + to_string((*ch_it)->Type) + ".");
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of ElevationGrid: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 
 
 		return;// mesh is build, nothing to do anymore.
 		return;// mesh is build, nothing to do anymore.
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid)
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_ElevationGrid)
@@ -313,7 +313,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
 		CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
 
 
 		// at first search for <Coordinate> node and create mesh.
 		// at first search for <Coordinate> node and create mesh.
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			{
 			{
@@ -322,7 +322,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		}
 		}
 
 
 		// copy additional information from children
 		// copy additional information from children
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
 				MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
 				MeshGeometry_AddColor(**pMesh, tnemesh.CoordIndex, tnemesh.ColorIndex, ((CX3DImporter_NodeElement_Color*)*ch_it)->Value, tnemesh.ColorPerVertex);
@@ -338,7 +338,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
 				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
 			else
 			else
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + to_string((*ch_it)->Type) + ".");
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedFaceSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 
 
 		return;// mesh is build, nothing to do anymore.
 		return;// mesh is build, nothing to do anymore.
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet)
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedFaceSet)
@@ -348,7 +348,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
 		CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
 
 
 		// at first search for <Coordinate> node and create mesh.
 		// at first search for <Coordinate> node and create mesh.
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			{
 			{
@@ -357,7 +357,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		}
 		}
 
 
 		// copy additional information from children
 		// copy additional information from children
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			ai_assert(*pMesh);
 			ai_assert(*pMesh);
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
@@ -369,7 +369,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 				{} // skip because already read when mesh created.
 				{} // skip because already read when mesh created.
 			else
 			else
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + to_string((*ch_it)->Type) + ".");
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedLineSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 
 
 		return;// mesh is build, nothing to do anymore.
 		return;// mesh is build, nothing to do anymore.
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet)
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedLineSet)
@@ -381,7 +381,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
 		CX3DImporter_NodeElement_IndexedSet& tnemesh = *((CX3DImporter_NodeElement_IndexedSet*)&pNodeElement);// create alias for convenience
 
 
 		// at first search for <Coordinate> node and create mesh.
 		// at first search for <Coordinate> node and create mesh.
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			{
 			{
@@ -390,7 +390,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		}
 		}
 
 
 		// copy additional information from children
 		// copy additional information from children
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			ai_assert(*pMesh);
 			ai_assert(*pMesh);
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
@@ -408,7 +408,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 			else
 			else
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of IndexedTriangleSet or IndexedTriangleFanSet, or \
 																	IndexedTriangleStripSet: " + to_string((*ch_it)->Type) + ".");
 																	IndexedTriangleStripSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 
 
 		return;// mesh is build, nothing to do anymore.
 		return;// mesh is build, nothing to do anymore.
 	}// if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet))
 	}// if((pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleFanSet) || (pNodeElement.Type == CX3DImporter_NodeElement::ENET_IndexedTriangleStripSet))
@@ -430,7 +430,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
 		CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
 
 
 		// at first search for <Coordinate> node and create mesh.
 		// at first search for <Coordinate> node and create mesh.
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			{
 			{
@@ -438,7 +438,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 
 
 				vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size());
 				vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size());
 				for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin();
 				for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin();
-					it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); it++)
+					it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); ++it)
 				{
 				{
 					vec_copy.push_back(*it);
 					vec_copy.push_back(*it);
 				}
 				}
@@ -448,7 +448,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		}
 		}
 
 
 		// copy additional information from children
 		// copy additional information from children
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			ai_assert(*pMesh);
 			ai_assert(*pMesh);
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
@@ -459,7 +459,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 				{} // skip because already read when mesh created.
 				{} // skip because already read when mesh created.
 			else
 			else
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + to_string((*ch_it)->Type) + ".");
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of PointSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 
 
 		return;// mesh is build, nothing to do anymore.
 		return;// mesh is build, nothing to do anymore.
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet)
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_PointSet)
@@ -469,7 +469,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
 		CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
 
 
 		// at first search for <Coordinate> node and create mesh.
 		// at first search for <Coordinate> node and create mesh.
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			{
 			{
@@ -478,7 +478,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		}
 		}
 
 
 		// copy additional information from children
 		// copy additional information from children
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			ai_assert(*pMesh);
 			ai_assert(*pMesh);
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
@@ -489,7 +489,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 				{} // skip because already read when mesh created.
 				{} // skip because already read when mesh created.
 			else
 			else
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + to_string((*ch_it)->Type) + ".");
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of LineSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 
 
 		return;// mesh is build, nothing to do anymore.
 		return;// mesh is build, nothing to do anymore.
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet)
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_LineSet)
@@ -499,7 +499,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
 		CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
 
 
 		// at first search for <Coordinate> node and create mesh.
 		// at first search for <Coordinate> node and create mesh.
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			{
 			{
@@ -508,7 +508,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		}
 		}
 
 
 		// copy additional information from children
 		// copy additional information from children
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if ( nullptr == *pMesh ) {
 			if ( nullptr == *pMesh ) {
 				break;
 				break;
@@ -526,7 +526,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
 				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
 			else
 			else
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + to_string((*ch_it)->Type) + ".");
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeFanSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 
 
 		return;// mesh is build, nothing to do anymore.
 		return;// mesh is build, nothing to do anymore.
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet)
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleFanSet)
@@ -536,7 +536,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
 		CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
 
 
 		// at first search for <Coordinate> node and create mesh.
 		// at first search for <Coordinate> node and create mesh.
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			{
 			{
@@ -544,7 +544,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 
 
 				vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size());
 				vec_copy.reserve(((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.size());
 				for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin();
 				for(std::list<aiVector3D>::const_iterator it = ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.begin();
-					it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); it++)
+					it != ((CX3DImporter_NodeElement_Coordinate*)*ch_it)->Value.end(); ++it)
 				{
 				{
 					vec_copy.push_back(*it);
 					vec_copy.push_back(*it);
 				}
 				}
@@ -554,7 +554,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		}
 		}
 
 
 		// copy additional information from children
 		// copy additional information from children
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			ai_assert(*pMesh);
 			ai_assert(*pMesh);
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
@@ -570,7 +570,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
 				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
 			else
 			else
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + to_string((*ch_it)->Type) + ".");
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TrianlgeSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 
 
 		return;// mesh is build, nothing to do anymore.
 		return;// mesh is build, nothing to do anymore.
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet)
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleSet)
@@ -580,7 +580,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
 		CX3DImporter_NodeElement_Set& tnemesh = *((CX3DImporter_NodeElement_Set*)&pNodeElement);// create alias for convenience
 
 
 		// at first search for <Coordinate> node and create mesh.
 		// at first search for <Coordinate> node and create mesh.
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Coordinate)
 			{
 			{
@@ -589,7 +589,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 		}
 		}
 
 
 		// copy additional information from children
 		// copy additional information from children
-		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 		{
 		{
 			ai_assert(*pMesh);
 			ai_assert(*pMesh);
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
 			if((*ch_it)->Type == CX3DImporter_NodeElement::ENET_Color)
@@ -605,7 +605,7 @@ void X3DImporter::Postprocess_BuildMesh(const CX3DImporter_NodeElement& pNodeEle
 				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
 				MeshGeometry_AddTexCoord(**pMesh, tnemesh.CoordIndex, tnemesh.TexCoordIndex, ((CX3DImporter_NodeElement_TextureCoordinate*)*ch_it)->Value);
 			else
 			else
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + to_string((*ch_it)->Type) + ".");
 				throw DeadlyImportError("Postprocess_BuildMesh. Unknown child of TriangleStripSet: " + to_string((*ch_it)->Type) + ".");
-		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ch_it++)
+		}// for(std::list<CX3DImporter_NodeElement*>::iterator ch_it = tnemesh.Child.begin(); ch_it != tnemesh.Child.end(); ++ch_it)
 
 
 		return;// mesh is build, nothing to do anymore.
 		return;// mesh is build, nothing to do anymore.
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_TriangleStripSet)
@@ -639,16 +639,16 @@ void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeEle
 			}
 			}
 			else
 			else
 			{
 			{
-				for(size_t i = 0; i < (size_t)tne_group.Choice; i++) chit_begin++;// forward iterator to chosen node.
+				for(size_t i = 0; i < (size_t)tne_group.Choice; i++) ++chit_begin;// forward iterator to chosen node.
 
 
 				chit_end = chit_begin;
 				chit_end = chit_begin;
-				chit_end++;// point end iterator to next element after chosen node.
+				++chit_end;// point end iterator to next element after chosen node.
 			}
 			}
 		}// if(tne_group.UseChoice)
 		}// if(tne_group.UseChoice)
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group)
 	}// if(pNodeElement.Type == CX3DImporter_NodeElement::ENET_Group)
 
 
 	// Reserve memory for fast access and check children.
 	// Reserve memory for fast access and check children.
-	for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++)
+	for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; ++it)
 	{// in this loop we do not read metadata because it's already read at begin.
 	{// in this loop we do not read metadata because it's already read at begin.
 		if((*it)->Type == CX3DImporter_NodeElement::ENET_Group)
 		if((*it)->Type == CX3DImporter_NodeElement::ENET_Group)
 		{
 		{
@@ -677,7 +677,7 @@ void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeEle
 	}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++)
 	}// for(std::list<CX3DImporter_NodeElement*>::const_iterator it = chit_begin; it != chit_end; it++)
 
 
 	// copy data about children and meshes to aiNode.
 	// copy data about children and meshes to aiNode.
-	if(SceneNode_Child.size() > 0)
+	if(!SceneNode_Child.empty())
 	{
 	{
 		std::list<aiNode*>::const_iterator it = SceneNode_Child.begin();
 		std::list<aiNode*>::const_iterator it = SceneNode_Child.begin();
 
 
@@ -686,7 +686,7 @@ void X3DImporter::Postprocess_BuildNode(const CX3DImporter_NodeElement& pNodeEle
 		for(size_t i = 0; i < pSceneNode.mNumChildren; i++) pSceneNode.mChildren[i] = *it++;
 		for(size_t i = 0; i < pSceneNode.mNumChildren; i++) pSceneNode.mChildren[i] = *it++;
 	}
 	}
 
 
-	if(SceneNode_Mesh.size() > 0)
+	if(!SceneNode_Mesh.empty())
 	{
 	{
 		std::list<unsigned int>::const_iterator it = SceneNode_Mesh.begin();
 		std::list<unsigned int>::const_iterator it = SceneNode_Mesh.begin();
 
 
@@ -706,7 +706,7 @@ void X3DImporter::Postprocess_BuildShape(const CX3DImporter_NodeElement_Shape& p
     CX3DImporter_NodeElement::EType mesh_type = CX3DImporter_NodeElement::ENET_Invalid;
     CX3DImporter_NodeElement::EType mesh_type = CX3DImporter_NodeElement::ENET_Invalid;
     unsigned int mat_ind = 0;
     unsigned int mat_ind = 0;
 
 
-	for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); it++)
+	for(std::list<CX3DImporter_NodeElement*>::const_iterator it = pShapeNodeElement.Child.begin(); it != pShapeNodeElement.Child.end(); ++it)
 	{
 	{
 		if(PostprocessHelper_ElementIsMesh((*it)->Type))
 		if(PostprocessHelper_ElementIsMesh((*it)->Type))
 		{
 		{
@@ -779,7 +779,7 @@ void X3DImporter::Postprocess_CollectMetadata(const CX3DImporter_NodeElement& pN
 		// copy collected metadata to output node.
 		// copy collected metadata to output node.
         pSceneNode.mMetaData = aiMetadata::Alloc( static_cast<unsigned int>(meta_list.size()) );
         pSceneNode.mMetaData = aiMetadata::Alloc( static_cast<unsigned int>(meta_list.size()) );
 		meta_idx = 0;
 		meta_idx = 0;
-		for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); it++, meta_idx++)
+		for(std::list<CX3DImporter_NodeElement*>::const_iterator it = meta_list.begin(); it != meta_list.end(); ++it, ++meta_idx)
 		{
 		{
 			CX3DImporter_NodeElement_Meta* cur_meta = (CX3DImporter_NodeElement_Meta*)*it;
 			CX3DImporter_NodeElement_Meta* cur_meta = (CX3DImporter_NodeElement_Meta*)*it;
 
 

+ 6 - 6
code/X3D/X3DImporter_Rendering.cpp

@@ -295,7 +295,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleFanSet()
 		ne_alias.CoordIndex.clear();
 		ne_alias.CoordIndex.clear();
 		int counter = 0;
 		int counter = 0;
 		int32_t idx[3];
 		int32_t idx[3];
-		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
+		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it)
 		{
 		{
 			idx[2] = *idx_it;
 			idx[2] = *idx_it;
 			if (idx[2] < 0)
 			if (idx[2] < 0)
@@ -413,7 +413,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleSet()
 		ne_alias.CoordIndex.clear();
 		ne_alias.CoordIndex.clear();
 		int counter = 0;
 		int counter = 0;
 		int32_t idx[3];
 		int32_t idx[3];
-		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
+		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it)
 		{
 		{
 			idx[counter++] = *idx_it;
 			idx[counter++] = *idx_it;
 			if (counter > 2)
 			if (counter > 2)
@@ -519,7 +519,7 @@ void X3DImporter::ParseNode_Rendering_IndexedTriangleStripSet()
 		ne_alias.CoordIndex.clear();
 		ne_alias.CoordIndex.clear();
 		int counter = 0;
 		int counter = 0;
 		int32_t idx[3];
 		int32_t idx[3];
-		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); idx_it++)
+		for(std::vector<int32_t>::const_iterator idx_it = index.begin(); idx_it != index.end(); ++idx_it)
 		{
 		{
 			idx[2] = *idx_it;
 			idx[2] = *idx_it;
 			if (idx[2] < 0)
 			if (idx[2] < 0)
@@ -617,7 +617,7 @@ void X3DImporter::ParseNode_Rendering_LineSet()
 		size_t coord_num = 0;
 		size_t coord_num = 0;
 
 
 		ne_alias.CoordIndex.clear();
 		ne_alias.CoordIndex.clear();
-		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it)
 		{
 		{
 			if(*vc_it < 2) throw DeadlyImportError("LineSet. vertexCount shall be greater than or equal to two.");
 			if(*vc_it < 2) throw DeadlyImportError("LineSet. vertexCount shall be greater than or equal to two.");
 
 
@@ -765,7 +765,7 @@ void X3DImporter::ParseNode_Rendering_TriangleFanSet()
 		// assign indices for first triangle
 		// assign indices for first triangle
 		coord_num_first = 0;
 		coord_num_first = 0;
 		coord_num_prev = 1;
 		coord_num_prev = 1;
-		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it)
 		{
 		{
 			if(*vc_it < 3) throw DeadlyImportError("TriangleFanSet. fanCount shall be greater than or equal to three.");
 			if(*vc_it < 3) throw DeadlyImportError("TriangleFanSet. fanCount shall be greater than or equal to three.");
 
 
@@ -956,7 +956,7 @@ void X3DImporter::ParseNode_Rendering_TriangleStripSet()
 
 
 		ne_alias.CoordIndex.clear();
 		ne_alias.CoordIndex.clear();
 		coord_num_sb = 0;
 		coord_num_sb = 0;
-		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); vc_it++)
+		for(std::vector<int32_t>::const_iterator vc_it = ne_alias.VertexCount.begin(); vc_it != ne_alias.VertexCount.end(); ++vc_it)
 		{
 		{
 			if(*vc_it < 3) throw DeadlyImportError("TriangleStripSet. stripCount shall be greater than or equal to three.");
 			if(*vc_it < 3) throw DeadlyImportError("TriangleStripSet. stripCount shall be greater than or equal to three.");
 
 

+ 1 - 1
code/X3D/X3DImporter_Texturing.cpp

@@ -89,7 +89,7 @@ void X3DImporter::ParseNode_Texturing_ImageTexture()
 		((CX3DImporter_NodeElement_ImageTexture*)ne)->RepeatS = repeatS;
 		((CX3DImporter_NodeElement_ImageTexture*)ne)->RepeatS = repeatS;
 		((CX3DImporter_NodeElement_ImageTexture*)ne)->RepeatT = repeatT;
 		((CX3DImporter_NodeElement_ImageTexture*)ne)->RepeatT = repeatT;
 		// Attribute "url" can contain list of strings. But we need only one - first.
 		// Attribute "url" can contain list of strings. But we need only one - first.
-		if(url.size() > 0)
+		if(!url.empty())
 			((CX3DImporter_NodeElement_ImageTexture*)ne)->URL = url.front();
 			((CX3DImporter_NodeElement_ImageTexture*)ne)->URL = url.front();
 		else
 		else
 			((CX3DImporter_NodeElement_ImageTexture*)ne)->URL = "";
 			((CX3DImporter_NodeElement_ImageTexture*)ne)->URL = "";

+ 8 - 61
code/glTF/glTFAsset.h

@@ -92,38 +92,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #   endif
 #   endif
 #endif
 #endif
 
 
+#include "glTF/glTFCommon.h"
+
 namespace glTF
 namespace glTF
 {
 {
-#ifdef ASSIMP_API
-    using Assimp::IOStream;
-    using Assimp::IOSystem;
-    using std::shared_ptr;
-#else
-    using std::shared_ptr;
-
-    typedef std::runtime_error DeadlyImportError;
-    typedef std::runtime_error DeadlyExportError;
-
-    enum aiOrigin { aiOrigin_SET = 0, aiOrigin_CUR = 1, aiOrigin_END = 2 };
-    class IOSystem;
-    class IOStream
-    {
-        FILE* f;
-    public:
-        IOStream(FILE* file) : f(file) {}
-        ~IOStream() { fclose(f); f = 0; }
-
-        size_t Read(void* b, size_t sz, size_t n) { return fread(b, sz, n, f); }
-        size_t Write(const void* b, size_t sz, size_t n) { return fwrite(b, sz, n, f); }
-        int    Seek(size_t off, aiOrigin orig) { return fseek(f, off, int(orig)); }
-        size_t Tell() const { return ftell(f); }
-
-        size_t FileSize() {
-            long p = Tell(), len = (Seek(0, aiOrigin_END), Tell());
-            return size_t((Seek(p, aiOrigin_SET), len));
-        }
-    };
-#endif
+    using glTFCommon::shared_ptr;
+    using glTFCommon::IOSystem;
+    using glTFCommon::IOStream;
 
 
     using rapidjson::Value;
     using rapidjson::Value;
     using rapidjson::Document;
     using rapidjson::Document;
@@ -136,37 +111,9 @@ namespace glTF
     struct Light;
     struct Light;
     struct Skin;
     struct Skin;
 
 
-
-    // Vec/matrix types, as raw float arrays
-    typedef float (vec3)[3];
-    typedef float (vec4)[4];
-    typedef float (mat4)[16];
-
-
-    namespace Util
-    {
-        void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
-
-        size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
-
-        inline size_t DecodeBase64(const char* in, uint8_t*& out)
-        {
-            return DecodeBase64(in, strlen(in), out);
-        }
-
-        struct DataURI
-        {
-            const char* mediaType;
-            const char* charset;
-            bool base64;
-            const char* data;
-            size_t dataLength;
-        };
-
-        //! Check if a uri is a data URI
-        inline bool ParseDataURI(const char* uri, size_t uriLen, DataURI& out);
-    }
-
+    using glTFCommon::vec3;
+    using glTFCommon::vec4;
+    using glTFCommon::mat4;
 
 
     //! Magic number for GLB files
     //! Magic number for GLB files
     #define AI_GLB_MAGIC_NUMBER "glTF"
     #define AI_GLB_MAGIC_NUMBER "glTF"

+ 10 - 192
code/glTF/glTFAsset.inl

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2019, assimp team
 Copyright (c) 2006-2019, 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,
@@ -52,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endif
 #endif
 
 
 using namespace Assimp;
 using namespace Assimp;
+using namespace glTFCommon;
 
 
 namespace glTF {
 namespace glTF {
 
 
@@ -301,7 +301,7 @@ inline void Buffer::Read(Value& obj, Asset& r)
 
 
     const char* uri = it->GetString();
     const char* uri = it->GetString();
 
 
-    Util::DataURI dataURI;
+    glTFCommon::Util::DataURI dataURI;
     if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
     if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
         if (dataURI.base64) {
         if (dataURI.base64) {
             uint8_t* data = 0;
             uint8_t* data = 0;
@@ -654,12 +654,12 @@ inline void Image::Read(Value& obj, Asset& r)
         if (Value* uri = FindString(obj, "uri")) {
         if (Value* uri = FindString(obj, "uri")) {
             const char* uristr = uri->GetString();
             const char* uristr = uri->GetString();
 
 
-            Util::DataURI dataURI;
+            glTFCommon::Util::DataURI dataURI;
             if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) {
             if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) {
                 mimeType = dataURI.mediaType;
                 mimeType = dataURI.mediaType;
                 if (dataURI.base64) {
                 if (dataURI.base64) {
                     uint8_t *ptr = nullptr;
                     uint8_t *ptr = nullptr;
-                    mDataLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, ptr);
+                    mDataLength = glTFCommon::Util::DecodeBase64(dataURI.data, dataURI.dataLength, ptr);
                     mData.reset(ptr);
                     mData.reset(ptr);
                 }
                 }
             }
             }
@@ -1180,8 +1180,12 @@ inline void Light::SetDefaults()
     falloffExponent = 0.f;
     falloffExponent = 0.f;
 }
 }
 
 
-inline void Node::Read(Value& obj, Asset& r)
-{
+inline 
+void Node::Read(Value& obj, Asset& r) {
+    if (name.empty()) {
+        name = id;
+    }
+
     if (Value* children = FindArray(obj, "children")) {
     if (Value* children = FindArray(obj, "children")) {
         this->children.reserve(children->Size());
         this->children.reserve(children->Size());
         for (unsigned int i = 0; i < children->Size(); ++i) {
         for (unsigned int i = 0; i < children->Size(); ++i) {
@@ -1474,190 +1478,4 @@ inline std::string Asset::FindUniqueID(const std::string& str, const char* suffi
     return id;
     return id;
 }
 }
 
 
-namespace Util {
-
-    inline
-    bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
-        if ( NULL == const_uri ) {
-            return false;
-        }
-
-        if (const_uri[0] != 0x10) { // we already parsed this uri?
-            if (strncmp(const_uri, "data:", 5) != 0) // not a data uri?
-                return false;
-        }
-
-        // set defaults
-        out.mediaType = "text/plain";
-        out.charset = "US-ASCII";
-        out.base64 = false;
-
-        char* uri = const_cast<char*>(const_uri);
-        if (uri[0] != 0x10) {
-            uri[0] = 0x10;
-            uri[1] = uri[2] = uri[3] = uri[4] = 0;
-
-            size_t i = 5, j;
-            if (uri[i] != ';' && uri[i] != ',') { // has media type?
-                uri[1] = char(i);
-                for (; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
-                    // nothing to do!
-                }
-            }
-            while (uri[i] == ';' && i < uriLen) {
-                uri[i++] = '\0';
-                for (j = i; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
-                    // nothing to do!
-                }
-
-                if ( strncmp( uri + j, "charset=", 8 ) == 0 ) {
-                    uri[2] = char(j + 8);
-                } else if ( strncmp( uri + j, "base64", 6 ) == 0 ) {
-                    uri[3] = char(j);
-                }
-            }
-            if (i < uriLen) {
-                uri[i++] = '\0';
-                uri[4] = char(i);
-            } else {
-                uri[1] = uri[2] = uri[3] = 0;
-                uri[4] = 5;
-            }
-        }
-
-        if ( uri[ 1 ] != 0 ) {
-            out.mediaType = uri + uri[ 1 ];
-        }
-        if ( uri[ 2 ] != 0 ) {
-            out.charset = uri + uri[ 2 ];
-        }
-        if ( uri[ 3 ] != 0 ) {
-            out.base64 = true;
-        }
-        out.data = uri + uri[4];
-        out.dataLength = (uri + uriLen) - out.data;
-
-        return true;
-    }
-
-    template<bool B>
-    struct DATA
-    {
-        static const uint8_t tableDecodeBase64[128];
-    };
-
-    template<bool B>
-    const uint8_t DATA<B>::tableDecodeBase64[128] = {
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0, 63,
-        52, 53, 54, 55, 56, 57, 58, 59, 60, 61,  0,  0,  0, 64,  0,  0,
-         0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
-        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,
-         0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,  0,  0,  0,  0,  0
-    };
-
-    inline char EncodeCharBase64(uint8_t b)
-    {
-        return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)];
-    }
-
-    inline uint8_t DecodeCharBase64(char c)
-    {
-        return DATA<true>::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs?
-        /*if (c >= 'A' && c <= 'Z') return c - 'A';
-        if (c >= 'a' && c <= 'z') return c - 'a' + 26;
-        if (c >= '0' && c <= '9') return c - '0' + 52;
-        if (c == '+') return 62;
-        if (c == '/') return 63;
-        return 64; // '-' */
-    }
-
-    inline size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
-    {
-        ai_assert(inLength % 4 == 0);
-
-        if (inLength < 4) {
-            out = 0;
-            return 0;
-        }
-
-        int nEquals = int(in[inLength - 1] == '=') +
-                      int(in[inLength - 2] == '=');
-
-        size_t outLength = (inLength * 3) / 4 - nEquals;
-        out = new uint8_t[outLength];
-        memset(out, 0, outLength);
-
-        size_t i, j = 0;
-
-        for (i = 0; i + 4 < inLength; i += 4) {
-            uint8_t b0 = DecodeCharBase64(in[i]);
-            uint8_t b1 = DecodeCharBase64(in[i + 1]);
-            uint8_t b2 = DecodeCharBase64(in[i + 2]);
-            uint8_t b3 = DecodeCharBase64(in[i + 3]);
-
-            out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
-            out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
-            out[j++] = (uint8_t)((b2 << 6) | b3);
-        }
-
-        {
-            uint8_t b0 = DecodeCharBase64(in[i]);
-            uint8_t b1 = DecodeCharBase64(in[i + 1]);
-            uint8_t b2 = DecodeCharBase64(in[i + 2]);
-            uint8_t b3 = DecodeCharBase64(in[i + 3]);
-
-            out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
-            if (b2 < 64) out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
-            if (b3 < 64) out[j++] = (uint8_t)((b2 << 6) | b3);
-        }
-
-        return outLength;
-    }
-
-
-
-    inline void EncodeBase64(
-        const uint8_t* in, size_t inLength,
-        std::string& out)
-    {
-        size_t outLength = ((inLength + 2) / 3) * 4;
-
-        size_t j = out.size();
-        out.resize(j + outLength);
-
-        for (size_t i = 0; i <  inLength; i += 3) {
-            uint8_t b = (in[i] & 0xFC) >> 2;
-            out[j++] = EncodeCharBase64(b);
-
-            b = (in[i] & 0x03) << 4;
-            if (i + 1 < inLength) {
-                b |= (in[i + 1] & 0xF0) >> 4;
-                out[j++] = EncodeCharBase64(b);
-
-                b = (in[i + 1] & 0x0F) << 2;
-                if (i + 2 < inLength) {
-                    b |= (in[i + 2] & 0xC0) >> 6;
-                    out[j++] = EncodeCharBase64(b);
-
-                    b = in[i + 2] & 0x3F;
-                    out[j++] = EncodeCharBase64(b);
-                }
-                else {
-                    out[j++] = EncodeCharBase64(b);
-                    out[j++] = '=';
-                }
-            }
-            else {
-                out[j++] = EncodeCharBase64(b);
-                out[j++] = '=';
-                out[j++] = '=';
-            }
-        }
-    }
-
-}
-
 } // ns glTF
 } // ns glTF

+ 5 - 3
code/glTF/glTFAssetWriter.inl

@@ -55,7 +55,8 @@ namespace glTF {
     namespace {
     namespace {
 
 
         template<size_t N>
         template<size_t N>
-        inline Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
+        inline 
+        Value& MakeValue(Value& val, float(&r)[N], MemoryPoolAllocator<>& al) {
             val.SetArray();
             val.SetArray();
             val.Reserve(N, al);
             val.Reserve(N, al);
             for (decltype(N) i = 0; i < N; ++i) {
             for (decltype(N) i = 0; i < N; ++i) {
@@ -64,7 +65,8 @@ namespace glTF {
             return val;
             return val;
         }
         }
 
 
-        inline Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
+        inline 
+        Value& MakeValue(Value& val, const std::vector<float> & r, MemoryPoolAllocator<>& al) {
             val.SetArray();
             val.SetArray();
             val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
             val.Reserve(static_cast<rapidjson::SizeType>(r.size()), al);
             for (unsigned int i = 0; i < r.size(); ++i) {
             for (unsigned int i = 0; i < r.size(); ++i) {
@@ -213,7 +215,7 @@ namespace glTF {
         else if (img.HasData()) {
         else if (img.HasData()) {
             uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
             uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
             uri += ";base64,";
             uri += ";base64,";
-            Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
+            glTFCommon::Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
         }
         }
         else {
         else {
             uri = img.uri;
             uri = img.uri;

+ 193 - 0
code/glTF/glTFCommon.cpp

@@ -0,0 +1,193 @@
+/*
+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 "glTF/glTFCommon.h"
+
+namespace glTFCommon {
+
+using namespace glTFCommon::Util;
+
+namespace Util {
+
+size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out) {
+    ai_assert(inLength % 4 == 0);
+
+    if (inLength < 4) {
+        out = 0;
+        return 0;
+    }
+
+    int nEquals = int(in[inLength - 1] == '=') +
+        int(in[inLength - 2] == '=');
+
+    size_t outLength = (inLength * 3) / 4 - nEquals;
+    out = new uint8_t[outLength];
+    memset(out, 0, outLength);
+
+    size_t i, j = 0;
+
+    for (i = 0; i + 4 < inLength; i += 4) {
+        uint8_t b0 = DecodeCharBase64(in[i]);
+        uint8_t b1 = DecodeCharBase64(in[i + 1]);
+        uint8_t b2 = DecodeCharBase64(in[i + 2]);
+        uint8_t b3 = DecodeCharBase64(in[i + 3]);
+
+        out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
+        out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
+        out[j++] = (uint8_t)((b2 << 6) | b3);
+    }
+
+    {
+        uint8_t b0 = DecodeCharBase64(in[i]);
+        uint8_t b1 = DecodeCharBase64(in[i + 1]);
+        uint8_t b2 = DecodeCharBase64(in[i + 2]);
+        uint8_t b3 = DecodeCharBase64(in[i + 3]);
+
+        out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
+        if (b2 < 64) out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
+        if (b3 < 64) out[j++] = (uint8_t)((b2 << 6) | b3);
+    }
+
+    return outLength;
+}
+
+void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out) {
+    size_t outLength = ((inLength + 2) / 3) * 4;
+
+    size_t j = out.size();
+    out.resize(j + outLength);
+
+    for (size_t i = 0; i < inLength; i += 3) {
+        uint8_t b = (in[i] & 0xFC) >> 2;
+        out[j++] = EncodeCharBase64(b);
+
+        b = (in[i] & 0x03) << 4;
+        if (i + 1 < inLength) {
+            b |= (in[i + 1] & 0xF0) >> 4;
+            out[j++] = EncodeCharBase64(b);
+
+            b = (in[i + 1] & 0x0F) << 2;
+            if (i + 2 < inLength) {
+                b |= (in[i + 2] & 0xC0) >> 6;
+                out[j++] = EncodeCharBase64(b);
+
+                b = in[i + 2] & 0x3F;
+                out[j++] = EncodeCharBase64(b);
+            }
+            else {
+                out[j++] = EncodeCharBase64(b);
+                out[j++] = '=';
+            }
+        }
+        else {
+            out[j++] = EncodeCharBase64(b);
+            out[j++] = '=';
+            out[j++] = '=';
+        }
+    }
+}
+
+bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
+    if (nullptr == const_uri) {
+        return false;
+    }
+
+    if (const_uri[0] != 0x10) { // we already parsed this uri?
+        if (strncmp(const_uri, "data:", 5) != 0) // not a data uri?
+            return false;
+    }
+
+    // set defaults
+    out.mediaType = "text/plain";
+    out.charset = "US-ASCII";
+    out.base64 = false;
+
+    char* uri = const_cast<char*>(const_uri);
+    if (uri[0] != 0x10) {
+        uri[0] = 0x10;
+        uri[1] = uri[2] = uri[3] = uri[4] = 0;
+
+        size_t i = 5, j;
+        if (uri[i] != ';' && uri[i] != ',') { // has media type?
+            uri[1] = char(i);
+            for (; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
+                // nothing to do!
+            }
+        }
+        while (uri[i] == ';' && i < uriLen) {
+            uri[i++] = '\0';
+            for (j = i; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
+                // nothing to do!
+            }
+
+            if (strncmp(uri + j, "charset=", 8) == 0) {
+                uri[2] = char(j + 8);
+            }
+            else if (strncmp(uri + j, "base64", 6) == 0) {
+                uri[3] = char(j);
+            }
+        }
+        if (i < uriLen) {
+            uri[i++] = '\0';
+            uri[4] = char(i);
+        }
+        else {
+            uri[1] = uri[2] = uri[3] = 0;
+            uri[4] = 5;
+        }
+    }
+
+    if (uri[1] != 0) {
+        out.mediaType = uri + uri[1];
+    }
+    if (uri[2] != 0) {
+        out.charset = uri + uri[2];
+    }
+    if (uri[3] != 0) {
+        out.base64 = true;
+    }
+    out.data = uri + uri[4];
+    out.dataLength = (uri + uriLen) - out.data;
+
+    return true;
+}
+
+}
+}

+ 248 - 0
code/glTF/glTFCommon.h

@@ -0,0 +1,248 @@
+/*
+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.
+
+----------------------------------------------------------------------
+*/
+#ifndef AI_GLFTCOMMON_H_INC
+#define AI_GLFTCOMMON_H_INC
+
+#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#include <assimp/Exceptional.h>
+
+#include <map>
+#include <string>
+#include <list>
+#include <vector>
+#include <algorithm>
+#include <stdexcept>
+
+#define RAPIDJSON_HAS_STDSTRING 1
+#include <rapidjson/rapidjson.h>
+#include <rapidjson/document.h>
+#include <rapidjson/error/en.h>
+
+#ifdef ASSIMP_API
+#   include <memory>
+#   include <assimp/DefaultIOSystem.h>
+#   include <assimp/ByteSwapper.h>
+#else
+#   include <memory>
+#   define AI_SWAP4(p)
+#   define ai_assert
+#endif
+
+
+#if _MSC_VER > 1500 || (defined __GNUC___)
+#       define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
+#   else
+#       define gltf_unordered_map map
+#endif
+
+#ifdef ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
+#   include <unordered_map>
+#   if _MSC_VER > 1600
+#       define gltf_unordered_map unordered_map
+#   else
+#       define gltf_unordered_map tr1::unordered_map
+#   endif
+#endif
+
+namespace glTFCommon {
+
+#ifdef ASSIMP_API
+    using Assimp::IOStream;
+    using Assimp::IOSystem;
+    using std::shared_ptr;
+#else
+    using std::shared_ptr;
+
+    typedef std::runtime_error DeadlyImportError;
+    typedef std::runtime_error DeadlyExportError;
+
+    enum aiOrigin {
+        aiOrigin_SET = 0,
+        aiOrigin_CUR = 1,
+        aiOrigin_END = 2
+    };
+
+    class IOSystem;
+
+    class IOStream {
+    public:
+        IOStream(FILE* file) : f(file) {}
+        ~IOStream() { fclose(f); f = 0; }
+
+        size_t Read(void* b, size_t sz, size_t n) { return fread(b, sz, n, f); }
+        size_t Write(const void* b, size_t sz, size_t n) { return fwrite(b, sz, n, f); }
+        int    Seek(size_t off, aiOrigin orig) { return fseek(f, off, int(orig)); }
+        size_t Tell() const { return ftell(f); }
+
+        size_t FileSize() {
+            long p = Tell(), len = (Seek(0, aiOrigin_END), Tell());
+            return size_t((Seek(p, aiOrigin_SET), len));
+        }
+
+    private:
+        FILE* f;
+    };
+#endif
+
+    // Vec/matrix types, as raw float arrays
+    typedef float(vec3)[3];
+    typedef float(vec4)[4];
+    typedef float(mat4)[16];
+
+    inline
+    void CopyValue(const glTFCommon::vec3& v, aiColor4D& out) {
+        out.r = v[0];
+        out.g = v[1];
+        out.b = v[2];
+        out.a = 1.0;
+    }
+
+    inline
+    void CopyValue(const glTFCommon::vec4& v, aiColor4D& out) {
+        out.r = v[0];
+        out.g = v[1];
+        out.b = v[2];
+        out.a = v[3];
+    }
+
+    inline
+    void CopyValue(const glTFCommon::vec4& v, aiColor3D& out) {
+        out.r = v[0];
+        out.g = v[1];
+        out.b = v[2];
+    }
+
+    inline
+    void CopyValue(const glTFCommon::vec3& v, aiColor3D& out) {
+        out.r = v[0];
+        out.g = v[1];
+        out.b = v[2];
+    }
+
+    inline
+    void CopyValue(const glTFCommon::vec3& v, aiVector3D& out) {
+        out.x = v[0];
+        out.y = v[1];
+        out.z = v[2];
+    }
+
+    inline
+    void CopyValue(const glTFCommon::vec4& v, aiQuaternion& out) {
+        out.x = v[0];
+        out.y = v[1];
+        out.z = v[2];
+        out.w = v[3];
+    }
+
+    inline
+    void CopyValue(const glTFCommon::mat4& v, aiMatrix4x4& o) {
+        o.a1 = v[0]; o.b1 = v[1]; o.c1 = v[2]; o.d1 = v[3];
+        o.a2 = v[4]; o.b2 = v[5]; o.c2 = v[6]; o.d2 = v[7];
+        o.a3 = v[8]; o.b3 = v[9]; o.c3 = v[10]; o.d3 = v[11];
+        o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
+    }
+
+    namespace Util {
+
+        void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
+
+        size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
+
+        inline
+            size_t DecodeBase64(const char* in, uint8_t*& out) {
+            return DecodeBase64(in, strlen(in), out);
+        }
+
+        struct DataURI {
+            const char* mediaType;
+            const char* charset;
+            bool base64;
+            const char* data;
+            size_t dataLength;
+        };
+
+        //! Check if a uri is a data URI
+        bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out);
+
+        template<bool B>
+        struct DATA {
+            static const uint8_t tableDecodeBase64[128];
+        };
+
+        template<bool B>
+        const uint8_t DATA<B>::tableDecodeBase64[128] = {
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
+                0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0, 63,
+            52, 53, 54, 55, 56, 57, 58, 59, 60, 61,  0,  0,  0, 64,  0,  0,
+                0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
+            15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,
+                0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
+            41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,  0,  0,  0,  0,  0
+        };
+
+        inline
+            char EncodeCharBase64(uint8_t b) {
+            return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)];
+        }
+
+        inline
+            uint8_t DecodeCharBase64(char c) {
+            return DATA<true>::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs?
+            /*if (c >= 'A' && c <= 'Z') return c - 'A';
+            if (c >= 'a' && c <= 'z') return c - 'a' + 26;
+            if (c >= '0' && c <= '9') return c - '0' + 52;
+            if (c == '+') return 62;
+            if (c == '/') return 63;
+            return 64; // '-' */
+        }
+
+        size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
+
+        void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
+    }
+
+}
+
+#endif  // ASSIMP_BUILD_NO_GLTF_IMPORTER
+
+#endif // AI_GLFTCOMMON_H_INC

+ 4 - 1
code/glTF/glTFExporter.cpp

@@ -242,7 +242,10 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
 
 
 namespace {
 namespace {
     void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) {
     void GetMatScalar(const aiMaterial* mat, float& val, const char* propName, int type, int idx) {
-        ai_assert(mat->Get(propName, type, idx, val) == AI_SUCCESS);
+        ai_assert( nullptr != mat );
+        if ( nullptr != mat ) {
+            mat->Get(propName, type, idx, val);
+        }
     }
     }
 }
 }
 
 

+ 24 - 58
code/glTF/glTFImporter.cpp

@@ -82,7 +82,7 @@ glTFImporter::glTFImporter()
 : BaseImporter()
 : BaseImporter()
 , meshOffsets()
 , meshOffsets()
 , embeddedTexIdxs()
 , embeddedTexIdxs()
-, mScene( NULL ) {
+, mScene( nullptr ) {
     // empty
     // empty
 }
 }
 
 
@@ -90,17 +90,16 @@ glTFImporter::~glTFImporter() {
     // empty
     // empty
 }
 }
 
 
-const aiImporterDesc* glTFImporter::GetInfo() const
-{
+const aiImporterDesc* glTFImporter::GetInfo() const {
     return &desc;
     return &desc;
 }
 }
 
 
-bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool /* checkSig */) const
-{
+bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool /* checkSig */) const {
     const std::string &extension = GetExtension(pFile);
     const std::string &extension = GetExtension(pFile);
 
 
-    if (extension != "gltf" && extension != "glb")
+    if (extension != "gltf" && extension != "glb") {
         return false;
         return false;
+    }
 
 
     if (pIOHandler) {
     if (pIOHandler) {
         glTF::Asset asset(pIOHandler);
         glTF::Asset asset(pIOHandler);
@@ -116,44 +115,9 @@ bool glTFImporter::CanRead(const std::string& pFile, IOSystem* pIOHandler, bool
     return false;
     return false;
 }
 }
 
 
-
-
-//static void CopyValue(const glTF::vec3& v, aiColor3D& out)
-//{
-//    out.r = v[0]; out.g = v[1]; out.b = v[2];
-//}
-
-static void CopyValue(const glTF::vec4& v, aiColor4D& out)
-{
-    out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3];
-}
-
-static void CopyValue(const glTF::vec4& v, aiColor3D& out)
-{
-    out.r = v[0]; out.g = v[1]; out.b = v[2];
-}
-
-static void CopyValue(const glTF::vec3& v, aiVector3D& out)
-{
-    out.x = v[0]; out.y = v[1]; out.z = v[2];
-}
-
-static void CopyValue(const glTF::vec4& v, aiQuaternion& out)
-{
-    out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3];
-}
-
-static void CopyValue(const glTF::mat4& v, aiMatrix4x4& o)
-{
-    o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3];
-    o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7];
-    o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11];
-    o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
-}
-
-inline void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& /*r*/, glTF::TexProperty prop, aiMaterial* mat,
-    aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx)
-{
+inline
+void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& /*r*/, glTF::TexProperty prop, aiMaterial* mat,
+        aiTextureType texType, const char* pKey, unsigned int type, unsigned int idx) {
     if (prop.texture) {
     if (prop.texture) {
         if (prop.texture->source) {
         if (prop.texture->source) {
             aiString uri(prop.texture->source->uri);
             aiString uri(prop.texture->source->uri);
@@ -167,16 +131,14 @@ inline void SetMaterialColorProperty(std::vector<int>& embeddedTexIdxs, Asset& /
 
 
             mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0);
             mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0);
         }
         }
-    }
-    else {
+    } else {
         aiColor4D col;
         aiColor4D col;
         CopyValue(prop.color, col);
         CopyValue(prop.color, col);
         mat->AddProperty(&col, 1, pKey, type, idx);
         mat->AddProperty(&col, 1, pKey, type, idx);
     }
     }
 }
 }
 
 
-void glTFImporter::ImportMaterials(glTF::Asset& r)
-{
+void glTFImporter::ImportMaterials(glTF::Asset& r) {
     mScene->mNumMaterials = unsigned(r.materials.Size());
     mScene->mNumMaterials = unsigned(r.materials.Size());
     mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials];
     mScene->mMaterials = new aiMaterial*[mScene->mNumMaterials];
 
 
@@ -304,7 +266,7 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
 
 
             aim->mName = mesh.id;
             aim->mName = mesh.id;
             if (mesh.primitives.size() > 1) {
             if (mesh.primitives.size() > 1) {
-                size_t& len = aim->mName.length;
+                ai_uint32& len = aim->mName.length;
                 aim->mName.data[len] = '-';
                 aim->mName.data[len] = '-';
                 len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
                 len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
             }
             }
@@ -499,27 +461,31 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
     CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
     CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
 }
 }
 
 
-void glTFImporter::ImportCameras(glTF::Asset& r)
-{
-    if (!r.cameras.Size()) return;
+void glTFImporter::ImportCameras(glTF::Asset& r) {
+    if (!r.cameras.Size()) {
+        return;
+    }
 
 
     mScene->mNumCameras = r.cameras.Size();
     mScene->mNumCameras = r.cameras.Size();
     mScene->mCameras = new aiCamera*[r.cameras.Size()];
     mScene->mCameras = new aiCamera*[r.cameras.Size()];
-
     for (size_t i = 0; i < r.cameras.Size(); ++i) {
     for (size_t i = 0; i < r.cameras.Size(); ++i) {
         Camera& cam = r.cameras[i];
         Camera& cam = r.cameras[i];
 
 
         aiCamera* aicam = mScene->mCameras[i] = new aiCamera();
         aiCamera* aicam = mScene->mCameras[i] = new aiCamera();
 
 
         if (cam.type == Camera::Perspective) {
         if (cam.type == Camera::Perspective) {
-
             aicam->mAspect        = cam.perspective.aspectRatio;
             aicam->mAspect        = cam.perspective.aspectRatio;
-            aicam->mHorizontalFOV = cam.perspective.yfov * aicam->mAspect;
+            aicam->mHorizontalFOV = cam.perspective.yfov * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect);
             aicam->mClipPlaneFar  = cam.perspective.zfar;
             aicam->mClipPlaneFar  = cam.perspective.zfar;
             aicam->mClipPlaneNear = cam.perspective.znear;
             aicam->mClipPlaneNear = cam.perspective.znear;
-        }
-        else {
-            // assimp does not support orthographic cameras
+        } else {
+            aicam->mClipPlaneFar = cam.ortographic.zfar;
+            aicam->mClipPlaneNear = cam.ortographic.znear;
+            aicam->mHorizontalFOV = 0.0;
+            aicam->mAspect = 1.0f;
+            if (0.f != cam.ortographic.ymag) {
+                aicam->mAspect = cam.ortographic.xmag / cam.ortographic.ymag;
+            }
         }
         }
     }
     }
 }
 }

+ 9 - 60
code/glTF2/glTF2Asset.h

@@ -95,38 +95,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include <assimp/StringUtils.h>
 #include <assimp/StringUtils.h>
 
 
+#include "glTF/glTFCommon.h"
+
 namespace glTF2
 namespace glTF2
 {
 {
-#ifdef ASSIMP_API
-    using Assimp::IOStream;
-    using Assimp::IOSystem;
-    using std::shared_ptr;
-#else
-    using std::shared_ptr;
-
-    typedef std::runtime_error DeadlyImportError;
-    typedef std::runtime_error DeadlyExportError;
-
-    enum aiOrigin { aiOrigin_SET = 0, aiOrigin_CUR = 1, aiOrigin_END = 2 };
-    class IOSystem;
-    class IOStream
-    {
-        FILE* f;
-    public:
-        IOStream(FILE* file) : f(file) {}
-        ~IOStream() { fclose(f); f = 0; }
-
-        size_t Read(void* b, size_t sz, size_t n) { return fread(b, sz, n, f); }
-        size_t Write(const void* b, size_t sz, size_t n) { return fwrite(b, sz, n, f); }
-        int    Seek(size_t off, aiOrigin orig) { return fseek(f, off, int(orig)); }
-        size_t Tell() const { return ftell(f); }
-
-        size_t FileSize() {
-            long p = Tell(), len = (Seek(0, aiOrigin_END), Tell());
-            return size_t((Seek(p, aiOrigin_SET), len));
-        }
-    };
-#endif
+    using glTFCommon::shared_ptr;
+    using glTFCommon::IOSystem;
+    using glTFCommon::IOStream;
 
 
     using rapidjson::Value;
     using rapidjson::Value;
     using rapidjson::Document;
     using rapidjson::Document;
@@ -138,35 +113,9 @@ namespace glTF2
     struct Texture;
     struct Texture;
     struct Skin;
     struct Skin;
 
 
-    // Vec/matrix types, as raw float arrays
-    typedef float (vec3)[3];
-    typedef float (vec4)[4];
-    typedef float (mat4)[16];
-
-    namespace Util
-    {
-        void EncodeBase64(const uint8_t* in, size_t inLength, std::string& out);
-
-        size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out);
-
-        inline size_t DecodeBase64(const char* in, uint8_t*& out)
-        {
-            return DecodeBase64(in, strlen(in), out);
-        }
-
-        struct DataURI
-        {
-            const char* mediaType;
-            const char* charset;
-            bool base64;
-            const char* data;
-            size_t dataLength;
-        };
-
-        //! Check if a uri is a data URI
-        inline bool ParseDataURI(const char* uri, size_t uriLen, DataURI& out);
-    }
-
+    using glTFCommon::vec3;
+    using glTFCommon::vec4;
+    using glTFCommon::mat4;
 
 
     //! Magic number for GLB files
     //! Magic number for GLB files
 	#define AI_GLB_MAGIC_NUMBER "glTF"
 	#define AI_GLB_MAGIC_NUMBER "glTF"
@@ -552,7 +501,7 @@ namespace glTF2
 		/// but in real life you'll get:
 		/// but in real life you'll get:
 		/// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4}
 		/// "accessor_0" : { byteOffset: 0, byteLength: 4}, "accessor_1" : { byteOffset: 2, byteLength: 4}
 		/// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded.
 		/// Yes, accessor of next mesh has offset and length which mean: current mesh data is decoded, all other data is encoded.
-		/// And when before you start to read data of current mesh (with encoded data ofcourse) you must decode region of "bufferView", after read finished
+		/// And when before you start to read data of current mesh (with encoded data of course) you must decode region of "bufferView", after read finished
 		/// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data.
 		/// delete encoding mark. And after that you can repeat process: decode data of mesh, read, delete decoded data.
 		///
 		///
 		/// Remark. Encoding all data at once is good in world with computers which do not has RAM limitation. So, you must use step by step encoding in
 		/// Remark. Encoding all data at once is good in world with computers which do not has RAM limitation. So, you must use step by step encoding in

+ 9 - 194
code/glTF2/glTF2Asset.inl

@@ -282,9 +282,7 @@ Ref<T> LazyDict<T>::Retrieve(unsigned int i)
 template<class T>
 template<class T>
 Ref<T> LazyDict<T>::Get(unsigned int i)
 Ref<T> LazyDict<T>::Get(unsigned int i)
 {
 {
-
     return Ref<T>(mObjs, i);
     return Ref<T>(mObjs, i);
-
 }
 }
 
 
 template<class T>
 template<class T>
@@ -361,11 +359,11 @@ inline void Buffer::Read(Value& obj, Asset& r)
 
 
     const char* uri = it->GetString();
     const char* uri = it->GetString();
 
 
-    Util::DataURI dataURI;
+    glTFCommon::Util::DataURI dataURI;
     if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
     if (ParseDataURI(uri, it->GetStringLength(), dataURI)) {
         if (dataURI.base64) {
         if (dataURI.base64) {
             uint8_t* data = 0;
             uint8_t* data = 0;
-            this->byteLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, data);
+            this->byteLength = glTFCommon::Util::DecodeBase64(dataURI.data, dataURI.dataLength, data);
             this->mData.reset(data, std::default_delete<uint8_t[]>());
             this->mData.reset(data, std::default_delete<uint8_t[]>());
 
 
             if (statedLength > 0 && this->byteLength != statedLength) {
             if (statedLength > 0 && this->byteLength != statedLength) {
@@ -717,12 +715,12 @@ inline void Image::Read(Value& obj, Asset& r)
         if (Value* uri = FindString(obj, "uri")) {
         if (Value* uri = FindString(obj, "uri")) {
             const char* uristr = uri->GetString();
             const char* uristr = uri->GetString();
 
 
-            Util::DataURI dataURI;
+            glTFCommon::Util::DataURI dataURI;
             if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) {
             if (ParseDataURI(uristr, uri->GetStringLength(), dataURI)) {
                 mimeType = dataURI.mediaType;
                 mimeType = dataURI.mediaType;
                 if (dataURI.base64) {
                 if (dataURI.base64) {
                     uint8_t *ptr = nullptr;
                     uint8_t *ptr = nullptr;
-                    mDataLength = Util::DecodeBase64(dataURI.data, dataURI.dataLength, ptr);
+                    mDataLength = glTFCommon::Util::DecodeBase64(dataURI.data, dataURI.dataLength, ptr);
                     mData.reset(ptr);
                     mData.reset(ptr);
                 }
                 }
             }
             }
@@ -1100,8 +1098,11 @@ inline void Light::Read(Value& obj, Asset& /*r*/)
     }
     }
 }
 }
 
 
-inline void Node::Read(Value& obj, Asset& r)
-{
+inline 
+void Node::Read(Value& obj, Asset& r) {
+    if (name.empty()) {
+        name = id;
+    }
 
 
     if (Value* children = FindArray(obj, "children")) {
     if (Value* children = FindArray(obj, "children")) {
         this->children.reserve(children->Size());
         this->children.reserve(children->Size());
@@ -1515,190 +1516,4 @@ inline std::string Asset::FindUniqueID(const std::string& str, const char* suffi
     return id;
     return id;
 }
 }
 
 
-namespace Util {
-
-    inline
-    bool ParseDataURI(const char* const_uri, size_t uriLen, DataURI& out) {
-        if ( NULL == const_uri ) {
-            return false;
-        }
-
-        if (const_uri[0] != 0x10) { // we already parsed this uri?
-            if (strncmp(const_uri, "data:", 5) != 0) // not a data uri?
-                return false;
-        }
-
-        // set defaults
-        out.mediaType = "text/plain";
-        out.charset = "US-ASCII";
-        out.base64 = false;
-
-        char* uri = const_cast<char*>(const_uri);
-        if (uri[0] != 0x10) {
-            uri[0] = 0x10;
-            uri[1] = uri[2] = uri[3] = uri[4] = 0;
-
-            size_t i = 5, j;
-            if (uri[i] != ';' && uri[i] != ',') { // has media type?
-                uri[1] = char(i);
-                for (; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
-                    // nothing to do!
-                }
-            }
-            while (uri[i] == ';' && i < uriLen) {
-                uri[i++] = '\0';
-                for (j = i; uri[i] != ';' && uri[i] != ',' && i < uriLen; ++i) {
-                    // nothing to do!
-                }
-
-                if ( strncmp( uri + j, "charset=", 8 ) == 0 ) {
-                    uri[2] = char(j + 8);
-                } else if ( strncmp( uri + j, "base64", 6 ) == 0 ) {
-                    uri[3] = char(j);
-                }
-            }
-            if (i < uriLen) {
-                uri[i++] = '\0';
-                uri[4] = char(i);
-            } else {
-                uri[1] = uri[2] = uri[3] = 0;
-                uri[4] = 5;
-            }
-        }
-
-        if ( uri[ 1 ] != 0 ) {
-            out.mediaType = uri + uri[ 1 ];
-        }
-        if ( uri[ 2 ] != 0 ) {
-            out.charset = uri + uri[ 2 ];
-        }
-        if ( uri[ 3 ] != 0 ) {
-            out.base64 = true;
-        }
-        out.data = uri + uri[4];
-        out.dataLength = (uri + uriLen) - out.data;
-
-        return true;
-    }
-
-    template<bool B>
-    struct DATA
-    {
-        static const uint8_t tableDecodeBase64[128];
-    };
-
-    template<bool B>
-    const uint8_t DATA<B>::tableDecodeBase64[128] = {
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0,
-         0,  0,  0,  0,  0,  0,  0,  0,  0,  0,  0, 62,  0,  0,  0, 63,
-        52, 53, 54, 55, 56, 57, 58, 59, 60, 61,  0,  0,  0, 64,  0,  0,
-         0,  0,  1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12, 13, 14,
-        15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,  0,  0,  0,  0,  0,
-         0, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
-        41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,  0,  0,  0,  0,  0
-    };
-
-    inline char EncodeCharBase64(uint8_t b)
-    {
-        return "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="[size_t(b)];
-    }
-
-    inline uint8_t DecodeCharBase64(char c)
-    {
-        return DATA<true>::tableDecodeBase64[size_t(c)]; // TODO faster with lookup table or ifs?
-        /*if (c >= 'A' && c <= 'Z') return c - 'A';
-        if (c >= 'a' && c <= 'z') return c - 'a' + 26;
-        if (c >= '0' && c <= '9') return c - '0' + 52;
-        if (c == '+') return 62;
-        if (c == '/') return 63;
-        return 64; // '-' */
-    }
-
-    inline size_t DecodeBase64(const char* in, size_t inLength, uint8_t*& out)
-    {
-        ai_assert(inLength % 4 == 0);
-
-        if (inLength < 4) {
-            out = 0;
-            return 0;
-        }
-
-        int nEquals = int(in[inLength - 1] == '=') +
-                      int(in[inLength - 2] == '=');
-
-        size_t outLength = (inLength * 3) / 4 - nEquals;
-        out = new uint8_t[outLength];
-        memset(out, 0, outLength);
-
-        size_t i, j = 0;
-
-        for (i = 0; i + 4 < inLength; i += 4) {
-            uint8_t b0 = DecodeCharBase64(in[i]);
-            uint8_t b1 = DecodeCharBase64(in[i + 1]);
-            uint8_t b2 = DecodeCharBase64(in[i + 2]);
-            uint8_t b3 = DecodeCharBase64(in[i + 3]);
-
-            out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
-            out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
-            out[j++] = (uint8_t)((b2 << 6) | b3);
-        }
-
-        {
-            uint8_t b0 = DecodeCharBase64(in[i]);
-            uint8_t b1 = DecodeCharBase64(in[i + 1]);
-            uint8_t b2 = DecodeCharBase64(in[i + 2]);
-            uint8_t b3 = DecodeCharBase64(in[i + 3]);
-
-            out[j++] = (uint8_t)((b0 << 2) | (b1 >> 4));
-            if (b2 < 64) out[j++] = (uint8_t)((b1 << 4) | (b2 >> 2));
-            if (b3 < 64) out[j++] = (uint8_t)((b2 << 6) | b3);
-        }
-
-        return outLength;
-    }
-
-
-
-    inline void EncodeBase64(
-        const uint8_t* in, size_t inLength,
-        std::string& out)
-    {
-        size_t outLength = ((inLength + 2) / 3) * 4;
-
-        size_t j = out.size();
-        out.resize(j + outLength);
-
-        for (size_t i = 0; i <  inLength; i += 3) {
-            uint8_t b = (in[i] & 0xFC) >> 2;
-            out[j++] = EncodeCharBase64(b);
-
-            b = (in[i] & 0x03) << 4;
-            if (i + 1 < inLength) {
-                b |= (in[i + 1] & 0xF0) >> 4;
-                out[j++] = EncodeCharBase64(b);
-
-                b = (in[i + 1] & 0x0F) << 2;
-                if (i + 2 < inLength) {
-                    b |= (in[i + 2] & 0xC0) >> 6;
-                    out[j++] = EncodeCharBase64(b);
-
-                    b = in[i + 2] & 0x3F;
-                    out[j++] = EncodeCharBase64(b);
-                }
-                else {
-                    out[j++] = EncodeCharBase64(b);
-                    out[j++] = '=';
-                }
-            }
-            else {
-                out[j++] = EncodeCharBase64(b);
-                out[j++] = '=';
-                out[j++] = '=';
-            }
-        }
-    }
-
-}
-
 } // ns glTF
 } // ns glTF

+ 1 - 1
code/glTF2/glTF2AssetWriter.inl

@@ -218,7 +218,7 @@ namespace glTF2 {
             if (img.HasData()) {
             if (img.HasData()) {
                 uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
                 uri = "data:" + (img.mimeType.empty() ? "application/octet-stream" : img.mimeType);
                 uri += ";base64,";
                 uri += ";base64,";
-                Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
+                glTFCommon::Util::EncodeBase64(img.GetData(), img.GetDataLength(), uri);
             }
             }
             else {
             else {
                 uri = img.uri;
                 uri = img.uri;

+ 125 - 20
code/glTF2/glTF2Importer.cpp

@@ -64,6 +64,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 using namespace Assimp;
 using namespace Assimp;
 using namespace glTF2;
 using namespace glTF2;
+using namespace glTFCommon;
 
 
 namespace {
 namespace {
     // generate bi-tangents from normals and tangents according to spec
     // generate bi-tangents from normals and tangents according to spec
@@ -140,22 +141,23 @@ static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode)
     }
     }
 }
 }
 
 
-static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
+/*static void CopyValue(const glTF2::vec3& v, aiColor3D& out)
 {
 {
     out.r = v[0]; out.g = v[1]; out.b = v[2];
     out.r = v[0]; out.g = v[1]; out.b = v[2];
 }
 }
 
 
+
 static void CopyValue(const glTF2::vec4& v, aiColor4D& out)
 static void CopyValue(const glTF2::vec4& v, aiColor4D& out)
 {
 {
     out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3];
     out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = v[3];
-}
+}*/
 
 
 /*static void CopyValue(const glTF2::vec4& v, aiColor3D& out)
 /*static void CopyValue(const glTF2::vec4& v, aiColor3D& out)
 {
 {
     out.r = v[0]; out.g = v[1]; out.b = v[2];
     out.r = v[0]; out.g = v[1]; out.b = v[2];
 }*/
 }*/
 
 
-static void CopyValue(const glTF2::vec3& v, aiColor4D& out)
+/*static void CopyValue(const glTF2::vec3& v, aiColor4D& out)
 {
 {
     out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0;
     out.r = v[0]; out.g = v[1]; out.b = v[2]; out.a = 1.0;
 }
 }
@@ -168,15 +170,15 @@ static void CopyValue(const glTF2::vec3& v, aiVector3D& out)
 static void CopyValue(const glTF2::vec4& v, aiQuaternion& out)
 static void CopyValue(const glTF2::vec4& v, aiQuaternion& out)
 {
 {
     out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3];
     out.x = v[0]; out.y = v[1]; out.z = v[2]; out.w = v[3];
-}
+}*/
 
 
-static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o)
+/*static void CopyValue(const glTF2::mat4& v, aiMatrix4x4& o)
 {
 {
     o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3];
     o.a1 = v[ 0]; o.b1 = v[ 1]; o.c1 = v[ 2]; o.d1 = v[ 3];
     o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7];
     o.a2 = v[ 4]; o.b2 = v[ 5]; o.c2 = v[ 6]; o.d2 = v[ 7];
     o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11];
     o.a3 = v[ 8]; o.b3 = v[ 9]; o.c3 = v[10]; o.d3 = v[11];
     o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
     o.a4 = v[12]; o.b4 = v[13]; o.c4 = v[14]; o.d4 = v[15];
-}
+}*/
 
 
 inline void SetMaterialColorProperty(Asset& /*r*/, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
 inline void SetMaterialColorProperty(Asset& /*r*/, vec4& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
 {
 {
@@ -188,7 +190,7 @@ inline void SetMaterialColorProperty(Asset& /*r*/, vec4& prop, aiMaterial* mat,
 inline void SetMaterialColorProperty(Asset& /*r*/, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
 inline void SetMaterialColorProperty(Asset& /*r*/, vec3& prop, aiMaterial* mat, const char* pKey, unsigned int type, unsigned int idx)
 {
 {
     aiColor4D col;
     aiColor4D col;
-    CopyValue(prop, col);
+    glTFCommon::CopyValue(prop, col);
     mat->AddProperty(&col, 1, pKey, type, idx);
     mat->AddProperty(&col, 1, pKey, type, idx);
 }
 }
 
 
@@ -383,7 +385,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
             aim->mName = mesh.name.empty() ? mesh.id : mesh.name;
             aim->mName = mesh.name.empty() ? mesh.id : mesh.name;
 
 
             if (mesh.primitives.size() > 1) {
             if (mesh.primitives.size() > 1) {
-                size_t& len = aim->mName.length;
+                ai_uint32& len = aim->mName.length;
                 aim->mName.data[len] = '-';
                 aim->mName.data[len] = '-';
                 len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
                 len += 1 + ASSIMP_itoa10(aim->mName.data + len + 1, unsigned(MAXLEN - len - 1), p);
             }
             }
@@ -442,7 +444,6 @@ void glTF2Importer::ImportMeshes(glTF2::Asset& r)
                         "\" does not match the vertex count");
                         "\" does not match the vertex count");
                     continue;
                     continue;
                 }
                 }
-                aim->mColors[c] = new aiColor4D[attr.color[c]->count];
                 attr.color[c]->ExtractData(aim->mColors[c]);
                 attr.color[c]->ExtractData(aim->mColors[c]);
             }
             }
             for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
             for (size_t tc = 0; tc < attr.texcoord.size() && tc < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++tc) {
@@ -700,12 +701,17 @@ void glTF2Importer::ImportCameras(glTF2::Asset& r)
         if (cam.type == Camera::Perspective) {
         if (cam.type == Camera::Perspective) {
 
 
             aicam->mAspect        = cam.cameraProperties.perspective.aspectRatio;
             aicam->mAspect        = cam.cameraProperties.perspective.aspectRatio;
-            aicam->mHorizontalFOV = cam.cameraProperties.perspective.yfov * aicam->mAspect;
+            aicam->mHorizontalFOV = cam.cameraProperties.perspective.yfov * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect);
             aicam->mClipPlaneFar  = cam.cameraProperties.perspective.zfar;
             aicam->mClipPlaneFar  = cam.cameraProperties.perspective.zfar;
             aicam->mClipPlaneNear = cam.cameraProperties.perspective.znear;
             aicam->mClipPlaneNear = cam.cameraProperties.perspective.znear;
-        }
-        else {
-            // assimp does not support orthographic cameras
+        } else {
+            aicam->mClipPlaneFar = cam.cameraProperties.ortographic.zfar;
+            aicam->mClipPlaneNear = cam.cameraProperties.ortographic.znear;
+            aicam->mHorizontalFOV = 0.0;
+            aicam->mAspect = 1.0f;
+            if (0.f != cam.cameraProperties.ortographic.ymag ) {
+                aicam->mAspect = cam.cameraProperties.ortographic.xmag / cam.cameraProperties.ortographic.ymag;
+            }
         }
         }
     }
     }
 }
 }
@@ -901,6 +907,9 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>&
                 std::vector<std::vector<aiVertexWeight>> weighting(mesh->mNumBones);
                 std::vector<std::vector<aiVertexWeight>> weighting(mesh->mNumBones);
                 BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting);
                 BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting);
 
 
+                mat4* pbindMatrices = nullptr;
+                node.skin->inverseBindMatrices->ExtractData(pbindMatrices);
+
                 for (uint32_t i = 0; i < mesh->mNumBones; ++i) {
                 for (uint32_t i = 0; i < mesh->mNumBones; ++i) {
                     aiBone* bone = new aiBone();
                     aiBone* bone = new aiBone();
 
 
@@ -916,6 +925,8 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>&
                     }
                     }
                     GetNodeTransform(bone->mOffsetMatrix, *joint);
                     GetNodeTransform(bone->mOffsetMatrix, *joint);
 
 
+                    CopyValue(pbindMatrices[i], bone->mOffsetMatrix);
+
                     std::vector<aiVertexWeight>& weights = weighting[i];
                     std::vector<aiVertexWeight>& weights = weighting[i];
 
 
                     bone->mNumWeights = static_cast<uint32_t>(weights.size());
                     bone->mNumWeights = static_cast<uint32_t>(weights.size());
@@ -931,6 +942,10 @@ aiNode* ImportNode(aiScene* pScene, glTF2::Asset& r, std::vector<unsigned int>&
                     }
                     }
                     mesh->mBones[i] = bone;
                     mesh->mBones[i] = bone;
                 }
                 }
+
+                if (pbindMatrices) {
+                    delete[] pbindMatrices;
+                }
             }
             }
         }
         }
 
 
@@ -987,11 +1002,18 @@ void glTF2Importer::ImportNodes(glTF2::Asset& r)
 }
 }
 
 
 struct AnimationSamplers {
 struct AnimationSamplers {
-    AnimationSamplers() : translation(nullptr), rotation(nullptr), scale(nullptr) {}
+    AnimationSamplers()
+    : translation(nullptr)
+    , rotation(nullptr)
+    , scale(nullptr)
+    , weight(nullptr) {
+        // empty
+    }
 
 
     Animation::Sampler* translation;
     Animation::Sampler* translation;
     Animation::Sampler* rotation;
     Animation::Sampler* rotation;
     Animation::Sampler* scale;
     Animation::Sampler* scale;
+    Animation::Sampler* weight;
 };
 };
 
 
 aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers)
 aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers)
@@ -1016,7 +1038,7 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl
         delete[] values;
         delete[] values;
     } else if (node.translation.isPresent) {
     } else if (node.translation.isPresent) {
         anim->mNumPositionKeys = 1;
         anim->mNumPositionKeys = 1;
-        anim->mPositionKeys = new aiVectorKey();
+        anim->mPositionKeys = new aiVectorKey[anim->mNumPositionKeys];
         anim->mPositionKeys->mTime = 0.f;
         anim->mPositionKeys->mTime = 0.f;
         anim->mPositionKeys->mValue.x = node.translation.value[0];
         anim->mPositionKeys->mValue.x = node.translation.value[0];
         anim->mPositionKeys->mValue.y = node.translation.value[1];
         anim->mPositionKeys->mValue.y = node.translation.value[1];
@@ -1041,7 +1063,7 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl
         delete[] values;
         delete[] values;
     } else if (node.rotation.isPresent) {
     } else if (node.rotation.isPresent) {
         anim->mNumRotationKeys = 1;
         anim->mNumRotationKeys = 1;
-        anim->mRotationKeys = new aiQuatKey();
+        anim->mRotationKeys = new aiQuatKey[anim->mNumRotationKeys];
         anim->mRotationKeys->mTime = 0.f;
         anim->mRotationKeys->mTime = 0.f;
         anim->mRotationKeys->mValue.x = node.rotation.value[0];
         anim->mRotationKeys->mValue.x = node.rotation.value[0];
         anim->mRotationKeys->mValue.y = node.rotation.value[1];
         anim->mRotationKeys->mValue.y = node.rotation.value[1];
@@ -1064,7 +1086,7 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl
         delete[] values;
         delete[] values;
     } else if (node.scale.isPresent) {
     } else if (node.scale.isPresent) {
         anim->mNumScalingKeys = 1;
         anim->mNumScalingKeys = 1;
-        anim->mScalingKeys = new aiVectorKey();
+        anim->mScalingKeys = new aiVectorKey[anim->mNumScalingKeys];
         anim->mScalingKeys->mTime = 0.f;
         anim->mScalingKeys->mTime = 0.f;
         anim->mScalingKeys->mValue.x = node.scale.value[0];
         anim->mScalingKeys->mValue.x = node.scale.value[0];
         anim->mScalingKeys->mValue.y = node.scale.value[1];
         anim->mScalingKeys->mValue.y = node.scale.value[1];
@@ -1074,6 +1096,43 @@ aiNodeAnim* CreateNodeAnim(glTF2::Asset& r, Node& node, AnimationSamplers& sampl
     return anim;
     return anim;
 }
 }
 
 
+aiMeshMorphAnim* CreateMeshMorphAnim(glTF2::Asset& r, Node& node, AnimationSamplers& samplers)
+{
+    aiMeshMorphAnim* anim = new aiMeshMorphAnim();
+    anim->mName = GetNodeName(node);
+
+    static const float kMillisecondsFromSeconds = 1000.f;
+
+    if (nullptr != samplers.weight) {
+        float* times = nullptr;
+        samplers.weight->input->ExtractData(times);
+        float* values = nullptr;
+        samplers.weight->output->ExtractData(values);
+        anim->mNumKeys = static_cast<uint32_t>(samplers.weight->input->count);
+
+        const unsigned int numMorphs = samplers.weight->output->count / anim->mNumKeys;
+
+        anim->mKeys = new aiMeshMorphKey[anim->mNumKeys];
+        unsigned int k = 0u;
+        for (unsigned int i = 0u; i < anim->mNumKeys; ++i) {
+            anim->mKeys[i].mTime = times[i] * kMillisecondsFromSeconds;
+            anim->mKeys[i].mNumValuesAndWeights = numMorphs;
+            anim->mKeys[i].mValues = new unsigned int[numMorphs];
+            anim->mKeys[i].mWeights = new double[numMorphs];
+
+            for (unsigned int j = 0u; j < numMorphs; ++j, ++k) {
+                anim->mKeys[i].mValues[j] = j;
+                anim->mKeys[i].mWeights[j] = ( 0.f > values[k] ) ? 0.f : values[k];
+            }
+        }
+
+        delete[] times;
+        delete[] values;
+    }
+
+    return anim;
+}
+
 std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation& anim)
 std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation& anim)
 {
 {
     std::unordered_map<unsigned int, AnimationSamplers> samplers;
     std::unordered_map<unsigned int, AnimationSamplers> samplers;
@@ -1092,6 +1151,8 @@ std::unordered_map<unsigned int, AnimationSamplers> GatherSamplers(Animation& an
             sampler.rotation = &anim.samplers[channel.sampler];
             sampler.rotation = &anim.samplers[channel.sampler];
         } else if (channel.target.path == AnimationPath_SCALE) {
         } else if (channel.target.path == AnimationPath_SCALE) {
             sampler.scale = &anim.samplers[channel.sampler];
             sampler.scale = &anim.samplers[channel.sampler];
+        } else if (channel.target.path == AnimationPath_WEIGHTS) {
+            sampler.weight = &anim.samplers[channel.sampler];
         }
         }
     }
     }
 
 
@@ -1118,18 +1179,45 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r)
 
 
         std::unordered_map<unsigned int, AnimationSamplers> samplers = GatherSamplers(anim);
         std::unordered_map<unsigned int, AnimationSamplers> samplers = GatherSamplers(anim);
 
 
-        ai_anim->mNumChannels = static_cast<uint32_t>(samplers.size());
+        uint32_t numChannels = 0u;
+        uint32_t numMorphMeshChannels = 0u;
+
+        for (auto& iter : samplers) {
+            if ((nullptr != iter.second.rotation) || (nullptr != iter.second.scale) || (nullptr != iter.second.translation)) {
+                ++numChannels;
+            }
+            if (nullptr != iter.second.weight) {
+                ++numMorphMeshChannels;
+            }
+        }
+
+        ai_anim->mNumChannels = numChannels;
         if (ai_anim->mNumChannels > 0) {
         if (ai_anim->mNumChannels > 0) {
             ai_anim->mChannels = new aiNodeAnim*[ai_anim->mNumChannels];
             ai_anim->mChannels = new aiNodeAnim*[ai_anim->mNumChannels];
             int j = 0;
             int j = 0;
             for (auto& iter : samplers) {
             for (auto& iter : samplers) {
-                ai_anim->mChannels[j] = CreateNodeAnim(r, r.nodes[iter.first], iter.second);
-                ++j;
+                if ((nullptr != iter.second.rotation) || (nullptr != iter.second.scale) || (nullptr != iter.second.translation)) {
+                    ai_anim->mChannels[j] = CreateNodeAnim(r, r.nodes[iter.first], iter.second);
+                    ++j;
+                }
+            }
+        }
+
+        ai_anim->mNumMorphMeshChannels = numMorphMeshChannels;
+        if (ai_anim->mNumMorphMeshChannels > 0) {
+            ai_anim->mMorphMeshChannels = new aiMeshMorphAnim*[ai_anim->mNumMorphMeshChannels];
+            int j = 0;
+            for (auto& iter : samplers) {
+                if (nullptr != iter.second.weight) {
+                  ai_anim->mMorphMeshChannels[j] = CreateMeshMorphAnim(r, r.nodes[iter.first], iter.second);
+                  ++j;
+                }
             }
             }
         }
         }
 
 
         // Use the latest keyframe for the duration of the animation
         // Use the latest keyframe for the duration of the animation
         double maxDuration = 0;
         double maxDuration = 0;
+        unsigned int maxNumberOfKeys = 0;
         for (unsigned int j = 0; j < ai_anim->mNumChannels; ++j) {
         for (unsigned int j = 0; j < ai_anim->mNumChannels; ++j) {
             auto chan = ai_anim->mChannels[j];
             auto chan = ai_anim->mChannels[j];
             if (chan->mNumPositionKeys) {
             if (chan->mNumPositionKeys) {
@@ -1137,21 +1225,38 @@ void glTF2Importer::ImportAnimations(glTF2::Asset& r)
                 if (lastPosKey.mTime > maxDuration) {
                 if (lastPosKey.mTime > maxDuration) {
                     maxDuration = lastPosKey.mTime;
                     maxDuration = lastPosKey.mTime;
                 }
                 }
+                maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumPositionKeys);
             }
             }
             if (chan->mNumRotationKeys) {
             if (chan->mNumRotationKeys) {
                 auto lastRotKey = chan->mRotationKeys[chan->mNumRotationKeys - 1];
                 auto lastRotKey = chan->mRotationKeys[chan->mNumRotationKeys - 1];
                 if (lastRotKey.mTime > maxDuration) {
                 if (lastRotKey.mTime > maxDuration) {
                     maxDuration = lastRotKey.mTime;
                     maxDuration = lastRotKey.mTime;
                 }
                 }
+                maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumRotationKeys);
             }
             }
             if (chan->mNumScalingKeys) {
             if (chan->mNumScalingKeys) {
                 auto lastScaleKey = chan->mScalingKeys[chan->mNumScalingKeys - 1];
                 auto lastScaleKey = chan->mScalingKeys[chan->mNumScalingKeys - 1];
                 if (lastScaleKey.mTime > maxDuration) {
                 if (lastScaleKey.mTime > maxDuration) {
                     maxDuration = lastScaleKey.mTime;
                     maxDuration = lastScaleKey.mTime;
                 }
                 }
+                maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumScalingKeys);
             }
             }
         }
         }
+
+        for (unsigned int j = 0; j < ai_anim->mNumMorphMeshChannels; ++j) {
+            const auto* const chan = ai_anim->mMorphMeshChannels[j];
+
+            if (0u != chan->mNumKeys) {
+                const auto& lastKey = chan->mKeys[chan->mNumKeys - 1u];
+                if (lastKey.mTime > maxDuration) {
+                    maxDuration = lastKey.mTime;
+                }
+                maxNumberOfKeys = std::max(maxNumberOfKeys, chan->mNumKeys);
+            }
+        }
+
         ai_anim->mDuration = maxDuration;
         ai_anim->mDuration = maxDuration;
+        ai_anim->mTicksPerSecond = 1000.0;
 
 
         mScene->mAnimations[i] = ai_anim;
         mScene->mAnimations[i] = ai_anim;
     }
     }

+ 4 - 4
contrib/gtest/test/gtest-param-test_test.cc

@@ -141,7 +141,7 @@ void VerifyGenerator(const ParamGenerator<T>& generator,
         << ", expected_values[i] is " << PrintValue(expected_values[i])
         << ", expected_values[i] is " << PrintValue(expected_values[i])
         << ", *it is " << PrintValue(*it)
         << ", *it is " << PrintValue(*it)
         << ", and 'it' is an iterator created with the copy constructor.\n";
         << ", and 'it' is an iterator created with the copy constructor.\n";
-    it++;
+    ++it;
   }
   }
   EXPECT_TRUE(it == generator.end())
   EXPECT_TRUE(it == generator.end())
         << "At the presumed end of sequence when accessing via an iterator "
         << "At the presumed end of sequence when accessing via an iterator "
@@ -161,7 +161,7 @@ void VerifyGenerator(const ParamGenerator<T>& generator,
         << ", expected_values[i] is " << PrintValue(expected_values[i])
         << ", expected_values[i] is " << PrintValue(expected_values[i])
         << ", *it is " << PrintValue(*it)
         << ", *it is " << PrintValue(*it)
         << ", and 'it' is an iterator created with the copy constructor.\n";
         << ", and 'it' is an iterator created with the copy constructor.\n";
-    it++;
+    ++it;
   }
   }
   EXPECT_TRUE(it == generator.end())
   EXPECT_TRUE(it == generator.end())
         << "At the presumed end of sequence when accessing via an iterator "
         << "At the presumed end of sequence when accessing via an iterator "
@@ -196,7 +196,7 @@ TEST(IteratorTest, ParamIteratorConformsToForwardIteratorConcept) {
                            << "element same as its source points to";
                            << "element same as its source points to";
 
 
   // Verifies that iterator assignment works as expected.
   // Verifies that iterator assignment works as expected.
-  it++;
+  ++it;
   EXPECT_FALSE(*it == *it2);
   EXPECT_FALSE(*it == *it2);
   it2 = it;
   it2 = it;
   EXPECT_TRUE(*it == *it2) << "Assigned iterators must point to the "
   EXPECT_TRUE(*it == *it2) << "Assigned iterators must point to the "
@@ -215,7 +215,7 @@ TEST(IteratorTest, ParamIteratorConformsToForwardIteratorConcept) {
   // Verifies that prefix and postfix operator++() advance an iterator
   // Verifies that prefix and postfix operator++() advance an iterator
   // all the same.
   // all the same.
   it2 = it;
   it2 = it;
-  it++;
+  ++it;
   ++it2;
   ++it2;
   EXPECT_TRUE(*it == *it2);
   EXPECT_TRUE(*it == *it2);
 }
 }

+ 1 - 1
contrib/irrXML/irrXML.h

@@ -215,7 +215,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 IFileReadCallBack
+	class IRRXML_API IFileReadCallBack
 	{
 	{
 	public:
 	public:
 
 

+ 11 - 9
include/assimp/BaseImporter.h

@@ -41,9 +41,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 /** @file Definition of the base class for all importer worker classes. */
 /** @file Definition of the base class for all importer worker classes. */
+#pragma once
 #ifndef INCLUDED_AI_BASEIMPORTER_H
 #ifndef INCLUDED_AI_BASEIMPORTER_H
 #define INCLUDED_AI_BASEIMPORTER_H
 #define INCLUDED_AI_BASEIMPORTER_H
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include "Exceptional.h"
 #include "Exceptional.h"
 
 
 #include <vector>
 #include <vector>
@@ -82,6 +87,10 @@ class IOStream;
 class ASSIMP_API BaseImporter {
 class ASSIMP_API BaseImporter {
     friend class Importer;
     friend class Importer;
 
 
+private:
+    /* Pushes state into importer for the importer scale */
+    virtual void UpdateImporterScale( Importer* pImp );
+
 public:
 public:
 
 
     /** Constructor to be privately used by #Importer */
     /** Constructor to be privately used by #Importer */
@@ -134,7 +143,7 @@ public:
      *  a suitable response to the caller.
      *  a suitable response to the caller.
      */
      */
     aiScene* ReadFile(
     aiScene* ReadFile(
-        const Importer* pImp,
+        Importer* pImp,
         const std::string& pFile,
         const std::string& pFile,
         IOSystem* pIOHandler
         IOSystem* pIOHandler
         );
         );
@@ -209,14 +218,6 @@ public:
         return applicationUnits;
         return applicationUnits;
     }
     }
 
 
-    /* Returns scale used by application called by ScaleProcess */
-    double GetImporterScale() const
-    {
-        ai_assert(importerScale != 0);
-        ai_assert(fileScale != 0);
-        return importerScale * fileScale;
-    }
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Called by #Importer::GetExtensionList for each loaded importer.
     /** Called by #Importer::GetExtensionList for each loaded importer.
      *  Take the extension list contained in the structure returned by
      *  Take the extension list contained in the structure returned by
@@ -230,6 +231,7 @@ protected:
     double fileScale = 1.0;
     double fileScale = 1.0;
 
 
 
 
+
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Imports the given file into the given scene structure. The
     /** Imports the given file into the given scene structure. The
      * function is expected to throw an ImportErrorException if there is
      * function is expected to throw an ImportErrorException if there is

+ 5 - 1
include/assimp/Bitmap.h

@@ -46,10 +46,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  *
  * Used for file formats which embed their textures into the model file.
  * Used for file formats which embed their textures into the model file.
  */
  */
-
+#pragma once
 #ifndef AI_BITMAP_H_INC
 #ifndef AI_BITMAP_H_INC
 #define AI_BITMAP_H_INC
 #define AI_BITMAP_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include "defs.h"
 #include "defs.h"
 #include <stdint.h>
 #include <stdint.h>
 #include <cstddef>
 #include <cstddef>

+ 5 - 0
include/assimp/ByteSwapper.h

@@ -42,9 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 /** @file Helper class tp perform various byte oder swappings
 /** @file Helper class tp perform various byte oder swappings
    (e.g. little to big endian) */
    (e.g. little to big endian) */
+#pragma once
 #ifndef AI_BYTESWAPPER_H_INC
 #ifndef AI_BYTESWAPPER_H_INC
 #define AI_BYTESWAPPER_H_INC
 #define AI_BYTESWAPPER_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/ai_assert.h>
 #include <assimp/ai_assert.h>
 #include <assimp/types.h>
 #include <assimp/types.h>
 #include <stdint.h>
 #include <stdint.h>

+ 12 - 2
include/assimp/CreateAnimMesh.h

@@ -43,16 +43,26 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file CreateAnimMesh.h
 /** @file CreateAnimMesh.h
  *  Create AnimMesh from Mesh
  *  Create AnimMesh from Mesh
  */
  */
+#pragma once
 #ifndef INCLUDED_AI_CREATE_ANIM_MESH_H
 #ifndef INCLUDED_AI_CREATE_ANIM_MESH_H
 #define INCLUDED_AI_CREATE_ANIM_MESH_H
 #define INCLUDED_AI_CREATE_ANIM_MESH_H
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/mesh.h>
 #include <assimp/mesh.h>
 
 
-namespace Assimp    {
+namespace Assimp {
 
 
-/** Create aiAnimMesh from aiMesh. */
+/**
+ *  Create aiAnimMesh from aiMesh.
+ *  @param  mesh    The input mesh to create an animated mesh from.
+ *  @return The new created animated mesh.
+ */
 ASSIMP_API aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh);
 ASSIMP_API aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh);
 
 
 } // end of namespace Assimp
 } // end of namespace Assimp
+
 #endif // INCLUDED_AI_CREATE_ANIM_MESH_H
 #endif // INCLUDED_AI_CREATE_ANIM_MESH_H
 
 

+ 9 - 10
include/assimp/DefaultIOStream.h

@@ -41,15 +41,20 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 /** @file Default file I/O using fXXX()-family of functions */
 /** @file Default file I/O using fXXX()-family of functions */
+#pragma once
 #ifndef AI_DEFAULTIOSTREAM_H_INC
 #ifndef AI_DEFAULTIOSTREAM_H_INC
 #define AI_DEFAULTIOSTREAM_H_INC
 #define AI_DEFAULTIOSTREAM_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <stdio.h>
 #include <stdio.h>
 #include <assimp/IOStream.hpp>
 #include <assimp/IOStream.hpp>
 #include <assimp/importerdesc.h>
 #include <assimp/importerdesc.h>
 #include <assimp/Defines.h>
 #include <assimp/Defines.h>
 
 
-namespace Assimp    {
+namespace Assimp {
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 //! @class  DefaultIOStream
 //! @class  DefaultIOStream
@@ -57,8 +62,7 @@ namespace Assimp    {
 //! @note   An instance of this class can exist without a valid file handle
 //! @note   An instance of this class can exist without a valid file handle
 //!         attached to it. All calls fail, but the instance can nevertheless be
 //!         attached to it. All calls fail, but the instance can nevertheless be
 //!         used with no restrictions.
 //!         used with no restrictions.
-class ASSIMP_API DefaultIOStream : public IOStream
-{
+class ASSIMP_API DefaultIOStream : public IOStream {
     friend class DefaultIOSystem;
     friend class DefaultIOSystem;
 #if __ANDROID__
 #if __ANDROID__
 # if __ANDROID_API__ > 9
 # if __ANDROID_API__ > 9
@@ -82,7 +86,6 @@ public:
         size_t pSize,
         size_t pSize,
         size_t pCount);
         size_t pCount);
 
 
-
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /// Write to stream
     /// Write to stream
     size_t Write(const void* pvBuffer,
     size_t Write(const void* pvBuffer,
@@ -107,16 +110,13 @@ public:
     void Flush();
     void Flush();
 
 
 private:
 private:
-    //  File data-structure, using clib
     FILE* mFile;
     FILE* mFile;
-    //  Filename
     std::string mFilename;
     std::string mFilename;
-    // Cached file size
     mutable size_t mCachedSize;
     mutable size_t mCachedSize;
 };
 };
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
-inline
+AI_FORCE_INLINE
 DefaultIOStream::DefaultIOStream() AI_NO_EXCEPT
 DefaultIOStream::DefaultIOStream() AI_NO_EXCEPT
 : mFile(nullptr)
 : mFile(nullptr)
 , mFilename("")
 , mFilename("")
@@ -125,7 +125,7 @@ DefaultIOStream::DefaultIOStream() AI_NO_EXCEPT
 }
 }
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
-inline
+AI_FORCE_INLINE
 DefaultIOStream::DefaultIOStream (FILE* pFile, const std::string &strFilename)
 DefaultIOStream::DefaultIOStream (FILE* pFile, const std::string &strFilename)
 : mFile(pFile)
 : mFile(pFile)
 , mFilename(strFilename)
 , mFilename(strFilename)
@@ -137,4 +137,3 @@ DefaultIOStream::DefaultIOStream (FILE* pFile, const std::string &strFilename)
 } // ns assimp
 } // ns assimp
 
 
 #endif //!!AI_DEFAULTIOSTREAM_H_INC
 #endif //!!AI_DEFAULTIOSTREAM_H_INC
-

+ 5 - 0
include/assimp/DefaultIOSystem.h

@@ -41,9 +41,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 /** @file Default implementation of IOSystem using the standard C file functions */
 /** @file Default implementation of IOSystem using the standard C file functions */
+#pragma once
 #ifndef AI_DEFAULTIOSYSTEM_H_INC
 #ifndef AI_DEFAULTIOSYSTEM_H_INC
 #define AI_DEFAULTIOSYSTEM_H_INC
 #define AI_DEFAULTIOSYSTEM_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
 
 
 namespace Assimp    {
 namespace Assimp    {

+ 9 - 0
include/assimp/Defines.h

@@ -38,6 +38,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 */
 */
 
 
+#pragma once
+#ifndef AI_DEFINES_H_INC
+#define AI_DEFINES_H_INC
+
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 // We need those constants, workaround for any platforms where nobody defined them yet
 // We need those constants, workaround for any platforms where nobody defined them yet
 #if (!defined SIZE_MAX)
 #if (!defined SIZE_MAX)
 #   define SIZE_MAX (~((size_t)0))
 #   define SIZE_MAX (~((size_t)0))
@@ -47,3 +55,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #   define UINT_MAX (~((unsigned int)0))
 #   define UINT_MAX (~((unsigned int)0))
 #endif
 #endif
 
 
+#endif // AI_DEINES_H_INC

+ 13 - 10
include/assimp/Exceptional.h

@@ -38,11 +38,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 */
 */
 
 
-#ifndef INCLUDED_EXCEPTIONAL_H
-#define INCLUDED_EXCEPTIONAL_H
+#pragma once
+#ifndef AI_INCLUDED_EXCEPTIONAL_H
+#define AI_INCLUDED_EXCEPTIONAL_H
+
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
 
 
 #include <stdexcept>
 #include <stdexcept>
 #include <assimp/DefaultIOStream.h>
 #include <assimp/DefaultIOStream.h>
+
 using std::runtime_error;
 using std::runtime_error;
 
 
 #ifdef _MSC_VER
 #ifdef _MSC_VER
@@ -53,17 +59,14 @@ using std::runtime_error;
 /** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an
 /** FOR IMPORTER PLUGINS ONLY: Simple exception class to be thrown if an
  *  unrecoverable error occurs while importing. Loading APIs return
  *  unrecoverable error occurs while importing. Loading APIs return
  *  NULL instead of a valid aiScene then.  */
  *  NULL instead of a valid aiScene then.  */
-class DeadlyImportError
-    : public runtime_error
-{
+class DeadlyImportError : public runtime_error {
 public:
 public:
     /** Constructor with arguments */
     /** Constructor with arguments */
     explicit DeadlyImportError( const std::string& errorText)
     explicit DeadlyImportError( const std::string& errorText)
-        : runtime_error(errorText)
-    {
+    : runtime_error(errorText) {
+        // empty
     }
     }
 
 
-private:
 };
 };
 
 
 typedef DeadlyImportError DeadlyExportError;
 typedef DeadlyImportError DeadlyExportError;
@@ -84,7 +87,7 @@ struct ExceptionSwallower   {
 template <typename T>
 template <typename T>
 struct ExceptionSwallower<T*>   {
 struct ExceptionSwallower<T*>   {
     T* operator ()() const {
     T* operator ()() const {
-        return NULL;
+        return nullptr;
     }
     }
 };
 };
 
 
@@ -122,4 +125,4 @@ struct ExceptionSwallower<void> {
     }\
     }\
 }
 }
 
 
-#endif // INCLUDED_EXCEPTIONAL_H
+#endif // AI_INCLUDED_EXCEPTIONAL_H

+ 4 - 0
include/assimp/Exporter.hpp

@@ -48,6 +48,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_EXPORT_HPP_INC
 #ifndef AI_EXPORT_HPP_INC
 #define AI_EXPORT_HPP_INC
 #define AI_EXPORT_HPP_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_EXPORT
 
 
 #include "cexport.h"
 #include "cexport.h"

+ 6 - 1
include/assimp/GenericProperty.h

@@ -40,12 +40,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 */
 */
 
 
+#pragma once
 #ifndef AI_GENERIC_PROPERTY_H_INCLUDED
 #ifndef AI_GENERIC_PROPERTY_H_INCLUDED
 #define AI_GENERIC_PROPERTY_H_INCLUDED
 #define AI_GENERIC_PROPERTY_H_INCLUDED
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/Importer.hpp>
 #include <assimp/Importer.hpp>
 #include <assimp/ai_assert.h>
 #include <assimp/ai_assert.h>
-#include "Hash.h"
+#include <assimp/Hash.h>
 
 
 #include <map>
 #include <map>
 
 

+ 5 - 1
include/assimp/Hash.h

@@ -39,10 +39,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 */
 */
-
+#pragma once
 #ifndef AI_HASH_H_INCLUDED
 #ifndef AI_HASH_H_INCLUDED
 #define AI_HASH_H_INCLUDED
 #define AI_HASH_H_INCLUDED
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <stdint.h>
 #include <stdint.h>
 #include <string.h>
 #include <string.h>
 
 

+ 8 - 4
include/assimp/IOStream.hpp

@@ -48,14 +48,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_IOSTREAM_H_INC
 #ifndef AI_IOSTREAM_H_INC
 #define AI_IOSTREAM_H_INC
 #define AI_IOSTREAM_H_INC
 
 
-#include "types.h"
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
+#include <assimp/types.h>
 
 
 #ifndef __cplusplus
 #ifndef __cplusplus
 #   error This header requires C++ to be used. aiFileIO.h is the \
 #   error This header requires C++ to be used. aiFileIO.h is the \
     corresponding C interface.
     corresponding C interface.
 #endif
 #endif
 
 
-namespace Assimp    {
+namespace Assimp {
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 /** @brief CPP-API: Class to handle file I/O for C++
 /** @brief CPP-API: Class to handle file I/O for C++
@@ -125,13 +129,13 @@ public:
 }; //! class IOStream
 }; //! class IOStream
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
-inline
+AI_FORCE_INLINE
 IOStream::IOStream() AI_NO_EXCEPT {
 IOStream::IOStream() AI_NO_EXCEPT {
     // empty
     // empty
 }
 }
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
-inline
+AI_FORCE_INLINE
 IOStream::~IOStream() {
 IOStream::~IOStream() {
     // empty
     // empty
 }
 }

+ 25 - 18
include/assimp/IOStreamBuffer.h

@@ -1,5 +1,3 @@
-#pragma once
-
 /*
 /*
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
@@ -42,10 +40,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 */
 */
 
 
+#pragma once
+#ifndef AI_IOSTREAMBUFFER_H_INC
+#define AI_IOSTREAMBUFFER_H_INC
+
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/types.h>
 #include <assimp/types.h>
 #include <assimp/IOStream.hpp>
 #include <assimp/IOStream.hpp>
-
-#include "ParsingUtils.h"
+#include <assimp/ParsingUtils.h>
 
 
 #include <vector>
 #include <vector>
 
 
@@ -124,7 +129,7 @@ private:
 };
 };
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 IOStreamBuffer<T>::IOStreamBuffer( size_t cache )
 IOStreamBuffer<T>::IOStreamBuffer( size_t cache )
 : m_stream( nullptr )
 : m_stream( nullptr )
 , m_filesize( 0 )
 , m_filesize( 0 )
@@ -138,13 +143,13 @@ IOStreamBuffer<T>::IOStreamBuffer( size_t cache )
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 IOStreamBuffer<T>::~IOStreamBuffer() {
 IOStreamBuffer<T>::~IOStreamBuffer() {
     // empty
     // empty
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 bool IOStreamBuffer<T>::open( IOStream *stream ) {
 bool IOStreamBuffer<T>::open( IOStream *stream ) {
     //  file still opened!
     //  file still opened!
     if ( nullptr != m_stream ) {
     if ( nullptr != m_stream ) {
@@ -174,7 +179,7 @@ bool IOStreamBuffer<T>::open( IOStream *stream ) {
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 bool IOStreamBuffer<T>::close() {
 bool IOStreamBuffer<T>::close() {
     if ( nullptr == m_stream ) {
     if ( nullptr == m_stream ) {
         return false;
         return false;
@@ -192,19 +197,19 @@ bool IOStreamBuffer<T>::close() {
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 size_t IOStreamBuffer<T>::size() const {
 size_t IOStreamBuffer<T>::size() const {
     return m_filesize;
     return m_filesize;
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 size_t IOStreamBuffer<T>::cacheSize() const {
 size_t IOStreamBuffer<T>::cacheSize() const {
     return m_cacheSize;
     return m_cacheSize;
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 bool IOStreamBuffer<T>::readNextBlock() {
 bool IOStreamBuffer<T>::readNextBlock() {
     m_stream->Seek( m_filePos, aiOrigin_SET );
     m_stream->Seek( m_filePos, aiOrigin_SET );
     size_t readLen = m_stream->Read( &m_cache[ 0 ], sizeof( T ), m_cacheSize );
     size_t readLen = m_stream->Read( &m_cache[ 0 ], sizeof( T ), m_cacheSize );
@@ -222,25 +227,25 @@ bool IOStreamBuffer<T>::readNextBlock() {
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 size_t IOStreamBuffer<T>::getNumBlocks() const {
 size_t IOStreamBuffer<T>::getNumBlocks() const {
     return m_numBlocks;
     return m_numBlocks;
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 size_t IOStreamBuffer<T>::getCurrentBlockIndex() const {
 size_t IOStreamBuffer<T>::getCurrentBlockIndex() const {
     return m_blockIdx;
     return m_blockIdx;
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 size_t IOStreamBuffer<T>::getFilePos() const {
 size_t IOStreamBuffer<T>::getFilePos() const {
     return m_filePos;
     return m_filePos;
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
 bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationToken ) {
     buffer.resize( m_cacheSize );
     buffer.resize( m_cacheSize );
     if ( m_cachePos >= m_cacheSize || 0 == m_filePos ) {
     if ( m_cachePos >= m_cacheSize || 0 == m_filePos ) {
@@ -289,13 +294,13 @@ bool IOStreamBuffer<T>::getNextDataLine( std::vector<T> &buffer, T continuationT
     return true;
     return true;
 }
 }
 
 
-static inline
+static AI_FORCE_INLINE
 bool isEndOfCache( size_t pos, size_t cacheSize ) {
 bool isEndOfCache( size_t pos, size_t cacheSize ) {
     return ( pos == cacheSize );
     return ( pos == cacheSize );
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
 bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
     buffer.resize(m_cacheSize);
     buffer.resize(m_cacheSize);
     if ( isEndOfCache( m_cachePos, m_cacheSize ) || 0 == m_filePos) {
     if ( isEndOfCache( m_cachePos, m_cacheSize ) || 0 == m_filePos) {
@@ -335,7 +340,7 @@ bool IOStreamBuffer<T>::getNextLine(std::vector<T> &buffer) {
 }
 }
 
 
 template<class T>
 template<class T>
-inline
+AI_FORCE_INLINE
 bool IOStreamBuffer<T>::getNextBlock( std::vector<T> &buffer) {
 bool IOStreamBuffer<T>::getNextBlock( std::vector<T> &buffer) {
     // Return the last block-value if getNextLine was used before
     // Return the last block-value if getNextLine was used before
     if ( 0 != m_cachePos ) {      
     if ( 0 != m_cachePos ) {      
@@ -353,3 +358,5 @@ bool IOStreamBuffer<T>::getNextBlock( std::vector<T> &buffer) {
 }
 }
 
 
 } // !ns Assimp
 } // !ns Assimp
+
+#endif // AI_IOSTREAMBUFFER_H_INC

+ 4 - 0
include/assimp/IOSystem.hpp

@@ -50,6 +50,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_IOSYSTEM_H_INC
 #ifndef AI_IOSYSTEM_H_INC
 #define AI_IOSYSTEM_H_INC
 #define AI_IOSYSTEM_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #ifndef __cplusplus
 #ifndef __cplusplus
 #   error This header requires C++ to be used. aiFileIO.h is the \
 #   error This header requires C++ to be used. aiFileIO.h is the \
     corresponding C interface.
     corresponding C interface.

+ 4 - 0
include/assimp/Importer.hpp

@@ -48,6 +48,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_ASSIMP_HPP_INC
 #ifndef AI_ASSIMP_HPP_INC
 #define AI_ASSIMP_HPP_INC
 #define AI_ASSIMP_HPP_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #ifndef __cplusplus
 #ifndef __cplusplus
 #   error This header requires C++ to be used. Use assimp.h for plain C.
 #   error This header requires C++ to be used. Use assimp.h for plain C.
 #endif // __cplusplus
 #endif // __cplusplus

+ 20 - 16
include/assimp/LineSplitter.h

@@ -48,9 +48,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef INCLUDED_LINE_SPLITTER_H
 #ifndef INCLUDED_LINE_SPLITTER_H
 #define INCLUDED_LINE_SPLITTER_H
 #define INCLUDED_LINE_SPLITTER_H
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <stdexcept>
 #include <stdexcept>
-#include "StreamReader.h"
-#include "ParsingUtils.h"
+#include <assimp/StreamReader.h>
+#include <assimp/ParsingUtils.h>
 
 
 namespace Assimp {
 namespace Assimp {
 
 
@@ -140,7 +144,7 @@ private:
     bool mSwallow, mSkip_empty_lines, mTrim;
     bool mSwallow, mSkip_empty_lines, mTrim;
 };
 };
 
 
-inline
+AI_FORCE_INLINE
 LineSplitter::LineSplitter(StreamReaderLE& stream, bool skip_empty_lines, bool trim )
 LineSplitter::LineSplitter(StreamReaderLE& stream, bool skip_empty_lines, bool trim )
 : mIdx(0)
 : mIdx(0)
 , mCur()
 , mCur()
@@ -153,12 +157,12 @@ LineSplitter::LineSplitter(StreamReaderLE& stream, bool skip_empty_lines, bool t
     mIdx = 0;
     mIdx = 0;
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 LineSplitter::~LineSplitter() {
 LineSplitter::~LineSplitter() {
     // empty
     // empty
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 LineSplitter& LineSplitter::operator++() {
 LineSplitter& LineSplitter::operator++() {
     if (mSwallow) {
     if (mSwallow) {
         mSwallow = false;
         mSwallow = false;
@@ -199,12 +203,12 @@ LineSplitter& LineSplitter::operator++() {
     return *this;
     return *this;
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 LineSplitter &LineSplitter::operator++(int) {
 LineSplitter &LineSplitter::operator++(int) {
     return ++(*this);
     return ++(*this);
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 const char *LineSplitter::operator[] (size_t idx) const {
 const char *LineSplitter::operator[] (size_t idx) const {
     const char* s = operator->()->c_str();
     const char* s = operator->()->c_str();
 
 
@@ -222,7 +226,7 @@ const char *LineSplitter::operator[] (size_t idx) const {
 }
 }
 
 
 template <size_t N>
 template <size_t N>
-inline
+AI_FORCE_INLINE
 void LineSplitter::get_tokens(const char* (&tokens)[N]) const {
 void LineSplitter::get_tokens(const char* (&tokens)[N]) const {
     const char* s = operator->()->c_str();
     const char* s = operator->()->c_str();
 
 
@@ -238,44 +242,44 @@ void LineSplitter::get_tokens(const char* (&tokens)[N]) const {
     }
     }
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 const std::string* LineSplitter::operator -> () const {
 const std::string* LineSplitter::operator -> () const {
     return &mCur;
     return &mCur;
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 std::string LineSplitter::operator* () const {
 std::string LineSplitter::operator* () const {
     return mCur;
     return mCur;
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 LineSplitter::operator bool() const {
 LineSplitter::operator bool() const {
     return mStream.GetRemainingSize() > 0;
     return mStream.GetRemainingSize() > 0;
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 LineSplitter::operator line_idx() const {
 LineSplitter::operator line_idx() const {
     return mIdx;
     return mIdx;
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 LineSplitter::line_idx LineSplitter::get_index() const {
 LineSplitter::line_idx LineSplitter::get_index() const {
     return mIdx;
     return mIdx;
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 StreamReaderLE &LineSplitter::get_stream() {
 StreamReaderLE &LineSplitter::get_stream() {
     return mStream;
     return mStream;
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 bool LineSplitter::match_start(const char* check) {
 bool LineSplitter::match_start(const char* check) {
     const size_t len = ::strlen(check);
     const size_t len = ::strlen(check);
 
 
     return len <= mCur.length() && std::equal(check, check + len, mCur.begin());
     return len <= mCur.length() && std::equal(check, check + len, mCur.begin());
 }
 }
 
 
-inline
+AI_FORCE_INLINE
 void LineSplitter::swallow_next_increment() {
 void LineSplitter::swallow_next_increment() {
     mSwallow = true;
     mSwallow = true;
 }
 }

+ 5 - 0
include/assimp/LogAux.h

@@ -43,9 +43,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  LogAux.h
 /** @file  LogAux.h
  *  @brief Common logging usage patterns for importer implementations
  *  @brief Common logging usage patterns for importer implementations
  */
  */
+#pragma once
 #ifndef INCLUDED_AI_LOGAUX_H
 #ifndef INCLUDED_AI_LOGAUX_H
 #define INCLUDED_AI_LOGAUX_H
 #define INCLUDED_AI_LOGAUX_H
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/TinyFormatter.h>
 #include <assimp/TinyFormatter.h>
 #include <assimp/Exceptional.h>
 #include <assimp/Exceptional.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>

+ 0 - 49
include/assimp/Macros.h

@@ -1,49 +0,0 @@
-/*
----------------------------------------------------------------------------
-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.
----------------------------------------------------------------------------
-*/
-
-/* Helper macro to set a pointer to NULL in debug builds
- */
-#if (defined ASSIMP_BUILD_DEBUG)
-#   define AI_DEBUG_INVALIDATE_PTR(x) x = NULL;
-#else
-#   define AI_DEBUG_INVALIDATE_PTR(x)
-#endif
-

+ 23 - 10
include/assimp/MathFunctions.h

@@ -39,22 +39,28 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 */
 */
 
 
+#pragma once
+
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 /** @file  MathFunctions.h
 /** @file  MathFunctions.h
- *  @brief Implementation of the math functions (gcd and lcm)
+*  @brief Implementation of math utility functions.
  *
  *
- *  Copied from BoostWorkaround/math
- */
+*/
+
+#include <limits>
 
 
 namespace Assimp {
 namespace Assimp {
 namespace Math {
 namespace Math {
 
 
 // TODO: use binary GCD for unsigned integers ....
 // TODO: use binary GCD for unsigned integers ....
 template < typename IntegerType >
 template < typename IntegerType >
-IntegerType  gcd( IntegerType a, IntegerType b )
-{
+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;
@@ -66,12 +72,19 @@ IntegerType  gcd( IntegerType a, IntegerType b )
 }
 }
 
 
 template < typename IntegerType >
 template < typename IntegerType >
-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)return t;
+	if (!t)
+        return t;
 	return a / t * b;
 	return a / t * b;
 }
 }
 
 
+template<class T>
+inline
+T getEpsilon() {
+    return std::numeric_limits<T>::epsilon();
+}
+
 }
 }
 }
 }

+ 6 - 0
include/assimp/MemoryIOWrapper.h

@@ -42,12 +42,18 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 /** @file MemoryIOWrapper.h
 /** @file MemoryIOWrapper.h
  *  Handy IOStream/IOSystem implemetation to read directly from a memory buffer */
  *  Handy IOStream/IOSystem implemetation to read directly from a memory buffer */
+#pragma once
 #ifndef AI_MEMORYIOSTREAM_H_INC
 #ifndef AI_MEMORYIOSTREAM_H_INC
 #define AI_MEMORYIOSTREAM_H_INC
 #define AI_MEMORYIOSTREAM_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/IOStream.hpp>
 #include <assimp/IOStream.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/ai_assert.h>
 #include <assimp/ai_assert.h>
+
 #include <stdint.h>
 #include <stdint.h>
 
 
 namespace Assimp    {
 namespace Assimp    {

+ 7 - 2
include/assimp/ParsingUtils.h

@@ -44,11 +44,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file ParsingUtils.h
 /** @file ParsingUtils.h
  *  @brief Defines helper functions for text parsing
  *  @brief Defines helper functions for text parsing
  */
  */
+#pragma once
 #ifndef AI_PARSING_UTILS_H_INC
 #ifndef AI_PARSING_UTILS_H_INC
 #define AI_PARSING_UTILS_H_INC
 #define AI_PARSING_UTILS_H_INC
 
 
-#include "StringComparison.h"
-#include "StringUtils.h"
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
+#include <assimp/StringComparison.h>
+#include <assimp/StringUtils.h>
 #include <assimp/defs.h>
 #include <assimp/defs.h>
 
 
 namespace Assimp {
 namespace Assimp {

+ 9 - 5
include/assimp/Profiler.h

@@ -43,12 +43,17 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file Profiler.h
 /** @file Profiler.h
  *  @brief Utility to measure the respective runtime of each import step
  *  @brief Utility to measure the respective runtime of each import step
  */
  */
-#ifndef INCLUDED_PROFILER_H
-#define INCLUDED_PROFILER_H
+#pragma once
+#ifndef AI_INCLUDED_PROFILER_H
+#define AI_INCLUDED_PROFILER_H
+
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
 
 
 #include <chrono>
 #include <chrono>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
-#include "TinyFormatter.h"
+#include <assimp/TinyFormatter.h>
 
 
 #include <map>
 #include <map>
 
 
@@ -67,7 +72,6 @@ public:
         // empty
         // empty
     }
     }
 
 
-public:
 
 
     /** Start a named timer */
     /** Start a named timer */
     void BeginRegion(const std::string& region) {
     void BeginRegion(const std::string& region) {
@@ -95,5 +99,5 @@ private:
 }
 }
 }
 }
 
 
-#endif
+#endif // AI_INCLUDED_PROFILER_H
 
 

+ 6 - 2
include/assimp/ProgressHandler.hpp

@@ -47,9 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_PROGRESSHANDLER_H_INC
 #ifndef AI_PROGRESSHANDLER_H_INC
 #define AI_PROGRESSHANDLER_H_INC
 #define AI_PROGRESSHANDLER_H_INC
 
 
-#include "types.h"
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
+#include <assimp/types.h>
 
 
-namespace Assimp    {
+namespace Assimp {
 
 
 // ------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------
 /** @brief CPP-API: Abstract interface for custom progress report receivers.
 /** @brief CPP-API: Abstract interface for custom progress report receivers.

+ 5 - 3
include/assimp/RemoveComments.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2019, assimp team
 Copyright (c) 2006-2019, 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,9 +42,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file Declares a helper class, "CommentRemover", which can be
 /** @file Declares a helper class, "CommentRemover", which can be
  *  used to remove comments (single and multi line) from a text file.
  *  used to remove comments (single and multi line) from a text file.
  */
  */
+#pragma once
 #ifndef AI_REMOVE_COMMENTS_H_INC
 #ifndef AI_REMOVE_COMMENTS_H_INC
 #define AI_REMOVE_COMMENTS_H_INC
 #define AI_REMOVE_COMMENTS_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
 
 
 #include <assimp/defs.h>
 #include <assimp/defs.h>
 
 
@@ -58,8 +61,7 @@ namespace Assimp    {
  *  to those in C or C++ so this code has been moved to a separate
  *  to those in C or C++ so this code has been moved to a separate
  *  module.
  *  module.
  */
  */
-class ASSIMP_API CommentRemover
-{
+class ASSIMP_API CommentRemover {
     // class cannot be instanced
     // class cannot be instanced
     CommentRemover() {}
     CommentRemover() {}
 
 

+ 5 - 0
include/assimp/SGSpatialSort.h

@@ -42,9 +42,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 /** Small helper classes to optimize finding vertices close to a given location
 /** Small helper classes to optimize finding vertices close to a given location
  */
  */
+#pragma once
 #ifndef AI_D3DSSPATIALSORT_H_INC
 #ifndef AI_D3DSSPATIALSORT_H_INC
 #define AI_D3DSSPATIALSORT_H_INC
 #define AI_D3DSSPATIALSORT_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/types.h>
 #include <assimp/types.h>
 #include <vector>
 #include <vector>
 #include <stdint.h>
 #include <stdint.h>

+ 10 - 1
include/assimp/SceneCombiner.h

@@ -43,17 +43,22 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file Declares a helper class, "SceneCombiner" providing various
 /** @file Declares a helper class, "SceneCombiner" providing various
  *  utilities to merge scenes.
  *  utilities to merge scenes.
  */
  */
+#pragma once
 #ifndef AI_SCENE_COMBINER_H_INC
 #ifndef AI_SCENE_COMBINER_H_INC
 #define AI_SCENE_COMBINER_H_INC
 #define AI_SCENE_COMBINER_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/ai_assert.h>
 #include <assimp/ai_assert.h>
 #include <assimp/types.h>
 #include <assimp/types.h>
 #include <assimp/Defines.h>
 #include <assimp/Defines.h>
+
 #include <stddef.h>
 #include <stddef.h>
 #include <set>
 #include <set>
 #include <list>
 #include <list>
 #include <stdint.h>
 #include <stdint.h>
-
 #include <vector>
 #include <vector>
 
 
 struct aiScene;
 struct aiScene;
@@ -65,8 +70,10 @@ struct aiLight;
 struct aiMetadata;
 struct aiMetadata;
 struct aiBone;
 struct aiBone;
 struct aiMesh;
 struct aiMesh;
+struct aiAnimMesh;
 struct aiAnimation;
 struct aiAnimation;
 struct aiNodeAnim;
 struct aiNodeAnim;
+struct aiMeshMorphAnim;
 
 
 namespace Assimp    {
 namespace Assimp    {
 
 
@@ -363,6 +370,7 @@ public:
     static void Copy     (aiMesh** dest, const aiMesh* src);
     static void Copy     (aiMesh** dest, const aiMesh* src);
 
 
     // similar to Copy():
     // similar to Copy():
+    static void Copy  (aiAnimMesh** dest, const aiAnimMesh* src);
     static void Copy  (aiMaterial** dest, const aiMaterial* src);
     static void Copy  (aiMaterial** dest, const aiMaterial* src);
     static void Copy  (aiTexture** dest, const aiTexture* src);
     static void Copy  (aiTexture** dest, const aiTexture* src);
     static void Copy  (aiAnimation** dest, const aiAnimation* src);
     static void Copy  (aiAnimation** dest, const aiAnimation* src);
@@ -370,6 +378,7 @@ public:
     static void Copy  (aiBone** dest, const aiBone* src);
     static void Copy  (aiBone** dest, const aiBone* src);
     static void Copy  (aiLight** dest, const aiLight* src);
     static void Copy  (aiLight** dest, const aiLight* src);
     static void Copy  (aiNodeAnim** dest, const aiNodeAnim* src);
     static void Copy  (aiNodeAnim** dest, const aiNodeAnim* src);
+    static void Copy  (aiMeshMorphAnim** dest, const aiMeshMorphAnim* src);
     static void Copy  (aiMetadata** dest, const aiMetadata* src);
     static void Copy  (aiMetadata** dest, const aiMetadata* src);
 
 
     // recursive, of course
     // recursive, of course

+ 5 - 0
include/assimp/SkeletonMeshBuilder.h

@@ -47,9 +47,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  for animation skeletons.
  *  for animation skeletons.
  */
  */
 
 
+#pragma once
 #ifndef AI_SKELETONMESHBUILDER_H_INC
 #ifndef AI_SKELETONMESHBUILDER_H_INC
 #define AI_SKELETONMESHBUILDER_H_INC
 #define AI_SKELETONMESHBUILDER_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <vector>
 #include <vector>
 #include <assimp/mesh.h>
 #include <assimp/mesh.h>
 
 

+ 6 - 0
include/assimp/SmoothingGroups.h

@@ -43,10 +43,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file Defines the helper data structures for importing 3DS files.
 /** @file Defines the helper data structures for importing 3DS files.
 http://www.jalix.org/ressources/graphics/3DS/_unofficials/3ds-unofficial.txt */
 http://www.jalix.org/ressources/graphics/3DS/_unofficials/3ds-unofficial.txt */
 
 
+#pragma once
 #ifndef AI_SMOOTHINGGROUPS_H_INC
 #ifndef AI_SMOOTHINGGROUPS_H_INC
 #define AI_SMOOTHINGGROUPS_H_INC
 #define AI_SMOOTHINGGROUPS_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/vector3.h>
 #include <assimp/vector3.h>
+
 #include <stdint.h>
 #include <stdint.h>
 #include <vector>
 #include <vector>
 
 

+ 5 - 2
include/assimp/SmoothingGroups.inl

@@ -41,13 +41,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 /** @file Generation of normal vectors basing on smoothing groups */
 /** @file Generation of normal vectors basing on smoothing groups */
 
 
+#pragma once
 #ifndef AI_SMOOTHINGGROUPS_INL_INCLUDED
 #ifndef AI_SMOOTHINGGROUPS_INL_INCLUDED
 #define AI_SMOOTHINGGROUPS_INL_INCLUDED
 #define AI_SMOOTHINGGROUPS_INL_INCLUDED
 
 
-// internal headers
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/SGSpatialSort.h>
 #include <assimp/SGSpatialSort.h>
 
 
-// CRT header
 #include <algorithm>
 #include <algorithm>
 
 
 using namespace Assimp;
 using namespace Assimp;

+ 5 - 0
include/assimp/SpatialSort.h

@@ -41,9 +41,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 /** Small helper classes to optimise finding vertizes close to a given location */
 /** Small helper classes to optimise finding vertizes close to a given location */
+#pragma once
 #ifndef AI_SPATIALSORT_H_INC
 #ifndef AI_SPATIALSORT_H_INC
 #define AI_SPATIALSORT_H_INC
 #define AI_SPATIALSORT_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <vector>
 #include <vector>
 #include <assimp/types.h>
 #include <assimp/types.h>
 
 

+ 6 - 1
include/assimp/StandardShapes.h

@@ -41,11 +41,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */
 */
 
 
 /** @file Declares a helper class, "StandardShapes" which generates
 /** @file Declares a helper class, "StandardShapes" which generates
- *  vertices for standard shapes, such as cylnders, cones, spheres ..
+ *  vertices for standard shapes, such as cylinders, cones, spheres ..
  */
  */
+#pragma once
 #ifndef AI_STANDARD_SHAPES_H_INC
 #ifndef AI_STANDARD_SHAPES_H_INC
 #define AI_STANDARD_SHAPES_H_INC
 #define AI_STANDARD_SHAPES_H_INC
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/vector3.h>
 #include <assimp/vector3.h>
 #include <vector>
 #include <vector>
 
 

+ 7 - 3
include/assimp/StreamReader.h

@@ -44,15 +44,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file Defines the StreamReader class which reads data from
 /** @file Defines the StreamReader class which reads data from
  *  a binary stream with a well-defined endianness.
  *  a binary stream with a well-defined endianness.
  */
  */
-
+#pragma once
 #ifndef AI_STREAMREADER_H_INCLUDED
 #ifndef AI_STREAMREADER_H_INCLUDED
 #define AI_STREAMREADER_H_INCLUDED
 #define AI_STREAMREADER_H_INCLUDED
 
 
+#ifdef __GNUC__
+#   pragma GCC system_header
+#endif
+
 #include <assimp/IOStream.hpp>
 #include <assimp/IOStream.hpp>
 #include <assimp/Defines.h>
 #include <assimp/Defines.h>
+#include <assimp/ByteSwapper.h>
+#include <assimp/Exceptional.h>
 
 
-#include "ByteSwapper.h"
-#include "Exceptional.h"
 #include <memory>
 #include <memory>
 
 
 namespace Assimp {
 namespace Assimp {

部分文件因文件數量過多而無法顯示