فهرست منبع

Merge branch 'master' into FBXParser_check_inputlength_fix

Max Vollmer (Microsoft Havok) 5 سال پیش
والد
کامیت
c9cf661b29
59فایلهای تغییر یافته به همراه1227 افزوده شده و 854 حذف شده
  1. 2 2
      .clang-format
  2. 54 52
      CMakeLists.txt
  3. 1 1
      assimp.pc.in
  4. 1 1
      assimpTargets-debug.cmake.in
  5. 1 1
      assimpTargets-release.cmake.in
  6. 158 164
      code/CMakeLists.txt
  7. 3 4
      code/Common/BaseImporter.cpp
  8. 16 23
      code/Common/BaseProcess.cpp
  9. 46 85
      code/Common/BaseProcess.h
  10. 4 4
      code/Common/Importer.cpp
  11. 1 1
      code/Common/PostStepRegistry.cpp
  12. 0 2
      code/Common/ZipArchiveIOSystem.cpp
  13. 5 6
      code/FBX/FBXMeshGeometry.cpp
  14. 63 27
      code/M3D/M3DImporter.cpp
  15. 4 11
      code/Obj/ObjFileData.h
  16. 22 27
      code/Obj/ObjFileImporter.cpp
  17. 2 2
      code/Obj/ObjFileMtlImporter.cpp
  18. 23 25
      code/Obj/ObjFileParser.cpp
  19. 1 1
      code/Obj/ObjFileParser.h
  20. 40 0
      code/PostProcessing/SplitByBoneCountProcess.cpp
  21. 1 1
      code/PostProcessing/SplitByBoneCountProcess.h
  22. 3 5
      code/PostProcessing/TextureTransform.cpp
  23. 6 0
      code/PostProcessing/ValidateDataStructure.cpp
  24. 1 0
      code/glTF/glTFAsset.h
  25. 3 1
      code/glTF/glTFAssetWriter.inl
  26. 8 12
      code/glTF/glTFExporter.cpp
  27. 1 0
      code/glTF/glTFImporter.cpp
  28. 1 0
      code/glTF2/glTF2Asset.h
  29. 4 4
      code/glTF2/glTF2AssetWriter.inl
  30. 29 13
      code/glTF2/glTF2Exporter.cpp
  31. 48 35
      code/glTF2/glTF2Importer.cpp
  32. 1 1
      contrib/CMakeLists.txt
  33. 2 6
      contrib/zip/CMakeLists.txt
  34. 48 3
      contrib/zip/README.md
  35. 16 1
      contrib/zip/src/zip.c
  36. 12 1
      contrib/zip/src/zip.h
  37. 0 5
      contrib/zip/test/CMakeLists.txt
  38. 3 1
      contrib/zip/test/test.c
  39. 2 2
      doc/CMakeLists.txt
  40. 17 22
      include/assimp/GenericProperty.h
  41. 2 2
      include/assimp/Importer.hpp
  42. 3 3
      include/assimp/matrix3x3.h
  43. 3 3
      include/assimp/matrix3x3.inl
  44. 1 1
      port/PyAssimp/pyassimp/core.py
  45. 52 0
      samples/SharedCode/UTFConverter.cpp
  46. 92 0
      samples/SharedCode/UTFConverter.h
  47. 6 6
      samples/SimpleOpenGL/CMakeLists.txt
  48. 9 6
      samples/SimpleTexturedDirectx11/CMakeLists.txt
  49. 80 75
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h
  50. 56 76
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp
  51. 4 4
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.h
  52. 57 0
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp
  53. 132 53
      samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp
  54. 8 5
      samples/SimpleTexturedOpenGL/CMakeLists.txt
  55. 62 40
      samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp
  56. 3 10
      test/CMakeLists.txt
  57. 1 1
      test/headercheck/CMakeLists.txt
  58. 1 8
      tools/assimp_cmd/CMakeLists.txt
  59. 2 9
      tools/assimp_view/CMakeLists.txt

+ 2 - 2
.clang-format

@@ -71,7 +71,7 @@ IncludeCategories:
     Priority:        3
     Priority:        3
 # IncludeIsMainRegex: '(Test)?$'
 # IncludeIsMainRegex: '(Test)?$'
 IndentCaseLabels: true
 IndentCaseLabels: true
-# IndentPPDirectives: None
+IndentPPDirectives: AfterHash
 IndentWidth:     4
 IndentWidth:     4
 # IndentWrappedFunctionNames: false
 # IndentWrappedFunctionNames: false
 # JavaScriptQuotes: Leave
 # JavaScriptQuotes: Leave
@@ -108,7 +108,7 @@ IndentWidth:     4
 # SpacesInParentheses: false
 # SpacesInParentheses: false
 # SpacesInSquareBrackets: false
 # SpacesInSquareBrackets: false
 TabWidth:        4
 TabWidth:        4
-UseTab:          Always
+UseTab:          Never
 ---
 ---
 ### C++ specific config ###
 ### C++ specific config ###
 Language:        Cpp
 Language:        Cpp

+ 54 - 52
CMakeLists.txt

@@ -49,7 +49,7 @@ IF(HUNTER_ENABLED)
   )
   )
 
 
   add_definitions(-DASSIMP_USE_HUNTER)
   add_definitions(-DASSIMP_USE_HUNTER)
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 PROJECT( Assimp VERSION 5.0.1 )
 PROJECT( Assimp VERSION 5.0.1 )
 
 
@@ -141,9 +141,9 @@ OPTION ( IGNORE_GIT_HASH
 IF (IOS AND NOT HUNTER_ENABLED)
 IF (IOS AND NOT HUNTER_ENABLED)
   IF (NOT CMAKE_BUILD_TYPE)
   IF (NOT CMAKE_BUILD_TYPE)
     SET(CMAKE_BUILD_TYPE "Release")
     SET(CMAKE_BUILD_TYPE "Release")
-  ENDIF (NOT CMAKE_BUILD_TYPE)
+  ENDIF ()
   ADD_DEFINITIONS(-DENABLE_BITCODE)
   ADD_DEFINITIONS(-DENABLE_BITCODE)
-ENDIF (IOS AND NOT HUNTER_ENABLED)
+ENDIF ()
 
 
 # Use subset of Windows.h
 # Use subset of Windows.h
 if (WIN32)
 if (WIN32)
@@ -159,19 +159,19 @@ IF(MSVC)
     # Multibyte character set is deprecated since at least MSVC2015 (possibly earlier)
     # Multibyte character set is deprecated since at least MSVC2015 (possibly earlier)
     ADD_DEFINITIONS( -DUNICODE -D_UNICODE )
     ADD_DEFINITIONS( -DUNICODE -D_UNICODE )
   ENDIF()
   ENDIF()
-ENDIF(MSVC)
+ENDIF()
 
 
 IF (BUILD_FRAMEWORK)
 IF (BUILD_FRAMEWORK)
   SET (BUILD_SHARED_LIBS ON)
   SET (BUILD_SHARED_LIBS ON)
   MESSAGE(STATUS "Framework bundle building enabled")
   MESSAGE(STATUS "Framework bundle building enabled")
-ENDIF(BUILD_FRAMEWORK)
+ENDIF()
 
 
 IF(NOT BUILD_SHARED_LIBS)
 IF(NOT BUILD_SHARED_LIBS)
   MESSAGE(STATUS "Shared libraries disabled")
   MESSAGE(STATUS "Shared libraries disabled")
   SET(LINK_SEARCH_START_STATIC TRUE)
   SET(LINK_SEARCH_START_STATIC TRUE)
 ELSE()
 ELSE()
   MESSAGE(STATUS "Shared libraries enabled")
   MESSAGE(STATUS "Shared libraries enabled")
-ENDIF(NOT BUILD_SHARED_LIBS)
+ENDIF()
 
 
 # Define here the needed parameters
 # Define here the needed parameters
 SET (ASSIMP_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
 SET (ASSIMP_VERSION_MAJOR ${PROJECT_VERSION_MAJOR})
@@ -208,11 +208,11 @@ ENDIF()
 
 
 IF(NOT GIT_COMMIT_HASH)
 IF(NOT GIT_COMMIT_HASH)
   SET(GIT_COMMIT_HASH 0)
   SET(GIT_COMMIT_HASH 0)
-ENDIF(NOT GIT_COMMIT_HASH)
+ENDIF()
 
 
 IF(ASSIMP_DOUBLE_PRECISION)
 IF(ASSIMP_DOUBLE_PRECISION)
     ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
     ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
-ENDIF(ASSIMP_DOUBLE_PRECISION)
+ENDIF()
 
 
 CONFIGURE_FILE(
 CONFIGURE_FILE(
   ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
   ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
@@ -241,7 +241,7 @@ SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
 IF( UNIX )
 IF( UNIX )
   # Use GNUInstallDirs for Unix predefined directories
   # Use GNUInstallDirs for Unix predefined directories
   INCLUDE(GNUInstallDirs)
   INCLUDE(GNUInstallDirs)
-ENDIF( UNIX )
+ENDIF()
 
 
 # Grouped compiler settings
 # Grouped compiler settings
 IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
 IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
@@ -293,7 +293,7 @@ IF ( IOS AND NOT HUNTER_ENABLED)
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
     # Experimental for pdb generation
     # Experimental for pdb generation
   ENDIF()
   ENDIF()
-ENDIF( IOS AND NOT HUNTER_ENABLED)
+ENDIF()
 
 
 IF (ASSIMP_COVERALLS)
 IF (ASSIMP_COVERALLS)
   MESSAGE(STATUS "Coveralls enabled")
   MESSAGE(STATUS "Coveralls enabled")
@@ -342,10 +342,14 @@ INCLUDE (PrecompiledHeader)
 # source tree. During an out-of-source build, however, do not litter this
 # source tree. During an out-of-source build, however, do not litter this
 # directory, since that is probably what the user wanted to avoid.
 # directory, since that is probably what the user wanted to avoid.
 IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
 IF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
-  SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
+  SET( CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" )
   SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
   SET( CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/lib" )
   SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" )
   SET( CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_HOME_DIRECTORY}/bin" )
-ENDIF ( CMAKE_SOURCE_DIR STREQUAL CMAKE_BINARY_DIR )
+ELSE()
+  SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/lib")
+  SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
+  SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/bin")
+ENDIF ()
 
 
 # Cache these to allow the user to override them manually.
 # Cache these to allow the user to override them manually.
 SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE STRING
 SET( ASSIMP_LIB_INSTALL_DIR "lib" CACHE STRING
@@ -407,7 +411,7 @@ IF(HUNTER_ENABLED)
       NAMESPACE "${NAMESPACE}"
       NAMESPACE "${NAMESPACE}"
       DESTINATION "${CONFIG_INSTALL_DIR}"
       DESTINATION "${CONFIG_INSTALL_DIR}"
   )
   )
-ELSE(HUNTER_ENABLED)
+ELSE()
   # cmake configuration files
   # cmake configuration files
   if(${BUILD_SHARED_LIBS})
   if(${BUILD_SHARED_LIBS})
     set(BUILD_LIB_TYPE SHARED)
     set(BUILD_LIB_TYPE SHARED)
@@ -435,20 +439,16 @@ ELSE(HUNTER_ENABLED)
     "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake"
     "${CMAKE_CURRENT_BINARY_DIR}/assimpTargets.cmake"
     ${PACKAGE_TARGETS_FILE}
     ${PACKAGE_TARGETS_FILE}
     DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
     DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
-ENDIF(HUNTER_ENABLED)
-
-if (ASSIMP_BUILD_SAMPLES OR ASSIMP_BUILD_SAMPLES)
-  FIND_PACKAGE(DirectX)
-endif(ASSIMP_BUILD_SAMPLES OR ASSIMP_BUILD_SAMPLES)
+ENDIF()
 
 
 IF( BUILD_DOCS )
 IF( BUILD_DOCS )
   ADD_SUBDIRECTORY(doc)
   ADD_SUBDIRECTORY(doc)
-ENDIF( BUILD_DOCS )
+ENDIF()
 
 
 # Look for system installed irrXML
 # Look for system installed irrXML
 IF ( SYSTEM_IRRXML )
 IF ( SYSTEM_IRRXML )
   FIND_PACKAGE( IrrXML REQUIRED )
   FIND_PACKAGE( IrrXML REQUIRED )
-ENDIF( SYSTEM_IRRXML )
+ENDIF()
 
 
 # Search for external dependencies, and build them from source if not found
 # Search for external dependencies, and build them from source if not found
 # Search for zlib
 # Search for zlib
@@ -460,10 +460,10 @@ IF(HUNTER_ENABLED)
   set(ZLIB_FOUND TRUE)
   set(ZLIB_FOUND TRUE)
   set(ZLIB_LIBRARIES ZLIB::zlib)
   set(ZLIB_LIBRARIES ZLIB::zlib)
   set(ASSIMP_BUILD_MINIZIP TRUE)
   set(ASSIMP_BUILD_MINIZIP TRUE)
-ELSE(HUNTER_ENABLED)
+ELSE()
   IF ( NOT ASSIMP_BUILD_ZLIB )
   IF ( NOT ASSIMP_BUILD_ZLIB )
     FIND_PACKAGE(ZLIB)
     FIND_PACKAGE(ZLIB)
-  ENDIF( NOT ASSIMP_BUILD_ZLIB )
+  ENDIF()
 
 
   IF( NOT ZLIB_FOUND )
   IF( NOT ZLIB_FOUND )
     MESSAGE(STATUS "compiling zlib from sources")
     MESSAGE(STATUS "compiling zlib from sources")
@@ -486,46 +486,46 @@ ELSE(HUNTER_ENABLED)
     SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
     SET(ZLIB_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/contrib/zlib ${CMAKE_CURRENT_BINARY_DIR}/contrib/zlib)
     # need to ensure we don't link with system zlib or minizip as well.
     # need to ensure we don't link with system zlib or minizip as well.
     SET(ASSIMP_BUILD_MINIZIP 1)
     SET(ASSIMP_BUILD_MINIZIP 1)
-  ELSE(NOT ZLIB_FOUND)
+  ELSE()
     ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
     ADD_DEFINITIONS(-DASSIMP_BUILD_NO_OWN_ZLIB)
     SET(ZLIB_LIBRARIES_LINKED -lz)
     SET(ZLIB_LIBRARIES_LINKED -lz)
-  ENDIF(NOT ZLIB_FOUND)
+  ENDIF()
   INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
   INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 IF( NOT IOS )
 IF( NOT IOS )
   IF( NOT ASSIMP_BUILD_MINIZIP )
   IF( NOT ASSIMP_BUILD_MINIZIP )
     use_pkgconfig(UNZIP minizip)
     use_pkgconfig(UNZIP minizip)
-  ENDIF( NOT ASSIMP_BUILD_MINIZIP )
-ELSE ( NOT IOS )
+  ENDIF()
+ELSE ()
   IF( NOT BUILD_SHARED_LIBS )
   IF( NOT BUILD_SHARED_LIBS )
     IF( NOT ASSIMP_BUILD_MINIZIP )
     IF( NOT ASSIMP_BUILD_MINIZIP )
       use_pkgconfig(UNZIP minizip)
       use_pkgconfig(UNZIP minizip)
-    ENDIF( NOT ASSIMP_BUILD_MINIZIP )
-  ENDIF ( NOT BUILD_SHARED_LIBS )
-ENDIF ( NOT IOS )
+    ENDIF()
+  ENDIF ()
+ENDIF ()
 
 
 IF ( ASSIMP_NO_EXPORT )
 IF ( ASSIMP_NO_EXPORT )
   ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT)
   ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT)
   MESSAGE( STATUS "Build an import-only version of Assimp." )
   MESSAGE( STATUS "Build an import-only version of Assimp." )
-ENDIF( ASSIMP_NO_EXPORT )
+ENDIF()
 
 
 SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING
 SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING
   "describe the current architecture."
   "describe the current architecture."
 )
 )
 IF    ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
 IF    ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
-ELSE  ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
+ELSE  ()
   ADD_DEFINITIONS ( -D'ASSIMP_BUILD_ARCHITECTURE="${ASSIMP_BUILD_ARCHITECTURE}"' )
   ADD_DEFINITIONS ( -D'ASSIMP_BUILD_ARCHITECTURE="${ASSIMP_BUILD_ARCHITECTURE}"' )
-ENDIF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
+ENDIF ()
 
 
 # ${CMAKE_GENERATOR}
 # ${CMAKE_GENERATOR}
 SET ( ASSIMP_BUILD_COMPILER "" CACHE STRING
 SET ( ASSIMP_BUILD_COMPILER "" CACHE STRING
   "describe the current compiler."
   "describe the current compiler."
 )
 )
 IF    ( ASSIMP_BUILD_COMPILER STREQUAL "")
 IF    ( ASSIMP_BUILD_COMPILER STREQUAL "")
-ELSE  ( ASSIMP_BUILD_COMPILER STREQUAL "")
+ELSE  ()
   ADD_DEFINITIONS ( -D'ASSIMP_BUILD_COMPILER="${ASSIMP_BUILD_COMPILER}"' )
   ADD_DEFINITIONS ( -D'ASSIMP_BUILD_COMPILER="${ASSIMP_BUILD_COMPILER}"' )
-ENDIF ( ASSIMP_BUILD_COMPILER STREQUAL "")
+ENDIF ()
 
 
 MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
 MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
 
 
@@ -571,45 +571,47 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
     MESSAGE( FATAL_ERROR
     MESSAGE( FATAL_ERROR
       "C4D is currently only available on Windows with melange SDK installed in contrib/Melange"
       "C4D is currently only available on Windows with melange SDK installed in contrib/Melange"
     )
     )
-  ENDIF ( MSVC )
-ELSE (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+  ENDIF ()
+ELSE ()
   ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
   ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
-ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+ENDIF ()
 
 
 IF(NOT HUNTER_ENABLED)
 IF(NOT HUNTER_ENABLED)
   ADD_SUBDIRECTORY(contrib)
   ADD_SUBDIRECTORY(contrib)
-ENDIF(NOT HUNTER_ENABLED)
+ENDIF()
 
 
 ADD_SUBDIRECTORY( code/ )
 ADD_SUBDIRECTORY( code/ )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
   # The viewer for windows only
   # The viewer for windows only
-  IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
-    OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
+  IF ( WIN32 )
+    OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" OFF )
     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 ( WIN32 AND DirectX_D3DX9_LIBRARY )
-  # Te command line tool
+    ENDIF ()
+  ENDIF ()
+  # The command line tool
   ADD_SUBDIRECTORY( tools/assimp_cmd/ )
   ADD_SUBDIRECTORY( tools/assimp_cmd/ )
-ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
+ENDIF ()
 
 
 IF ( ASSIMP_BUILD_SAMPLES)
 IF ( ASSIMP_BUILD_SAMPLES)
+  SET( SAMPLES_DIR ${CMAKE_CURRENT_SOURCE_DIR}/samples )
+  SET( SAMPLES_SHARED_CODE_DIR ${SAMPLES_DIR}/SharedCode )
   IF ( WIN32 )
   IF ( WIN32 )
     ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
     ADD_SUBDIRECTORY( samples/SimpleTexturedOpenGL/ )
     ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 )
     ADD_SUBDIRECTORY( samples/SimpleTexturedDirectx11 )
-  ENDIF ( WIN32 )
+  ENDIF ()
   ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
   ADD_SUBDIRECTORY( samples/SimpleOpenGL/ )
-ENDIF ( ASSIMP_BUILD_SAMPLES )
+ENDIF ()
 
 
 IF ( ASSIMP_BUILD_TESTS )
 IF ( ASSIMP_BUILD_TESTS )
   ADD_SUBDIRECTORY( test/ )
   ADD_SUBDIRECTORY( test/ )
-ENDIF ( ASSIMP_BUILD_TESTS )
+ENDIF ()
 
 
 # Generate a pkg-config .pc for the Assimp library.
 # Generate a pkg-config .pc for the Assimp library.
 CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
 CONFIGURE_FILE( "${PROJECT_SOURCE_DIR}/assimp.pc.in" "${PROJECT_BINARY_DIR}/assimp.pc" @ONLY )
 IF ( ASSIMP_INSTALL )
 IF ( ASSIMP_INSTALL )
   INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
   INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTALL_DIR}/pkgconfig/ COMPONENT ${LIBASSIMP-DEV_COMPONENT})
-ENDIF( ASSIMP_INSTALL )
+ENDIF()
 
 
 IF ( ASSIMP_INSTALL )
 IF ( ASSIMP_INSTALL )
   IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
   IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
@@ -680,7 +682,7 @@ if(WIN32)
       SET(ASSIMP_MSVC_VERSION "vc140")
       SET(ASSIMP_MSVC_VERSION "vc140")
     ELSEIF(MSVC15)
     ELSEIF(MSVC15)
       SET(ASSIMP_MSVC_VERSION "vc141")
       SET(ASSIMP_MSVC_VERSION "vc141")
-    ENDIF(MSVC12)
+    ENDIF()
   ENDIF()
   ENDIF()
 
 
   IF(MSVC12 OR MSVC14 OR MSVC15 )
   IF(MSVC12 OR MSVC14 OR MSVC15 )
@@ -705,5 +707,5 @@ if(WIN32)
       ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
       ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
       ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
       ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
     ENDIF()
     ENDIF()
-  ENDIF(MSVC12 OR MSVC14 OR MSVC15 )
-ENDIF (WIN32)
+  ENDIF()
+ENDIF ()

+ 1 - 1
assimp.pc.in

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

+ 1 - 1
assimpTargets-debug.cmake.in

@@ -35,7 +35,7 @@ if(MSVC)
   endif()
   endif()
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
 
 
-  file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX)
+  file(TO_NATIVE_PATH "${_IMPORT_PREFIX}" _IMPORT_PREFIX)
 
 
   if(ASSIMP_BUILD_SHARED_LIBS)
   if(ASSIMP_BUILD_SHARED_LIBS)
     set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@")
     set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_DEBUG_POSTFIX@@CMAKE_SHARED_LIBRARY_SUFFIX@")

+ 1 - 1
assimpTargets-release.cmake.in

@@ -35,7 +35,7 @@ if(MSVC)
   endif()
   endif()
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
   set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
   	
   	
-  file(TO_NATIVE_PATH ${_IMPORT_PREFIX} _IMPORT_PREFIX)
+  file(TO_NATIVE_PATH "${_IMPORT_PREFIX}" _IMPORT_PREFIX)
 
 
   if(ASSIMP_BUILD_SHARED_LIBS)
   if(ASSIMP_BUILD_SHARED_LIBS)
     set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@")
     set(sharedLibraryName "assimp${ASSIMP_LIBRARY_SUFFIX}@CMAKE_SHARED_LIBRARY_SUFFIX@")

+ 158 - 164
code/CMakeLists.txt

