浏览代码

Merge pull request #1 from assimp/master

pull from assimp
Brendan Hack 7 年之前
父节点
当前提交
5c6c87c7b1
共有 100 个文件被更改,包括 2368 次插入1152 次删除
  1. 3 0
      .gitignore
  2. 258 0
      CHANGES
  3. 65 88
      CMakeLists.txt
  4. 10 0
      CONTRIBUTING.md
  5. 16 1
      CREDITS
  6. 3 0
      INSTALL
  7. 24 24
      Readme.md
  8. 4 0
      appveyor.yml
  9. 3 25
      assimp-config.cmake.in
  10. 18 16
      code/3DSConverter.cpp
  11. 4 3
      code/3DSExporter.cpp
  12. 3 2
      code/3DSExporter.h
  13. 88 29
      code/3DSHelper.h
  14. 44 46
      code/3DSLoader.cpp
  15. 2 1
      code/3DSLoader.h
  16. 17 2
      code/3MFXmlTags.h
  17. 21 20
      code/ACLoader.cpp
  18. 2 1
      code/ACLoader.h
  19. 3 2
      code/AMFImporter.cpp
  20. 2 13
      code/AMFImporter.hpp
  21. 2 1
      code/AMFImporter_Geometry.cpp
  22. 6 5
      code/AMFImporter_Macro.hpp
  23. 3 2
      code/AMFImporter_Material.cpp
  24. 2 1
      code/AMFImporter_Node.hpp
  25. 8 6
      code/AMFImporter_Postprocess.cpp
  26. 17 17
      code/ASELoader.cpp
  27. 2 1
      code/ASELoader.h
  28. 35 32
      code/ASEParser.cpp
  29. 91 46
      code/ASEParser.h
  30. 6 5
      code/AssbinExporter.cpp
  31. 2 1
      code/AssbinExporter.h
  32. 2 1
      code/AssbinLoader.cpp
  33. 2 1
      code/AssbinLoader.h
  34. 3 2
      code/Assimp.cpp
  35. 2 1
      code/AssimpCExport.cpp
  36. 6 4
      code/AssxmlExporter.cpp
  37. 2 1
      code/AssxmlExporter.h
  38. 3 2
      code/B3DImporter.cpp
  39. 2 1
      code/B3DImporter.h
  40. 16 14
      code/BVHLoader.cpp
  41. 6 2
      code/BVHLoader.h
  42. 52 41
      code/BaseImporter.cpp
  43. 3 2
      code/BaseProcess.cpp
  44. 2 1
      code/BaseProcess.h
  45. 4 2
      code/Bitmap.cpp
  46. 185 0
      code/BlenderCustomData.cpp
  47. 89 0
      code/BlenderCustomData.h
  48. 12 13
      code/BlenderDNA.cpp
  49. 38 4
      code/BlenderDNA.h
  50. 106 5
      code/BlenderDNA.inl
  51. 8 3
      code/BlenderIntermediate.h
  52. 76 24
      code/BlenderLoader.cpp
  53. 2 1
      code/BlenderLoader.h
  54. 2 29
      code/BlenderModifier.cpp
  55. 30 32
      code/BlenderModifier.h
  56. 45 1
      code/BlenderScene.cpp
  57. 81 2
      code/BlenderScene.h
  58. 11 0
      code/BlenderSceneGen.h
  59. 2 1
      code/BlenderTessellator.cpp
  60. 3 2
      code/BlenderTessellator.h
  61. 2 1
      code/CInterfaceIOWrapper.cpp
  62. 2 1
      code/CInterfaceIOWrapper.h
  63. 28 8
      code/CMakeLists.txt
  64. 30 80
      code/COBLoader.cpp
  65. 3 22
      code/COBLoader.h
  66. 2 1
      code/COBScene.h
  67. 5 4
      code/CSMLoader.cpp
  68. 2 1
      code/CSMLoader.h
  69. 9 8
      code/CalcTangentsProcess.cpp
  70. 2 1
      code/CalcTangentsProcess.h
  71. 11 6
      code/ColladaExporter.cpp
  72. 3 2
      code/ColladaExporter.h
  73. 6 4
      code/ColladaHelper.h
  74. 77 67
      code/ColladaLoader.cpp
  75. 3 1
      code/ColladaLoader.h
  76. 45 29
      code/ColladaParser.cpp
  77. 5 1
      code/ColladaParser.h
  78. 8 7
      code/ComputeUVMappingProcess.cpp
  79. 2 1
      code/ComputeUVMappingProcess.h
  80. 26 17
      code/ConvertToLHProcess.cpp
  81. 2 1
      code/ConvertToLHProcess.h
  82. 77 7
      code/D3MFExporter.cpp
  83. 5 2
      code/D3MFExporter.h
  84. 226 78
      code/D3MFImporter.cpp
  85. 2 1
      code/D3MFImporter.h
  86. 43 32
      code/D3MFOpcPackage.cpp
  87. 9 6
      code/D3MFOpcPackage.h
  88. 3 3
      code/DXFHelper.h
  89. 45 62
      code/DXFLoader.cpp
  90. 2 1
      code/DXFLoader.h
  91. 7 8
      code/DeboneProcess.cpp
  92. 2 1
      code/DeboneProcess.h
  93. 2 1
      code/DefaultIOStream.cpp
  94. 9 8
      code/DefaultIOSystem.cpp
  95. 58 69
      code/DefaultLogger.cpp
  96. 2 1
      code/DefaultProgressHandler.h
  97. 11 12
      code/EmbedTexturesProcess.cpp
  98. 2 1
      code/EmbedTexturesProcess.h
  99. 29 13
      code/Exporter.cpp
  100. 2 1
      code/FBXAnimation.cpp

+ 3 - 0
.gitignore

@@ -12,6 +12,8 @@ build
 bin/
 bin/
 lib/
 lib/
 
 
+# QtCreator
+CMakeLists.txt.user
 
 
 # Generated
 # Generated
 assimp.pc
 assimp.pc
@@ -38,6 +40,7 @@ tools/assimp_cmd/Makefile
 
 
 # Tests
 # Tests
 test/results
 test/results
+test/readlinetest*
 
 
 # Python
 # Python
 __pycache__
 __pycache__

+ 258 - 0
CHANGES

@@ -1,6 +1,264 @@
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 CHANGELOG
 CHANGELOG
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
+4.1.0 (2017-12):
+- FEATURES:
+ - Export 3MF ( experimental )
+ - Import / Export glTF 2
+ - Introduce new zib-lib to eb able to export zip-archives
+- FIXES/HOUSEKEEPING:
+ - Added missing include to stdlib.h and remove load library call
+ - Fix install for builds with MSVC compiler and NMake.
+ - Update list of supported file formats.
+ - Add TriLib to the official list of supported ports.
+ - Re-enabling PACK_STRUCT for MDL files.
+ - Use std.::unique_ptr
+ - Update D3MFExporter.h
+ - Update MD3Loader.cpp, using index
+ - Fix all warnings on MSVC14
+ - Copy assimp dll to unit folder on windows
+ - Update jvm port supported formats
+ - Add support for building Mac OS X Framework bundles
+ - Check for nullptr dereferencing before copying scene data
+ - Update ValidateDataStructure.h, typo
+ - Enable data structure validation in cases where it doesn't cause failures
+ - Remove some dead assignments
+ - fast_atof: Silence some uninitialized variable warnings
+ - Check for area test if the face is a triangle.
+ - Set mNumUVComponents to 0 when deleting texture coordinate sets
+ - Only scale the root node because this will rescale all children nodes as well.
+ - Issue 1514: Fix frame pointer arithmetic
+ - Prevent failing stringstream to crash the export process
+ - powf -> pow
+ - add Defines.h to include folder for install.
+ - Android:
+  - Fix android build
+  - Fix assimp for cross compile for android
+  - Use define for D_FILE_OFFSET_BITS only for not-android systems.
+ - FBX:
+  - Fix handling with embedded textures
+  - FBX 7500 Binary reading
+  - Remove dead assignment
+  - Fix export of deleted meshes; Add LazyDict::Remove method
+  - Log an error instead of letting the fbx-importer crash. ( issue 213 )
+  - Replace bad pointer casting with memcpy
+  - Remove useless const qualifier from return value
+  - Add explicit instantiation of log_prefix so other FBX source files can see it
+  - add missing inversion of postrotation matrix for fbx.
+  - FIReader: Silence uninitialized variable warning
+  - Update version check in FBX reader to check for version >= 7500
+  - Use actual min/max of anim keys when start/stop time is missing
+- GLTF1:
+ - Fix output of glTF 1 version string
+ - Fix delete / delete[] mismatch in glTFAsset
+ - Don’t ignore rgba(1,1,1,1) color properties
+ - glTF2 primitives fixes
+ - Don’t ignore rgba(1,1,1,1) color properties
+ - Fix delete / delete[] mismatch in glTFAsset
+ - Remove KHR_binary_glTF code
+ - glTF nodes can only hold one mesh. this simply assigns to and check’s a Node’s Mesh
+ - version in glb header is stored as uint32_t
+- GLTF2:
+ - node name conflict fix
+ - Fix transform matrices multiplication order
+ - Preserve node names when importing
+ - Add support for tangents in import
+ - Fix typo on gltf2 camera parameters
+ - Moved byteStride from accessor to bufferView
+ - Implemented reading binary glTF2 (glb) files
+ - Fix signed/unsigned warning
+ - Add postprocess step for scaling
+ - Fix shininess to roughness conversion
+ - Prefer “BLEND” over “MASK” as an alphaMode default
+ - Approximate specularity / glossiness in metallicRoughness materials
+ - Diffuse color and diffuse texture import and export improvements
+ - Addressed some mismatched news/deletes caused by the new glTF2 sources.
+ - Fix delete / delete[] mismatches in glTF2 importer
+ - use correct name of exporter to gltf2
+ - Fix possible infinite loop when exporting to gltf2
+ - Fix glTF2::Asset::FindUniqueID() when the input string is >= 256 chars
+ - Fix glTF2 alphaMode storage and reading
+ - Fix glTF 2.0 multi-primitive support
+ - Load gltf .bin files from correct directory
+ - Add support for importing both glTF and glTF2 files
+ - ampler improvements; Add new LazyDict method
+ - Changes to GLTF2 materials
+ - Remove Light, Technique references
+ - Start removing materials common, and adding pbrSpecularGlossiness
+ - Use !ObjectEmpty() vs. MemberCount() > 0
+ - Working read, import, export, and write of gltf2 (pbr) material
+ - Check in gltf2 models to test directory
+ - Remove un-needed test models
+ - Start managing and importing gltf2 pbr materials
+ - Update glTF2 Asset to use indexes
+ - Duplicate gltfImporter as gltf2Importer; Include glTF2 importer in CMake List
+ - glTF2: Fix animation export
+ - use opacity for diffuse alpha + alphaMode
+- STL:
+ - Restore import of multi mesh binary STLs
+- Blender:
+ - Silence warning about uninitialized member
+- MDLImporter:
+ - Don't take address of packed struct member
+- assimp_cmd:
+ - Fix strict-aliasing warnings
+- Open3DGC:
+ - Fix strict-aliasing warnings
+ - Add assertions to silence static analyzer warnings
+ - Remove redundant const qualifiers from return types
+ - Fix some uninitialized variable warnings
+ - Remove OPEN3DGC and compression references
+- unzip:
+ - Remove dead assignment
+ - Bail on bad compression method
+ - Fix possibly uninitialized variables
+- clipper:
+ - Add assertion to silence a static analyzer warning
+- OpenDDLExport:
+ - Reduce scope of a variable
+ - Remove dead variable
+ - Remove dead assignment
+ - Fix another potential memory leak
+- X3DImporter:
+ - Add assertions to silence static analyzer warnings
+ - Add missing unittest
+ - Workaround for buggy Android NDK (issue #1361)
+- TerragenLoader:
+ - Remove unused variable
+- SIBImporter:
+ - Add assertions to silence static analyzer warnings
+- IFC:
+ - Remove dead code
+ - Add explicit instantiation of log_prefix so IFCMaterial.cpp can see it
+- PLY:
+ - Remove dead assignment and reduce scope of a variable
+ - fix vertex attribute lookup.
+- OpenGEX:
+ - Add assertion to silence a static analyzer warning
+ - Fix for TextureFile with number in file name
+ - Return early when element is TextureFile
+- NFF:
+ - Add assertions to silence static analyzer warnings
+ - Split up some complicated assignments
+- Raw: Fix misleading indentation warning
+ - Reduce scope of a variable
+- LWO
+ - Reduce scope of a variable
+- IRRLoader:
+ - Fix confusing boolean casting
+- AssbinExporter:
+ - Add assertion to silence a static analyzer warning
+- ASE:
+ - Add assertion to silence a static analyzer warning
+- AMFImporter:
+ - Add assertion to silence a static analyzer warning
+ - Add a block
+- OptimizeGraph:
+ - Fix possible null pointer dereference
+ - RemoveRedundantMaterials:
+ - Add assertion to silence a static analyzer warning
+- ImproveCacheLocality:
+ - Add assertion to silence a static analyzer warning
+- RemoveRedundantMaterials:
+ - Set pointer to nullptr after deleting it
+- Travis:
+ - Disable unit tests in scan-build config
+ - Move slower builds earlier to improve parallelization
+ - Add static analysis to build
+ - Remove unused branch rule for travis.
+ - Add Clang UBSan build configuration
+ - Treat warnings as errors, without typos this time
+- Unittests:
+ - Add VS-based source groups for the unittests.
+- Collada:
+ - export <library_animations> tag
+ - Update ColladaExporter.cpp
+ - Silence uninitialized variable warning
+ - Add support for line strip primitives
+- Obj Wavefront:
+ - check in exporting against out-of-bounds-access .
+ - Issue 1351: use correct name for obj-meshname export for groups.
+ - fix mem-lead: face will be not released in case of an error.
+ - Anatoscope obj exporter nomtl
+ - Raise exception when obj file contains invalid face indices
+ - Added alternative displacement texture token in OBJ MTL material.
+ - Obj: rename attribute from exporter.
+ - Fix OBJ discarding all material names if the material library is missing
+- Step:
+ - use correct lookup for utf32
+- MD2:
+ - Fix MD2 frames containing garbage
+- STL
+ - add missing const.
+ - Fix memory-alignment bug.
+ - Fix issue 104: deal with more solids in one STL file.
+- CMake
+ - Fix issue 213: use correct include folder for assimp
+- Doxygen
+ - Fix issue 1513: put irrXML onto exclucde list for doxygen run
+- PyAssimp:
+ - Search for libassimp.so in LD_LIBRARY_PATH if available.
+ - Fix operator precedence issue in header check
+ - Split setup.py into multiple lines
+ - Detect if Anaconda and fixed 3d_viewer for Python 3
+ - created a python3 version of the 3dviewer and fixed the / = float in py3
+- Blender:
+ - Fix invalid access to mesh array when the array is empty.
+ - Fix short overflow.
+ - Silence warning about inline function which is declared but not defined
+- JAssimp
+ - Changed license header for IHMC contributions from Apache 2.0 to BSD
+ - Add Node metadata to the Jassmip Java API
+ - Added supported for custom IO Systems in Java. Implemented ClassLoader IO System
+ - Added a link to pure jvm assimp port
+- Clang sanitizer:
+ - Undefined Behavior sanitizer
+ - Fixed a divide by zero error in IFCBoolean that was latent, but nevertheless a bug
+- B3DImporter:
+ - Replace bad pointer casting with memcpy
+- AppVeyor:
+ - Cleanup and Addition of VS 2017 and running Tests
+ - Fixed File Size reported as 0 in tests that use temporary files
+ - x86 isn't a valid VS platform. Win32 it is, then.
+ - Replaced the worker image name, which doesn't work as generator name, with a manually created generator name.
+ - Cleaned up appveyor setup, added VS 2017 to the build matrix and attempted to add running of tests.
+ - Treat warnings as errors on Appveyor
+ - Disable warning 4351 on MSVC 2013
+- OpenGEXImporter:
+ - Copy materials to scene
+ - Store RefInfo in unique_ptr so they get automatically cleaned up
+ - Fix IOStream leak
+ - Store ChildInfo in unique_ptr so they get automatically cleaned up
+ - improve logging to be able to detect error-prone situations.
+-  AMFImporter:
+ - Fix memory leak
+- UnrealLoader:
+ - Fix IOStream leak
+- Upgrade RapidJSON to get rid of a clang warning
+- zlib:
+ - Update zlib contribution
+ - Removed unnecessary files from zlib contribution
+ - Replaced unsigned long for the crc table to z_crc_t, to match what is returned by get-crc_table
+- MakeVerboseFormat:
+  - Fix delete / delete[] mismatches in MakeVerboseFormat
+- MaterialSystem:
+ - Fix out-of-bounds read in MaterialSystem unit test
+- SIB:
+ - Added support for SIB models from Silo 2.5
+- AssbinExporter:
+ - Fix strict aliasing violation
+ - Add Write specialization for aiColor3D
+- DefaultLogger:
+ - Whitespace cleanup to fix GCC misleading indentation warning
+- MDP:
+ - Fix encoding issues.
+ - PreTransformVertices:
+ - fix name lost in mesh and nodes when load with flag
+- C4D:
+ - Fixes for C4D importer
+- Unzip:
+ - Latest greatest.
+
 4.0.1 (2017-07-28)
 4.0.1 (2017-07-28)
     - FIXES/HOUSEKEEPING:
     - FIXES/HOUSEKEEPING:
     - fix version test.
     - fix version test.

+ 65 - 88
CMakeLists.txt

@@ -1,6 +1,7 @@
 # Open Asset Import Library (assimp)
 # Open Asset Import Library (assimp)
 # ----------------------------------------------------------------------
 # ----------------------------------------------------------------------
-# Copyright (c) 2006-2017, assimp team
+# Copyright (c) 2006-2018, 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,
@@ -109,7 +110,6 @@ if (WIN32)
 endif()
 endif()
 
 
 IF(MSVC)
 IF(MSVC)
-  SET (CMAKE_PREFIX_PATH "D:\\libs\\devil")
   OPTION( ASSIMP_INSTALL_PDB
   OPTION( ASSIMP_INSTALL_PDB
     "Install MSVC debug files."
     "Install MSVC debug files."
     ON
     ON
@@ -138,8 +138,7 @@ SET (PROJECT_VERSION "${ASSIMP_VERSION}")
 
 
 SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
 SET( ASSIMP_PACKAGE_VERSION "0" CACHE STRING "the package-specific version used for uploading the sources" )
 
 
-# Needed for openddl_parser config, no use of c++11 at this moment
-ADD_DEFINITIONS( -DOPENDDL_NO_USE_CPP11 )
+# Enable C++1 globally
 set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
 set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
 
 
 # Get the current working branch
 # Get the current working branch
@@ -153,7 +152,7 @@ EXECUTE_PROCESS(
 
 
 # Get the latest abbreviated commit hash of the working branch
 # Get the latest abbreviated commit hash of the working branch
 EXECUTE_PROCESS(
 EXECUTE_PROCESS(
-  COMMAND git log -1 --format=%h
+  COMMAND git log -1 --format=%h --no-show-signature
   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
   OUTPUT_VARIABLE GIT_COMMIT_HASH
   OUTPUT_VARIABLE GIT_COMMIT_HASH
   OUTPUT_STRIP_TRAILING_WHITESPACE
   OUTPUT_STRIP_TRAILING_WHITESPACE
@@ -161,7 +160,7 @@ EXECUTE_PROCESS(
 )
 )
 
 
 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(NOT GIT_COMMIT_HASH)
 
 
 IF(ASSIMP_DOUBLE_PRECISION)
 IF(ASSIMP_DOUBLE_PRECISION)
@@ -179,10 +178,10 @@ CONFIGURE_FILE(
 )
 )
 
 
 INCLUDE_DIRECTORIES(
 INCLUDE_DIRECTORIES(
-    ./
-	include
-    ${CMAKE_CURRENT_BINARY_DIR}
-    ${CMAKE_CURRENT_BINARY_DIR}/include
+  ./
+  include
+  ${CMAKE_CURRENT_BINARY_DIR}
+  ${CMAKE_CURRENT_BINARY_DIR}/include
 )
 )
 
 
 LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
 LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
@@ -192,14 +191,6 @@ SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPO
 SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
 SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
 
 
 IF( UNIX )
 IF( UNIX )
-  # Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux
-  IF( ${OPERATING_SYSTEM} MATCHES "Android")
-  ELSE()
-    IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
-      #ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
-    ENDIF()
-  ENDIF()
-
   # Use GNUInstallDirs for Unix predefined directories
   # Use GNUInstallDirs for Unix predefined directories
   INCLUDE(GNUInstallDirs)
   INCLUDE(GNUInstallDirs)
 ENDIF( UNIX )
 ENDIF( UNIX )
@@ -212,11 +203,13 @@ IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
   SET(LIBSTDC++_LIBRARIES -lstdc++)
   SET(LIBSTDC++_LIBRARIES -lstdc++)
 ELSEIF(MSVC)
 ELSEIF(MSVC)
   # enable multi-core compilation with MSVC
   # enable multi-core compilation with MSVC
-  add_compile_options(/MP)
-
+  ADD_COMPILE_OPTIONS(/MP)
+  IF("${CMAKE_GENERATOR}" MATCHES "(Win64|IA64)")
+    ADD_COMPILE_OPTIONS( /bigobj )
+  ENDIF()
   # disable "elements of array '' will be default initialized" warning on MSVC2013
   # disable "elements of array '' will be default initialized" warning on MSVC2013
   IF(MSVC12)
   IF(MSVC12)
-    add_compile_options(/wd4351)
+    ADD_COMPILE_OPTIONS(/wd4351)
   ENDIF()
   ENDIF()
 ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
 ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" )
   SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -Wno-long-long -std=c++11" )
@@ -227,34 +220,39 @@ ELSEIF( CMAKE_COMPILER_IS_MINGW )
   ADD_DEFINITIONS( -U__STRICT_ANSI__ )
   ADD_DEFINITIONS( -U__STRICT_ANSI__ )
 ENDIF()
 ENDIF()
 
 
-if (ASSIMP_COVERALLS)
-    MESSAGE(STATUS "Coveralls enabled")
-    INCLUDE(Coveralls)
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
-    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
-endif()
+IF (IOS)
+  SET(CMAKE_C_FLAGS   "${CMAKE_C_FLAGS}   -fembed-bitcode -O3")
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fembed-bitcode -O3")
+ENDIF()
 
 
-if (ASSIMP_WERROR)
+IF (ASSIMP_COVERALLS)
+  MESSAGE(STATUS "Coveralls enabled")
+  INCLUDE(Coveralls)
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -g -O0 -fprofile-arcs -ftest-coverage")
+ENDIF()
+
+IF (ASSIMP_WERROR)
   MESSAGE(STATUS "Treating warnings as errors")
   MESSAGE(STATUS "Treating warnings as errors")
   IF (MSVC)
   IF (MSVC)
-    add_compile_options(/WX)
+    ADD_COMPILE_OPTIONS(/WX)
   ELSE()
   ELSE()
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
     SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
     SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
   ENDIF()
   ENDIF()
-endif()
+ENDIF()
 
 
-if (ASSIMP_ASAN)
-    MESSAGE(STATUS "AddressSanitizer enabled")
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
-    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
-endif()
+IF (ASSIMP_ASAN)
+  MESSAGE(STATUS "AddressSanitizer enabled")
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=address")
+ENDIF()
 
 
-if (ASSIMP_UBSAN)
-    MESSAGE(STATUS "Undefined Behavior sanitizer enabled")
-    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
-    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
-endif()
+IF (ASSIMP_UBSAN)
+  MESSAGE(STATUS "Undefined Behavior sanitizer enabled")
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fsanitize=undefined -fno-sanitize-recover=all")
+ENDIF()
 
 
 INCLUDE (FindPkgMacros)
 INCLUDE (FindPkgMacros)
 INCLUDE (PrecompiledHeader)
 INCLUDE (PrecompiledHeader)
@@ -287,42 +285,42 @@ ENDIF()
 IF (NOT TARGET uninstall)
 IF (NOT TARGET uninstall)
   # add make uninstall capability
   # add make uninstall capability
   CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
   CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules/cmake_uninstall.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" IMMEDIATE @ONLY)
-  add_custom_target(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
+  ADD_CUSTOM_TARGET(uninstall "${CMAKE_COMMAND}" -P "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake")
 ENDIF()
 ENDIF()
 
 
 # cmake configuration files
 # cmake configuration files
 CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in"         "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
 CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config.cmake.in"         "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake" @ONLY IMMEDIATE)
 CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
 CONFIGURE_FILE("${CMAKE_CURRENT_SOURCE_DIR}/assimp-config-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" @ONLY IMMEDIATE)
-install(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake"             "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
+INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/assimp-config.cmake"             "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.cmake" DESTINATION "${ASSIMP_LIB_INSTALL_DIR}/cmake/assimp-${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}" COMPONENT ${LIBASSIMP-DEV_COMPONENT})
 
 
 FIND_PACKAGE( DirectX )
 FIND_PACKAGE( DirectX )
 
 
 IF( BUILD_DOCS )
 IF( BUILD_DOCS )
-    add_subdirectory(doc)
+  ADD_SUBDIRECTORY(doc)
 ENDIF( BUILD_DOCS )
 ENDIF( BUILD_DOCS )
 
 
 # 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( SYSTEM_IRRXML )
 
 
 # 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
 IF ( NOT ASSIMP_BUILD_ZLIB )
 IF ( NOT ASSIMP_BUILD_ZLIB )
-    find_package(ZLIB)
+  FIND_PACKAGE(ZLIB)
 ENDIF( NOT ASSIMP_BUILD_ZLIB )
 ENDIF( NOT ASSIMP_BUILD_ZLIB )
 
 
 IF( NOT ZLIB_FOUND )
 IF( NOT ZLIB_FOUND )
-  message(STATUS "compiling zlib from souces")
+  MESSAGE(STATUS "compiling zlib from sources")
   INCLUDE(CheckIncludeFile)
   INCLUDE(CheckIncludeFile)
   INCLUDE(CheckTypeSize)
   INCLUDE(CheckTypeSize)
   INCLUDE(CheckFunctionExists)
   INCLUDE(CheckFunctionExists)
   # compile from sources
   # compile from sources
-  add_subdirectory(contrib/zlib)
+  ADD_SUBDIRECTORY(contrib/zlib)
   SET(ZLIB_FOUND 1)
   SET(ZLIB_FOUND 1)
   SET(ZLIB_LIBRARIES zlibstatic)
   SET(ZLIB_LIBRARIES zlibstatic)
   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)
-else(NOT ZLIB_FOUND)
+ELSE(NOT ZLIB_FOUND)
   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(NOT ZLIB_FOUND)
@@ -364,7 +362,9 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
     SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes")
     SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes")
 
 
     # pick the correct prebuilt library
     # pick the correct prebuilt library
-    IF(MSVC14)
+    IF(MSVC15)
+      SET(C4D_LIB_POSTFIX "_2017")
+    ELSEIF(MSVC14)
       SET(C4D_LIB_POSTFIX "_2015")
       SET(C4D_LIB_POSTFIX "_2015")
     ELSEIF(MSVC12)
     ELSEIF(MSVC12)
       SET(C4D_LIB_POSTFIX "_2013")
       SET(C4D_LIB_POSTFIX "_2013")
@@ -405,39 +405,14 @@ ADD_SUBDIRECTORY(contrib)
 ADD_SUBDIRECTORY( code/ )
 ADD_SUBDIRECTORY( code/ )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
   IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
   IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
-    option ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
+    OPTION ( ASSIMP_BUILD_ASSIMP_VIEW "If the Assimp view tool is built. (requires DirectX)" ${DirectX_FOUND} )
     IF ( ASSIMP_BUILD_ASSIMP_VIEW )
     IF ( ASSIMP_BUILD_ASSIMP_VIEW )
       ADD_SUBDIRECTORY( tools/assimp_view/ )
       ADD_SUBDIRECTORY( tools/assimp_view/ )
     ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW )
     ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW )
   ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
   ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
 
 
   ADD_SUBDIRECTORY( tools/assimp_cmd/ )
   ADD_SUBDIRECTORY( tools/assimp_cmd/ )
-
-  # Check dependencies for assimp_qt_viewer.
-  # Why here? Maybe user do not want Qt viewer and have no Qt.
-  # Why assimp_qt_viewer/CMakeLists.txt still contain similar check?
-  # Because viewer can be build independently of Assimp.
-  FIND_PACKAGE(Qt5Widgets QUIET)
-  FIND_PACKAGE(DevIL QUIET)
-  FIND_PACKAGE(OpenGL QUIET)
-  IF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
-    ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
-  ELSE()
-    SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "")
-    IF (NOT Qt5_FOUND)
-      SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} Qt5")
-    ENDIF (NOT Qt5_FOUND)
-
-    IF (NOT IL_FOUND)
-      SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} DevIL")
-    ENDIF (NOT IL_FOUND)
-
-    IF (NOT OPENGL_FOUND)
-      SET ( ASSIMP_QT_VIEWER_DEPENDENCIES "${ASSIMP_QT_VIEWER_DEPENDENCIES} OpengGL")
-    ENDIF (NOT OPENGL_FOUND)
-
-    MESSAGE (WARNING "Build of assimp_qt_viewer is disabled. Unsatisfied dendencies: ${ASSIMP_QT_VIEWER_DEPENDENCIES}")
-  ENDIF ( Qt5Widgets_FOUND AND IL_FOUND AND OPENGL_FOUND)
+  ADD_SUBDIRECTORY( tools/assimp_qt_viewer/ )
 ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 ENDIF ( ASSIMP_BUILD_ASSIMP_TOOLS )
 
 
 IF ( ASSIMP_BUILD_SAMPLES)
 IF ( ASSIMP_BUILD_SAMPLES)
@@ -457,7 +432,7 @@ INSTALL( FILES "${PROJECT_BINARY_DIR}/assimp.pc" DESTINATION ${ASSIMP_LIB_INSTAL
 
 
 IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
 IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
   # Packing information
   # Packing information
-  SET(CPACK_PACKAGE_NAME                    "assimp{ASSIMP_VERSION_MAJOR}")
+  SET(CPACK_PACKAGE_NAME                    "assimp{ASSIMP_VERSION_MAJOR}.{ASSIMP_VERSION_MINOR}")
   SET(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.")
   SET(CPACK_PACKAGE_CONTACT "" CACHE STRING "Package maintainer and PGP signer.")
   SET(CPACK_PACKAGE_VENDOR                  "https://github.com/assimp")
   SET(CPACK_PACKAGE_VENDOR                  "https://github.com/assimp")
   SET(CPACK_PACKAGE_DISPLAY_NAME            "Assimp ${ASSIMP_VERSION}")
   SET(CPACK_PACKAGE_DISPLAY_NAME            "Assimp ${ASSIMP_VERSION}")
@@ -469,8 +444,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
   SET(CPACK_PACKAGE_INSTALL_DIRECTORY       "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
   SET(CPACK_PACKAGE_INSTALL_DIRECTORY       "assimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}")
   SET(CPACK_RESOURCE_FILE_LICENSE           "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
   SET(CPACK_RESOURCE_FILE_LICENSE           "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
 
 
-  string(TOUPPER ${LIBASSIMP_COMPONENT}     "LIBASSIMP_COMPONENT_UPPER")
-  string(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER")
+  STRING(TOUPPER ${LIBASSIMP_COMPONENT}     "LIBASSIMP_COMPONENT_UPPER")
+  STRING(TOUPPER ${LIBASSIMP-DEV_COMPONENT} "LIBASSIMP-DEV_COMPONENT_UPPER")
 
 
   SET(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME                       "tools")
   SET(CPACK_COMPONENT_ASSIMP-BIN_DISPLAY_NAME                       "tools")
   SET(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS                            "${LIBASSIMP_COMPONENT}" )
   SET(CPACK_COMPONENT_ASSIMP-BIN_DEPENDS                            "${LIBASSIMP_COMPONENT}" )
@@ -487,8 +462,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
   SET(CPACK_DEBIAN_PACKAGE_SECTION  "libs" )
   SET(CPACK_DEBIAN_PACKAGE_SECTION  "libs" )
   SET(CPACK_DEBIAN_PACKAGE_DEPENDS  "${CPACK_COMPONENTS_ALL}")
   SET(CPACK_DEBIAN_PACKAGE_DEPENDS  "${CPACK_COMPONENTS_ALL}")
   SET(CPACK_DEBIAN_PACKAGE_SUGGESTS)
   SET(CPACK_DEBIAN_PACKAGE_SUGGESTS)
-  SET(CPACK_DEBIAN_PACKAGE_NAME     "assimp")
-  SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/cppunit-1.12.1 contrib/cppunit_note.txt contrib/zlib workspaces test doc obj samples packaging)
+  set(cPACK_DEBIAN_PACKAGE_NAME     "assimp")
+  SET(CPACK_DEBIAN_PACKAGE_REMOVE_SOURCE_FILES contrib/gtest contrib/zlib workspaces test doc obj samples packaging)
   SET(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force)
   SET(CPACK_DEBIAN_PACKAGE_SOURCE_COPY svn export --force)
   SET(CPACK_DEBIAN_CHANGELOG)
   SET(CPACK_DEBIAN_CHANGELOG)
   execute_process(COMMAND lsb_release -is
   execute_process(COMMAND lsb_release -is
@@ -500,8 +475,8 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
     SET(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release")
     SET(CPACK_DEBIAN_DISTRIBUTION_RELEASES lucid maverick natty oneiric precise CACHE STRING "Release code-names of the distrubiton release")
   ENDIF()
   ENDIF()
   SET(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources")
   SET(DPUT_HOST "" CACHE STRING "PPA repository to upload the debian sources")
-  include(CPack)
-  include(DebSourcePPA)
+  INCLUDE(CPack)
+  INCLUDE(DebSourcePPA)
 ENDIF()
 ENDIF()
 
 
 if(WIN32)
 if(WIN32)
@@ -513,14 +488,16 @@ if(WIN32)
     SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/")
     SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/")
   ENDIF()
   ENDIF()
 
 
-  if(MSVC12)
+  IF(MSVC12)
     SET(ASSIMP_MSVC_VERSION "vc120")
     SET(ASSIMP_MSVC_VERSION "vc120")
-  elseif(MSVC14)
+  ELSEIF(MSVC14)
     SET(ASSIMP_MSVC_VERSION "vc140")
     SET(ASSIMP_MSVC_VERSION "vc140")
+  ELSEIF(MSVC15)
+    SET(ASSIMP_MSVC_VERSION "vc141")
   ENDIF(MSVC12)
   ENDIF(MSVC12)
 
 
-  if(MSVC12 OR MSVC14)
-    add_custom_target(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM)
+  IF(MSVC12 OR MSVC14 OR MSVC15 )
+    ADD_CUSTOM_TARGET(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM)
     IF(CMAKE_GENERATOR MATCHES "^Visual Studio")
     IF(CMAKE_GENERATOR MATCHES "^Visual Studio")
       ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll	${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
       ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.dll	${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.dll VERBATIM)
       ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp	${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
       ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Release/assimp-${ASSIMP_MSVC_VERSION}-mt.exp	${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.exp VERBATIM)
@@ -541,5 +518,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)
+  ENDIF(MSVC12 OR MSVC14 OR MSVC15 )
 ENDIF (WIN32)
 ENDIF (WIN32)

+ 10 - 0
CONTRIBUTING.md

@@ -0,0 +1,10 @@
+# How to contribute
+
+If you want to contribute, follow these steps:
+
+- First, create your own clone of assimp.
+- When you want to fix a bug or add a new feature, create a branch on your own fork following [these instructions](https://help.github.com/articles/creating-a-pull-request-from-a-fork/).
+- Push it to your fork of the repository and open a pull request.
+- A pull request will start our continuous integration service, which checks if the build works for Linux and Windows.
+  It will check for memory leaks, compiler warnings and memory alignment issues. If any of these tests fail, fix it and the tests will be restarted automatically.
+  - At the end, we will perform a code review and merge your branch to the master branch.

+ 16 - 1
CREDITS

@@ -157,12 +157,27 @@ Contributed ExportProperties interface
 Contributed X File exporter
 Contributed X File exporter
 Contributed Step (stp) exporter
 Contributed Step (stp) exporter
 
 
+- Thomas Iorns (mesilliac)
+Initial FBX Export support
+
 For a more detailed list just check: https://github.com/assimp/assimp/network/members
 For a more detailed list just check: https://github.com/assimp/assimp/network/members
 
 
-Patreons:
+
+========
+Patreons
+========
+
+Huge thanks to our Patreons!
+
 - migenius
 - migenius
 - Marcus
 - Marcus
 - Cort
 - Cort
 - elect
 - elect
 - Steffen
 - Steffen
 
 
+
+===================
+Commercial Sponsors
+===================
+
+- MyDidimo (mydidimo.com): Sponsored development of FBX Export support

+ 3 - 0
INSTALL

@@ -42,3 +42,6 @@ For Windows:
 1. Open a command prompt
 1. Open a command prompt
 2. cmake CMakeLists.txt
 2. cmake CMakeLists.txt
 2. Open your default IDE and build it
 2. Open your default IDE and build it
+
+For iOS:
+Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS

+ 24 - 24
Readme.md

@@ -32,32 +32,32 @@ Please check our Wiki as well: https://github.com/assimp/assimp/wiki
 
 
 #### Supported file formats ####
 #### Supported file formats ####
 
 
-A full list [is here](http://assimp.org/main_features_formats.html).
 __Importers__:
 __Importers__:
+
 - 3D
 - 3D
-- 3DS
-- 3MF
+- [3DS](https://en.wikipedia.org/wiki/.3ds)
+- [3MF](https://en.wikipedia.org/wiki/3D_Manufacturing_Format)
 - AC
 - AC
-- AC3D
+- [AC3D](https://en.wikipedia.org/wiki/AC3D)
 - ACC
 - ACC
 - AMJ
 - AMJ
 - ASE
 - ASE
 - ASK
 - ASK
 - B3D
 - B3D
-- BLEND (Blender)
-- BVH
-- COB
+- [BLEND](https://en.wikipedia.org/wiki/.blend_(file_format))
+- [BVH](https://en.wikipedia.org/wiki/Biovision_Hierarchy)
 - CMS
 - CMS
-- DAE/Collada
-- DXF
+- COB
+- [DAE/Collada](https://en.wikipedia.org/wiki/COLLADA)
+- [DXF](https://en.wikipedia.org/wiki/AutoCAD_DXF)
 - ENFF
 - ENFF
-- FBX
-- glTF 1.0 + GLB
-- glTF 2.0
+- [FBX](https://en.wikipedia.org/wiki/FBX)
+- [glTF 1.0](https://en.wikipedia.org/wiki/GlTF#glTF_1.0) + GLB
+- [glTF 2.0](https://en.wikipedia.org/wiki/GlTF#glTF_2.0)
 - HMB
 - HMB
 - IFC-STEP
 - IFC-STEP
 - IRR / IRRMESH
 - IRR / IRRMESH
-- LWO
+- [LWO](https://en.wikipedia.org/wiki/LightWave_3D)
 - LWS
 - LWS
 - LXO
 - LXO
 - MD2
 - MD2
@@ -70,10 +70,10 @@ __Importers__:
 - MS3D
 - MS3D
 - NDO
 - NDO
 - NFF
 - NFF
-- OBJ
-- OFF
-- OGEX
-- PLY
+- [OBJ](https://en.wikipedia.org/wiki/Wavefront_.obj_file)
+- [OFF](https://en.wikipedia.org/wiki/OFF_(file_format))
+- [OGEX](https://en.wikipedia.org/wiki/Open_Game_Engine_Exchange)
+- [PLY](https://en.wikipedia.org/wiki/PLY_(file_format))
 - PMX
 - PMX
 - PRJ
 - PRJ
 - Q3O
 - Q3O
@@ -82,19 +82,19 @@ __Importers__:
 - SCN
 - SCN
 - SIB
 - SIB
 - SMD
 - SMD
-- STL
-- STP
+- [STP](https://en.wikipedia.org/wiki/ISO_10303-21)
+- [STL](https://en.wikipedia.org/wiki/STL_(file_format))
 - TER
 - TER
 - UC
 - UC
 - VTA
 - VTA
 - X
 - X
-- X3D
+- [X3D](https://en.wikipedia.org/wiki/X3D)
 - XGL
 - XGL
 - ZGL
 - ZGL
 
 
 Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
 Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
 
 
-- C4D (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange)
+- [C4D](https://en.wikipedia.org/wiki/Cinema_4D) (https://github.com/assimp/assimp/wiki/Cinema4D-&-Melange)
 
 
 __Exporters__:
 __Exporters__:
 
 
@@ -109,6 +109,8 @@ __Exporters__:
 - STEP
 - STEP
 - glTF 1.0 (partial)
 - glTF 1.0 (partial)
 - glTF 2.0 (partial)
 - glTF 2.0 (partial)
+- 3MF ( experimental )
+- FBX ( experimental )
 
 
 ### Building ###
 ### Building ###
 Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
 Take a look into the `INSTALL` file. Our build system is CMake, if you used CMake before there is a good chance you know what to do.
@@ -120,7 +122,7 @@ Take a look into the `INSTALL` file. Our build system is CMake, if you used CMak
 * [Pascal](port/AssimpPascal/Readme.md)
 * [Pascal](port/AssimpPascal/Readme.md)
 * [Javascript (Alpha)](https://github.com/makc/assimp2json)
 * [Javascript (Alpha)](https://github.com/makc/assimp2json)
 * [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777)
 * [Unity 3d Plugin](https://www.assetstore.unity3d.com/en/#!/content/91777)
-* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (currently supported obj, ply, stl, collada, md2)
+* [JVM](https://github.com/kotlin-graphics/assimp) Full jvm port (current [status](https://github.com/kotlin-graphics/assimp/wiki/Status))
 
 
 ### Other tools ###
 ### Other tools ###
 [open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
 [open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
@@ -138,8 +140,6 @@ Open Asset Import Library is implemented in C++. The directory structure is:
 	/tools		Tools (old assimp viewer, command line `assimp`)
 	/tools		Tools (old assimp viewer, command line `assimp`)
 	/samples	A small number of samples to illustrate possible
 	/samples	A small number of samples to illustrate possible
                         use cases for Assimp
                         use cases for Assimp
-	/workspaces	Build environments for vc,xcode,... (deprecated,
-			CMake has superseeded all legacy build options!)
 
 
 
 
 ### Where to get help ###
 ### Where to get help ###

+ 4 - 0
appveyor.yml

@@ -32,6 +32,9 @@ install:
   - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
   - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
   - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
   - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
   - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%"
   - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%"
+  - set PATH=%PATH%;"C:\\Program Files (x86)\\Inno Setup 5"
+  - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/5/7/b/57b2947c-7221-4f33-b35e-2fc78cb10df4/vc_redist.x64.exe -OutFile .\packaging\windows-innosetup\vc_redist.x64.exe
+  - ps: Invoke-WebRequest -Uri https://download.microsoft.com/download/1/d/8/1d8137db-b5bb-4925-8c5d-927424a2e4de/vc_redist.x86.exe -OutFile .\packaging\windows-innosetup\vc_redist.x86.exe
   
   
 cache:
 cache:
   - code\assimp.dir\%CONFIGURATION%
   - code\assimp.dir\%CONFIGURATION%
@@ -50,6 +53,7 @@ build:
   project: Assimp.sln
   project: Assimp.sln
   
   
 after_build:
 after_build:
+  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" iscc packaging\windows-innosetup\script.iss
   - 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\*
   - 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\*
 
 
 test_script:
 test_script:

+ 3 - 25
assimp-config.cmake.in

@@ -10,10 +10,7 @@
 # ASSIMP_LIBRARY_DIRS - link directories
 # ASSIMP_LIBRARY_DIRS - link directories
 # ASSIMP_LIBRARIES - libraries to link plugins with
 # ASSIMP_LIBRARIES - libraries to link plugins with
 # ASSIMP_Boost_VERSION - the boost version assimp was compiled with
 # ASSIMP_Boost_VERSION - the boost version assimp was compiled with
-get_filename_component(_PREFIX "${CMAKE_CURRENT_LIST_FILE}" PATH)
-get_filename_component(_PREFIX "${_PREFIX}" PATH)
-get_filename_component(_PREFIX "${_PREFIX}" PATH)
-get_filename_component(ASSIMP_ROOT_DIR "${_PREFIX}" PATH)
+get_filename_component(ASSIMP_ROOT_DIR "@CMAKE_INSTALL_PREFIX@" REALPATH)
 
 
 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
@@ -34,36 +31,18 @@ if( MSVC )
   else()
   else()
     set(MSVC_PREFIX "vc150")
     set(MSVC_PREFIX "vc150")
   endif()
   endif()
-  set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" FORCE)
+  set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@-${MSVC_PREFIX}-mt" CACHE STRING "the suffix for the assimp windows library" )
 else()
 else()
-  set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" FORCE)
+  set(ASSIMP_LIBRARY_SUFFIX "@ASSIMP_LIBRARY_SUFFIX@" CACHE STRING "the suffix for the openrave libraries" )
 endif()
 endif()
 
 
 set( ASSIMP_CXX_FLAGS ) # dynamically linked library
 set( ASSIMP_CXX_FLAGS ) # dynamically linked library
-if( WIN32 )
-  # for visual studio linking, most of the time boost dlls will be used
-  set( ASSIMP_CXX_FLAGS " -DBOOST_ALL_DYN_LINK -DBOOST_ALL_NO_LIB")
-endif()
 set( ASSIMP_LINK_FLAGS "" )
 set( ASSIMP_LINK_FLAGS "" )
 set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@")
 set( ASSIMP_LIBRARY_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_LIB_INSTALL_DIR@")
 set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@")
 set( ASSIMP_INCLUDE_DIRS "${ASSIMP_ROOT_DIR}/@ASSIMP_INCLUDE_INSTALL_DIR@")
 set( ASSIMP_LIBRARIES assimp${ASSIMP_LIBRARY_SUFFIX})
 set( ASSIMP_LIBRARIES assimp${ASSIMP_LIBRARY_SUFFIX})
 set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}@CMAKE_DEBUG_POSTFIX@)
 set( ASSIMP_LIBRARIES ${ASSIMP_LIBRARIES}@CMAKE_DEBUG_POSTFIX@)
 
 
-# search for the boost version assimp was compiled with
-#set(Boost_USE_MULTITHREAD ON)
-#set(Boost_USE_STATIC_LIBS OFF)
-#set(Boost_USE_STATIC_RUNTIME OFF)
-#find_package(Boost ${ASSIMP_Boost_VERSION} EXACT COMPONENTS thread date_time)
-#if(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
-#	set( ASSIMP_INCLUDE_DIRS "${ASSIMP_INCLUDE_DIRS}" ${Boost_INCLUDE_DIRS})
-#else(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
-#	message(WARNING "Failed to find Boost ${ASSIMP_Boost_VERSION} necessary for assimp")
-#endif(Boost_VERSION AND NOT "${Boost_VERSION}" STREQUAL "0")
-
-# the boost version assimp was compiled with
-set( ASSIMP_Boost_VERSION "@Boost_MAJOR_VERSION@.@Boost_MINOR_VERSION@")
-
 # for compatibility with pkg-config
 # for compatibility with pkg-config
 set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
 set(ASSIMP_CFLAGS_OTHER "${ASSIMP_CXX_FLAGS}")
 set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}")
 set(ASSIMP_LDFLAGS_OTHER "${ASSIMP_LINK_FLAGS}")
@@ -74,7 +53,6 @@ MARK_AS_ADVANCED(
   ASSIMP_LINK_FLAGS
   ASSIMP_LINK_FLAGS
   ASSIMP_INCLUDE_DIRS
   ASSIMP_INCLUDE_DIRS
   ASSIMP_LIBRARIES
   ASSIMP_LIBRARIES
-  ASSIMP_Boost_VERSION
   ASSIMP_CFLAGS_OTHER
   ASSIMP_CFLAGS_OTHER
   ASSIMP_LDFLAGS_OTHER
   ASSIMP_LDFLAGS_OTHER
   ASSIMP_LIBRARY_SUFFIX
   ASSIMP_LIBRARY_SUFFIX

+ 18 - 16
code/3DSConverter.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -71,7 +72,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
     unsigned int idx( NotSet );
     unsigned int idx( NotSet );
     for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
     for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
     {
     {
-        std::string s = mScene->mMaterials[i].mName;
+        std::string &s = mScene->mMaterials[i].mName;
         for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) {
         for ( std::string::iterator it = s.begin(); it != s.end(); ++it ) {
             *it = static_cast< char >( ::tolower( *it ) );
             *it = static_cast< char >( ::tolower( *it ) );
         }
         }
@@ -119,7 +120,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
             else if ( (*a) >= mScene->mMaterials.size())
             else if ( (*a) >= mScene->mMaterials.size())
             {
             {
                 (*a) = idx;
                 (*a) = idx;
-                DefaultLogger::get()->warn("Material index overflow in 3DS file. Using default material");
+                ASSIMP_LOG_WARN("Material index overflow in 3DS file. Using default material");
                 ++cnt;
                 ++cnt;
             }
             }
         }
         }
@@ -127,12 +128,11 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
     if (cnt && idx == mScene->mMaterials.size())
     if (cnt && idx == mScene->mMaterials.size())
     {
     {
         // We need to create our own default material
         // We need to create our own default material
-        D3DS::Material sMat;
+        D3DS::Material sMat("%%%DEFAULT");
         sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f);
         sMat.mDiffuse = aiColor3D(0.3f,0.3f,0.3f);
-        sMat.mName = "%%%DEFAULT";
         mScene->mMaterials.push_back(sMat);
         mScene->mMaterials.push_back(sMat);
 
 
-        DefaultLogger::get()->info("3DS: Generating default material");
+        ASSIMP_LOG_INFO("3DS: Generating default material");
     }
     }
 }
 }
 
 
@@ -147,12 +147,12 @@ void Discreet3DSImporter::CheckIndices(D3DS::Mesh& sMesh)
         {
         {
             if ((*i).mIndices[a] >= sMesh.mPositions.size())
             if ((*i).mIndices[a] >= sMesh.mPositions.size())
             {
             {
-                DefaultLogger::get()->warn("3DS: Vertex index overflow)");
+                ASSIMP_LOG_WARN("3DS: Vertex index overflow)");
                 (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1;
                 (*i).mIndices[a] = (uint32_t)sMesh.mPositions.size()-1;
             }
             }
             if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size())
             if ( !sMesh.mTexCoords.empty() && (*i).mIndices[a] >= sMesh.mTexCoords.size())
             {
             {
-                DefaultLogger::get()->warn("3DS: Texture coordinate index overflow)");
+                ASSIMP_LOG_WARN("3DS: Texture coordinate index overflow)");
                 (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1;
                 (*i).mIndices[a] = (uint32_t)sMesh.mTexCoords.size()-1;
             }
             }
         }
         }
@@ -204,8 +204,9 @@ void CopyTexture(aiMaterial& mat, D3DS::Texture& texture, aiTextureType type)
         mat.AddProperty<ai_real>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
         mat.AddProperty<ai_real>( &texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type,0));
 
 
     // Setup the texture mapping mode
     // Setup the texture mapping mode
-    mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
-    mat.AddProperty<int>((int*)&texture.mMapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
+    int mapMode = static_cast<int>(texture.mMapMode);
+    mat.AddProperty<int>(&mapMode,1,AI_MATKEY_MAPPINGMODE_U(type,0));
+    mat.AddProperty<int>(&mapMode,1,AI_MATKEY_MAPPINGMODE_V(type,0));
 
 
     // Mirroring - double the scaling values
     // Mirroring - double the scaling values
     // FIXME: this is not really correct ...
     // FIXME: this is not really correct ...
@@ -313,7 +314,8 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material& oldMat,
         case D3DS::Discreet3DS::Blinn :
         case D3DS::Discreet3DS::Blinn :
             eShading = aiShadingMode_Blinn; break;
             eShading = aiShadingMode_Blinn; break;
     }
     }
-    mat.AddProperty<int>( (int*)&eShading,1,AI_MATKEY_SHADING_MODEL);
+    int eShading_ = static_cast<int>(eShading);
+    mat.AddProperty<int>(&eShading_, 1, AI_MATKEY_SHADING_MODEL);
 
 
     // DIFFUSE texture
     // DIFFUSE texture
     if( oldMat.sTexDiffuse.mMapName.length() > 0)
     if( oldMat.sTexDiffuse.mMapName.length() > 0)
@@ -497,7 +499,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
                         pvCurrent->x *= -1.f;
                         pvCurrent->x *= -1.f;
                         t2->x *= -1.f;
                         t2->x *= -1.f;
                     }
                     }
-                    DefaultLogger::get()->info("3DS: Flipping mesh X-Axis");
+                    ASSIMP_LOG_INFO("3DS: Flipping mesh X-Axis");
                 }
                 }
 
 
                 // Handle pivot point
                 // Handle pivot point
@@ -573,11 +575,11 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
         pcIn->aTargetPositionKeys.size() > 1)
         pcIn->aTargetPositionKeys.size() > 1)
     {
     {
         aiAnimation* anim = pcSOut->mAnimations[0];
         aiAnimation* anim = pcSOut->mAnimations[0];
-        ai_assert(NULL != anim);
+        ai_assert(nullptr != anim);
 
 
         if (pcIn->aCameraRollKeys.size() > 1)
         if (pcIn->aCameraRollKeys.size() > 1)
         {
         {
-            DefaultLogger::get()->debug("3DS: Converting camera roll track ...");
+            ASSIMP_LOG_DEBUG("3DS: Converting camera roll track ...");
 
 
             // Camera roll keys - in fact they're just rotations
             // Camera roll keys - in fact they're just rotations
             // around the camera's z axis. The angles are given
             // around the camera's z axis. The angles are given
@@ -597,7 +599,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene* pcSOut,aiNode* pcOut,
 #if 0
 #if 0
         if (pcIn->aTargetPositionKeys.size() > 1)
         if (pcIn->aTargetPositionKeys.size() > 1)
         {
         {
-            DefaultLogger::get()->debug("3DS: Converting target track ...");
+            ASSIMP_LOG_DEBUG("3DS: Converting target track ...");
 
 
             // Camera or spot light - need to convert the separate
             // Camera or spot light - need to convert the separate
             // target position channel to our representation
             // target position channel to our representation
@@ -743,7 +745,7 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene* pcOut)
         //   |       |       |            |         |
         //   |       |       |            |         |
         // MESH_0  MESH_1  MESH_2  ...  MESH_N    CAMERA_0 ....
         // MESH_0  MESH_1  MESH_2  ...  MESH_N    CAMERA_0 ....
         //
         //
-        DefaultLogger::get()->warn("No hierarchy information has been found in the file. ");
+        ASSIMP_LOG_WARN("No hierarchy information has been found in the file. ");
 
 
         pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes +
         pcOut->mRootNode->mNumChildren = pcOut->mNumMeshes +
             static_cast<unsigned int>(mScene->mCameras.size() + mScene->mLights.size());
             static_cast<unsigned int>(mScene->mCameras.size() + mScene->mLights.size());

+ 4 - 3
code/3DSExporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -183,7 +184,7 @@ void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScen
 } // end of namespace Assimp
 } // end of namespace Assimp
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr<IOStream> outfile, const aiScene* scene)
+Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, const aiScene* scene)
 : scene(scene)
 : scene(scene)
 , writer(outfile)
 , writer(outfile)
 {
 {
@@ -380,7 +381,7 @@ void Discreet3DSExporter::WriteTexture(const aiMaterial& mat, aiTextureType type
 
 
     // TODO: handle embedded textures properly
     // TODO: handle embedded textures properly
     if (path.data[0] == '*') {
     if (path.data[0] == '*') {
-        DefaultLogger::get()->error("Ignoring embedded texture for export: " + std::string(path.C_Str()));
+        ASSIMP_LOG_ERROR("Ignoring embedded texture for export: " + std::string(path.C_Str()));
         return;
         return;
     }
     }
 
 

+ 3 - 2
code/3DSExporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -66,7 +67,7 @@ namespace Assimp
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 class Discreet3DSExporter {
 class Discreet3DSExporter {
 public:
 public:
-    Discreet3DSExporter(std::shared_ptr<IOStream> outfile, const aiScene* pScene);
+    Discreet3DSExporter(std::shared_ptr<IOStream> &outfile, const aiScene* pScene);
     ~Discreet3DSExporter();
     ~Discreet3DSExporter();
 
 
 private:
 private:

+ 88 - 29
code/3DSHelper.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -370,9 +371,14 @@ struct Texture
 /** Helper structure representing a 3ds material */
 /** Helper structure representing a 3ds material */
 struct Material
 struct Material
 {
 {
-    //! Default constructor. Builds a default name for the material
-    Material()
-    : mDiffuse            ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) ) // FIX ... we won't want object to be black
+    //! Default constructor has been deleted
+    Material() = delete;
+
+
+    //! Constructor with explicit name
+    explicit Material(const std::string &name)
+    : mName(name)
+    , mDiffuse            ( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ) ) // FIX ... we won't want object to be black
     , mSpecularExponent   ( ai_real( 0.0 ) )
     , mSpecularExponent   ( ai_real( 0.0 ) )
     , mShininessStrength  ( ai_real( 1.0 ) )
     , mShininessStrength  ( ai_real( 1.0 ) )
     , mShading(Discreet3DS::Gouraud)
     , mShading(Discreet3DS::Gouraud)
@@ -380,13 +386,70 @@ struct Material
     , mBumpHeight         ( ai_real( 1.0 ) )
     , mBumpHeight         ( ai_real( 1.0 ) )
     , mTwoSided           (false)
     , mTwoSided           (false)
     {
     {
-        static int iCnt = 0;
+    }
+
 
 
-        char szTemp[128];
-        ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
-        mName = szTemp;
+    Material(const Material &other)            = default;
+    Material &operator=(const Material &other) = default;
+
+
+    //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
+    Material(Material &&other)
+    : mName(std::move(other.mName))
+    , mDiffuse(std::move(other.mDiffuse))
+    , mSpecularExponent(std::move(other.mSpecularExponent))
+    , mShininessStrength(std::move(other.mShininessStrength))
+    , mSpecular(std::move(other.mSpecular))
+    , mAmbient(std::move(other.mAmbient))
+    , mShading(std::move(other.mShading))
+    , mTransparency(std::move(other.mTransparency))
+    , sTexDiffuse(std::move(other.sTexDiffuse))
+    , sTexOpacity(std::move(other.sTexOpacity))
+    , sTexSpecular(std::move(other.sTexSpecular))
+    , sTexReflective(std::move(other.sTexReflective))
+    , sTexBump(std::move(other.sTexBump))
+    , sTexEmissive(std::move(other.sTexEmissive))
+    , sTexShininess(std::move(other.sTexShininess))
+    , mBumpHeight(std::move(other.mBumpHeight))
+    , mEmissive(std::move(other.mEmissive))
+    , sTexAmbient(std::move(other.sTexAmbient))
+    , mTwoSided(std::move(other.mTwoSided))
+    {
+    }
+
+
+    Material &operator=(Material &&other) {
+        if (this == &other) {
+            return *this;
+        }
+
+        mName = std::move(other.mName);
+        mDiffuse = std::move(other.mDiffuse);
+        mSpecularExponent = std::move(other.mSpecularExponent);
+        mShininessStrength = std::move(other.mShininessStrength),
+        mSpecular = std::move(other.mSpecular);
+        mAmbient = std::move(other.mAmbient);
+        mShading = std::move(other.mShading);
+        mTransparency = std::move(other.mTransparency);
+        sTexDiffuse = std::move(other.sTexDiffuse);
+        sTexOpacity = std::move(other.sTexOpacity);
+        sTexSpecular = std::move(other.sTexSpecular);
+        sTexReflective = std::move(other.sTexReflective);
+        sTexBump = std::move(other.sTexBump);
+        sTexEmissive = std::move(other.sTexEmissive);
+        sTexShininess = std::move(other.sTexShininess);
+        mBumpHeight = std::move(other.mBumpHeight);
+        mEmissive = std::move(other.mEmissive);
+        sTexAmbient = std::move(other.sTexAmbient);
+        mTwoSided = std::move(other.mTwoSided);
+
+        return *this;
     }
     }
 
 
+
+    ~Material() {}
+
+
     //! Name of the material
     //! Name of the material
     std::string mName;
     std::string mName;
     //! Diffuse color of the material
     //! Diffuse color of the material
@@ -432,17 +495,16 @@ struct Material
 /** Helper structure to represent a 3ds file mesh */
 /** Helper structure to represent a 3ds file mesh */
 struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
 struct Mesh : public MeshWithSmoothingGroups<D3DS::Face>
 {
 {
-    //! Default constructor
-    Mesh()
-    {
-        static int iCnt = 0;
+    //! Default constructor has been deleted
+    Mesh() = delete;
 
 
-        // Generate a default name for the mesh
-        char szTemp[128];
-        ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
-        mName = szTemp;
+    //! Constructor with explicit name
+    explicit Mesh(const std::string &name)
+    : mName(name)
+    {
     }
     }
 
 
+
     //! Name of the mesh
     //! Name of the mesh
     std::string mName;
     std::string mName;
 
 
@@ -488,25 +550,22 @@ struct aiFloatKey
 /** Helper structure to represent a 3ds file node */
 /** Helper structure to represent a 3ds file node */
 struct Node
 struct Node
 {
 {
-    Node():
-    	mParent(NULL)
-		,	mInstanceNumber(0)
-		,	mHierarchyPos		(0)
-		,	mHierarchyIndex		(0)
-		,	mInstanceCount		(1)
+    Node() = delete;
+
+    explicit Node(const std::string &name)
+    : mParent(NULL)
+    , mName(name)
+    , mInstanceNumber(0)
+    , mHierarchyPos       (0)
+    , mHierarchyIndex     (0)
+    , mInstanceCount      (1)
     {
     {
-        static int iCnt = 0;
-
-        // Generate a default name for the node
-        char szTemp[128];
-        ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
-        mName = szTemp;
-
         aRotationKeys.reserve (20);
         aRotationKeys.reserve (20);
         aPositionKeys.reserve (20);
         aPositionKeys.reserve (20);
         aScalingKeys.reserve  (20);
         aScalingKeys.reserve  (20);
     }
     }
 
 
+
     ~Node()
     ~Node()
     {
     {
         for (unsigned int i = 0; i < mChildren.size();++i)
         for (unsigned int i = 0; i < mChildren.size();++i)

+ 44 - 46
code/3DSLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -70,7 +71,7 @@ static const aiImporterDesc desc = {
     0,
     0,
     0,
     0,
     0,
     0,
-    "3ds prj"
+	"3ds prj"
 };
 };
 
 
 
 
@@ -105,29 +106,31 @@ static const aiImporterDesc desc = {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 Discreet3DSImporter::Discreet3DSImporter()
 Discreet3DSImporter::Discreet3DSImporter()
-    : stream(),
-    mLastNodeIndex(),
-    mCurrentNode(),
-    mRootNode(),
-    mScene(),
-    mMasterScale(),
-    bHasBG(),
-    bIsPrj()
-{}
+: stream()
+, mLastNodeIndex()
+, mCurrentNode()
+, mRootNode()
+, mScene()
+, mMasterScale()
+, bHasBG()
+, bIsPrj() {
+    // empty
+}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-Discreet3DSImporter::~Discreet3DSImporter()
-{}
+Discreet3DSImporter::~Discreet3DSImporter() {
+    // empty
+}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
-bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
-{
+bool Discreet3DSImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
     std::string extension = GetExtension(pFile);
     std::string extension = GetExtension(pFile);
-    if(extension == "3ds" || extension == "prj" ) {
+	if(extension == "3ds" || extension == "prj") {
         return true;
         return true;
     }
     }
+
     if (!extension.length() || checkSig) {
     if (!extension.length() || checkSig) {
         uint16_t token[3];
         uint16_t token[3];
         token[0] = 0x4d4d;
         token[0] = 0x4d4d;
@@ -170,7 +173,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
 
 
     // Initialize members
     // Initialize members
     mLastNodeIndex             = -1;
     mLastNodeIndex             = -1;
-    mCurrentNode               = new D3DS::Node();
+    mCurrentNode               = new D3DS::Node("UNNAMED");
     mRootNode                  = mCurrentNode;
     mRootNode                  = mCurrentNode;
     mRootNode->mHierarchyPos   = -1;
     mRootNode->mHierarchyPos   = -1;
     mRootNode->mHierarchyIndex = -1;
     mRootNode->mHierarchyIndex = -1;
@@ -209,7 +212,7 @@ void Discreet3DSImporter::InternReadFile( const std::string& pFile,
     ConvertScene(pScene);
     ConvertScene(pScene);
 
 
     // Generate the node graph for the scene. This is a little bit
     // Generate the node graph for the scene. This is a little bit
-    // tricky since we'll need to split some meshes into submeshes
+    // tricky since we'll need to split some meshes into sub-meshes
     GenerateNodeGraph(pScene);
     GenerateNodeGraph(pScene);
 
 
     // Now apply the master scaling factor to the scene
     // Now apply the master scaling factor to the scene
@@ -255,8 +258,9 @@ void Discreet3DSImporter::ReadChunk(Discreet3DS::Chunk* pcOut)
     if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize())
     if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSize())
         throw DeadlyImportError("Chunk is too large");
         throw DeadlyImportError("Chunk is too large");
 
 
-    if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit())
-        DefaultLogger::get()->error("3DS: Chunk overflow");
+    if (pcOut->Size - sizeof(Discreet3DS::Chunk) > stream->GetRemainingSizeToLimit()) {
+        ASSIMP_LOG_ERROR("3DS: Chunk overflow");
+    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -317,7 +321,7 @@ void Discreet3DSImporter::ParseEditorChunk()
         // print the version number
         // print the version number
         char buff[10];
         char buff[10];
         ASSIMP_itoa10(buff,stream->GetI2());
         ASSIMP_itoa10(buff,stream->GetI2());
-        DefaultLogger::get()->info(std::string("3DS file format version: ") + buff);
+        ASSIMP_LOG_INFO_F(std::string("3DS file format version: "), buff);
         }
         }
         break;
         break;
     };
     };
@@ -346,7 +350,7 @@ void Discreet3DSImporter::ParseObjectChunk()
     case Discreet3DS::CHUNK_MAT_MATERIAL:
     case Discreet3DS::CHUNK_MAT_MATERIAL:
 
 
         // Add a new material to the list
         // Add a new material to the list
-        mScene->mMaterials.push_back(D3DS::Material());
+        mScene->mMaterials.push_back(D3DS::Material(std::string("UNNAMED_" + to_string(mScene->mMaterials.size()))));
         ParseMaterialChunk();
         ParseMaterialChunk();
         break;
         break;
 
 
@@ -358,7 +362,7 @@ void Discreet3DSImporter::ParseObjectChunk()
         if (is_qnan(mClrAmbient.r))
         if (is_qnan(mClrAmbient.r))
         {
         {
             // We failed to read the ambient base color.
             // We failed to read the ambient base color.
-            DefaultLogger::get()->error("3DS: Failed to read ambient base color");
+            ASSIMP_LOG_ERROR("3DS: Failed to read ambient base color");
             mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f;
             mClrAmbient.r = mClrAmbient.g = mClrAmbient.b = 0.0f;
         }
         }
         break;
         break;
@@ -402,11 +406,7 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
     case Discreet3DS::CHUNK_TRIMESH:
     case Discreet3DS::CHUNK_TRIMESH:
         {
         {
         // this starts a new triangle mesh
         // this starts a new triangle mesh
-        mScene->mMeshes.push_back(D3DS::Mesh());
-        D3DS::Mesh& m = mScene->mMeshes.back();
-
-        // Setup the name of the mesh
-        m.mName = std::string(name, num);
+        mScene->mMeshes.push_back(D3DS::Mesh(std::string(name, num)));
 
 
         // Read mesh chunks
         // Read mesh chunks
         ParseMeshChunk();
         ParseMeshChunk();
@@ -464,7 +464,7 @@ void Discreet3DSImporter::ParseChunk(const char* name, unsigned int num)
         if (len < 1e-5) {
         if (len < 1e-5) {
 
 
             // There are some files with lookat == position. Don't know why or whether it's ok or not.
             // There are some files with lookat == position. Don't know why or whether it's ok or not.
-            DefaultLogger::get()->error("3DS: Unable to read proper camera look-at vector");
+            ASSIMP_LOG_ERROR("3DS: Unable to read proper camera look-at vector");
             camera->mLookAt = aiVector3D(0.0,1.0,0.0);
             camera->mLookAt = aiVector3D(0.0,1.0,0.0);
 
 
         }
         }
@@ -630,9 +630,9 @@ void Discreet3DSImporter::SkipTCBInfo()
     if (!flags) {
     if (!flags) {
         // Currently we can't do anything with these values. They occur
         // Currently we can't do anything with these values. They occur
         // quite rare, so it wouldn't be worth the effort implementing
         // quite rare, so it wouldn't be worth the effort implementing
-        // them. 3DS ist not really suitable for complex animations,
+        // them. 3DS is not really suitable for complex animations,
         // so full support is not required.
         // so full support is not required.
-        DefaultLogger::get()->warn("3DS: Skipping TCB animation info");
+        ASSIMP_LOG_WARN("3DS: Skipping TCB animation info");
     }
     }
 
 
     if (flags & Discreet3DS::KEY_USE_TENS) {
     if (flags & Discreet3DS::KEY_USE_TENS) {
@@ -690,8 +690,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
             pcNode->mInstanceCount++;
             pcNode->mInstanceCount++;
             instanceNumber = pcNode->mInstanceCount;
             instanceNumber = pcNode->mInstanceCount;
         }
         }
-        pcNode = new D3DS::Node();
-        pcNode->mName = name;
+        pcNode = new D3DS::Node(name);
         pcNode->mInstanceNumber = instanceNumber;
         pcNode->mInstanceNumber = instanceNumber;
 
 
         // There are two unknown values which we can safely ignore
         // There are two unknown values which we can safely ignore
@@ -734,7 +733,6 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
 
 
             // If object name is DUMMY, take this one instead
             // If object name is DUMMY, take this one instead
             if (mCurrentNode->mName == "$$$DUMMY")  {
             if (mCurrentNode->mName == "$$$DUMMY")  {
-                //DefaultLogger::get()->warn("3DS: Skipping dummy object name for non-dummy object");
                 mCurrentNode->mName = std::string(sz);
                 mCurrentNode->mName = std::string(sz);
                 break;
                 break;
             }
             }
@@ -745,7 +743,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
 
 
         if ( Discreet3DS::CHUNK_TRACKINFO != parent)
         if ( Discreet3DS::CHUNK_TRACKINFO != parent)
         {
         {
-            DefaultLogger::get()->warn("3DS: Skipping pivot subchunk for non usual object");
+            ASSIMP_LOG_WARN("3DS: Skipping pivot subchunk for non usual object");
             break;
             break;
         }
         }
 
 
@@ -807,7 +805,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
         {
         {
         // roll keys are accepted for cameras only
         // roll keys are accepted for cameras only
         if (parent != Discreet3DS::CHUNK_TRACKCAMERA)   {
         if (parent != Discreet3DS::CHUNK_TRACKCAMERA)   {
-            DefaultLogger::get()->warn("3DS: Ignoring roll track for non-camera object");
+            ASSIMP_LOG_WARN("3DS: Ignoring roll track for non-camera object");
             break;
             break;
         }
         }
         bool sortKeys = false;
         bool sortKeys = false;
@@ -847,7 +845,7 @@ void Discreet3DSImporter::ParseHierarchyChunk(uint16_t parent)
         // CAMERA FOV KEYFRAME
         // CAMERA FOV KEYFRAME
     case Discreet3DS::CHUNK_TRACKFOV:
     case Discreet3DS::CHUNK_TRACKFOV:
         {
         {
-            DefaultLogger::get()->error("3DS: Skipping FOV animation track. "
+            ASSIMP_LOG_ERROR("3DS: Skipping FOV animation track. "
                 "This is not supported");
                 "This is not supported");
         }
         }
         break;
         break;
@@ -987,7 +985,7 @@ void Discreet3DSImporter::ParseFaceChunk()
             }
             }
         }
         }
         if (0xcdcdcdcd == idx)  {
         if (0xcdcdcdcd == idx)  {
-            DefaultLogger::get()->error(std::string("3DS: Unknown material: ") + sz);
+            ASSIMP_LOG_ERROR_F( "3DS: Unknown material: ", sz);
         }
         }
 
 
         // Now continue and read all material indices
         // Now continue and read all material indices
@@ -997,7 +995,7 @@ void Discreet3DSImporter::ParseFaceChunk()
 
 
             // check range
             // check range
             if (fidx >= mMesh.mFaceMaterials.size())    {
             if (fidx >= mMesh.mFaceMaterials.size())    {
-                DefaultLogger::get()->error("3DS: Invalid face index in face material list");
+                ASSIMP_LOG_ERROR("3DS: Invalid face index in face material list");
             }
             }
             else mMesh.mFaceMaterials[fidx] = idx;
             else mMesh.mFaceMaterials[fidx] = idx;
         }}
         }}
@@ -1112,7 +1110,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
 
 
         if (!cnt)   {
         if (!cnt)   {
             // This may not be, we use the default name instead
             // This may not be, we use the default name instead
-            DefaultLogger::get()->error("3DS: Empty material name");
+            ASSIMP_LOG_ERROR("3DS: Empty material name");
         }
         }
         else mScene->mMaterials.back().mName = std::string(sz,cnt);
         else mScene->mMaterials.back().mName = std::string(sz,cnt);
         }
         }
@@ -1125,7 +1123,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
         ParseColorChunk(pc);
         ParseColorChunk(pc);
         if (is_qnan(pc->r)) {
         if (is_qnan(pc->r)) {
             // color chunk is invalid. Simply ignore it
             // color chunk is invalid. Simply ignore it
-            DefaultLogger::get()->error("3DS: Unable to read DIFFUSE chunk");
+            ASSIMP_LOG_ERROR("3DS: Unable to read DIFFUSE chunk");
             pc->r = pc->g = pc->b = 1.0f;
             pc->r = pc->g = pc->b = 1.0f;
         }}
         }}
         break;
         break;
@@ -1137,7 +1135,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
         ParseColorChunk(pc);
         ParseColorChunk(pc);
         if (is_qnan(pc->r)) {
         if (is_qnan(pc->r)) {
             // color chunk is invalid. Simply ignore it
             // color chunk is invalid. Simply ignore it
-            DefaultLogger::get()->error("3DS: Unable to read SPECULAR chunk");
+            ASSIMP_LOG_ERROR("3DS: Unable to read SPECULAR chunk");
             pc->r = pc->g = pc->b = 1.0f;
             pc->r = pc->g = pc->b = 1.0f;
         }}
         }}
         break;
         break;
@@ -1149,7 +1147,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
         ParseColorChunk(pc);
         ParseColorChunk(pc);
         if (is_qnan(pc->r)) {
         if (is_qnan(pc->r)) {
             // color chunk is invalid. Simply ignore it
             // color chunk is invalid. Simply ignore it
-            DefaultLogger::get()->error("3DS: Unable to read AMBIENT chunk");
+            ASSIMP_LOG_ERROR("3DS: Unable to read AMBIENT chunk");
             pc->r = pc->g = pc->b = 0.0f;
             pc->r = pc->g = pc->b = 0.0f;
         }}
         }}
         break;
         break;
@@ -1161,7 +1159,7 @@ void Discreet3DSImporter::ParseMaterialChunk()
         ParseColorChunk(pc);
         ParseColorChunk(pc);
         if (is_qnan(pc->r)) {
         if (is_qnan(pc->r)) {
             // color chunk is invalid. Simply ignore it
             // color chunk is invalid. Simply ignore it
-            DefaultLogger::get()->error("3DS: Unable to read EMISSIVE chunk");
+            ASSIMP_LOG_ERROR("3DS: Unable to read EMISSIVE chunk");
             pc->r = pc->g = pc->b = 0.0f;
             pc->r = pc->g = pc->b = 0.0f;
         }}
         }}
         break;
         break;
@@ -1295,7 +1293,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
         pcOut->mScaleU = stream->GetF4();
         pcOut->mScaleU = stream->GetF4();
         if (0.0f == pcOut->mScaleU)
         if (0.0f == pcOut->mScaleU)
         {
         {
-            DefaultLogger::get()->warn("Texture coordinate scaling in the x direction is zero. Assuming 1.");
+            ASSIMP_LOG_WARN("Texture coordinate scaling in the x direction is zero. Assuming 1.");
             pcOut->mScaleU = 1.0f;
             pcOut->mScaleU = 1.0f;
         }
         }
         break;
         break;
@@ -1304,7 +1302,7 @@ void Discreet3DSImporter::ParseTextureChunk(D3DS::Texture* pcOut)
         pcOut->mScaleV = stream->GetF4();
         pcOut->mScaleV = stream->GetF4();
         if (0.0f == pcOut->mScaleV)
         if (0.0f == pcOut->mScaleV)
         {
         {
-            DefaultLogger::get()->warn("Texture coordinate scaling in the y direction is zero. Assuming 1.");
+            ASSIMP_LOG_WARN("Texture coordinate scaling in the y direction is zero. Assuming 1.");
             pcOut->mScaleV = 1.0f;
             pcOut->mScaleV = 1.0f;
         }
         }
         break;
         break;

+ 2 - 1
code/3DSLoader.h

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 17 - 2
code/3MFXmlTags.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -44,6 +45,11 @@ namespace Assimp {
 namespace D3MF {
 namespace D3MF {
 
 
 namespace XmlTag {
 namespace XmlTag {
+    // Meta-data
+    static const std::string meta = "metadata";
+    static const std::string meta_name = "name";
+
+    // Model-data specific tags
     static const std::string model = "model";
     static const std::string model = "model";
     static const std::string model_unit = "unit";
     static const std::string model_unit = "unit";
     static const std::string metadata = "metadata";
     static const std::string metadata = "metadata";
@@ -61,6 +67,8 @@ namespace XmlTag {
     static const std::string v2 = "v2";
     static const std::string v2 = "v2";
     static const std::string v3 = "v3";
     static const std::string v3 = "v3";
     static const std::string id = "id";
     static const std::string id = "id";
+    static const std::string pid = "pid";
+    static const std::string p1 = "p1";
     static const std::string name = "name";
     static const std::string name = "name";
     static const std::string type = "type";
     static const std::string type = "type";
     static const std::string build = "build";
     static const std::string build = "build";
@@ -68,6 +76,14 @@ namespace XmlTag {
     static const std::string objectid = "objectid";
     static const std::string objectid = "objectid";
     static const std::string transform = "transform";
     static const std::string transform = "transform";
 
 
+    // Material definitions
+    static const std::string basematerials = "basematerials";
+    static const std::string basematerials_id = "id";
+    static const std::string basematerials_base = "base";
+    static const std::string basematerials_name = "name";
+    static const std::string basematerials_displaycolor = "displaycolor";
+
+    // Meta info tags
     static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
     static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
     static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
     static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
     static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
     static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
@@ -82,7 +98,6 @@ namespace XmlTag {
     static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
     static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
     static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
     static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
     static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
     static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
-
 }
 }
 
 
 } // Namespace D3MF
 } // Namespace D3MF

+ 21 - 20
code/ACLoader.cpp

@@ -4,7 +4,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -84,7 +85,7 @@ static const aiImporterDesc desc = {
 #define AI_AC_SKIP_TO_NEXT_TOKEN() \
 #define AI_AC_SKIP_TO_NEXT_TOKEN() \
     if (!SkipSpaces(&buffer)) \
     if (!SkipSpaces(&buffer)) \
     { \
     { \
-        DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL"); \
+        ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL"); \
         continue; \
         continue; \
     }
     }
 
 
@@ -100,7 +101,7 @@ static const aiImporterDesc desc = {
     { \
     { \
         if (IsLineEnd( *buffer )) \
         if (IsLineEnd( *buffer )) \
         { \
         { \
-            DefaultLogger::get()->error("AC3D: Unexpected EOF/EOL in string"); \
+            ASSIMP_LOG_ERROR("AC3D: Unexpected EOF/EOL in string"); \
             out = "ERROR"; \
             out = "ERROR"; \
             break; \
             break; \
         } \
         } \
@@ -119,7 +120,7 @@ static const aiImporterDesc desc = {
     { \
     { \
         if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \
         if (strncmp(buffer,name,name_length) || !IsSpace(buffer[name_length])) \
         { \
         { \
-            DefaultLogger::get()->error("AC3D: Unexpexted token. " name " was expected."); \
+            ASSIMP_LOG_ERROR("AC3D: Unexpexted token. " name " was expected."); \
             continue; \
             continue; \
         } \
         } \
         buffer += name_length+1; \
         buffer += name_length+1; \
@@ -216,7 +217,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
         light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i",static_cast<unsigned int>(mLights->size())-1);
         light->mName.length = ::ai_snprintf(light->mName.data, MAXLEN, "ACLight_%i",static_cast<unsigned int>(mLights->size())-1);
         obj.name = std::string( light->mName.data );
         obj.name = std::string( light->mName.data );
 
 
-        DefaultLogger::get()->debug("AC3D: Light source encountered");
+        ASSIMP_LOG_DEBUG("AC3D: Light source encountered");
         obj.type = Object::Light;
         obj.type = Object::Light;
     }
     }
     else if (!ASSIMP_strincmp(buffer,"group",5))
     else if (!ASSIMP_strincmp(buffer,"group",5))
@@ -306,12 +307,12 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
             {
             {
                 if (!GetNextLine())
                 if (!GetNextLine())
                 {
                 {
-                    DefaultLogger::get()->error("AC3D: Unexpected EOF: not all vertices have been parsed yet");
+                    ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: not all vertices have been parsed yet");
                     break;
                     break;
                 }
                 }
                 else if (!IsNumeric(*buffer))
                 else if (!IsNumeric(*buffer))
                 {
                 {
-                    DefaultLogger::get()->error("AC3D: Unexpected token: not all vertices have been parsed yet");
+                    ASSIMP_LOG_ERROR("AC3D: Unexpected token: not all vertices have been parsed yet");
                     --buffer; // make sure the line is processed a second time
                     --buffer; // make sure the line is processed a second time
                     break;
                     break;
                 }
                 }
@@ -337,8 +338,8 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
                     // example writes no surf chunks
                     // example writes no surf chunks
                     if (!Q3DWorkAround)
                     if (!Q3DWorkAround)
                     {
                     {
-                        DefaultLogger::get()->warn("AC3D: SURF token was expected");
-                        DefaultLogger::get()->debug("Continuing with Quick3D Workaround enabled");
+                        ASSIMP_LOG_WARN("AC3D: SURF token was expected");
+                        ASSIMP_LOG_DEBUG("Continuing with Quick3D Workaround enabled");
                     }
                     }
                     --buffer; // make sure the line is processed a second time
                     --buffer; // make sure the line is processed a second time
                     // break; --- see fix notes above
                     // break; --- see fix notes above
@@ -383,7 +384,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
                         {
                         {
                             if(!GetNextLine())
                             if(!GetNextLine())
                             {
                             {
-                                DefaultLogger::get()->error("AC3D: Unexpected EOF: surface references are incomplete");
+                                ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: surface references are incomplete");
                                 break;
                                 break;
                             }
                             }
                             surf.entries.push_back(Surface::SurfaceEntry());
                             surf.entries.push_back(Surface::SurfaceEntry());
@@ -404,7 +405,7 @@ void AC3DImporter::LoadObjectSection(std::vector<Object>& objects)
             }
             }
         }
         }
     }
     }
-    DefaultLogger::get()->error("AC3D: Unexpected EOF: \'kids\' line was expected");
+    ASSIMP_LOG_ERROR("AC3D: Unexpected EOF: \'kids\' line was expected");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -477,7 +478,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
                  therefore: if no surfaces are defined return point data only
                  therefore: if no surfaces are defined return point data only
              */
              */
 
 
-            DefaultLogger::get()->info("AC3D: No surfaces defined in object definition, "
+            ASSIMP_LOG_INFO("AC3D: No surfaces defined in object definition, "
                 "a point list is returned");
                 "a point list is returned");
 
 
             meshes.push_back(new aiMesh());
             meshes.push_back(new aiMesh());
@@ -518,12 +519,12 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
                 unsigned int idx = (*it).mat;
                 unsigned int idx = (*it).mat;
                 if (idx >= needMat.size())
                 if (idx >= needMat.size())
                 {
                 {
-                    DefaultLogger::get()->error("AC3D: material index is out of range");
+                    ASSIMP_LOG_ERROR("AC3D: material index is out of range");
                     idx = 0;
                     idx = 0;
                 }
                 }
                 if ((*it).entries.empty())
                 if ((*it).entries.empty())
                 {
                 {
-                    DefaultLogger::get()->warn("AC3D: surface her zero vertex references");
+                    ASSIMP_LOG_WARN("AC3D: surface her zero vertex references");
                 }
                 }
 
 
                 // validate all vertex indices to make sure we won't crash here
                 // validate all vertex indices to make sure we won't crash here
@@ -532,7 +533,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
                 {
                 {
                     if ((*it2).first >= object.vertices.size())
                     if ((*it2).first >= object.vertices.size())
                     {
                     {
-                        DefaultLogger::get()->warn("AC3D: Invalid vertex reference");
+                        ASSIMP_LOG_WARN("AC3D: Invalid vertex reference");
                         (*it2).first = 0;
                         (*it2).first = 0;
                     }
                     }
                 }
                 }
@@ -560,7 +561,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
 
 
                     if ((*it).flags & 0xf)
                     if ((*it).flags & 0xf)
                     {
                     {
-                        DefaultLogger::get()->warn("AC3D: The type flag of a surface is unknown");
+                        ASSIMP_LOG_WARN("AC3D: The type flag of a surface is unknown");
                         (*it).flags &= ~(0xf);
                         (*it).flags &= ~(0xf);
                     }
                     }
 
 
@@ -711,7 +712,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
             if (object.subDiv)  {
             if (object.subDiv)  {
                 if (configEvalSubdivision) {
                 if (configEvalSubdivision) {
                     std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
                     std::unique_ptr<Subdivider> div(Subdivider::Create(Subdivider::CATMULL_CLARKE));
-                    DefaultLogger::get()->info("AC3D: Evaluating subdivision surface: "+object.name);
+                    ASSIMP_LOG_INFO("AC3D: Evaluating subdivision surface: "+object.name);
 
 
                     std::vector<aiMesh*> cpy(meshes.size()-oldm,NULL);
                     std::vector<aiMesh*> cpy(meshes.size()-oldm,NULL);
                     div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true);
                     div->Subdivide(&meshes[oldm],cpy.size(),&cpy.front(),object.subDiv,true);
@@ -720,7 +721,7 @@ aiNode* AC3DImporter::ConvertObjectSection(Object& object,
                     // previous meshes are deleted vy Subdivide().
                     // previous meshes are deleted vy Subdivide().
                 }
                 }
                 else {
                 else {
-                    DefaultLogger::get()->info("AC3D: Letting the subdivision surface untouched due to my configuration: "
+                    ASSIMP_LOG_INFO("AC3D: Letting the subdivision surface untouched due to my configuration: "
                         +object.name);
                         +object.name);
                 }
                 }
             }
             }
@@ -812,7 +813,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
     unsigned int version = HexDigitToDecimal( buffer[4] );
     unsigned int version = HexDigitToDecimal( buffer[4] );
     char msg[3];
     char msg[3];
     ASSIMP_itoa10(msg,3,version);
     ASSIMP_itoa10(msg,3,version);
-    DefaultLogger::get()->info(std::string("AC3D file format version: ") + msg);
+    ASSIMP_LOG_INFO_F("AC3D file format version: ", msg);
 
 
     std::vector<Material> materials;
     std::vector<Material> materials;
     materials.reserve(5);
     materials.reserve(5);
@@ -856,7 +857,7 @@ void AC3DImporter::InternReadFile( const std::string& pFile,
     }
     }
     if (materials.empty())
     if (materials.empty())
     {
     {
-        DefaultLogger::get()->warn("AC3D: No material has been found");
+        ASSIMP_LOG_WARN("AC3D: No material has been found");
         materials.push_back(Material());
         materials.push_back(Material());
     }
     }
 
 

+ 2 - 1
code/ACLoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 3 - 2
code/AMFImporter.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -229,7 +230,7 @@ casu_cres:
 	if(!skipped_before[sk_idx])
 	if(!skipped_before[sk_idx])
 	{
 	{
 		skipped_before[sk_idx] = true;
 		skipped_before[sk_idx] = true;
-		LogWarning("Skipping node \"" + nn + "\" in " + pParentNodeName + ".");
+        ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, ".");
 	}
 	}
 }
 }
 
 

+ 2 - 13
code/AMFImporter.hpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -357,18 +358,6 @@ private:
 	/************** Functions: LOG set *************/
 	/************** Functions: LOG set *************/
 	/***********************************************/
 	/***********************************************/
 
 
-	/// \fn void LogInfo(const std::string& pMessage)
-	/// Short variant for calling \ref DefaultLogger::get()->info()
-	void LogInfo(const std::string& pMessage) { DefaultLogger::get()->info(pMessage); }
-
-	/// \fn void LogWarning(const std::string& pMessage)
-	/// Short variant for calling \ref DefaultLogger::get()->warn()
-	void LogWarning(const std::string& pMessage) { DefaultLogger::get()->warn(pMessage); }
-
-	/// \fn void LogError(const std::string& pMessage)
-	/// Short variant for calling \ref DefaultLogger::get()->error()
-	void LogError(const std::string& pMessage) { DefaultLogger::get()->error(pMessage); }
-
 	/***********************************************/
 	/***********************************************/
 	/************** Functions: XML set *************/
 	/************** Functions: XML set *************/
 	/***********************************************/
 	/***********************************************/

+ 2 - 1
code/AMFImporter_Geometry.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.

+ 6 - 5
code/AMFImporter_Macro.hpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -70,7 +71,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 	}
 	}
 
 
 /// \def MACRO_ATTRREAD_CHECK_REF
 /// \def MACRO_ATTRREAD_CHECK_REF
-/// Check curent attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
+/// Check current attribute name and if it equal to requested then read value. Result write to output variable by reference. If result was read then
 /// "continue" will called.
 /// "continue" will called.
 /// \param [in] pAttrName - attribute name.
 /// \param [in] pAttrName - attribute name.
 /// \param [out] pVarName - output variable name.
 /// \param [out] pVarName - output variable name.
@@ -83,7 +84,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 	}
 	}
 
 
 /// \def MACRO_ATTRREAD_CHECK_RET
 /// \def MACRO_ATTRREAD_CHECK_RET
-/// Check curent attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
+/// Check current attribute name and if it equal to requested then read value. Result write to output variable using return value of \ref pFunction.
 /// If result was read then  "continue" will called.
 /// If result was read then  "continue" will called.
 /// \param [in] pAttrName - attribute name.
 /// \param [in] pAttrName - attribute name.
 /// \param [out] pVarName - output variable name.
 /// \param [out] pVarName - output variable name.
@@ -129,7 +130,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 	} while(false)
 	} while(false)
 
 
 /// \def MACRO_NODECHECK_READCOMP_F
 /// \def MACRO_NODECHECK_READCOMP_F
-/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "float".
+/// Check current node name and if it equal to requested then read value. Result write to output variable of type "float".
 /// If result was read then  "continue" will called. Also check if node data already read then raise exception.
 /// If result was read then  "continue" will called. Also check if node data already read then raise exception.
 /// \param [in] pNodeName - node name.
 /// \param [in] pNodeName - node name.
 /// \param [in, out] pReadFlag - read flag.
 /// \param [in, out] pReadFlag - read flag.
@@ -146,7 +147,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 	}
 	}
 
 
 /// \def MACRO_NODECHECK_READCOMP_U32
 /// \def MACRO_NODECHECK_READCOMP_U32
-/// Check curent node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
+/// Check current node name and if it equal to requested then read value. Result write to output variable of type "uint32_t".
 /// If result was read then  "continue" will called. Also check if node data already read then raise exception.
 /// If result was read then  "continue" will called. Also check if node data already read then raise exception.
 /// \param [in] pNodeName - node name.
 /// \param [in] pNodeName - node name.
 /// \param [in, out] pReadFlag - read flag.
 /// \param [in, out] pReadFlag - read flag.

+ 3 - 2
code/AMFImporter_Material.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -98,7 +99,7 @@ CAMFImporter_NodeElement* ne;
 		ParseHelper_Node_Exit();
 		ParseHelper_Node_Exit();
 		// check that all components was defined
 		// check that all components was defined
 		if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined.");
 		if(!(read_flag[0] && read_flag[1] && read_flag[2])) throw DeadlyImportError("Not all color components are defined.");
-		// check if <a> is absent. Then manualy add "a == 1".
+		// check if <a> is absent. Then manually add "a == 1".
 		if(!read_flag[3]) als.Color.a = 1;
 		if(!read_flag[3]) als.Color.a = 1;
 
 
 	}// if(!mReader->isEmptyElement())
 	}// if(!mReader->isEmptyElement())

+ 2 - 1
code/AMFImporter_Node.hpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.

+ 8 - 6
code/AMFImporter_Postprocess.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -155,10 +156,11 @@ size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string&
 	TextureConverted_Index = 0;
 	TextureConverted_Index = 0;
 	for(const SPP_Texture& tex_convd: mTexture_Converted)
 	for(const SPP_Texture& tex_convd: mTexture_Converted)
 	{
 	{
-		if(tex_convd.ID == TextureConverted_ID)
-			return TextureConverted_Index;
-		else
-			TextureConverted_Index++;
+        if ( tex_convd.ID == TextureConverted_ID ) {
+            return TextureConverted_Index;
+        } else {
+            ++TextureConverted_Index;
+        }
 	}
 	}
 
 
 	//
 	//
@@ -768,7 +770,7 @@ std::list<aiNode*> ch_node;
 		// find referenced object
 		// find referenced object
 		if(!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID);
 		if(!Find_ConvertedNode(als.ObjectID, pNodeList, &found_node)) Throw_ID_NotFound(als.ObjectID);
 
 
-		// create node for apllying transformation
+		// create node for applying transformation
 		t_node = new aiNode;
 		t_node = new aiNode;
 		t_node->mParent = con_node;
 		t_node->mParent = con_node;
 		// apply transformation
 		// apply transformation

+ 17 - 17
code/ASELoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -83,11 +84,11 @@ static const aiImporterDesc desc = {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 ASEImporter::ASEImporter()
 ASEImporter::ASEImporter()
-    : mParser(),
-    mBuffer(),
-    pcScene(),
-    configRecomputeNormals(),
-    noSkeletonMesh()
+: mParser()
+, mBuffer()
+, pcScene()
+, configRecomputeNormals()
+, noSkeletonMesh()
 {}
 {}
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -199,7 +200,7 @@ void ASEImporter::InternReadFile( const std::string& pFile,
             ConvertMeshes(*i,avOutMeshes);
             ConvertMeshes(*i,avOutMeshes);
         }
         }
         if (tookNormals)    {
         if (tookNormals)    {
-            DefaultLogger::get()->debug("ASE: Taking normals from the file. Use "
+            ASSIMP_LOG_DEBUG("ASE: Taking normals from the file. Use "
                 "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you "
                 "the AI_CONFIG_IMPORT_ASE_RECONSTRUCT_NORMALS setting if you "
                 "experience problems");
                 "experience problems");
         }
         }
@@ -276,14 +277,13 @@ void ASEImporter::GenerateDefaultMaterial()
     }
     }
     if (bHas || mParser->m_vMaterials.empty())  {
     if (bHas || mParser->m_vMaterials.empty())  {
         // add a simple material without submaterials to the parser's list
         // add a simple material without submaterials to the parser's list
-        mParser->m_vMaterials.push_back ( ASE::Material() );
+        mParser->m_vMaterials.push_back ( ASE::Material(AI_DEFAULT_MATERIAL_NAME) );
         ASE::Material& mat = mParser->m_vMaterials.back();
         ASE::Material& mat = mParser->m_vMaterials.back();
 
 
         mat.mDiffuse  = aiColor3D(0.6f,0.6f,0.6f);
         mat.mDiffuse  = aiColor3D(0.6f,0.6f,0.6f);
         mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
         mat.mSpecular = aiColor3D(1.0f,1.0f,1.0f);
         mat.mAmbient  = aiColor3D(0.05f,0.05f,0.05f);
         mat.mAmbient  = aiColor3D(0.05f,0.05f,0.05f);
         mat.mShading  = Discreet3DS::Gouraud;
         mat.mShading  = Discreet3DS::Gouraud;
-        mat.mName     = AI_DEFAULT_MATERIAL_NAME;
     }
     }
 }
 }
 
 
@@ -297,15 +297,15 @@ void ASEImporter::BuildAnimations(const std::vector<BaseNode*>& nodes)
 
 
         // TODO: Implement Bezier & TCB support
         // TODO: Implement Bezier & TCB support
         if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) {
         if ((*i)->mAnim.mPositionType != ASE::Animation::TRACK) {
-            DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
+            ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. "
                 "This is not supported.");
                 "This is not supported.");
         }
         }
         if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) {
         if ((*i)->mAnim.mRotationType != ASE::Animation::TRACK) {
-            DefaultLogger::get()->warn("ASE: Rotation controller uses Bezier/TCB keys. "
+            ASSIMP_LOG_WARN("ASE: Rotation controller uses Bezier/TCB keys. "
                 "This is not supported.");
                 "This is not supported.");
         }
         }
         if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK)  {
         if ((*i)->mAnim.mScalingType != ASE::Animation::TRACK)  {
-            DefaultLogger::get()->warn("ASE: Position controller uses Bezier/TCB keys. "
+            ASSIMP_LOG_WARN("ASE: Position controller uses Bezier/TCB keys. "
                 "This is not supported.");
                 "This is not supported.");
         }
         }
 
 
@@ -583,7 +583,7 @@ void ASEImporter::AddNodes (const std::vector<BaseNode*>& nodes,
         node->mTransformation = mParentAdjust*snode->mTransform;
         node->mTransformation = mParentAdjust*snode->mTransform;
 
 
         // Add sub nodes - prevent stack overflow due to recursive parenting
         // Add sub nodes - prevent stack overflow due to recursive parenting
-        if (node->mName != node->mParent->mName) {
+        if (node->mName != node->mParent->mName && node->mName != node->mParent->mParent->mName ) {
             AddNodes(nodes,node,node->mName.data,snode->mTransform);
             AddNodes(nodes,node,node->mName.data,snode->mTransform);
         }
         }
 
 
@@ -624,7 +624,7 @@ void ASEImporter::AddNodes (const std::vector<BaseNode*>& nodes,
             node->mNumChildren++;
             node->mNumChildren++;
 
 
             // What we did is so great, it is at least worth a debug message
             // What we did is so great, it is at least worth a debug message
-            DefaultLogger::get()->debug("ASE: Generating separate target node ("+snode->mName+")");
+            ASSIMP_LOG_DEBUG("ASE: Generating separate target node ("+snode->mName+")");
         }
         }
     }
     }
 
 
@@ -947,7 +947,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
     // validate the material index of the mesh
     // validate the material index of the mesh
     if (mesh.iMaterialIndex >= mParser->m_vMaterials.size())    {
     if (mesh.iMaterialIndex >= mParser->m_vMaterials.size())    {
         mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1;
         mesh.iMaterialIndex = (unsigned int)mParser->m_vMaterials.size()-1;
-        DefaultLogger::get()->warn("Material index is out of range");
+        ASSIMP_LOG_WARN("Material index is out of range");
     }
     }
 
 
     // If the material the mesh is assigned to is consisting of submeshes, split it
     // If the material the mesh is assigned to is consisting of submeshes, split it
@@ -957,11 +957,11 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
 
 
         std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[vSubMaterials.size()];
         std::vector<unsigned int>* aiSplit = new std::vector<unsigned int>[vSubMaterials.size()];
 
 
-        // build a list of all faces per submaterial
+        // build a list of all faces per sub-material
         for (unsigned int i = 0; i < mesh.mFaces.size();++i)    {
         for (unsigned int i = 0; i < mesh.mFaces.size();++i)    {
             // check range
             // check range
             if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) {
             if (mesh.mFaces[i].iMaterial >= vSubMaterials.size()) {
-                DefaultLogger::get()->warn("Submaterial index is out of range");
+                ASSIMP_LOG_WARN("Submaterial index is out of range");
 
 
                 // use the last material instead
                 // use the last material instead
                 aiSplit[vSubMaterials.size()-1].push_back(i);
                 aiSplit[vSubMaterials.size()-1].push_back(i);

+ 2 - 1
code/ASELoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 35 - 32
code/ASEParser.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -150,7 +151,7 @@ void Parser::LogWarning(const char* szWarn)
 #endif
 #endif
 
 
     // output the warning to the logger ...
     // output the warning to the logger ...
-    DefaultLogger::get()->warn(szTemp);
+    ASSIMP_LOG_WARN(szTemp);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -166,7 +167,7 @@ void Parser::LogInfo(const char* szWarn)
 #endif
 #endif
 
 
     // output the information to the logger ...
     // output the information to the logger ...
-    DefaultLogger::get()->info(szTemp);
+    ASSIMP_LOG_INFO(szTemp);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -266,7 +267,9 @@ void Parser::Parse()
                 // at the file extension (ASE, ASK, ASC)
                 // at the file extension (ASE, ASK, ASC)
                 // *************************************************************
                 // *************************************************************
 
 
-                if (fmt)iFileFormat = fmt;
+                if ( fmt ) {
+                    iFileFormat = fmt;
+                }
                 continue;
                 continue;
             }
             }
             // main scene information
             // main scene information
@@ -292,7 +295,7 @@ void Parser::Parse()
             if (TokenMatch(filePtr,"GEOMOBJECT",10))
             if (TokenMatch(filePtr,"GEOMOBJECT",10))
 
 
             {
             {
-                m_vMeshes.push_back(Mesh());
+                m_vMeshes.push_back(Mesh("UNNAMED"));
                 ParseLV1ObjectBlock(m_vMeshes.back());
                 ParseLV1ObjectBlock(m_vMeshes.back());
                 continue;
                 continue;
             }
             }
@@ -308,14 +311,14 @@ void Parser::Parse()
             if (TokenMatch(filePtr,"LIGHTOBJECT",11))
             if (TokenMatch(filePtr,"LIGHTOBJECT",11))
 
 
             {
             {
-                m_vLights.push_back(Light());
+                m_vLights.push_back(Light("UNNAMED"));
                 ParseLV1ObjectBlock(m_vLights.back());
                 ParseLV1ObjectBlock(m_vLights.back());
                 continue;
                 continue;
             }
             }
             // camera object
             // camera object
             if (TokenMatch(filePtr,"CAMERAOBJECT",12))
             if (TokenMatch(filePtr,"CAMERAOBJECT",12))
             {
             {
-                m_vCameras.push_back(Camera());
+                m_vCameras.push_back(Camera("UNNAMED"));
                 ParseLV1ObjectBlock(m_vCameras.back());
                 ParseLV1ObjectBlock(m_vCameras.back());
                 continue;
                 continue;
             }
             }
@@ -426,28 +429,25 @@ void Parser::ParseLV1SoftSkinBlock()
                         // Reserve enough storage
                         // Reserve enough storage
                         vert.mBoneWeights.reserve(numWeights);
                         vert.mBoneWeights.reserve(numWeights);
 
 
-                        for (unsigned int w = 0; w < numWeights;++w)
-                        {
-                            std::string bone;
+                        std::string bone;
+                        for (unsigned int w = 0; w < numWeights;++w) {
+                            bone.clear();
                             ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
                             ParseString(bone,"*MESH_SOFTSKINVERTS.Bone");
 
 
                             // Find the bone in the mesh's list
                             // Find the bone in the mesh's list
                             std::pair<int,ai_real> me;
                             std::pair<int,ai_real> me;
                             me.first = -1;
                             me.first = -1;
 
 
-                            for (unsigned int n = 0; n < curMesh->mBones.size();++n)
-                            {
-                                if (curMesh->mBones[n].mName == bone)
-                                {
+                            for (unsigned int n = 0; n < curMesh->mBones.size();++n) {
+                                if (curMesh->mBones[n].mName == bone) {
                                     me.first = n;
                                     me.first = n;
                                     break;
                                     break;
                                 }
                                 }
                             }
                             }
-                            if (-1 == me.first)
-                            {
+                            if (-1 == me.first) {
                                 // We don't have this bone yet, so add it to the list
                                 // We don't have this bone yet, so add it to the list
-                                me.first = (int)curMesh->mBones.size();
-                                curMesh->mBones.push_back(ASE::Bone(bone));
+                                me.first = static_cast<int>( curMesh->mBones.size() );
+                                curMesh->mBones.push_back( ASE::Bone( bone ) );
                             }
                             }
                             ParseLV4MeshFloat( me.second );
                             ParseLV4MeshFloat( me.second );
 
 
@@ -528,7 +528,7 @@ void Parser::ParseLV1MaterialListBlock()
                 ParseLV4MeshLong(iMaterialCount);
                 ParseLV4MeshLong(iMaterialCount);
 
 
                 // now allocate enough storage to hold all materials
                 // now allocate enough storage to hold all materials
-                m_vMaterials.resize(iOldMaterialCount+iMaterialCount);
+                m_vMaterials.resize(iOldMaterialCount+iMaterialCount, Material("INVALID"));
                 continue;
                 continue;
             }
             }
             if (TokenMatch(filePtr,"MATERIAL",8))
             if (TokenMatch(filePtr,"MATERIAL",8))
@@ -706,7 +706,7 @@ void Parser::ParseLV2MaterialBlock(ASE::Material& mat)
                 ParseLV4MeshLong(iNumSubMaterials);
                 ParseLV4MeshLong(iNumSubMaterials);
 
 
                 // allocate enough storage
                 // allocate enough storage
-                mat.avSubMaterials.resize(iNumSubMaterials);
+                mat.avSubMaterials.resize(iNumSubMaterials, Material("INVALID SUBMATERIAL"));
             }
             }
             // submaterial chunks
             // submaterial chunks
             if (TokenMatch(filePtr,"SUBMATERIAL",11))
             if (TokenMatch(filePtr,"SUBMATERIAL",11))
@@ -744,6 +744,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
     // empty the texture won't be used later.
     // empty the texture won't be used later.
     // ***********************************************************
     // ***********************************************************
     bool parsePath = true;
     bool parsePath = true;
+    std::string temp;
     while (true)
     while (true)
     {
     {
         if ('*' == *filePtr)
         if ('*' == *filePtr)
@@ -752,12 +753,12 @@ void Parser::ParseLV3MapBlock(Texture& map)
             // type of map
             // type of map
             if (TokenMatch(filePtr,"MAP_CLASS" ,9))
             if (TokenMatch(filePtr,"MAP_CLASS" ,9))
             {
             {
-                std::string temp;
+                temp.clear();
                 if(!ParseString(temp,"*MAP_CLASS"))
                 if(!ParseString(temp,"*MAP_CLASS"))
                     SkipToNextToken();
                     SkipToNextToken();
                 if (temp != "Bitmap" && temp != "Normal Bump")
                 if (temp != "Bitmap" && temp != "Normal Bump")
                 {
                 {
-                    DefaultLogger::get()->warn("ASE: Skipping unknown map type: " + temp);
+                    ASSIMP_LOG_WARN_F("ASE: Skipping unknown map type: ", temp);
                     parsePath = false;
                     parsePath = false;
                 }
                 }
                 continue;
                 continue;
@@ -772,7 +773,7 @@ void Parser::ParseLV3MapBlock(Texture& map)
                 {
                 {
                     // Files with 'None' as map name are produced by
                     // Files with 'None' as map name are produced by
                     // an Maja to ASE exporter which name I forgot ..
                     // an Maja to ASE exporter which name I forgot ..
-                    DefaultLogger::get()->warn("ASE: Skipping invalid map entry");
+                    ASSIMP_LOG_WARN("ASE: Skipping invalid map entry");
                     map.mMapName = "";
                     map.mMapName = "";
                 }
                 }
 
 
@@ -1071,7 +1072,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
                         ( mesh.mType != BaseNode::Light  || ((ASE::Light&)mesh).mLightType   != ASE::Light::TARGET))
                         ( mesh.mType != BaseNode::Light  || ((ASE::Light&)mesh).mLightType   != ASE::Light::TARGET))
                     {
                     {
 
 
-                        DefaultLogger::get()->error("ASE: Found target animation channel "
+                        ASSIMP_LOG_ERROR("ASE: Found target animation channel "
                             "but the node is neither a camera nor a spot light");
                             "but the node is neither a camera nor a spot light");
                         anim = NULL;
                         anim = NULL;
                     }
                     }
@@ -1097,7 +1098,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
                 if (!anim || anim == &mesh.mTargetAnim)
                 if (!anim || anim == &mesh.mTargetAnim)
                 {
                 {
                     // Target animation channels may have no rotation channels
                     // Target animation channels may have no rotation channels
-                    DefaultLogger::get()->error("ASE: Ignoring scaling channel in target animation");
+                    ASSIMP_LOG_ERROR("ASE: Ignoring scaling channel in target animation");
                     SkipSection();
                     SkipSection();
                 }
                 }
                 else ParseLV3ScaleAnimationBlock(*anim);
                 else ParseLV3ScaleAnimationBlock(*anim);
@@ -1111,7 +1112,7 @@ void Parser::ParseLV2AnimationBlock(ASE::BaseNode& mesh)
                 if (!anim || anim == &mesh.mTargetAnim)
                 if (!anim || anim == &mesh.mTargetAnim)
                 {
                 {
                     // Target animation channels may have no rotation channels
                     // Target animation channels may have no rotation channels
-                    DefaultLogger::get()->error("ASE: Ignoring rotation channel in target animation");
+                    ASSIMP_LOG_ERROR("ASE: Ignoring rotation channel in target animation");
                     SkipSection();
                     SkipSection();
                 }
                 }
                 else ParseLV3RotAnimationBlock(*anim);
                 else ParseLV3RotAnimationBlock(*anim);
@@ -1294,12 +1295,14 @@ void Parser::ParseLV2NodeTransformBlock(ASE::BaseNode& mesh)
                     {
                     {
                         mode = 2;
                         mode = 2;
                     }
                     }
-                    else DefaultLogger::get()->error("ASE: Ignoring target transform, "
-                        "this is no spot light or target camera");
+                    else {
+                        ASSIMP_LOG_ERROR("ASE: Ignoring target transform, "
+                            "this is no spot light or target camera");
+                    }
                 }
                 }
                 else
                 else
                 {
                 {
-                    DefaultLogger::get()->error("ASE: Unknown node transformation: " + temp);
+                    ASSIMP_LOG_ERROR("ASE: Unknown node transformation: " + temp);
                     // mode = 0
                     // mode = 0
                 }
                 }
                 continue;
                 continue;
@@ -1553,7 +1556,7 @@ void Parser::ParseLV3MeshWeightsBlock(ASE::Mesh& mesh)
 void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
 void Parser::ParseLV4MeshBones(unsigned int iNumBones,ASE::Mesh& mesh)
 {
 {
     AI_ASE_PARSER_INIT();
     AI_ASE_PARSER_INIT();
-    mesh.mBones.resize(iNumBones);
+    mesh.mBones.resize(iNumBones, Bone("UNNAMED"));
     while (true)
     while (true)
     {
     {
         if ('*' == *filePtr)
         if ('*' == *filePtr)
@@ -1915,7 +1918,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
                 else if (index == face.mIndices[2])
                 else if (index == face.mIndices[2])
                     index = 2;
                     index = 2;
                 else    {
                 else    {
-                    DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
+                    ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_VERTEXNORMAL section");
                     continue;
                     continue;
                 }
                 }
                 // We'll renormalize later
                 // We'll renormalize later
@@ -1927,7 +1930,7 @@ void Parser::ParseLV3MeshNormalListBlock(ASE::Mesh& sMesh)
                 ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
                 ParseLV4MeshFloatTriple(&vNormal.x,faceIdx);
 
 
                 if (faceIdx >= sMesh.mFaces.size()) {
                 if (faceIdx >= sMesh.mFaces.size()) {
-                    DefaultLogger::get()->error("ASE: Invalid vertex index in MESH_FACENORMAL section");
+                    ASSIMP_LOG_ERROR("ASE: Invalid vertex index in MESH_FACENORMAL section");
                     continue;
                     continue;
                 }
                 }
 
 

+ 91 - 46
code/ASEParser.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -67,10 +68,53 @@ using namespace D3DS;
 /** Helper structure representing an ASE material */
 /** Helper structure representing an ASE material */
 struct Material : public D3DS::Material
 struct Material : public D3DS::Material
 {
 {
-    //! Default constructor
-    Material() : pcInstance(NULL), bNeed (false)
+    //! Default constructor has been deleted
+    Material() = delete;
+
+
+    //! Constructor with explicit name
+    explicit Material(const std::string &name)
+    : D3DS::Material(name)
+    , pcInstance(NULL)
+    , bNeed (false)
     {}
     {}
 
 
+
+    Material(const Material &other)            = default;
+    Material &operator=(const Material &other) = default;
+
+
+    //! Move constructor. This is explicitly written because MSVC doesn't support defaulting it
+    Material(Material &&other)
+    : D3DS::Material(std::move(other))
+    , avSubMaterials(std::move(other.avSubMaterials))
+    , pcInstance(std::move(other.pcInstance))
+    , bNeed(std::move(other.bNeed))
+    {
+        other.pcInstance = nullptr;
+    }
+
+
+    Material &operator=(Material &&other) {
+        if (this == &other) {
+            return *this;
+        }
+
+        D3DS::Material::operator=(std::move(other));
+
+        avSubMaterials = std::move(other.avSubMaterials);
+        pcInstance = std::move(other.pcInstance);
+        bNeed = std::move(other.bNeed);
+
+        other.pcInstance = nullptr;
+
+        return *this;
+    }
+
+
+    ~Material() {}
+
+
     //! Contains all sub materials of this material
     //! Contains all sub materials of this material
     std::vector<Material> avSubMaterials;
     std::vector<Material> avSubMaterials;
 
 
@@ -125,15 +169,7 @@ struct Face : public FaceWithSmoothingGroup
 struct Bone
 struct Bone
 {
 {
     //! Constructor
     //! Constructor
-    Bone()
-    {
-        static int iCnt = 0;
-
-        // Generate a default name for the bone
-        char szTemp[128];
-        ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
-        mName = szTemp;
-    }
+    Bone() = delete;
 
 
     //! Construction from an existing name
     //! Construction from an existing name
     explicit Bone( const std::string& name)
     explicit Bone( const std::string& name)
@@ -213,22 +249,19 @@ struct BaseNode
 {
 {
     enum Type {Light, Camera, Mesh, Dummy} mType;
     enum Type {Light, Camera, Mesh, Dummy} mType;
 
 
-    //! Constructor. Creates a default name for the node
-    explicit BaseNode(Type _mType)
-        : mType         (_mType)
-        , mProcessed    (false)
-    {
-        // generate a default name for the  node
-        static int iCnt = 0;
-        char szTemp[128]; // should be sufficiently large
-        ::ai_snprintf(szTemp, 128, "UNNAMED_%i",iCnt++);
-        mName = szTemp;
 
 
+    //! Construction from an existing name
+    BaseNode(Type _mType, const std::string &name)
+    : mType         (_mType)
+    , mName         (name)
+    , mProcessed    (false)
+    {
         // Set mTargetPosition to qnan
         // Set mTargetPosition to qnan
         const ai_real qnan = get_qnan();
         const ai_real qnan = get_qnan();
         mTargetPosition.x = qnan;
         mTargetPosition.x = qnan;
     }
     }
 
 
+
     //! Name of the mesh
     //! Name of the mesh
     std::string mName;
     std::string mName;
 
 
@@ -260,19 +293,22 @@ struct BaseNode
 /** Helper structure to represent an ASE file mesh */
 /** Helper structure to represent an ASE file mesh */
 struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode
 struct Mesh : public MeshWithSmoothingGroups<ASE::Face>, public BaseNode
 {
 {
-    //! Constructor.
-    Mesh()
-        : BaseNode  (BaseNode::Mesh)
-        , bSkip     (false)
+    //! Default constructor has been deleted
+    Mesh() = delete;
+
+
+    //! Construction from an existing name
+    explicit Mesh(const std::string &name)
+    : BaseNode  (BaseNode::Mesh, name)
+    , iMaterialIndex(Face::DEFAULT_MATINDEX)
+    , bSkip     (false)
     {
     {
         // use 2 texture vertex components by default
         // use 2 texture vertex components by default
         for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
         for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS;++c)
             this->mNumUVComponents[c] = 2;
             this->mNumUVComponents[c] = 2;
-
-        // setup the default material index by default
-        iMaterialIndex = Face::DEFAULT_MATINDEX;
     }
     }
 
 
+
     //! List of all texture coordinate sets
     //! List of all texture coordinate sets
     std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
     std::vector<aiVector3D> amTexCoords[AI_MAX_NUMBER_OF_TEXTURECOORDS];
 
 
@@ -307,17 +343,21 @@ struct Light : public BaseNode
         DIRECTIONAL
         DIRECTIONAL
     };
     };
 
 
-    //! Constructor.
-    Light()
-        : BaseNode   (BaseNode::Light)
-        , mLightType (OMNI)
-        , mColor     (1.f,1.f,1.f)
-        , mIntensity (1.f) // light is white by default
-        , mAngle     (45.f)
-        , mFalloff   (0.f)
+    //! Default constructor has been deleted
+    Light() = delete;
+
+    //! Construction from an existing name
+    explicit Light(const std::string &name)
+    : BaseNode   (BaseNode::Light, name)
+    , mLightType (OMNI)
+    , mColor     (1.f,1.f,1.f)
+    , mIntensity (1.f) // light is white by default
+    , mAngle     (45.f)
+    , mFalloff   (0.f)
     {
     {
     }
     }
 
 
+
     LightType mLightType;
     LightType mLightType;
     aiColor3D mColor;
     aiColor3D mColor;
     ai_real mIntensity;
     ai_real mIntensity;
@@ -335,16 +375,21 @@ struct Camera : public BaseNode
         TARGET
         TARGET
     };
     };
 
 
-    //! Constructor
-    Camera()
-        : BaseNode    (BaseNode::Camera)
-        , mFOV        (0.75f)   // in radians
-        , mNear       (0.1f)
-        , mFar        (1000.f)  // could be zero
-        , mCameraType (FREE)
+    //! Default constructor has been deleted
+    Camera() = delete;
+
+
+    //! Construction from an existing name
+    explicit Camera(const std::string &name)
+    : BaseNode    (BaseNode::Camera, name)
+    , mFOV        (0.75f)   // in radians
+    , mNear       (0.1f)
+    , mFar        (1000.f)  // could be zero
+    , mCameraType (FREE)
     {
     {
     }
     }
 
 
+
     ai_real mFOV, mNear, mFar;
     ai_real mFOV, mNear, mFar;
     CameraType mCameraType;
     CameraType mCameraType;
 };
 };
@@ -355,7 +400,7 @@ struct Dummy : public BaseNode
 {
 {
     //! Constructor
     //! Constructor
     Dummy()
     Dummy()
-        : BaseNode  (BaseNode::Dummy)
+        : BaseNode  (BaseNode::Dummy, "DUMMY")
     {
     {
     }
     }
 };
 };
@@ -382,7 +427,7 @@ public:
 
 
     // -------------------------------------------------------------------
     // -------------------------------------------------------------------
     //! Construct a parser from a given input file which is
     //! Construct a parser from a given input file which is
-    //! guaranted to be terminated with zero.
+    //! guaranteed to be terminated with zero.
     //! @param szFile Input file
     //! @param szFile Input file
     //! @param fileFormatDefault Assumed file format version. If the
     //! @param fileFormatDefault Assumed file format version. If the
     //!   file format is specified in the file the new value replaces
     //!   file format is specified in the file the new value replaces

+ 6 - 5
code/AssbinExporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -41,6 +42,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  AssbinExporter.cpp
 /** @file  AssbinExporter.cpp
  *  ASSBIN exporter main code
  *  ASSBIN exporter main code
  */
  */
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
+
 #include "assbin_chunks.h"
 #include "assbin_chunks.h"
 #include <assimp/version.h>
 #include <assimp/version.h>
 #include <assimp/IOStream.hpp>
 #include <assimp/IOStream.hpp>
@@ -57,10 +62,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #include <time.h>
 #include <time.h>
 
 
-
-#ifndef ASSIMP_BUILD_NO_EXPORT
-#ifndef ASSIMP_BUILD_NO_ASSBIN_EXPORTER
-
 using namespace Assimp;
 using namespace Assimp;
 
 
 namespace Assimp    {
 namespace Assimp    {

+ 2 - 1
code/AssbinExporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 2 - 1
code/AssbinLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.

+ 2 - 1
code/AssbinLoader.h

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 3 - 2
code/Assimp.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -145,7 +146,7 @@ private:
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void ReportSceneNotFoundError() {
 void ReportSceneNotFoundError() {
-    DefaultLogger::get()->error("Unable to find the Assimp::Importer for this aiScene. "
+    ASSIMP_LOG_ERROR("Unable to find the Assimp::Importer for this aiScene. "
         "The C-API does not accept scenes produced by the C++ API and vice versa");
         "The C-API does not accept scenes produced by the C++ API and vice versa");
 
 
     ai_assert(false);
     ai_assert(false);

+ 2 - 1
code/AssimpCExport.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.

+ 6 - 4
code/AssxmlExporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -41,6 +42,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 /** @file  AssxmlExporter.cpp
 /** @file  AssxmlExporter.cpp
  *  ASSXML exporter main code
  *  ASSXML exporter main code
  */
  */
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
+
 #include <stdarg.h>
 #include <stdarg.h>
 #include <assimp/version.h>
 #include <assimp/version.h>
 #include "ProcessHelper.h"
 #include "ProcessHelper.h"
@@ -57,9 +62,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <time.h>
 #include <time.h>
 #include <stdio.h>
 #include <stdio.h>
 
 
-#ifndef ASSIMP_BUILD_NO_EXPORT
-#ifndef ASSIMP_BUILD_NO_ASSXML_EXPORTER
-
 using namespace Assimp;
 using namespace Assimp;
 
 
 namespace Assimp    {
 namespace Assimp    {

+ 2 - 1
code/AssxmlExporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 3 - 2
code/B3DImporter.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -613,7 +614,7 @@ void B3DImporter::ReadBB3D( aiScene *scene ){
         if (!DefaultLogger::isNullLogger()) {
         if (!DefaultLogger::isNullLogger()) {
             char dmp[128];
             char dmp[128];
             ai_snprintf(dmp, 128, "B3D file format version: %i",version);
             ai_snprintf(dmp, 128, "B3D file format version: %i",version);
-            DefaultLogger::get()->info(dmp);
+            ASSIMP_LOG_INFO(dmp);
         }
         }
 
 
         while( ChunkSize() ){
         while( ChunkSize() ){

+ 2 - 1
code/B3DImporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 16 - 14
code/BVHLoader.cpp

@@ -4,7 +4,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -198,6 +199,7 @@ aiNode* BVHLoader::ReadNode()
     Node& internNode = mNodes.back();
     Node& internNode = mNodes.back();
 
 
     // now read the node's contents
     // now read the node's contents
+    std::string siteToken;
     while( 1)
     while( 1)
     {
     {
         std::string token = GetNextToken();
         std::string token = GetNextToken();
@@ -217,7 +219,8 @@ aiNode* BVHLoader::ReadNode()
         else if( token == "End")
         else if( token == "End")
         {
         {
             // The real symbol is "End Site". Second part comes in a separate token
             // The real symbol is "End Site". Second part comes in a separate token
-            std::string siteToken = GetNextToken();
+            siteToken.clear();
+            siteToken = GetNextToken();
             if( siteToken != "Site")
             if( siteToken != "Site")
                 ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." );
                 ThrowException( format() << "Expected \"End Site\" keyword, but found \"" << token << " " << siteToken << "\"." );
 
 
@@ -261,21 +264,18 @@ aiNode* BVHLoader::ReadEndSite( const std::string& pParentName)
     aiNode* node = new aiNode( "EndSite_" + pParentName);
     aiNode* node = new aiNode( "EndSite_" + pParentName);
 
 
     // now read the node's contents. Only possible entry is "OFFSET"
     // now read the node's contents. Only possible entry is "OFFSET"
-    while( 1)
-    {
-        std::string token = GetNextToken();
+    std::string token;
+    while( 1) {
+        token.clear();
+        token = GetNextToken();
 
 
         // end node's offset
         // end node's offset
-        if( token == "OFFSET")
-        {
+        if( token == "OFFSET") {
             ReadNodeOffset( node);
             ReadNodeOffset( node);
-        }
-        else if( token == "}")
-        {
+        } else if( token == "}") {
             // we're done with the end node
             // we're done with the end node
             break;
             break;
-        } else
-        {
+        } else {
             // everything else is a parse error
             // everything else is a parse error
             ThrowException( format() << "Unknown keyword \"" << token << "\"." );
             ThrowException( format() << "Unknown keyword \"" << token << "\"." );
         }
         }
@@ -295,8 +295,10 @@ void BVHLoader::ReadNodeOffset( aiNode* pNode)
     offset.z = GetNextTokenAsFloat();
     offset.z = GetNextTokenAsFloat();
 
 
     // build a transformation matrix from it
     // build a transformation matrix from it
-    pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x, 0.0f, 1.0f, 0.0f, offset.y,
-        0.0f, 0.0f, 1.0f, offset.z, 0.0f, 0.0f, 0.0f, 1.0f);
+    pNode->mTransformation = aiMatrix4x4( 1.0f, 0.0f, 0.0f, offset.x,
+                                          0.0f, 1.0f, 0.0f, offset.y,
+                                          0.0f, 0.0f, 1.0f, offset.z,
+                                          0.0f, 0.0f, 0.0f, 1.0f);
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 6 - 2
code/BVHLoader.h

@@ -4,7 +4,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -83,7 +84,10 @@ class BVHLoader : public BaseImporter
         std::vector<ChannelType> mChannels;
         std::vector<ChannelType> mChannels;
         std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames
         std::vector<float> mChannelValues; // motion data values for that node. Of size NumChannels * NumFrames
 
 
-        Node() { }
+        Node()
+        : mNode(nullptr)
+        { }
+
         explicit Node( const aiNode* pNode) : mNode( pNode) { }
         explicit Node( const aiNode* pNode) : mNode( pNode) { }
     };
     };
 
 

+ 52 - 41
code/BaseImporter.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -63,23 +64,24 @@ using namespace Assimp;
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 BaseImporter::BaseImporter()
 BaseImporter::BaseImporter()
-: m_progress()
-{
+: m_progress() {
     // nothing to do here
     // nothing to do here
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
 // Destructor, private as well
-BaseImporter::~BaseImporter()
-{
+BaseImporter::~BaseImporter() {
     // nothing to do here
     // nothing to do here
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Imports the given file and returns the imported data.
 // Imports the given file and returns the imported data.
-aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler)
-{
+aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile, IOSystem* pIOHandler) {
     m_progress = pImp->GetProgressHandler();
     m_progress = pImp->GetProgressHandler();
+    if (nullptr == m_progress) {
+        return nullptr;
+    }
+
     ai_assert(m_progress);
     ai_assert(m_progress);
 
 
     // Gather configuration properties for this run
     // Gather configuration properties for this run
@@ -99,8 +101,8 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile,
     } catch( const std::exception& err )    {
     } catch( const std::exception& err )    {
         // extract error description
         // extract error description
         m_ErrorText = err.what();
         m_ErrorText = err.what();
-        DefaultLogger::get()->error(m_ErrorText);
-        return NULL;
+        ASSIMP_LOG_ERROR(m_ErrorText);
+        return nullptr;
     }
     }
 
 
     // return what we gathered from the import.
     // return what we gathered from the import.
@@ -114,13 +116,12 @@ void BaseImporter::SetupProperties(const Importer* /*pImp*/)
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
-{
+void BaseImporter::GetExtensionList(std::set<std::string>& extensions) {
     const aiImporterDesc* desc = GetInfo();
     const aiImporterDesc* desc = GetInfo();
-    ai_assert(desc != NULL);
+    ai_assert(desc != nullptr);
 
 
     const char* ext = desc->mFileExtensions;
     const char* ext = desc->mFileExtensions;
-    ai_assert(ext != NULL);
+    ai_assert(ext != nullptr );
 
 
     const char* last = ext;
     const char* last = ext;
     do {
     do {
@@ -142,23 +143,22 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
     const char**        tokens,
     const char**        tokens,
     unsigned int        numTokens,
     unsigned int        numTokens,
     unsigned int        searchBytes /* = 200 */,
     unsigned int        searchBytes /* = 200 */,
-    bool                tokensSol /* false */)
+    bool                tokensSol /* false */,
+    bool                noAlphaBeforeTokens /* false */)
 {
 {
-    ai_assert( NULL != tokens );
+    ai_assert( nullptr != tokens );
     ai_assert( 0 != numTokens );
     ai_assert( 0 != numTokens );
     ai_assert( 0 != searchBytes);
     ai_assert( 0 != searchBytes);
 
 
-    if (!pIOHandler)
+    if ( nullptr == pIOHandler ) {
         return false;
         return false;
+    }
 
 
     std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
     std::unique_ptr<IOStream> pStream (pIOHandler->Open(pFile));
     if (pStream.get() ) {
     if (pStream.get() ) {
         // 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();
-        if( NULL == buffer ) {
-            return false;
-        }
 
 
         const size_t read = pStream->Read(buffer,1,searchBytes);
         const size_t read = pStream->Read(buffer,1,searchBytes);
         if( !read ) {
         if( !read ) {
@@ -180,16 +180,29 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
         }
         }
         *cur2 = '\0';
         *cur2 = '\0';
 
 
-        for (unsigned int i = 0; i < numTokens;++i) {
-            ai_assert(NULL != tokens[i]);
-            const char* r = strstr(buffer,tokens[i]);
+        std::string token;
+        for (unsigned int i = 0; i < numTokens; ++i ) {
+            ai_assert( nullptr != tokens[i] );
+            const size_t len( strlen( tokens[ i ] ) );
+            token.clear();
+            const char *ptr( tokens[ i ] );
+            for ( size_t tokIdx = 0; tokIdx < len; ++tokIdx ) {
+                token.push_back( tolower( *ptr ) );
+                ++ptr;
+            }
+            const char* r = strstr( buffer, token.c_str() );
             if( !r ) {
             if( !r ) {
                 continue;
                 continue;
             }
             }
+            // We need to make sure that we didn't accidentially identify the end of another token as our token,
+            // e.g. in a previous version the "gltf " present in some gltf files was detected as "f "
+            if (noAlphaBeforeTokens && (r != buffer && isalpha(r[-1]))) {
+                continue;
+            }
             // We got a match, either we don't care where it is, or it happens to
             // We got a match, either we don't care where it is, or it happens to
             // be in the beginning of the file / line
             // be in the beginning of the file / line
             if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
             if (!tokensSol || r == buffer || r[-1] == '\r' || r[-1] == '\n') {
-                DefaultLogger::get()->debug(std::string("Found positive match for header keyword: ") + tokens[i]);
+                ASSIMP_LOG_DEBUG_F( "Found positive match for header keyword: ", tokens[i] );
                 return true;
                 return true;
             }
             }
         }
         }
@@ -245,7 +258,8 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
 /* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
 /* static */ bool BaseImporter::CheckMagicToken(IOSystem* pIOHandler, const std::string& pFile,
     const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
     const void* _magic, unsigned int num, unsigned int offset, unsigned int size)
 {
 {
-    ai_assert(size <= 16 && _magic);
+    ai_assert( size <= 16 );
+    ai_assert( _magic );
 
 
     if (!pIOHandler) {
     if (!pIOHandler) {
         return false;
         return false;
@@ -315,7 +329,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 
 
     // UTF 8 with BOM
     // UTF 8 with BOM
     if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) {
     if((uint8_t)data[0] == 0xEF && (uint8_t)data[1] == 0xBB && (uint8_t)data[2] == 0xBF) {
-        DefaultLogger::get()->debug("Found UTF-8 BOM ...");
+        ASSIMP_LOG_DEBUG("Found UTF-8 BOM ...");
 
 
         std::copy(data.begin()+3,data.end(),data.begin());
         std::copy(data.begin()+3,data.end(),data.begin());
         data.resize(data.size()-3);
         data.resize(data.size()-3);
@@ -334,7 +348,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 
 
     // UTF 32 LE with BOM
     // UTF 32 LE with BOM
     if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
     if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
-        DefaultLogger::get()->debug("Found UTF-32 BOM ...");
+        ASSIMP_LOG_DEBUG("Found UTF-32 BOM ...");
 
 
         std::vector<char> output;
         std::vector<char> output;
         int *ptr = (int*)&data[ 0 ];
         int *ptr = (int*)&data[ 0 ];
@@ -354,7 +368,7 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 
 
     // UTF 16 LE with BOM
     // UTF 16 LE with BOM
     if(*((uint16_t*)&data.front()) == 0xFEFF) {
     if(*((uint16_t*)&data.front()) == 0xFEFF) {
-        DefaultLogger::get()->debug("Found UTF-16 BOM ...");
+        ASSIMP_LOG_DEBUG("Found UTF-16 BOM ...");
 
 
         std::vector<unsigned char> output;
         std::vector<unsigned char> output;
         utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
         utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
@@ -379,16 +393,14 @@ void BaseImporter::ConvertUTF8toISO8859_1(std::string& data)
                 data[j] = ((unsigned char) data[++i] + 0x40);
                 data[j] = ((unsigned char) data[++i] + 0x40);
             } else {
             } else {
                 std::stringstream stream;
                 std::stringstream stream;
-
                 stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1.";
                 stream << "UTF8 code " << std::hex << data[i] << data[i + 1] << " can not be converted into ISA-8859-1.";
-
-                DefaultLogger::get()->error(stream.str());
+                ASSIMP_LOG_ERROR( stream.str() );
 
 
                 data[j++] = data[i++];
                 data[j++] = data[i++];
                 data[j] = data[i];
                 data[j] = data[i];
             }
             }
         } else {
         } else {
-            DefaultLogger::get()->error("UTF8 code but only one character remaining");
+            ASSIMP_LOG_ERROR("UTF8 code but only one character remaining");
 
 
             data[j] = data[i];
             data[j] = data[i];
         }
         }
@@ -404,7 +416,7 @@ void BaseImporter::TextFileToBuffer(IOStream* stream,
     std::vector<char>& data,
     std::vector<char>& data,
     TextFileMode mode)
     TextFileMode mode)
 {
 {
-    ai_assert(NULL != stream);
+    ai_assert(nullptr != stream);
 
 
     const size_t fileSize = stream->FileSize();
     const size_t fileSize = stream->FileSize();
     if (mode == FORBID_EMPTY) {
     if (mode == FORBID_EMPTY) {
@@ -465,14 +477,14 @@ struct Assimp::BatchData {
     , pImporter( nullptr )
     , pImporter( nullptr )
     , next_id(0xffff)
     , next_id(0xffff)
     , validate( validate ) {
     , validate( validate ) {
-        ai_assert( NULL != pIO );
+        ai_assert( nullptr != pIO );
         
         
         pImporter = new Importer();
         pImporter = new Importer();
         pImporter->SetIOHandler( pIO );
         pImporter->SetIOHandler( pIO );
     }
     }
 
 
     ~BatchData() {
     ~BatchData() {
-        pImporter->SetIOHandler( NULL ); /* get pointer back into our possession */
+        pImporter->SetIOHandler( nullptr ); /* get pointer back into our possession */
         delete pImporter;
         delete pImporter;
     }
     }
 
 
@@ -498,9 +510,8 @@ struct Assimp::BatchData {
 typedef std::list<LoadRequest>::iterator LoadReqIt;
 typedef std::list<LoadRequest>::iterator LoadReqIt;
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-BatchLoader::BatchLoader(IOSystem* pIO, bool validate )
-{
-    ai_assert(NULL != pIO);
+BatchLoader::BatchLoader(IOSystem* pIO, bool validate ) {
+    ai_assert(nullptr != pIO);
 
 
     m_data = new BatchData( pIO, validate );
     m_data = new BatchData( pIO, validate );
 }
 }
@@ -566,7 +577,7 @@ aiScene* BatchLoader::GetImport( unsigned int which )
             return sc;
             return sc;
         }
         }
     }
     }
-    return NULL;
+    return nullptr;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -589,13 +600,13 @@ void BatchLoader::LoadAll()
 
 
         if (!DefaultLogger::isNullLogger())
         if (!DefaultLogger::isNullLogger())
         {
         {
-            DefaultLogger::get()->info("%%% BEGIN EXTERNAL FILE %%%");
-            DefaultLogger::get()->info("File: " + (*it).file);
+            ASSIMP_LOG_INFO("%%% BEGIN EXTERNAL FILE %%%");
+            ASSIMP_LOG_INFO_F("File: ", (*it).file);
         }
         }
         m_data->pImporter->ReadFile((*it).file,pp);
         m_data->pImporter->ReadFile((*it).file,pp);
         (*it).scene = m_data->pImporter->GetOrphanedScene();
         (*it).scene = m_data->pImporter->GetOrphanedScene();
         (*it).loaded = true;
         (*it).loaded = true;
 
 
-        DefaultLogger::get()->info("%%% END EXTERNAL FILE %%%");
+        ASSIMP_LOG_INFO("%%% END EXTERNAL FILE %%%");
     }
     }
 }
 }

+ 3 - 2
code/BaseProcess.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -84,7 +85,7 @@ void BaseProcess::ExecuteOnScene( Importer* pImp)
 
 
         // extract error description
         // extract error description
         pImp->Pimpl()->mErrorString = err.what();
         pImp->Pimpl()->mErrorString = err.what();
-        DefaultLogger::get()->error(pImp->Pimpl()->mErrorString);
+        ASSIMP_LOG_ERROR(pImp->Pimpl()->mErrorString);
 
 
         // and kill the partially imported data
         // and kill the partially imported data
         delete pImp->Pimpl()->mScene;
         delete pImp->Pimpl()->mScene;

+ 2 - 1
code/BaseProcess.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 4 - 2
code/Bitmap.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -84,7 +85,8 @@ namespace Assimp {
     }
     }
 
 
     template<typename T>
     template<typename T>
-    inline std::size_t Copy(uint8_t* data, T& field) {
+    inline 
+    std::size_t Copy(uint8_t* data, const T &field) {
 #ifdef AI_BUILD_BIG_ENDIAN
 #ifdef AI_BUILD_BIG_ENDIAN
         T field_swapped=AI_BE(field);
         T field_swapped=AI_BE(field);
         std::memcpy(data, &field_swapped, sizeof(field)); return sizeof(field);
         std::memcpy(data, &field_swapped, sizeof(field)); return sizeof(field);

+ 185 - 0
code/BlenderCustomData.cpp

@@ -0,0 +1,185 @@
+#include "BlenderCustomData.h"
+#include "BlenderDNA.h"
+#include <array>
+#include <functional>
+
+namespace Assimp {
+    namespace Blender {
+        /**
+        *   @brief  read/convert of Structure array to memory
+        */
+        template<typename T>
+        bool read(const Structure &s, T *p, const size_t cnt, const FileDatabase &db) {
+            for (size_t i = 0; i < cnt; ++i) {
+                T read;
+                s.Convert(read, db);
+                *p = read;
+                p++;
+            }
+            return true;
+        }
+
+        /**
+        *   @brief  pointer to function read memory for n CustomData types
+        */
+        typedef bool        (*PRead)(ElemBase *pOut, const size_t cnt, const FileDatabase &db);
+        typedef ElemBase *  (*PCreate)(const size_t cnt);
+        typedef void(*PDestroy)(ElemBase *);
+
+#define IMPL_STRUCT_READ(ty)                                                    \
+        bool read##ty(ElemBase *v, const size_t cnt, const FileDatabase &db) {  \
+            return read<ty>(db.dna[#ty], dynamic_cast<ty *>(v), cnt, db);       \
+        }
+
+#define IMPL_STRUCT_CREATE(ty)                                                  \
+        ElemBase *create##ty(const size_t cnt) {                                \
+            return new ty[cnt];                                                 \
+        }
+
+#define IMPL_STRUCT_DESTROY(ty)                                                 \
+        void destroy##ty(ElemBase *pE) {                                        \
+            ty *p = dynamic_cast<ty *>(pE);                                     \
+            delete[]p;                                                          \
+        }
+
+        /**
+        *   @brief  helper macro to define Structure functions
+        */
+#define IMPL_STRUCT(ty)                                                         \
+        IMPL_STRUCT_READ(ty)                                                    \
+        IMPL_STRUCT_CREATE(ty)                                                  \
+        IMPL_STRUCT_DESTROY(ty)
+
+        // supported structures for CustomData
+        IMPL_STRUCT(MVert)
+        IMPL_STRUCT(MEdge)
+        IMPL_STRUCT(MFace)
+        IMPL_STRUCT(MTFace)
+        IMPL_STRUCT(MTexPoly)
+        IMPL_STRUCT(MLoopUV)
+        IMPL_STRUCT(MLoopCol)
+        IMPL_STRUCT(MPoly)
+        IMPL_STRUCT(MLoop)
+
+        /**
+        *   @brief  describes the size of data and the read function to be used for single CustomerData.type
+        */
+        struct CustomDataTypeDescription {
+            PRead Read;                         ///< function to read one CustomData type element
+            PCreate Create;                       ///< function to allocate n type elements
+            PDestroy Destroy;
+
+            CustomDataTypeDescription(PRead read, PCreate create, PDestroy destroy)
+                : Read(read)
+                , Create(create)
+                , Destroy(destroy)
+            {}
+        };
+
+
+        /**
+        *   @brief  helper macro to define Structure type specific CustomDataTypeDescription
+        *   @note   IMPL_STRUCT_READ for same ty must be used earlier to implement the typespecific read function
+        */
+#define DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(ty)           \
+        CustomDataTypeDescription{&read##ty, &create##ty, &destroy##ty}
+
+        /**
+        *   @brief  helper macro to define CustomDataTypeDescription for UNSUPPORTED type
+        */
+#define DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION          \
+        CustomDataTypeDescription{nullptr, nullptr, nullptr}
+
+        /**
+        *   @brief  descriptors for data pointed to from CustomDataLayer.data
+        *   @note   some of the CustomData uses already well defined Structures
+        *           other (like CD_ORCO, ...) uses arrays of rawtypes or even arrays of Structures
+        *           use a special readfunction for that cases
+        */
+        std::array<CustomDataTypeDescription, CD_NUMTYPES> customDataTypeDescriptions = { {
+            DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MVert),
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MEdge),
+            DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MFace),
+            DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTFace),
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MTexPoly),
+            DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopUV),
+            DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoopCol),
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MPoly),
+            DECL_STRUCT_CUSTOMDATATYPEDESCRIPTION(MLoop),
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION,
+            DECL_UNSUPPORTED_CUSTOMDATATYPEDESCRIPTION
+        }};
+
+
+        bool isValidCustomDataType(const int cdtype) {
+            return cdtype >= 0 && cdtype < CD_NUMTYPES;
+        }
+
+        bool readCustomData(std::shared_ptr<ElemBase> &out, const int cdtype, const size_t cnt, const FileDatabase &db) {
+            if (!isValidCustomDataType(cdtype)) {
+                throw Error((Formatter::format(), "CustomData.type ", cdtype, " out of index"));
+            }
+
+            const CustomDataTypeDescription cdtd = customDataTypeDescriptions[cdtype];
+            if (cdtd.Read && cdtd.Create && cdtd.Destroy && cnt > 0) {
+                // allocate cnt elements and parse them from file
+                out.reset(cdtd.Create(cnt), cdtd.Destroy);
+                return cdtd.Read(out.get(), cnt, db);
+            }
+            return false;
+        }
+
+        std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, const CustomDataType cdtype, const std::string &name) {
+            for (auto it = customdata.layers.begin(); it != customdata.layers.end(); ++it) {
+                if (it->get()->type == cdtype && name == it->get()->name) {
+                    return *it;
+                }
+            }
+            return nullptr;
+        }
+
+        const ElemBase * getCustomDataLayerData(const CustomData &customdata, const CustomDataType cdtype, const std::string &name)
+        {
+            const std::shared_ptr<CustomDataLayer> pLayer = getCustomDataLayer(customdata, cdtype, name);
+            if (pLayer && pLayer->data) {
+                return pLayer->data.get();
+            }
+            return nullptr;
+        }
+    }
+}

+ 89 - 0
code/BlenderCustomData.h

@@ -0,0 +1,89 @@
+#pragma once
+
+#include "BlenderDNA.h"
+#include "BlenderScene.h"
+#include <memory>
+
+namespace Assimp {
+    namespace Blender {
+        /* CustomData.type from Blender (2.79b) */
+        enum CustomDataType {
+            CD_AUTO_FROM_NAME = -1,
+            CD_MVERT = 0,
+#ifdef DNA_DEPRECATED
+            CD_MSTICKY = 1,  /* DEPRECATED */
+#endif
+            CD_MDEFORMVERT = 2,
+            CD_MEDGE = 3,
+            CD_MFACE = 4,
+            CD_MTFACE = 5,
+            CD_MCOL = 6,
+            CD_ORIGINDEX = 7,
+            CD_NORMAL = 8,
+            /*	CD_POLYINDEX        = 9, */
+            CD_PROP_FLT = 10,
+            CD_PROP_INT = 11,
+            CD_PROP_STR = 12,
+            CD_ORIGSPACE = 13,  /* for modifier stack face location mapping */
+            CD_ORCO = 14,
+            CD_MTEXPOLY = 15,
+            CD_MLOOPUV = 16,
+            CD_MLOOPCOL = 17,
+            CD_TANGENT = 18,
+            CD_MDISPS = 19,
+            CD_PREVIEW_MCOL = 20,  /* for displaying weightpaint colors */
+            /*	CD_ID_MCOL          = 21, */
+            CD_TEXTURE_MLOOPCOL = 22,
+            CD_CLOTH_ORCO = 23,
+            CD_RECAST = 24,
+
+            /* BMESH ONLY START */
+            CD_MPOLY = 25,
+            CD_MLOOP = 26,
+            CD_SHAPE_KEYINDEX = 27,
+            CD_SHAPEKEY = 28,
+            CD_BWEIGHT = 29,
+            CD_CREASE = 30,
+            CD_ORIGSPACE_MLOOP = 31,
+            CD_PREVIEW_MLOOPCOL = 32,
+            CD_BM_ELEM_PYPTR = 33,
+            /* BMESH ONLY END */
+
+            CD_PAINT_MASK = 34,
+            CD_GRID_PAINT_MASK = 35,
+            CD_MVERT_SKIN = 36,
+            CD_FREESTYLE_EDGE = 37,
+            CD_FREESTYLE_FACE = 38,
+            CD_MLOOPTANGENT = 39,
+            CD_TESSLOOPNORMAL = 40,
+            CD_CUSTOMLOOPNORMAL = 41,
+
+            CD_NUMTYPES = 42
+        };
+
+        /**
+        *   @brief  check if given cdtype is valid (ie >= 0 and < CD_NUMTYPES)
+        *   @param[in]  cdtype to check
+        *   @return true when valid
+        */
+        bool isValidCustomDataType(const int cdtype);
+
+        /**
+        *   @brief  returns CustomDataLayer ptr for given cdtype and name
+        *   @param[in]  customdata CustomData to search for wanted layer
+        *   @param[in]  cdtype to search for
+        *   @param[in]  name to search for
+        *   @return CustomDataLayer * or nullptr if not found
+        */
+        std::shared_ptr<CustomDataLayer> getCustomDataLayer(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
+
+        /**
+        *   @brief  returns CustomDataLayer data ptr for given cdtype and name
+        *   @param[in]  customdata CustomData to search for wanted layer
+        *   @param[in]  cdtype to search for
+        *   @param[in]  name to search for
+        *   @return * to struct data or nullptr if not found
+        */
+        const ElemBase * getCustomDataLayerData(const CustomData &customdata, CustomDataType cdtype, const std::string &name);
+    }
+}

+ 12 - 13
code/BlenderDNA.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -57,12 +58,11 @@ using namespace Assimp::Formatter;
 
 
 static bool match4(StreamReaderAny& stream, const char* string) {
 static bool match4(StreamReaderAny& stream, const char* string) {
     ai_assert( nullptr != string );
     ai_assert( nullptr != string );
-    char tmp[] = {
-        (const char)(stream).GetI1(),
-        (const char)(stream).GetI1(),
-        (const char)(stream).GetI1(),
-        (const char)(stream).GetI1()
-    };
+    char tmp[4];
+    tmp[ 0 ] = ( stream ).GetI1();
+    tmp[ 1 ] = ( stream ).GetI1();
+    tmp[ 2 ] = ( stream ).GetI1();
+    tmp[ 3 ] = ( stream ).GetI1();
     return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
     return (tmp[0]==string[0] && tmp[1]==string[1] && tmp[2]==string[2] && tmp[3]==string[3]);
 }
 }
 
 
@@ -210,8 +210,7 @@ void DNAParser::Parse ()
         s.size = offset;
         s.size = offset;
     }
     }
 
 
-    DefaultLogger::get()->debug((format(),"BlenderDNA: Got ",dna.structures.size(),
-        " structures with totally ",fields," fields"));
+    ASSIMP_LOG_DEBUG_F( "BlenderDNA: Got ", dna.structures.size()," structures with totally ",fields," fields");
 
 
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
     dna.DumpToFile();
     dna.DumpToFile();
@@ -228,12 +227,12 @@ void DNAParser::Parse ()
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void DNA :: DumpToFile()
 void DNA :: DumpToFile()
 {
 {
-    // we dont't bother using the VFS here for this is only for debugging.
+    // we don't bother using the VFS here for this is only for debugging.
     // (and all your bases are belong to us).
     // (and all your bases are belong to us).
 
 
     std::ofstream f("dna.txt");
     std::ofstream f("dna.txt");
     if (f.fail()) {
     if (f.fail()) {
-        DefaultLogger::get()->error("Could not dump dna to dna.txt");
+        ASSIMP_LOG_ERROR("Could not dump dna to dna.txt");
         return;
         return;
     }
     }
     f << "Field format: type name offset size" << "\n";
     f << "Field format: type name offset size" << "\n";
@@ -248,7 +247,7 @@ void DNA :: DumpToFile()
     }
     }
     f << std::flush;
     f << std::flush;
 
 
-    DefaultLogger::get()->info("BlenderDNA: Dumped dna to dna.txt");
+    ASSIMP_LOG_INFO("BlenderDNA: Dumped dna to dna.txt");
 }
 }
 #endif
 #endif
 
 
@@ -367,7 +366,7 @@ void SectionParser :: Next()
     }
     }
 
 
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
 #ifdef ASSIMP_BUILD_BLENDER_DEBUG
-    DefaultLogger::get()->debug(current.id);
+    ASSIMP_LOG_DEBUG(current.id);
 #endif
 #endif
 }
 }
 
 

+ 38 - 4
code/BlenderDNA.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -204,7 +205,7 @@ enum ErrorPolicy {
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 /** Represents a data structure in a BLEND file. A Structure defines n fields
 /** Represents a data structure in a BLEND file. A Structure defines n fields
- *  and their locatios and encodings the input stream. Usually, every
+ *  and their locations and encodings the input stream. Usually, every
  *  Structure instance pertains to one equally-named data structure in the
  *  Structure instance pertains to one equally-named data structure in the
  *  BlenderScene.h header. This class defines various utilities to map a
  *  BlenderScene.h header. This class defines various utilities to map a
  *  binary `blob` read from the file to such a structure instance with
  *  binary `blob` read from the file to such a structure instance with
@@ -308,6 +309,28 @@ public:
     void ReadField(T& out, const char* name,
     void ReadField(T& out, const char* name,
         const FileDatabase& db) const;
         const FileDatabase& db) const;
 
 
+    // --------------------------------------------------------
+    /**
+    *   @brief  field parsing for dynamic vectors
+    *   @param[in]  out vector of struct to be filled
+    *   @param[in]  name of field
+    *   @param[in]  db to access the file, dna, ...
+    *   @return true when read was successful
+    */
+    template <int error_policy, template <typename> class TOUT, typename T>
+    bool ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const;
+
+    /**
+    *   @brief  parses raw customdata
+    *   @param[in]  out shared_ptr to be filled
+    *   @param[in]  cdtype customdata type to read
+    *   @param[in]  name of field ptr
+    *   @param[in]  db to access the file, dna, ...
+    *   @return true when read was successful
+    */
+    template <int error_policy>
+    bool ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const;
+
 private:
 private:
 
 
     // --------------------------------------------------------
     // --------------------------------------------------------
@@ -380,7 +403,7 @@ template <>  struct Structure :: _defaultInitializer<ErrorPolicy_Warn> {
 
 
     template <typename T>
     template <typename T>
     void operator ()(T& out, const char* reason = "<add reason>") {
     void operator ()(T& out, const char* reason = "<add reason>") {
-        DefaultLogger::get()->warn(reason);
+        ASSIMP_LOG_WARN(reason);
 
 
         // ... and let the show go on
         // ... and let the show go on
         _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out);
         _defaultInitializer<0 /*ErrorPolicy_Igno*/>()(out);
@@ -662,7 +685,7 @@ public:
     /** Check whether a specific item is in the cache.
     /** Check whether a specific item is in the cache.
      *  @param s Data type of the item
      *  @param s Data type of the item
      *  @param out Output pointer. Unchanged if the
      *  @param out Output pointer. Unchanged if the
-     *   cache doens't know the item yet.
+     *   cache doesn't know the item yet.
      *  @param ptr Item address to look for. */
      *  @param ptr Item address to look for. */
     template <typename T> void get (
     template <typename T> void get (
         const Structure& s,
         const Structure& s,
@@ -802,6 +825,17 @@ private:
     FileDatabase& db;
     FileDatabase& db;
 };
 };
 
 
+/**
+*   @brief  read CustomData's data to ptr to mem
+*   @param[out] out memory ptr to set
+*   @param[in]  cdtype  to read
+*   @param[in]  cnt cnt of elements to read
+*   @param[in]  db to read elements from
+*   @return true when ok
+*/
+bool readCustomData(std::shared_ptr<ElemBase> &out, int cdtype, size_t cnt, const FileDatabase &db);
+
+
     } // end Blend
     } // end Blend
 } // end Assimp
 } // end Assimp
 
 

+ 106 - 5
code/BlenderDNA.inl

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -306,6 +307,108 @@ void Structure :: ReadField(T& out, const char* name, const FileDatabase& db) co
 }
 }
 
 
 
 
+//--------------------------------------------------------------------------------
+// field parsing for raw untyped data (like CustomDataLayer.data)
+template <int error_policy>
+bool Structure::ReadCustomDataPtr(std::shared_ptr<ElemBase>&out, int cdtype, const char* name, const FileDatabase& db) const {
+
+	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+
+	Pointer ptrval;
+	const Field* f;
+	try	{
+		f = &(*this)[name];
+
+		// sanity check, should never happen if the genblenddna script is right
+		if (!(f->flags & FieldFlag_Pointer)) {
+			throw Error((Formatter::format(), "Field `", name, "` of structure `",
+				this->name, "` ought to be a pointer"));
+		}
+
+		db.reader->IncPtr(f->offset);
+		Convert(ptrval, db);
+		// actually it is meaningless on which Structure the Convert is called
+		// because the `Pointer` argument triggers a special implementation.
+	}
+	catch (const Error& e) {
+		_defaultInitializer<error_policy>()(out, e.what());
+		out.reset();
+	}
+
+	bool readOk = true;
+	if (ptrval.val)	{
+		// get block for ptr
+		const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
+		db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
+		// read block->num instances of given type to out
+		readOk = readCustomData(out, cdtype, block->num, db);
+	}
+
+	// and recover the previous stream position
+	db.reader->SetCurrentPos(old);
+
+#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
+	++db.stats().fields_read;
+#endif
+
+	return readOk;
+}
+
+//--------------------------------------------------------------------------------
+template <int error_policy, template <typename> class TOUT, typename T>
+bool Structure::ReadFieldPtrVector(vector<TOUT<T>>&out, const char* name, const FileDatabase& db) const {
+	out.clear();
+
+	const StreamReaderAny::pos old = db.reader->GetCurrentPos();
+
+	Pointer ptrval;
+	const Field* f;
+	try	{
+		f = &(*this)[name];
+
+		// sanity check, should never happen if the genblenddna script is right
+		if (!(f->flags & FieldFlag_Pointer)) {
+			throw Error((Formatter::format(), "Field `", name, "` of structure `",
+				this->name, "` ought to be a pointer"));
+		}
+
+		db.reader->IncPtr(f->offset);
+		Convert(ptrval, db);
+		// actually it is meaningless on which Structure the Convert is called
+		// because the `Pointer` argument triggers a special implementation.
+	}
+	catch (const Error& e) {
+		_defaultInitializer<error_policy>()(out, e.what());
+		out.clear();
+		return false;
+	}
+
+
+	if (ptrval.val)	{
+		// find the file block the pointer is pointing to
+		const FileBlockHead* block = LocateFileBlockForAddress(ptrval, db);
+		db.reader->SetCurrentPos(block->start + static_cast<size_t>((ptrval.val - block->address.val)));
+		// FIXME: basically, this could cause problems with 64 bit pointers on 32 bit systems.
+		// I really ought to improve StreamReader to work with 64 bit indices exclusively.
+
+		const Structure& s = db.dna[f->type];
+		for (size_t i = 0; i < block->num; ++i)	{
+			TOUT<T> p(new T);
+			s.Convert(*p, db);
+			out.push_back(p);
+		}
+	}
+
+	db.reader->SetCurrentPos(old);
+
+#ifndef ASSIMP_BUILD_BLENDER_NO_STATS
+	++db.stats().fields_read;
+#endif
+
+	return false;
+}
+
+
 //--------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------
 template <template <typename> class TOUT, typename T>
 template <template <typename> class TOUT, typename T>
 bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,
 bool Structure :: ResolvePointer(TOUT<T>& out, const Pointer & ptrval, const FileDatabase& db,
@@ -467,9 +570,7 @@ template <> bool Structure :: ResolvePointer<std::shared_ptr,ElemBase>(std::shar
         // this might happen if DNA::RegisterConverters hasn't been called so far
         // this might happen if DNA::RegisterConverters hasn't been called so far
         // or if the target type is not contained in `our` DNA.
         // or if the target type is not contained in `our` DNA.
         out.reset();
         out.reset();
-        DefaultLogger::get()->warn((Formatter::format(),
-            "Failed to find a converter for the `",s.name,"` structure"
-            ));
+        ASSIMP_LOG_WARN_F( "Failed to find a converter for the `",s.name,"` structure" );
         return false;
         return false;
     }
     }
 
 
@@ -501,7 +602,7 @@ const FileBlockHead* Structure :: LocateFileBlockForAddress(const Pointer & ptrv
 {
 {
     // the file blocks appear in list sorted by
     // the file blocks appear in list sorted by
     // with ascending base addresses so we can run a
     // with ascending base addresses so we can run a
-    // binary search to locate the pointee quickly.
+    // binary search to locate the pointer quickly.
 
 
     // NOTE: Blender seems to distinguish between side-by-side
     // NOTE: Blender seems to distinguish between side-by-side
     // data (stored in the same data block) and far pointers,
     // data (stored in the same data block) and far pointers,

+ 8 - 3
code/BlenderIntermediate.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -121,9 +122,11 @@ namespace Blender {
 #   pragma warning(disable:4351)
 #   pragma warning(disable:4351)
 #endif
 #endif
 
 
+    // As counter-intuitive as it may seem, a comparator must return false for equal values.
+    // The C++ standard defines and expects this behavior: true if lhs < rhs, false otherwise.
     struct ObjectCompare {
     struct ObjectCompare {
         bool operator() (const Object* left, const Object* right) const {
         bool operator() (const Object* left, const Object* right) const {
-            return ::strncmp(left->id.name, right->id.name, strlen( left->id.name ) ) == 0;
+            return ::strncmp(left->id.name, right->id.name, strlen( left->id.name ) ) < 0;
         }
         }
     };
     };
 
 
@@ -142,9 +145,11 @@ namespace Blender {
             , db(db)
             , db(db)
         {}
         {}
 
 
+        // As counter-intuitive as it may seem, a comparator must return false for equal values.
+        // The C++ standard defines and expects this behavior: true if lhs < rhs, false otherwise.
         struct ObjectCompare {
         struct ObjectCompare {
             bool operator() (const Object* left, const Object* right) const {
             bool operator() (const Object* left, const Object* right) const {
-                return ::strncmp( left->id.name, right->id.name, strlen( left->id.name ) ) == 0;
+                return ::strncmp( left->id.name, right->id.name, strlen( left->id.name ) ) < 0;
             }
             }
         };
         };
 
 

+ 76 - 24
code/BlenderLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -53,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BlenderIntermediate.h"
 #include "BlenderIntermediate.h"
 #include "BlenderModifier.h"
 #include "BlenderModifier.h"
 #include "BlenderBMesh.h"
 #include "BlenderBMesh.h"
+#include "BlenderCustomData.h"
 #include <assimp/StringUtils.h>
 #include <assimp/StringUtils.h>
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include <assimp/importerdesc.h>
 #include <assimp/importerdesc.h>
@@ -153,14 +155,6 @@ void BlenderImporter::SetupProperties(const Importer* /*pImp*/)
     // nothing to be done for the moment
     // nothing to be done for the moment
 }
 }
 
 
-struct free_it {
-    free_it(void* free) : free(free) {}
-    ~free_it() {
-        ::free(this->free);
-    }
-
-    void* free;
-};
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Imports the given file into the given scene structure.
 // Imports the given file into the given scene structure.
@@ -168,8 +162,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
     aiScene* pScene, IOSystem* pIOHandler)
     aiScene* pScene, IOSystem* pIOHandler)
 {
 {
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
 #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
-    Bytef* dest = NULL;
-    free_it free_it_really(dest);
+    std::vector<Bytef> uncompressed;
 #endif
 #endif
 
 
 
 
@@ -217,6 +210,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
 
 
         size_t total = 0l;
         size_t total = 0l;
 
 
+        // TODO: be smarter about this, decompress directly into heap buffer
         // and decompress the data .... do 1k chunks in the hope that we won't kill the stack
         // and decompress the data .... do 1k chunks in the hope that we won't kill the stack
 #define MYBLOCK 1024
 #define MYBLOCK 1024
         Bytef block[MYBLOCK];
         Bytef block[MYBLOCK];
@@ -231,8 +225,8 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
             }
             }
             const size_t have = MYBLOCK - zstream.avail_out;
             const size_t have = MYBLOCK - zstream.avail_out;
             total += have;
             total += have;
-            dest = reinterpret_cast<Bytef*>( realloc(dest,total) );
-            memcpy(dest + total - have,block,have);
+            uncompressed.resize(total);
+            memcpy(uncompressed.data() + total - have,block,have);
         }
         }
         while (ret != Z_STREAM_END);
         while (ret != Z_STREAM_END);
 
 
@@ -240,7 +234,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
         inflateEnd(&zstream);
         inflateEnd(&zstream);
 
 
         // replace the input stream with a memory stream
         // replace the input stream with a memory stream
-        stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(dest),total));
+        stream.reset(new MemoryIOStream(reinterpret_cast<uint8_t*>(uncompressed.data()),total));
 
 
         // .. and retry
         // .. and retry
         stream->Read(magic,7,1);
         stream->Read(magic,7,1);
@@ -334,12 +328,12 @@ void BlenderImporter::ExtractScene(Scene& out, const FileDatabase& file)
     ss.Convert(out,file);
     ss.Convert(out,file);
 
 
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
 #ifndef ASSIMP_BUILD_BLENDER_NO_STATS
-    DefaultLogger::get()->info((format(),
+    ASSIMP_LOG_INFO_F(
         "(Stats) Fields read: " ,file.stats().fields_read,
         "(Stats) Fields read: " ,file.stats().fields_read,
         ", pointers resolved: " ,file.stats().pointers_resolved,
         ", pointers resolved: " ,file.stats().pointers_resolved,
         ", cache hits: "        ,file.stats().cache_hits,
         ", cache hits: "        ,file.stats().cache_hits,
         ", cached objects: "    ,file.stats().cached_objects
         ", cached objects: "    ,file.stats().cached_objects
-    ));
+    );
 #endif
 #endif
 }
 }
 
 
@@ -1028,6 +1022,34 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
         }
         }
     }
     }
 
 
+    // TODO should we create the TextureUVMapping map in Convert<Material> to prevent redundant processing?
+
+    // create texture <-> uvname mapping for all materials
+    // key is texture number, value is data *
+    typedef std::map<uint32_t, const MLoopUV *> TextureUVMapping;
+    // key is material number, value is the TextureUVMapping for the material
+    typedef std::map<uint32_t, TextureUVMapping> MaterialTextureUVMappings;
+    MaterialTextureUVMappings matTexUvMappings;
+    const uint32_t maxMat = static_cast<const uint32_t>(mesh->mat.size());
+    for (uint32_t m = 0; m < maxMat; ++m) {
+        // get material by index
+        const std::shared_ptr<Material> pMat = mesh->mat[m];
+        TextureUVMapping texuv;
+        const uint32_t maxTex = sizeof(pMat->mtex) / sizeof(pMat->mtex[0]);
+        for (uint32_t t = 0; t < maxTex; ++t) {
+            if (pMat->mtex[t] && pMat->mtex[t]->uvname[0]) {
+                // get the CustomData layer for given uvname and correct type
+                const ElemBase *pLoop = getCustomDataLayerData(mesh->ldata, CD_MLOOPUV, pMat->mtex[t]->uvname);
+                if (pLoop) {
+                    texuv.insert(std::make_pair(t, dynamic_cast<const MLoopUV *>(pLoop)));
+                }
+            }
+        }
+        if (texuv.size()) {
+            matTexUvMappings.insert(std::make_pair(m, texuv));
+        }
+    }
+
     // collect texture coordinates, they're stored in a separate per-face buffer
     // collect texture coordinates, they're stored in a separate per-face buffer
     if (mesh->mtface || mesh->mloopuv) {
     if (mesh->mtface || mesh->mloopuv) {
         if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
         if (mesh->totface > static_cast<int> ( mesh->mtface.size())) {
@@ -1035,8 +1057,17 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
         }
         }
         for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
         for (std::vector<aiMesh*>::iterator it = temp->begin()+old; it != temp->end(); ++it) {
             ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
             ai_assert((*it)->mNumVertices && (*it)->mNumFaces);
-
-            (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
+            const auto itMatTexUvMapping = matTexUvMappings.find((*it)->mMaterialIndex);
+            if (itMatTexUvMapping == matTexUvMappings.end()) {
+                // default behaviour like before
+                (*it)->mTextureCoords[0] = new aiVector3D[(*it)->mNumVertices];
+            }
+            else {
+                // create texture coords for every mapped tex
+                for (uint32_t i = 0; i < itMatTexUvMapping->second.size(); ++i) {
+                    (*it)->mTextureCoords[i] = new aiVector3D[(*it)->mNumVertices];
+                }
+            }
             (*it)->mNumFaces = (*it)->mNumVertices = 0;
             (*it)->mNumFaces = (*it)->mNumVertices = 0;
         }
         }
 
 
@@ -1058,13 +1089,34 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
             aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
             aiMesh* const out = temp[ mat_num_to_mesh_idx[ v.mat_nr ] ];
             const aiFace& f = out->mFaces[out->mNumFaces++];
             const aiFace& f = out->mFaces[out->mNumFaces++];
 
 
-            aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
-            for (unsigned int j = 0; j < f.mNumIndices; ++j,++vo,++out->mNumVertices) {
-                const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
-                vo->x = uv.uv[0];
-                vo->y = uv.uv[1];
+            const auto itMatTexUvMapping = matTexUvMappings.find(v.mat_nr);
+            if (itMatTexUvMapping == matTexUvMappings.end()) {
+                // old behavior
+                aiVector3D* vo = &out->mTextureCoords[0][out->mNumVertices];
+                for (unsigned int j = 0; j < f.mNumIndices; ++j, ++vo, ++out->mNumVertices) {
+                    const MLoopUV& uv = mesh->mloopuv[v.loopstart + j];
+                    vo->x = uv.uv[0];
+                    vo->y = uv.uv[1];
+                }
+            }
+            else {
+                // create textureCoords for every mapped tex
+                for (uint32_t m = 0; m < itMatTexUvMapping->second.size(); ++m) {
+                    const MLoopUV *tm = itMatTexUvMapping->second[m];
+                    aiVector3D* vo = &out->mTextureCoords[m][out->mNumVertices];
+                    uint32_t j = 0;
+                    for (; j < f.mNumIndices; ++j, ++vo) {
+                        const MLoopUV& uv = tm[v.loopstart + j];
+                        vo->x = uv.uv[0];
+                        vo->y = uv.uv[1];
+                    }
+                    // only update written mNumVertices in last loop
+                    // TODO why must the numVertices be incremented here?
+                    if (m == itMatTexUvMapping->second.size() - 1) {
+                        out->mNumVertices += j;
+                    }
+                }
             }
             }
-
         }
         }
     }
     }
 
 

+ 2 - 1
code/BlenderLoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 2 - 29
code/BlenderModifier.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -69,34 +70,6 @@ static const fpCreateModifier creators[] = {
         NULL // sentinel
         NULL // sentinel
 };
 };
 
 
-// ------------------------------------------------------------------------------------------------
-// just testing out some new macros to simplify logging
-#define ASSIMP_LOG_WARN_F(string,...)\
-    DefaultLogger::get()->warn((Formatter::format(string),__VA_ARGS__))
-
-#define ASSIMP_LOG_ERROR_F(string,...)\
-    DefaultLogger::get()->error((Formatter::format(string),__VA_ARGS__))
-
-#define ASSIMP_LOG_DEBUG_F(string,...)\
-    DefaultLogger::get()->debug((Formatter::format(string),__VA_ARGS__))
-
-#define ASSIMP_LOG_INFO_F(string,...)\
-    DefaultLogger::get()->info((Formatter::format(string),__VA_ARGS__))
-
-
-#define ASSIMP_LOG_WARN(string)\
-    DefaultLogger::get()->warn(string)
-
-#define ASSIMP_LOG_ERROR(string)\
-    DefaultLogger::get()->error(string)
-
-#define ASSIMP_LOG_DEBUG(string)\
-    DefaultLogger::get()->debug(string)
-
-#define ASSIMP_LOG_INFO(string)\
-    DefaultLogger::get()->info(string)
-
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 struct SharedModifierData : ElemBase
 struct SharedModifierData : ElemBase
 {
 {

+ 30 - 32
code/BlenderModifier.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -46,53 +47,57 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_BLEND_MODIFIER_H
 #define INCLUDED_AI_BLEND_MODIFIER_H
 
 
 #include "BlenderIntermediate.h"
 #include "BlenderIntermediate.h"
-#include <assimp/TinyFormatter.h>
 
 
 namespace Assimp {
 namespace Assimp {
 namespace Blender {
 namespace Blender {
 
 
 // -------------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------------
-/** Dummy base class for all blender modifiers. Modifiers are reused between imports, so
- *  they should be stateless and not try to cache model data. */
+/** 
+ *  Dummy base class for all blender modifiers. Modifiers are reused between imports, so
+ *  they should be stateless and not try to cache model data. 
+ */
 // -------------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------------
-class BlenderModifier
-{
+class BlenderModifier {
 public:
 public:
+    /**
+     *  The class destructor, virtual.
+     */
     virtual ~BlenderModifier() {
     virtual ~BlenderModifier() {
         // empty
         // empty
     }
     }
 
 
-public:
-
     // --------------------
     // --------------------
-    /** Check if *this* modifier is active, given a ModifierData& block.*/
+    /** 
+     *  Check if *this* modifier is active, given a ModifierData& block.
+     */
     virtual bool IsActive( const ModifierData& /*modin*/) {
     virtual bool IsActive( const ModifierData& /*modin*/) {
         return false;
         return false;
     }
     }
 
 
     // --------------------
     // --------------------
-    /** Apply the modifier to a given output node. The original data used
+    /** 
+     *  Apply the modifier to a given output node. The original data used
      *  to construct the node is given as well. Not called unless IsActive()
      *  to construct the node is given as well. Not called unless IsActive()
-     *  was called and gave positive response. */
+     *  was called and gave positive response. 
+     */
     virtual void DoIt(aiNode& /*out*/,
     virtual void DoIt(aiNode& /*out*/,
         ConversionData& /*conv_data*/,
         ConversionData& /*conv_data*/,
         const ElemBase& orig_modifier,
         const ElemBase& orig_modifier,
         const Scene& /*in*/,
         const Scene& /*in*/,
         const Object& /*orig_object*/
         const Object& /*orig_object*/
     ) {
     ) {
-        DefaultLogger::get()->warn((Formatter::format("This modifier is not supported, skipping: "),orig_modifier.dna_type));
+        ASSIMP_LOG_INFO_F("This modifier is not supported, skipping: ",orig_modifier.dna_type );
         return;
         return;
     }
     }
 };
 };
 
 
-
 // -------------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------------
-/** Manage all known modifiers and instance and apply them if necessary */
+/** 
+ *  Manage all known modifiers and instance and apply them if necessary 
+ */
 // -------------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------------
-class BlenderModifierShowcase
-{
+class BlenderModifierShowcase {
 public:
 public:
-
     // --------------------
     // --------------------
     /** Apply all requested modifiers provided we support them. */
     /** Apply all requested modifiers provided we support them. */
     void ApplyModifiers(aiNode& out,
     void ApplyModifiers(aiNode& out,
@@ -102,25 +107,18 @@ public:
     );
     );
 
 
 private:
 private:
-
     TempArray< std::vector,BlenderModifier > cached_modifiers;
     TempArray< std::vector,BlenderModifier > cached_modifiers;
 };
 };
 
 
-
-
-
-
-// MODIFIERS
-
-
+// MODIFIERS /////////////////////////////////////////////////////////////////////////////////
 
 
 // -------------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------------
-/** Mirror modifier. Status: implemented. */
+/** 
+ *  Mirror modifier. Status: implemented. 
+ */
 // -------------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------------
-class BlenderModifier_Mirror : public BlenderModifier
-{
+class BlenderModifier_Mirror : public BlenderModifier {
 public:
 public:
-
     // --------------------
     // --------------------
     virtual bool IsActive( const ModifierData& modin);
     virtual bool IsActive( const ModifierData& modin);
 
 
@@ -136,8 +134,7 @@ public:
 // -------------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------------
 /** Subdivision modifier. Status: dummy. */
 /** Subdivision modifier. Status: dummy. */
 // -------------------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------------------
-class BlenderModifier_Subdivision : public BlenderModifier
-{
+class BlenderModifier_Subdivision : public BlenderModifier {
 public:
 public:
 
 
     // --------------------
     // --------------------
@@ -152,6 +149,7 @@ public:
     ) ;
     ) ;
 };
 };
 
 
+}
+}
 
 
-}}
 #endif // !INCLUDED_AI_BLEND_MODIFIER_H
 #endif // !INCLUDED_AI_BLEND_MODIFIER_H

+ 45 - 1
code/BlenderScene.cpp

@@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BlenderScene.h"
 #include "BlenderScene.h"
 #include "BlenderSceneGen.h"
 #include "BlenderSceneGen.h"
 #include "BlenderDNA.h"
 #include "BlenderDNA.h"
+#include "BlenderCustomData.h"
 
 
 using namespace Assimp;
 using namespace Assimp;
 using namespace Assimp::Blender;
 using namespace Assimp::Blender;
@@ -116,7 +117,7 @@ template <> void Structure :: Convert<MTex> (
     ReadField<ErrorPolicy_Igno>(temp,"projy",db);
     ReadField<ErrorPolicy_Igno>(temp,"projy",db);
     dest.projy = static_cast<Assimp::Blender::MTex::Projection>(temp);
     dest.projy = static_cast<Assimp::Blender::MTex::Projection>(temp);
     ReadField<ErrorPolicy_Igno>(temp,"projz",db);
     ReadField<ErrorPolicy_Igno>(temp,"projz",db);
-    dest.projx = static_cast<Assimp::Blender::MTex::Projection>(temp);
+    dest.projz = static_cast<Assimp::Blender::MTex::Projection>(temp);
     ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db);
     ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db);
     ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db);
     ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db);
     ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db);
     ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db);
@@ -481,6 +482,12 @@ template <> void Structure :: Convert<Mesh> (
     ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
     ReadFieldPtr<ErrorPolicy_Igno>(dest.mcol,"*mcol",db);
     ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
     ReadFieldPtr<ErrorPolicy_Fail>(dest.mat,"**mat",db);
 
 
+    ReadField<ErrorPolicy_Igno>(dest.vdata, "vdata", db);
+    ReadField<ErrorPolicy_Igno>(dest.edata, "edata", db);
+    ReadField<ErrorPolicy_Igno>(dest.fdata, "fdata", db);
+    ReadField<ErrorPolicy_Igno>(dest.pdata, "pdata", db);
+    ReadField<ErrorPolicy_Warn>(dest.ldata, "ldata", db);
+
     db.reader->IncPtr(size);
     db.reader->IncPtr(size);
 }
 }
 
 
@@ -786,6 +793,41 @@ template <> void Structure :: Convert<Image> (
     db.reader->IncPtr(size);
     db.reader->IncPtr(size);
 }
 }
 
 
+//--------------------------------------------------------------------------------
+template <> void Structure::Convert<CustomData>(
+    CustomData& dest,
+    const FileDatabase& db
+    ) const
+{
+    ReadFieldArray<ErrorPolicy_Warn>(dest.typemap, "typemap", db);
+    ReadField<ErrorPolicy_Warn>(dest.totlayer, "totlayer", db);
+    ReadField<ErrorPolicy_Warn>(dest.maxlayer, "maxlayer", db);
+    ReadField<ErrorPolicy_Warn>(dest.totsize, "totsize", db);
+    ReadFieldPtrVector<ErrorPolicy_Warn>(dest.layers, "*layers", db);
+
+    db.reader->IncPtr(size);
+}
+
+//--------------------------------------------------------------------------------
+template <> void Structure::Convert<CustomDataLayer>(
+    CustomDataLayer& dest,
+    const FileDatabase& db
+    ) const
+{
+    ReadField<ErrorPolicy_Fail>(dest.type, "type", db);
+    ReadField<ErrorPolicy_Fail>(dest.offset, "offset", db);
+    ReadField<ErrorPolicy_Fail>(dest.flag, "flag", db);
+    ReadField<ErrorPolicy_Fail>(dest.active, "active", db);
+    ReadField<ErrorPolicy_Fail>(dest.active_rnd, "active_rnd", db);
+    ReadField<ErrorPolicy_Fail>(dest.active_clone, "active_clone", db);
+    ReadField<ErrorPolicy_Fail>(dest.active_mask, "active_mask", db);
+    ReadField<ErrorPolicy_Fail>(dest.uid, "uid", db);
+    ReadFieldArray<ErrorPolicy_Warn>(dest.name, "name", db);
+    ReadCustomDataPtr<ErrorPolicy_Fail>(dest.data, dest.type, "*data", db);
+
+    db.reader->IncPtr(size);
+}
+
 //--------------------------------------------------------------------------------
 //--------------------------------------------------------------------------------
 void DNA::RegisterConverters() {
 void DNA::RegisterConverters() {
 
 
@@ -822,6 +864,8 @@ void DNA::RegisterConverters() {
     converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> );
     converters["Camera"] = DNA::FactoryPair( &Structure::Allocate<Camera>, &Structure::Convert<Camera> );
     converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> );
     converters["MirrorModifierData"] = DNA::FactoryPair( &Structure::Allocate<MirrorModifierData>, &Structure::Convert<MirrorModifierData> );
     converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
     converters["Image"] = DNA::FactoryPair( &Structure::Allocate<Image>, &Structure::Convert<Image> );
+    converters["CustomData"] = DNA::FactoryPair(&Structure::Allocate<CustomData>, &Structure::Convert<CustomData>);
+    converters["CustomDataLayer"] = DNA::FactoryPair(&Structure::Allocate<CustomDataLayer>, &Structure::Convert<CustomDataLayer>);
 }
 }
 
 
 #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER
 #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

+ 81 - 2
code/BlenderScene.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -156,10 +157,16 @@ struct World : ElemBase {
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 struct MVert : ElemBase {
 struct MVert : ElemBase {
     float co[3] FAIL;
     float co[3] FAIL;
-    float no[3] FAIL;
+    float no[3] FAIL;       // readed as short and divided through / 32767.f
     char flag;
     char flag;
     int mat_nr WARN;
     int mat_nr WARN;
     int bweight;
     int bweight;
+
+    MVert() : ElemBase()
+        , flag(0)
+        , mat_nr(0)
+        , bweight(0)
+    {}
 };
 };
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
@@ -368,6 +375,72 @@ struct Material : ElemBase {
     std::shared_ptr<MTex> mtex[18];
     std::shared_ptr<MTex> mtex[18];
 };
 };
 
 
+/*
+CustomDataLayer 104
+
+    int type 0 4
+    int offset 4 4
+    int flag 8 4
+    int active 12 4
+    int active_rnd 16 4
+    int active_clone 20 4
+    int active_mask 24 4
+    int uid 28 4
+    char name 32 64
+    void *data 96 8
+*/
+struct CustomDataLayer : ElemBase {
+    int type;
+    int offset;
+    int flag;
+    int active;
+    int active_rnd;
+    int active_clone;
+    int active_mask;
+    int uid;
+    char name[64];
+    std::shared_ptr<ElemBase> data;     // must be converted to real type according type member
+
+    CustomDataLayer()
+        : ElemBase()
+        , type(0)
+        , offset(0)
+        , flag(0)
+        , active(0)
+        , active_rnd(0)
+        , active_clone(0)
+        , active_mask(0)
+        , uid(0)
+        , data(nullptr)
+    {
+        memset(name, 0, sizeof name);
+    }
+};
+
+/*
+CustomData 208
+
+    CustomDataLayer *layers 0 8
+    int typemap 8 168
+    int pad_i1 176 4
+    int totlayer 180 4
+    int maxlayer 184 4
+    int totsize 188 4
+    BLI_mempool *pool 192 8
+    CustomDataExternal *external 200 8
+*/
+struct CustomData : ElemBase {
+    vector<std::shared_ptr<struct CustomDataLayer> > layers;
+    int typemap[42];    // CD_NUMTYPES
+    int totlayer;
+    int maxlayer;
+    int totsize;
+    /*
+    std::shared_ptr<BLI_mempool> pool;
+    std::shared_ptr<CustomDataExternal> external;
+    */
+};
+
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------
 struct Mesh : ElemBase {
 struct Mesh : ElemBase {
     ID id FAIL;
     ID id FAIL;
@@ -397,6 +470,12 @@ struct Mesh : ElemBase {
     vector<MCol> mcol;
     vector<MCol> mcol;
 
 
     vector< std::shared_ptr<Material> > mat FAIL;
     vector< std::shared_ptr<Material> > mat FAIL;
+
+    struct CustomData vdata;
+    struct CustomData edata;
+    struct CustomData fdata;
+    struct CustomData pdata;
+    struct CustomData ldata;
 };
 };
 
 
 // -------------------------------------------------------------------------------
 // -------------------------------------------------------------------------------

+ 11 - 0
code/BlenderSceneGen.h

@@ -248,6 +248,17 @@ template <> void Structure :: Convert<Image> (
     ) const
     ) const
 ;
 ;
 
 
+template <> void Structure::Convert<CustomData>(
+    CustomData& dest,
+    const FileDatabase& db
+    ) const
+    ;
+
+template <> void Structure::Convert<CustomDataLayer>(
+    CustomDataLayer& dest,
+    const FileDatabase& db
+    ) const
+    ;
 
 
     }
     }
 }
 }

+ 2 - 1
code/BlenderTessellator.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 3 - 2
code/BlenderTessellator.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -46,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_BLEND_TESSELLATOR_H
 #define INCLUDED_AI_BLEND_TESSELLATOR_H
 
 
 // Use these to toggle between GLU Tessellate or poly2tri
 // Use these to toggle between GLU Tessellate or poly2tri
-// Note (acg) keep GLU Tesselate disabled by default - if it is turned on,
+// Note (acg) keep GLU Tessellate disabled by default - if it is turned on,
 // assimp needs to be linked against GLU, which is currently not yet
 // assimp needs to be linked against GLU, which is currently not yet
 // made configurable in CMake and potentially not wanted by most users
 // made configurable in CMake and potentially not wanted by most users
 // as it requires a Gl environment.
 // as it requires a Gl environment.

+ 2 - 1
code/CInterfaceIOWrapper.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.

+ 2 - 1
code/CInterfaceIOWrapper.h

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.

+ 28 - 8
code/CMakeLists.txt

@@ -1,7 +1,8 @@
 # Open Asset Import Library (assimp)
 # Open Asset Import Library (assimp)
 # ----------------------------------------------------------------------
 # ----------------------------------------------------------------------
 #
 #
-# Copyright (c) 2006-2017, assimp team
+# Copyright (c) 2006-2018, assimp team
+
 
 
 # All rights reserved.
 # All rights reserved.
 #
 #
@@ -71,6 +72,7 @@ SET( PUBLIC_HEADERS
   ${HEADER_PATH}/matrix4x4.h
   ${HEADER_PATH}/matrix4x4.h
   ${HEADER_PATH}/matrix4x4.inl
   ${HEADER_PATH}/matrix4x4.inl
   ${HEADER_PATH}/mesh.h
   ${HEADER_PATH}/mesh.h
+  ${HEADER_PATH}/pbrmaterial.h
   ${HEADER_PATH}/postprocess.h
   ${HEADER_PATH}/postprocess.h
   ${HEADER_PATH}/quaternion.h
   ${HEADER_PATH}/quaternion.h
   ${HEADER_PATH}/quaternion.inl
   ${HEADER_PATH}/quaternion.inl
@@ -175,8 +177,6 @@ SET( Common_SRCS
   SkeletonMeshBuilder.cpp
   SkeletonMeshBuilder.cpp
   SplitByBoneCountProcess.cpp
   SplitByBoneCountProcess.cpp
   SplitByBoneCountProcess.h
   SplitByBoneCountProcess.h
-  ScaleProcess.cpp
-  ScaleProcess.h
   StandardShapes.cpp
   StandardShapes.cpp
   TargetAnimation.cpp
   TargetAnimation.cpp
   TargetAnimation.h
   TargetAnimation.h
@@ -186,6 +186,8 @@ SET( Common_SRCS
   Bitmap.cpp
   Bitmap.cpp
   Version.cpp
   Version.cpp
   CreateAnimMesh.cpp
   CreateAnimMesh.cpp
+  simd.h
+  simd.cpp
 )
 )
 SOURCE_GROUP(Common FILES ${Common_SRCS})
 SOURCE_GROUP(Common FILES ${Common_SRCS})
 
 
@@ -206,8 +208,15 @@ OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_
 # macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
 # 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)
 # this way selective loaders can be compiled (reduces filesize + compile time)
 MACRO(ADD_ASSIMP_IMPORTER name)
 MACRO(ADD_ASSIMP_IMPORTER name)
-  OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" ${ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT})
-  IF(ASSIMP_BUILD_${name}_IMPORTER)
+  IF (ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT)
+    set(ASSIMP_IMPORTER_ENABLED TRUE)
+    IF (DEFINED ASSIMP_BUILD_${name}_IMPORTER AND NOT ASSIMP_BUILD_${name}_IMPORTER)
+      set(ASSIMP_IMPORTER_ENABLED FALSE)
+    ENDIF ()
+  ELSE ()
+    set(ASSIMP_IMPORTER_ENABLED ${ASSIMP_BUILD_${name}_IMPORTER})
+  ENDIF ()
+  IF (ASSIMP_IMPORTER_ENABLED)
     LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
     LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
     SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
     SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
     SET(${name}_SRCS ${ARGN})
     SET(${name}_SRCS ${ARGN})
@@ -460,6 +469,8 @@ ADD_ASSIMP_IMPORTER( BLEND
   BlenderBMesh.cpp
   BlenderBMesh.cpp
   BlenderTessellator.h
   BlenderTessellator.h
   BlenderTessellator.cpp
   BlenderTessellator.cpp
+  BlenderCustomData.h
+  BlenderCustomData.cpp
 )
 )
 
 
 ADD_ASSIMP_IMPORTER( IFC
 ADD_ASSIMP_IMPORTER( IFC
@@ -483,9 +494,9 @@ ADD_ASSIMP_IMPORTER( IFC
 )
 )
 if (ASSIMP_BUILD_IFC_IMPORTER)
 if (ASSIMP_BUILD_IFC_IMPORTER)
   if (MSVC)
   if (MSVC)
-    set_source_files_properties(IFCReaderGen1.cpp IFCReaderGen2.cpp PROPERTIES COMPILE_FLAGS "/bigobj")
+    set_source_files_properties(Importer/IFC/IFCReaderGen1_2x3.cpp Importer/IFC/IFCReaderGen2_2x3.cpp PROPERTIES COMPILE_FLAGS "/bigobj")
   elseif(CMAKE_COMPILER_IS_MINGW)
   elseif(CMAKE_COMPILER_IS_MINGW)
-    set_source_files_properties(IFCReaderGen1.cpp IFCReaderGen2.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 (ASSIMP_BUILD_IFC_IMPORTER)
 
 
@@ -521,6 +532,13 @@ ADD_ASSIMP_IMPORTER( FBX
   FBXDeformer.cpp
   FBXDeformer.cpp
   FBXBinaryTokenizer.cpp
   FBXBinaryTokenizer.cpp
   FBXDocumentUtil.cpp
   FBXDocumentUtil.cpp
+  FBXExporter.h
+  FBXExporter.cpp
+  FBXExportNode.h
+  FBXExportNode.cpp
+  FBXExportProperty.h
+  FBXExportProperty.cpp
+  FBXCommon.h
 )
 )
 
 
 SET( PostProcessing_SRCS
 SET( PostProcessing_SRCS
@@ -577,6 +595,8 @@ SET( PostProcessing_SRCS
   PolyTools.h
   PolyTools.h
   MakeVerboseFormat.cpp
   MakeVerboseFormat.cpp
   MakeVerboseFormat.h
   MakeVerboseFormat.h
+  ScaleProcess.cpp
+  ScaleProcess.h
 )
 )
 SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
 SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
 
 
@@ -640,7 +660,7 @@ ADD_ASSIMP_IMPORTER( X
   XFileExporter.cpp
   XFileExporter.cpp
 )
 )
 
 
-ADD_ASSIMP_IMPORTER(X3D
+ADD_ASSIMP_IMPORTER( X3D
   X3DExporter.cpp
   X3DExporter.cpp
   X3DExporter.hpp
   X3DExporter.hpp
   X3DImporter.cpp
   X3DImporter.cpp

+ 30 - 80
code/COBLoader.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, 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,
@@ -46,11 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_COB_IMPORTER
 #ifndef ASSIMP_BUILD_NO_COB_IMPORTER
 #include "COBLoader.h"
 #include "COBLoader.h"
 #include "COBScene.h"
 #include "COBScene.h"
-
+#include "ConvertToLHProcess.h"
 #include <assimp/StreamReader.h>
 #include <assimp/StreamReader.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/fast_atof.h>
 #include <assimp/fast_atof.h>
-
 #include <assimp/LineSplitter.h>
 #include <assimp/LineSplitter.h>
 #include <assimp/TinyFormatter.h>
 #include <assimp/TinyFormatter.h>
 #include <memory>
 #include <memory>
@@ -104,7 +104,7 @@ COBImporter::~COBImporter()
 bool COBImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
 bool COBImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
 {
 {
     const std::string& extension = GetExtension(pFile);
     const std::string& extension = GetExtension(pFile);
-    if (extension == "cob" || extension == "scn") {
+    if (extension == "cob" || extension == "scn" || extension == "COB" || extension == "SCN") {
         return true;
         return true;
     }
     }
 
 
@@ -150,7 +150,7 @@ void COBImporter::InternReadFile( const std::string& pFile,
         ThrowException("Could not found magic id: `Caligari`");
         ThrowException("Could not found magic id: `Caligari`");
     }
     }
 
 
-    DefaultLogger::get()->info("File format tag: "+std::string(head+9,6));
+    ASSIMP_LOG_INFO_F("File format tag: ",std::string(head+9,6));
     if (head[16]!='L') {
     if (head[16]!='L') {
         ThrowException("File is big-endian, which is not supported");
         ThrowException("File is big-endian, which is not supported");
     }
     }
@@ -224,6 +224,9 @@ void COBImporter::InternReadFile( const std::string& pFile,
     }
     }
 
 
     pScene->mRootNode = BuildNodes(*root.get(),scene,pScene);
     pScene->mRootNode = BuildNodes(*root.get(),scene,pScene);
+	//flip normals after import
+    FlipWindingOrderProcess flip;
+    flip.Execute( pScene );
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -300,7 +303,7 @@ aiNode* COBImporter::BuildNodes(const Node& root,const Scene& scin,aiScene* fill
                     }
                     }
                     std::unique_ptr<const Material> defmat;
                     std::unique_ptr<const Material> defmat;
                     if(!min) {
                     if(!min) {
-                        DefaultLogger::get()->debug(format()<<"Could not resolve material index "
+                        ASSIMP_LOG_DEBUG(format()<<"Could not resolve material index "
                             <<reflist.first<<" - creating default material for this slot");
                             <<reflist.first<<" - creating default material for this slot");
 
 
                         defmat.reset(min=new Material());
                         defmat.reset(min=new Material());
@@ -472,7 +475,7 @@ void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo
 
 
     // we can recover if the chunk size was specified.
     // we can recover if the chunk size was specified.
     if(nfo.size != static_cast<unsigned int>(-1)) {
     if(nfo.size != static_cast<unsigned int>(-1)) {
-        DefaultLogger::get()->error(error);
+        ASSIMP_LOG_ERROR(error);
 
 
         // (HACK) - our current position in the stream is the beginning of the
         // (HACK) - our current position in the stream is the beginning of the
         // head line of the next chunk. That's fine, but the caller is going
         // head line of the next chunk. That's fine, but the caller is going
@@ -484,46 +487,6 @@ void COBImporter::UnsupportedChunk_Ascii(LineSplitter& splitter, const ChunkInfo
     else ThrowException(error);
     else ThrowException(error);
 }
 }
 
 
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogWarn_Ascii(const LineSplitter& splitter, const format& message)    {
-    LogWarn_Ascii(message << " [at line "<< splitter.get_index()<<"]");
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogError_Ascii(const LineSplitter& splitter, const format& message)   {
-    LogError_Ascii(message << " [at line "<< splitter.get_index()<<"]");
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogInfo_Ascii(const LineSplitter& splitter, const format& message)    {
-    LogInfo_Ascii(message << " [at line "<< splitter.get_index()<<"]");
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogDebug_Ascii(const LineSplitter& splitter, const format& message)   {
-    LogDebug_Ascii(message << " [at line "<< splitter.get_index()<<"]");
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogWarn_Ascii(const Formatter::format& message)   {
-    DefaultLogger::get()->warn(std::string("COB: ")+=message);
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogError_Ascii(const Formatter::format& message)  {
-    DefaultLogger::get()->error(std::string("COB: ")+=message);
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogInfo_Ascii(const Formatter::format& message)   {
-    DefaultLogger::get()->info(std::string("COB: ")+=message);
-}
-
-// ------------------------------------------------------------------------------------------------
-void COBImporter::LogDebug_Ascii(const Formatter::format& message)  {
-    DefaultLogger::get()->debug(std::string("COB: ")+=message);
-}
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void COBImporter::ReadBasicNodeInfo_Ascii(Node& msh, LineSplitter& splitter, const ChunkInfo& /*nfo*/)
 void COBImporter::ReadBasicNodeInfo_Ascii(Node& msh, LineSplitter& splitter, const ChunkInfo& /*nfo*/)
 {
 {
@@ -573,8 +536,7 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
 
 
     ++splitter;
     ++splitter;
     if (!splitter.match_start("mat# ")) {
     if (!splitter.match_start("mat# ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `mat#` line in `Mat1` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `mat#` line in `Mat1` chunk ", nfo.id );
         return;
         return;
     }
     }
 
 
@@ -586,8 +548,7 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
     ++splitter;
     ++splitter;
 
 
     if (!splitter.match_start("shader: ")) {
     if (!splitter.match_start("shader: ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `mat#` line in `Mat1` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `mat#` line in `Mat1` chunk ", nfo.id);
         return;
         return;
     }
     }
     std::string shader = std::string(splitter[1]);
     std::string shader = std::string(splitter[1]);
@@ -600,14 +561,12 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
         mat.shader = Material::PHONG;
         mat.shader = Material::PHONG;
     }
     }
     else if (shader != "flat") {
     else if (shader != "flat") {
-        LogWarn_Ascii(splitter,format()<<
-            "Unknown value for `shader` in `Mat1` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Unknown value for `shader` in `Mat1` chunk ", nfo.id );
     }
     }
 
 
     ++splitter;
     ++splitter;
     if (!splitter.match_start("rgb ")) {
     if (!splitter.match_start("rgb ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `rgb` line in `Mat1` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `rgb` line in `Mat1` chunk ", nfo.id);
     }
     }
 
 
     const char* rgb = splitter[1];
     const char* rgb = splitter[1];
@@ -615,8 +574,7 @@ void COBImporter::ReadMat1_Ascii(Scene& out, LineSplitter& splitter, const Chunk
 
 
     ++splitter;
     ++splitter;
     if (!splitter.match_start("alpha ")) {
     if (!splitter.match_start("alpha ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `alpha` line in `Mat1` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `alpha` line in `Mat1` chunk ", nfo.id);
     }
     }
 
 
     const char* tokens[10];
     const char* tokens[10];
@@ -637,8 +595,7 @@ void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const Chunk
     }
     }
     ++splitter;
     ++splitter;
     if (!splitter.match_start("Units ")) {
     if (!splitter.match_start("Units ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `Units` line in `Unit` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `Units` line in `Unit` chunk ", nfo.id);
         return;
         return;
     }
     }
 
 
@@ -649,13 +606,12 @@ void COBImporter::ReadUnit_Ascii(Scene& out, LineSplitter& splitter, const Chunk
             const unsigned int t=strtoul10(splitter[1]);
             const unsigned int t=strtoul10(splitter[1]);
 
 
             nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
             nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
-                LogWarn_Ascii(splitter,format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
+                ASSIMP_LOG_WARN_F(t, " is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id)
                 ,1.f):units[t];
                 ,1.f):units[t];
             return;
             return;
         }
         }
     }
     }
-    LogWarn_Ascii(splitter,format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
-        <<nfo.parent_id<<" which does not exist");
+    ASSIMP_LOG_WARN_F( "`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -689,15 +645,13 @@ void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const Chunk
         msh.ltype = Light::SPOT;
         msh.ltype = Light::SPOT;
     }
     }
     else {
     else {
-        LogWarn_Ascii(splitter,format()<<
-            "Unknown kind of light source in `Lght` chunk "<<nfo.id<<" : "<<*splitter);
+        ASSIMP_LOG_WARN_F( "Unknown kind of light source in `Lght` chunk ", nfo.id, " : ", *splitter );
         msh.ltype = Light::SPOT;
         msh.ltype = Light::SPOT;
     }
     }
 
 
     ++splitter;
     ++splitter;
     if (!splitter.match_start("color ")) {
     if (!splitter.match_start("color ")) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `color` line in `Lght` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `color` line in `Lght` chunk ", nfo.id );
     }
     }
 
 
     const char* rgb = splitter[1];
     const char* rgb = splitter[1];
@@ -705,16 +659,14 @@ void COBImporter::ReadLght_Ascii(Scene& out, LineSplitter& splitter, const Chunk
 
 
     SkipSpaces(&rgb);
     SkipSpaces(&rgb);
     if (strncmp(rgb,"cone angle",10)) {
     if (strncmp(rgb,"cone angle",10)) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `cone angle` entity in `color` line in `Lght` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `cone angle` entity in `color` line in `Lght` chunk ", nfo.id );
     }
     }
     SkipSpaces(rgb+10,&rgb);
     SkipSpaces(rgb+10,&rgb);
     msh.angle = fast_atof(&rgb);
     msh.angle = fast_atof(&rgb);
 
 
     SkipSpaces(&rgb);
     SkipSpaces(&rgb);
     if (strncmp(rgb,"inner angle",11)) {
     if (strncmp(rgb,"inner angle",11)) {
-        LogWarn_Ascii(splitter,format()<<
-            "Expected `inner angle` entity in `color` line in `Lght` chunk "<<nfo.id);
+        ASSIMP_LOG_WARN_F( "Expected `inner angle` entity in `color` line in `Lght` chunk ", nfo.id);
     }
     }
     SkipSpaces(rgb+11,&rgb);
     SkipSpaces(rgb+11,&rgb);
     msh.inner_angle = fast_atof(&rgb);
     msh.inner_angle = fast_atof(&rgb);
@@ -825,7 +777,7 @@ void COBImporter::ReadPolH_Ascii(Scene& out, LineSplitter& splitter, const Chunk
 
 
             for(unsigned int cur = 0; cur < cnt && ++splitter ;++cur) {
             for(unsigned int cur = 0; cur < cnt && ++splitter ;++cur) {
                 if (splitter.match_start("Hole")) {
                 if (splitter.match_start("Hole")) {
-                    LogWarn_Ascii(splitter,"Skipping unsupported `Hole` line");
+                    ASSIMP_LOG_WARN( "Skipping unsupported `Hole` line" );
                     continue;
                     continue;
                 }
                 }
 
 
@@ -885,7 +837,7 @@ void COBImporter::ReadBitM_Ascii(Scene& /*out*/, LineSplitter& splitter, const C
 
 
     const unsigned int head = strtoul10((++splitter)[1]);
     const unsigned int head = strtoul10((++splitter)[1]);
     if (head != sizeof(Bitmap::BitmapHeader)) {
     if (head != sizeof(Bitmap::BitmapHeader)) {
-        LogWarn_Ascii(splitter,"Unexpected ThumbNailHdrSize, skipping this chunk");
+        ASSIMP_LOG_WARN("Unexpected ThumbNailHdrSize, skipping this chunk");
         return;
         return;
     }
     }
 
 
@@ -932,7 +884,7 @@ void COBImporter::UnsupportedChunk_Binary( StreamReaderLE& reader, const ChunkIn
 
 
     // we can recover if the chunk size was specified.
     // we can recover if the chunk size was specified.
     if(nfo.size != static_cast<unsigned int>(-1)) {
     if(nfo.size != static_cast<unsigned int>(-1)) {
-        DefaultLogger::get()->error(error);
+        ASSIMP_LOG_ERROR(error);
         reader.IncPtr(nfo.size);
         reader.IncPtr(nfo.size);
     }
     }
     else ThrowException(error);
     else ThrowException(error);
@@ -1139,7 +1091,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const
             mat.type = Material::METAL;
             mat.type = Material::METAL;
             break;
             break;
         default:
         default:
-            LogError_Ascii(format("Unrecognized shader type in `Mat1` chunk with id ")<<nfo.id);
+            ASSIMP_LOG_ERROR_F( "Unrecognized shader type in `Mat1` chunk with id ", nfo.id );
             mat.type = Material::FLAT;
             mat.type = Material::FLAT;
     }
     }
 
 
@@ -1154,7 +1106,7 @@ void COBImporter::ReadMat1_Binary(COB::Scene& out, StreamReaderLE& reader, const
             mat.autofacet = Material::SMOOTH;
             mat.autofacet = Material::SMOOTH;
             break;
             break;
         default:
         default:
-            LogError_Ascii(format("Unrecognized faceting mode in `Mat1` chunk with id ")<<nfo.id);
+            ASSIMP_LOG_ERROR_F( "Unrecognized faceting mode in `Mat1` chunk with id ", nfo.id );
             mat.autofacet = Material::FACETED;
             mat.autofacet = Material::FACETED;
     }
     }
     mat.autofacet_angle = static_cast<float>(reader.GetI1());
     mat.autofacet_angle = static_cast<float>(reader.GetI1());
@@ -1286,15 +1238,13 @@ void COBImporter::ReadUnit_Binary(COB::Scene& out, StreamReaderLE& reader, const
         if (nd->id == nfo.parent_id) {
         if (nd->id == nfo.parent_id) {
             const unsigned int t=reader.GetI2();
             const unsigned int t=reader.GetI2();
             nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
             nd->unit_scale = t>=sizeof(units)/sizeof(units[0])?(
-                LogWarn_Ascii(format()<<t<<" is not a valid value for `Units` attribute in `Unit chunk` "<<nfo.id)
+                ASSIMP_LOG_WARN_F(t," is not a valid value for `Units` attribute in `Unit chunk` ", nfo.id)
                 ,1.f):units[t];
                 ,1.f):units[t];
 
 
             return;
             return;
         }
         }
     }
     }
-    LogWarn_Ascii(format()<<"`Unit` chunk "<<nfo.id<<" is a child of "
-        <<nfo.parent_id<<" which does not exist");
+    ASSIMP_LOG_WARN_F( "`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
 }
 }
 
 
-
-#endif
+#endif // ASSIMP_BUILD_NO_COB_IMPORTER

+ 3 - 22
code/COBLoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -76,10 +77,7 @@ class COBImporter : public BaseImporter
 public:
 public:
     COBImporter();
     COBImporter();
     ~COBImporter();
     ~COBImporter();
-
-
-public:
-
+    
     // --------------------
     // --------------------
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
     bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
         bool checkSig) const;
         bool checkSig) const;
@@ -114,15 +112,11 @@ private:
      *  @param stream Stream to read from.  */
      *  @param stream Stream to read from.  */
     void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream);
     void ReadBinaryFile(COB::Scene& out, StreamReaderLE* stream);
 
 
-
-private:
-
     // Conversion to Assimp output format
     // Conversion to Assimp output format
 
 
     aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill);
     aiNode* BuildNodes(const COB::Node& root,const COB::Scene& scin,aiScene* fill);
 
 
 private:
 private:
-
     // ASCII file support
     // ASCII file support
 
 
     void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name);
     void UnsupportedChunk_Ascii(LineSplitter& splitter, const COB::ChunkInfo& nfo, const char* name);
@@ -141,19 +135,6 @@ private:
     void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
     void ReadChan_Ascii(COB::Scene& out, LineSplitter& splitter, const COB::ChunkInfo& nfo);
 
 
 
 
-    // ASCII file logging stuff to add proper line numbers to messages
-
-    static void LogWarn_Ascii (const LineSplitter& splitter, const Formatter::format& message);
-    static void LogError_Ascii(const LineSplitter& splitter, const Formatter::format& message);
-    static void LogInfo_Ascii (const LineSplitter& splitter, const Formatter::format& message);
-    static void LogDebug_Ascii(const LineSplitter& splitter, const Formatter::format& message);
-
-    static void LogWarn_Ascii  (const Formatter::format& message);
-    static void LogError_Ascii (const Formatter::format& message);
-    static void LogInfo_Ascii  (const Formatter::format& message);
-    static void LogDebug_Ascii (const Formatter::format& message);
-
-
     // Binary file support
     // Binary file support
 
 
     void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name);
     void UnsupportedChunk_Binary(StreamReaderLE& reader, const COB::ChunkInfo& nfo, const char* name);

+ 2 - 1
code/COBScene.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 5 - 4
code/CSMLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -135,7 +136,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
     TextFileToBuffer(file.get(),mBuffer2);
     TextFileToBuffer(file.get(),mBuffer2);
     const char* buffer = &mBuffer2[0];
     const char* buffer = &mBuffer2[0];
 
 
-    aiAnimation* anim = new aiAnimation();
+    std::unique_ptr<aiAnimation> anim(new aiAnimation());
     int first = 0, last = 0x00ffffff;
     int first = 0, last = 0x00ffffff;
 
 
     // now process the file and look out for '$' sections
     // now process the file and look out for '$' sections
@@ -232,7 +233,7 @@ void CSMImporter::InternReadFile( const std::string& pFile,
 
 
                         if (TokenMatchI(buffer, "DROPOUT", 7))  {
                         if (TokenMatchI(buffer, "DROPOUT", 7))  {
                             // seems this is invalid marker data; at least the doc says it's possible
                             // seems this is invalid marker data; at least the doc says it's possible
-                            DefaultLogger::get()->warn("CSM: Encountered invalid marker data (DROPOUT)");
+                            ASSIMP_LOG_WARN("CSM: Encountered invalid marker data (DROPOUT)");
                         }
                         }
                         else    {
                         else    {
                             aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
                             aiVectorKey* sub = s->mPositionKeys + s->mNumPositionKeys;
@@ -293,8 +294,8 @@ void CSMImporter::InternReadFile( const std::string& pFile,
 
 
     // Store the one and only animation in the scene
     // Store the one and only animation in the scene
     pScene->mAnimations    = new aiAnimation*[pScene->mNumAnimations=1];
     pScene->mAnimations    = new aiAnimation*[pScene->mNumAnimations=1];
-    pScene->mAnimations[0] = anim;
     anim->mName.Set("$CSM_MasterAnim");
     anim->mName.Set("$CSM_MasterAnim");
+    pScene->mAnimations[0] = anim.release();
 
 
     // mark the scene as incomplete and run SkeletonMeshBuilder on it
     // mark the scene as incomplete and run SkeletonMeshBuilder on it
     pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;
     pScene->mFlags |= AI_SCENE_FLAGS_INCOMPLETE;

+ 2 - 1
code/CSMLoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 9 - 8
code/CalcTangentsProcess.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -94,7 +95,7 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
 {
 {
     ai_assert( NULL != pScene );
     ai_assert( NULL != pScene );
 
 
-    DefaultLogger::get()->debug("CalcTangentsProcess begin");
+    ASSIMP_LOG_DEBUG("CalcTangentsProcess begin");
 
 
     bool bHas = false;
     bool bHas = false;
     for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
     for ( unsigned int a = 0; a < pScene->mNumMeshes; a++ ) {
@@ -102,9 +103,9 @@ void CalcTangentsProcess::Execute( aiScene* pScene)
     }
     }
 
 
     if ( bHas ) {
     if ( bHas ) {
-        DefaultLogger::get()->info("CalcTangentsProcess finished. Tangents have been calculated");
+        ASSIMP_LOG_INFO("CalcTangentsProcess finished. Tangents have been calculated");
     } else {
     } else {
-        DefaultLogger::get()->debug("CalcTangentsProcess finished");
+        ASSIMP_LOG_DEBUG("CalcTangentsProcess finished");
     }
     }
 }
 }
 
 
@@ -125,19 +126,19 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
     // are undefined.
     // are undefined.
     if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
     if (!(pMesh->mPrimitiveTypes & (aiPrimitiveType_TRIANGLE | aiPrimitiveType_POLYGON)))
     {
     {
-        DefaultLogger::get()->info("Tangents are undefined for line and point meshes");
+        ASSIMP_LOG_INFO("Tangents are undefined for line and point meshes");
         return false;
         return false;
     }
     }
 
 
     // what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
     // what we can check, though, is if the mesh has normals and texture coordinates. That's a requirement
     if( pMesh->mNormals == NULL)
     if( pMesh->mNormals == NULL)
     {
     {
-        DefaultLogger::get()->error("Failed to compute tangents; need normals");
+        ASSIMP_LOG_ERROR("Failed to compute tangents; need normals");
         return false;
         return false;
     }
     }
     if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
     if( configSourceUV >= AI_MAX_NUMBER_OF_TEXTURECOORDS || !pMesh->mTextureCoords[configSourceUV] )
     {
     {
-        DefaultLogger::get()->error((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
+        ASSIMP_LOG_ERROR((Formatter::format("Failed to compute tangents; need UV data in channel"),configSourceUV));
         return false;
         return false;
     }
     }
 
 
@@ -189,7 +190,7 @@ bool CalcTangentsProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshIndex)
         float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
         float tx = meshTex[p2].x - meshTex[p0].x, ty = meshTex[p2].y - meshTex[p0].y;
         float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
         float dirCorrection = (tx * sy - ty * sx) < 0.0f ? -1.0f : 1.0f;
         // when t1, t2, t3 in same position in UV space, just use default UV direction.
         // when t1, t2, t3 in same position in UV space, just use default UV direction.
-        if ( 0 == sx && 0 ==sy && 0 == tx && 0 == ty ) {
+        if (  sx * ty == sy * tx ) {
             sx = 0.0; sy = 1.0;
             sx = 0.0; sy = 1.0;
             tx = 1.0; ty = 0.0;
             tx = 1.0; ty = 0.0;
         }
         }

+ 2 - 1
code/CalcTangentsProcess.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 11 - 6
code/ColladaExporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -1268,7 +1269,8 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
 	
 	
 	mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
 	mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
 	PushTag();
 	PushTag();
-	
+
+    std::string node_idstr;
 	for (size_t a = 0; a < anim->mNumChannels; ++a) {
 	for (size_t a = 0; a < anim->mNumChannels; ++a) {
 		const aiNodeAnim * nodeAnim = anim->mChannels[a];
 		const aiNodeAnim * nodeAnim = anim->mChannels[a];
 		
 		
@@ -1276,7 +1278,9 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
 		if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys ||  nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
 		if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys ||  nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
 		
 		
 		{
 		{
-			const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input");
+            node_idstr.clear();
+            node_idstr += nodeAnim->mNodeName.data;
+            node_idstr += std::string( "_matrix-input" );
 
 
 			std::vector<ai_real> frames;
 			std::vector<ai_real> frames;
 			for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
 			for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
@@ -1288,12 +1292,14 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
 		}
 		}
 		
 		
 		{
 		{
-			const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output");
+            node_idstr.clear();
+
+            node_idstr += nodeAnim->mNodeName.data;
+            node_idstr += std::string("_matrix-output");
 			
 			
 			std::vector<ai_real> keyframes;
 			std::vector<ai_real> keyframes;
 			keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
 			keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
 			for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
 			for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
-				
 				aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue;
 				aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue;
 				aiMatrix4x4 ScalingM;  // identity
 				aiMatrix4x4 ScalingM;  // identity
 				ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z;
 				ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z;
@@ -1360,7 +1366,6 @@ void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
 			PopTag();
 			PopTag();
 			mOutput << startstr << "</source>" << endstr;
 			mOutput << startstr << "</source>" << endstr;
 		}
 		}
-		
 	}
 	}
 	
 	
 	for (size_t a = 0; a < anim->mNumChannels; ++a) {
 	for (size_t a = 0; a < anim->mNumChannels; ++a) {

+ 3 - 2
code/ColladaExporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -188,7 +189,7 @@ protected:
      {}
      {}
   };
   };
 
 
-  // summarize a material in an convinient way.
+  // summarize a material in an convenient way.
   struct Material
   struct Material
   {
   {
     std::string name;
     std::string name;

+ 6 - 4
code/ColladaHelper.h

@@ -4,7 +4,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -271,12 +272,13 @@ struct Node
     /** Node instances at this node */
     /** Node instances at this node */
     std::vector<NodeInstance> mNodeInstances;
     std::vector<NodeInstance> mNodeInstances;
 
 
-    /** Rootnodes: Name of primary camera, if any */
+    /** Root-nodes: Name of primary camera, if any */
     std::string mPrimaryCamera;
     std::string mPrimaryCamera;
 
 
     //! Constructor. Begin with a zero parent
     //! Constructor. Begin with a zero parent
-    Node() {
-        mParent = NULL;
+    Node()
+    : mParent( nullptr ){
+        // empty
     }
     }
 
 
     //! Destructor: delete all children subsequently
     //! Destructor: delete all children subsequently

+ 77 - 67
code/ColladaLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -46,13 +47,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
 #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
 
 
 #include "ColladaLoader.h"
 #include "ColladaLoader.h"
+#include "ColladaParser.h"
+
 #include <assimp/anim.h>
 #include <assimp/anim.h>
 #include <assimp/scene.h>
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/Importer.hpp>
 #include <assimp/Importer.hpp>
 #include <assimp/importerdesc.h>
 #include <assimp/importerdesc.h>
+#include <assimp/Defines.h>
 
 
-#include "ColladaParser.h"
 #include <assimp/fast_atof.h>
 #include <assimp/fast_atof.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/ParsingUtils.h>
 #include <assimp/SkeletonMeshBuilder.h>
 #include <assimp/SkeletonMeshBuilder.h>
@@ -62,7 +65,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "math.h"
 #include "math.h"
 #include <algorithm>
 #include <algorithm>
 #include <numeric>
 #include <numeric>
-#include <assimp/Defines.h>
 
 
 using namespace Assimp;
 using namespace Assimp;
 using namespace Assimp::Formatter;
 using namespace Assimp::Formatter;
@@ -130,6 +132,7 @@ void ColladaLoader::SetupProperties(const Importer* pImp)
 {
 {
     noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
     noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES,0) != 0;
     ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
     ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
+    useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES,0) != 0;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -178,26 +181,27 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
     // ... then fill the materials with the now adjusted settings
     // ... then fill the materials with the now adjusted settings
     FillMaterials(parser, pScene);
     FillMaterials(parser, pScene);
 
 
-        // Apply unitsize scale calculation
-        pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0,  0,  0,
-                                                          0,  parser.mUnitSize,  0,  0,
-                                                          0,  0,  parser.mUnitSize,  0,
-                                                          0,  0,  0,  1);
-        if( !ignoreUpDirection ) {
-        // Convert to Y_UP, if different orientation
-        if( parser.mUpDirection == ColladaParser::UP_X)
-            pScene->mRootNode->mTransformation *= aiMatrix4x4(
-                 0, -1,  0,  0,
-                 1,  0,  0,  0,
-                 0,  0,  1,  0,
-                 0,  0,  0,  1);
-        else if( parser.mUpDirection == ColladaParser::UP_Z)
-            pScene->mRootNode->mTransformation *= aiMatrix4x4(
-                 1,  0,  0,  0,
-                 0,  0,  1,  0,
-                 0, -1,  0,  0,
-                 0,  0,  0,  1);
-        }
+    // Apply unitsize scale calculation
+    pScene->mRootNode->mTransformation *= aiMatrix4x4(parser.mUnitSize, 0,  0,  0,
+                                                        0,  parser.mUnitSize,  0,  0,
+                                                        0,  0,  parser.mUnitSize,  0,
+                                                        0,  0,  0,  1);
+    if( !ignoreUpDirection ) {
+    // Convert to Y_UP, if different orientation
+    if( parser.mUpDirection == ColladaParser::UP_X)
+        pScene->mRootNode->mTransformation *= aiMatrix4x4(
+                0, -1,  0,  0,
+                1,  0,  0,  0,
+                0,  0,  1,  0,
+                0,  0,  0,  1);
+    else if( parser.mUpDirection == ColladaParser::UP_Z)
+        pScene->mRootNode->mTransformation *= aiMatrix4x4(
+                1,  0,  0,  0,
+                0,  0,  1,  0,
+                0, -1,  0,  0,
+                0,  0,  0,  1);
+    }
+
     // store all meshes
     // store all meshes
     StoreSceneMeshes( pScene);
     StoreSceneMeshes( pScene);
 
 
@@ -291,7 +295,7 @@ void ColladaLoader::ResolveNodeInstances( const ColladaParser& pParser, const Co
             nd = FindNode(pParser.mRootNode, nodeInst.mNode);
             nd = FindNode(pParser.mRootNode, nodeInst.mNode);
         }
         }
         if (!nd)
         if (!nd)
-            DefaultLogger::get()->error("Collada: Unable to resolve reference to instanced node " + nodeInst.mNode);
+            ASSIMP_LOG_ERROR_F("Collada: Unable to resolve reference to instanced node ", nodeInst.mNode);
 
 
         else {
         else {
             //  attach this node to the list of children
             //  attach this node to the list of children
@@ -308,7 +312,7 @@ void ColladaLoader::ApplyVertexToEffectSemanticMapping(Collada::Sampler& sampler
     std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
     std::map<std::string, Collada::InputSemanticMapEntry>::const_iterator it = table.mMap.find(sampler.mUVChannel);
     if (it != table.mMap.end()) {
     if (it != table.mMap.end()) {
         if (it->second.mType != Collada::IT_Texcoord)
         if (it->second.mType != Collada::IT_Texcoord)
-            DefaultLogger::get()->error("Collada: Unexpected effect input mapping");
+            ASSIMP_LOG_ERROR("Collada: Unexpected effect input mapping");
 
 
         sampler.mUVId = it->second.mSet;
         sampler.mUVId = it->second.mSet;
     }
     }
@@ -324,7 +328,7 @@ void ColladaLoader::BuildLightsForNode( const ColladaParser& pParser, const Coll
         ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight);
         ColladaParser::LightLibrary::const_iterator srcLightIt = pParser.mLightLibrary.find( lid.mLight);
         if( srcLightIt == pParser.mLightLibrary.end())
         if( srcLightIt == pParser.mLightLibrary.end())
         {
         {
-            DefaultLogger::get()->warn("Collada: Unable to find light for ID \"" + lid.mLight + "\". Skipping.");
+            ASSIMP_LOG_WARN_F("Collada: Unable to find light for ID \"" , lid.mLight , "\". Skipping.");
             continue;
             continue;
         }
         }
         const Collada::Light* srcLight = &srcLightIt->second;
         const Collada::Light* srcLight = &srcLightIt->second;
@@ -392,14 +396,14 @@ void ColladaLoader::BuildCamerasForNode( const ColladaParser& pParser, const Col
         ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera);
         ColladaParser::CameraLibrary::const_iterator srcCameraIt = pParser.mCameraLibrary.find( cid.mCamera);
         if( srcCameraIt == pParser.mCameraLibrary.end())
         if( srcCameraIt == pParser.mCameraLibrary.end())
         {
         {
-            DefaultLogger::get()->warn("Collada: Unable to find camera for ID \"" + cid.mCamera + "\". Skipping.");
+            ASSIMP_LOG_WARN_F("Collada: Unable to find camera for ID \"" , cid.mCamera , "\". Skipping.");
             continue;
             continue;
         }
         }
         const Collada::Camera* srcCamera = &srcCameraIt->second;
         const Collada::Camera* srcCamera = &srcCameraIt->second;
 
 
         // orthographic cameras not yet supported in Assimp
         // orthographic cameras not yet supported in Assimp
         if (srcCamera->mOrtho) {
         if (srcCamera->mOrtho) {
-            DefaultLogger::get()->warn("Collada: Orthographic cameras are not supported.");
+            ASSIMP_LOG_WARN("Collada: Orthographic cameras are not supported.");
         }
         }
 
 
         // now fill our ai data structure
         // now fill our ai data structure
@@ -469,7 +473,7 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
 
 
             if( !srcMesh)
             if( !srcMesh)
             {
             {
-                DefaultLogger::get()->warn( format() << "Collada: Unable to find geometry for ID \"" << mid.mMeshOrController << "\". Skipping." );
+                ASSIMP_LOG_WARN_F( "Collada: Unable to find geometry for ID \"", mid.mMeshOrController, "\". Skipping." );
                 continue;
                 continue;
             }
             }
         } else
         } else
@@ -498,7 +502,8 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
             }
             }
             else
             else
             {
             {
-                DefaultLogger::get()->warn( format() << "Collada: No material specified for subgroup <" << submesh.mMaterial << "> in geometry <" << mid.mMeshOrController << ">." );
+                ASSIMP_LOG_WARN_F( "Collada: No material specified for subgroup <", submesh.mMaterial, "> in geometry <",
+                    mid.mMeshOrController, ">." );
                 if( !mid.mMaterials.empty() )
                 if( !mid.mMaterials.empty() )
                     meshMaterial = mid.mMaterials.begin()->second.mMatName;
                     meshMaterial = mid.mMaterials.begin()->second.mMatName;
             }
             }
@@ -736,10 +741,6 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
     // create bones if given
     // create bones if given
     if( pSrcController && pSrcController->mType == Collada::Skin)
     if( pSrcController && pSrcController->mType == Collada::Skin)
     {
     {
-        // refuse if the vertex count does not match
-//      if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices)
-//          throw DeadlyImportError( "Joint Controller vertex count does not match mesh vertex count");
-
         // resolve references - joint names
         // resolve references - joint names
         const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
         const Collada::Accessor& jointNamesAcc = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, pSrcController->mJointNameSource);
         const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource);
         const Collada::Data& jointNames = pParser.ResolveLibraryReference( pParser.mDataLibrary, jointNamesAcc.mSource);
@@ -871,7 +872,7 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
             if( bnode)
             if( bnode)
                 bone->mName.Set( FindNameForNode( bnode));
                 bone->mName.Set( FindNameForNode( bnode));
             else
             else
-                DefaultLogger::get()->warn( format() << "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"" << bone->mName.data << "\"." );
+                ASSIMP_LOG_WARN_F( "ColladaLoader::CreateMesh(): could not find corresponding node for joint \"", bone->mName.data, "\"." );
 
 
             // and insert bone
             // and insert bone
             dstMesh->mBones[boneCount++] = bone;
             dstMesh->mBones[boneCount++] = bone;
@@ -952,7 +953,7 @@ void ColladaLoader::StoreSceneMaterials( aiScene* pScene)
 // Stores all animations
 // Stores all animations
 void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser)
 void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pParser)
 {
 {
-    // recursivly collect all animations from the collada scene
+    // recursively collect all animations from the collada scene
     StoreAnimations( pScene, pParser, &pParser.mAnims, "");
     StoreAnimations( pScene, pParser, &pParser.mAnims, "");
 
 
     // catch special case: many animations with the same length, each affecting only a single node.
     // catch special case: many animations with the same length, each affecting only a single node.
@@ -967,7 +968,8 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
             for( size_t b = a+1; b < mAnims.size(); ++b)
             for( size_t b = a+1; b < mAnims.size(); ++b)
             {
             {
                 aiAnimation* other = mAnims[b];
                 aiAnimation* other = mAnims[b];
-                if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && other->mTicksPerSecond == templateAnim->mTicksPerSecond )
+                if( other->mNumChannels == 1 && other->mDuration == templateAnim->mDuration && 
+                        other->mTicksPerSecond == templateAnim->mTicksPerSecond )
                     collectedAnimIndices.push_back( b);
                     collectedAnimIndices.push_back( b);
             }
             }
 
 
@@ -1119,6 +1121,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
             continue;
             continue;
 
 
         // now check all channels if they affect the current node
         // now check all channels if they affect the current node
+        std::string targetID, subElement;
         for( std::vector<Collada::AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
         for( std::vector<Collada::AnimationChannel>::const_iterator cit = pSrcAnim->mChannels.begin();
             cit != pSrcAnim->mChannels.end(); ++cit)
             cit != pSrcAnim->mChannels.end(); ++cit)
         {
         {
@@ -1145,7 +1148,9 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
             }
             }
             if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
             if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
                 continue;
                 continue;
-            std::string targetID = srcChannel.mTarget.substr( 0, slashPos);
+
+            targetID.clear();
+            targetID = srcChannel.mTarget.substr( 0, slashPos);
             if( targetID != srcNode->mID)
             if( targetID != srcNode->mID)
                 continue;
                 continue;
 
 
@@ -1158,7 +1163,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
 
 
                 entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1);
                 entry.mTransformId = srcChannel.mTarget.substr( slashPos+1, dotPos - slashPos - 1);
 
 
-                std::string subElement = srcChannel.mTarget.substr( dotPos+1);
+                subElement.clear();
+                subElement = srcChannel.mTarget.substr( dotPos+1);
                 if( subElement == "ANGLE")
                 if( subElement == "ANGLE")
                     entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle
                     entry.mSubElement = 3; // last number in an Axis-Angle-Transform is the angle
                 else if( subElement == "X")
                 else if( subElement == "X")
@@ -1168,9 +1174,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
                 else if( subElement == "Z")
                 else if( subElement == "Z")
                     entry.mSubElement = 2;
                     entry.mSubElement = 2;
                 else
                 else
-                    DefaultLogger::get()->warn( format() << "Unknown anim subelement <" << subElement << ">. Ignoring" );
-            } else
-            {
+                    ASSIMP_LOG_WARN_F( "Unknown anim subelement <", subElement, ">. Ignoring" );
+            } else {
                 // no subelement following, transformId is remaining string
                 // no subelement following, transformId is remaining string
                 entry.mTransformId = srcChannel.mTarget.substr( slashPos+1);
                 entry.mTransformId = srcChannel.mTarget.substr( slashPos+1);
             }
             }
@@ -1179,7 +1184,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
             if (bracketPos != std::string::npos)
             if (bracketPos != std::string::npos)
             {
             {
                 entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1);
                 entry.mTransformId = srcChannel.mTarget.substr(slashPos + 1, bracketPos - slashPos - 1);
-                std::string subElement = srcChannel.mTarget.substr(bracketPos);
+                subElement.clear();
+                subElement = srcChannel.mTarget.substr(bracketPos);
 
 
                 if (subElement == "(0)(0)")
                 if (subElement == "(0)(0)")
                     entry.mSubElement = 0;
                     entry.mSubElement = 0;
@@ -1213,7 +1219,6 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
                     entry.mSubElement = 14;
                     entry.mSubElement = 14;
                 else if (subElement == "(3)(3)")
                 else if (subElement == "(3)(3)")
                     entry.mSubElement = 15;
                     entry.mSubElement = 15;
-
             }
             }
 
 
             // determine which transform step is affected by this channel
             // determine which transform step is affected by this channel
@@ -1399,7 +1404,7 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
               anims.push_back( dstAnim);
               anims.push_back( dstAnim);
         } else
         } else
         {
         {
-          DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
+            ASSIMP_LOG_WARN( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
         }
         }
 
 
         if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 )
         if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 )
@@ -1554,7 +1559,7 @@ void ColladaLoader::AddTexture ( aiMaterial& mat, const ColladaParser& pParser,
             }
             }
         }
         }
         if (-1 == map) {
         if (-1 == map) {
-            DefaultLogger::get()->warn("Collada: unable to determine UV channel for texture");
+            ASSIMP_LOG_WARN("Collada: unable to determine UV channel for texture");
             map = 0;
             map = 0;
         }
         }
     }
     }
@@ -1591,7 +1596,7 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
                 break;
                 break;
 
 
             default:
             default:
-                DefaultLogger::get()->warn("Collada: Unrecognized shading mode, using gouraud shading");
+                ASSIMP_LOG_WARN("Collada: Unrecognized shading mode, using gouraud shading");
                 shadeMode = aiShadingMode_Gouraud;
                 shadeMode = aiShadingMode_Gouraud;
                 break;
                 break;
             }
             }
@@ -1650,9 +1655,10 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
         }
         }
 
 
         // add textures, if given
         // add textures, if given
-        if( !effect.mTexAmbient.mName.empty())
-             /* It is merely a lightmap */
-            AddTexture( mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP);
+        if (!effect.mTexAmbient.mName.empty()) {
+            // It is merely a light-map
+            AddTexture(mat, pParser, effect, effect.mTexAmbient, aiTextureType_LIGHTMAP);
+        }
 
 
         if( !effect.mTexEmissive.mName.empty())
         if( !effect.mTexEmissive.mName.empty())
             AddTexture( mat, pParser, effect, effect.mTexEmissive, aiTextureType_EMISSIVE);
             AddTexture( mat, pParser, effect, effect.mTexEmissive, aiTextureType_EMISSIVE);
@@ -1680,8 +1686,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
 {
 {
     newMats.reserve(pParser.mMaterialLibrary.size());
     newMats.reserve(pParser.mMaterialLibrary.size());
 
 
-    for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); matIt != pParser.mMaterialLibrary.end(); ++matIt)
-    {
+    for( ColladaParser::MaterialLibrary::const_iterator matIt = pParser.mMaterialLibrary.begin(); 
+        matIt != pParser.mMaterialLibrary.end(); ++matIt) {
         const Collada::Material& material = matIt->second;
         const Collada::Material& material = matIt->second;
         // a material is only a reference to an effect
         // a material is only a reference to an effect
         ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find( material.mEffect);
         ColladaParser::EffectLibrary::iterator effIt = pParser.mEffectLibrary.find( material.mEffect);
@@ -1745,11 +1751,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
     ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
     ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
     if( imIt == pParser.mImageLibrary.end())
     if( imIt == pParser.mImageLibrary.end())
     {
     {
-        //missing texture should not stop the conversion
-        //throw DeadlyImportError( format() <<
-        //    "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
-
-        DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\".");
+        ASSIMP_LOG_WARN_F("Collada: Unable to resolve effect texture entry \"", pName, "\", ended up at ID \"", name, "\".");
 
 
         //set default texture file name
         //set default texture file name
         result.Set(name + ".jpg");
         result.Set(name + ".jpg");
@@ -1768,7 +1770,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
 
 
         // setup format hint
         // setup format hint
         if (imIt->second.mEmbeddedFormat.length() > 3) {
         if (imIt->second.mEmbeddedFormat.length() > 3) {
-            DefaultLogger::get()->warn("Collada: texture format hint is too long, truncating to 3 characters");
+            ASSIMP_LOG_WARN("Collada: texture format hint is too long, truncating to 3 characters");
         }
         }
         strncpy(tex->achFormatHint,imIt->second.mEmbeddedFormat.c_str(),3);
         strncpy(tex->achFormatHint,imIt->second.mEmbeddedFormat.c_str(),3);
 
 
@@ -1780,7 +1782,7 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
 
 
         // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
         // TODO: check the possibility of using the flag "AI_CONFIG_IMPORT_FBX_EMBEDDED_TEXTURES_LEGACY_NAMING"
         // In FBX files textures are now stored internally by Assimp with their filename included
         // In FBX files textures are now stored internally by Assimp with their filename included
-        // Now Assimp can lookup thru the loaded textures after all data is processed
+        // Now Assimp can lookup through the loaded textures after all data is processed
         // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
         // We need to load all textures before referencing them, as FBX file format order may reference a texture before loading it
         // This may occur on this case too, it has to be studied
         // This may occur on this case too, it has to be studied
         // setup texture reference string
         // setup texture reference string
@@ -1804,7 +1806,7 @@ void ColladaLoader::ConvertPath (aiString& ss)
 {
 {
     // TODO: collada spec, p 22. Handle URI correctly.
     // TODO: collada spec, p 22. Handle URI correctly.
     // For the moment we're just stripping the file:// away to make it work.
     // For the moment we're just stripping the file:// away to make it work.
-    // Windoes doesn't seem to be able to find stuff like
+    // Windows doesn't seem to be able to find stuff like
     // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg'
     // 'file://..\LWO\LWO2\MappingModes\earthSpherical.jpg'
     if (0 == strncmp(ss.data,"file://",7))
     if (0 == strncmp(ss.data,"file://",7))
     {
     {
@@ -1815,10 +1817,13 @@ void ColladaLoader::ConvertPath (aiString& ss)
 
 
   // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
   // Maxon Cinema Collada Export writes "file:///C:\andsoon" with three slashes...
   // I need to filter it without destroying linux paths starting with "/somewhere"
   // I need to filter it without destroying linux paths starting with "/somewhere"
-  if( ss.data[0] == '/' && isalpha( ss.data[1]) && ss.data[2] == ':' )
-  {
-    ss.length--;
-    memmove( ss.data, ss.data+1, ss.length);
+#if defined( _MSC_VER )
+    if( ss.data[0] == '/' && isalpha( (unsigned char) ss.data[1]) && ss.data[2] == ':' ) {
+#else
+    if (ss.data[ 0 ] == '/' && isalpha( ss.data[ 1 ] ) && ss.data[ 2 ] == ':') {
+#endif
+    --ss.length;
+    ::memmove( ss.data, ss.data+1, ss.length);
     ss.data[ss.length] = 0;
     ss.data[ss.length] = 0;
   }
   }
 
 
@@ -1868,9 +1873,9 @@ const std::string& ColladaLoader::ReadString( const Collada::Accessor& pAccessor
 void ColladaLoader::CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const
 void ColladaLoader::CollectNodes( const aiNode* pNode, std::vector<const aiNode*>& poNodes) const
 {
 {
     poNodes.push_back( pNode);
     poNodes.push_back( pNode);
-
-    for( size_t a = 0; a < pNode->mNumChildren; ++a)
-        CollectNodes( pNode->mChildren[a], poNodes);
+    for (size_t a = 0; a < pNode->mNumChildren; ++a) {
+        CollectNodes(pNode->mChildren[a], poNodes);
+    }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -1912,6 +1917,11 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c
 // The name must be unique for proper node-bone association.
 // The name must be unique for proper node-bone association.
 std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
 std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
 {
 {
+    // If explicitly requested, just use the collada name.
+    if (useColladaName) {
+        return pNode->mName;
+    }
+
     // Now setup the name of the assimp node. The collada name might not be
     // Now setup the name of the assimp node. The collada name might not be
     // unique, so we use the collada ID.
     // unique, so we use the collada ID.
     if (!pNode->mID.empty())
     if (!pNode->mID.empty())

+ 3 - 1
code/ColladaLoader.h

@@ -4,7 +4,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -247,6 +248,7 @@ protected:
 
 
     bool noSkeletonMesh;
     bool noSkeletonMesh;
     bool ignoreUpDirection;
     bool ignoreUpDirection;
+    bool useColladaName;
 
 
     /** Used by FindNameForNode() to generate unique node names */
     /** Used by FindNameForNode() to generate unique node names */
     unsigned int mNodeNameCounter;
     unsigned int mNodeNameCounter;

+ 45 - 29
code/ColladaParser.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -67,7 +68,7 @@ using namespace Assimp::Formatter;
 // Constructor to be privately used by Importer
 // Constructor to be privately used by Importer
 ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
 ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
     : mFileName( pFile )
     : mFileName( pFile )
-    , mReader( NULL )
+    , mReader( nullptr )
     , mDataLibrary()
     , mDataLibrary()
     , mAccessorLibrary()
     , mAccessorLibrary()
     , mMeshLibrary()
     , mMeshLibrary()
@@ -78,20 +79,20 @@ ColladaParser::ColladaParser( IOSystem* pIOHandler, const std::string& pFile)
     , mLightLibrary()
     , mLightLibrary()
     , mCameraLibrary()
     , mCameraLibrary()
     , mControllerLibrary()
     , mControllerLibrary()
-    , mRootNode( NULL )
+    , mRootNode( nullptr )
     , mAnims()
     , mAnims()
     , mUnitSize( 1.0f )
     , mUnitSize( 1.0f )
     , mUpDirection( UP_Y )
     , mUpDirection( UP_Y )
     , mFormat(FV_1_5_n )    // We assume the newest file format by default
     , mFormat(FV_1_5_n )    // We assume the newest file format by default
 {
 {
     // validate io-handler instance
     // validate io-handler instance
-    if ( NULL == pIOHandler ) {
+    if (nullptr == pIOHandler ) {
         throw DeadlyImportError("IOSystem is NULL." );
         throw DeadlyImportError("IOSystem is NULL." );
     }
     }
 
 
     // open the file
     // open the file
     std::unique_ptr<IOStream> file( pIOHandler->Open(pFile ) );
     std::unique_ptr<IOStream> file( pIOHandler->Open(pFile ) );
-    if (file.get() == NULL) {
+    if (file.get() == nullptr) {
         throw DeadlyImportError( "Failed to open file " + pFile + "." );
         throw DeadlyImportError( "Failed to open file " + pFile + "." );
     }
     }
 
 
@@ -151,22 +152,22 @@ void ColladaParser::ReadContents()
 
 
                     if (!::strncmp(version,"1.5",3)) {
                     if (!::strncmp(version,"1.5",3)) {
                         mFormat =  FV_1_5_n;
                         mFormat =  FV_1_5_n;
-                        DefaultLogger::get()->debug("Collada schema version is 1.5.n");
+                        ASSIMP_LOG_DEBUG("Collada schema version is 1.5.n");
                     }
                     }
                     else if (!::strncmp(version,"1.4",3)) {
                     else if (!::strncmp(version,"1.4",3)) {
                         mFormat =  FV_1_4_n;
                         mFormat =  FV_1_4_n;
-                        DefaultLogger::get()->debug("Collada schema version is 1.4.n");
+                        ASSIMP_LOG_DEBUG("Collada schema version is 1.4.n");
                     }
                     }
                     else if (!::strncmp(version,"1.3",3)) {
                     else if (!::strncmp(version,"1.3",3)) {
                         mFormat =  FV_1_3_n;
                         mFormat =  FV_1_3_n;
-                        DefaultLogger::get()->debug("Collada schema version is 1.3.n");
+                        ASSIMP_LOG_DEBUG("Collada schema version is 1.3.n");
                     }
                     }
                 }
                 }
 
 
                 ReadStructure();
                 ReadStructure();
             } else
             } else
             {
             {
-                DefaultLogger::get()->debug( format() << "Ignoring global element <" << mReader->getNodeName() << ">." );
+                ASSIMP_LOG_DEBUG_F( "Ignoring global element <", mReader->getNodeName(), ">." );
                 SkipElement();
                 SkipElement();
             }
             }
         } else
         } else
@@ -221,6 +222,7 @@ void ColladaParser::ReadStructure()
     }
     }
 
 
 	PostProcessRootAnimations();
 	PostProcessRootAnimations();
+    PostProcessControllers();
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -359,6 +361,21 @@ void ColladaParser::ReadAnimationClipLibrary()
 	}
 	}
 }
 }
 
 
+void ColladaParser::PostProcessControllers()
+{
+    std::string meshId;
+    for (ControllerLibrary::iterator it = mControllerLibrary.begin(); it != mControllerLibrary.end(); ++it) {
+        meshId = it->second.mMeshId;
+        ControllerLibrary::iterator findItr = mControllerLibrary.find(meshId);
+        while(findItr != mControllerLibrary.end()) {
+            meshId = findItr->second.mMeshId;
+            findItr = mControllerLibrary.find(meshId);
+        }
+    
+        it->second.mMeshId = meshId;
+    }
+}
+
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Re-build animations from animation clip library, if present, otherwise combine single-channel animations
 // Re-build animations from animation clip library, if present, otherwise combine single-channel animations
 void ColladaParser::PostProcessRootAnimations()
 void ColladaParser::PostProcessRootAnimations()
@@ -967,13 +984,13 @@ void ColladaParser::ReadImage( Collada::Image& pImage)
                     // they're not skipped.
                     // they're not skipped.
                     int attrib = TestAttribute("array_index");
                     int attrib = TestAttribute("array_index");
                     if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
                     if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
-                        DefaultLogger::get()->warn("Collada: Ignoring texture array index");
+                        ASSIMP_LOG_WARN("Collada: Ignoring texture array index");
                         continue;
                         continue;
                     }
                     }
 
 
                     attrib = TestAttribute("mip_index");
                     attrib = TestAttribute("mip_index");
                     if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
                     if (attrib != -1 && mReader->getAttributeValueAsInt(attrib) > 0) {
-                        DefaultLogger::get()->warn("Collada: Ignoring MIP map layer");
+                        ASSIMP_LOG_WARN("Collada: Ignoring MIP map layer");
                         continue;
                         continue;
                     }
                     }
 
 
@@ -994,7 +1011,7 @@ void ColladaParser::ReadImage( Collada::Image& pImage)
                     // embedded image. get format
                     // embedded image. get format
                     const int attrib = TestAttribute("format");
                     const int attrib = TestAttribute("format");
                     if (-1 == attrib)
                     if (-1 == attrib)
-                        DefaultLogger::get()->warn("Collada: Unknown image file format");
+                        ASSIMP_LOG_WARN("Collada: Unknown image file format");
                     else pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib);
                     else pImage.mEmbeddedFormat = mReader->getAttributeValue(attrib);
 
 
                     const char* data = GetTextContent();
                     const char* data = GetTextContent();
@@ -1573,7 +1590,7 @@ void ColladaParser::ReadSamplerProperties( Sampler& out )
                     out.mOp = aiTextureOp_Multiply;
                     out.mOp = aiTextureOp_Multiply;
 
 
                 else  {
                 else  {
-                    DefaultLogger::get()->warn("Collada: Unsupported MAYA texture blend mode");
+                    ASSIMP_LOG_WARN("Collada: Unsupported MAYA texture blend mode");
                 }
                 }
                 TestClosing( "blend_mode");
                 TestClosing( "blend_mode");
             }
             }
@@ -2524,7 +2541,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
             if( pInput.mIndex == 0)
             if( pInput.mIndex == 0)
                 pMesh->mPositions.push_back( aiVector3D( obj[0], obj[1], obj[2]));
                 pMesh->mPositions.push_back( aiVector3D( obj[0], obj[1], obj[2]));
             else
             else
-                DefaultLogger::get()->error("Collada: just one vertex position stream supported");
+                ASSIMP_LOG_ERROR("Collada: just one vertex position stream supported");
             break;
             break;
         case IT_Normal:
         case IT_Normal:
             // pad to current vertex count if necessary
             // pad to current vertex count if necessary
@@ -2535,7 +2552,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
             if( pInput.mIndex == 0)
             if( pInput.mIndex == 0)
                 pMesh->mNormals.push_back( aiVector3D( obj[0], obj[1], obj[2]));
                 pMesh->mNormals.push_back( aiVector3D( obj[0], obj[1], obj[2]));
             else
             else
-                DefaultLogger::get()->error("Collada: just one vertex normal stream supported");
+                ASSIMP_LOG_ERROR("Collada: just one vertex normal stream supported");
             break;
             break;
         case IT_Tangent:
         case IT_Tangent:
             // pad to current vertex count if necessary
             // pad to current vertex count if necessary
@@ -2546,7 +2563,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
             if( pInput.mIndex == 0)
             if( pInput.mIndex == 0)
                 pMesh->mTangents.push_back( aiVector3D( obj[0], obj[1], obj[2]));
                 pMesh->mTangents.push_back( aiVector3D( obj[0], obj[1], obj[2]));
             else
             else
-                DefaultLogger::get()->error("Collada: just one vertex tangent stream supported");
+                ASSIMP_LOG_ERROR("Collada: just one vertex tangent stream supported");
             break;
             break;
         case IT_Bitangent:
         case IT_Bitangent:
             // pad to current vertex count if necessary
             // pad to current vertex count if necessary
@@ -2557,7 +2574,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
             if( pInput.mIndex == 0)
             if( pInput.mIndex == 0)
                 pMesh->mBitangents.push_back( aiVector3D( obj[0], obj[1], obj[2]));
                 pMesh->mBitangents.push_back( aiVector3D( obj[0], obj[1], obj[2]));
             else
             else
-                DefaultLogger::get()->error("Collada: just one vertex bitangent stream supported");
+                ASSIMP_LOG_ERROR("Collada: just one vertex bitangent stream supported");
             break;
             break;
         case IT_Texcoord:
         case IT_Texcoord:
             // up to 4 texture coord sets are fine, ignore the others
             // up to 4 texture coord sets are fine, ignore the others
@@ -2573,7 +2590,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
                     pMesh->mNumUVComponents[pInput.mIndex]=3;
                     pMesh->mNumUVComponents[pInput.mIndex]=3;
             }   else
             }   else
             {
             {
-                DefaultLogger::get()->error("Collada: too many texture coordinate sets. Skipping.");
+                ASSIMP_LOG_ERROR("Collada: too many texture coordinate sets. Skipping.");
             }
             }
             break;
             break;
         case IT_Color:
         case IT_Color:
@@ -2593,7 +2610,7 @@ void ColladaParser::ExtractDataObjectFromChannel( const InputChannel& pInput, si
                 pMesh->mColors[pInput.mIndex].push_back(result);
                 pMesh->mColors[pInput.mIndex].push_back(result);
             } else
             } else
             {
             {
-                DefaultLogger::get()->error("Collada: too many vertex color sets. Skipping.");
+                ASSIMP_LOG_ERROR("Collada: too many vertex color sets. Skipping.");
             }
             }
 
 
             break;
             break;
@@ -2722,7 +2739,7 @@ void ColladaParser::ReadSceneNode( Node* pNode)
                 {
                 {
                     const char* s = mReader->getAttributeValue(attrId);
                     const char* s = mReader->getAttributeValue(attrId);
                     if (s[0] != '#')
                     if (s[0] != '#')
-                        DefaultLogger::get()->error("Collada: Unresolved reference format of camera");
+                        ASSIMP_LOG_ERROR("Collada: Unresolved reference format of camera");
                     else
                     else
                         pNode->mPrimaryCamera = s+1;
                         pNode->mPrimaryCamera = s+1;
                 }
                 }
@@ -2735,7 +2752,7 @@ void ColladaParser::ReadSceneNode( Node* pNode)
                 {
                 {
                     const char* s = mReader->getAttributeValue(attrID);
                     const char* s = mReader->getAttributeValue(attrID);
                     if (s[0] != '#')
                     if (s[0] != '#')
-                        DefaultLogger::get()->error("Collada: Unresolved reference format of node");
+                        ASSIMP_LOG_ERROR("Collada: Unresolved reference format of node");
                     else
                     else
                     {
                     {
                         pNode->mNodeInstances.push_back(NodeInstance());
                         pNode->mNodeInstances.push_back(NodeInstance());
@@ -2753,7 +2770,7 @@ void ColladaParser::ReadSceneNode( Node* pNode)
                 // Reference to a light, name given in 'url' attribute
                 // Reference to a light, name given in 'url' attribute
                 int attrID = TestAttribute("url");
                 int attrID = TestAttribute("url");
                 if (-1 == attrID)
                 if (-1 == attrID)
-                    DefaultLogger::get()->warn("Collada: Expected url attribute in <instance_light> element");
+                    ASSIMP_LOG_WARN("Collada: Expected url attribute in <instance_light> element");
                 else
                 else
                 {
                 {
                     const char* url = mReader->getAttributeValue( attrID);
                     const char* url = mReader->getAttributeValue( attrID);
@@ -2769,7 +2786,7 @@ void ColladaParser::ReadSceneNode( Node* pNode)
                 // Reference to a camera, name given in 'url' attribute
                 // Reference to a camera, name given in 'url' attribute
                 int attrID = TestAttribute("url");
                 int attrID = TestAttribute("url");
                 if (-1 == attrID)
                 if (-1 == attrID)
-                    DefaultLogger::get()->warn("Collada: Expected url attribute in <instance_camera> element");
+                    ASSIMP_LOG_WARN("Collada: Expected url attribute in <instance_camera> element");
                 else
                 else
                 {
                 {
                     const char* url = mReader->getAttributeValue( attrID);
                     const char* url = mReader->getAttributeValue( attrID);
@@ -2856,7 +2873,7 @@ void ColladaParser::ReadMaterialVertexInputBinding( Collada::SemanticMappingTabl
                 tbl.mMap[s] = vn;
                 tbl.mMap[s] = vn;
             }
             }
             else if( IsElement( "bind")) {
             else if( IsElement( "bind")) {
-                DefaultLogger::get()->warn("Collada: Found unsupported <bind> element");
+                ASSIMP_LOG_WARN("Collada: Found unsupported <bind> element");
             }
             }
         }
         }
         else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)    {
         else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END)    {
@@ -2975,10 +2992,9 @@ void ColladaParser::ReportWarning(const char* msg,...)
     ai_assert(iLen > 0);
     ai_assert(iLen > 0);
 
 
     va_end(args);
     va_end(args);
-    DefaultLogger::get()->warn("Validation warning: " + std::string(szBuffer,iLen));
+    ASSIMP_LOG_WARN_F("Validation warning: ", std::string(szBuffer,iLen));
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Skips all data until the end node of the current element
 // Skips all data until the end node of the current element
 void ColladaParser::SkipElement()
 void ColladaParser::SkipElement()
@@ -3089,7 +3105,7 @@ const char* ColladaParser::TestTextContent()
     // read contents of the element
     // read contents of the element
     if( !mReader->read() )
     if( !mReader->read() )
         return NULL;
         return NULL;
-    if( mReader->getNodeType() != irr::io::EXN_TEXT)
+    if( mReader->getNodeType() != irr::io::EXN_TEXT && mReader->getNodeType() != irr::io::EXN_CDATA)
         return NULL;
         return NULL;
 
 
     // skip leading whitespace
     // skip leading whitespace
@@ -3173,7 +3189,7 @@ aiMatrix4x4 ColladaParser::CalculateResultTransform( const std::vector<Transform
 Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& semantic)
 Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& semantic)
 {
 {
     if ( semantic.empty() ) {
     if ( semantic.empty() ) {
-        DefaultLogger::get()->warn( format() << "Vertex input type is empty." );
+        ASSIMP_LOG_WARN("Vertex input type is empty." );
         return IT_Invalid;
         return IT_Invalid;
     }
     }
 
 
@@ -3192,7 +3208,7 @@ Collada::InputType ColladaParser::GetTypeForSemantic( const std::string& semanti
     else if( semantic == "TANGENT" || semantic == "TEXTANGENT")
     else if( semantic == "TANGENT" || semantic == "TEXTANGENT")
         return IT_Tangent;
         return IT_Tangent;
 
 
-    DefaultLogger::get()->warn( format() << "Unknown vertex input type \"" << semantic << "\". Ignoring." );
+    ASSIMP_LOG_WARN_F( "Unknown vertex input type \"", semantic, "\". Ignoring." );
     return IT_Invalid;
     return IT_Invalid;
 }
 }
 
 

+ 5 - 1
code/ColladaParser.h

@@ -2,7 +2,8 @@
  Open Asset Import Library (assimp)
  Open Asset Import Library (assimp)
  ----------------------------------------------------------------------
  ----------------------------------------------------------------------
 
 
- Copyright (c) 2006-2017, assimp team
+ Copyright (c) 2006-2018, assimp team
+
 
 
  All rights reserved.
  All rights reserved.
 
 
@@ -86,6 +87,9 @@ namespace Assimp
 		/** Reads the animation clip library */
 		/** Reads the animation clip library */
 		void ReadAnimationClipLibrary();
 		void ReadAnimationClipLibrary();
 
 
+        /** Unwrap controllers dependency hierarchy */
+        void PostProcessControllers();
+    
 		/** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */
 		/** Re-build animations from animation clip library, if present, otherwise combine single-channel animations */
 		void PostProcessRootAnimations();
 		void PostProcessRootAnimations();
 
 

+ 8 - 7
code/ComputeUVMappingProcess.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -98,7 +99,7 @@ inline unsigned int FindEmptyUVChannel (aiMesh* mesh)
     for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
     for (unsigned int m = 0; m < AI_MAX_NUMBER_OF_TEXTURECOORDS;++m)
         if (!mesh->mTextureCoords[m])return m;
         if (!mesh->mTextureCoords[m])return m;
 
 
-    DefaultLogger::get()->error("Unable to compute UV coordinates, no free UV slot found");
+    ASSIMP_LOG_ERROR("Unable to compute UV coordinates, no free UV slot found");
     return UINT_MAX;
     return UINT_MAX;
 }
 }
 
 
@@ -383,13 +384,13 @@ void ComputeUVMappingProcess::ComputePlaneMapping(aiMesh* mesh,const aiVector3D&
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
 void ComputeUVMappingProcess::ComputeBoxMapping( aiMesh*, aiVector3D* )
 {
 {
-    DefaultLogger::get()->error("Mapping type currently not implemented");
+    ASSIMP_LOG_ERROR("Mapping type currently not implemented");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void ComputeUVMappingProcess::Execute( aiScene* pScene)
 void ComputeUVMappingProcess::Execute( aiScene* pScene)
 {
 {
-    DefaultLogger::get()->debug("GenUVCoordsProcess begin");
+    ASSIMP_LOG_DEBUG("GenUVCoordsProcess begin");
     char buffer[1024];
     char buffer[1024];
 
 
     if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
     if (pScene->mFlags & AI_SCENE_FLAGS_NON_VERBOSE_FORMAT)
@@ -417,7 +418,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
                             TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
                             TextureTypeToString((aiTextureType)prop->mSemantic),prop->mIndex,
                             MappingTypeToString(mapping));
                             MappingTypeToString(mapping));
 
 
-                        DefaultLogger::get()->info(buffer);
+                        ASSIMP_LOG_INFO(buffer);
                     }
                     }
 
 
                     if (aiTextureMapping_OTHER == mapping)
                     if (aiTextureMapping_OTHER == mapping)
@@ -484,7 +485,7 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
                             }
                             }
                             if (m && idx != outIdx)
                             if (m && idx != outIdx)
                             {
                             {
-                                DefaultLogger::get()->warn("UV index mismatch. Not all meshes assigned to "
+                                ASSIMP_LOG_WARN("UV index mismatch. Not all meshes assigned to "
                                     "this material have equal numbers of UV channels. The UV index stored in  "
                                     "this material have equal numbers of UV channels. The UV index stored in  "
                                     "the material structure does therefore not apply for all meshes. ");
                                     "the material structure does therefore not apply for all meshes. ");
                             }
                             }
@@ -501,5 +502,5 @@ void ComputeUVMappingProcess::Execute( aiScene* pScene)
             }
             }
         }
         }
     }
     }
-    DefaultLogger::get()->debug("GenUVCoordsProcess finished");
+    ASSIMP_LOG_DEBUG("GenUVCoordsProcess finished");
 }
 }

+ 2 - 1
code/ComputeUVMappingProcess.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 26 - 17
code/ConvertToLHProcess.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -84,18 +85,20 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene)
 {
 {
     // Check for an existent root node to proceed
     // Check for an existent root node to proceed
     ai_assert(pScene->mRootNode != NULL);
     ai_assert(pScene->mRootNode != NULL);
-    DefaultLogger::get()->debug("MakeLeftHandedProcess begin");
+    ASSIMP_LOG_DEBUG("MakeLeftHandedProcess begin");
 
 
     // recursively convert all the nodes
     // recursively convert all the nodes
     ProcessNode( pScene->mRootNode, aiMatrix4x4());
     ProcessNode( pScene->mRootNode, aiMatrix4x4());
 
 
     // process the meshes accordingly
     // process the meshes accordingly
-    for( unsigned int a = 0; a < pScene->mNumMeshes; ++a)
-        ProcessMesh( pScene->mMeshes[a]);
+    for ( unsigned int a = 0; a < pScene->mNumMeshes; ++a ) {
+        ProcessMesh( pScene->mMeshes[ a ] );
+    }
 
 
     // process the materials accordingly
     // process the materials accordingly
-    for( unsigned int a = 0; a < pScene->mNumMaterials; ++a)
-        ProcessMaterial( pScene->mMaterials[a]);
+    for ( unsigned int a = 0; a < pScene->mNumMaterials; ++a ) {
+        ProcessMaterial( pScene->mMaterials[ a ] );
+    }
 
 
     // transform all animation channels as well
     // transform all animation channels as well
     for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
     for( unsigned int a = 0; a < pScene->mNumAnimations; a++)
@@ -107,7 +110,7 @@ void MakeLeftHandedProcess::Execute( aiScene* pScene)
             ProcessAnimation( nodeAnim);
             ProcessAnimation( nodeAnim);
         }
         }
     }
     }
-    DefaultLogger::get()->debug("MakeLeftHandedProcess finished");
+    ASSIMP_LOG_DEBUG("MakeLeftHandedProcess finished");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -135,8 +138,11 @@ void MakeLeftHandedProcess::ProcessNode( aiNode* pNode, const aiMatrix4x4& pPare
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Converts a single mesh to left handed coordinates.
 // Converts a single mesh to left handed coordinates.
-void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh)
-{
+void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh) {
+    if ( nullptr == pMesh ) {
+        ASSIMP_LOG_ERROR( "Nullptr to mesh found." );
+        return;
+    }
     // mirror positions, normals and stuff along the Z axis
     // mirror positions, normals and stuff along the Z axis
     for( size_t a = 0; a < pMesh->mNumVertices; ++a)
     for( size_t a = 0; a < pMesh->mNumVertices; ++a)
     {
     {
@@ -172,8 +178,12 @@ void MakeLeftHandedProcess::ProcessMesh( aiMesh* pMesh)
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Converts a single material to left handed coordinates.
 // Converts a single material to left handed coordinates.
-void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat)
-{
+void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat) {
+    if ( nullptr == _mat ) {
+        ASSIMP_LOG_ERROR( "Nullptr to aiMaterial found." );
+        return;
+    }
+
     aiMaterial* mat = (aiMaterial*)_mat;
     aiMaterial* mat = (aiMaterial*)_mat;
     for (unsigned int a = 0; a < mat->mNumProperties;++a)   {
     for (unsigned int a = 0; a < mat->mNumProperties;++a)   {
         aiMaterialProperty* prop = mat->mProperties[a];
         aiMaterialProperty* prop = mat->mProperties[a];
@@ -182,7 +192,6 @@ void MakeLeftHandedProcess::ProcessMaterial( aiMaterial* _mat)
         if (!::strcmp( prop->mKey.data, "$tex.mapaxis"))    {
         if (!::strcmp( prop->mKey.data, "$tex.mapaxis"))    {
             ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
             ai_assert( prop->mDataLength >= sizeof(aiVector3D)); /* something is wrong with the validation if we end up here */
             aiVector3D* pff = (aiVector3D*)prop->mData;
             aiVector3D* pff = (aiVector3D*)prop->mData;
-
             pff->z *= -1.f;
             pff->z *= -1.f;
         }
         }
     }
     }
@@ -236,13 +245,13 @@ bool FlipUVsProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 // Executes the post processing step on the given imported data.
 void FlipUVsProcess::Execute( aiScene* pScene)
 void FlipUVsProcess::Execute( aiScene* pScene)
 {
 {
-    DefaultLogger::get()->debug("FlipUVsProcess begin");
+    ASSIMP_LOG_DEBUG("FlipUVsProcess begin");
     for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
     for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
         ProcessMesh(pScene->mMeshes[i]);
         ProcessMesh(pScene->mMeshes[i]);
 
 
     for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
     for (unsigned int i = 0; i < pScene->mNumMaterials;++i)
         ProcessMaterial(pScene->mMaterials[i]);
         ProcessMaterial(pScene->mMaterials[i]);
-    DefaultLogger::get()->debug("FlipUVsProcess finished");
+    ASSIMP_LOG_DEBUG("FlipUVsProcess finished");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -253,7 +262,7 @@ void FlipUVsProcess::ProcessMaterial (aiMaterial* _mat)
     for (unsigned int a = 0; a < mat->mNumProperties;++a)   {
     for (unsigned int a = 0; a < mat->mNumProperties;++a)   {
         aiMaterialProperty* prop = mat->mProperties[a];
         aiMaterialProperty* prop = mat->mProperties[a];
         if( !prop ) {
         if( !prop ) {
-            DefaultLogger::get()->debug( "Property is null" );
+            ASSIMP_LOG_DEBUG( "Property is null" );
             continue;
             continue;
         }
         }
 
 
@@ -310,10 +319,10 @@ bool FlipWindingOrderProcess::IsActive( unsigned int pFlags) const
 // Executes the post processing step on the given imported data.
 // Executes the post processing step on the given imported data.
 void FlipWindingOrderProcess::Execute( aiScene* pScene)
 void FlipWindingOrderProcess::Execute( aiScene* pScene)
 {
 {
-    DefaultLogger::get()->debug("FlipWindingOrderProcess begin");
+    ASSIMP_LOG_DEBUG("FlipWindingOrderProcess begin");
     for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
     for (unsigned int i = 0; i < pScene->mNumMeshes;++i)
         ProcessMesh(pScene->mMeshes[i]);
         ProcessMesh(pScene->mMeshes[i]);
-    DefaultLogger::get()->debug("FlipWindingOrderProcess finished");
+    ASSIMP_LOG_DEBUG("FlipWindingOrderProcess finished");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------

+ 2 - 1
code/ConvertToLHProcess.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 77 - 7
code/D3MFExporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -48,8 +49,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOStream.hpp>
 #include <assimp/IOStream.hpp>
 #include <assimp/Exporter.hpp>
 #include <assimp/Exporter.hpp>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/DefaultLogger.hpp>
-
+#include <assimp/StringUtils.h>
 #include <assimp/Exceptional.h>
 #include <assimp/Exceptional.h>
+
 #include "3MFXmlTags.h"
 #include "3MFXmlTags.h"
 #include "D3MFOpcPackage.h"
 #include "D3MFOpcPackage.h"
 
 
@@ -115,6 +117,7 @@ bool D3MFExporter::exportArchive( const char *file ) {
     if ( nullptr == m_zipArchive ) {
     if ( nullptr == m_zipArchive ) {
         return false;
         return false;
     }
     }
+
     ok |= exportContentTypes();
     ok |= exportContentTypes();
     ok |= export3DModel();
     ok |= export3DModel();
     ok |= exportRelations();
     ok |= exportRelations();
@@ -125,7 +128,6 @@ bool D3MFExporter::exportArchive( const char *file ) {
     return ok;
     return ok;
 }
 }
 
 
-
 bool D3MFExporter::exportContentTypes() {
 bool D3MFExporter::exportContentTypes() {
     mContentOutput.clear();
     mContentOutput.clear();
 
 
@@ -152,7 +154,11 @@ bool D3MFExporter::exportRelations() {
     mRelOutput << "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">";
     mRelOutput << "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">";
 
 
     for ( size_t i = 0; i < mRelations.size(); ++i ) {
     for ( size_t i = 0; i < mRelations.size(); ++i ) {
-        mRelOutput << "<Relationship Target=\"/" << mRelations[ i ]->target << "\" ";
+        if ( mRelations[ i ]->target[ 0 ] == '/' ) {
+            mRelOutput << "<Relationship Target=\"" << mRelations[ i ]->target << "\" ";
+        } else {
+            mRelOutput << "<Relationship Target=\"/" << mRelations[ i ]->target << "\" ";
+        }
         mRelOutput << "Id=\"" << mRelations[i]->id << "\" ";
         mRelOutput << "Id=\"" << mRelations[i]->id << "\" ";
         mRelOutput << "Type=\"" << mRelations[ i ]->type << "\" />";
         mRelOutput << "Type=\"" << mRelations[ i ]->type << "\" />";
         mRelOutput << std::endl;
         mRelOutput << std::endl;
@@ -176,6 +182,10 @@ bool D3MFExporter::export3DModel() {
     mModelOutput << "<" << XmlTag::resources << ">";
     mModelOutput << "<" << XmlTag::resources << ">";
     mModelOutput << std::endl;
     mModelOutput << std::endl;
 
 
+    writeMetaData();
+
+    writeBaseMaterials();
+
     writeObjects();
     writeObjects();
 
 
 
 
@@ -202,6 +212,63 @@ void D3MFExporter::writeHeader() {
     mModelOutput << std::endl;
     mModelOutput << std::endl;
 }
 }
 
 
+void D3MFExporter::writeMetaData() {
+    if ( nullptr == mScene->mMetaData ) {
+        return;
+    }
+
+    const unsigned int numMetaEntries( mScene->mMetaData->mNumProperties );
+    if ( 0 == numMetaEntries ) {
+        return;
+    }
+
+	const aiString *key = nullptr;
+    const aiMetadataEntry *entry(nullptr);
+    for ( size_t i = 0; i < numMetaEntries; ++i ) {
+        mScene->mMetaData->Get( i, key, entry );
+        std::string k( key->C_Str() );
+        aiString value;
+        mScene->mMetaData->Get(  k, value );
+        mModelOutput << "<" << XmlTag::meta << " " << XmlTag::meta_name << "=\"" << key->C_Str() << "\">";
+        mModelOutput << value.C_Str();
+        mModelOutput << "</" << XmlTag::meta << ">" << std::endl;
+    }
+}
+
+void D3MFExporter::writeBaseMaterials() {
+    mModelOutput << "<basematerials id=\"1\">\n";
+    std::string strName, hexDiffuseColor , tmp;
+    for ( size_t i = 0; i < mScene->mNumMaterials; ++i ) {
+        aiMaterial *mat = mScene->mMaterials[ i ];
+        aiString name;
+        if ( mat->Get( AI_MATKEY_NAME, name ) != aiReturn_SUCCESS ) {
+            strName = "basemat_" + to_string( i );
+        } else {
+            strName = name.C_Str();
+        }
+        aiColor4D color;
+        if ( mat->Get( AI_MATKEY_COLOR_DIFFUSE, color ) == aiReturn_SUCCESS ) {
+            hexDiffuseColor.clear();
+            tmp.clear();
+            hexDiffuseColor = "#";
+            
+            tmp = DecimalToHexa( color.r );
+            hexDiffuseColor += tmp;
+            tmp = DecimalToHexa( color.g );
+            hexDiffuseColor += tmp;
+            tmp = DecimalToHexa( color.b );
+            hexDiffuseColor += tmp;
+            tmp = DecimalToHexa( color.a );
+            hexDiffuseColor += tmp;
+        } else {
+            hexDiffuseColor = "#FFFFFFFF";
+        }
+
+        mModelOutput << "<base name=\""+strName+"\" "+" displaycolor=\""+hexDiffuseColor+"\" />\n";
+    }
+    mModelOutput << "</basematerials>\n";
+}
+
 void D3MFExporter::writeObjects() {
 void D3MFExporter::writeObjects() {
     if ( nullptr == mScene->mRootNode ) {
     if ( nullptr == mScene->mRootNode ) {
         return;
         return;
@@ -241,7 +308,9 @@ void D3MFExporter::writeMesh( aiMesh *mesh ) {
     }
     }
     mModelOutput << "</" << XmlTag::vertices << ">" << std::endl;
     mModelOutput << "</" << XmlTag::vertices << ">" << std::endl;
 
 
-    writeFaces( mesh );
+    const unsigned int matIdx( mesh->mMaterialIndex );
+
+    writeFaces( mesh, matIdx );
 
 
     mModelOutput << "</" << XmlTag::mesh << ">" << std::endl;
     mModelOutput << "</" << XmlTag::mesh << ">" << std::endl;
 }
 }
@@ -251,7 +320,7 @@ void D3MFExporter::writeVertex( const aiVector3D &pos ) {
     mModelOutput << std::endl;
     mModelOutput << std::endl;
 }
 }
 
 
-void D3MFExporter::writeFaces( aiMesh *mesh ) {
+void D3MFExporter::writeFaces( aiMesh *mesh, unsigned int matIdx ) {
     if ( nullptr == mesh ) {
     if ( nullptr == mesh ) {
         return;
         return;
     }
     }
@@ -263,7 +332,8 @@ void D3MFExporter::writeFaces( aiMesh *mesh ) {
     for ( unsigned int i = 0; i < mesh->mNumFaces; ++i ) {
     for ( unsigned int i = 0; i < mesh->mNumFaces; ++i ) {
         aiFace &currentFace = mesh->mFaces[ i ];
         aiFace &currentFace = mesh->mFaces[ i ];
         mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[ 0 ] << "\" v2=\""
         mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[ 0 ] << "\" v2=\""
-                << currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ] << "\"/>";
+                << currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ]
+                << "\" pid=\"1\" p1=\""+to_string(matIdx)+"\" />";
         mModelOutput << std::endl;
         mModelOutput << std::endl;
     }
     }
     mModelOutput << "</" << XmlTag::triangles << ">";
     mModelOutput << "</" << XmlTag::triangles << ">";

+ 5 - 2
code/D3MFExporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -75,10 +76,12 @@ public:
 
 
 protected:
 protected:
     void writeHeader();
     void writeHeader();
+    void writeMetaData();
+    void writeBaseMaterials();
     void writeObjects();
     void writeObjects();
     void writeMesh( aiMesh *mesh );
     void writeMesh( aiMesh *mesh );
     void writeVertex( const aiVector3D &pos );
     void writeVertex( const aiVector3D &pos );
-    void writeFaces( aiMesh *mesh );
+    void writeFaces( aiMesh *mesh, unsigned int matIdx );
     void writeBuild();
     void writeBuild();
     void exportContentTyp( const std::string &filename );
     void exportContentTyp( const std::string &filename );
     void writeModelToArchive( const std::string &folder, const std::string &modelName );
     void writeModelToArchive( const std::string &folder, const std::string &modelName );

+ 226 - 78
code/D3MFImporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -57,17 +58,27 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <memory>
 #include <memory>
 
 
 #include "D3MFOpcPackage.h"
 #include "D3MFOpcPackage.h"
-#include <contrib/unzip/unzip.h>
+#include <unzip.h>
 #include <assimp/irrXMLWrapper.h>
 #include <assimp/irrXMLWrapper.h>
 #include "3MFXmlTags.h"
 #include "3MFXmlTags.h"
+#include <assimp/fast_atof.h>
+
+#include <iomanip>
 
 
 namespace Assimp {
 namespace Assimp {
 namespace D3MF {
 namespace D3MF {
 
 
 class XmlSerializer {
 class XmlSerializer {
 public:
 public:
+    using MatArray = std::vector<aiMaterial*>;
+    using MatId2MatArray = std::map<unsigned int, std::vector<unsigned int>>;
+
     XmlSerializer(XmlReader* xmlReader)
     XmlSerializer(XmlReader* xmlReader)
-    : xmlReader(xmlReader) {
+    : mMeshes()
+    , mMatArray()
+    , mActiveMatGroup( 99999999 )
+    , mMatId2MatArray()
+    , xmlReader(xmlReader){
 		// empty
 		// empty
     }
     }
 
 
@@ -76,14 +87,24 @@ public:
     }
     }
 
 
     void ImportXml(aiScene* scene) {
     void ImportXml(aiScene* scene) {
+        if ( nullptr == scene ) {
+            return;
+        }
+
         scene->mRootNode = new aiNode();
         scene->mRootNode = new aiNode();
         std::vector<aiNode*> children;
         std::vector<aiNode*> children;
 
 
+        std::string nodeName;
         while(ReadToEndElement(D3MF::XmlTag::model)) {
         while(ReadToEndElement(D3MF::XmlTag::model)) {
-            if(xmlReader->getNodeName() == D3MF::XmlTag::object) {
+            nodeName = xmlReader->getNodeName();
+            if( nodeName == D3MF::XmlTag::object) {
                 children.push_back(ReadObject(scene));
                 children.push_back(ReadObject(scene));
-            } else if(xmlReader->getNodeName() == D3MF::XmlTag::build) {
-
+            } else if( nodeName == D3MF::XmlTag::build) {
+                // 
+            } else if ( nodeName == D3MF::XmlTag::basematerials ) {
+                ReadBaseMaterials();
+            } else if ( nodeName == D3MF::XmlTag::meta ) {
+                ReadMetadata();
             }
             }
         }
         }
 
 
@@ -91,31 +112,47 @@ public:
             scene->mRootNode->mName.Set( "3MF" );
             scene->mRootNode->mName.Set( "3MF" );
         }
         }
 
 
-        scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
+        // import the metadata
+        if ( !mMetaData.empty() ) {
+            const size_t numMeta( mMetaData.size() );
+            scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>( numMeta ) );
+            for ( size_t i = 0; i < numMeta; ++i ) {
+                aiString val( mMetaData[ i ].value );
+                scene->mMetaData->Set(static_cast<unsigned int>( i ), mMetaData[ i ].name, val );
+            }
+        }
+
+        // import the meshes
+        scene->mNumMeshes = static_cast<unsigned int>( mMeshes.size());
         scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
         scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
+        std::copy( mMeshes.begin(), mMeshes.end(), scene->mMeshes);
 
 
-        std::copy(meshes.begin(), meshes.end(), scene->mMeshes);
+        // import the materials
+        scene->mNumMaterials = static_cast<unsigned int>( mMatArray.size() );
+        if ( 0 != scene->mNumMaterials ) {
+            scene->mMaterials = new aiMaterial*[ scene->mNumMaterials ];
+            std::copy( mMatArray.begin(), mMatArray.end(), scene->mMaterials );
+        }
 
 
+        // create the scenegraph
         scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
         scene->mRootNode->mNumChildren = static_cast<unsigned int>(children.size());
         scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
         scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
-
         std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
         std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
     }
     }
 
 
 private:
 private:
-    aiNode* ReadObject(aiScene* scene)
-    {
+    aiNode* ReadObject(aiScene* scene) {
         std::unique_ptr<aiNode> node(new aiNode());
         std::unique_ptr<aiNode> node(new aiNode());
 
 
         std::vector<unsigned long> meshIds;
         std::vector<unsigned long> meshIds;
 
 
         const char *attrib( nullptr );
         const char *attrib( nullptr );
         std::string name, type;
         std::string name, type;
-        attrib = xmlReader->getAttributeValue( D3MF::XmlTag::name.c_str() );
+        attrib = xmlReader->getAttributeValue( D3MF::XmlTag::id.c_str() );
         if ( nullptr != attrib ) {
         if ( nullptr != attrib ) {
             name = attrib;
             name = attrib;
         }
         }
-        attrib = xmlReader->getAttributeValue( D3MF::XmlTag::name.c_str() );
+        attrib = xmlReader->getAttributeValue( D3MF::XmlTag::type.c_str() );
         if ( nullptr != attrib ) {
         if ( nullptr != attrib ) {
             type = attrib;
             type = attrib;
         }
         }
@@ -123,19 +160,16 @@ private:
         node->mParent = scene->mRootNode;
         node->mParent = scene->mRootNode;
         node->mName.Set(name);
         node->mName.Set(name);
 
 
-        size_t meshIdx = meshes.size();
+        size_t meshIdx = mMeshes.size();
 
 
-        while(ReadToEndElement(D3MF::XmlTag::object))
-        {
-            if(xmlReader->getNodeName() == D3MF::XmlTag::mesh)
-            {
+        while(ReadToEndElement(D3MF::XmlTag::object)) {
+            if(xmlReader->getNodeName() == D3MF::XmlTag::mesh) {
                 auto mesh = ReadMesh();
                 auto mesh = ReadMesh();
 
 
                 mesh->mName.Set(name);
                 mesh->mName.Set(name);
-                meshes.push_back(mesh);
+                mMeshes.push_back(mesh);
                 meshIds.push_back(static_cast<unsigned long>(meshIdx));
                 meshIds.push_back(static_cast<unsigned long>(meshIdx));
-                meshIdx++;
-
+                ++meshIdx;
             }
             }
         }
         }
 
 
@@ -146,19 +180,14 @@ private:
         std::copy(meshIds.begin(), meshIds.end(), node->mMeshes);
         std::copy(meshIds.begin(), meshIds.end(), node->mMeshes);
 
 
         return node.release();
         return node.release();
-
     }
     }
 
 
-    aiMesh* ReadMesh() {
+    aiMesh *ReadMesh() {
         aiMesh* mesh = new aiMesh();
         aiMesh* mesh = new aiMesh();
-        while(ReadToEndElement(D3MF::XmlTag::mesh))
-        {
-            if(xmlReader->getNodeName() == D3MF::XmlTag::vertices)
-            {
+        while(ReadToEndElement(D3MF::XmlTag::mesh)) {
+            if(xmlReader->getNodeName() == D3MF::XmlTag::vertices) {
                 ImportVertices(mesh);
                 ImportVertices(mesh);
-            }
-            else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles)
-            {
+            } else if(xmlReader->getNodeName() == D3MF::XmlTag::triangles) {
                 ImportTriangles(mesh);
                 ImportTriangles(mesh);
             }
             }
         }
         }
@@ -166,14 +195,25 @@ private:
         return mesh;
         return mesh;
     }
     }
 
 
-    void ImportVertices(aiMesh* mesh)
-    {
-        std::vector<aiVector3D> vertices;
+    void ReadMetadata() {
+        const std::string name = xmlReader->getAttributeValue( D3MF::XmlTag::meta_name.c_str() );
+        xmlReader->read();
+        const std::string value = xmlReader->getNodeData();
+
+        if ( name.empty() ) {
+            return;
+        }
 
 
-        while(ReadToEndElement(D3MF::XmlTag::vertices))
-        {
-            if(xmlReader->getNodeName() == D3MF::XmlTag::vertex)
-            {
+        MetaEntry entry;
+        entry.name = name;
+        entry.value = value;
+        mMetaData.push_back( entry );
+    }
+
+    void ImportVertices(aiMesh* mesh) {
+        std::vector<aiVector3D> vertices;
+        while(ReadToEndElement(D3MF::XmlTag::vertices)) {
+            if(xmlReader->getNodeName() == D3MF::XmlTag::vertex) {
                 vertices.push_back(ReadVertex());
                 vertices.push_back(ReadVertex());
             }
             }
         }
         }
@@ -181,11 +221,9 @@ private:
         mesh->mVertices = new aiVector3D[mesh->mNumVertices];
         mesh->mVertices = new aiVector3D[mesh->mNumVertices];
 
 
         std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
         std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
-
     }
     }
 
 
-    aiVector3D ReadVertex()
-    {
+    aiVector3D ReadVertex() {
         aiVector3D vertex;
         aiVector3D vertex;
 
 
         vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr);
         vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr);
@@ -195,16 +233,18 @@ private:
         return vertex;
         return vertex;
     }
     }
 
 
-    void ImportTriangles(aiMesh* mesh)
-    {
+    void ImportTriangles(aiMesh* mesh) {
          std::vector<aiFace> faces;
          std::vector<aiFace> faces;
 
 
-
-         while(ReadToEndElement(D3MF::XmlTag::triangles))
-         {
-             if(xmlReader->getNodeName() == D3MF::XmlTag::triangle)
-             {
+         while(ReadToEndElement(D3MF::XmlTag::triangles)) {
+             const std::string nodeName( xmlReader->getNodeName() );
+             if(xmlReader->getNodeName() == D3MF::XmlTag::triangle) {
                  faces.push_back(ReadTriangle());
                  faces.push_back(ReadTriangle());
+                 const char *pidToken( xmlReader->getAttributeValue( D3MF::XmlTag::p1.c_str() ) );
+                 if ( nullptr != pidToken ) {
+                     int matIdx( std::atoi( pidToken ) );
+                     mesh->mMaterialIndex = matIdx;
+                 }
              }
              }
          }
          }
 
 
@@ -215,8 +255,7 @@ private:
         std::copy(faces.begin(), faces.end(), mesh->mFaces);
         std::copy(faces.begin(), faces.end(), mesh->mFaces);
     }
     }
 
 
-    aiFace ReadTriangle()
-    {
+    aiFace ReadTriangle() {
         aiFace face;
         aiFace face;
 
 
         face.mNumIndices = 3;
         face.mNumIndices = 3;
@@ -228,45 +267,150 @@ private:
         return face;
         return face;
     }
     }
 
 
+    void ReadBaseMaterials() {
+        std::vector<unsigned int> MatIdArray;
+        const char *baseMaterialId( xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_id.c_str() ) );
+        if ( nullptr != baseMaterialId ) {
+            unsigned int id = std::atoi( baseMaterialId );
+            const size_t newMatIdx( mMatArray.size() );
+            if ( id != mActiveMatGroup ) {
+                mActiveMatGroup = id;
+                MatId2MatArray::const_iterator it( mMatId2MatArray.find( id ) );
+                if ( mMatId2MatArray.end() == it ) {
+                    MatIdArray.clear();
+                    mMatId2MatArray[ id ] = MatIdArray;
+                } else {
+                    MatIdArray = it->second;
+                }
+            }
+            MatIdArray.push_back( static_cast<unsigned int>( newMatIdx ) );
+            mMatId2MatArray[ mActiveMatGroup ] = MatIdArray;
+        }
+
+        while ( ReadToEndElement( D3MF::XmlTag::basematerials ) ) {
+            mMatArray.push_back( readMaterialDef() );
+        }
+    }
+
+    bool parseColor( const char *color, aiColor4D &diffuse ) {
+        if ( nullptr == color ) {
+            return false;
+        }
+
+        const size_t len( strlen( color ) );
+        if ( 9 != len ) {
+            return false;
+        }
+
+        const char *buf( color );
+        if ( '#' != *buf ) {
+            return false;
+        }
+        ++buf;
+        char comp[ 3 ] = { 0,0,'\0' };
+
+        comp[ 0 ] = *buf;
+        ++buf;
+        comp[ 1 ] = *buf;
+        ++buf;
+        diffuse.r = static_cast<ai_real>( strtol( comp, NULL, 16 ) );
+
+
+        comp[ 0 ] = *buf;
+        ++buf;
+        comp[ 1 ] = *buf;
+        ++buf;
+        diffuse.g = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
+
+        comp[ 0 ] = *buf;
+        ++buf;
+        comp[ 1 ] = *buf;
+        ++buf;
+        diffuse.b = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
+
+        comp[ 0 ] = *buf;
+        ++buf;
+        comp[ 1 ] = *buf;
+        ++buf;
+        diffuse.a = static_cast< ai_real >( strtol( comp, NULL, 16 ) );
+
+        return true;
+    }
+
+    void assignDiffuseColor( aiMaterial *mat ) {
+        const char *color = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_displaycolor.c_str() );
+        aiColor4D diffuse;
+        if ( parseColor( color, diffuse ) ) {
+            mat->AddProperty<aiColor4D>( &diffuse, 1, AI_MATKEY_COLOR_DIFFUSE );
+        }
+
+    }
+    aiMaterial *readMaterialDef() {
+        aiMaterial *mat( nullptr );
+        const char *name( nullptr );
+        const std::string nodeName( xmlReader->getNodeName() );
+        if ( nodeName == D3MF::XmlTag::basematerials_base ) {
+            name = xmlReader->getAttributeValue( D3MF::XmlTag::basematerials_name.c_str() );
+            std::string stdMatName;
+            aiString matName;
+            std::string strId( to_string( mActiveMatGroup ) );
+            stdMatName += "id";
+            stdMatName += strId;
+            stdMatName += "_";
+            if ( nullptr != name ) {
+                stdMatName += std::string( name );
+            } else {
+                stdMatName += "basemat";
+            }
+            matName.Set( stdMatName );
+
+            mat = new aiMaterial;
+            mat->AddProperty( &matName, AI_MATKEY_NAME );
+
+            assignDiffuseColor( mat );
+        }
+
+        return mat;
+    }
+
 private:
 private:
-    bool ReadToStartElement(const std::string& startTag)
-    {
-        while(xmlReader->read())
-        {
-            if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && xmlReader->getNodeName() == startTag)
-            {
+    bool ReadToStartElement(const std::string& startTag) {
+        while(xmlReader->read()) {
+            const std::string &nodeName( xmlReader->getNodeName() );
+            if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT && nodeName == startTag) {
                 return true;
                 return true;
-            }
-            else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END &&
-                     xmlReader->getNodeName() == startTag)
-            {
+            } else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == startTag) {
                 return false;
                 return false;
             }
             }
         }
         }
-        //DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
+
         return false;
         return false;
     }
     }
 
 
-    bool ReadToEndElement(const std::string& closeTag)
-    {
-        while(xmlReader->read())
-        {
+    bool ReadToEndElement(const std::string& closeTag) {
+        while(xmlReader->read()) {
+            const std::string &nodeName( xmlReader->getNodeName() );
             if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) {
             if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT) {
                 return true;
                 return true;
-            }
-            else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END
-                     && xmlReader->getNodeName() == closeTag)
-            {
+            } else if (xmlReader->getNodeType() == irr::io::EXN_ELEMENT_END && nodeName == closeTag) {
                 return false;
                 return false;
             }
             }
         }
         }
-        DefaultLogger::get()->error("unexpected EOF, expected closing <" + closeTag + "> tag");
+        ASSIMP_LOG_ERROR("unexpected EOF, expected closing <" + closeTag + "> tag");
+
         return false;
         return false;
     }
     }
 
 
-
 private:
 private:
-    std::vector<aiMesh*> meshes;
+    struct MetaEntry {
+        std::string name;
+        std::string value;
+    };
+    std::vector<MetaEntry> mMetaData;
+    std::vector<aiMesh*> mMeshes;
+    MatArray mMatArray;
+    unsigned int mActiveMatGroup;
+    MatId2MatArray mMatId2MatArray;
     XmlReader* xmlReader;
     XmlReader* xmlReader;
 };
 };
 
 
@@ -287,7 +431,6 @@ static const aiImporterDesc desc = {
     Extension.c_str()
     Extension.c_str()
 };
 };
 
 
-
 D3MFImporter::D3MFImporter()
 D3MFImporter::D3MFImporter()
 : BaseImporter() {
 : BaseImporter() {
     // empty
     // empty
@@ -297,14 +440,19 @@ D3MFImporter::~D3MFImporter() {
     // empty
     // empty
 }
 }
 
 
-bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
-    const std::string extension = GetExtension(pFile);
+bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const {
+    const std::string extension( GetExtension( filename ) );
     if(extension == Extension ) {
     if(extension == Extension ) {
         return true;
         return true;
     } else if ( !extension.length() || checkSig ) {
     } else if ( !extension.length() || checkSig ) {
-        if (nullptr == pIOHandler ) {
-            return true;
+        if ( nullptr == pIOHandler ) {
+            return false;
+        }
+        if ( !D3MF::D3MFOpcPackage::isZipArchive( pIOHandler, filename ) ) {
+            return false;
         }
         }
+        D3MF::D3MFOpcPackage opcPackage( pIOHandler, filename );
+        return opcPackage.validate();
     }
     }
 
 
     return false;
     return false;
@@ -318,8 +466,8 @@ const aiImporterDesc *D3MFImporter::GetInfo() const {
     return &desc;
     return &desc;
 }
 }
 
 
-void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
-    D3MF::D3MFOpcPackage opcPackage(pIOHandler, pFile);
+void D3MFImporter::InternReadFile( const std::string &filename, aiScene *pScene, IOSystem *pIOHandler ) {
+    D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
 
 
     std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream()));
     std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream()));
     std::unique_ptr<D3MF::XmlReader> xmlReader(irr::io::createIrrXMLReader(xmlStream.get()));
     std::unique_ptr<D3MF::XmlReader> xmlReader(irr::io::createIrrXMLReader(xmlStream.get()));

+ 2 - 1
code/D3MFImporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 43 - 32
code/D3MFOpcPackage.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -55,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <map>
 #include <map>
 #include <algorithm>
 #include <algorithm>
 #include <cassert>
 #include <cassert>
-#include <contrib/unzip/unzip.h>
+#include <unzip.h>
 #include "3MFXmlTags.h"
 #include "3MFXmlTags.h"
 
 
 namespace Assimp {
 namespace Assimp {
@@ -246,13 +247,13 @@ private:
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //  Constructor.
 //  Constructor.
 D3MFZipArchive::D3MFZipArchive(IOSystem* pIOHandler, const std::string& rFile)
 D3MFZipArchive::D3MFZipArchive(IOSystem* pIOHandler, const std::string& rFile)
-: m_ZipFileHandle(NULL)
+: m_ZipFileHandle( nullptr )
 , m_ArchiveMap() {
 , m_ArchiveMap() {
     if (! rFile.empty()) {                
     if (! rFile.empty()) {                
         zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);            
         zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);            
 
 
         m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping);
         m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping);
-        if(m_ZipFileHandle != NULL) {            
+        if(m_ZipFileHandle != nullptr ) {
             mapArchive();
             mapArchive();
         }
         }
     }
     }
@@ -266,32 +267,32 @@ D3MFZipArchive::~D3MFZipArchive() {
     }
     }
     m_ArchiveMap.clear();
     m_ArchiveMap.clear();
 
 
-    if(m_ZipFileHandle != NULL) {
+    if(m_ZipFileHandle != nullptr) {
         unzClose(m_ZipFileHandle);
         unzClose(m_ZipFileHandle);
-        m_ZipFileHandle = NULL;
+        m_ZipFileHandle = nullptr;
     }
     }
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //  Returns true, if the archive is already open.
 //  Returns true, if the archive is already open.
 bool D3MFZipArchive::isOpen() const {
 bool D3MFZipArchive::isOpen() const {
-    return (m_ZipFileHandle != NULL);
+    return (m_ZipFileHandle != nullptr );
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 //  Returns true, if the filename is part of the archive.
 //  Returns true, if the filename is part of the archive.
 bool D3MFZipArchive::Exists(const char* pFile) const {
 bool D3MFZipArchive::Exists(const char* pFile) const {
-    ai_assert(pFile != NULL);
+    ai_assert(pFile != nullptr );
 
 
-    bool exist = false;
-
-    if (pFile != NULL) {
-        std::string rFile(pFile);
-        std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(rFile);
+    if ( pFile == nullptr ) {
+        return false;
+    }
 
 
-        if(it != m_ArchiveMap.end()) {
-            exist = true;
-        }
+    std::string filename(pFile);
+    std::map<std::string, ZipFile*>::const_iterator it = m_ArchiveMap.find(filename);
+    bool exist( false );
+    if(it != m_ArchiveMap.end()) {
+        exist = true;
     }
     }
 
 
     return exist;
     return exist;
@@ -433,8 +434,8 @@ public:
 
 
     std::vector<OpcPackageRelationshipPtr> m_relationShips;
     std::vector<OpcPackageRelationshipPtr> m_relationShips;
 };
 };
-// ------------------------------------------------------------------------------------------------
 
 
+// ------------------------------------------------------------------------------------------------
 D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
 D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
 : mRootStream(nullptr)
 : mRootStream(nullptr)
 , mZipArchive() {    
 , mZipArchive() {    
@@ -459,28 +460,19 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
             if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) {
             if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) {
                 rootFile = rootFile.substr( 1 );
                 rootFile = rootFile.substr( 1 );
                 if ( rootFile[ 0 ] == '/' ) {
                 if ( rootFile[ 0 ] == '/' ) {
-                    // deal with zipbug
+                    // deal with zip-bug
                     rootFile = rootFile.substr( 1 );
                     rootFile = rootFile.substr( 1 );
                 }
                 }
             }
             }
 
 
-            DefaultLogger::get()->debug(rootFile);
+            ASSIMP_LOG_DEBUG(rootFile);
 
 
             mRootStream = mZipArchive->Open(rootFile.c_str());
             mRootStream = mZipArchive->Open(rootFile.c_str());
             ai_assert( mRootStream != nullptr );
             ai_assert( mRootStream != nullptr );
             if ( nullptr == mRootStream ) {
             if ( nullptr == mRootStream ) {
-                throw DeadlyExportError( "Cannot open rootfile in archive : " + rootFile );
+                throw DeadlyExportError( "Cannot open root-file in archive : " + rootFile );
             }
             }
 
 
-        //    const size_t size = zipArchive->FileSize();
-        //    m_Data.resize( size );
-
-        //    const size_t readSize = pMapFile->Read( &m_Data[0], sizeof( char ), size );
-        //    if ( readSize != size )
-        //    {
-        //        m_Data.clear();
-        //        return false;
-        //    }
             mZipArchive->Close( fileStream );
             mZipArchive->Close( fileStream );
 
 
         } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
         } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
@@ -497,6 +489,25 @@ IOStream* D3MFOpcPackage::RootStream() const {
     return mRootStream;
     return mRootStream;
 }
 }
 
 
+static const std::string ModelRef = "3D/3dmodel.model";
+
+bool D3MFOpcPackage::validate() {
+    if ( nullptr == mRootStream || nullptr == mZipArchive ) {
+        return false;
+    }
+
+    return mZipArchive->Exists( ModelRef.c_str() );
+}
+
+bool D3MFOpcPackage::isZipArchive( IOSystem* pIOHandler, const std::string& rFile ) {
+    D3MF::D3MFZipArchive ar( pIOHandler, rFile );
+    if ( !ar.isOpen() ) {
+        return false;
+    }
+
+    return true;
+}
+
 std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
 std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
     std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
     std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(stream));
     std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
     std::unique_ptr<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
@@ -507,14 +518,14 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream* stream) {
         return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
         return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
     });
     });
 
 
-    if(itr == reader.m_relationShips.end())
-        throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
+    if ( itr == reader.m_relationShips.end() ) {
+        throw DeadlyImportError( "Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE );
+    }
 
 
     return (*itr)->target;
     return (*itr)->target;
 }
 }
 
 
 } // Namespace D3MF
 } // Namespace D3MF
-
 } // Namespace Assimp
 } // Namespace Assimp
 
 
 #endif //ASSIMP_BUILD_NO_3MF_IMPORTER
 #endif //ASSIMP_BUILD_NO_3MF_IMPORTER

+ 9 - 6
code/D3MFOpcPackage.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -50,8 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 namespace Assimp {
 namespace Assimp {
 namespace D3MF {
 namespace D3MF {
 
 
-typedef irr::io::IrrXMLReader XmlReader;
-typedef std::shared_ptr<XmlReader> XmlReaderPtr;
+using XmlReader = irr::io::IrrXMLReader ;
+using XmlReaderPtr = std::shared_ptr<XmlReader> ;
 
 
 struct OpcPackageRelationship {
 struct OpcPackageRelationship {
     std::string id;
     std::string id;
@@ -63,9 +64,11 @@ class D3MFZipArchive;
 
 
 class D3MFOpcPackage {
 class D3MFOpcPackage {
 public:
 public:
-    D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile);
+    D3MFOpcPackage( IOSystem* pIOHandler, const std::string& rFile );
     ~D3MFOpcPackage();
     ~D3MFOpcPackage();
     IOStream* RootStream() const;
     IOStream* RootStream() const;
+    bool validate();
+    static bool isZipArchive( IOSystem* pIOHandler, const std::string& rFile );
 
 
 protected:
 protected:
     std::string ReadPackageRootRelationship(IOStream* stream);
     std::string ReadPackageRootRelationship(IOStream* stream);
@@ -75,7 +78,7 @@ private:
     std::unique_ptr<D3MFZipArchive> mZipArchive;
     std::unique_ptr<D3MFZipArchive> mZipArchive;
 };
 };
 
 
-}
-}
+} // Namespace D3MF
+} // Namespace Assimp
 
 
 #endif // D3MFOPCPACKAGE_H
 #endif // D3MFOPCPACKAGE_H

+ 3 - 3
code/DXFHelper.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -145,7 +146,7 @@ public:
                 for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
                 for(;splitter->length() && splitter->at(0) != '}'; splitter++, cnt++);
 
 
                 splitter++;
                 splitter++;
-                DefaultLogger::get()->debug((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
+                ASSIMP_LOG_DEBUG((Formatter::format("DXF: skipped over control group ("),cnt," lines)"));
             }
             }
         } catch(std::logic_error&) {
         } catch(std::logic_error&) {
             ai_assert(!splitter);
             ai_assert(!splitter);
@@ -168,7 +169,6 @@ public:
     }
     }
 
 
 private:
 private:
-
     LineSplitter splitter;
     LineSplitter splitter;
     int groupcode;
     int groupcode;
     std::string value;
     std::string value;

+ 45 - 62
code/DXFLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -118,9 +119,18 @@ DXFImporter::~DXFImporter()
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
 // Returns whether the class can handle the format of the given file.
-bool DXFImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const
-{
-    return SimpleExtensionCheck(pFile,"dxf");
+bool DXFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig ) const {
+    const std::string& extension = GetExtension( pFile );
+    if ( extension == "dxf" ) {
+        return true;
+    }
+
+    if ( extension.empty() || checkSig ) {
+        static const char *pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" };
+        return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 4, 32 );
+    }
+
+    return false;
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -190,7 +200,7 @@ void DXFImporter::InternReadFile( const std::string& pFile,
 
 
         // comments
         // comments
         else if (reader.Is(999)) {
         else if (reader.Is(999)) {
-            DefaultLogger::get()->info("DXF Comment: " + reader.Value());
+            ASSIMP_LOG_INFO_F("DXF Comment: ", reader.Value());
         }
         }
 
 
         // don't read past the official EOF sign
         // don't read past the official EOF sign
@@ -202,7 +212,7 @@ void DXFImporter::InternReadFile( const std::string& pFile,
         ++reader;
         ++reader;
     }
     }
     if (!eof) {
     if (!eof) {
-        DefaultLogger::get()->warn("DXF: EOF reached, but did not encounter DXF EOF marker");
+        ASSIMP_LOG_WARN("DXF: EOF reached, but did not encounter DXF EOF marker");
     }
     }
 
 
     ConvertMeshes(pScene,output);
     ConvertMeshes(pScene,output);
@@ -219,7 +229,7 @@ void DXFImporter::InternReadFile( const std::string& pFile,
 void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output)
 void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output)
 {
 {
     // the process of resolving all the INSERT statements can grow the
     // the process of resolving all the INSERT statements can grow the
-    // polycount excessively, so log the original number.
+    // poly-count excessively, so log the original number.
     // XXX Option to import blocks as separate nodes?
     // XXX Option to import blocks as separate nodes?
     if (!DefaultLogger::isNullLogger()) {
     if (!DefaultLogger::isNullLogger()) {
 
 
@@ -231,16 +241,14 @@ void DXFImporter::ConvertMeshes(aiScene* pScene, DXF::FileData& output)
             }
             }
         }
         }
 
 
-        DefaultLogger::get()->debug((Formatter::format("DXF: Unexpanded polycount is "),
-            icount,", vertex count is ",vcount
-        ));
+        ASSIMP_LOG_DEBUG_F("DXF: Unexpanded polycount is ", icount, ", vertex count is ", vcount);
     }
     }
 
 
     if (! output.blocks.size()  ) {
     if (! output.blocks.size()  ) {
         throw DeadlyImportError("DXF: no data blocks loaded");
         throw DeadlyImportError("DXF: no data blocks loaded");
     }
     }
 
 
-    DXF::Block* entities = 0;
+    DXF::Block* entities( nullptr );
 
 
     // index blocks by name
     // index blocks by name
     DXF::BlockMap blocks_by_name;
     DXF::BlockMap blocks_by_name;
@@ -365,9 +373,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
         // first check if the referenced blocks exists ...
         // first check if the referenced blocks exists ...
         const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name);
         const DXF::BlockMap::const_iterator it = blocks_by_name.find(insert.name);
         if (it == blocks_by_name.end()) {
         if (it == blocks_by_name.end()) {
-            DefaultLogger::get()->error((Formatter::format("DXF: Failed to resolve block reference: "),
-                insert.name,"; skipping"
-            ));
+            ASSIMP_LOG_ERROR_F("DXF: Failed to resolve block reference: ", insert.name,"; skipping" );
             continue;
             continue;
         }
         }
 
 
@@ -387,7 +393,7 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
 
 
                 // XXX rotation currently ignored - I didn't find an appropriate sample model.
                 // XXX rotation currently ignored - I didn't find an appropriate sample model.
                 if (insert.angle != 0.f) {
                 if (insert.angle != 0.f) {
-                    DefaultLogger::get()->warn("DXF: BLOCK rotation not currently implemented");
+                    ASSIMP_LOG_WARN("DXF: BLOCK rotation not currently implemented");
                 }
                 }
 
 
                 for (aiVector3D& v : pl_out->positions) {
                 for (aiVector3D& v : pl_out->positions) {
@@ -400,7 +406,6 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
     }
     }
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/)
 void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/)
 {
 {
@@ -427,7 +432,6 @@ void DXFImporter::GenerateMaterials(aiScene* pScene, DXF::FileData& /*output*/)
     pScene->mMaterials[0] = pcMat;
     pScene->mMaterials[0] = pcMat;
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/)
 void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/)
 {
 {
@@ -438,9 +442,7 @@ void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/)
     if (1 == pScene->mNumMeshes)    {
     if (1 == pScene->mNumMeshes)    {
         pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ];
         pScene->mRootNode->mMeshes = new unsigned int[ pScene->mRootNode->mNumMeshes = 1 ];
         pScene->mRootNode->mMeshes[0] = 0;
         pScene->mRootNode->mMeshes[0] = 0;
-    }
-    else
-    {
+    } else {
         pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ];
         pScene->mRootNode->mChildren = new aiNode*[ pScene->mRootNode->mNumChildren = pScene->mNumMeshes ];
         for (unsigned int m = 0; m < pScene->mRootNode->mNumChildren;++m)   {
         for (unsigned int m = 0; m < pScene->mRootNode->mNumChildren;++m)   {
             aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode();
             aiNode* p = pScene->mRootNode->mChildren[m] = new aiNode();
@@ -455,22 +457,17 @@ void DXFImporter::GenerateHierarchy(aiScene* pScene, DXF::FileData& /*output*/)
 
 
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void DXFImporter::SkipSection(DXF::LineReader& reader)
-{
+void DXFImporter::SkipSection(DXF::LineReader& reader) {
     for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
     for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void DXFImporter::ParseHeader(DXF::LineReader& reader, DXF::FileData& /*output*/)
-{
+void DXFImporter::ParseHeader(DXF::LineReader& reader, DXF::FileData& ) {
     for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
     for( ;!reader.End() && !reader.Is(0,"ENDSEC"); reader++);
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output)
-{
+void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output) {
     while( !reader.End() && !reader.Is(0,"ENDSEC")) {
     while( !reader.End() && !reader.Is(0,"ENDSEC")) {
         if (reader.Is(0,"BLOCK")) {
         if (reader.Is(0,"BLOCK")) {
             ParseBlock(++reader,output);
             ParseBlock(++reader,output);
@@ -479,15 +476,11 @@ void DXFImporter::ParseBlocks(DXF::LineReader& reader, DXF::FileData& output)
         ++reader;
         ++reader;
     }
     }
 
 
-    DefaultLogger::get()->debug((Formatter::format("DXF: got "),
-        output.blocks.size()," entries in BLOCKS"
-    ));
+    ASSIMP_LOG_DEBUG_F("DXF: got ", output.blocks.size()," entries in BLOCKS" );
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output)
-{
+void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output) {
     // push a new block onto the stack.
     // push a new block onto the stack.
     output.blocks.push_back( DXF::Block() );
     output.blocks.push_back( DXF::Block() );
     DXF::Block& block = output.blocks.back();
     DXF::Block& block = output.blocks.back();
@@ -517,7 +510,7 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output)
 
 
         // XXX is this a valid case?
         // XXX is this a valid case?
         if (reader.Is(0,"INSERT")) {
         if (reader.Is(0,"INSERT")) {
-            DefaultLogger::get()->warn("DXF: INSERT within a BLOCK not currently supported; skipping");
+            ASSIMP_LOG_WARN("DXF: INSERT within a BLOCK not currently supported; skipping");
             for( ;!reader.End() && !reader.Is(0,"ENDBLK"); ++reader);
             for( ;!reader.End() && !reader.Is(0,"ENDBLK"); ++reader);
             break;
             break;
         }
         }
@@ -531,7 +524,6 @@ void DXFImporter::ParseBlock(DXF::LineReader& reader, DXF::FileData& output)
     }
     }
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
 void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
 {
 {
@@ -561,19 +553,16 @@ void DXFImporter::ParseEntities(DXF::LineReader& reader, DXF::FileData& output)
         ++reader;
         ++reader;
     }
     }
 
 
-    DefaultLogger::get()->debug((Formatter::format("DXF: got "),
-        block.lines.size()," polylines and ", block.insertions.size() ," inserted blocks in ENTITIES"
-    ));
+    ASSIMP_LOG_DEBUG_F( "DXF: got ", block.lines.size()," polylines and ", block.insertions.size(), 
+        " inserted blocks in ENTITIES" );
 }
 }
 
 
-
 void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output)
 void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output)
 {
 {
     output.blocks.back().insertions.push_back( DXF::InsertBlock() );
     output.blocks.back().insertions.push_back( DXF::InsertBlock() );
     DXF::InsertBlock& bl = output.blocks.back().insertions.back();
     DXF::InsertBlock& bl = output.blocks.back().insertions.back();
 
 
     while( !reader.End() && !reader.Is(0)) {
     while( !reader.End() && !reader.Is(0)) {
-
         switch(reader.GroupCode())
         switch(reader.GroupCode())
         {
         {
             // name of referenced block
             // name of referenced block
@@ -618,8 +607,7 @@ void DXFImporter::ParseInsertion(DXF::LineReader& reader, DXF::FileData& output)
 #define DXF_POLYLINE_FLAG_POLYFACEMESH  0x40
 #define DXF_POLYLINE_FLAG_POLYFACEMESH  0x40
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
-{
+void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output) {
     output.blocks.back().lines.push_back( std::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
     output.blocks.back().lines.push_back( std::shared_ptr<DXF::PolyLine>( new DXF::PolyLine() ) );
     DXF::PolyLine& line = *output.blocks.back().lines.back();
     DXF::PolyLine& line = *output.blocks.back().lines.back();
 
 
@@ -672,16 +660,15 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
     //}
     //}
 
 
     if (vguess && line.positions.size() != vguess) {
     if (vguess && line.positions.size() != vguess) {
-        DefaultLogger::get()->warn((Formatter::format("DXF: unexpected vertex count in polymesh: "),
-            line.positions.size(),", expected ", vguess
-        ));
+        ASSIMP_LOG_WARN_F("DXF: unexpected vertex count in polymesh: ",
+            line.positions.size(),", expected ", vguess );
     }
     }
 
 
     if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH ) {
     if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH ) {
         if (line.positions.size() < 3 || line.indices.size() < 3)   {
         if (line.positions.size() < 3 || line.indices.size() < 3)   {
-                DefaultLogger::get()->warn("DXF: not enough vertices for polymesh; ignoring");
-                output.blocks.back().lines.pop_back();
-                return;
+            ASSIMP_LOG_WARN("DXF: not enough vertices for polymesh; ignoring");
+            output.blocks.back().lines.pop_back();
+            return;
         }
         }
 
 
         // if these numbers are wrong, parsing might have gone wild.
         // if these numbers are wrong, parsing might have gone wild.
@@ -689,13 +676,11 @@ void DXFImporter::ParsePolyLine(DXF::LineReader& reader, DXF::FileData& output)
         // to set the 71 and 72 fields, respectively, to valid values.
         // to set the 71 and 72 fields, respectively, to valid values.
         // So just fire a warning.
         // So just fire a warning.
         if (iguess && line.counts.size() != iguess) {
         if (iguess && line.counts.size() != iguess) {
-            DefaultLogger::get()->warn((Formatter::format("DXF: unexpected face count in polymesh: "),
-                line.counts.size(),", expected ", iguess
-            ));
+            ASSIMP_LOG_WARN_F( "DXF: unexpected face count in polymesh: ", line.counts.size(),", expected ", iguess );
         }
         }
     }
     }
     else if (!line.indices.size() && !line.counts.size()) {
     else if (!line.indices.size() && !line.counts.size()) {
-        // a polyline - so there are no indices yet.
+        // a poly-line - so there are no indices yet.
         size_t guess = line.positions.size() + (line.flags & DXF_POLYLINE_FLAG_CLOSED ? 1 : 0);
         size_t guess = line.positions.size() + (line.flags & DXF_POLYLINE_FLAG_CLOSED ? 1 : 0);
         line.indices.reserve(guess);
         line.indices.reserve(guess);
 
 
@@ -737,10 +722,10 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li
         {
         {
         case 8:
         case 8:
                 // layer to which the vertex belongs to - assume that
                 // layer to which the vertex belongs to - assume that
-                // this is always the layer the top-level polyline
+                // this is always the layer the top-level poly-line
                 // entity resides on as well.
                 // entity resides on as well.
                 if(reader.Value() != line.layer) {
                 if(reader.Value() != line.layer) {
-                    DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
+                    ASSIMP_LOG_WARN("DXF: expected vertex to be part of a poly-face but the 0x128 flag isn't set");
                 }
                 }
                 break;
                 break;
 
 
@@ -759,7 +744,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li
         case 73:
         case 73:
         case 74:
         case 74:
             if (cnti == 4) {
             if (cnti == 4) {
-                DefaultLogger::get()->warn("DXF: more than 4 indices per face not supported; ignoring");
+                ASSIMP_LOG_WARN("DXF: more than 4 indices per face not supported; ignoring");
                 break;
                 break;
             }
             }
             indices[cnti++] = reader.ValueAsUnsignedInt();
             indices[cnti++] = reader.ValueAsUnsignedInt();
@@ -775,7 +760,7 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li
     }
     }
 
 
     if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH && !(flags & DXF_VERTEX_FLAG_PART_OF_POLYFACE)) {
     if (line.flags & DXF_POLYLINE_FLAG_POLYFACEMESH && !(flags & DXF_VERTEX_FLAG_PART_OF_POLYFACE)) {
-        DefaultLogger::get()->warn("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
+        ASSIMP_LOG_WARN("DXF: expected vertex to be part of a polyface but the 0x128 flag isn't set");
     }
     }
 
 
     if (cnti) {
     if (cnti) {
@@ -783,14 +768,13 @@ void DXFImporter::ParsePolyLineVertex(DXF::LineReader& reader, DXF::PolyLine& li
         for (unsigned int i = 0; i < cnti; ++i) {
         for (unsigned int i = 0; i < cnti; ++i) {
             // IMPORTANT NOTE: POLYMESH indices are ONE-BASED
             // IMPORTANT NOTE: POLYMESH indices are ONE-BASED
             if (indices[i] == 0) {
             if (indices[i] == 0) {
-                DefaultLogger::get()->warn("DXF: invalid vertex index, indices are one-based.");
+                ASSIMP_LOG_WARN("DXF: invalid vertex index, indices are one-based.");
                 --line.counts.back();
                 --line.counts.back();
                 continue;
                 continue;
             }
             }
             line.indices.push_back(indices[i]-1);
             line.indices.push_back(indices[i]-1);
         }
         }
-    }
-    else {
+    } else {
         line.positions.push_back(out);
         line.positions.push_back(out);
         line.colors.push_back(clr);
         line.colors.push_back(clr);
     }
     }
@@ -900,7 +884,7 @@ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output)
 
 
     // sanity checks to see if we got something meaningful
     // sanity checks to see if we got something meaningful
     if ((b[1] && !b[0]) || !b[2] || !b[3]) {
     if ((b[1] && !b[0]) || !b[2] || !b[3]) {
-        DefaultLogger::get()->warn("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring");
+        ASSIMP_LOG_WARN("DXF: unexpected vertex setup in 3DFACE/LINE/FACE entity; ignoring");
         output.blocks.back().lines.pop_back();
         output.blocks.back().lines.pop_back();
         return;
         return;
     }
     }
@@ -916,4 +900,3 @@ void DXFImporter::Parse3DFace(DXF::LineReader& reader, DXF::FileData& output)
 }
 }
 
 
 #endif // !! ASSIMP_BUILD_NO_DXF_IMPORTER
 #endif // !! ASSIMP_BUILD_NO_DXF_IMPORTER
-

+ 2 - 1
code/DXFLoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 7 - 8
code/DeboneProcess.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -90,7 +91,7 @@ void DeboneProcess::SetupProperties(const Importer* pImp)
 // Executes the post processing step on the given imported data.
 // Executes the post processing step on the given imported data.
 void DeboneProcess::Execute( aiScene* pScene)
 void DeboneProcess::Execute( aiScene* pScene)
 {
 {
-    DefaultLogger::get()->debug("DeboneProcess begin");
+    ASSIMP_LOG_DEBUG("DeboneProcess begin");
 
 
     if(!pScene->mNumMeshes) {
     if(!pScene->mNumMeshes) {
         return;
         return;
@@ -147,9 +148,7 @@ void DeboneProcess::Execute( aiScene* pScene)
                 }
                 }
 
 
                 if(!DefaultLogger::isNullLogger()) {
                 if(!DefaultLogger::isNullLogger()) {
-                    char buffer[1024];
-                    ::ai_snprintf(buffer,1024,"Removed %u bones. Input bones: %u. Output bones: %u",in-out,in,out);
-                    DefaultLogger::get()->info(buffer);
+                    ASSIMP_LOG_INFO_F("Removed %u bones. Input bones:", in - out, ". Output bones: ", out);
                 }
                 }
 
 
                 // and destroy the source mesh. It should be completely contained inside the new submeshes
                 // and destroy the source mesh. It should be completely contained inside the new submeshes
@@ -172,7 +171,7 @@ void DeboneProcess::Execute( aiScene* pScene)
         UpdateNode( pScene->mRootNode);
         UpdateNode( pScene->mRootNode);
     }
     }
 
 
-    DefaultLogger::get()->debug("DeboneProcess end");
+    ASSIMP_LOG_DEBUG("DeboneProcess end");
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -208,7 +207,7 @@ bool DeboneProcess::ConsiderMesh(const aiMesh* pMesh)
                 if(vertexBones[vid]!=cUnowned)  {
                 if(vertexBones[vid]!=cUnowned)  {
                     if(vertexBones[vid]==i) //double entry
                     if(vertexBones[vid]==i) //double entry
                     {
                     {
-                        DefaultLogger::get()->warn("Encountered double entry in bone weights");
+                        ASSIMP_LOG_WARN("Encountered double entry in bone weights");
                     }
                     }
                     else //TODO: track attraction in order to break tie
                     else //TODO: track attraction in order to break tie
                     {
                     {
@@ -280,7 +279,7 @@ void DeboneProcess::SplitMesh( const aiMesh* pMesh, std::vector< std::pair< aiMe
                 if(vertexBones[vid]!=cUnowned)  {
                 if(vertexBones[vid]!=cUnowned)  {
                     if(vertexBones[vid]==i) //double entry
                     if(vertexBones[vid]==i) //double entry
                     {
                     {
-                        //DefaultLogger::get()->warn("Encountered double entry in bone weights");
+                        ASSIMP_LOG_WARN("Encountered double entry in bone weights");
                     }
                     }
                     else //TODO: track attraction in order to break tie
                     else //TODO: track attraction in order to break tie
                     {
                     {

+ 2 - 1
code/DeboneProcess.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 2 - 1
code/DefaultIOStream.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.

+ 9 - 8
code/DefaultIOSystem.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -75,11 +76,11 @@ bool DefaultIOSystem::Exists( const char* pFile) const
 #ifdef _WIN32
 #ifdef _WIN32
     wchar_t fileName16[PATHLIMIT];
     wchar_t fileName16[PATHLIMIT];
 
 
-    bool isUnicode = IsTextUnicode(pFile, strlen(pFile), NULL);
+    bool isUnicode = IsTextUnicode(pFile, static_cast<int>(strlen(pFile)), NULL) != 0;
     if (isUnicode) {
     if (isUnicode) {
 
 
         MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
         MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, pFile, -1, fileName16, PATHLIMIT);
-        struct _stat64 filestat;
+        struct __stat64 filestat;
         if (0 != _wstat64(fileName16, &filestat)) {
         if (0 != _wstat64(fileName16, &filestat)) {
             return false;
             return false;
         }
         }
@@ -109,7 +110,7 @@ IOStream* DefaultIOSystem::Open( const char* strFile, const char* strMode)
     FILE* file;
     FILE* file;
 #ifdef _WIN32
 #ifdef _WIN32
     wchar_t fileName16[PATHLIMIT];
     wchar_t fileName16[PATHLIMIT];
-    bool isUnicode = IsTextUnicode(strFile, strlen(strFile), NULL );
+    bool isUnicode = IsTextUnicode(strFile, static_cast<int>(strlen(strFile)), NULL) != 0;
     if (isUnicode) {
     if (isUnicode) {
         MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
         MultiByteToWideChar(CP_UTF8, MB_PRECOMPOSED, strFile, -1, fileName16, PATHLIMIT);
         std::string mode8(strMode);
         std::string mode8(strMode);
@@ -157,7 +158,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
 {
 {
     ai_assert(in && _out);
     ai_assert(in && _out);
 #if defined( _MSC_VER ) || defined( __MINGW32__ )
 #if defined( _MSC_VER ) || defined( __MINGW32__ )
-    bool isUnicode = IsTextUnicode(in, strlen(in), NULL);
+    bool isUnicode = IsTextUnicode(in, static_cast<int>(strlen(in)), NULL) != 0;
     if (isUnicode) {
     if (isUnicode) {
         wchar_t out16[PATHLIMIT];
         wchar_t out16[PATHLIMIT];
         wchar_t in16[PATHLIMIT];
         wchar_t in16[PATHLIMIT];
@@ -169,7 +170,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
         if (!ret) {
         if (!ret) {
             // preserve the input path, maybe someone else is able to fix
             // preserve the input path, maybe someone else is able to fix
             // the path before it is accessed (e.g. our file system filter)
             // the path before it is accessed (e.g. our file system filter)
-            DefaultLogger::get()->warn("Invalid path: " + std::string(in));
+            ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
             strcpy(_out, in);
             strcpy(_out, in);
         }
         }
 
 
@@ -178,7 +179,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
         if (!ret) {
         if (!ret) {
             // preserve the input path, maybe someone else is able to fix
             // preserve the input path, maybe someone else is able to fix
             // the path before it is accessed (e.g. our file system filter)
             // the path before it is accessed (e.g. our file system filter)
-            DefaultLogger::get()->warn("Invalid path: " + std::string(in));
+            ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
             strcpy(_out, in);
             strcpy(_out, in);
         }
         }
     }
     }
@@ -188,7 +189,7 @@ inline static void MakeAbsolutePath (const char* in, char* _out)
     if(!ret) {
     if(!ret) {
         // preserve the input path, maybe someone else is able to fix
         // preserve the input path, maybe someone else is able to fix
         // the path before it is accessed (e.g. our file system filter)
         // the path before it is accessed (e.g. our file system filter)
-        DefaultLogger::get()->warn("Invalid path: "+std::string(in));
+        ASSIMP_LOG_WARN_F("Invalid path: ", std::string(in));
         strcpy(_out,in);
         strcpy(_out,in);
     }
     }
 #endif
 #endif

+ 58 - 69
code/DefaultLogger.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -44,7 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of DefaultLogger (and Logger)
  *  @brief Implementation of DefaultLogger (and Logger)
  */
  */
 
 
-
 // Default log streams
 // Default log streams
 #include "Win32DebugLogStream.h"
 #include "Win32DebugLogStream.h"
 #include "StdOStreamLogStream.h"
 #include "StdOStreamLogStream.h"
@@ -61,8 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef ASSIMP_BUILD_SINGLETHREADED
 #ifndef ASSIMP_BUILD_SINGLETHREADED
 #   include <thread>
 #   include <thread>
 #   include <mutex>
 #   include <mutex>
-
-std::mutex loggerMutex;
+    std::mutex loggerMutex;
 #endif
 #endif
 
 
 namespace Assimp    {
 namespace Assimp    {
@@ -75,22 +74,19 @@ static const unsigned int SeverityAll = Logger::Info | Logger::Err | Logger::War
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 // Represents a log-stream + its error severity
 // Represents a log-stream + its error severity
-struct LogStreamInfo
-{
-    unsigned int m_uiErrorSeverity;
-    LogStream *m_pStream;
+struct LogStreamInfo {
+    unsigned int  m_uiErrorSeverity;
+    LogStream    *m_pStream;
 
 
     // Constructor
     // Constructor
     LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
     LogStreamInfo( unsigned int uiErrorSev, LogStream *pStream ) :
         m_uiErrorSeverity( uiErrorSev ),
         m_uiErrorSeverity( uiErrorSev ),
-        m_pStream( pStream )
-    {
+        m_pStream( pStream ) {
         // empty
         // empty
     }
     }
 
 
     // Destructor
     // Destructor
-    ~LogStreamInfo()
-    {
+    ~LogStreamInfo() {
         delete m_pStream;
         delete m_pStream;
     }
     }
 };
 };
@@ -108,7 +104,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream    streams,
 #ifdef WIN32
 #ifdef WIN32
         return new Win32DebugLogStream();
         return new Win32DebugLogStream();
 #else
 #else
-        return NULL;
+        return nullptr;
 #endif
 #endif
 
 
         // Platform-independent default streams
         // Platform-independent default streams
@@ -117,7 +113,7 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream    streams,
     case aiDefaultLogStream_STDOUT:
     case aiDefaultLogStream_STDOUT:
         return new StdOStreamLogStream(std::cout);
         return new StdOStreamLogStream(std::cout);
     case aiDefaultLogStream_FILE:
     case aiDefaultLogStream_FILE:
-        return (name && *name ? new FileLogStream(name,io) : NULL);
+        return (name && *name ? new FileLogStream(name,io) : nullptr );
     default:
     default:
         // We don't know this default log stream, so raise an assertion
         // We don't know this default log stream, so raise an assertion
         ai_assert(false);
         ai_assert(false);
@@ -133,34 +129,38 @@ LogStream* LogStream::createDefaultStream(aiDefaultLogStream    streams,
 Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
 Logger *DefaultLogger::create(const char* name /*= "AssimpLog.txt"*/,
     LogSeverity severity                       /*= NORMAL*/,
     LogSeverity severity                       /*= NORMAL*/,
     unsigned int defStreams                    /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
     unsigned int defStreams                    /*= aiDefaultLogStream_DEBUGGER | aiDefaultLogStream_FILE*/,
-    IOSystem* io                               /*= NULL*/)
-{
+    IOSystem* io                               /*= NULL*/) {
     // enter the mutex here to avoid concurrency problems
     // enter the mutex here to avoid concurrency problems
 #ifndef ASSIMP_BUILD_SINGLETHREADED
 #ifndef ASSIMP_BUILD_SINGLETHREADED
     std::lock_guard<std::mutex> lock(loggerMutex);
     std::lock_guard<std::mutex> lock(loggerMutex);
 #endif
 #endif
 
 
-    if (m_pLogger && !isNullLogger() )
+    if ( m_pLogger && !isNullLogger() ) {
         delete m_pLogger;
         delete m_pLogger;
+    }
 
 
     m_pLogger = new DefaultLogger( severity );
     m_pLogger = new DefaultLogger( severity );
 
 
     // Attach default log streams
     // Attach default log streams
     // Stream the log to the MSVC debugger?
     // Stream the log to the MSVC debugger?
-    if (defStreams & aiDefaultLogStream_DEBUGGER)
-        m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_DEBUGGER));
+    if ( defStreams & aiDefaultLogStream_DEBUGGER ) {
+        m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_DEBUGGER ) );
+    }
 
 
     // Stream the log to COUT?
     // Stream the log to COUT?
-    if (defStreams & aiDefaultLogStream_STDOUT)
-        m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDOUT));
+    if ( defStreams & aiDefaultLogStream_STDOUT ) {
+        m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDOUT ) );
+    }
 
 
     // Stream the log to CERR?
     // Stream the log to CERR?
-    if (defStreams & aiDefaultLogStream_STDERR)
-         m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_STDERR));
+    if ( defStreams & aiDefaultLogStream_STDERR ) {
+        m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_STDERR ) );
+    }
 
 
     // Stream the log to a file
     // Stream the log to a file
-    if (defStreams & aiDefaultLogStream_FILE && name && *name)
-        m_pLogger->attachStream( LogStream::createDefaultStream(aiDefaultLogStream_FILE,name,io));
+    if ( defStreams & aiDefaultLogStream_FILE && name && *name ) {
+        m_pLogger->attachStream( LogStream::createDefaultStream( aiDefaultLogStream_FILE, name, io ) );
+    }
 
 
     return m_pLogger;
     return m_pLogger;
 }
 }
@@ -199,7 +199,6 @@ void Logger::warn(const char* message)  {
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 void Logger::error(const char* message) {
 void Logger::error(const char* message) {
-
     // SECURITY FIX: see above
     // SECURITY FIX: see above
     if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
     if (strlen(message)>MAX_LOG_MESSAGE_LENGTH) {
         return;
         return;
@@ -208,23 +207,24 @@ void Logger::error(const char* message) {
 }
 }
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
-void DefaultLogger::set( Logger *logger )
-{
+void DefaultLogger::set( Logger *logger ) {
     // enter the mutex here to avoid concurrency problems
     // enter the mutex here to avoid concurrency problems
 #ifndef ASSIMP_BUILD_SINGLETHREADED
 #ifndef ASSIMP_BUILD_SINGLETHREADED
     std::lock_guard<std::mutex> lock(loggerMutex);
     std::lock_guard<std::mutex> lock(loggerMutex);
 #endif
 #endif
 
 
-    if (!logger)logger = &s_pNullLogger;
-    if (m_pLogger && !isNullLogger() )
+    if ( nullptr == logger ) {
+        logger = &s_pNullLogger;
+    }
+    if ( nullptr != m_pLogger && !isNullLogger() ) {
         delete m_pLogger;
         delete m_pLogger;
+    }
 
 
     DefaultLogger::m_pLogger = logger;
     DefaultLogger::m_pLogger = logger;
 }
 }
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
-bool DefaultLogger::isNullLogger()
-{
+bool DefaultLogger::isNullLogger() {
     return m_pLogger == &s_pNullLogger;
     return m_pLogger == &s_pNullLogger;
 }
 }
 
 
@@ -235,8 +235,7 @@ Logger *DefaultLogger::get() {
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 //  Kills the only instance
 //  Kills the only instance
-void DefaultLogger::kill()
-{
+void DefaultLogger::kill() {
     // enter the mutex here to avoid concurrency problems
     // enter the mutex here to avoid concurrency problems
 #ifndef ASSIMP_BUILD_SINGLETHREADED
 #ifndef ASSIMP_BUILD_SINGLETHREADED
     std::lock_guard<std::mutex> lock(loggerMutex);
     std::lock_guard<std::mutex> lock(loggerMutex);
@@ -251,10 +250,10 @@ void DefaultLogger::kill()
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 //  Debug message
 //  Debug message
-void DefaultLogger::OnDebug( const char* message )
-{
-	if ( m_Severity == Logger::NORMAL )
-		return;
+void DefaultLogger::OnDebug( const char* message ) {
+    if ( m_Severity == Logger::NORMAL ) {
+        return;
+    }
 
 
 	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
 	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
 	char msg[Size];
 	char msg[Size];
@@ -265,8 +264,7 @@ void DefaultLogger::OnDebug( const char* message )
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 //  Logs an info
 //  Logs an info
-void DefaultLogger::OnInfo( const char* message )
-{
+void DefaultLogger::OnInfo( const char* message ){
 	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
 	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
 	char msg[Size];
 	char msg[Size];
     ai_snprintf(msg, Size, "Info,  T%u: %s", GetThreadID(), message );
     ai_snprintf(msg, Size, "Info,  T%u: %s", GetThreadID(), message );
@@ -276,8 +274,7 @@ void DefaultLogger::OnInfo( const char* message )
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 //  Logs a warning
 //  Logs a warning
-void DefaultLogger::OnWarn( const char* message )
-{
+void DefaultLogger::OnWarn( const char* message ) {
 	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
 	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
 	char msg[Size];
 	char msg[Size];
 	ai_snprintf(msg, Size, "Warn,  T%u: %s", GetThreadID(), message );
 	ai_snprintf(msg, Size, "Warn,  T%u: %s", GetThreadID(), message );
@@ -287,8 +284,7 @@ void DefaultLogger::OnWarn( const char* message )
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 //  Logs an error
 //  Logs an error
-void DefaultLogger::OnError( const char* message )
-{
+void DefaultLogger::OnError( const char* message ) {
 	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
 	static const size_t Size = MAX_LOG_MESSAGE_LENGTH + 16;
 	char msg[ Size ];
 	char msg[ Size ];
     ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message );
     ai_snprintf(msg, Size, "Error, T%u: %s", GetThreadID(), message );
@@ -298,10 +294,10 @@ void DefaultLogger::OnError( const char* message )
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 //  Will attach a new stream
 //  Will attach a new stream
-bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
-{
-    if (!pStream)
+bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity ) {
+    if ( nullptr == pStream ) {
         return false;
         return false;
+    }
 
 
     if (0 == severity)  {
     if (0 == severity)  {
         severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
         severity = Logger::Info | Logger::Err | Logger::Warn | Logger::Debugging;
@@ -311,8 +307,7 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
         it != m_StreamArray.end();
         it != m_StreamArray.end();
         ++it )
         ++it )
     {
     {
-        if ( (*it)->m_pStream == pStream )
-        {
+        if ( (*it)->m_pStream == pStream ) {
             (*it)->m_uiErrorSeverity |= severity;
             (*it)->m_uiErrorSeverity |= severity;
             return true;
             return true;
         }
         }
@@ -325,34 +320,31 @@ bool DefaultLogger::attachStream( LogStream *pStream, unsigned int severity )
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 //  Detach a stream
 //  Detach a stream
-bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
-{
-    if (!pStream)
+bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity ) {
+    if ( nullptr == pStream ) {
         return false;
         return false;
+    }
 
 
     if (0 == severity)  {
     if (0 == severity)  {
         severity = SeverityAll;
         severity = SeverityAll;
     }
     }
 
 
-    for ( StreamIt it = m_StreamArray.begin();
-        it != m_StreamArray.end();
-        ++it )
-    {
-        if ( (*it)->m_pStream == pStream )
-        {
+    bool res( false );
+    for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
+        if ( (*it)->m_pStream == pStream ) {
             (*it)->m_uiErrorSeverity &= ~severity;
             (*it)->m_uiErrorSeverity &= ~severity;
-            if ( (*it)->m_uiErrorSeverity == 0 )
-            {
+            if ( (*it)->m_uiErrorSeverity == 0 ) {
                 // don't delete the underlying stream 'cause the caller gains ownership again
                 // don't delete the underlying stream 'cause the caller gains ownership again
-                (**it).m_pStream = NULL;
+                (**it).m_pStream = nullptr;
                 delete *it;
                 delete *it;
                 m_StreamArray.erase( it );
                 m_StreamArray.erase( it );
+                res = true;
                 break;
                 break;
             }
             }
             return true;
             return true;
         }
         }
     }
     }
-    return false;
+    return res;
 }
 }
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
@@ -360,15 +352,13 @@ bool DefaultLogger::detatchStream( LogStream *pStream, unsigned int severity )
 DefaultLogger::DefaultLogger(LogSeverity severity)
 DefaultLogger::DefaultLogger(LogSeverity severity)
     :   Logger  ( severity )
     :   Logger  ( severity )
     ,   noRepeatMsg (false)
     ,   noRepeatMsg (false)
-    ,   lastLen( 0 )
-{
+    ,   lastLen( 0 ) {
     lastMsg[0] = '\0';
     lastMsg[0] = '\0';
 }
 }
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 //  Destructor
 //  Destructor
-DefaultLogger::~DefaultLogger()
-{
+DefaultLogger::~DefaultLogger() {
     for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
     for ( StreamIt it = m_StreamArray.begin(); it != m_StreamArray.end(); ++it ) {
         // also frees the underlying stream, we are its owner.
         // also frees the underlying stream, we are its owner.
         delete *it;
         delete *it;
@@ -377,9 +367,8 @@ DefaultLogger::~DefaultLogger()
 
 
 // ----------------------------------------------------------------------------------
 // ----------------------------------------------------------------------------------
 //  Writes message to stream
 //  Writes message to stream
-void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev )
-{
-    ai_assert(NULL != message);
+void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev ) {
+    ai_assert(nullptr != message);
 
 
     // Check whether this is a repeated message
     // Check whether this is a repeated message
     if (! ::strncmp( message,lastMsg, lastLen-1))
     if (! ::strncmp( message,lastMsg, lastLen-1))

+ 2 - 1
code/DefaultProgressHandler.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 11 - 12
code/EmbedTexturesProcess.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 
@@ -92,29 +93,27 @@ void EmbedTexturesProcess::Execute(aiScene* pScene) {
         }
         }
     }
     }
 
 
-    char stringBuffer[128];
-    ::ai_snprintf(stringBuffer, 128, "EmbedTexturesProcess finished. Embedded %u textures.", embeddedTexturesCount);
-    DefaultLogger::get()->info(stringBuffer);
+    ASSIMP_LOG_INFO_F("EmbedTexturesProcess finished. Embedded ", embeddedTexturesCount, " textures." );
 }
 }
 
 
 bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
 bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
-    uint32_t imageSize = 0;
-    std::string imagePath = path;
+    std::streampos imageSize = 0;
+    std::string    imagePath = path;
 
 
     // Test path directly
     // Test path directly
     std::ifstream file(imagePath, std::ios::binary | std::ios::ate);
     std::ifstream file(imagePath, std::ios::binary | std::ios::ate);
-    if ((imageSize = file.tellg()) == -1u) {
-        DefaultLogger::get()->warn("EmbedTexturesProcess: Cannot find image: " + imagePath + ". Will try to find it in root folder.");
+    if ((imageSize = file.tellg()) == std::streampos(-1)) {
+        ASSIMP_LOG_WARN_F("EmbedTexturesProcess: Cannot find image: ", imagePath, ". Will try to find it in root folder.");
 
 
         // Test path in root path
         // Test path in root path
         imagePath = mRootPath + path;
         imagePath = mRootPath + path;
         file.open(imagePath, std::ios::binary | std::ios::ate);
         file.open(imagePath, std::ios::binary | std::ios::ate);
-        if ((imageSize = file.tellg()) == -1u) {
+        if ((imageSize = file.tellg()) == std::streampos(-1)) {
             // Test path basename in root path
             // Test path basename in root path
             imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u);
             imagePath = mRootPath + path.substr(path.find_last_of("\\/") + 1u);
             file.open(imagePath, std::ios::binary | std::ios::ate);
             file.open(imagePath, std::ios::binary | std::ios::ate);
-            if ((imageSize = file.tellg()) == -1u) {
-                DefaultLogger::get()->error("EmbedTexturesProcess: Unable to embed texture: " + path + ".");
+            if ((imageSize = file.tellg()) == std::streampos(-1)) {
+                ASSIMP_LOG_ERROR_F("EmbedTexturesProcess: Unable to embed texture: ", path, ".");
                 return false;
                 return false;
             }
             }
         }
         }
@@ -133,7 +132,7 @@ bool EmbedTexturesProcess::addTexture(aiScene* pScene, std::string path) const {
     // Add the new texture
     // Add the new texture
     auto pTexture = new aiTexture();
     auto pTexture = new aiTexture();
     pTexture->mHeight = 0; // Means that this is still compressed
     pTexture->mHeight = 0; // Means that this is still compressed
-    pTexture->mWidth = imageSize;
+    pTexture->mWidth = static_cast<uint32_t>(imageSize);
     pTexture->pcData = imageContent;
     pTexture->pcData = imageContent;
 
 
     auto extension = path.substr(path.find_last_of('.') + 1u);
     auto extension = path.substr(path.find_last_of('.') + 1u);

+ 2 - 1
code/EmbedTexturesProcess.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

+ 29 - 13
code/Exporter.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 ---------------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 
 
 All rights reserved.
 All rights reserved.
@@ -61,6 +62,7 @@ Here we implement only the C++ interface (Assimp::Exporter).
 #include "JoinVerticesProcess.h"
 #include "JoinVerticesProcess.h"
 #include "MakeVerboseFormat.h"
 #include "MakeVerboseFormat.h"
 #include "ConvertToLHProcess.h"
 #include "ConvertToLHProcess.h"
+#include "PretransformVertices.h"
 #include <assimp/Exceptional.h>
 #include <assimp/Exceptional.h>
 #include "ScenePrivate.h"
 #include "ScenePrivate.h"
 #include <memory>
 #include <memory>
@@ -96,6 +98,8 @@ void ExportSceneGLB2(const char*, IOSystem*, const aiScene*, const ExportPropert
 void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneAssbin(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneAssxml(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportSceneX3D(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneFBX(const char*, IOSystem*, const aiScene*, const ExportProperties*);
+void ExportSceneFBXA(const char*, IOSystem*, const aiScene*, const ExportProperties*);
 void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
 void ExportScene3MF( const char*, IOSystem*, const aiScene*, const ExportProperties* );
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
@@ -146,13 +150,13 @@ Exporter::ExportFormatEntry gExporters[] =
 #endif
 #endif
 
 
 #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
 #ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
-    Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
+    Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf", &ExportSceneGLTF2,
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
-    Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
+    Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb", &ExportSceneGLB2,
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
-    Exporter::ExportFormatEntry( "gltf2", "GL Transmission Format v. 2", "gltf2", &ExportSceneGLTF2,
+    Exporter::ExportFormatEntry( "gltf", "GL Transmission Format", "gltf", &ExportSceneGLTF,
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
-    Exporter::ExportFormatEntry( "glb2", "GL Transmission Format v. 2 (binary)", "glb2", &ExportSceneGLB2,
+    Exporter::ExportFormatEntry( "glb", "GL Transmission Format (binary)", "glb", &ExportSceneGLB,
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
         aiProcess_JoinIdenticalVertices | aiProcess_Triangulate | aiProcess_SortByPType ),
 #endif
 #endif
 
 
@@ -168,6 +172,11 @@ Exporter::ExportFormatEntry gExporters[] =
     Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ),
     Exporter::ExportFormatEntry( "x3d", "Extensible 3D", "x3d" , &ExportSceneX3D, 0 ),
 #endif
 #endif
 
 
+#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
+    Exporter::ExportFormatEntry( "fbx", "Autodesk FBX (binary)", "fbx", &ExportSceneFBX, 0 ),
+    Exporter::ExportFormatEntry( "fbxa", "Autodesk FBX (ascii)", "fbx", &ExportSceneFBXA, 0 ),
+#endif
+
 #ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
 #ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
     Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 )
     Exporter::ExportFormatEntry( "3mf", "The 3MF-File-Format", "3mf", &ExportScene3MF, 0 )
 #endif
 #endif
@@ -300,7 +309,8 @@ bool IsVerboseFormat(const aiScene* pScene) {
 }
 }
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
-aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath, unsigned int pPreprocessing, const ExportProperties* pProperties) {
+aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const char* pPath,
+        unsigned int pPreprocessing, const ExportProperties* pProperties) {
     ASSIMP_BEGIN_EXCEPTION_REGION();
     ASSIMP_BEGIN_EXCEPTION_REGION();
 
 
     // when they create scenes from scratch, users will likely create them not in verbose
     // when they create scenes from scratch, users will likely create them not in verbose
@@ -354,7 +364,7 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
                     }
                     }
 
 
                     if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
                     if (verbosify || (exp.mEnforcePP & aiProcess_JoinIdenticalVertices)) {
-                        DefaultLogger::get()->debug("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
+                        ASSIMP_LOG_DEBUG("export: Scene data not in verbose format, applying MakeVerboseFormat step first");
 
 
                         MakeVerboseFormatProcess proc;
                         MakeVerboseFormatProcess proc;
                         proc.Execute(scenecopy.get());
                         proc.Execute(scenecopy.get());
@@ -388,6 +398,11 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
                         }
                         }
                     }
                     }
 
 
+                    bool exportPointCloud(false);
+                    if (nullptr != pProperties) {
+                        exportPointCloud = pProperties->GetPropertyBool(AI_CONFIG_EXPORT_POINT_CLOUDS);
+                    }
+
                     // dispatch other processes
                     // dispatch other processes
                     for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
                     for( unsigned int a = 0; a < pimpl->mPostProcessingSteps.size(); a++) {
                         BaseProcess* const p = pimpl->mPostProcessingSteps[a];
                         BaseProcess* const p = pimpl->mPostProcessingSteps[a];
@@ -396,7 +411,9 @@ aiReturn Exporter::Export( const aiScene* pScene, const char* pFormatId, const c
                             && !dynamic_cast<FlipUVsProcess*>(p)
                             && !dynamic_cast<FlipUVsProcess*>(p)
                             && !dynamic_cast<FlipWindingOrderProcess*>(p)
                             && !dynamic_cast<FlipWindingOrderProcess*>(p)
                             && !dynamic_cast<MakeLeftHandedProcess*>(p)) {
                             && !dynamic_cast<MakeLeftHandedProcess*>(p)) {
-
+                            if (dynamic_cast<PretransformVertices*>(p) && exportPointCloud) {
+                                continue;
+                            }
                             p->Execute(scenecopy.get());
                             p->Execute(scenecopy.get());
                         }
                         }
                     }
                     }
@@ -432,7 +449,6 @@ const char* Exporter::GetErrorString() const {
     return pimpl->mError.c_str();
     return pimpl->mError.c_str();
 }
 }
 
 
-
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Exporter::FreeBlob() {
 void Exporter::FreeBlob() {
     delete pimpl->blob;
     delete pimpl->blob;
@@ -461,7 +477,7 @@ size_t Exporter::GetExportFormatCount() const {
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const {
 const aiExportFormatDesc* Exporter::GetExportFormatDescription( size_t index ) const {
     if (index >= GetExportFormatCount()) {
     if (index >= GetExportFormatCount()) {
-        return NULL;
+        return nullptr;
     }
     }
 
 
     // Return from static storage if the requested index is built-in.
     // Return from static storage if the requested index is built-in.
@@ -486,7 +502,8 @@ aiReturn Exporter::RegisterExporter(const ExportFormatEntry& desc) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 void Exporter::UnregisterExporter(const char* id) {
 void Exporter::UnregisterExporter(const char* id) {
-    for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin(); it != pimpl->mExporters.end(); ++it) {
+    for(std::vector<ExportFormatEntry>::iterator it = pimpl->mExporters.begin();
+            it != pimpl->mExporters.end(); ++it) {
         if (!strcmp((*it).mDescription.id,id)) {
         if (!strcmp((*it).mDescription.id,id)) {
             pimpl->mExporters.erase(it);
             pimpl->mExporters.erase(it);
             break;
             break;
@@ -522,8 +539,7 @@ bool ExportProperties::SetPropertyFloat(const char* szName, ai_real iValue) {
 
 
 // ------------------------------------------------------------------------------------------------
 // ------------------------------------------------------------------------------------------------
 // Set a configuration property
 // Set a configuration property
-bool ExportProperties :: SetPropertyString(const char* szName, const std::string& value)
-{
+bool ExportProperties::SetPropertyString(const char* szName, const std::string& value) {
     return SetGenericProperty<std::string>(mStringProperties, szName,value);
     return SetGenericProperty<std::string>(mStringProperties, szName,value);
 }
 }
 
 

+ 2 - 1
code/FBXAnimation.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 ----------------------------------------------------------------------
 
 
-Copyright (c) 2006-2017, assimp team
+Copyright (c) 2006-2018, assimp team
+
 
 
 All rights reserved.
 All rights reserved.
 
 

部分文件因为文件数量过多而无法显示