@@ -49,7 +49,7 @@ SET( HEADER_PATH ../include/assimp )
 if(NOT ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
 if(NOT ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
     message(WARNING "Requesting Android JNI I/O-System in non-Android toolchain. Resetting ASSIMP_ANDROID_JNIIOSYSTEM to OFF.")
     message(WARNING "Requesting Android JNI I/O-System in non-Android toolchain. Resetting ASSIMP_ANDROID_JNIIOSYSTEM to OFF.")
     set(ASSIMP_ANDROID_JNIIOSYSTEM OFF)
     set(ASSIMP_ANDROID_JNIIOSYSTEM OFF)
-endif(NOT ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
+endif()
 
 
 SET( COMPILER_HEADERS
 SET( COMPILER_HEADERS
   ${HEADER_PATH}/Compiler/pushpack1.h
   ${HEADER_PATH}/Compiler/pushpack1.h
@@ -148,7 +148,7 @@ SET( Core_SRCS
 
 
 IF(MSVC)
 IF(MSVC)
   list(APPEND Core_SRCS "res/assimp.rc")
   list(APPEND Core_SRCS "res/assimp.rc")
-ENDIF(MSVC)
+ENDIF()
 
 
 SET( Logging_SRCS
 SET( Logging_SRCS
   ${HEADER_PATH}/DefaultLogger.hpp
   ${HEADER_PATH}/DefaultLogger.hpp
@@ -185,8 +185,6 @@ SET( Common_SRCS
   Common/ScenePreprocessor.cpp
   Common/ScenePreprocessor.cpp
   Common/ScenePreprocessor.h
   Common/ScenePreprocessor.h
   Common/SkeletonMeshBuilder.cpp
   Common/SkeletonMeshBuilder.cpp
-  Common/SplitByBoneCountProcess.cpp
-  Common/SplitByBoneCountProcess.h
   Common/StandardShapes.cpp
   Common/StandardShapes.cpp
   Common/TargetAnimation.cpp
   Common/TargetAnimation.cpp
   Common/TargetAnimation.h
   Common/TargetAnimation.h
@@ -222,7 +220,7 @@ IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
     C4D/C4DImporter.h
     C4D/C4DImporter.h
   )
   )
   SOURCE_GROUP( C4D FILES ${C4D_SRCS})
   SOURCE_GROUP( C4D FILES ${C4D_SRCS})
-ENDIF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
+ENDIF ()
 
 
 # if this variable is set to TRUE, the user can manually disable importers by setting
 # if this variable is set to TRUE, the user can manually disable importers by setting
 # ASSIMP_BUILD_XXX_IMPORTER to FALSE for each importer
 # ASSIMP_BUILD_XXX_IMPORTER to FALSE for each importer
@@ -252,35 +250,39 @@ MACRO(ADD_ASSIMP_IMPORTER name)
   ENDIF()
   ENDIF()
 ENDMACRO()
 ENDMACRO()
 
 
-# if this variable is set to TRUE, the user can manually disable exporters by setting
-# ASSIMP_BUILD_XXX_EXPORTER to FALSE for each exporter
-# if this variable is set to FALSE, the user can manually enable exporters by setting
-# ASSIMP_BUILD_XXX_EXPORTER to TRUE for each exporter
-OPTION(ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_EXPORTER values" TRUE)
+if (NOT ASSIMP_NO_EXPORT)
 
 
-# macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
-# this way selective loaders can be compiled (reduces filesize + compile time)
-MACRO(ADD_ASSIMP_EXPORTER name)
-  IF (ASSIMP_NO_EXPORT)
-	set(ASSIMP_EXPORTER_ENABLED FALSE)
-  ELSEIF (ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT)
-    set(ASSIMP_EXPORTER_ENABLED TRUE)
-    IF (DEFINED ASSIMP_BUILD_${name}_EXPORTER AND NOT ASSIMP_BUILD_${name}_EXPORTER)
+  # if this variable is set to TRUE, the user can manually disable exporters by setting
+  # ASSIMP_BUILD_XXX_EXPORTER to FALSE for each exporter
+  # if this variable is set to FALSE, the user can manually enable exporters by setting
+  # ASSIMP_BUILD_XXX_EXPORTER to TRUE for each exporter
+  OPTION(ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_EXPORTER values" TRUE)
+
+  # macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
+  # this way selective loaders can be compiled (reduces filesize + compile time)
+  MACRO(ADD_ASSIMP_EXPORTER name)
+    IF (ASSIMP_NO_EXPORT)
       set(ASSIMP_EXPORTER_ENABLED FALSE)
       set(ASSIMP_EXPORTER_ENABLED FALSE)
+    ELSEIF (ASSIMP_BUILD_ALL_EXPORTERS_BY_DEFAULT)
+      set(ASSIMP_EXPORTER_ENABLED TRUE)
+      IF (DEFINED ASSIMP_BUILD_${name}_EXPORTER AND NOT ASSIMP_BUILD_${name}_EXPORTER)
+        set(ASSIMP_EXPORTER_ENABLED FALSE)
+      ENDIF ()
+    ELSE ()
+      set(ASSIMP_EXPORTER_ENABLED ${ASSIMP_BUILD_${name}_EXPORTER})
     ENDIF ()
     ENDIF ()
-  ELSE ()
-    set(ASSIMP_EXPORTER_ENABLED ${ASSIMP_BUILD_${name}_EXPORTER})
-  ENDIF ()
 
 
-  IF (ASSIMP_EXPORTER_ENABLED)
-    SET(ASSIMP_EXPORTERS_ENABLED "${ASSIMP_EXPORTERS_ENABLED} ${name}")
-	LIST(APPEND ASSIMP_EXPORTER_SRCS ${ARGN})
-    SOURCE_GROUP(${name}_EXPORTER FILES ${ARGN})
-  ELSE()
-    SET(ASSIMP_EXPORTERS_DISABLED "${ASSIMP_EXPORTERS_DISABLED} ${name}")
-    add_definitions(-DASSIMP_BUILD_NO_${name}_EXPORTER)
-  ENDIF()
-ENDMACRO()
+    IF (ASSIMP_EXPORTER_ENABLED)
+      SET(ASSIMP_EXPORTERS_ENABLED "${ASSIMP_EXPORTERS_ENABLED} ${name}")
+      LIST(APPEND ASSIMP_EXPORTER_SRCS ${ARGN})
+      SOURCE_GROUP(${name}_EXPORTER FILES ${ARGN})
+    ELSE()
+      SET(ASSIMP_EXPORTERS_DISABLED "${ASSIMP_EXPORTERS_DISABLED} ${name}")
+      add_definitions(-DASSIMP_BUILD_NO_${name}_EXPORTER)
+    ENDIF()
+  ENDMACRO()
+
+endif()
 
 
 SET(ASSIMP_LOADER_SRCS "")
 SET(ASSIMP_LOADER_SRCS "")
 SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers
 SET(ASSIMP_IMPORTERS_ENABLED "") # list of enabled importers
@@ -307,11 +309,6 @@ ADD_ASSIMP_IMPORTER( 3DS
   3DS/3DSLoader.h
   3DS/3DSLoader.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( 3DS
-  3DS/3DSExporter.h
-  3DS/3DSExporter.cpp
-)
-
 ADD_ASSIMP_IMPORTER( AC
 ADD_ASSIMP_IMPORTER( AC
   AC/ACLoader.cpp
   AC/ACLoader.cpp
   AC/ACLoader.h
   AC/ACLoader.h
@@ -329,20 +326,6 @@ ADD_ASSIMP_IMPORTER( ASSBIN
   Assbin/AssbinLoader.cpp
   Assbin/AssbinLoader.cpp
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( ASSBIN
-  Assbin/AssbinExporter.h
-  Assbin/AssbinExporter.cpp
-  Assbin/AssbinFileWriter.h
-  Assbin/AssbinFileWriter.cpp
-)
-
-ADD_ASSIMP_EXPORTER( ASSXML
-  Assxml/AssxmlExporter.h
-  Assxml/AssxmlExporter.cpp
-  Assxml/AssxmlFileWriter.h
-  Assxml/AssxmlFileWriter.cpp
-)
-
 ADD_ASSIMP_IMPORTER( B3D
 ADD_ASSIMP_IMPORTER( B3D
   B3D/B3DImporter.cpp
   B3D/B3DImporter.cpp
   B3D/B3DImporter.h
   B3D/B3DImporter.h
@@ -362,11 +345,6 @@ ADD_ASSIMP_IMPORTER( COLLADA
   Collada/ColladaParser.h
   Collada/ColladaParser.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( COLLADA
-  Collada/ColladaExporter.h
-  Collada/ColladaExporter.cpp
-)
-
 ADD_ASSIMP_IMPORTER( DXF
 ADD_ASSIMP_IMPORTER( DXF
   DXF/DXFLoader.cpp
   DXF/DXFLoader.cpp
   DXF/DXFLoader.h
   DXF/DXFLoader.h
@@ -423,11 +401,6 @@ ADD_ASSIMP_IMPORTER( M3D
   M3D/m3d.h
   M3D/m3d.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( M3D
-  M3D/M3DExporter.h
-  M3D/M3DExporter.cpp
-)
-
 ADD_ASSIMP_IMPORTER( MD2
 ADD_ASSIMP_IMPORTER( MD2
   MD2/MD2FileData.h
   MD2/MD2FileData.h
   MD2/MD2Loader.cpp
   MD2/MD2Loader.cpp
@@ -505,11 +478,6 @@ ADD_ASSIMP_IMPORTER( OBJ
   Obj/ObjTools.h
   Obj/ObjTools.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( OBJ
-  Obj/ObjExporter.h
-  Obj/ObjExporter.cpp
-)
-
 ADD_ASSIMP_IMPORTER( OGRE
 ADD_ASSIMP_IMPORTER( OGRE
   Ogre/OgreImporter.h
   Ogre/OgreImporter.h
   Ogre/OgreStructs.h
   Ogre/OgreStructs.h
@@ -529,11 +497,6 @@ ADD_ASSIMP_IMPORTER( OPENGEX
   OpenGEX/OpenGEXStructs.h
   OpenGEX/OpenGEXStructs.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( OPENGEX
-  OpenGEX/OpenGEXExporter.cpp
-  OpenGEX/OpenGEXExporter.h
-)
-
 ADD_ASSIMP_IMPORTER( PLY
 ADD_ASSIMP_IMPORTER( PLY
   Ply/PlyLoader.cpp
   Ply/PlyLoader.cpp
   Ply/PlyLoader.h
   Ply/PlyLoader.h
@@ -541,11 +504,6 @@ ADD_ASSIMP_IMPORTER( PLY
   Ply/PlyParser.h
   Ply/PlyParser.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( PLY
-  Ply/PlyExporter.cpp
-  Ply/PlyExporter.h
-)
-
 ADD_ASSIMP_IMPORTER( MS3D
 ADD_ASSIMP_IMPORTER( MS3D
   MS3D/MS3DLoader.cpp
   MS3D/MS3DLoader.cpp
   MS3D/MS3DLoader.h
   MS3D/MS3DLoader.h
@@ -599,7 +557,7 @@ if (ASSIMP_BUILD_IFC_IMPORTER)
   elseif(CMAKE_COMPILER_IS_MINGW)
   elseif(CMAKE_COMPILER_IS_MINGW)
     set_source_files_properties(Importer/IFC/IFCReaderGen1_2x3.cpp Importer/IFC/IFCReaderGen2_2x3.cpp PROPERTIES COMPILE_FLAGS "-O2 -Wa,-mbig-obj")
     set_source_files_properties(Importer/IFC/IFCReaderGen1_2x3.cpp Importer/IFC/IFCReaderGen2_2x3.cpp PROPERTIES COMPILE_FLAGS "-O2 -Wa,-mbig-obj")
   endif()
   endif()
-endif (ASSIMP_BUILD_IFC_IMPORTER)
+endif ()
 
 
 ADD_ASSIMP_IMPORTER( XGL
 ADD_ASSIMP_IMPORTER( XGL
   XGL/XGLLoader.cpp
   XGL/XGLLoader.cpp
@@ -635,14 +593,86 @@ ADD_ASSIMP_IMPORTER( FBX
   FBX/FBXCommon.h
   FBX/FBXCommon.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( FBX
-  FBX/FBXExporter.h
-  FBX/FBXExporter.cpp
-  FBX/FBXExportNode.h
-  FBX/FBXExportNode.cpp
-  FBX/FBXExportProperty.h
-  FBX/FBXExportProperty.cpp
-)
+if (NOT ASSIMP_NO_EXPORT)
+
+  ADD_ASSIMP_EXPORTER( OBJ
+    Obj/ObjExporter.h
+    Obj/ObjExporter.cpp)
+
+  ADD_ASSIMP_EXPORTER( OPENGEX
+    OpenGEX/OpenGEXExporter.cpp
+    OpenGEX/OpenGEXExporter.h)
+
+  ADD_ASSIMP_EXPORTER( PLY
+    Ply/PlyExporter.cpp
+    Ply/PlyExporter.h)
+
+  ADD_ASSIMP_EXPORTER( 3DS
+    3DS/3DSExporter.h
+    3DS/3DSExporter.cpp)
+
+  ADD_ASSIMP_EXPORTER( ASSBIN
+    Assbin/AssbinExporter.h
+    Assbin/AssbinExporter.cpp
+    Assbin/AssbinFileWriter.h
+    Assbin/AssbinFileWriter.cpp)
+
+  ADD_ASSIMP_EXPORTER( ASSXML
+    Assxml/AssxmlExporter.h
+    Assxml/AssxmlExporter.cpp
+    Assxml/AssxmlFileWriter.h
+    Assxml/AssxmlFileWriter.cpp)
+
+  ADD_ASSIMP_EXPORTER(M3D
+    M3D/M3DExporter.h
+    M3D/M3DExporter.cpp)
+
+  ADD_ASSIMP_EXPORTER(COLLADA
+    Collada/ColladaExporter.h
+    Collada/ColladaExporter.cpp)
+
+  ADD_ASSIMP_EXPORTER( FBX
+    FBX/FBXExporter.h
+    FBX/FBXExporter.cpp
+    FBX/FBXExportNode.h
+    FBX/FBXExportNode.cpp
+    FBX/FBXExportProperty.h
+    FBX/FBXExportProperty.cpp)
+
+  ADD_ASSIMP_EXPORTER( STL
+    STL/STLExporter.h
+    STL/STLExporter.cpp)
+
+  ADD_ASSIMP_EXPORTER( X
+    X/XFileExporter.h
+    X/XFileExporter.cpp)
+
+  ADD_ASSIMP_EXPORTER( X3D
+    X3D/X3DExporter.cpp
+    X3D/X3DExporter.hpp)
+
+  ADD_ASSIMP_EXPORTER( GLTF
+    glTF/glTFExporter.h
+    glTF/glTFExporter.cpp
+    glTF2/glTF2Exporter.h
+    glTF2/glTF2Exporter.cpp)
+
+  ADD_ASSIMP_EXPORTER( 3MF
+    3MF/D3MFExporter.h
+    3MF/D3MFExporter.cpp)
+
+  ADD_ASSIMP_EXPORTER( ASSJSON
+    Assjson/cencode.c
+    Assjson/cencode.h
+    Assjson/json_exporter.cpp
+    Assjson/mesh_splitter.cpp
+    Assjson/mesh_splitter.h)
+
+  ADD_ASSIMP_EXPORTER( STEP
+    Step/StepExporter.h
+    Step/StepExporter.cpp)
+
+endif()
 
 
 SET( PostProcessing_SRCS
 SET( PostProcessing_SRCS
   PostProcessing/CalcTangentsProcess.cpp
   PostProcessing/CalcTangentsProcess.cpp
@@ -705,6 +735,8 @@ SET( PostProcessing_SRCS
   PostProcessing/ArmaturePopulate.h
   PostProcessing/ArmaturePopulate.h
   PostProcessing/GenBoundingBoxesProcess.cpp
   PostProcessing/GenBoundingBoxesProcess.cpp
   PostProcessing/GenBoundingBoxesProcess.h
   PostProcessing/GenBoundingBoxesProcess.h
+  PostProcessing/SplitByBoneCountProcess.cpp
+  PostProcessing/SplitByBoneCountProcess.h
 )
 )
 SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
 SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
 
 
@@ -744,11 +776,6 @@ ADD_ASSIMP_IMPORTER( STL
   STL/STLLoader.h
   STL/STLLoader.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( STL
-  STL/STLExporter.h
-  STL/STLExporter.cpp
-)
-
 ADD_ASSIMP_IMPORTER( TERRAGEN
 ADD_ASSIMP_IMPORTER( TERRAGEN
   Terragen/TerragenLoader.cpp
   Terragen/TerragenLoader.cpp
   Terragen/TerragenLoader.h
   Terragen/TerragenLoader.h
@@ -767,11 +794,6 @@ ADD_ASSIMP_IMPORTER( X
   X/XFileParser.h
   X/XFileParser.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( X
-  X/XFileExporter.h
-  X/XFileExporter.cpp
-)
-
 ADD_ASSIMP_IMPORTER( X3D
 ADD_ASSIMP_IMPORTER( X3D
   X3D/X3DImporter.cpp
   X3D/X3DImporter.cpp
   X3D/X3DImporter.hpp
   X3D/X3DImporter.hpp
@@ -792,11 +814,6 @@ ADD_ASSIMP_IMPORTER( X3D
   X3D/X3DVocabulary.cpp
   X3D/X3DVocabulary.cpp
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( X3D
-  X3D/X3DExporter.cpp
-  X3D/X3DExporter.hpp
-)
-
 ADD_ASSIMP_IMPORTER( GLTF
 ADD_ASSIMP_IMPORTER( GLTF
   glTF/glTFCommon.h
   glTF/glTFCommon.h
   glTF/glTFCommon.cpp
   glTF/glTFCommon.cpp
@@ -814,13 +831,6 @@ ADD_ASSIMP_IMPORTER( GLTF
   glTF2/glTF2Importer.h
   glTF2/glTF2Importer.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( GLTF
-  glTF/glTFExporter.h
-  glTF/glTFExporter.cpp
-  glTF2/glTF2Exporter.h
-  glTF2/glTF2Exporter.cpp
-)
-
 ADD_ASSIMP_IMPORTER( 3MF
 ADD_ASSIMP_IMPORTER( 3MF
   3MF/D3MFImporter.h
   3MF/D3MFImporter.h
   3MF/D3MFImporter.cpp
   3MF/D3MFImporter.cpp
@@ -829,11 +839,6 @@ ADD_ASSIMP_IMPORTER( 3MF
   3MF/3MFXmlTags.h
   3MF/3MFXmlTags.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( 3MF
-  3MF/D3MFExporter.h
-  3MF/D3MFExporter.cpp
-)
-
 ADD_ASSIMP_IMPORTER( MMD
 ADD_ASSIMP_IMPORTER( MMD
   MMD/MMDCpp14.h
   MMD/MMDCpp14.h
   MMD/MMDImporter.cpp
   MMD/MMDImporter.cpp
@@ -844,14 +849,6 @@ ADD_ASSIMP_IMPORTER( MMD
   MMD/MMDVmdParser.h
   MMD/MMDVmdParser.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( ASSJSON
-  Assjson/cencode.c
-  Assjson/cencode.h
-  Assjson/json_exporter.cpp
-  Assjson/mesh_splitter.cpp
-  Assjson/mesh_splitter.h
-)
-
 # Workaround for issue #2406 - force problematic large file to be optimized to prevent string table overflow error
 # Workaround for issue #2406 - force problematic large file to be optimized to prevent string table overflow error
 # Used -Os instead of -O2 as previous issues had mentioned, since -Os is roughly speaking -O2, excluding any
 # Used -Os instead of -O2 as previous issues had mentioned, since -Os is roughly speaking -O2, excluding any
 # optimizations that take up extra space. Given that the issue is a string table overflowing, -Os seemed appropriate
 # optimizations that take up extra space. Given that the issue is a string table overflowing, -Os seemed appropriate
@@ -874,11 +871,6 @@ ADD_ASSIMP_IMPORTER( STEP
     Importer/StepFile/StepReaderGen.h
     Importer/StepFile/StepReaderGen.h
 )
 )
 
 
-ADD_ASSIMP_EXPORTER( STEP
-    Step/StepExporter.h
-    Step/StepExporter.cpp
-)
-
 if ((NOT ASSIMP_NO_EXPORT) OR (NOT ASSIMP_EXPORTERS_ENABLED STREQUAL ""))
 if ((NOT ASSIMP_NO_EXPORT) OR (NOT ASSIMP_EXPORTERS_ENABLED STREQUAL ""))
 	SET( Exporter_SRCS
 	SET( Exporter_SRCS
 	  Common/Exporter.cpp
 	  Common/Exporter.cpp
@@ -897,35 +889,35 @@ SOURCE_GROUP( Extra FILES ${Extra_SRCS})
 IF(HUNTER_ENABLED)
 IF(HUNTER_ENABLED)
   hunter_add_package(irrXML)
   hunter_add_package(irrXML)
   find_package(irrXML CONFIG REQUIRED)
   find_package(irrXML CONFIG REQUIRED)
-ELSE(HUNTER_ENABLED)
+ELSE()
   # irrXML already included in contrib directory by parent CMakeLists.txt.
   # irrXML already included in contrib directory by parent CMakeLists.txt.
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 # utf8
 # utf8
 IF(HUNTER_ENABLED)
 IF(HUNTER_ENABLED)
   hunter_add_package(utf8)
   hunter_add_package(utf8)
   find_package(utf8 CONFIG REQUIRED)
   find_package(utf8 CONFIG REQUIRED)
-ELSE(HUNTER_ENABLED)
+ELSE()
   # utf8 is header-only, so Assimp doesn't need to do anything.
   # utf8 is header-only, so Assimp doesn't need to do anything.
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 # polyclipping
 # polyclipping
 IF(HUNTER_ENABLED)
 IF(HUNTER_ENABLED)
   hunter_add_package(polyclipping)
   hunter_add_package(polyclipping)
   find_package(polyclipping CONFIG REQUIRED)
   find_package(polyclipping CONFIG REQUIRED)
-ELSE(HUNTER_ENABLED)
+ELSE()
   SET( Clipper_SRCS
   SET( Clipper_SRCS
     ../contrib/clipper/clipper.hpp
     ../contrib/clipper/clipper.hpp
     ../contrib/clipper/clipper.cpp
     ../contrib/clipper/clipper.cpp
   )
   )
   SOURCE_GROUP( Contrib\\Clipper FILES ${Clipper_SRCS})
   SOURCE_GROUP( Contrib\\Clipper FILES ${Clipper_SRCS})
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 # poly2tri
 # poly2tri
 IF(HUNTER_ENABLED)
 IF(HUNTER_ENABLED)
   hunter_add_package(poly2tri)
   hunter_add_package(poly2tri)
   find_package(poly2tri CONFIG REQUIRED)
   find_package(poly2tri CONFIG REQUIRED)
-ELSE(HUNTER_ENABLED)
+ELSE()
   SET( Poly2Tri_SRCS
   SET( Poly2Tri_SRCS
     ../contrib/poly2tri/poly2tri/common/shapes.cc
     ../contrib/poly2tri/poly2tri/common/shapes.cc
     ../contrib/poly2tri/poly2tri/common/shapes.h
     ../contrib/poly2tri/poly2tri/common/shapes.h
@@ -940,13 +932,13 @@ ELSE(HUNTER_ENABLED)
     ../contrib/poly2tri/poly2tri/sweep/sweep_context.h
     ../contrib/poly2tri/poly2tri/sweep/sweep_context.h
   )
   )
   SOURCE_GROUP( Contrib\\Poly2Tri FILES ${Poly2Tri_SRCS})
   SOURCE_GROUP( Contrib\\Poly2Tri FILES ${Poly2Tri_SRCS})
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 # minizip/unzip
 # minizip/unzip
 IF(HUNTER_ENABLED)
 IF(HUNTER_ENABLED)
   hunter_add_package(minizip)
   hunter_add_package(minizip)
   find_package(minizip CONFIG REQUIRED)
   find_package(minizip CONFIG REQUIRED)
-ELSE(HUNTER_ENABLED)
+ELSE()
   SET( unzip_SRCS
   SET( unzip_SRCS
     ../contrib/unzip/crypt.h
     ../contrib/unzip/crypt.h
     ../contrib/unzip/ioapi.c
     ../contrib/unzip/ioapi.c
@@ -955,13 +947,13 @@ ELSE(HUNTER_ENABLED)
     ../contrib/unzip/unzip.h
     ../contrib/unzip/unzip.h
   )
   )
   SOURCE_GROUP(Contrib\\unzip FILES ${unzip_SRCS})
   SOURCE_GROUP(Contrib\\unzip FILES ${unzip_SRCS})
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 # zip (https://github.com/kuba--/zip)
 # zip (https://github.com/kuba--/zip)
 IF(HUNTER_ENABLED)
 IF(HUNTER_ENABLED)
   hunter_add_package(zip)
   hunter_add_package(zip)
   find_package(zip CONFIG REQUIRED)
   find_package(zip CONFIG REQUIRED)
-ELSE(HUNTER_ENABLED)
+ELSE()
   SET( ziplib_SRCS
   SET( ziplib_SRCS
     ../contrib/zip/src/miniz.h
     ../contrib/zip/src/miniz.h
     ../contrib/zip/src/zip.c
     ../contrib/zip/src/zip.c
@@ -976,13 +968,13 @@ ELSE(HUNTER_ENABLED)
   endif()
   endif()
 
 
   SOURCE_GROUP( ziplib FILES ${ziplib_SRCS} )
   SOURCE_GROUP( ziplib FILES ${ziplib_SRCS} )
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 # openddlparser
 # openddlparser
 IF(HUNTER_ENABLED)
 IF(HUNTER_ENABLED)
   hunter_add_package(openddlparser)
   hunter_add_package(openddlparser)
   find_package(openddlparser CONFIG REQUIRED)
   find_package(openddlparser CONFIG REQUIRED)
-ELSE(HUNTER_ENABLED)
+ELSE()
   SET ( openddl_parser_SRCS
   SET ( openddl_parser_SRCS
     ../contrib/openddlparser/code/OpenDDLParser.cpp
     ../contrib/openddlparser/code/OpenDDLParser.cpp
     ../contrib/openddlparser/code/DDLNode.cpp
     ../contrib/openddlparser/code/DDLNode.cpp
@@ -999,12 +991,12 @@ ELSE(HUNTER_ENABLED)
     ../contrib/openddlparser/include/openddlparser/Value.h
     ../contrib/openddlparser/include/openddlparser/Value.h
   )
   )
   SOURCE_GROUP( Contrib\\openddl_parser FILES ${openddl_parser_SRCS})
   SOURCE_GROUP( Contrib\\openddl_parser FILES ${openddl_parser_SRCS})
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 # Open3DGC
 # Open3DGC
 IF(HUNTER_ENABLED)
 IF(HUNTER_ENABLED)
   # Nothing to do, not available in Hunter yet.
   # Nothing to do, not available in Hunter yet.
-ELSE(HUNTER_ENABLED)
+ELSE()
   SET ( open3dgc_SRCS
   SET ( open3dgc_SRCS
     ../contrib/Open3DGC/o3dgcAdjacencyInfo.h
     ../contrib/Open3DGC/o3dgcAdjacencyInfo.h
     ../contrib/Open3DGC/o3dgcArithmeticCodec.cpp
     ../contrib/Open3DGC/o3dgcArithmeticCodec.cpp
@@ -1037,7 +1029,7 @@ ELSE(HUNTER_ENABLED)
     ../contrib/Open3DGC/o3dgcVector.inl
     ../contrib/Open3DGC/o3dgcVector.inl
   )
   )
   SOURCE_GROUP( Contrib\\open3dgc FILES ${open3dgc_SRCS})
   SOURCE_GROUP( Contrib\\open3dgc FILES ${open3dgc_SRCS})
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 # Check dependencies for glTF importer with Open3DGC-compression.
 # Check dependencies for glTF importer with Open3DGC-compression.
 # RT-extensions is used in "contrib/Open3DGC/o3dgcTimer.h" for collecting statistics. Pointed file
 # RT-extensions is used in "contrib/Open3DGC/o3dgcTimer.h" for collecting statistics. Pointed file
@@ -1056,40 +1048,42 @@ ENDIF ()
 IF(HUNTER_ENABLED)
 IF(HUNTER_ENABLED)
   hunter_add_package(RapidJSON)
   hunter_add_package(RapidJSON)
   find_package(RapidJSON CONFIG REQUIRED)
   find_package(RapidJSON CONFIG REQUIRED)
-ELSE(HUNTER_ENABLED)
+ELSE()
   INCLUDE_DIRECTORIES( "../contrib/rapidjson/include" )
   INCLUDE_DIRECTORIES( "../contrib/rapidjson/include" )
   INCLUDE_DIRECTORIES( "../contrib" )
   INCLUDE_DIRECTORIES( "../contrib" )
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 # VC2010 fixes
 # VC2010 fixes
 if(MSVC10)
 if(MSVC10)
   option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
   option( VC10_STDINT_FIX "Fix for VC10 Compiler regarding pstdint.h redefinition errors" OFF )
   if( VC10_STDINT_FIX )
   if( VC10_STDINT_FIX )
     ADD_DEFINITIONS( -D_STDINT )
     ADD_DEFINITIONS( -D_STDINT )
-  endif( VC10_STDINT_FIX )
-endif(MSVC10)
+  endif()
+endif()
 
 
 ADD_DEFINITIONS( -DASSIMP_BUILD_DLL_EXPORT )
 ADD_DEFINITIONS( -DASSIMP_BUILD_DLL_EXPORT )
 
 
 if ( MSVC )
 if ( MSVC )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
-endif ( MSVC )
+endif ()
 
 
 IF(NOT HUNTER_ENABLED)
 IF(NOT HUNTER_ENABLED)
   if (UNZIP_FOUND)
   if (UNZIP_FOUND)
     SET (unzip_compile_SRCS "")
     SET (unzip_compile_SRCS "")
-  else (UNZIP_FOUND)
+  else ()
     SET (unzip_compile_SRCS ${unzip_SRCS})
     SET (unzip_compile_SRCS ${unzip_SRCS})
     INCLUDE_DIRECTORIES( "../contrib/unzip/" )
     INCLUDE_DIRECTORIES( "../contrib/unzip/" )
-  endif (UNZIP_FOUND)
-ENDIF(NOT HUNTER_ENABLED)
+  endif ()
+ENDIF()
 
 
 MESSAGE(STATUS "Enabled importer formats:${ASSIMP_IMPORTERS_ENABLED}")
 MESSAGE(STATUS "Enabled importer formats:${ASSIMP_IMPORTERS_ENABLED}")
 MESSAGE(STATUS "Disabled importer formats:${ASSIMP_IMPORTERS_DISABLED}")
 MESSAGE(STATUS "Disabled importer formats:${ASSIMP_IMPORTERS_DISABLED}")
 
 
-MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}")
-MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}")
+if (NOT ASSIMP_NO_EXPORT)
+  MESSAGE(STATUS "Enabled exporter formats:${ASSIMP_EXPORTERS_ENABLED}")
+  MESSAGE(STATUS "Disabled exporter formats:${ASSIMP_EXPORTERS_DISABLED}")
+endif()
 
 
 SOURCE_GROUP( include\\assimp    FILES ${PUBLIC_HEADERS} )
 SOURCE_GROUP( include\\assimp    FILES ${PUBLIC_HEADERS} )
 
 
@@ -1129,12 +1123,12 @@ IF(NOT HUNTER_ENABLED)
       ${IRRXML_INCLUDE_DIR}
       ${IRRXML_INCLUDE_DIR}
       ../contrib/openddlparser/include
       ../contrib/openddlparser/include
   )
   )
-ENDIF(NOT HUNTER_ENABLED)
+ENDIF()
 
 
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
   SET( assimp_src ${assimp_src} ${C4D_SRCS})
   SET( assimp_src ${assimp_src} ${C4D_SRCS})
   INCLUDE_DIRECTORIES(${C4D_INCLUDES})
   INCLUDE_DIRECTORIES(${C4D_INCLUDES})
-ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+ENDIF ()
 
 
 ADD_LIBRARY( assimp ${assimp_src} )
 ADD_LIBRARY( assimp ${assimp_src} )
 ADD_LIBRARY(assimp::assimp ALIAS assimp)
 ADD_LIBRARY(assimp::assimp ALIAS assimp)
@@ -1158,21 +1152,21 @@ IF(HUNTER_ENABLED)
       utf8::utf8
       utf8::utf8
       zip::zip
       zip::zip
   )
   )
-ELSE(HUNTER_ENABLED)
+ELSE()
   TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ${IRRXML_LIBRARY} )
   TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ${IRRXML_LIBRARY} )
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 
 
 if(ASSIMP_ANDROID_JNIIOSYSTEM)
 if(ASSIMP_ANDROID_JNIIOSYSTEM)
   set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
   set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
   add_subdirectory(../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/ ../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/)
   add_subdirectory(../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/ ../${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/)
   target_link_libraries(assimp android_jniiosystem)
   target_link_libraries(assimp android_jniiosystem)
-endif(ASSIMP_ANDROID_JNIIOSYSTEM)
+endif()
 
 
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
   TARGET_LINK_LIBRARIES(assimp optimized ${C4D_RELEASE_LIBRARIES})
   TARGET_LINK_LIBRARIES(assimp optimized ${C4D_RELEASE_LIBRARIES})
   TARGET_LINK_LIBRARIES(assimp debug ${C4D_DEBUG_LIBRARIES})
   TARGET_LINK_LIBRARIES(assimp debug ${C4D_DEBUG_LIBRARIES})
   TARGET_LINK_LIBRARIES(assimp ${C4D_EXTRA_LIBRARIES})
   TARGET_LINK_LIBRARIES(assimp ${C4D_EXTRA_LIBRARIES})
-ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
+ENDIF ()
 
 
 if( MSVC )
 if( MSVC )
   # in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix
   # in order to prevent DLL hell, each of the DLLs have to be suffixed with the major version and msvc prefix
@@ -1233,8 +1227,8 @@ if (APPLE)
          "../${HEADER_PATH}/Compiler"
          "../${HEADER_PATH}/Compiler"
          assimp.framework/Headers/Compiler
          assimp.framework/Headers/Compiler
       COMMENT "Copying public ./Compiler/ header files to framework bundle's Headers/Compiler/")
       COMMENT "Copying public ./Compiler/ header files to framework bundle's Headers/Compiler/")
-  ENDIF(BUILD_FRAMEWORK)
-ENDIF(APPLE)
+  ENDIF()
+ENDIF()
 
 
 # Build against external unzip, or add ../contrib/unzip so
 # Build against external unzip, or add ../contrib/unzip so
 # assimp can #include "unzip.h"
 # assimp can #include "unzip.h"
@@ -1242,15 +1236,15 @@ IF(NOT HUNTER_ENABLED)
   if (UNZIP_FOUND)
   if (UNZIP_FOUND)
     INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS})
     INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS})
     TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
     TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
-  else (UNZIP_FOUND)
+  else ()
     INCLUDE_DIRECTORIES("../")
     INCLUDE_DIRECTORIES("../")
-  endif (UNZIP_FOUND)
-ENDIF(NOT HUNTER_ENABLED)
+  endif ()
+ENDIF()
 
 
 # Add RT-extension library for glTF importer with Open3DGC-compression.
 # Add RT-extension library for glTF importer with Open3DGC-compression.
 IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC)
 IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC)
   TARGET_LINK_LIBRARIES(assimp ${RT_LIBRARY})
   TARGET_LINK_LIBRARIES(assimp ${RT_LIBRARY})
-ENDIF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC)
+ENDIF ()
 
 
 IF(HUNTER_ENABLED)
 IF(HUNTER_ENABLED)
   INSTALL( TARGETS assimp
   INSTALL( TARGETS assimp
@@ -1261,14 +1255,14 @@ IF(HUNTER_ENABLED)
     FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
     FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
     COMPONENT ${LIBASSIMP_COMPONENT}
     COMPONENT ${LIBASSIMP_COMPONENT}
     INCLUDES DESTINATION "include")
     INCLUDES DESTINATION "include")
-ELSE(HUNTER_ENABLED)
+ELSE()
 INSTALL( TARGETS assimp
 INSTALL( TARGETS assimp
     LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
     LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
     ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
     ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
     RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
     RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
     FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
     FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
     COMPONENT ${LIBASSIMP_COMPONENT})
     COMPONENT ${LIBASSIMP_COMPONENT})
-ENDIF(HUNTER_ENABLED)
+ENDIF()
 INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)
 INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)
 INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev)
 INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev)
 
 
@@ -1276,7 +1270,7 @@ if (ASSIMP_ANDROID_JNIIOSYSTEM)
   INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h
   INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h
     DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
     DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
     COMPONENT assimp-dev)
     COMPONENT assimp-dev)
-ENDIF(ASSIMP_ANDROID_JNIIOSYSTEM)
+ENDIF()
 
 
 if(MSVC AND ASSIMP_INSTALL_PDB)
 if(MSVC AND ASSIMP_INSTALL_PDB)
   # When only the static library is built, these properties must
   # When only the static library is built, these properties must

+ 3 - 4
code/Common/BaseImporter.cpp

@@ -191,7 +191,7 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
     }
     }
 
 
     std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
     std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
-    if (pStream.get() ) {
+    if (pStream) {
         // read 200 characters from the file
         // read 200 characters from the file
         std::unique_ptr<char[]> _buffer (new char[searchBytes+1 /* for the '\0' */]);
         std::unique_ptr<char[]> _buffer (new char[searchBytes+1 /* for the '\0' */]);
         char *buffer( _buffer.get() );
         char *buffer( _buffer.get() );
@@ -283,7 +283,6 @@ std::string BaseImporter::GetExtension( const std::string& file ) {
         return "";
         return "";
     }
     }
 
 
-
     // thanks to Andy Maloney for the hint
     // thanks to Andy Maloney for the hint
     std::string ret = file.substr( pos + 1 );
     std::string ret = file.substr( pos + 1 );
     std::transform( ret.begin(), ret.end(), ret.begin(), ToLower<char>);
     std::transform( ret.begin(), ret.end(), ret.begin(), ToLower<char>);
@@ -309,7 +308,7 @@ std::string BaseImporter::GetExtension( const std::string& file ) {
     };
     };
     magic = reinterpret_cast<const char*>(_magic);
     magic = reinterpret_cast<const char*>(_magic);
     std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
     std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
-    if (pStream.get() ) {
+    if (pStream) {
 
 
         // skip to offset
         // skip to offset
         pStream->Seek(offset,aiOrigin_SET);
         pStream->Seek(offset,aiOrigin_SET);
@@ -603,7 +602,7 @@ unsigned int BatchLoader::AddLoadRequest(const std::string& file,
     }
     }
 
 
     // no, we don't have it. So add it to the queue ...
     // no, we don't have it. So add it to the queue ...
-    m_data->requests.push_back(LoadRequest(file,steps,map, m_data->next_id));
+    m_data->requests.emplace_back(file, steps, map, m_data->next_id);
     return m_data->next_id++;
     return m_data->next_id++;
 }
 }
 
 

+ 16 - 23
code/Common/BaseProcess.cpp

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2020, assimp team
 Copyright (c) 2006-2020, assimp team
 
 
-
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -43,45 +41,43 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 /** @file Implementation of BaseProcess */
 /** @file Implementation of BaseProcess */
 
 
-#include <assimp/BaseImporter.h>
 #include "BaseProcess.h"
 #include "BaseProcess.h"
-#include <assimp/DefaultLogger.hpp>
-#include <assimp/scene.h>
 #include "Importer.h"
 #include "Importer.h"
+#include <assimp/BaseImporter.h>
+#include <assimp/scene.h>
+#include <assimp/DefaultLogger.hpp>
 
 
 using namespace Assimp;
 using namespace Assimp;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 BaseProcess::BaseProcess() AI_NO_EXCEPT
 BaseProcess::BaseProcess() AI_NO_EXCEPT
-: shared()
-, progress()
-{
+        : shared(),
+          progress() {
+    // empty
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-BaseProcess::~BaseProcess()
-{
+BaseProcess::~BaseProcess() {
     // nothing to do here
     // nothing to do here
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void BaseProcess::ExecuteOnScene( Importer* pImp)
-{
-    ai_assert(NULL != pImp && NULL != pImp->Pimpl()->mScene);
+void BaseProcess::ExecuteOnScene(Importer *pImp) {
+    ai_assert( nullptr != pImp );
+    ai_assert( nullptr != pImp->Pimpl()->mScene);
 
 
     progress = pImp->GetProgressHandler();
     progress = pImp->GetProgressHandler();
-    ai_assert(progress);
+    ai_assert(nullptr != progress);
 
 
-    SetupProperties( pImp );
+    SetupProperties(pImp);
 
 
     // catch exceptions thrown inside the PostProcess-Step
     // catch exceptions thrown inside the PostProcess-Step
-    try
-    {
+    try {
         Execute(pImp->Pimpl()->mScene);
         Execute(pImp->Pimpl()->mScene);
 
 
-    } catch( const std::exception& err )    {
+    } catch (const std::exception &err) {
 
 
         // extract error description
         // extract error description
         pImp->Pimpl()->mErrorString = err.what();
         pImp->Pimpl()->mErrorString = err.what();
@@ -94,14 +90,11 @@ void BaseProcess::ExecuteOnScene( Importer* pImp)
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void BaseProcess::SetupProperties(const Importer* /*pImp*/)
-{
+void BaseProcess::SetupProperties(const Importer * /*pImp*/) {
     // the default implementation does nothing
     // the default implementation does nothing
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-bool BaseProcess::RequireVerboseFormat() const
-{
+bool BaseProcess::RequireVerboseFormat() const {
     return true;
     return true;
 }
 }
-

+ 46 - 85
code/Common/BaseProcess.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2020, assimp team
 Copyright (c) 2006-2020, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -44,12 +43,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef INCLUDED_AI_BASEPROCESS_H
 #ifndef INCLUDED_AI_BASEPROCESS_H
 #define INCLUDED_AI_BASEPROCESS_H
 #define INCLUDED_AI_BASEPROCESS_H
 
 
-#include <map>
 #include <assimp/GenericProperty.h>
 #include <assimp/GenericProperty.h>
 
 
+#include <map>
+
 struct aiScene;
 struct aiScene;
 
 
-namespace Assimp    {
+namespace Assimp {
 
 
 class Importer;
 class Importer;
 
 
@@ -60,64 +60,50 @@ class Importer;
  *  to provide additional information to other steps. This is primarily
  *  to provide additional information to other steps. This is primarily
  *  intended for cross-step optimizations.
  *  intended for cross-step optimizations.
  */
  */
-class SharedPostProcessInfo
-{
+class SharedPostProcessInfo {
 public:
 public:
-
-    struct Base
-    {
-        virtual ~Base()
-        {}
+    struct Base {
+        virtual ~Base() {}
     };
     };
 
 
     //! Represents data that is allocated on the heap, thus needs to be deleted
     //! Represents data that is allocated on the heap, thus needs to be deleted
     template <typename T>
     template <typename T>
-    struct THeapData : public Base
-    {
-        explicit THeapData(T* in)
-            : data (in)
-        {}
-
-        ~THeapData()
-        {
+    struct THeapData : public Base {
+        explicit THeapData(T *in) :
+                data(in) {}
+
+        ~THeapData() {
             delete data;
             delete data;
         }
         }
-        T* data;
+        T *data;
     };
     };
 
 
     //! Represents static, by-value data not allocated on the heap
     //! Represents static, by-value data not allocated on the heap
     template <typename T>
     template <typename T>
-    struct TStaticData : public Base
-    {
-        explicit TStaticData(T in)
-            : data (in)
-        {}
+    struct TStaticData : public Base {
+        explicit TStaticData(T in) :
+                data(in) {}
 
 
-        ~TStaticData()
-        {}
+        ~TStaticData() {}
 
 
         T data;
         T data;
     };
     };
 
 
     // some typedefs for cleaner code
     // some typedefs for cleaner code
     typedef unsigned int KeyType;
     typedef unsigned int KeyType;
-    typedef std::map<KeyType, Base*>  PropertyMap;
+    typedef std::map<KeyType, Base *> PropertyMap;
 
 
 public:
 public:
-
     //! Destructor
     //! Destructor
-    ~SharedPostProcessInfo()
-    {
+    ~SharedPostProcessInfo() {
         Clean();
         Clean();
     }
     }
 
 
     //! Remove all stored properties from the table
     //! Remove all stored properties from the table
-    void Clean()
-    {
+    void Clean() {
         // invoke the virtual destructor for all stored properties
         // invoke the virtual destructor for all stored properties
         for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
         for (PropertyMap::iterator it = pmap.begin(), end = pmap.end();
-             it != end; ++it)
-        {
+                it != end; ++it) {
             delete (*it).second;
             delete (*it).second;
         }
         }
         pmap.clear();
         pmap.clear();
@@ -125,24 +111,21 @@ public:
 
 
     //! Add a heap property to the list
     //! Add a heap property to the list
     template <typename T>
     template <typename T>
-    void AddProperty( const char* name, T* in ){
-        AddProperty(name,(Base*)new THeapData<T>(in));
+    void AddProperty(const char *name, T *in) {
+        AddProperty(name, (Base *)new THeapData<T>(in));
     }
     }
 
 
     //! Add a static by-value property to the list
     //! Add a static by-value property to the list
     template <typename T>
     template <typename T>
-    void AddProperty( const char* name, T in ){
-        AddProperty(name,(Base*)new TStaticData<T>(in));
+    void AddProperty(const char *name, T in) {
+        AddProperty(name, (Base *)new TStaticData<T>(in));
     }
     }
 
 
-
     //! Get a heap property
     //! Get a heap property
     template <typename T>
     template <typename T>
-    bool GetProperty( const char* name, T*& out ) const
-    {
-        THeapData<T>* t = (THeapData<T>*)GetPropertyInternal(name);
-        if(!t)
-        {
+    bool GetProperty(const char *name, T *&out) const {
+        THeapData<T> *t = (THeapData<T> *)GetPropertyInternal(name);
+        if (!t) {
             out = NULL;
             out = NULL;
             return false;
             return false;
         }
         }
@@ -152,53 +135,34 @@ public:
 
 
     //! Get a static, by-value property
     //! Get a static, by-value property
     template <typename T>
     template <typename T>
-    bool GetProperty( const char* name, T& out ) const
-    {
-        TStaticData<T>* t = (TStaticData<T>*)GetPropertyInternal(name);
-        if(!t)return false;
+    bool GetProperty(const char *name, T &out) const {
+        TStaticData<T> *t = (TStaticData<T> *)GetPropertyInternal(name);
+        if ( nullptr == t) {
+            return false;
+        }
         out = t->data;
         out = t->data;
         return true;
         return true;
     }
     }
 
 
     //! Remove a property of a specific type
     //! Remove a property of a specific type
-    void RemoveProperty( const char* name)  {
-        SetGenericPropertyPtr<Base>(pmap,name,NULL);
+    void RemoveProperty(const char *name) {
+        SetGenericPropertyPtr<Base>(pmap, name, nullptr );
     }
     }
 
 
 private:
 private:
-
-    void AddProperty( const char* name, Base* data) {
-        SetGenericPropertyPtr<Base>(pmap,name,data);
+    void AddProperty(const char *name, Base *data) {
+        SetGenericPropertyPtr<Base>(pmap, name, data);
     }
     }
 
 
-    Base* GetPropertyInternal( const char* name) const  {
-        return GetGenericProperty<Base*>(pmap,name,NULL);
+    Base *GetPropertyInternal(const char *name) const {
+        return GetGenericProperty<Base *>(pmap, name, nullptr );
     }
     }
 
 
 private:
 private:
-
     //! Map of all stored properties
     //! Map of all stored properties
     PropertyMap pmap;
     PropertyMap pmap;
 };
 };
 
 
-#if 0
-
-// ---------------------------------------------------------------------------
-/** @brief Represents a dependency table for a postprocessing steps.
- *
- *  For future use.
- */
- struct PPDependencyTable
- {
-     unsigned int execute_me_before_these;
-     unsigned int execute_me_after_these;
-     unsigned int only_if_these_are_not_specified;
-     unsigned int mutually_exclusive_with;
- };
-
-#endif
-
-
 #define AI_SPP_SPATIAL_SORT "$Spat"
 #define AI_SPP_SPATIAL_SORT "$Spat"
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
@@ -228,7 +192,7 @@ public:
      * @return true if the process is present in this flag fields,
      * @return true if the process is present in this flag fields,
      *   false if not.
      *   false if not.
     */
     */
-    virtual bool IsActive( unsigned int pFlags) const = 0;
+    virtual bool IsActive(unsigned int pFlags) const = 0;
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Check whether this step expects its input vertex data to be
     /** Check whether this step expects its input vertex data to be
@@ -241,14 +205,14 @@ public:
     * the object pointer will be set to NULL).
     * the object pointer will be set to NULL).
     * @param pImp Importer instance (pImp->mScene must be valid)
     * @param pImp Importer instance (pImp->mScene must be valid)
     */
     */
-    void ExecuteOnScene( Importer* pImp);
+    void ExecuteOnScene(Importer *pImp);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Called prior to ExecuteOnScene().
     /** Called prior to ExecuteOnScene().
     * The function is a request to the process to update its configuration
     * The function is a request to the process to update its configuration
     * basing on the Importer's configuration property list.
     * basing on the Importer's configuration property list.
     */
     */
-    virtual void SetupProperties(const Importer* pImp);
+    virtual void SetupProperties(const Importer *pImp);
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Executes the post processing step on the given imported data.
     /** Executes the post processing step on the given imported data.
@@ -256,35 +220,32 @@ public:
     * This method must be implemented by deriving classes.
     * This method must be implemented by deriving classes.
     * @param pScene The imported data to work at.
     * @param pScene The imported data to work at.
     */
     */
-    virtual void Execute( aiScene* pScene) = 0;
-
+    virtual void Execute(aiScene *pScene) = 0;
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Assign a new SharedPostProcessInfo to the step. This object
     /** Assign a new SharedPostProcessInfo to the step. This object
      *  allows multiple postprocess steps to share data.
      *  allows multiple postprocess steps to share data.
      * @param sh May be NULL
      * @param sh May be NULL
     */
     */
-    inline void SetSharedData(SharedPostProcessInfo* sh)    {
+    inline void SetSharedData(SharedPostProcessInfo *sh) {
         shared = sh;
         shared = sh;
     }
     }
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     /** Get the shared data that is assigned to the step.
     /** Get the shared data that is assigned to the step.
     */
     */
-    inline SharedPostProcessInfo* GetSharedData()   {
+    inline SharedPostProcessInfo *GetSharedData() {
         return shared;
         return shared;
     }
     }
 
 
 protected:
 protected:
-
     /** See the doc of #SharedPostProcessInfo for more details */
     /** See the doc of #SharedPostProcessInfo for more details */
-    SharedPostProcessInfo* shared;
+    SharedPostProcessInfo *shared;
 
 
     /** Currently active progress handler */
     /** Currently active progress handler */
-    ProgressHandler* progress;
+    ProgressHandler *progress;
 };
 };
 
 
-
 } // end of namespace Assimp
 } // end of namespace Assimp
 
 
 #endif // AI_BASEPROCESS_H_INC
 #endif // AI_BASEPROCESS_H_INC

+ 4 - 4
code/Common/Importer.cpp

@@ -1071,7 +1071,7 @@ ai_real Importer::GetPropertyFloat(const char* szName, ai_real iErrorReturn /*=
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Get a configuration property
 // Get a configuration property
-const std::string Importer::GetPropertyString(const char* szName, const std::string& iErrorReturn /*= ""*/) const {
+std::string Importer::GetPropertyString(const char* szName, const std::string& iErrorReturn /*= ""*/) const {
     ai_assert(nullptr != pimpl);
     ai_assert(nullptr != pimpl);
     
     
     return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
     return GetGenericProperty<std::string>(pimpl->mStringProperties,szName,iErrorReturn);
@@ -1079,7 +1079,7 @@ const std::string Importer::GetPropertyString(const char* szName, const std::str
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Get a configuration property
 // Get a configuration property
-const aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const {
+aiMatrix4x4 Importer::GetPropertyMatrix(const char* szName, const aiMatrix4x4& iErrorReturn /*= aiMatrix4x4()*/) const {
     ai_assert(nullptr != pimpl);
     ai_assert(nullptr != pimpl);
     
     
     return GetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties,szName,iErrorReturn);
     return GetGenericProperty<aiMatrix4x4>(pimpl->mMatrixProperties,szName,iErrorReturn);
@@ -1110,10 +1110,9 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const {
     aiScene* mScene = pimpl->mScene;
     aiScene* mScene = pimpl->mScene;
 
 
     // return if we have no scene loaded
     // return if we have no scene loaded
-    if (!pimpl->mScene)
+    if (!mScene)
         return;
         return;
 
 
-
     in.total = sizeof(aiScene);
     in.total = sizeof(aiScene);
 
 
     // add all meshes
     // add all meshes
@@ -1202,5 +1201,6 @@ void Importer::GetMemoryRequirements(aiMemoryInfo& in) const {
             in.materials += pc->mProperties[a]->mDataLength;
             in.materials += pc->mProperties[a]->mDataLength;
         }
         }
     }
     }
+
     in.total += in.materials;
     in.total += in.materials;
 }
 }

+ 1 - 1
code/Common/PostStepRegistry.cpp

@@ -123,7 +123,7 @@ corresponding preprocessor flag to selectively disable steps.
 #   include "PostProcessing/OptimizeGraph.h"
 #   include "PostProcessing/OptimizeGraph.h"
 #endif
 #endif
 #ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS
 #ifndef ASSIMP_BUILD_NO_SPLITBYBONECOUNT_PROCESS
-#   include "Common/SplitByBoneCountProcess.h"
+#   include "PostProcessing/SplitByBoneCountProcess.h"
 #endif
 #endif
 #ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS
 #ifndef ASSIMP_BUILD_NO_DEBONE_PROCESS
 #   include "PostProcessing/DeboneProcess.h"
 #   include "PostProcessing/DeboneProcess.h"

+ 0 - 2
code/Common/ZipArchiveIOSystem.cpp

@@ -343,8 +343,6 @@ namespace Assimp {
     }
     }
 
 
     ZipArchiveIOSystem::Implement::~Implement() {
     ZipArchiveIOSystem::Implement::~Implement() {
-        m_ArchiveMap.clear();
-
         if (m_ZipFileHandle != nullptr) {
         if (m_ZipFileHandle != nullptr) {
             unzClose(m_ZipFileHandle);
             unzClose(m_ZipFileHandle);
             m_ZipFileHandle = nullptr;
             m_ZipFileHandle = nullptr;

+ 5 - 6
code/FBX/FBXMeshGeometry.cpp

@@ -446,20 +446,19 @@ void ResolveVertexDataArray(std::vector<T>& data_out, const Scope& source,
             return;
             return;
         }
         }
         std::vector<T> tempData;
         std::vector<T> tempData;
-		ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
+        ParseVectorDataArray(tempData, GetRequiredElement(source, dataElementName));
 
 
-        if (tempData.size() != vertex_count) {
+        if (tempData.size() != mapping_offsets.size()) {
             FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ")
             FBXImporter::LogError(Formatter::format("length of input data unexpected for ByVertice mapping: ")
-                                  << tempData.size() << ", expected " << vertex_count);
+                                  << tempData.size() << ", expected " << mapping_offsets.size());
             return;
             return;
         }
         }
 
 
         data_out.resize(vertex_count);
         data_out.resize(vertex_count);
-		for (size_t i = 0, e = tempData.size(); i < e; ++i) {
-
+        for (size_t i = 0, e = tempData.size(); i < e; ++i) {
             const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
             const unsigned int istart = mapping_offsets[i], iend = istart + mapping_counts[i];
             for (unsigned int j = istart; j < iend; ++j) {
             for (unsigned int j = istart; j < iend; ++j) {
-				data_out[mappings[j]] = tempData[i];
+                data_out[mappings[j]] = tempData[i];
             }
             }
         }
         }
     }
     }

+ 63 - 27
code/M3D/M3DImporter.cpp

@@ -109,7 +109,9 @@ using namespace std;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //  Default constructor
 //  Default constructor
 M3DImporter::M3DImporter() :
 M3DImporter::M3DImporter() :
-		mScene(nullptr) {}
+		mScene(nullptr) {
+			// empty
+		}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //  Returns true, if file is a binary or ASCII Model 3D file.
 //  Returns true, if file is a binary or ASCII Model 3D file.
@@ -225,7 +227,7 @@ void M3DImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSys
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // convert materials. properties are converted using a static table in M3DMaterials.h
 // convert materials. properties are converted using a static table in M3DMaterials.h
-void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) {
+void M3DImporter::importMaterials(const M3DWrapper &m3d) {
 	unsigned int i, j, k, l, n;
 	unsigned int i, j, k, l, n;
 	m3dm_t *m;
 	m3dm_t *m;
 	aiString name = aiString(AI_DEFAULT_MATERIAL_NAME);
 	aiString name = aiString(AI_DEFAULT_MATERIAL_NAME);
@@ -233,9 +235,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) {
 	ai_real f;
 	ai_real f;
 
 
 	ai_assert(mScene != nullptr);
 	ai_assert(mScene != nullptr);
-	ai_assert(m3d_wrap);
+	ai_assert(m3d);
 
 
-	mScene->mNumMaterials = m3d_wrap->nummaterial + 1;
+	mScene->mNumMaterials = m3d->nummaterial + 1;
 	mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials];
 	mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials];
 
 
 	ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials);
 	ASSIMP_LOG_DEBUG_F("M3D: importMaterials ", mScene->mNumMaterials);
@@ -248,8 +250,12 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) {
 	mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE);
 	mat->AddProperty(&c, 1, AI_MATKEY_COLOR_DIFFUSE);
 	mScene->mMaterials[0] = mat;
 	mScene->mMaterials[0] = mat;
 
 
-	for (i = 0; i < m3d_wrap->nummaterial; i++) {
-		m = &m3d_wrap->material[i];
+	if (!m3d->nummaterial || !m3d->material) {
+		return;
+	}
+
+	for (i = 0; i < m3d->nummaterial; i++) {
+		m = &m3d->material[i];
 		aiMaterial *mat = new aiMaterial;
 		aiMaterial *mat = new aiMaterial;
 		name.Set(std::string(m->name));
 		name.Set(std::string(m->name));
 		mat->AddProperty(&name, AI_MATKEY_NAME);
 		mat->AddProperty(&name, AI_MATKEY_NAME);
@@ -294,9 +300,9 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) {
 			// texture map properties
 			// texture map properties
 			if (m->prop[j].type >= 128 && aiTxProps[k].pKey &&
 			if (m->prop[j].type >= 128 && aiTxProps[k].pKey &&
 					// extra check, should never happen, do we have the refered texture?
 					// extra check, should never happen, do we have the refered texture?
-					m->prop[j].value.textureid < m3d_wrap->numtexture &&
-					m3d_wrap->texture[m->prop[j].value.textureid].name) {
-				name.Set(std::string(std::string(m3d_wrap->texture[m->prop[j].value.textureid].name) + ".png"));
+					m->prop[j].value.textureid < m3d->numtexture &&
+					m3d->texture[m->prop[j].value.textureid].name) {
+				name.Set(std::string(std::string(m3d->texture[m->prop[j].value.textureid].name) + ".png"));
 				mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index);
 				mat->AddProperty(&name, aiTxProps[k].pKey, aiTxProps[k].type, aiTxProps[k].index);
 				n = 0;
 				n = 0;
 				mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index);
 				mat->AddProperty(&n, 1, _AI_MATKEY_UVWSRC_BASE, aiProps[k].type, aiProps[k].index);
@@ -310,7 +316,12 @@ void M3DImporter::importMaterials(const M3DWrapper &m3d_wrap) {
 // import textures, this is the simplest of all
 // import textures, this is the simplest of all
 void M3DImporter::importTextures(const M3DWrapper &m3d) {
 void M3DImporter::importTextures(const M3DWrapper &m3d) {
 	unsigned int i;
 	unsigned int i;
-	const char *formatHint[] = { "rgba0800", "rgba0808", "rgba8880", "rgba8888" };
+	const char *formatHint[] = {
+		"rgba0800",
+		"rgba0808",
+		"rgba8880",
+		"rgba8888"
+	};
 	m3dtx_t *t;
 	m3dtx_t *t;
 
 
 	ai_assert(mScene != nullptr);
 	ai_assert(mScene != nullptr);
@@ -319,8 +330,9 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) {
 	mScene->mNumTextures = m3d->numtexture;
 	mScene->mNumTextures = m3d->numtexture;
 	ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures);
 	ASSIMP_LOG_DEBUG_F("M3D: importTextures ", mScene->mNumTextures);
 
 
-	if (!m3d->numtexture)
+	if (!m3d->numtexture || !m3d->texture) {
 		return;
 		return;
+	}
 
 
 	mScene->mTextures = new aiTexture *[m3d->numtexture];
 	mScene->mTextures = new aiTexture *[m3d->numtexture];
 	for (i = 0; i < m3d->numtexture; i++) {
 	for (i = 0; i < m3d->numtexture; i++) {
@@ -371,7 +383,13 @@ void M3DImporter::importTextures(const M3DWrapper &m3d) {
 // individually. In assimp there're per mesh vertex and UV lists, and they must be
 // individually. In assimp there're per mesh vertex and UV lists, and they must be
 // indexed simultaneously.
 // indexed simultaneously.
 void M3DImporter::importMeshes(const M3DWrapper &m3d) {
 void M3DImporter::importMeshes(const M3DWrapper &m3d) {
-	unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX;
+	ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface);
+
+	if (!m3d->numface || !m3d->face || !m3d->numvertex || !m3d->vertex) {
+		return;
+	}
+
+    unsigned int i, j, k, l, numpoly = 3, lastMat = M3D_INDEXMAX;
 	std::vector<aiMesh *> *meshes = new std::vector<aiMesh *>();
 	std::vector<aiMesh *> *meshes = new std::vector<aiMesh *>();
 	std::vector<aiFace> *faces = nullptr;
 	std::vector<aiFace> *faces = nullptr;
 	std::vector<aiVector3D> *vertices = nullptr;
 	std::vector<aiVector3D> *vertices = nullptr;
@@ -385,7 +403,6 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) {
 	ai_assert(m3d);
 	ai_assert(m3d);
 	ai_assert(mScene->mRootNode != nullptr);
 	ai_assert(mScene->mRootNode != nullptr);
 
 
-	ASSIMP_LOG_DEBUG_F("M3D: importMeshes ", m3d->numface);
 
 
 	for (i = 0; i < m3d->numface; i++) {
 	for (i = 0; i < m3d->numface; i++) {
 		// we must switch mesh if material changes
 		// we must switch mesh if material changes
@@ -420,6 +437,7 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) {
 			k = static_cast<unsigned int>(vertices->size());
 			k = static_cast<unsigned int>(vertices->size());
 			pFace->mIndices[j] = k;
 			pFace->mIndices[j] = k;
 			l = m3d->face[i].vertex[j];
 			l = m3d->face[i].vertex[j];
+			if(l >= m3d->numvertex) continue;
 			pos.x = m3d->vertex[l].x;
 			pos.x = m3d->vertex[l].x;
 			pos.y = m3d->vertex[l].y;
 			pos.y = m3d->vertex[l].y;
 			pos.z = m3d->vertex[l].z;
 			pos.z = m3d->vertex[l].z;
@@ -432,14 +450,14 @@ void M3DImporter::importMeshes(const M3DWrapper &m3d) {
 				vertexids->push_back(l);
 				vertexids->push_back(l);
 			}
 			}
 			l = m3d->face[i].texcoord[j];
 			l = m3d->face[i].texcoord[j];
-			if (l != M3D_UNDEF) {
+			if (l != M3D_UNDEF && l < m3d->numtmap) {
 				uv.x = m3d->tmap[l].u;
 				uv.x = m3d->tmap[l].u;
 				uv.y = m3d->tmap[l].v;
 				uv.y = m3d->tmap[l].v;
 				uv.z = 0.0;
 				uv.z = 0.0;
 				texcoords->push_back(uv);
 				texcoords->push_back(uv);
 			}
 			}
 			l = m3d->face[i].normal[j];
 			l = m3d->face[i].normal[j];
-			if (l != M3D_UNDEF) {
+			if (l != M3D_UNDEF && l < m3d->numvertex) {
 				norm.x = m3d->vertex[l].x;
 				norm.x = m3d->vertex[l].x;
 				norm.y = m3d->vertex[l].y;
 				norm.y = m3d->vertex[l].y;
 				norm.z = m3d->vertex[l].z;
 				norm.z = m3d->vertex[l].z;
@@ -487,8 +505,15 @@ void M3DImporter::importBones(const M3DWrapper &m3d, unsigned int parentid, aiNo
 
 
 	ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid);
 	ASSIMP_LOG_DEBUG_F("M3D: importBones ", m3d->numbone, " parentid ", (int)parentid);
 
 
-	for (n = 0, i = parentid + 1; i < m3d->numbone; i++)
-		if (m3d->bone[i].parent == parentid) n++;
+	if (!m3d->numbone || !m3d->bone) {
+		return;
+	}
+
+	for (n = 0, i = parentid + 1; i < m3d->numbone; i++) {
+		if (m3d->bone[i].parent == parentid) {
+			n++;
+		}
+	}
 	pParent->mChildren = new aiNode *[n];
 	pParent->mChildren = new aiNode *[n];
 
 
 	for (i = parentid + 1; i < m3d->numbone; i++) {
 	for (i = parentid + 1; i < m3d->numbone; i++) {
@@ -521,8 +546,9 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) {
 
 
 	ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations);
 	ASSIMP_LOG_DEBUG_F("M3D: importAnimations ", mScene->mNumAnimations);
 
 
-	if (!m3d->numaction || !m3d->numbone)
+	if (!m3d->numaction || !m3d->action || !m3d->numbone || !m3d->bone || !m3d->vertex) {
 		return;
 		return;
+	}
 
 
 	mScene->mAnimations = new aiAnimation *[m3d->numaction];
 	mScene->mAnimations = new aiAnimation *[m3d->numaction];
 	for (i = 0; i < m3d->numaction; i++) {
 	for (i = 0; i < m3d->numaction; i++) {
@@ -552,6 +578,7 @@ void M3DImporter::importAnimations(const M3DWrapper &m3d) {
 						ori = a->frame[j].transform[k].ori;
 						ori = a->frame[j].transform[k].ori;
 					}
 					}
 				}
 				}
+				if(pos >= m3d->numvertex || ori >= m3d->numvertex) continue;
 				m3dv_t *v = &m3d->vertex[pos];
 				m3dv_t *v = &m3d->vertex[pos];
 				m3dv_t *q = &m3d->vertex[ori];
 				m3dv_t *q = &m3d->vertex[ori];
 				pAnim->mChannels[l]->mPositionKeys[j].mTime = t;
 				pAnim->mChannels[l]->mPositionKeys[j].mTime = t;
@@ -587,6 +614,8 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in
 	ai_assert(m3d);
 	ai_assert(m3d);
 	ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex);
 	ai_assert(posid != M3D_UNDEF && posid < m3d->numvertex);
 	ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex);
 	ai_assert(orientid != M3D_UNDEF && orientid < m3d->numvertex);
+	if (!m3d->numvertex || !m3d->vertex)
+		return;
 	m3dv_t *p = &m3d->vertex[posid];
 	m3dv_t *p = &m3d->vertex[posid];
 	m3dv_t *q = &m3d->vertex[orientid];
 	m3dv_t *q = &m3d->vertex[orientid];
 
 
@@ -629,16 +658,18 @@ void M3DImporter::convertPose(const M3DWrapper &m3d, aiMatrix4x4 *m, unsigned in
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // find a node by name
 // find a node by name
 aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) {
 aiNode *M3DImporter::findNode(aiNode *pNode, aiString name) {
-	unsigned int i;
-
 	ai_assert(pNode != nullptr);
 	ai_assert(pNode != nullptr);
 	ai_assert(mScene != nullptr);
 	ai_assert(mScene != nullptr);
 
 
-	if (pNode->mName == name)
+	if (pNode->mName == name) {
 		return pNode;
 		return pNode;
-	for (i = 0; i < pNode->mNumChildren; i++) {
+	}
+
+	for (unsigned int i = 0; i < pNode->mNumChildren; i++) {
 		aiNode *pChild = findNode(pNode->mChildren[i], name);
 		aiNode *pChild = findNode(pNode->mChildren[i], name);
-		if (pChild) return pChild;
+		if (pChild) {
+			return pChild;
+		}
 	}
 	}
 	return nullptr;
 	return nullptr;
 }
 }
@@ -700,8 +731,8 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector
 		// this is complicated, because M3D stores a list of bone id / weight pairs per
 		// this is complicated, because M3D stores a list of bone id / weight pairs per
 		// vertex but assimp uses lists of local vertex id/weight pairs per local bone list
 		// vertex but assimp uses lists of local vertex id/weight pairs per local bone list
 		pMesh->mNumBones = m3d->numbone;
 		pMesh->mNumBones = m3d->numbone;
-		/* we need aiBone with mOffsetMatrix for bones without weights as well */
-		if (pMesh->mNumBones) {
+		// we need aiBone with mOffsetMatrix for bones without weights as well
+		if (pMesh->mNumBones && m3d->numbone && m3d->bone) {
 			pMesh->mBones = new aiBone *[pMesh->mNumBones];
 			pMesh->mBones = new aiBone *[pMesh->mNumBones];
 			for (unsigned int i = 0; i < m3d->numbone; i++) {
 			for (unsigned int i = 0; i < m3d->numbone; i++) {
 				aiNode *pNode;
 				aiNode *pNode;
@@ -715,10 +746,13 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector
 				} else
 				} else
 					pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4();
 					pMesh->mBones[i]->mOffsetMatrix = aiMatrix4x4();
 			}
 			}
-			if (vertexids->size()) {
+			if (vertexids->size() && m3d->numvertex && m3d->vertex && m3d->numskin && m3d->skin) {
 				unsigned int i, j;
 				unsigned int i, j;
 				// first count how many vertices we have per bone
 				// first count how many vertices we have per bone
 				for (i = 0; i < vertexids->size(); i++) {
 				for (i = 0; i < vertexids->size(); i++) {
+					if(vertexids->at(i) >= m3d->numvertex) {
+						continue;
+					}
 					unsigned int s = m3d->vertex[vertexids->at(i)].skinid;
 					unsigned int s = m3d->vertex[vertexids->at(i)].skinid;
 					if (s != M3D_UNDEF && s != M3D_INDEXMAX) {
 					if (s != M3D_UNDEF && s != M3D_INDEXMAX) {
 						for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) {
 						for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) {
@@ -742,9 +776,11 @@ void M3DImporter::populateMesh(const M3DWrapper &m3d, aiMesh *pMesh, std::vector
 				}
 				}
 				// fill up with data
 				// fill up with data
 				for (i = 0; i < vertexids->size(); i++) {
 				for (i = 0; i < vertexids->size(); i++) {
+					if(vertexids->at(i) >= m3d->numvertex) continue;
 					unsigned int s = m3d->vertex[vertexids->at(i)].skinid;
 					unsigned int s = m3d->vertex[vertexids->at(i)].skinid;
-					if (s != M3D_UNDEF && s != M3D_INDEXMAX) {
+					if (s != M3D_UNDEF && s != M3D_INDEXMAX && s < m3d->numskin) {
 						for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) {
 						for (unsigned int k = 0; k < M3D_NUMBONE && m3d->skin[s].weight[k] > 0.0; k++) {
+							if(m3d->skin[s].boneid[k] >= m3d->numbone) continue;
 							aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name));
 							aiString name = aiString(std::string(m3d->bone[m3d->skin[s].boneid[k]].name));
 							for (j = 0; j < pMesh->mNumBones; j++) {
 							for (j = 0; j < pMesh->mNumBones; j++) {
 								if (pMesh->mBones[j]->mName == name) {
 								if (pMesh->mBones[j]->mName == name) {

+ 4 - 11
code/Obj/ObjFileData.h

@@ -110,10 +110,7 @@ struct Object {
     std::vector<unsigned int> m_Meshes;
     std::vector<unsigned int> m_Meshes;
 
 
     //! \brief  Default constructor
     //! \brief  Default constructor
-    Object() 
-    : m_strObjName("") {
-        // empty
-    }
+    Object() = default;
 
 
     //! \brief  Destructor
     //! \brief  Destructor
     ~Object() {
     ~Object() {
@@ -191,16 +188,12 @@ struct Material {
     ,   illumination_model (1)
     ,   illumination_model (1)
     ,   ior     ( ai_real( 1.0 ) )
     ,   ior     ( ai_real( 1.0 ) )
     ,   transparent( ai_real( 1.0), ai_real (1.0), ai_real(1.0)) {
     ,   transparent( ai_real( 1.0), ai_real (1.0), ai_real(1.0)) {
-        // empty
-        for (size_t i = 0; i < TextureTypeCount; ++i) {
-            clamp[ i ] = false;
-        }
+
+	    std::fill_n(clamp, static_cast<unsigned int>(TextureTypeCount), false);
     }
     }
 
 
     // Destructor
     // Destructor
-    ~Material() {
-        // empty
-    }
+    ~Material() = default;
 };
 };
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 22 - 27
code/Obj/ObjFileImporter.cpp

@@ -175,15 +175,15 @@ void ObjFileImporter::CreateDataFromImport(const ObjFile::Model* pModel, aiScene
         ai_assert(false);
         ai_assert(false);
     }
     }
 
 
-    if (pModel->m_Objects.size() > 0) {
+    if (!pModel->m_Objects.empty()) {
 
 
         unsigned int meshCount = 0;
         unsigned int meshCount = 0;
         unsigned int childCount = 0;
         unsigned int childCount = 0;
 
 
-        for(size_t index = 0; index < pModel->m_Objects.size(); ++index) {
-            if(pModel->m_Objects[index]) {
+        for (auto object : pModel->m_Objects) {
+            if(object) {
                 ++childCount;
                 ++childCount;
-                meshCount += (unsigned int)pModel->m_Objects[index]->m_Meshes.size();
+                meshCount += (unsigned int)object->m_Meshes.size();
             }
             }
         }
         }
 
 
@@ -365,8 +365,8 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
         unsigned int outIndex( 0 );
         unsigned int outIndex( 0 );
 
 
         // Copy all data from all stored meshes
         // Copy all data from all stored meshes
-        for (size_t index = 0; index < pObjMesh->m_Faces.size(); index++) {
-            ObjFile::Face* const inp = pObjMesh->m_Faces[ index ];
+        for (auto& face : pObjMesh->m_Faces) {
+            ObjFile::Face* const inp = face;
             if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
             if (inp->m_PrimitiveType == aiPrimitiveType_LINE) {
                 for(size_t i = 0; i < inp->m_vertices.size() - 1; ++i) {
                 for(size_t i = 0; i < inp->m_vertices.size() - 1; ++i) {
                     aiFace& f = pMesh->mFaces[ outIndex++ ];
                     aiFace& f = pMesh->mFaces[ outIndex++ ];
@@ -385,7 +385,7 @@ aiMesh *ObjFileImporter::createTopology( const ObjFile::Model* pModel, const Obj
             }
             }
 
 
             aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
             aiFace *pFace = &pMesh->mFaces[ outIndex++ ];
-            const unsigned int uiNumIndices = (unsigned int) pObjMesh->m_Faces[ index ]->m_vertices.size();
+            const unsigned int uiNumIndices = (unsigned int) face->m_vertices.size();
             uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
             uiIdxCount += pFace->mNumIndices = (unsigned int) uiNumIndices;
             if (pFace->mNumIndices > 0) {
             if (pFace->mNumIndices > 0) {
                 pFace->mIndices = new unsigned int[ uiNumIndices ];
                 pFace->mIndices = new unsigned int[ uiNumIndices ];
@@ -446,13 +446,10 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
     // Copy vertices, normals and textures into aiMesh instance
     // Copy vertices, normals and textures into aiMesh instance
     bool normalsok = true, uvok = true;
     bool normalsok = true, uvok = true;
     unsigned int newIndex = 0, outIndex = 0;
     unsigned int newIndex = 0, outIndex = 0;
-    for ( size_t index=0; index < pObjMesh->m_Faces.size(); index++ ) {
-        // Get source face
-        ObjFile::Face *pSourceFace = pObjMesh->m_Faces[ index ];
-
+    for (auto sourceFace : pObjMesh->m_Faces) {
         // Copy all index arrays
         // Copy all index arrays
-        for ( size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < pSourceFace->m_vertices.size(); vertexIndex++ ) {
-            const unsigned int vertex = pSourceFace->m_vertices.at( vertexIndex );
+        for (size_t vertexIndex = 0, outVertexIndex = 0; vertexIndex < sourceFace->m_vertices.size(); vertexIndex++ ) {
+            const unsigned int vertex = sourceFace->m_vertices.at(vertexIndex );
             if ( vertex >= pModel->m_Vertices.size() ) {
             if ( vertex >= pModel->m_Vertices.size() ) {
                 throw DeadlyImportError( "OBJ: vertex index out of range" );
                 throw DeadlyImportError( "OBJ: vertex index out of range" );
             }
             }
@@ -464,8 +461,8 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
             pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
             pMesh->mVertices[ newIndex ] = pModel->m_Vertices[ vertex ];
 
 
             // Copy all normals
             // Copy all normals
-            if ( normalsok && !pModel->m_Normals.empty() && vertexIndex < pSourceFace->m_normals.size()) {
-                const unsigned int normal = pSourceFace->m_normals.at( vertexIndex );
+            if ( normalsok && !pModel->m_Normals.empty() && vertexIndex < sourceFace->m_normals.size()) {
+                const unsigned int normal = sourceFace->m_normals.at(vertexIndex );
                 if ( normal >= pModel->m_Normals.size() )
                 if ( normal >= pModel->m_Normals.size() )
                 {
                 {
                     normalsok = false;
                     normalsok = false;
@@ -484,9 +481,9 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
             }
             }
 
 
             // Copy all texture coordinates
             // Copy all texture coordinates
-            if ( uvok && !pModel->m_TextureCoord.empty() && vertexIndex < pSourceFace->m_texturCoords.size())
+            if ( uvok && !pModel->m_TextureCoord.empty() && vertexIndex < sourceFace->m_texturCoords.size())
             {
             {
-                const unsigned int tex = pSourceFace->m_texturCoords.at( vertexIndex );
+                const unsigned int tex = sourceFace->m_texturCoords.at(vertexIndex );
 
 
                 if ( tex >= pModel->m_TextureCoord.size() )
                 if ( tex >= pModel->m_TextureCoord.size() )
                 {
                 {
@@ -502,16 +499,16 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
             // Get destination face
             // Get destination face
             aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
             aiFace *pDestFace = &pMesh->mFaces[ outIndex ];
 
 
-            const bool last = ( vertexIndex == pSourceFace->m_vertices.size() - 1 );
-            if (pSourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) {
+            const bool last = (vertexIndex == sourceFace->m_vertices.size() - 1 );
+            if (sourceFace->m_PrimitiveType != aiPrimitiveType_LINE || !last) {
                 pDestFace->mIndices[ outVertexIndex ] = newIndex;
                 pDestFace->mIndices[ outVertexIndex ] = newIndex;
                 outVertexIndex++;
                 outVertexIndex++;
             }
             }
 
 
-            if (pSourceFace->m_PrimitiveType == aiPrimitiveType_POINT) {
+            if (sourceFace->m_PrimitiveType == aiPrimitiveType_POINT) {
                 outIndex++;
                 outIndex++;
                 outVertexIndex = 0;
                 outVertexIndex = 0;
-            } else if (pSourceFace->m_PrimitiveType == aiPrimitiveType_LINE) {
+            } else if (sourceFace->m_PrimitiveType == aiPrimitiveType_LINE) {
                 outVertexIndex = 0;
                 outVertexIndex = 0;
 
 
                 if(!last)
                 if(!last)
@@ -520,7 +517,7 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model* pModel,
                 if (vertexIndex) {
                 if (vertexIndex) {
                     if(!last) {
                     if(!last) {
                         pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
                         pMesh->mVertices[ newIndex+1 ] = pMesh->mVertices[ newIndex ];
-                        if ( !pSourceFace->m_normals.empty() && !pModel->m_Normals.empty()) {
+                        if (!sourceFace->m_normals.empty() && !pModel->m_Normals.empty()) {
                             pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
                             pMesh->mNormals[ newIndex+1 ] = pMesh->mNormals[newIndex ];
                         }
                         }
                         if ( !pModel->m_TextureCoord.empty() ) {
                         if ( !pModel->m_TextureCoord.empty() ) {
@@ -563,13 +560,11 @@ void ObjFileImporter::countObjects(const std::vector<ObjFile::Object*> &rObjects
         return;
         return;
 
 
     iNumMeshes += static_cast<unsigned int>( rObjects.size() );
     iNumMeshes += static_cast<unsigned int>( rObjects.size() );
-    for (std::vector<ObjFile::Object*>::const_iterator it = rObjects.begin();
-        it != rObjects.end();
-        ++it)
+    for (auto object: rObjects)
     {
     {
-        if (!(*it)->m_SubObjects.empty())
+        if (!object->m_SubObjects.empty())
         {
         {
-            countObjects((*it)->m_SubObjects, iNumMeshes);
+            countObjects(object->m_SubObjects, iNumMeshes);
         }
         }
     }
     }
 }
 }

+ 2 - 2
code/Obj/ObjFileMtlImporter.cpp

@@ -274,7 +274,7 @@ void ObjFileMtlImporter::getFloatValue( ai_real &value )
 //  Creates a material from loaded data.
 //  Creates a material from loaded data.
 void ObjFileMtlImporter::createMaterial()
 void ObjFileMtlImporter::createMaterial()
 {
 {
-    std::string line( "" );
+    std::string line;
     while( !IsLineEnd( *m_DataIt ) ) {
     while( !IsLineEnd( *m_DataIt ) ) {
         line += *m_DataIt;
         line += *m_DataIt;
         ++m_DataIt;
         ++m_DataIt;
@@ -282,7 +282,7 @@ void ObjFileMtlImporter::createMaterial()
 
 
     std::vector<std::string> token;
     std::vector<std::string> token;
     const unsigned int numToken = tokenize<std::string>( line, token, " \t" );
     const unsigned int numToken = tokenize<std::string>( line, token, " \t" );
-    std::string name( "" );
+    std::string name;
     if ( numToken == 1 ) {
     if ( numToken == 1 ) {
         name = AI_DEFAULT_MATERIAL_NAME;
         name = AI_DEFAULT_MATERIAL_NAME;
     } else {
     } else {

+ 23 - 25
code/Obj/ObjFileParser.cpp

@@ -53,6 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/material.h>
 #include <assimp/material.h>
 #include <assimp/Importer.hpp>
 #include <assimp/Importer.hpp>
 #include <cstdlib>
 #include <cstdlib>
+#include <memory>
+#include <utility>
 
 
 namespace Assimp {
 namespace Assimp {
 
 
@@ -71,16 +73,16 @@ ObjFileParser::ObjFileParser()
 
 
 ObjFileParser::ObjFileParser( IOStreamBuffer<char> &streamBuffer, const std::string &modelName,
 ObjFileParser::ObjFileParser( IOStreamBuffer<char> &streamBuffer, const std::string &modelName,
                               IOSystem *io, ProgressHandler* progress,
                               IOSystem *io, ProgressHandler* progress,
-                              const std::string &originalObjFileName) :
+                              std::string originalObjFileName) :
     m_DataIt(),
     m_DataIt(),
     m_DataItEnd(),
     m_DataItEnd(),
     m_pModel(nullptr),
     m_pModel(nullptr),
     m_uiLine(0),
     m_uiLine(0),
-    m_pIO( io ),
+    m_pIO(io),
     m_progress(progress),
     m_progress(progress),
-    m_originalObjFileName(originalObjFileName)
+    m_originalObjFileName(std::move(originalObjFileName))
 {
 {
-    std::fill_n(m_buffer,Buffersize,0);
+    std::fill_n(m_buffer, Buffersize,0);
 
 
     // Create the model instance to store all the data
     // Create the model instance to store all the data
     m_pModel.reset(new ObjFile::Model());
     m_pModel.reset(new ObjFile::Model());
@@ -96,7 +98,8 @@ ObjFileParser::ObjFileParser( IOStreamBuffer<char> &streamBuffer, const std::str
     parseFile( streamBuffer );
     parseFile( streamBuffer );
 }
 }
 
 
-ObjFileParser::~ObjFileParser() {
+ObjFileParser::~ObjFileParser()
+{
 }
 }
 
 
 void ObjFileParser::setBuffer( std::vector<char> &buffer ) {
 void ObjFileParser::setBuffer( std::vector<char> &buffer ) {
@@ -128,7 +131,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
             processed = static_cast<unsigned int>(filePos);
             processed = static_cast<unsigned int>(filePos);
             lastFilePos = filePos;
             lastFilePos = filePos;
             progressCounter++;
             progressCounter++;
-            m_progress->UpdateFileRead( processed, progressTotal );
+            m_progress->UpdateFileRead(processed, progressTotal);
         }
         }
 
 
         // parse line
         // parse line
@@ -182,7 +185,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
 
 
                 getNameNoSpace(m_DataIt, m_DataItEnd, name);
                 getNameNoSpace(m_DataIt, m_DataItEnd, name);
 
 
-                size_t nextSpace = name.find(" ");
+                size_t nextSpace = name.find(' ');
                 if (nextSpace != std::string::npos)
                 if (nextSpace != std::string::npos)
                     name = name.substr(0, nextSpace);
                     name = name.substr(0, nextSpace);
 
 
@@ -199,7 +202,7 @@ void ObjFileParser::parseFile( IOStreamBuffer<char> &streamBuffer ) {
 
 
                 getNameNoSpace(m_DataIt, m_DataItEnd, name);
                 getNameNoSpace(m_DataIt, m_DataItEnd, name);
 
 
-                size_t nextSpace = name.find(" ");
+                size_t nextSpace = name.find(' ');
                 if (nextSpace != std::string::npos)
                 if (nextSpace != std::string::npos)
                     name = name.substr(0, nextSpace);
                     name = name.substr(0, nextSpace);
 
 
@@ -274,13 +277,8 @@ static bool isDataDefinitionEnd( const char *tmp ) {
 
 
 static bool isNanOrInf(const char * in) {
 static bool isNanOrInf(const char * in) {
     // Look for "nan" or "inf", case insensitive
     // Look for "nan" or "inf", case insensitive
-    if ((in[0] == 'N' || in[0] == 'n') && ASSIMP_strincmp(in, "nan", 3) == 0) {
-        return true;
-    }
-    else if ((in[0] == 'I' || in[0] == 'i') && ASSIMP_strincmp(in, "inf", 3) == 0) {
-        return true;
-    }
-    return false;
+	return ((in[0] == 'N' || in[0] == 'n') && ASSIMP_strincmp(in, "nan", 3) == 0) ||
+	       ((in[0] == 'I' || in[0] == 'i') && ASSIMP_strincmp(in, "inf", 3) == 0);
 }
 }
 
 
 size_t ObjFileParser::getNumComponentsInDataDefinition() {
 size_t ObjFileParser::getNumComponentsInDataDefinition() {
@@ -341,7 +339,7 @@ size_t ObjFileParser::getTexCoordVector( std::vector<aiVector3D> &point3d_array
     if (!std::isfinite(z))
     if (!std::isfinite(z))
         z = 0;
         z = 0;
 
 
-    point3d_array.push_back( aiVector3D( x, y, z ) );
+    point3d_array.emplace_back( x, y, z );
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
     return numComponents;
     return numComponents;
 }
 }
@@ -357,7 +355,7 @@ void ObjFileParser::getVector3( std::vector<aiVector3D> &point3d_array ) {
     copyNextWord( m_buffer, Buffersize );
     copyNextWord( m_buffer, Buffersize );
     z = ( ai_real ) fast_atof( m_buffer );
     z = ( ai_real ) fast_atof( m_buffer );
 
 
-    point3d_array.push_back( aiVector3D( x, y, z ) );
+    point3d_array.emplace_back( x, y, z );
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
@@ -378,7 +376,7 @@ void ObjFileParser::getHomogeneousVector3( std::vector<aiVector3D> &point3d_arra
     if (w == 0)
     if (w == 0)
       throw DeadlyImportError("OBJ: Invalid component in homogeneous vector (Division by zero)");
       throw DeadlyImportError("OBJ: Invalid component in homogeneous vector (Division by zero)");
 
 
-    point3d_array.push_back( aiVector3D( x/w, y/w, z/w ) );
+    point3d_array.emplace_back( x/w, y/w, z/w );
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
 
 
@@ -393,7 +391,7 @@ void ObjFileParser::getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, st
     copyNextWord( m_buffer, Buffersize );
     copyNextWord( m_buffer, Buffersize );
     z = ( ai_real ) fast_atof( m_buffer );
     z = ( ai_real ) fast_atof( m_buffer );
 
 
-    point3d_array_a.push_back( aiVector3D( x, y, z ) );
+    point3d_array_a.emplace_back( x, y, z );
 
 
     copyNextWord(m_buffer, Buffersize);
     copyNextWord(m_buffer, Buffersize);
     x = (ai_real) fast_atof(m_buffer);
     x = (ai_real) fast_atof(m_buffer);
@@ -404,7 +402,7 @@ void ObjFileParser::getTwoVectors3( std::vector<aiVector3D> &point3d_array_a, st
     copyNextWord( m_buffer, Buffersize );
     copyNextWord( m_buffer, Buffersize );
     z = ( ai_real ) fast_atof( m_buffer );
     z = ( ai_real ) fast_atof( m_buffer );
 
 
-    point3d_array_b.push_back( aiVector3D( x, y, z ) );
+    point3d_array_b.emplace_back( x, y, z );
 
 
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
@@ -417,7 +415,7 @@ void ObjFileParser::getVector2( std::vector<aiVector2D> &point2d_array ) {
     copyNextWord(m_buffer, Buffersize);
     copyNextWord(m_buffer, Buffersize);
     y = (ai_real) fast_atof(m_buffer);
     y = (ai_real) fast_atof(m_buffer);
 
 
-    point2d_array.push_back(aiVector2D(x, y));
+    point2d_array.emplace_back(x, y);
 
 
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
     m_DataIt = skipLine<DataArrayIt>( m_DataIt, m_DataItEnd, m_uiLine );
 }
 }
@@ -439,9 +437,9 @@ void ObjFileParser::getFace( aiPrimitiveType type ) {
 
 
     const bool vt = (!m_pModel->m_TextureCoord.empty());
     const bool vt = (!m_pModel->m_TextureCoord.empty());
     const bool vn = (!m_pModel->m_Normals.empty());
     const bool vn = (!m_pModel->m_Normals.empty());
-    int iStep = 0, iPos = 0;
+    int iPos = 0;
     while ( m_DataIt != m_DataItEnd ) {
     while ( m_DataIt != m_DataItEnd ) {
-        iStep = 1;
+        int iStep = 1;
 
 
         if ( IsLineEnd( *m_DataIt ) ) {
         if ( IsLineEnd( *m_DataIt ) ) {
             break;
             break;
@@ -845,7 +843,7 @@ void ObjFileParser::createMesh( const std::string &meshName )
 bool ObjFileParser::needsNewMesh( const std::string &materialName )
 bool ObjFileParser::needsNewMesh( const std::string &materialName )
 {
 {
     // If no mesh data yet
     // If no mesh data yet
-    if(m_pModel->m_pCurrentMesh == 0)
+    if (m_pModel->m_pCurrentMesh == nullptr)
     {
     {
         return true;
         return true;
     }
     }
@@ -856,7 +854,7 @@ bool ObjFileParser::needsNewMesh( const std::string &materialName )
         && curMatIdx != matIdx
         && curMatIdx != matIdx
         // no need create a new mesh if no faces in current
         // no need create a new mesh if no faces in current
         // lets say 'usemtl' goes straight after 'g'
         // lets say 'usemtl' goes straight after 'g'
-        && m_pModel->m_pCurrentMesh->m_Faces.size() > 0 )
+        && !m_pModel->m_pCurrentMesh->m_Faces.empty() )
     {
     {
         // New material -> only one material per mesh, so we need to create a new
         // New material -> only one material per mesh, so we need to create a new
         // material
         // material

+ 1 - 1
code/Obj/ObjFileParser.h

@@ -78,7 +78,7 @@ public:
     /// @brief  The default constructor.
     /// @brief  The default constructor.
     ObjFileParser();
     ObjFileParser();
     /// @brief  Constructor with data array.
     /// @brief  Constructor with data array.
-    ObjFileParser( IOStreamBuffer<char> &streamBuffer, const std::string &modelName, IOSystem* io, ProgressHandler* progress, const std::string &originalObjFileName);
+    ObjFileParser(IOStreamBuffer<char> &streamBuffer, const std::string &modelName, IOSystem* io, ProgressHandler* progress, std::string originalObjFileName);
     /// @brief  Destructor
     /// @brief  Destructor
     ~ObjFileParser();
     ~ObjFileParser();
     /// @brief  If you want to load in-core data.
     /// @brief  If you want to load in-core data.

+ 40 - 0
code/Common/SplitByBoneCountProcess.cpp → code/PostProcessing/SplitByBoneCountProcess.cpp

@@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include <limits>
 #include <limits>
 #include <assimp/TinyFormatter.h>
 #include <assimp/TinyFormatter.h>
+#include <assimp/Exceptional.h>
 
 
 using namespace Assimp;
 using namespace Assimp;
 using namespace Assimp::Formatter;
 using namespace Assimp::Formatter;
@@ -94,7 +95,10 @@ void SplitByBoneCountProcess::Execute( aiScene* pScene)
     bool isNecessary = false;
     bool isNecessary = false;
     for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
     for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
         if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount )
         if( pScene->mMeshes[a]->mNumBones > mMaxBoneCount )
+        {
             isNecessary = true;
             isNecessary = true;
+            break;
+        }
 
 
     if( !isNecessary )
     if( !isNecessary )
     {
     {
@@ -155,7 +159,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
 {
 {
     // skip if not necessary
     // skip if not necessary
     if( pMesh->mNumBones <= mMaxBoneCount )
     if( pMesh->mNumBones <= mMaxBoneCount )
+    {
         return;
         return;
+    }
 
 
     // necessary optimisation: build a list of all affecting bones for each vertex
     // necessary optimisation: build a list of all affecting bones for each vertex
     // TODO: (thom) maybe add a custom allocator here to avoid allocating tens of thousands of small arrays
     // TODO: (thom) maybe add a custom allocator here to avoid allocating tens of thousands of small arrays
@@ -165,7 +171,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
     {
     {
         const aiBone* bone = pMesh->mBones[a];
         const aiBone* bone = pMesh->mBones[a];
         for( unsigned int b = 0; b < bone->mNumWeights; ++b)
         for( unsigned int b = 0; b < bone->mNumWeights; ++b)
+        {
             vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
             vertexBones[ bone->mWeights[b].mVertexId ].push_back( BoneWeight( a, bone->mWeights[b].mWeight));
+        }
     }
     }
 
 
     unsigned int numFacesHandled = 0;
     unsigned int numFacesHandled = 0;
@@ -189,7 +197,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
         {
         {
             // skip if the face is already stored in a submesh
             // skip if the face is already stored in a submesh
             if( isFaceHandled[a] )
             if( isFaceHandled[a] )
+            {
                 continue;
                 continue;
+            }
 
 
             const aiFace& face = pMesh->mFaces[a];
             const aiFace& face = pMesh->mFaces[a];
             // check every vertex if its bones would still fit into the current submesh
             // check every vertex if its bones would still fit into the current submesh
@@ -201,17 +211,27 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
                     unsigned int boneIndex = vb[c].first;
                     unsigned int boneIndex = vb[c].first;
                     // if the bone is already used in this submesh, it's ok
                     // if the bone is already used in this submesh, it's ok
                     if( isBoneUsed[boneIndex] )
                     if( isBoneUsed[boneIndex] )
+                    {
                         continue;
                         continue;
+                    }
 
 
                     // if it's not used, yet, we would need to add it. Store its bone index
                     // if it's not used, yet, we would need to add it. Store its bone index
                     if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() )
                     if( std::find( newBonesAtCurrentFace.begin(), newBonesAtCurrentFace.end(), boneIndex) == newBonesAtCurrentFace.end() )
+                    {
                         newBonesAtCurrentFace.push_back( boneIndex);
                         newBonesAtCurrentFace.push_back( boneIndex);
+                    }
                 }
                 }
             }
             }
 
 
+            if (newBonesAtCurrentFace.size() > mMaxBoneCount)
+            {
+                throw DeadlyImportError("SplitByBoneCountProcess: Single face requires more bones than specified max bone count!");
+            }
             // leave out the face if the new bones required for this face don't fit the bone count limit anymore
             // leave out the face if the new bones required for this face don't fit the bone count limit anymore
             if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount )
             if( numBones + newBonesAtCurrentFace.size() > mMaxBoneCount )
+            {
                 continue;
                 continue;
+            }
 
 
             // mark all new bones as necessary
             // mark all new bones as necessary
             while( !newBonesAtCurrentFace.empty() )
             while( !newBonesAtCurrentFace.empty() )
@@ -219,7 +239,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
                 unsigned int newIndex = newBonesAtCurrentFace.back();
                 unsigned int newIndex = newBonesAtCurrentFace.back();
                 newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
                 newBonesAtCurrentFace.pop_back(); // this also avoids the deallocation which comes with a clear()
                 if( isBoneUsed[newIndex] )
                 if( isBoneUsed[newIndex] )
+                {
                     continue;
                     continue;
+                }
 
 
                 isBoneUsed[newIndex] = true;
                 isBoneUsed[newIndex] = true;
                 numBones++;
                 numBones++;
@@ -237,7 +259,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
         // create a new mesh to hold this subset of the source mesh
         // create a new mesh to hold this subset of the source mesh
         aiMesh* newMesh = new aiMesh;
         aiMesh* newMesh = new aiMesh;
         if( pMesh->mName.length > 0 )
         if( pMesh->mName.length > 0 )
+        {
             newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size());
             newMesh->mName.Set( format() << pMesh->mName.data << "_sub" << poNewMeshes.size());
+        }
         newMesh->mMaterialIndex = pMesh->mMaterialIndex;
         newMesh->mMaterialIndex = pMesh->mMaterialIndex;
         newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
         newMesh->mPrimitiveTypes = pMesh->mPrimitiveTypes;
         poNewMeshes.push_back( newMesh);
         poNewMeshes.push_back( newMesh);
@@ -247,7 +271,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
         newMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
         newMesh->mNumFaces = static_cast<unsigned int>(subMeshFaces.size());
         newMesh->mVertices = new aiVector3D[newMesh->mNumVertices];
         newMesh->mVertices = new aiVector3D[newMesh->mNumVertices];
         if( pMesh->HasNormals() )
         if( pMesh->HasNormals() )
+        {
             newMesh->mNormals = new aiVector3D[newMesh->mNumVertices];
             newMesh->mNormals = new aiVector3D[newMesh->mNumVertices];
+        }
         if( pMesh->HasTangentsAndBitangents() )
         if( pMesh->HasTangentsAndBitangents() )
         {
         {
             newMesh->mTangents = new aiVector3D[newMesh->mNumVertices];
             newMesh->mTangents = new aiVector3D[newMesh->mNumVertices];
@@ -256,13 +282,17 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
         for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
         for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
         {
         {
             if( pMesh->HasTextureCoords( a) )
             if( pMesh->HasTextureCoords( a) )
+            {
                 newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices];
                 newMesh->mTextureCoords[a] = new aiVector3D[newMesh->mNumVertices];
+            }
             newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
             newMesh->mNumUVComponents[a] = pMesh->mNumUVComponents[a];
         }
         }
         for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
         for( unsigned int a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
         {
         {
             if( pMesh->HasVertexColors( a) )
             if( pMesh->HasVertexColors( a) )
+            {
                 newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices];
                 newMesh->mColors[a] = new aiColor4D[newMesh->mNumVertices];
+            }
         }
         }
 
 
         // and copy over the data, generating faces with linear indices along the way
         // and copy over the data, generating faces with linear indices along the way
@@ -285,7 +315,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
 
 
                 newMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
                 newMesh->mVertices[nvi] = pMesh->mVertices[srcIndex];
                 if( pMesh->HasNormals() )
                 if( pMesh->HasNormals() )
+                {
                     newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
                     newMesh->mNormals[nvi] = pMesh->mNormals[srcIndex];
+                }
                 if( pMesh->HasTangentsAndBitangents() )
                 if( pMesh->HasTangentsAndBitangents() )
                 {
                 {
                     newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
                     newMesh->mTangents[nvi] = pMesh->mTangents[srcIndex];
@@ -294,12 +326,16 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
                 for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c )
                 for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c )
                 {
                 {
                     if( pMesh->HasTextureCoords( c) )
                     if( pMesh->HasTextureCoords( c) )
+                    {
                         newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
                         newMesh->mTextureCoords[c][nvi] = pMesh->mTextureCoords[c][srcIndex];
+                    }
                 }
                 }
                 for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c )
                 for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c )
                 {
                 {
                     if( pMesh->HasVertexColors( c) )
                     if( pMesh->HasVertexColors( c) )
+                    {
                         newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
                         newMesh->mColors[c][nvi] = pMesh->mColors[c][srcIndex];
+                    }
                 }
                 }
 
 
                 nvi++;
                 nvi++;
@@ -316,7 +352,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
         for( unsigned int a = 0; a < pMesh->mNumBones; ++a )
         for( unsigned int a = 0; a < pMesh->mNumBones; ++a )
         {
         {
             if( !isBoneUsed[a] )
             if( !isBoneUsed[a] )
+            {
                 continue;
                 continue;
+            }
 
 
             // create the new bone
             // create the new bone
             const aiBone* srcBone = pMesh->mBones[a];
             const aiBone* srcBone = pMesh->mBones[a];
@@ -340,7 +378,9 @@ void SplitByBoneCountProcess::SplitMesh( const aiMesh* pMesh, std::vector<aiMesh
             {
             {
                 unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
                 unsigned int newBoneIndex = mappedBoneIndex[ bonesOnThisVertex[b].first ];
                 if( newBoneIndex != std::numeric_limits<unsigned int>::max() )
                 if( newBoneIndex != std::numeric_limits<unsigned int>::max() )
+                {
                     newMesh->mBones[newBoneIndex]->mNumWeights++;
                     newMesh->mBones[newBoneIndex]->mNumWeights++;
+                }
             }
             }
         }
         }
 
 

+ 1 - 1
code/Common/SplitByBoneCountProcess.h → code/PostProcessing/SplitByBoneCountProcess.h

@@ -46,7 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_SPLITBYBONECOUNTPROCESS_H_INC
 #define AI_SPLITBYBONECOUNTPROCESS_H_INC
 
 
 #include <vector>
 #include <vector>
-#include "BaseProcess.h"
+#include "Common/BaseProcess.h"
 
 
 #include <assimp/mesh.h>
 #include <assimp/mesh.h>
 #include <assimp/scene.h>
 #include <assimp/scene.h>

+ 3 - 5
code/PostProcessing/TextureTransform.cpp

@@ -92,9 +92,8 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
      *  are applied is - as always - scaling, rotation, translation.
      *  are applied is - as always - scaling, rotation, translation.
      */
      */
 
 
-    char szTemp[512];
-    int rounded = 0;
-
+	int rounded;
+	char szTemp[512];
 
 
     /* Optimize the rotation angle. That's slightly difficult as
     /* Optimize the rotation angle. That's slightly difficult as
      * we have an inprecise floating-point number (when comparing
      * we have an inprecise floating-point number (when comparing
@@ -185,7 +184,6 @@ void TextureTransformStep::PreProcessUVTransform(STransformVecInfo& info)
             info.mTranslation.y = out;
             info.mTranslation.y = out;
         }
         }
     }
     }
-    return;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -428,7 +426,7 @@ void TextureTransformStep::Execute( aiScene* pScene)
         // at the end of the list
         // at the end of the list
         bool ref[AI_MAX_NUMBER_OF_TEXTURECOORDS];
         bool ref[AI_MAX_NUMBER_OF_TEXTURECOORDS];
         for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
         for (unsigned int n = 0; n < AI_MAX_NUMBER_OF_TEXTURECOORDS;++n)
-            ref[n] = (!mesh->mTextureCoords[n] ? true : false);
+            ref[n] = !mesh->mTextureCoords[n];
 
 
         for (it = trafo.begin();it != trafo.end(); ++it)
         for (it = trafo.begin();it != trafo.end(); ++it)
             ref[(*it).uvIndex] = true;
             ref[(*it).uvIndex] = true;

+ 6 - 0
code/PostProcessing/ValidateDataStructure.cpp

@@ -777,6 +777,12 @@ void ValidateDSProcess::Validate( const aiMaterial* pMaterial)
     SearchForInvalidTextures(pMaterial,aiTextureType_DISPLACEMENT);
     SearchForInvalidTextures(pMaterial,aiTextureType_DISPLACEMENT);
     SearchForInvalidTextures(pMaterial,aiTextureType_LIGHTMAP);
     SearchForInvalidTextures(pMaterial,aiTextureType_LIGHTMAP);
     SearchForInvalidTextures(pMaterial,aiTextureType_REFLECTION);
     SearchForInvalidTextures(pMaterial,aiTextureType_REFLECTION);
+    SearchForInvalidTextures(pMaterial,aiTextureType_BASE_COLOR);
+    SearchForInvalidTextures(pMaterial,aiTextureType_NORMAL_CAMERA);
+    SearchForInvalidTextures(pMaterial,aiTextureType_EMISSION_COLOR);
+    SearchForInvalidTextures(pMaterial,aiTextureType_METALNESS);
+    SearchForInvalidTextures(pMaterial,aiTextureType_DIFFUSE_ROUGHNESS);
+    SearchForInvalidTextures(pMaterial,aiTextureType_AMBIENT_OCCLUSION);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 1 - 0
code/glTF/glTFAsset.h

@@ -191,6 +191,7 @@ namespace glTF
     //! Values for the BufferView::target field
     //! Values for the BufferView::target field
     enum BufferViewTarget
     enum BufferViewTarget
     {
     {
+        BufferViewTarget_NONE = 0,
         BufferViewTarget_ARRAY_BUFFER = 34962,
         BufferViewTarget_ARRAY_BUFFER = 34962,
         BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
         BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
     };
     };

+ 3 - 1
code/glTF/glTFAssetWriter.inl

@@ -203,7 +203,9 @@ namespace glTF {
         obj.AddMember("buffer", Value(bv.buffer->id, w.mAl).Move(), w.mAl);
         obj.AddMember("buffer", Value(bv.buffer->id, w.mAl).Move(), w.mAl);
         obj.AddMember("byteOffset", static_cast<uint64_t>(bv.byteOffset), w.mAl);
         obj.AddMember("byteOffset", static_cast<uint64_t>(bv.byteOffset), w.mAl);
         obj.AddMember("byteLength", static_cast<uint64_t>(bv.byteLength), w.mAl);
         obj.AddMember("byteLength", static_cast<uint64_t>(bv.byteLength), w.mAl);
-        obj.AddMember("target", int(bv.target), w.mAl);
+        if (bv.target != BufferViewTarget_NONE) {
+            obj.AddMember("target", int(bv.target), w.mAl);
+        }
     }
     }
 
 
     inline void Write(Value& /*obj*/, Camera& /*c*/, AssetWriter& /*w*/)
     inline void Write(Value& /*obj*/, Camera& /*c*/, AssetWriter& /*w*/)

+ 8 - 12
code/glTF/glTFExporter.cpp

@@ -160,10 +160,7 @@ static void CopyValue(const aiMatrix4x4& v, glTF::mat4& o)
 
 
 static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o)
 static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o)
 {
 {
-    o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4;
-    o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4;
-    o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4;
-    o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4;
+    memcpy(&o, &v, sizeof(aiMatrix4x4));
 }
 }
 
 
 static void IdentityMatrix4(glTF::mat4& o)
 static void IdentityMatrix4(glTF::mat4& o)
@@ -230,9 +227,8 @@ inline void SetAccessorRange(ComponentType compType, Ref<Accessor> acc, void* da
 	}
 	}
 }
 }
 
 
-inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
-    unsigned int count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
-{
+inline Ref<Accessor> ExportData(Asset &a, std::string &meshName, Ref<Buffer> &buffer,
+        unsigned int count, void *data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE) {
     if (!count || !data) return Ref<Accessor>();
     if (!count || !data) return Ref<Accessor>();
 
 
     unsigned int numCompsIn = AttribType::GetNumComponents(typeIn);
     unsigned int numCompsIn = AttribType::GetNumComponents(typeIn);
@@ -251,7 +247,7 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
     bv->buffer = buffer;
     bv->buffer = buffer;
     bv->byteOffset = unsigned(offset);
     bv->byteOffset = unsigned(offset);
     bv->byteLength = length; //! The target that the WebGL buffer should be bound to.
     bv->byteLength = length; //! The target that the WebGL buffer should be bound to.
-    bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER;
+    bv->target = target;
 
 
     // accessor
     // accessor
     Ref<Accessor> acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor"));
     Ref<Accessor> acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor"));
@@ -616,13 +612,13 @@ void glTFExporter::ExportMeshes()
 		// If compression is used then you need parameters of uncompressed region: begin and size. At this step "begin" is stored.
 		// If compression is used then you need parameters of uncompressed region: begin and size. At this step "begin" is stored.
 		if(comp_allow) idx_srcdata_begin = b->byteLength;
 		if(comp_allow) idx_srcdata_begin = b->byteLength;
 
 
-        Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+        Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
 		if (v) p.attributes.position.push_back(v);
 		if (v) p.attributes.position.push_back(v);
 
 
 		/******************** Normals ********************/
 		/******************** Normals ********************/
 		if(comp_allow && (aim->mNormals != 0)) idx_srcdata_normal = b->byteLength;// Store index of normals array.
 		if(comp_allow && (aim->mNormals != 0)) idx_srcdata_normal = b->byteLength;// Store index of normals array.
 
 
-		Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+		Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
 		if (n) p.attributes.normal.push_back(n);
 		if (n) p.attributes.normal.push_back(n);
 
 
 		/************** Texture coordinates **************/
 		/************** Texture coordinates **************/
@@ -639,7 +635,7 @@ void glTFExporter::ExportMeshes()
 
 
 				if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array.
 				if(comp_allow) idx_srcdata_tc.push_back(b->byteLength);// Store index of texture coordinates array.
 
 
-				Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false);
+				Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
 				if (tc) p.attributes.texcoord.push_back(tc);
 				if (tc) p.attributes.texcoord.push_back(tc);
 			}
 			}
 		}
 		}
@@ -657,7 +653,7 @@ void glTFExporter::ExportMeshes()
                 }
                 }
             }
             }
 
 
-			p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, true);
+			p.indices = ExportData(*mAsset, meshId, b, unsigned(indices.size()), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_SHORT, BufferViewTarget_ELEMENT_ARRAY_BUFFER);
 		}
 		}
 
 
         switch (aim->mPrimitiveTypes) {
         switch (aim->mPrimitiveTypes) {

+ 1 - 0
code/glTF/glTFImporter.cpp

@@ -222,6 +222,7 @@ void glTFImporter::ImportMeshes(glTF::Asset& r)
     std::vector<aiMesh*> meshes;
     std::vector<aiMesh*> meshes;
 
 
     unsigned int k = 0;
     unsigned int k = 0;
+    meshOffsets.clear();
 
 
     for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
     for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
         Mesh& mesh = r.meshes[m];
         Mesh& mesh = r.meshes[m];

+ 1 - 0
code/glTF2/glTF2Asset.h

@@ -198,6 +198,7 @@ namespace glTF2
     //! Values for the BufferView::target field
     //! Values for the BufferView::target field
     enum BufferViewTarget
     enum BufferViewTarget
     {
     {
+        BufferViewTarget_NONE = 0,
         BufferViewTarget_ARRAY_BUFFER = 34962,
         BufferViewTarget_ARRAY_BUFFER = 34962,
         BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
         BufferViewTarget_ELEMENT_ARRAY_BUFFER = 34963
     };
     };

+ 4 - 4
code/glTF2/glTF2AssetWriter.inl

@@ -176,13 +176,13 @@ namespace glTF2 {
                 valSampler.AddMember("input", s.input->index, w.mAl);
                 valSampler.AddMember("input", s.input->index, w.mAl);
                 switch (s.interpolation) {
                 switch (s.interpolation) {
                     case Interpolation_LINEAR:
                     case Interpolation_LINEAR:
-                        valSampler.AddMember("path", "LINEAR", w.mAl);
+                        valSampler.AddMember("interpolation", "LINEAR", w.mAl);
                         break;
                         break;
                     case Interpolation_STEP:
                     case Interpolation_STEP:
-                        valSampler.AddMember("path", "STEP", w.mAl);
+                        valSampler.AddMember("interpolation", "STEP", w.mAl);
                         break;
                         break;
                     case Interpolation_CUBICSPLINE:
                     case Interpolation_CUBICSPLINE:
-                        valSampler.AddMember("path", "CUBICSPLINE", w.mAl);
+                        valSampler.AddMember("interpolation", "CUBICSPLINE", w.mAl);
                         break;
                         break;
                 }
                 }
                 valSampler.AddMember("output", s.output->index, w.mAl);
                 valSampler.AddMember("output", s.output->index, w.mAl);
@@ -209,7 +209,7 @@ namespace glTF2 {
         if (bv.byteStride != 0) {
         if (bv.byteStride != 0) {
             obj.AddMember("byteStride", bv.byteStride, w.mAl);
             obj.AddMember("byteStride", bv.byteStride, w.mAl);
         }
         }
-        if (bv.target != 0) {
+        if (bv.target != BufferViewTarget_NONE) {
             obj.AddMember("target", int(bv.target), w.mAl);
             obj.AddMember("target", int(bv.target), w.mAl);
         }
         }
     }
     }

+ 29 - 13
code/glTF2/glTF2Exporter.cpp

@@ -141,10 +141,7 @@ static void CopyValue(const aiMatrix4x4& v, mat4& o) {
 }
 }
 
 
 static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) {
 static void CopyValue(const aiMatrix4x4& v, aiMatrix4x4& o) {
-    o.a1 = v.a1; o.a2 = v.a2; o.a3 = v.a3; o.a4 = v.a4;
-    o.b1 = v.b1; o.b2 = v.b2; o.b3 = v.b3; o.b4 = v.b4;
-    o.c1 = v.c1; o.c2 = v.c2; o.c3 = v.c3; o.c4 = v.c4;
-    o.d1 = v.d1; o.d2 = v.d2; o.d3 = v.d3; o.d4 = v.d4;
+    memcpy(&o, &v, sizeof(aiMatrix4x4));
 }
 }
 
 
 static void IdentityMatrix4(mat4& o) {
 static void IdentityMatrix4(mat4& o) {
@@ -211,7 +208,7 @@ inline void SetAccessorRange(ComponentType compType, Ref<Accessor> acc, void* da
 }
 }
 
 
 inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
 inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& buffer,
-    size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, bool isIndices = false)
+    size_t count, void* data, AttribType::Value typeIn, AttribType::Value typeOut, ComponentType compType, BufferViewTarget target = BufferViewTarget_NONE)
 {
 {
     if (!count || !data) {
     if (!count || !data) {
         return Ref<Accessor>();
         return Ref<Accessor>();
@@ -234,7 +231,7 @@ inline Ref<Accessor> ExportData(Asset& a, std::string& meshName, Ref<Buffer>& bu
     bv->byteOffset = offset;
     bv->byteOffset = offset;
     bv->byteLength = length; //! The target that the WebGL buffer should be bound to.
     bv->byteLength = length; //! The target that the WebGL buffer should be bound to.
     bv->byteStride = 0;
     bv->byteStride = 0;
-    bv->target = isIndices ? BufferViewTarget_ELEMENT_ARRAY_BUFFER : BufferViewTarget_ARRAY_BUFFER;
+    bv->target = target;
 
 
     // accessor
     // accessor
     Ref<Accessor> acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor"));
     Ref<Accessor> acc = a.accessors.Create(a.FindUniqueID(meshName, "accessor"));
@@ -747,7 +744,7 @@ void glTF2Exporter::ExportMeshes()
         p.material = mAsset->materials.Get(aim->mMaterialIndex);
         p.material = mAsset->materials.Get(aim->mMaterialIndex);
 
 
 		/******************* Vertices ********************/
 		/******************* Vertices ********************/
-        Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+		Ref<Accessor> v = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mVertices, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
 		if (v) p.attributes.position.push_back(v);
 		if (v) p.attributes.position.push_back(v);
 
 
 		/******************** Normals ********************/
 		/******************** Normals ********************/
@@ -758,7 +755,7 @@ void glTF2Exporter::ExportMeshes()
             }
             }
         }
         }
 
 
-		Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT);
+		Ref<Accessor> n = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mNormals, AttribType::VEC3, AttribType::VEC3, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
         if (n) p.attributes.normal.push_back(n);
         if (n) p.attributes.normal.push_back(n);
 
 
 		/************** Texture coordinates **************/
 		/************** Texture coordinates **************/
@@ -776,14 +773,14 @@ void glTF2Exporter::ExportMeshes()
             if (aim->mNumUVComponents[i] > 0) {
             if (aim->mNumUVComponents[i] > 0) {
                 AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3;
                 AttribType::Value type = (aim->mNumUVComponents[i] == 2) ? AttribType::VEC2 : AttribType::VEC3;
 
 
-				Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, false);
+				Ref<Accessor> tc = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mTextureCoords[i], AttribType::VEC3, type, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
 				if (tc) p.attributes.texcoord.push_back(tc);
 				if (tc) p.attributes.texcoord.push_back(tc);
 			}
 			}
 		}
 		}
 
 
 		/*************** Vertex colors ****************/
 		/*************** Vertex colors ****************/
 		for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) {
 		for (unsigned int indexColorChannel = 0; indexColorChannel < aim->GetNumColorChannels(); ++indexColorChannel) {
-			Ref<Accessor> c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, false);
+			Ref<Accessor> c = ExportData(*mAsset, meshId, b, aim->mNumVertices, aim->mColors[indexColorChannel], AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT, BufferViewTarget_ARRAY_BUFFER);
 			if (c)
 			if (c)
 				p.attributes.color.push_back(c);
 				p.attributes.color.push_back(c);
 		}
 		}
@@ -799,7 +796,7 @@ void glTF2Exporter::ExportMeshes()
                 }
                 }
             }
             }
 
 
-			p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, true);
+			p.indices = ExportData(*mAsset, meshId, b, indices.size(), &indices[0], AttribType::SCALAR, AttribType::SCALAR, ComponentType_UNSIGNED_INT, BufferViewTarget_ELEMENT_ARRAY_BUFFER);
 		}
 		}
 
 
         switch (aim->mPrimitiveTypes) {
         switch (aim->mPrimitiveTypes) {
@@ -956,8 +953,27 @@ unsigned int glTF2Exporter::ExportNode(const aiNode* n, Ref<Node>& parent)
     node->name = name;
     node->name = name;
 
 
     if (!n->mTransformation.IsIdentity()) {
     if (!n->mTransformation.IsIdentity()) {
-        node->matrix.isPresent = true;
-        CopyValue(n->mTransformation, node->matrix.value);
+		if (mScene->mNumAnimations > 0) {
+			aiQuaternion quaternion;
+			n->mTransformation.Decompose(*reinterpret_cast<aiVector3D *>(&node->scale.value), quaternion, *reinterpret_cast<aiVector3D *>(&node->translation.value));
+
+			aiVector3D vector(static_cast<ai_real>(1.0f), static_cast<ai_real>(1.0f), static_cast<ai_real>(1.0f));
+			if (!reinterpret_cast<aiVector3D *>(&node->scale.value)->Equal(vector)) {
+				node->scale.isPresent = true;
+			}
+			if (!reinterpret_cast<aiVector3D *>(&node->translation.value)->Equal(vector)) {
+				node->translation.isPresent = true;
+			}
+			node->rotation.isPresent = true;
+			node->rotation.value[0] = quaternion.x;
+			node->rotation.value[1] = quaternion.y;
+			node->rotation.value[2] = quaternion.z;
+			node->rotation.value[3] = quaternion.w;
+			node->matrix.isPresent = false;
+		} else {
+			node->matrix.isPresent = true;
+			CopyValue(n->mTransformation, node->matrix.value);
+		}
     }
     }
 
 
     for (unsigned int i = 0; i < n->mNumMeshes; ++i) {
     for (unsigned int i = 0; i < n->mNumMeshes; ++i) {

+ 48 - 35
code/glTF2/glTF2Importer.cpp

@@ -111,8 +111,9 @@ const aiImporterDesc *glTF2Importer::GetInfo() const {
 bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const {
 bool glTF2Importer::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) {
 		glTF2::Asset asset(pIOHandler);
 		glTF2::Asset asset(pIOHandler);
@@ -323,8 +324,9 @@ static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsign
 	for (unsigned i = 0; i < nFaces; ++i) {
 	for (unsigned i = 0; i < nFaces; ++i) {
 		for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
 		for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
 			unsigned idx = faces[i].mIndices[j];
 			unsigned idx = faces[i].mIndices[j];
-			if (idx >= nVerts)
+			if (idx >= nVerts) {
 				return false;
 				return false;
+			}
 		}
 		}
 	}
 	}
 	return true;
 	return true;
@@ -335,6 +337,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
 	std::vector<aiMesh *> meshes;
 	std::vector<aiMesh *> meshes;
 
 
 	unsigned int k = 0;
 	unsigned int k = 0;
+    meshOffsets.clear();
 
 
 	for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
 	for (unsigned int m = 0; m < r.meshes.Size(); ++m) {
 		Mesh &mesh = r.meshes[m];
 		Mesh &mesh = r.meshes[m];
@@ -860,7 +863,19 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
 		if (node.skin) {
 		if (node.skin) {
 			for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) {
 			for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) {
 				aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo];
 				aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo];
-				mesh->mNumBones = static_cast<unsigned int>(node.skin->jointNames.size());
+				unsigned int numBones =static_cast<unsigned int>(node.skin->jointNames.size());
+
+				std::vector<std::vector<aiVertexWeight>> weighting(numBones);
+				BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting);
+
+				unsigned int realNumBones = 0;
+				for (uint32_t i = 0; i < numBones; ++i) {
+					if (weighting[i].size() > 0) {
+						realNumBones++;
+					}
+				}
+
+				mesh->mNumBones = static_cast<unsigned int>(realNumBones);
 				mesh->mBones = new aiBone *[mesh->mNumBones];
 				mesh->mBones = new aiBone *[mesh->mNumBones];
 
 
 				// GLTF and Assimp choose to store bone weights differently.
 				// GLTF and Assimp choose to store bone weights differently.
@@ -872,43 +887,33 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
 				// both because it's somewhat slow and because, for many applications,
 				// both because it's somewhat slow and because, for many applications,
 				// we then need to reconvert the data back into the vertex-to-bone
 				// we then need to reconvert the data back into the vertex-to-bone
 				// mapping which makes things doubly-slow.
 				// mapping which makes things doubly-slow.
-				std::vector<std::vector<aiVertexWeight>> weighting(mesh->mNumBones);
-				BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting);
 
 
 				mat4 *pbindMatrices = nullptr;
 				mat4 *pbindMatrices = nullptr;
 				node.skin->inverseBindMatrices->ExtractData(pbindMatrices);
 				node.skin->inverseBindMatrices->ExtractData(pbindMatrices);
 
 
-				for (uint32_t i = 0; i < mesh->mNumBones; ++i) {
-					aiBone *bone = new aiBone();
-
-					Ref<Node> joint = node.skin->jointNames[i];
-					if (!joint->name.empty()) {
-						bone->mName = joint->name;
-					} else {
-						// Assimp expects each bone to have a unique name.
-						static const std::string kDefaultName = "bone_";
-						char postfix[10] = { 0 };
-						ASSIMP_itoa10(postfix, i);
-						bone->mName = (kDefaultName + postfix);
-					}
-					GetNodeTransform(bone->mOffsetMatrix, *joint);
-
-					CopyValue(pbindMatrices[i], bone->mOffsetMatrix);
-
-					std::vector<aiVertexWeight> &weights = weighting[i];
-
-					bone->mNumWeights = static_cast<uint32_t>(weights.size());
-					if (bone->mNumWeights > 0) {
+				int cb = 0;
+				for (uint32_t i = 0; i < numBones; ++i) {
+					const std::vector<aiVertexWeight> &weights = weighting[i];
+					if (weights.size() > 0) {
+						aiBone *bone = new aiBone();
+
+						Ref<Node> joint = node.skin->jointNames[i];
+						if (!joint->name.empty()) {
+							bone->mName = joint->name;
+						} else {
+							// Assimp expects each bone to have a unique name.
+							static const std::string kDefaultName = "bone_";
+							char postfix[10] = { 0 };
+							ASSIMP_itoa10(postfix, i);
+							bone->mName = (kDefaultName + postfix);
+						}
+						GetNodeTransform(bone->mOffsetMatrix, *joint);
+						CopyValue(pbindMatrices[i], bone->mOffsetMatrix);
+						bone->mNumWeights = static_cast<uint32_t>(weights.size());
 						bone->mWeights = new aiVertexWeight[bone->mNumWeights];
 						bone->mWeights = new aiVertexWeight[bone->mNumWeights];
 						memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight));
 						memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight));
-					} else {
-						// Assimp expects all bones to have at least 1 weight.
-						bone->mWeights = new aiVertexWeight[1];
-						bone->mNumWeights = 1;
-						bone->mWeights->mVertexId = 0;
-						bone->mWeights->mWeight = 0.f;
+						mesh->mBones[cb++] = bone;
 					}
 					}
-					mesh->mBones[i] = bone;
 				}
 				}
 
 
 				if (pbindMatrices) {
 				if (pbindMatrices) {
@@ -925,6 +930,11 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
 
 
 	if (node.camera) {
 	if (node.camera) {
 		pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
 		pScene->mCameras[node.camera.GetIndex()]->mName = ainode->mName;
+		if (node.translation.isPresent) {
+			aiVector3D trans;
+			CopyValue(node.translation.value, trans);
+			pScene->mCameras[node.camera.GetIndex()]->mPosition = trans;
+		}
 	}
 	}
 
 
 	if (node.light) {
 	if (node.light) {
@@ -1226,8 +1236,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
 
 
 	int numEmbeddedTexs = 0;
 	int numEmbeddedTexs = 0;
 	for (size_t i = 0; i < r.images.Size(); ++i) {
 	for (size_t i = 0; i < r.images.Size(); ++i) {
-		if (r.images[i].HasData())
+		if (r.images[i].HasData()) {
 			numEmbeddedTexs += 1;
 			numEmbeddedTexs += 1;
+		}
 	}
 	}
 
 
 	if (numEmbeddedTexs == 0)
 	if (numEmbeddedTexs == 0)
@@ -1238,7 +1249,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
 	// Add the embedded textures
 	// Add the embedded textures
 	for (size_t i = 0; i < r.images.Size(); ++i) {
 	for (size_t i = 0; i < r.images.Size(); ++i) {
 		Image &img = r.images[i];
 		Image &img = r.images[i];
-		if (!img.HasData()) continue;
+		if (!img.HasData()) {
+			continue;
+		}
 
 
 		int idx = mScene->mNumTextures++;
 		int idx = mScene->mNumTextures++;
 		embeddedTexIdxs[i] = idx;
 		embeddedTexIdxs[i] = idx;

+ 1 - 1
contrib/CMakeLists.txt

@@ -1,4 +1,4 @@
 # Compile internal irrXML only if system is not requested
 # Compile internal irrXML only if system is not requested
 if( NOT SYSTEM_IRRXML )
 if( NOT SYSTEM_IRRXML )
     add_subdirectory(irrXML)
     add_subdirectory(irrXML)
-endif( NOT SYSTEM_IRRXML )
+endif()

+ 2 - 6
contrib/zip/CMakeLists.txt

@@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 3.0)
 
 
 project(zip
 project(zip
   LANGUAGES C
   LANGUAGES C
-  VERSION "0.1.15")
+  VERSION "0.1.18")
 set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
 set(CMAKE_MODULE_PATH "${PROJECT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})
 
 
 option(CMAKE_DISABLE_TESTING "Disable test creation" OFF)
 option(CMAKE_DISABLE_TESTING "Disable test creation" OFF)
@@ -16,10 +16,6 @@ elseif ("${CMAKE_C_COMPILER_ID}" STREQUAL "GNU" OR
         "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
         "${CMAKE_C_COMPILER_ID}" STREQUAL "Clang" OR
         "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
         "${CMAKE_C_COMPILER_ID}" STREQUAL "AppleClang")
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic")
   set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=c99 -Wall -Wextra -Werror -pedantic")
-  if(ENABLE_COVERAGE)
-    set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
-    set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} --coverage")
-  endif()
 endif (MSVC)
 endif (MSVC)
 
 
 # zip
 # zip
@@ -35,7 +31,7 @@ if (NOT CMAKE_DISABLE_TESTING)
   enable_testing()
   enable_testing()
   add_subdirectory(test)
   add_subdirectory(test)
   find_package(Sanitizers)
   find_package(Sanitizers)
-  add_sanitizers(${PROJECT_NAME} ${test_out} ${test_miniz_out})
+  add_sanitizers(${PROJECT_NAME} ${test_out})
 endif()
 endif()
 
 
 ####
 ####

+ 48 - 3
contrib/zip/README.md

@@ -1,10 +1,8 @@
 ### A portable (OSX/Linux/Windows), simple zip library written in C
 ### A portable (OSX/Linux/Windows), simple zip library written in C
 This is done by hacking awesome [miniz](https://code.google.com/p/miniz) library and layering functions on top of the miniz v1.15 API.
 This is done by hacking awesome [miniz](https://code.google.com/p/miniz) library and layering functions on top of the miniz v1.15 API.
 
 
-[![Windows](https://ci.appveyor.com/api/projects/status/bph8dr3jacgmjv32/branch/master?svg=true&label=windows)](https://ci.appveyor.com/project/kuba--/zip)
-[![Linux](https://travis-ci.org/kuba--/zip.svg?branch=master&label=linux%2fosx)](https://travis-ci.org/kuba--/zip)
+[![Build](https://github.com/kuba--/zip/workflows/build/badge.svg)](https://github.com/kuba--/zip/actions?query=workflow%3Abuild)
 [![Version](https://badge.fury.io/gh/kuba--%2Fzip.svg)](https://github.com/kuba--/zip/releases)
 [![Version](https://badge.fury.io/gh/kuba--%2Fzip.svg)](https://github.com/kuba--/zip/releases)
-[![Codecov](https://codecov.io/gh/kuba--/zip/branch/master/graph/badge.svg)](https://codecov.io/gh/kuba--/zip)
 
 
 
 
 # The Idea
 # The Idea
@@ -213,6 +211,53 @@ func main() {
 }
 }
 ```
 ```
 
 
+### Rust (ffi)
+```rust
+extern crate libc;
+use std::ffi::CString;
+
+#[repr(C)]
+pub struct Zip {
+    _private: [u8; 0],
+}
+
+#[link(name = "zip")]
+extern "C" {
+    fn zip_open(path: *const libc::c_char, level: libc::c_int, mode: libc::c_char) -> *mut Zip;
+    fn zip_close(zip: *mut Zip) -> libc::c_void;
+
+    fn zip_entry_open(zip: *mut Zip, entryname: *const libc::c_char) -> libc::c_int;
+    fn zip_entry_close(zip: *mut Zip) -> libc::c_int;
+    fn zip_entry_write(
+        zip: *mut Zip,
+        buf: *const libc::c_void,
+        bufsize: libc::size_t,
+    ) -> libc::c_int;
+}
+
+fn main() {
+    let path = CString::new("/tmp/test.zip").unwrap();
+    let mode: libc::c_char = 'w' as libc::c_char;
+
+    let entryname = CString::new("test.txt").unwrap();
+    let content = "test content\0";
+
+    unsafe {
+        let zip: *mut Zip = zip_open(path.as_ptr(), 5, mode);
+        {
+            zip_entry_open(zip, entryname.as_ptr());
+            {
+                let buf = content.as_ptr() as *const libc::c_void;
+                let bufsize = content.len() as libc::size_t;
+                zip_entry_write(zip, buf, bufsize);
+            }
+            zip_entry_close(zip);
+        }
+        zip_close(zip);
+    }
+}
+```
+
 ### Ruby (ffi)
 ### Ruby (ffi)
 Install _ffi_ gem.
 Install _ffi_ gem.
 ```shell
 ```shell

+ 16 - 1
contrib/zip/src/zip.c

@@ -222,6 +222,20 @@ void zip_close(struct zip_t *zip) {
   }
   }
 }
 }
 
 
+int zip_is64(struct zip_t *zip) {
+  if (!zip) {
+    // zip_t handler is not initialized
+    return -1;
+  }
+
+  if (!zip->archive.m_pState) {
+    // zip state is not initialized
+    return -1;
+  }
+
+  return (int)zip->archive.m_pState->m_zip64;
+}
+
 int zip_entry_open(struct zip_t *zip, const char *entryname) {
 int zip_entry_open(struct zip_t *zip, const char *entryname) {
   size_t entrylen = 0;
   size_t entrylen = 0;
   mz_zip_archive *pzip = NULL;
   mz_zip_archive *pzip = NULL;
@@ -794,7 +808,8 @@ int zip_create(const char *zipname, const char *filenames[], size_t len) {
 
 
     if (MZ_FILE_STAT(name, &file_stat) != 0) {
     if (MZ_FILE_STAT(name, &file_stat) != 0) {
       // problem getting information - check errno
       // problem getting information - check errno
-      return -1;
+      status = -1;
+      break;
     }
     }
 
 
     if ((file_stat.st_mode & 0200) == 0) {
     if ((file_stat.st_mode & 0200) == 0) {

+ 12 - 1
contrib/zip/src/zip.h

@@ -21,7 +21,7 @@ extern "C" {
 
 
 #if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) &&               \
 #if !defined(_SSIZE_T_DEFINED) && !defined(_SSIZE_T_DEFINED_) &&               \
     !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) &&              \
     !defined(__DEFINED_ssize_t) && !defined(__ssize_t_defined) &&              \
-    !defined(_SSIZE_T) && !defined(_SSIZE_T_)
+    !defined(_SSIZE_T) && !defined(_SSIZE_T_) && !defined(_SSIZE_T_DECLARED)
 
 
 // 64-bit Windows is the only mainstream platform
 // 64-bit Windows is the only mainstream platform
 // where sizeof(long) != sizeof(void*)
 // where sizeof(long) != sizeof(void*)
@@ -37,6 +37,7 @@ typedef long ssize_t; /* byte count or error */
 #define __ssize_t_defined
 #define __ssize_t_defined
 #define _SSIZE_T
 #define _SSIZE_T
 #define _SSIZE_T_
 #define _SSIZE_T_
+#define _SSIZE_T_DECLARED
 
 
 #endif
 #endif
 
 
@@ -90,6 +91,16 @@ extern struct zip_t *zip_open(const char *zipname, int level, char mode);
  */
  */
 extern void zip_close(struct zip_t *zip);
 extern void zip_close(struct zip_t *zip);
 
 
+/**
+ * Determines if the archive has a zip64 end of central directory headers.
+ *
+ * @param zip zip archive handler.
+ *
+ * @return the return code - 1 (true), 0 (false), negative number (< 0) on
+ *         error.
+ */
+extern int zip_is64(struct zip_t *zip);
+
 /**
 /**
  * Opens an entry by name in the zip archive.
  * Opens an entry by name in the zip archive.
  *
  *

+ 0 - 5
contrib/zip/test/CMakeLists.txt

@@ -2,15 +2,10 @@ cmake_minimum_required(VERSION 2.8)
 
 
 # test
 # test
 set(test_out test.out)
 set(test_out test.out)
-set(test_miniz_out test_miniz.out)
 
 
 add_executable(${test_out} test.c)
 add_executable(${test_out} test.c)
 target_link_libraries(${test_out} zip)
 target_link_libraries(${test_out} zip)
-add_executable(${test_miniz_out} test_miniz.c)
-target_link_libraries(${test_miniz_out} zip)
 
 
 add_test(NAME ${test_out} COMMAND ${test_out})
 add_test(NAME ${test_out} COMMAND ${test_out})
-add_test(NAME ${test_miniz_out} COMMAND ${test_miniz_out})
 
 
 set(test_out ${test_out} PARENT_SCOPE)
 set(test_out ${test_out} PARENT_SCOPE)
-set(test_miniz_out ${test_miniz_out} PARENT_SCOPE)

+ 3 - 1
contrib/zip/test/test.c

@@ -47,7 +47,7 @@ static void test_write(void) {
   assert(CRC32DATA1 == zip_entry_crc32(zip));
   assert(CRC32DATA1 == zip_entry_crc32(zip));
   ++total_entries;
   ++total_entries;
   assert(0 == zip_entry_close(zip));
   assert(0 == zip_entry_close(zip));
-
+  assert(0 == zip_is64(zip));
   zip_close(zip);
   zip_close(zip);
 }
 }
 
 
@@ -92,6 +92,7 @@ static void test_read(void) {
   size_t buftmp;
   size_t buftmp;
   struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
   struct zip_t *zip = zip_open(ZIPNAME, 0, 'r');
   assert(zip != NULL);
   assert(zip != NULL);
+  assert(0 == zip_is64(zip));
 
 
   assert(0 == zip_entry_open(zip, "test\\test-1.txt"));
   assert(0 == zip_entry_open(zip, "test\\test-1.txt"));
   assert(strlen(TESTDATA1) == zip_entry_size(zip));
   assert(strlen(TESTDATA1) == zip_entry_size(zip));
@@ -310,6 +311,7 @@ static void test_fwrite(void) {
   assert(0 == zip_entry_open(zip, WFILE));
   assert(0 == zip_entry_open(zip, WFILE));
   assert(0 == zip_entry_fwrite(zip, WFILE));
   assert(0 == zip_entry_fwrite(zip, WFILE));
   assert(0 == zip_entry_close(zip));
   assert(0 == zip_entry_close(zip));
+  assert(0 == zip_is64(zip));
 
 
   zip_close(zip);
   zip_close(zip);
   remove(WFILE);
   remove(WFILE);

+ 2 - 2
doc/CMakeLists.txt

@@ -6,7 +6,7 @@ set( HTML_OUTPUT "AssimpDoc_Html" CACHE STRING "Output directory for generated H
 set( MICROSOFT_HELP_WORKSHOP "NO")
 set( MICROSOFT_HELP_WORKSHOP "NO")
 if( MSVC )
 if( MSVC )
     set( MICROSOFT_HELP_WORKSHOP "YES" )
     set( MICROSOFT_HELP_WORKSHOP "YES" )
-endif( MSVC )
+endif()
 
 
 configure_file(
 configure_file(
     ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
     ${CMAKE_CURRENT_SOURCE_DIR}/Doxyfile.in
@@ -38,5 +38,5 @@ if( DEFINED CMAKE_INSTALL_DOCDIR )
         ${CMAKE_CURRENT_SOURCE_DIR}/AssimpDoc_Html/dragonsplash.png
         ${CMAKE_CURRENT_SOURCE_DIR}/AssimpDoc_Html/dragonsplash.png
         DESTINATION ${CMAKE_INSTALL_DOCDIR}/${HTML_OUTPUT}
         DESTINATION ${CMAKE_INSTALL_DOCDIR}/${HTML_OUTPUT}
     )
     )
-endif( DEFINED CMAKE_INSTALL_DOCDIR )
+endif()
 
 

+ 17 - 22
include/assimp/GenericProperty.h

@@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
 
 
 Copyright (c) 2006-2020, assimp team
 Copyright (c) 2006-2020, assimp team
 
 
-
 All rights reserved.
 All rights reserved.
 
 
 Redistribution and use of this software in source and binary forms,
 Redistribution and use of this software in source and binary forms,
@@ -45,26 +44,25 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_GENERIC_PROPERTY_H_INCLUDED
 #define AI_GENERIC_PROPERTY_H_INCLUDED
 
 
 #ifdef __GNUC__
 #ifdef __GNUC__
-#   pragma GCC system_header
+#    pragma GCC system_header
 #endif
 #endif
 
 
-#include <assimp/Importer.hpp>
-#include <assimp/ai_assert.h>
 #include <assimp/Hash.h>
 #include <assimp/Hash.h>
+#include <assimp/ai_assert.h>
+#include <assimp/Importer.hpp>
 
 
 #include <map>
 #include <map>
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <class T>
 template <class T>
-inline
-bool SetGenericProperty(std::map< unsigned int, T >& list,
-        const char* szName, const T& value) {
+inline bool SetGenericProperty(std::map<unsigned int, T> &list,
+        const char *szName, const T &value) {
     ai_assert(nullptr != szName);
     ai_assert(nullptr != szName);
     const uint32_t hash = SuperFastHash(szName);
     const uint32_t hash = SuperFastHash(szName);
 
 
     typename std::map<unsigned int, T>::iterator it = list.find(hash);
     typename std::map<unsigned int, T>::iterator it = list.find(hash);
-    if (it == list.end())   {
-        list.insert(std::pair<unsigned int, T>( hash, value ));
+    if (it == list.end()) {
+        list.insert(std::pair<unsigned int, T>(hash, value));
         return false;
         return false;
     }
     }
     (*it).second = value;
     (*it).second = value;
@@ -74,9 +72,8 @@ bool SetGenericProperty(std::map< unsigned int, T >& list,
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <class T>
 template <class T>
-inline
-const T& GetGenericProperty(const std::map< unsigned int, T >& list,
-        const char* szName, const T& errorReturn) {
+inline const T &GetGenericProperty(const std::map<unsigned int, T> &list,
+        const char *szName, const T &errorReturn) {
     ai_assert(nullptr != szName);
     ai_assert(nullptr != szName);
     const uint32_t hash = SuperFastHash(szName);
     const uint32_t hash = SuperFastHash(szName);
 
 
@@ -92,22 +89,21 @@ const T& GetGenericProperty(const std::map< unsigned int, T >& list,
 // Special version for pointer types - they will be deleted when replaced with another value
 // Special version for pointer types - they will be deleted when replaced with another value
 // passing NULL removes the whole property
 // passing NULL removes the whole property
 template <class T>
 template <class T>
-inline
-void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
-        const char* szName, T* value, bool* bWasExisting = nullptr ) {
+inline void SetGenericPropertyPtr(std::map<unsigned int, T *> &list,
+        const char *szName, T *value, bool *bWasExisting = nullptr) {
     ai_assert(nullptr != szName);
     ai_assert(nullptr != szName);
     const uint32_t hash = SuperFastHash(szName);
     const uint32_t hash = SuperFastHash(szName);
 
 
-    typename std::map<unsigned int, T*>::iterator it = list.find(hash);
-    if (it == list.end())   {
+    typename std::map<unsigned int, T *>::iterator it = list.find(hash);
+    if (it == list.end()) {
         if (bWasExisting) {
         if (bWasExisting) {
             *bWasExisting = false;
             *bWasExisting = false;
         }
         }
 
 
-        list.insert(std::pair<unsigned int,T*>( hash, value ));
+        list.insert(std::pair<unsigned int, T *>(hash, value));
         return;
         return;
     }
     }
-    if ((*it).second != value)  {
+    if ((*it).second != value) {
         delete (*it).second;
         delete (*it).second;
         (*it).second = value;
         (*it).second = value;
     }
     }
@@ -121,9 +117,8 @@ void SetGenericPropertyPtr(std::map< unsigned int, T* >& list,
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <class T>
 template <class T>
-inline
-bool HasGenericProperty(const std::map< unsigned int, T >& list,
-        const char* szName) {
+inline bool HasGenericProperty(const std::map<unsigned int, T> &list,
+        const char *szName) {
     ai_assert(nullptr != szName);
     ai_assert(nullptr != szName);
     const uint32_t hash = SuperFastHash(szName);
     const uint32_t hash = SuperFastHash(szName);
 
 

+ 2 - 2
include/assimp/Importer.hpp

@@ -285,7 +285,7 @@ public:
      *  The return value remains valid until the property is modified.
      *  The return value remains valid until the property is modified.
      * @see GetPropertyInteger()
      * @see GetPropertyInteger()
      */
      */
-    const std::string GetPropertyString(const char* szName,
+    std::string GetPropertyString(const char* szName,
         const std::string& sErrorReturn = "") const;
         const std::string& sErrorReturn = "") const;
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
@@ -294,7 +294,7 @@ public:
      *  The return value remains valid until the property is modified.
      *  The return value remains valid until the property is modified.
      * @see GetPropertyInteger()
      * @see GetPropertyInteger()
      */
      */
-    const aiMatrix4x4 GetPropertyMatrix(const char* szName,
+    aiMatrix4x4 GetPropertyMatrix(const char* szName,
         const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const;
         const aiMatrix4x4& sErrorReturn = aiMatrix4x4()) const;
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------

+ 3 - 3
include/assimp/matrix3x3.h

@@ -93,10 +93,10 @@ public:
     const TReal* operator[] (unsigned int p_iIndex) const;
     const TReal* operator[] (unsigned int p_iIndex) const;
 
 
     // comparison operators
     // comparison operators
-    bool operator== (const aiMatrix4x4t<TReal>& m) const;
-    bool operator!= (const aiMatrix4x4t<TReal>& m) const;
+    bool operator== (const aiMatrix3x3t<TReal>& m) const;
+    bool operator!= (const aiMatrix3x3t<TReal>& m) const;
 
 
-    bool Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon = 1e-6) const;
+    bool Equal(const aiMatrix3x3t<TReal>& m, TReal epsilon = 1e-6) const;
 
 
     template <typename TOther>
     template <typename TOther>
     operator aiMatrix3x3t<TOther> () const;
     operator aiMatrix3x3t<TOther> () const;

+ 3 - 3
include/assimp/matrix3x3.inl

@@ -141,7 +141,7 @@ const TReal* aiMatrix3x3t<TReal>::operator[] (unsigned int p_iIndex) const {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
 AI_FORCE_INLINE
 AI_FORCE_INLINE
-bool aiMatrix3x3t<TReal>::operator== (const aiMatrix4x4t<TReal>& m) const {
+bool aiMatrix3x3t<TReal>::operator== (const aiMatrix3x3t<TReal>& m) const {
     return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 &&
     return a1 == m.a1 && a2 == m.a2 && a3 == m.a3 &&
            b1 == m.b1 && b2 == m.b2 && b3 == m.b3 &&
            b1 == m.b1 && b2 == m.b2 && b3 == m.b3 &&
            c1 == m.c1 && c2 == m.c2 && c3 == m.c3;
            c1 == m.c1 && c2 == m.c2 && c3 == m.c3;
@@ -150,14 +150,14 @@ bool aiMatrix3x3t<TReal>::operator== (const aiMatrix4x4t<TReal>& m) const {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 template <typename TReal>
 template <typename TReal>
 AI_FORCE_INLINE
 AI_FORCE_INLINE
-bool aiMatrix3x3t<TReal>::operator!= (const aiMatrix4x4t<TReal>& m) const {
+bool aiMatrix3x3t<TReal>::operator!= (const aiMatrix3x3t<TReal>& m) const {
     return !(*this == m);
     return !(*this == m);
 }
 }
 
 
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 template<typename TReal>
 template<typename TReal>
 AI_FORCE_INLINE
 AI_FORCE_INLINE
-bool aiMatrix3x3t<TReal>::Equal(const aiMatrix4x4t<TReal>& m, TReal epsilon) const {
+bool aiMatrix3x3t<TReal>::Equal(const aiMatrix3x3t<TReal>& m, TReal epsilon) const {
     return
     return
         std::abs(a1 - m.a1) <= epsilon &&
         std::abs(a1 - m.a1) <= epsilon &&
         std::abs(a2 - m.a2) <= epsilon &&
         std::abs(a2 - m.a2) <= epsilon &&

+ 1 - 1
port/PyAssimp/pyassimp/core.py

@@ -138,7 +138,7 @@ def _init(self, target = None, parent = None):
             logger.debug(str(self) + ": Added array " + str(getattr(target, name)) +  " as self." + name.lower())
             logger.debug(str(self) + ": Added array " + str(getattr(target, name)) +  " as self." + name.lower())
             continue
             continue
 
 
-        if m.startswith('m'):
+        if m.startswith('m') and len(m) > 1 and m[1].upper() == m[1]:
 
 
             if name == "parent":
             if name == "parent":
                 setattr(target, name, parent)
                 setattr(target, name, parent)

+ 52 - 0
samples/SharedCode/UTFConverter.cpp

@@ -0,0 +1,52 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#include "UTFConverter.h"
+
+namespace AssimpSamples {
+namespace SharedCode {
+
+typename UTFConverter::UTFConverterImpl UTFConverter::impl_;
+
+}
+}

+ 92 - 0
samples/SharedCode/UTFConverter.h

@@ -0,0 +1,92 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#ifndef ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H
+#define ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H
+
+#include <string>
+#include <locale>
+#include <codecvt>
+
+namespace AssimpSamples {
+namespace SharedCode {
+
+// Used to convert between multibyte and unicode strings.
+class UTFConverter {
+    using UTFConverterImpl = std::wstring_convert<std::codecvt_utf8<wchar_t>, wchar_t>;
+public:
+    UTFConverter(const char* s) :
+        s_(s),
+        ws_(impl_.from_bytes(s)) {
+    }
+    UTFConverter(const wchar_t* s) :
+        s_(impl_.to_bytes(s)),
+        ws_(s) {
+    }
+    UTFConverter(const std::string& s) :
+        s_(s),
+        ws_(impl_.from_bytes(s)) {
+    }
+    UTFConverter(const std::wstring& s) :
+        s_(impl_.to_bytes(s)),
+        ws_(s) {
+    }
+    inline const char* c_str() const {
+        return s_.c_str();
+    }
+    inline const std::string& str() const {
+        return s_;
+    }
+    inline const wchar_t* c_wstr() const {
+        return ws_.c_str();
+    }
+private:
+    static UTFConverterImpl impl_;
+    std::string s_;
+    std::wstring ws_;
+};
+
+}
+}
+
+#endif // ASSIMP_SAMPLES_SHARED_CODE_UTFCONVERTER_H

+ 6 - 6
samples/SimpleOpenGL/CMakeLists.txt

@@ -2,24 +2,24 @@ FIND_PACKAGE(OpenGL)
 FIND_PACKAGE(GLUT)
 FIND_PACKAGE(GLUT)
 IF ( MSVC )
 IF ( MSVC )
   SET(M_LIB)
   SET(M_LIB)
-ELSE ( MSVC )
+ELSE ()
   find_library(M_LIB m)
   find_library(M_LIB m)
-ENDIF ( MSVC )
+ENDIF ()
 
 
 IF ( NOT GLUT_FOUND )
 IF ( NOT GLUT_FOUND )
   IF ( MSVC )
   IF ( MSVC )
     SET ( GLUT_FOUND 1 )
     SET ( GLUT_FOUND 1 )
     SET ( GLUT_INCLUDE_DIR ${Assimp_SOURCE_DIR}/samples/freeglut/ )
     SET ( GLUT_INCLUDE_DIR ${Assimp_SOURCE_DIR}/samples/freeglut/ )
     SET ( GLUT_LIBRARIES ${Assimp_SOURCE_DIR}/samples/freeglut/lib/freeglut.lib )
     SET ( GLUT_LIBRARIES ${Assimp_SOURCE_DIR}/samples/freeglut/lib/freeglut.lib )
-  ELSE ( MSVC )
+  ELSE ()
     MESSAGE( WARNING "Please install glut." )
     MESSAGE( WARNING "Please install glut." )
-  ENDIF ( MSVC )
-ENDIF ( NOT GLUT_FOUND )
+  ENDIF ()
+ENDIF ()
 
 
 if ( MSVC )
 if ( MSVC )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
-endif ( MSVC )
+endif ()
 
 
 INCLUDE_DIRECTORIES(
 INCLUDE_DIRECTORIES(
   ${Assimp_SOURCE_DIR}/include
   ${Assimp_SOURCE_DIR}/include

+ 9 - 6
samples/SimpleTexturedDirectx11/CMakeLists.txt

@@ -2,20 +2,20 @@ FIND_PACKAGE(DirectX)
 
 
 IF ( MSVC )
 IF ( MSVC )
   SET(M_LIB)
   SET(M_LIB)
-ENDIF ( MSVC )
+ENDIF ()
 
 
 if ( MSVC )
 if ( MSVC )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
   REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE )
   REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE )
-endif ( MSVC )
+endif ()
+
+ADD_COMPILE_DEFINITIONS(SHADER_PATH="${CMAKE_CURRENT_SOURCE_DIR}/SimpleTexturedDirectx11/")
 
 
 INCLUDE_DIRECTORIES(
 INCLUDE_DIRECTORIES(
   ${Assimp_SOURCE_DIR}/include
   ${Assimp_SOURCE_DIR}/include
   ${Assimp_SOURCE_DIR}/code
   ${Assimp_SOURCE_DIR}/code
-  ${OPENGL_INCLUDE_DIR}
-  ${GLUT_INCLUDE_DIR}
-  ${Assimp_SOURCE_DIR}/samples/freeglut/include
+  ${SAMPLES_SHARED_CODE_DIR}
 )
 )
 
 
 LINK_DIRECTORIES(
 LINK_DIRECTORIES(
@@ -32,11 +32,14 @@ ADD_EXECUTABLE( assimp_simpletextureddirectx11 WIN32
   SimpleTexturedDirectx11/TextureLoader.h 
   SimpleTexturedDirectx11/TextureLoader.h 
   #SimpleTexturedDirectx11/VertexShader.hlsl  
   #SimpleTexturedDirectx11/VertexShader.hlsl  
   SimpleTexturedDirectx11/main.cpp
   SimpleTexturedDirectx11/main.cpp
+  SimpleTexturedDirectx11/SafeRelease.hpp
+  ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp
+  ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h
 )
 )
 
 
 SET_PROPERTY(TARGET assimp_simpletextureddirectx11 PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
 SET_PROPERTY(TARGET assimp_simpletextureddirectx11 PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
 
 
-TARGET_LINK_LIBRARIES( assimp_simpletextureddirectx11 assimp ${DirectX_LIBRARY} comctl32.lib winmm.lib )
+TARGET_LINK_LIBRARIES( assimp_simpletextureddirectx11 assimp comctl32.lib winmm.lib )
 SET_TARGET_PROPERTIES( assimp_simpletextureddirectx11 PROPERTIES
 SET_TARGET_PROPERTIES( assimp_simpletextureddirectx11 PROPERTIES
   OUTPUT_NAME assimp_simpletextureddirectx11
   OUTPUT_NAME assimp_simpletextureddirectx11
 )
 )

+ 80 - 75
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/Mesh.h

@@ -6,97 +6,102 @@
 #include <sstream>
 #include <sstream>
 #include <iostream>
 #include <iostream>
 #include <vector>
 #include <vector>
-using namespace std;
-
-#include <vector>
+#include <stdexcept>
 #include <d3d11_1.h>
 #include <d3d11_1.h>
 #include <DirectXMath.h>
 #include <DirectXMath.h>
+
 using namespace DirectX;
 using namespace DirectX;
 
 
+#include "SafeRelease.hpp"
+
 struct VERTEX {
 struct VERTEX {
 	FLOAT X, Y, Z;
 	FLOAT X, Y, Z;
 	XMFLOAT2 texcoord;
 	XMFLOAT2 texcoord;
 };
 };
 
 
 struct Texture {
 struct Texture {
-	string type;
-	string path;
+	std::string type;
+	std::string path;
 	ID3D11ShaderResourceView *texture;
 	ID3D11ShaderResourceView *texture;
+
+	void Release() {
+		SafeRelease(texture);
+	}
 };
 };
 
 
 class Mesh {
 class Mesh {
 public:
 public:
-	vector<VERTEX> vertices;
-	vector<UINT> indices;
-	vector<Texture> textures;
-	ID3D11Device *dev;
-
-	Mesh(ID3D11Device *dev, vector<VERTEX> vertices, vector<UINT> indices, vector<Texture> textures)
-	{
-		this->vertices = vertices;
-		this->indices = indices;
-		this->textures = textures;
-
-		this->dev = dev;
-
-		this->setupMesh(dev);
-	}
-
-	void Draw(ID3D11DeviceContext *devcon)
-	{
-		UINT stride = sizeof(VERTEX);
-		UINT offset = 0;
-
-		devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
-		devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
-
-		devcon->PSSetShaderResources(0, 1, &textures[0].texture);
-
-		devcon->DrawIndexed(indices.size(), 0, 0);
-	}
-
-	void Close()
-	{
-		VertexBuffer->Release();
-		IndexBuffer->Release();
-	}
+    std::vector<VERTEX> vertices;
+    std::vector<UINT> indices;
+    std::vector<Texture> textures;
+    ID3D11Device *dev;
+
+    Mesh(ID3D11Device *dev, const std::vector<VERTEX>& vertices, const std::vector<UINT>& indices, const std::vector<Texture>& textures) :
+            vertices(vertices),
+            indices(indices),
+            textures(textures),
+            dev(dev),
+            VertexBuffer(nullptr),
+            IndexBuffer(nullptr) {
+        this->setupMesh(this->dev);
+    }
+
+    void Draw(ID3D11DeviceContext *devcon) {
+        UINT stride = sizeof(VERTEX);
+        UINT offset = 0;
+
+        devcon->IASetVertexBuffers(0, 1, &VertexBuffer, &stride, &offset);
+        devcon->IASetIndexBuffer(IndexBuffer, DXGI_FORMAT_R32_UINT, 0);
+
+        devcon->PSSetShaderResources(0, 1, &textures[0].texture);
+
+        devcon->DrawIndexed(static_cast<UINT>(indices.size()), 0, 0);
+    }
+
+    void Close() {
+        SafeRelease(VertexBuffer);
+        SafeRelease(IndexBuffer);
+    }
 private:
 private:
-	/*  Render data  */
-	ID3D11Buffer *VertexBuffer, *IndexBuffer;
-
-	/*  Functions    */
-	// Initializes all the buffer objects/arrays
-	bool setupMesh(ID3D11Device *dev)
-	{
-		HRESULT hr;
-
-		D3D11_BUFFER_DESC vbd;
-		vbd.Usage = D3D11_USAGE_IMMUTABLE;
-		vbd.ByteWidth = sizeof(VERTEX) * vertices.size();
-		vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
-		vbd.CPUAccessFlags = 0;
-		vbd.MiscFlags = 0;
-
-		D3D11_SUBRESOURCE_DATA initData;
-		initData.pSysMem = &vertices[0];
-
-		hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer);
-		if (FAILED(hr))
-			return false;
-
-		D3D11_BUFFER_DESC ibd;
-		ibd.Usage = D3D11_USAGE_IMMUTABLE;
-		ibd.ByteWidth = sizeof(UINT) * indices.size();
-		ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
-		ibd.CPUAccessFlags = 0;
-		ibd.MiscFlags = 0;
-
-		initData.pSysMem = &indices[0];
-
-		hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer);
-		if (FAILED(hr))
-			return false;
-	}
+    // Render data
+    ID3D11Buffer *VertexBuffer, *IndexBuffer;
+
+    // Functions
+    // Initializes all the buffer objects/arrays
+    void setupMesh(ID3D11Device *dev) {
+        HRESULT hr;
+
+        D3D11_BUFFER_DESC vbd;
+        vbd.Usage = D3D11_USAGE_IMMUTABLE;
+        vbd.ByteWidth = static_cast<UINT>(sizeof(VERTEX) * vertices.size());
+        vbd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
+        vbd.CPUAccessFlags = 0;
+        vbd.MiscFlags = 0;
+
+        D3D11_SUBRESOURCE_DATA initData;
+        initData.pSysMem = &vertices[0];
+
+        hr = dev->CreateBuffer(&vbd, &initData, &VertexBuffer);
+        if (FAILED(hr)) {
+            Close();
+            throw std::runtime_error("Failed to create vertex buffer.");
+        }
+
+        D3D11_BUFFER_DESC ibd;
+        ibd.Usage = D3D11_USAGE_IMMUTABLE;
+        ibd.ByteWidth = static_cast<UINT>(sizeof(UINT) * indices.size());
+        ibd.BindFlags = D3D11_BIND_INDEX_BUFFER;
+        ibd.CPUAccessFlags = 0;
+        ibd.MiscFlags = 0;
+
+        initData.pSysMem = &indices[0];
+
+        hr = dev->CreateBuffer(&ibd, &initData, &IndexBuffer);
+        if (FAILED(hr)) {
+            Close();
+            throw std::runtime_error("Failed to create index buffer.");
+        }
+    }
 };
 };
 
 
 #endif
 #endif

+ 56 - 76
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/ModelLoader.cpp

@@ -1,16 +1,21 @@
 #include "ModelLoader.h"
 #include "ModelLoader.h"
 
 
-ModelLoader::ModelLoader()
-{
+ModelLoader::ModelLoader() : 
+        dev(nullptr),
+        devcon(nullptr),
+        meshes(),
+        directory(),
+        textures_loaded(),
+        hwnd(nullptr) {
+    // empty
 }
 }
 
 
 
 
-ModelLoader::~ModelLoader()
-{
+ModelLoader::~ModelLoader() {
+    // empty
 }
 }
 
 
-bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename)
-{
+bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devcon, std::string filename) {
 	Assimp::Importer importer;
 	Assimp::Importer importer;
 
 
 	const aiScene* pScene = importer.ReadFile(filename,
 	const aiScene* pScene = importer.ReadFile(filename,
@@ -20,9 +25,10 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc
 	if (pScene == NULL)
 	if (pScene == NULL)
 		return false;
 		return false;
 
 
-	this->directory = filename.substr(0, filename.find_last_of('/'));
+	this->directory = filename.substr(0, filename.find_last_of("/\\"));
 
 
 	this->dev = dev;
 	this->dev = dev;
+	this->devcon = devcon;
 	this->hwnd = hwnd;
 	this->hwnd = hwnd;
 
 
 	processNode(pScene->mRootNode, pScene);
 	processNode(pScene->mRootNode, pScene);
@@ -30,41 +36,37 @@ bool ModelLoader::Load(HWND hwnd, ID3D11Device * dev, ID3D11DeviceContext * devc
 	return true;
 	return true;
 }
 }
 
 
-void ModelLoader::Draw(ID3D11DeviceContext * devcon)
-{
-	for (int i = 0; i < meshes.size(); i++)
-	{
+void ModelLoader::Draw(ID3D11DeviceContext * devcon) {
+	for (int i = 0; i < meshes.size(); ++i ) {
 		meshes[i].Draw(devcon);
 		meshes[i].Draw(devcon);
 	}
 	}
 }
 }
 
 
-string textype;
+std::string textype;
 
 
-Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene)
-{
+Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) {
 	// Data to fill
 	// Data to fill
-	vector<VERTEX> vertices;
-	vector<UINT> indices;
-	vector<Texture> textures;
+	std::vector<VERTEX> vertices;
+	std::vector<UINT> indices;
+	std::vector<Texture> textures;
 
 
-	if (mesh->mMaterialIndex >= 0)
-	{
+	if (mesh->mMaterialIndex >= 0) {
 		aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
 		aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
 
 
-		if (textype.empty()) textype = determineTextureType(scene, mat);
+		if (textype.empty()) {
+            textype = determineTextureType(scene, mat);
+        }
 	}
 	}
 
 
 	// Walk through each of the mesh's vertices
 	// Walk through each of the mesh's vertices
-	for (UINT i = 0; i < mesh->mNumVertices; i++)
-	{
+	for (UINT i = 0; i < mesh->mNumVertices; i++) {
 		VERTEX vertex;
 		VERTEX vertex;
 
 
 		vertex.X = mesh->mVertices[i].x;
 		vertex.X = mesh->mVertices[i].x;
 		vertex.Y = mesh->mVertices[i].y;
 		vertex.Y = mesh->mVertices[i].y;
 		vertex.Z = mesh->mVertices[i].z;
 		vertex.Z = mesh->mVertices[i].z;
 
 
-		if (mesh->mTextureCoords[0])
-		{
+		if (mesh->mTextureCoords[0]) {
 			vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x;
 			vertex.texcoord.x = (float)mesh->mTextureCoords[0][i].x;
 			vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y;
 			vertex.texcoord.y = (float)mesh->mTextureCoords[0][i].y;
 		}
 		}
@@ -72,57 +74,47 @@ Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene)
 		vertices.push_back(vertex);
 		vertices.push_back(vertex);
 	}
 	}
 
 
-	for (UINT i = 0; i < mesh->mNumFaces; i++)
-	{
+	for (UINT i = 0; i < mesh->mNumFaces; i++) {
 		aiFace face = mesh->mFaces[i];
 		aiFace face = mesh->mFaces[i];
 
 
 		for (UINT j = 0; j < face.mNumIndices; j++)
 		for (UINT j = 0; j < face.mNumIndices; j++)
 			indices.push_back(face.mIndices[j]);
 			indices.push_back(face.mIndices[j]);
 	}
 	}
 
 
-	if (mesh->mMaterialIndex >= 0)
-	{
+	if (mesh->mMaterialIndex >= 0) {
 		aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
 		aiMaterial* material = scene->mMaterials[mesh->mMaterialIndex];
 
 
-		vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene);
+		std::vector<Texture> diffuseMaps = this->loadMaterialTextures(material, aiTextureType_DIFFUSE, "texture_diffuse", scene);
 		textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
 		textures.insert(textures.end(), diffuseMaps.begin(), diffuseMaps.end());
 	}
 	}
 
 
 	return Mesh(dev, vertices, indices, textures);
 	return Mesh(dev, vertices, indices, textures);
 }
 }
 
 
-vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, string typeName, const aiScene * scene)
-{
-	vector<Texture> textures;
-	for (UINT i = 0; i < mat->GetTextureCount(type); i++)
-	{
+std::vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureType type, std::string typeName, const aiScene * scene) {
+	std::vector<Texture> textures;
+	for (UINT i = 0; i < mat->GetTextureCount(type); i++) {
 		aiString str;
 		aiString str;
 		mat->GetTexture(type, i, &str);
 		mat->GetTexture(type, i, &str);
 		// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
 		// Check if texture was loaded before and if so, continue to next iteration: skip loading a new texture
 		bool skip = false;
 		bool skip = false;
-		for (UINT j = 0; j < textures_loaded.size(); j++)
-		{
-			if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0)
-			{
+		for (UINT j = 0; j < textures_loaded.size(); j++) {
+			if (std::strcmp(textures_loaded[j].path.c_str(), str.C_Str()) == 0) {
 				textures.push_back(textures_loaded[j]);
 				textures.push_back(textures_loaded[j]);
 				skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
 				skip = true; // A texture with the same filepath has already been loaded, continue to next one. (optimization)
 				break;
 				break;
 			}
 			}
 		}
 		}
-		if (!skip)
-		{   // If texture hasn't been loaded already, load it
+		if (!skip) {   // If texture hasn't been loaded already, load it
 			HRESULT hr;
 			HRESULT hr;
 			Texture texture;
 			Texture texture;
-			if (textype == "embedded compressed texture")
-			{
+			if (textype == "embedded compressed texture") {
 				int textureindex = getTextureIndex(&str);
 				int textureindex = getTextureIndex(&str);
 				texture.texture = getTextureFromModel(scene, textureindex);
 				texture.texture = getTextureFromModel(scene, textureindex);
-			}
-			else
-			{
-				string filename = string(str.C_Str());
+			} else {
+				std::string filename = std::string(str.C_Str());
 				filename = directory + '/' + filename;
 				filename = directory + '/' + filename;
-				wstring filenamews = wstring(filename.begin(), filename.end());
+				std::wstring filenamews = std::wstring(filename.begin(), filename.end());
 				hr = CreateWICTextureFromFile(dev, devcon, filenamews.c_str(), nullptr, &texture.texture);
 				hr = CreateWICTextureFromFile(dev, devcon, filenamews.c_str(), nullptr, &texture.texture);
 				if (FAILED(hr))
 				if (FAILED(hr))
 					MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
 					MessageBox(hwnd, "Texture couldn't be loaded", "Error!", MB_ICONERROR | MB_OK);
@@ -136,64 +128,52 @@ vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextureTyp
 	return textures;
 	return textures;
 }
 }
 
 
-void ModelLoader::Close()
-{
-	for (int i = 0; i < meshes.size(); i++)
-	{
+void ModelLoader::Close() {
+	for (auto& t : textures_loaded)
+		t.Release();
+
+	for (int i = 0; i < meshes.size(); i++) {
 		meshes[i].Close();
 		meshes[i].Close();
 	}
 	}
-
-	dev->Release();
 }
 }
 
 
-void ModelLoader::processNode(aiNode * node, const aiScene * scene)
-{
-	for (UINT i = 0; i < node->mNumMeshes; i++)
-	{
+void ModelLoader::processNode(aiNode * node, const aiScene * scene) {
+	for (UINT i = 0; i < node->mNumMeshes; i++) {
 		aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
 		aiMesh* mesh = scene->mMeshes[node->mMeshes[i]];
 		meshes.push_back(this->processMesh(mesh, scene));
 		meshes.push_back(this->processMesh(mesh, scene));
 	}
 	}
 
 
-	for (UINT i = 0; i < node->mNumChildren; i++)
-	{
+	for (UINT i = 0; i < node->mNumChildren; i++) {
 		this->processNode(node->mChildren[i], scene);
 		this->processNode(node->mChildren[i], scene);
 	}
 	}
 }
 }
 
 
-string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat)
-{
+std::string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) {
 	aiString textypeStr;
 	aiString textypeStr;
 	mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
 	mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
-	string textypeteststr = textypeStr.C_Str();
-	if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5")
-	{
-		if (scene->mTextures[0]->mHeight == 0)
-		{
+	std::string textypeteststr = textypeStr.C_Str();
+	if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") {
+		if (scene->mTextures[0]->mHeight == 0) {
 			return "embedded compressed texture";
 			return "embedded compressed texture";
-		}
-		else
-		{
+		} else {
 			return "embedded non-compressed texture";
 			return "embedded non-compressed texture";
 		}
 		}
 	}
 	}
-	if (textypeteststr.find('.') != string::npos)
-	{
+	if (textypeteststr.find('.') != std::string::npos) {
 		return "textures are on disk";
 		return "textures are on disk";
 	}
 	}
 
 
     return ".";
     return ".";
 }
 }
 
 
-int ModelLoader::getTextureIndex(aiString * str)
-{
-	string tistr;
+int ModelLoader::getTextureIndex(aiString * str) {
+	std::string tistr;
 	tistr = str->C_Str();
 	tistr = str->C_Str();
 	tistr = tistr.substr(1);
 	tistr = tistr.substr(1);
 	return stoi(tistr);
 	return stoi(tistr);
 }
 }
 
 
-ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex)
-{
+ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex) {
 	HRESULT hr;
 	HRESULT hr;
 	ID3D11ShaderResourceView *texture;
 	ID3D11ShaderResourceView *texture;
 
 

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

@@ -28,14 +28,14 @@ private:
 	ID3D11Device *dev;
 	ID3D11Device *dev;
 	ID3D11DeviceContext *devcon;
 	ID3D11DeviceContext *devcon;
 	std::vector<Mesh> meshes;
 	std::vector<Mesh> meshes;
-	string directory;
-	vector<Texture> textures_loaded;
+	std::string directory;
+	std::vector<Texture> textures_loaded;
 	HWND hwnd;
 	HWND hwnd;
 
 
 	void processNode(aiNode* node, const aiScene* scene);
 	void processNode(aiNode* node, const aiScene* scene);
 	Mesh processMesh(aiMesh* mesh, const aiScene* scene);
 	Mesh processMesh(aiMesh* mesh, const aiScene* scene);
-	vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, string typeName, const aiScene* scene);
-	string determineTextureType(const aiScene* scene, aiMaterial* mat);
+	std::vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName, const aiScene* scene);
+	std::string determineTextureType(const aiScene* scene, aiMaterial* mat);
 	int getTextureIndex(aiString* str);
 	int getTextureIndex(aiString* str);
 	ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex);
 	ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex);
 };
 };

+ 57 - 0
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/SafeRelease.hpp

@@ -0,0 +1,57 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (c) 2006-2020, assimp team
+
+
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#ifdef _MSC_VER
+#pragma once
+#endif
+
+/* Used to reduce to reduce the number of lines when calling Release()
+   on a D3D interface. Implemented as a template instead of a 'SAFE_RELEASE'
+   MACRO to ease debugging. */
+template<typename T>
+inline void SafeRelease(T*& x) {
+    if (x) {
+        x->Release();
+        x = nullptr;
+    }
+}

+ 132 - 53
samples/SimpleTexturedDirectx11/SimpleTexturedDirectx11/main.cpp

@@ -14,12 +14,16 @@
 // ---------------------------------------------------------------------------
 // ---------------------------------------------------------------------------
 
 
 #include <Windows.h>
 #include <Windows.h>
+#include <shellapi.h>
+#include <stdexcept>
 #include <windowsx.h>
 #include <windowsx.h>
 #include <d3d11_1.h>
 #include <d3d11_1.h>
 #include <dxgi1_2.h>
 #include <dxgi1_2.h>
 #include <DirectXMath.h>
 #include <DirectXMath.h>
 #include <d3dcompiler.h>
 #include <d3dcompiler.h>
 #include "ModelLoader.h"
 #include "ModelLoader.h"
+#include "UTFConverter.h"
+#include "SafeRelease.hpp"
 
 
 #pragma comment (lib, "d3d11.lib")
 #pragma comment (lib, "d3d11.lib")
 #pragma comment (lib, "Dxgi.lib")
 #pragma comment (lib, "Dxgi.lib")
@@ -27,6 +31,10 @@
 #pragma comment (lib, "dxguid.lib")
 #pragma comment (lib, "dxguid.lib")
 
 
 using namespace DirectX;
 using namespace DirectX;
+using namespace AssimpSamples::SharedCode;
+
+#define VERTEX_SHADER_FILE L"VertexShader.hlsl"
+#define PIXEL_SHADER_FILE L"PixelShader.hlsl"
 
 
 // ------------------------------------------------------------
 // ------------------------------------------------------------
 //                        Structs
 //                        Structs
@@ -45,29 +53,32 @@ struct ConstantBuffer {
 
 
 const char g_szClassName[] = "directxWindowClass";
 const char g_szClassName[] = "directxWindowClass";
 
 
+static std::string g_ModelPath;
 
 
 UINT width, height;
 UINT width, height;
-HWND hwnd;
+HWND hwnd = nullptr;
 
 
 // ------------------------------------------------------------
 // ------------------------------------------------------------
 //                        DirectX Variables
 //                        DirectX Variables
 // ------------------------------------------------------------
 // ------------------------------------------------------------
 D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
 D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
 D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
 D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
-ID3D11Device *dev;
-ID3D11Device1 *dev1;
-ID3D11DeviceContext *devcon;
-ID3D11DeviceContext1 *devcon1;
-IDXGISwapChain *swapchain;
-IDXGISwapChain1 *swapchain1;
-ID3D11RenderTargetView *backbuffer;
-ID3D11VertexShader *pVS;
-ID3D11PixelShader *pPS;
-ID3D11InputLayout *pLayout;
-ID3D11Buffer *pConstantBuffer;
-ID3D11Texture2D *g_pDepthStencil;
-ID3D11DepthStencilView *g_pDepthStencilView;
-ID3D11SamplerState *TexSamplerState;
+ID3D11Device *dev = nullptr;
+ID3D11Device1 *dev1 = nullptr;
+ID3D11DeviceContext *devcon = nullptr;
+ID3D11DeviceContext1 *devcon1 = nullptr;
+IDXGISwapChain *swapchain = nullptr;
+IDXGISwapChain1 *swapchain1 = nullptr;
+ID3D11RenderTargetView *backbuffer = nullptr;
+ID3D11VertexShader *pVS = nullptr;
+ID3D11PixelShader *pPS = nullptr;
+ID3D11InputLayout *pLayout = nullptr;
+ID3D11Buffer *pConstantBuffer = nullptr;
+ID3D11Texture2D *g_pDepthStencil = nullptr;
+ID3D11DepthStencilView *g_pDepthStencilView = nullptr;
+ID3D11SamplerState *TexSamplerState = nullptr;
+ID3D11RasterizerState *rasterstate = nullptr;
+ID3D11Debug* d3d11debug = nullptr;
 
 
 XMMATRIX m_World;
 XMMATRIX m_World;
 XMMATRIX m_View;
 XMMATRIX m_View;
@@ -91,7 +102,7 @@ void Throwanerror(LPCSTR errormessage);
 //                        Our Model
 //                        Our Model
 // ------------------------------------------------------------
 // ------------------------------------------------------------
 
 
-ModelLoader *ourModel;
+ModelLoader *ourModel = nullptr;
 
 
 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 {
 {
@@ -109,9 +120,42 @@ LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 	return 0;
 	return 0;
 }
 }
 
 
-int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
-	LPSTR lpCmdLine, int nCmdShow)
+int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
+	LPWSTR lpCmdLine, int nCmdShow)
 {
 {
+	int argc;
+	LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+	if (!argv) {
+		MessageBox(NULL, 
+			TEXT("An error occured while reading command line arguments."),
+			TEXT("Error!"),
+			MB_ICONERROR | MB_OK);
+		return EXIT_FAILURE;
+	}
+
+	// Free memory allocated from CommandLineToArgvW.
+	auto free_command_line_allocated_memory = [&argv]() {
+		if (argv) {
+			LocalFree(argv);
+			argv = nullptr;
+		}
+	};
+
+	// Ensure that a model file has been specified.
+	if (argc < 2) {
+		MessageBox(NULL, 
+			TEXT("No model file specified. The program will now close."), 
+			TEXT("Error!"),
+			MB_ICONERROR | MB_OK);
+		free_command_line_allocated_memory();
+		return EXIT_FAILURE;
+	}
+
+	// Retrieve the model file path.
+	g_ModelPath = UTFConverter(argv[1]).str();
+
+	free_command_line_allocated_memory();
+	
 	WNDCLASSEX wc;
 	WNDCLASSEX wc;
 	MSG msg;
 	MSG msg;
 
 
@@ -160,26 +204,35 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
 	width = wr.right - wr.left;
 	width = wr.right - wr.left;
 	height = wr.bottom - wr.top;
 	height = wr.bottom - wr.top;
 
 
-	InitD3D(hInstance, hwnd);
+	try {
+		InitD3D(hInstance, hwnd);
 
 
-	while (true)
-	{
-
-		if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+		while (true)
 		{
 		{
-			TranslateMessage(&msg);
-			DispatchMessage(&msg);
 
 
-			if (msg.message == WM_QUIT)
-				break;
-		}
+			if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
+			{
+				TranslateMessage(&msg);
+				DispatchMessage(&msg);
 
 
-		RenderFrame();
-	}
+				if (msg.message == WM_QUIT)
+					break;
+			}
 
 
-	CleanD3D();
+			RenderFrame();
+		}
 
 
-	return msg.wParam;
+		CleanD3D();
+		return static_cast<int>(msg.wParam);
+	} catch (const std::exception& e) {
+		MessageBox(hwnd, e.what(), TEXT("Error!"), MB_ICONERROR | MB_OK);
+		CleanD3D();
+		return EXIT_FAILURE;
+	} catch (...) {
+		MessageBox(hwnd, TEXT("Caught an unknown exception."), TEXT("Error!"), MB_ICONERROR | MB_OK);
+		CleanD3D();
+		return EXIT_FAILURE;
+	}
 }
 }
 
 
 void InitD3D(HINSTANCE hinstance, HWND hWnd)
 void InitD3D(HINSTANCE hinstance, HWND hWnd)
@@ -227,6 +280,12 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 	if (FAILED(hr))
 	if (FAILED(hr))
 		Throwanerror("Directx Device Creation Failed!");
 		Throwanerror("Directx Device Creation Failed!");
 
 
+#if _DEBUG
+	hr = dev->QueryInterface(IID_PPV_ARGS(&d3d11debug));
+	if (FAILED(hr))
+		OutputDebugString(TEXT("Failed to retrieve DirectX 11 debug interface.\n"));
+#endif
+
 	UINT m4xMsaaQuality;
 	UINT m4xMsaaQuality;
 	dev->CheckMultisampleQualityLevels(
 	dev->CheckMultisampleQualityLevels(
 		DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
 		DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
@@ -348,7 +407,6 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 	devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
 	devcon->OMSetRenderTargets(1, &backbuffer, g_pDepthStencilView);
 
 
 	D3D11_RASTERIZER_DESC rasterDesc;
 	D3D11_RASTERIZER_DESC rasterDesc;
-	ID3D11RasterizerState *rasterState;
 	rasterDesc.AntialiasedLineEnable = false;
 	rasterDesc.AntialiasedLineEnable = false;
 	rasterDesc.CullMode = D3D11_CULL_BACK;
 	rasterDesc.CullMode = D3D11_CULL_BACK;
 	rasterDesc.DepthBias = 0;
 	rasterDesc.DepthBias = 0;
@@ -360,8 +418,8 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 	rasterDesc.ScissorEnable = false;
 	rasterDesc.ScissorEnable = false;
 	rasterDesc.SlopeScaledDepthBias = 0.0f;
 	rasterDesc.SlopeScaledDepthBias = 0.0f;
 
 
-	dev->CreateRasterizerState(&rasterDesc, &rasterState);
-	devcon->RSSetState(rasterState);
+	dev->CreateRasterizerState(&rasterDesc, &rasterstate);
+	devcon->RSSetState(rasterstate);
 
 
 	D3D11_VIEWPORT viewport;
 	D3D11_VIEWPORT viewport;
 	ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
 	ZeroMemory(&viewport, sizeof(D3D11_VIEWPORT));
@@ -381,19 +439,38 @@ void InitD3D(HINSTANCE hinstance, HWND hWnd)
 
 
 void CleanD3D(void)
 void CleanD3D(void)
 {
 {
-	swapchain->SetFullscreenState(FALSE, NULL);
-
-	ourModel->Close();
-	g_pDepthStencil->Release();
-	g_pDepthStencilView->Release();
-	pLayout->Release();
-	pVS->Release();
-	pPS->Release();
-	pConstantBuffer->Release();
-	swapchain->Release();
-	backbuffer->Release();
-	dev->Release();
-	devcon->Release();
+	if (swapchain)
+		swapchain->SetFullscreenState(FALSE, NULL);
+
+	if (ourModel) {
+		ourModel->Close();
+		delete ourModel;
+		ourModel = nullptr;
+	}
+	SafeRelease(TexSamplerState);
+	SafeRelease(pConstantBuffer);
+	SafeRelease(pLayout);
+	SafeRelease(pVS);
+	SafeRelease(pPS);
+	SafeRelease(rasterstate);
+	SafeRelease(g_pDepthStencilView);
+	SafeRelease(g_pDepthStencil);
+	SafeRelease(backbuffer);
+	SafeRelease(swapchain);
+	SafeRelease(swapchain1);
+	SafeRelease(devcon1);
+	SafeRelease(dev1);
+	SafeRelease(devcon);
+#if _DEBUG
+	if (d3d11debug) {
+		OutputDebugString(TEXT("Dumping DirectX 11 live objects.\n"));
+		d3d11debug->ReportLiveDeviceObjects(D3D11_RLDO_DETAIL);
+		SafeRelease(d3d11debug);
+	} else {
+		OutputDebugString(TEXT("Unable to dump live objects: no DirectX 11 debug interface available.\n"));
+	}
+#endif
+	SafeRelease(dev);
 }
 }
 
 
 void RenderFrame(void)
 void RenderFrame(void)
@@ -431,8 +508,10 @@ void RenderFrame(void)
 void InitPipeline()
 void InitPipeline()
 {
 {
 	ID3DBlob *VS, *PS;
 	ID3DBlob *VS, *PS;
-	CompileShaderFromFile(L"VertexShader.hlsl", 0, "main", "vs_4_0", &VS);
-	CompileShaderFromFile(L"PixelShader.hlsl", 0, "main", "ps_4_0", &PS);
+	if(FAILED(CompileShaderFromFile(SHADER_PATH VERTEX_SHADER_FILE, 0, "main", "vs_4_0", &VS)))
+		Throwanerror(UTFConverter(L"Failed to compile shader from file " VERTEX_SHADER_FILE).c_str());
+	if(FAILED(CompileShaderFromFile(SHADER_PATH PIXEL_SHADER_FILE, 0, "main", "ps_4_0", &PS)))
+		Throwanerror(UTFConverter(L"Failed to compile shader from file " PIXEL_SHADER_FILE).c_str());
 
 
 	dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
 	dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
 	dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
 	dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);
@@ -485,7 +564,7 @@ void InitGraphics()
 	m_View = XMMatrixLookAtLH(Eye, At, Up);
 	m_View = XMMatrixLookAtLH(Eye, At, Up);
 
 
 	ourModel = new ModelLoader;
 	ourModel = new ModelLoader;
-	if (!ourModel->Load(hwnd, dev, devcon, "Models/myModel.fbx"))
+	if (!ourModel->Load(hwnd, dev, devcon, g_ModelPath))
 		Throwanerror("Model couldn't be loaded");
 		Throwanerror("Model couldn't be loaded");
 }
 }
 
 
@@ -514,5 +593,5 @@ HRESULT	CompileShaderFromFile(LPCWSTR pFileName, const D3D_SHADER_MACRO* pDefine
 
 
 void Throwanerror(LPCSTR errormessage)
 void Throwanerror(LPCSTR errormessage)
 {
 {
-	MessageBox(hwnd, errormessage, "Error!", MB_ICONERROR | MB_OK);
-}
+	throw std::runtime_error(errormessage);
+}

+ 8 - 5
samples/SimpleTexturedOpenGL/CMakeLists.txt

@@ -6,21 +6,22 @@ IF ( NOT GLUT_FOUND )
     SET ( GLUT_FOUND 1 )
     SET ( GLUT_FOUND 1 )
     SET ( GLUT_INCLUDE_DIR ${Assimp_SOURCE_DIR}/samples/freeglut/ )
     SET ( GLUT_INCLUDE_DIR ${Assimp_SOURCE_DIR}/samples/freeglut/ )
     SET ( GLUT_LIBRARIES ${Assimp_SOURCE_DIR}/samples/freeglut/lib/freeglut.lib )
     SET ( GLUT_LIBRARIES ${Assimp_SOURCE_DIR}/samples/freeglut/lib/freeglut.lib )
-  ELSE ( MSVC )
+  ELSE ()
     MESSAGE( WARNING "Please install glut." )
     MESSAGE( WARNING "Please install glut." )
-  ENDIF ( MSVC )
-ENDIF ( NOT GLUT_FOUND )
+  ENDIF ()
+ENDIF ()
 
 
 if ( MSVC )
 if ( MSVC )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_SCL_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
-endif ( MSVC )
+endif ()
 
 
 INCLUDE_DIRECTORIES(
 INCLUDE_DIRECTORIES(
   ${Assimp_SOURCE_DIR}/include
   ${Assimp_SOURCE_DIR}/include
   ${Assimp_SOURCE_DIR}/code
   ${Assimp_SOURCE_DIR}/code
   ${OPENGL_INCLUDE_DIR}
   ${OPENGL_INCLUDE_DIR}
   ${GLUT_INCLUDE_DIR}
   ${GLUT_INCLUDE_DIR}
+  ${SAMPLES_SHARED_CODE_DIR}
 )
 )
 
 
 LINK_DIRECTORIES(
 LINK_DIRECTORIES(
@@ -31,11 +32,13 @@ LINK_DIRECTORIES(
 ADD_EXECUTABLE( assimp_simpletexturedogl WIN32
 ADD_EXECUTABLE( assimp_simpletexturedogl WIN32
   SimpleTexturedOpenGL/include/boost_includes.h
   SimpleTexturedOpenGL/include/boost_includes.h
   SimpleTexturedOpenGL/src/model_loading.cpp
   SimpleTexturedOpenGL/src/model_loading.cpp
+  ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.cpp
+  ${SAMPLES_SHARED_CODE_DIR}/UTFConverter.h
 )
 )
 
 
 SET_PROPERTY(TARGET assimp_simpletexturedogl PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
 SET_PROPERTY(TARGET assimp_simpletexturedogl PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
 
 
-TARGET_LINK_LIBRARIES( assimp_simpletexturedogl assimp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} DevIL.lib )
+TARGET_LINK_LIBRARIES( assimp_simpletexturedogl assimp ${OPENGL_LIBRARIES} ${GLUT_LIBRARIES} )
 
 
 SET_TARGET_PROPERTIES( assimp_simpletexturedogl PROPERTIES
 SET_TARGET_PROPERTIES( assimp_simpletexturedogl PROPERTIES
   OUTPUT_NAME assimp_simpletexturedogl
   OUTPUT_NAME assimp_simpletexturedogl

+ 62 - 40
samples/SimpleTexturedOpenGL/SimpleTexturedOpenGL/src/model_loading.cpp

@@ -33,7 +33,7 @@
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/LogStream.hpp>
 #include <assimp/LogStream.hpp>
-
+#include "UTFConverter.h"
 
 
 // The default hard-coded path. Can be overridden by supplying a path through the command line.
 // The default hard-coded path. Can be overridden by supplying a path through the command line.
 static std::string modelpath = "../../test/models/OBJ/spider.obj";
 static std::string modelpath = "../../test/models/OBJ/spider.obj";
@@ -75,6 +75,8 @@ GLuint*		textureIds;							// pointer to texture Array
 // Create an instance of the Importer class
 // Create an instance of the Importer class
 Assimp::Importer importer;
 Assimp::Importer importer;
 
 
+using namespace AssimpSamples::SharedCode;
+
 void createAILogger()
 void createAILogger()
 {
 {
     // Change this line to normal if you not want to analyse the import process
     // Change this line to normal if you not want to analyse the import process
@@ -120,7 +122,7 @@ bool Import3DFromFile( const std::string& pFile)
 	}
 	}
 	else
 	else
 	{
 	{
-		MessageBox(NULL, ("Couldn't open file: " + pFile).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION);
+		MessageBox(NULL, UTFConverter("Couldn't open file: " + pFile).c_wstr() , TEXT("ERROR"), MB_OK | MB_ICONEXCLAMATION);
 		logInfo( importer.GetErrorString());
 		logInfo( importer.GetErrorString());
 		return false;
 		return false;
 	}
 	}
@@ -170,8 +172,21 @@ std::string getBasePath(const std::string& path)
 	return (std::string::npos == pos) ? "" : path.substr(0, pos + 1);
 	return (std::string::npos == pos) ? "" : path.substr(0, pos + 1);
 }
 }
 
 
+void freeTextureIds()
+{
+	textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step)
+
+	if (textureIds)
+	{
+		delete[] textureIds;
+		textureIds = NULL;
+	}
+}
+
 int LoadGLTextures(const aiScene* scene)
 int LoadGLTextures(const aiScene* scene)
 {
 {
+	freeTextureIds();
+
 	//ILboolean success;
 	//ILboolean success;
 
 
 	/* Before calling ilInit() version should be checked. */
 	/* Before calling ilInit() version should be checked. */
@@ -205,7 +220,7 @@ int LoadGLTextures(const aiScene* scene)
 		}
 		}
 	}
 	}
 
 
-	int numTextures = textureIdMap.size();
+	const size_t numTextures = textureIdMap.size();
 
 
 
 
 	/* array with DevIL image IDs */
 	/* array with DevIL image IDs */
@@ -217,13 +232,13 @@ int LoadGLTextures(const aiScene* scene)
 
 
 	/* create and fill array with GL texture ids */
 	/* create and fill array with GL texture ids */
 	textureIds = new GLuint[numTextures];
 	textureIds = new GLuint[numTextures];
-	glGenTextures(numTextures, textureIds); /* Texture name generation */
+	glGenTextures(static_cast<GLsizei>(numTextures), textureIds); /* Texture name generation */
 
 
 	/* get iterator */
 	/* get iterator */
 	std::map<std::string, GLuint*>::iterator itr = textureIdMap.begin();
 	std::map<std::string, GLuint*>::iterator itr = textureIdMap.begin();
 
 
 	std::string basepath = getBasePath(modelpath);
 	std::string basepath = getBasePath(modelpath);
-	for (int i=0; i<numTextures; i++)
+	for (size_t i=0; i<numTextures; i++)
 	{
 	{
 
 
 		//save IL image ID
 		//save IL image ID
@@ -268,7 +283,7 @@ int LoadGLTextures(const aiScene* scene)
 		else
 		else
 		{
 		{
 			/* Error occurred */
 			/* Error occurred */
-			MessageBox(NULL, ("Couldn't load Image: " + fileloc).c_str() , "ERROR", MB_OK | MB_ICONEXCLAMATION);
+			MessageBox(NULL, UTFConverter("Couldn't load Image: " + fileloc).c_wstr(), TEXT("ERROR"), MB_OK | MB_ICONEXCLAMATION);
 		}
 		}
 	}
 	}
     // Because we have already copied image data into texture data  we can release memory used by image.
     // Because we have already copied image data into texture data  we can release memory used by image.
@@ -534,31 +549,34 @@ void KillGLWindow()			// Properly Kill The Window
 	{
 	{
 		if (!wglMakeCurrent(NULL, NULL))	// Are We Able To Release The DC And RC Contexts?
 		if (!wglMakeCurrent(NULL, NULL))	// Are We Able To Release The DC And RC Contexts?
 		{
 		{
-			MessageBox(NULL, "Release Of DC And RC Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
+			MessageBox(NULL, TEXT("Release Of DC And RC Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
 		}
 		}
 
 
 		if (!wglDeleteContext(hRC))			// Are We Able To Delete The RC?
 		if (!wglDeleteContext(hRC))			// Are We Able To Delete The RC?
 		{
 		{
-			MessageBox(NULL, "Release Rendering Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
+			MessageBox(NULL, TEXT("Release Rendering Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
 		}
 		}
 		hRC = NULL;
 		hRC = NULL;
 	}
 	}
 
 
-	if (hDC && !ReleaseDC(hWnd, hDC))	// Are We able to Release The DC?
+	if (hDC)
 	{
 	{
-		MessageBox(NULL, "Release Device Context Failed.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
-		hDC=NULL;
+		if (!ReleaseDC(hWnd, hDC)) // Are We able to Release The DC?
+			MessageBox(NULL, TEXT("Release Device Context Failed."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
+		hDC = NULL;
 	}
 	}
 
 
-	if (hWnd && !DestroyWindow(hWnd))	// Are We Able To Destroy The Window
+	if (hWnd)
 	{
 	{
-		MessageBox(NULL, "Could Not Release hWnd.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
+		if (!DestroyWindow(hWnd)) // Are We Able To Destroy The Window
+			MessageBox(NULL, TEXT("Could Not Release hWnd."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
 		hWnd = NULL;
 		hWnd = NULL;
-	}
+	} 
 
 
-	if (!UnregisterClass("OpenGL", hInstance))	// Are We Able To Unregister Class
+	if (hInstance)
 	{
 	{
-		MessageBox(NULL, "Could Not Unregister Class.", "SHUTDOWN ERROR", MB_OK | MB_ICONINFORMATION);
+		if (!UnregisterClass(TEXT("OpenGL"), hInstance)) // Are We Able To Unregister Class
+			MessageBox(NULL, TEXT("Could Not Unregister Class."), TEXT("SHUTDOWN ERROR"), MB_OK | MB_ICONINFORMATION);
 		hInstance = NULL;
 		hInstance = NULL;
 	}
 	}
 }
 }
@@ -566,7 +584,7 @@ void KillGLWindow()			// Properly Kill The Window
 GLboolean abortGLInit(const char* abortMessage)
 GLboolean abortGLInit(const char* abortMessage)
 {
 {
 	KillGLWindow();									// Reset Display
 	KillGLWindow();									// Reset Display
-	MessageBox(NULL, abortMessage, "ERROR", MB_OK|MB_ICONEXCLAMATION);
+	MessageBox(NULL, UTFConverter(abortMessage).c_wstr(), TEXT("ERROR"), MB_OK|MB_ICONEXCLAMATION);
 	return FALSE;									// quit and return False
 	return FALSE;									// quit and return False
 }
 }
 
 
@@ -594,11 +612,11 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 	wc.hCursor		= LoadCursor(NULL, IDC_ARROW);	// Load the default arrow
 	wc.hCursor		= LoadCursor(NULL, IDC_ARROW);	// Load the default arrow
 	wc.hbrBackground= NULL;							// No Background required for OpenGL
 	wc.hbrBackground= NULL;							// No Background required for OpenGL
 	wc.lpszMenuName	= NULL;							// No Menu
 	wc.lpszMenuName	= NULL;							// No Menu
-	wc.lpszClassName= "OpenGL";						// Class Name
+	wc.lpszClassName= TEXT("OpenGL");		        // Class Name
 
 
 	if (!RegisterClass(&wc))
 	if (!RegisterClass(&wc))
 	{
 	{
-		MessageBox(NULL, "Failed to register the window class", "ERROR", MB_OK | MB_ICONEXCLAMATION);
+		MessageBox(NULL, TEXT("Failed to register the window class"), TEXT("ERROR"), MB_OK | MB_ICONEXCLAMATION);
 		return FALSE;		//exit and return false
 		return FALSE;		//exit and return false
 	}
 	}
 
 
@@ -616,14 +634,14 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 		if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
 		if (ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN)!=DISP_CHANGE_SUCCESSFUL)
 		{
 		{
 			// If The Mode Fails, Offer Two Options.  Quit Or Run In A Window.
 			// If The Mode Fails, Offer Two Options.  Quit Or Run In A Window.
-			if (MessageBox(NULL,"The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?","NeHe GL",MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
+			if (MessageBox(NULL,TEXT("The Requested Fullscreen Mode Is Not Supported By\nYour Video Card. Use Windowed Mode Instead?"),TEXT("NeHe GL"),MB_YESNO|MB_ICONEXCLAMATION)==IDYES)
 			{
 			{
 				fullscreen = FALSE;		// Select Windowed Mode (Fullscreen = FALSE)
 				fullscreen = FALSE;		// Select Windowed Mode (Fullscreen = FALSE)
 			}
 			}
 			else
 			else
 			{
 			{
 				//Popup Messagebox: Closing
 				//Popup Messagebox: Closing
-				MessageBox(NULL, "Program will close now.", "ERROR", MB_OK|MB_ICONSTOP);
+				MessageBox(NULL, TEXT("Program will close now."), TEXT("ERROR"), MB_OK|MB_ICONSTOP);
 				return FALSE; //exit, return false
 				return FALSE; //exit, return false
 			}
 			}
 		}
 		}
@@ -644,8 +662,8 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requestes Size
 	AdjustWindowRectEx(&WindowRect, dwStyle, FALSE, dwExStyle);		// Adjust Window To True Requestes Size
 
 
 	if (!(hWnd=CreateWindowEx(	dwExStyle,						// Extended Style For The Window
 	if (!(hWnd=CreateWindowEx(	dwExStyle,						// Extended Style For The Window
-								"OpenGL",						// Class Name
-								title,							// Window Title
+								TEXT("OpenGL"),						// Class Name
+								UTFConverter(title).c_wstr(),							// Window Title
 								WS_CLIPSIBLINGS |				// Required Window Style
 								WS_CLIPSIBLINGS |				// Required Window Style
 								WS_CLIPCHILDREN |				// Required Window Style
 								WS_CLIPCHILDREN |				// Required Window Style
 								dwStyle,						// Selected WIndow Style
 								dwStyle,						// Selected WIndow Style
@@ -729,6 +747,16 @@ BOOL CreateGLWindow(const char* title, int width, int height, int bits, bool ful
 	return TRUE;
 	return TRUE;
 }
 }
 
 
+void cleanup()
+{
+	freeTextureIds();
+
+	destroyAILogger();
+
+	if (hWnd)
+		KillGLWindow();
+};
+
 LRESULT CALLBACK WndProc(HWND hWnd,				// Handles for this Window
 LRESULT CALLBACK WndProc(HWND hWnd,				// Handles for this Window
 						 UINT uMsg,				// Message for this Window
 						 UINT uMsg,				// Message for this Window
 						 WPARAM wParam,			// additional message Info
 						 WPARAM wParam,			// additional message Info
@@ -807,20 +835,25 @@ int WINAPI WinMain( HINSTANCE hInstance,         // The instance
 	if (argv != NULL && argc > 1)
 	if (argv != NULL && argc > 1)
 	{
 	{
 		std::wstring modelpathW(argv[1]);
 		std::wstring modelpathW(argv[1]);
-		modelpath = std::string(modelpathW.begin(), modelpathW.end());
+		modelpath = UTFConverter(modelpathW).str();
 	}
 	}
 
 
-	if (!Import3DFromFile(modelpath)) return 0;
+	if (!Import3DFromFile(modelpath))
+	{
+		cleanup();
+		return 0;
+	}
 
 
 	logInfo("=============== Post Import ====================");
 	logInfo("=============== Post Import ====================");
 
 
-	if (MessageBox(NULL, "Would You Like To Run In Fullscreen Mode?", "Start Fullscreen?", MB_YESNO|MB_ICONEXCLAMATION)==IDNO)
+	if (MessageBox(NULL, TEXT("Would You Like To Run In Fullscreen Mode?"), TEXT("Start Fullscreen?"), MB_YESNO|MB_ICONEXCLAMATION)==IDNO)
 	{
 	{
 		fullscreen=FALSE;
 		fullscreen=FALSE;
 	}
 	}
 
 
 	if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen))
 	if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen))
 	{
 	{
+		cleanup();
 		return 0;
 		return 0;
 	}
 	}
 
 
@@ -861,6 +894,7 @@ int WINAPI WinMain( HINSTANCE hInstance,         // The instance
 				fullscreen=!fullscreen;
 				fullscreen=!fullscreen;
 				if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen))
 				if (!CreateGLWindow(windowTitle, 640, 480, 16, fullscreen))
 				{
 				{
+					cleanup();
 					return 0;
 					return 0;
 				}
 				}
 			}
 			}
@@ -868,18 +902,6 @@ int WINAPI WinMain( HINSTANCE hInstance,         // The instance
 	}
 	}
 
 
 	// *** cleanup ***
 	// *** cleanup ***
-
-	textureIdMap.clear(); //no need to delete pointers in it manually here. (Pointers point to textureIds deleted in next step)
-
-	if (textureIds)
-	{
-		delete[] textureIds;
-		textureIds = NULL;
-	}
-
-	// *** cleanup end ***
-
-	destroyAILogger();
-	KillGLWindow();
-	return (msg.wParam);
+	cleanup();
+	return static_cast<int>(msg.wParam);
 }
 }

+ 3 - 10
test/CMakeLists.txt

@@ -201,20 +201,13 @@ SET_PROPERTY( TARGET assimp PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} )
 
 
 IF( WIN32 )
 IF( WIN32 )
     SET( platform_libs )
     SET( platform_libs )
-ELSE( WIN32 )
+ELSE()
     SET( platform_libs pthread )
     SET( platform_libs pthread )
-ENDIF( WIN32 )
-
-IF( WIN32 )
-  ADD_CUSTOM_COMMAND(TARGET unit
-    PRE_BUILD
-    COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:assimp> $<TARGET_FILE_DIR:unit>
-    MAIN_DEPENDENCY assimp)
-ENDIF( WIN32 )
+ENDIF()
 
 
 IF(MSVC)
 IF(MSVC)
 		add_definitions(-D_CRT_SECURE_NO_WARNINGS)
 		add_definitions(-D_CRT_SECURE_NO_WARNINGS)
-ENDIF(MSVC)
+ENDIF()
 
 
 target_link_libraries( unit assimp ${platform_libs} )
 target_link_libraries( unit assimp ${platform_libs} )
 
 

+ 1 - 1
test/headercheck/CMakeLists.txt

@@ -30,7 +30,7 @@ FOREACH( HEADER ${headers} )
   # add library
   # add library
   add_library( ${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_FILE} )
   add_library( ${TEST_NAME} EXCLUDE_FROM_ALL ${TEST_FILE} )
   list(APPEND headerchecklibs ${TEST_NAME})
   list(APPEND headerchecklibs ${TEST_NAME})
-ENDFOREACH( HEADER )
+ENDFOREACH()
 
 
 add_custom_target(headercheck DEPENDS ${headerchecklibs})
 add_custom_target(headercheck DEPENDS ${headerchecklibs})
 
 

+ 1 - 8
tools/assimp_cmd/CMakeLists.txt

@@ -37,7 +37,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
 #
 #----------------------------------------------------------------------
 #----------------------------------------------------------------------
-cmake_minimum_required( VERSION 2.6 )
+cmake_minimum_required( VERSION 3.0 )
 
 
 INCLUDE_DIRECTORIES(
 INCLUDE_DIRECTORIES(
   ${Assimp_SOURCE_DIR}/include
   ${Assimp_SOURCE_DIR}/include
@@ -61,13 +61,6 @@ ADD_EXECUTABLE( assimp_cmd
 
 
 SET_PROPERTY(TARGET assimp_cmd PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
 SET_PROPERTY(TARGET assimp_cmd PROPERTY DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX})
 
 
-IF( WIN32 )
-  ADD_CUSTOM_COMMAND(TARGET assimp_cmd
-    PRE_BUILD
-    COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:assimp> $<TARGET_FILE_DIR:assimp_cmd>
-    MAIN_DEPENDENCY assimp)
-ENDIF( WIN32 )
-
 TARGET_LINK_LIBRARIES( assimp_cmd assimp ${ZLIB_LIBRARIES} )
 TARGET_LINK_LIBRARIES( assimp_cmd assimp ${ZLIB_LIBRARIES} )
 SET_TARGET_PROPERTIES( assimp_cmd PROPERTIES
 SET_TARGET_PROPERTIES( assimp_cmd PROPERTIES
   OUTPUT_NAME assimp
   OUTPUT_NAME assimp

+ 2 - 9
tools/assimp_view/CMakeLists.txt

@@ -37,7 +37,7 @@
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #
 #
 #----------------------------------------------------------------------
 #----------------------------------------------------------------------
-cmake_minimum_required( VERSION 2.6 )
+cmake_minimum_required( VERSION 3.0 )
 
 
 FIND_PACKAGE(DirectX REQUIRED)
 FIND_PACKAGE(DirectX REQUIRED)
 
 
@@ -90,14 +90,7 @@ IF ( MSVC )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
   ADD_DEFINITIONS( -D_CRT_SECURE_NO_WARNINGS )
   # assimp_viewer is ANSI (MBCS) throughout
   # assimp_viewer is ANSI (MBCS) throughout
   REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE )
   REMOVE_DEFINITIONS( -DUNICODE -D_UNICODE )
-ENDIF ( MSVC )
-
-
-#
-ADD_CUSTOM_COMMAND(TARGET assimp_viewer
-  PRE_BUILD
-  COMMAND ${CMAKE_COMMAND} -E copy_if_different $<TARGET_FILE:assimp> $<TARGET_FILE_DIR:assimp_viewer>
-  MAIN_DEPENDENCY assimp)
+ENDIF ()
 
 
 # Link the executable to the assimp + dx libs.
 # Link the executable to the assimp + dx libs.
 TARGET_LINK_LIBRARIES ( assimp_viewer assimp ${DirectX_LIBRARY} ${DirectX_D3DX9_LIBRARY} comctl32.lib winmm.lib )
 TARGET_LINK_LIBRARIES ( assimp_viewer assimp ${DirectX_LIBRARY} ${DirectX_D3DX9_LIBRARY} comctl32.lib winmm.lib )