Browse Source

Merge branch 'master' into master

Kim Kulling 7 years ago
parent
commit
422776b479
100 changed files with 3772 additions and 1615 deletions
  1. 14 0
      .gitattributes
  2. 2 0
      .gitignore
  3. 58 8
      .travis.sh
  4. 49 33
      .travis.yml
  5. 349 173
      CHANGES
  6. 165 79
      CMakeLists.txt
  7. 168 160
      CREDITS
  8. 78 78
      LICENSE
  9. 170 140
      Readme.md
  10. 43 22
      appveyor.yml
  11. 36 1
      assimp-config-version.cmake.in
  12. 1 1
      assimp.pc.in
  13. 2 2
      cmake-modules/CoverallsGenerateGcov.cmake
  14. 72 0
      cmake-modules/FindDevIL.cmake
  15. 17 0
      cmake-modules/FindIrrXML.cmake
  16. 7 4
      cmake-modules/FindPkgMacros.cmake
  17. 1 1
      cmake-modules/FindZLIB.cmake
  18. 8 4
      code/3DSConverter.cpp
  19. 10 4
      code/3DSExporter.cpp
  20. 10 12
      code/3DSExporter.h
  21. 15 12
      code/3DSHelper.h
  22. 4 2
      code/3DSLoader.cpp
  23. 2 1
      code/3DSLoader.h
  24. 89 0
      code/3MFXmlTags.h
  25. 3 1
      code/ACLoader.cpp
  26. 2 1
      code/ACLoader.h
  27. 4 4
      code/AMFImporter.cpp
  28. 12 12
      code/AMFImporter.hpp
  29. 2 1
      code/AMFImporter_Geometry.cpp
  30. 2 1
      code/AMFImporter_Macro.hpp
  31. 2 1
      code/AMFImporter_Material.cpp
  32. 25 48
      code/AMFImporter_Node.hpp
  33. 39 29
      code/AMFImporter_Postprocess.cpp
  34. 8 1
      code/ASELoader.cpp
  35. 7 5
      code/ASELoader.h
  36. 9 6
      code/ASEParser.cpp
  37. 6 1
      code/ASEParser.h
  38. 59 5
      code/AssbinExporter.cpp
  39. 2 1
      code/AssbinExporter.h
  40. 63 9
      code/AssbinLoader.cpp
  41. 3 4
      code/AssbinLoader.h
  42. 14 20
      code/Assimp.cpp
  43. 4 2
      code/AssimpCExport.cpp
  44. 4 3
      code/AssxmlExporter.cpp
  45. 2 1
      code/AssxmlExporter.h
  46. 27 4
      code/B3DImporter.cpp
  47. 4 2
      code/B3DImporter.h
  48. 3 1
      code/BVHLoader.cpp
  49. 2 1
      code/BVHLoader.h
  50. 15 48
      code/BaseImporter.cpp
  51. 4 44
      code/BaseImporter.h
  52. 2 1
      code/BaseProcess.cpp
  53. 2 3
      code/BaseProcess.h
  54. 4 3
      code/Bitmap.cpp
  55. 61 82
      code/Bitmap.h
  56. 5 1
      code/BlenderBMesh.cpp
  57. 3 1
      code/BlenderDNA.cpp
  58. 10 7
      code/BlenderDNA.h
  59. 9 4
      code/BlenderDNA.inl
  60. 4 4
      code/BlenderIntermediate.h
  61. 24 16
      code/BlenderLoader.cpp
  62. 2 1
      code/BlenderLoader.h
  63. 8 5
      code/BlenderModifier.cpp
  64. 2 1
      code/BlenderModifier.h
  65. 33 14
      code/BlenderScene.cpp
  66. 57 4
      code/BlenderScene.h
  67. 12 3
      code/BlenderTessellator.cpp
  68. 2 1
      code/BlenderTessellator.h
  69. 6 5
      code/BlobIOSystem.h
  70. 2 1
      code/ByteSwapper.h
  71. 6 6
      code/C4DImporter.cpp
  72. 1 1
      code/C4DImporter.h
  73. 2 1
      code/CInterfaceIOWrapper.cpp
  74. 2 1
      code/CInterfaceIOWrapper.h
  75. 102 36
      code/CMakeLists.txt
  76. 11 9
      code/COBLoader.cpp
  77. 2 1
      code/COBLoader.h
  78. 6 4
      code/COBScene.h
  79. 3 2
      code/CSMLoader.cpp
  80. 2 1
      code/CSMLoader.h
  81. 2 1
      code/CalcTangentsProcess.cpp
  82. 2 1
      code/CalcTangentsProcess.h
  83. 527 60
      code/ColladaExporter.cpp
  84. 20 3
      code/ColladaExporter.h
  85. 34 3
      code/ColladaHelper.h
  86. 298 55
      code/ColladaLoader.cpp
  87. 7 1
      code/ColladaLoader.h
  88. 82 28
      code/ColladaParser.cpp
  89. 3 3
      code/ColladaParser.h
  90. 2 1
      code/ComputeUVMappingProcess.cpp
  91. 2 1
      code/ComputeUVMappingProcess.h
  92. 2 1
      code/ConvertToLHProcess.cpp
  93. 2 1
      code/ConvertToLHProcess.h
  94. 92 0
      code/CreateAnimMesh.cpp
  95. 57 0
      code/CreateAnimMesh.h
  96. 328 0
      code/D3MFExporter.cpp
  97. 103 0
      code/D3MFExporter.h
  98. 37 87
      code/D3MFImporter.cpp
  99. 7 11
      code/D3MFImporter.h
  100. 83 146
      code/D3MFOpcPackage.cpp

+ 14 - 0
.gitattributes

@@ -2,7 +2,21 @@
 *.cpp text eol=lf
 *.h text eol=lf
 *.c text eol=lf
+*.cc text eol=lf
+*.cpp text eol=lf
+*.rc text eol=lf
 *.hpp text eol=lf
 *.txt text eol=lf
 *.cmake text eol=lf
 *.sh text eol=lf
+CHANGES text eol=lf
+CREDITS text eol=lf
+LICENSE text eol=lf
+Readme.md text eol=lf
+# make sure that repo-specific settings (.gitignore, CI-setup,...)
+# are excluded from the source-package generated via 'git archive'
+.git*      	export-ignore
+/.travis*	export-ignore
+/.coveralls*	export-ignore
+appveyor.yml	export-ignore
+

+ 2 - 0
.gitignore

@@ -81,3 +81,5 @@ lib64/assimp-vc120-mtd.ilk
 lib64/assimp-vc120-mtd.exp
 lib64/assimp-vc120-mt.exp
 xcuserdata
+
+cmake-build-debug

+ 58 - 8
.travis.sh

@@ -1,16 +1,66 @@
-function generate()
-{
-    cmake -G "Unix Makefiles" -DASSIMP_NO_EXPORT=$TRAVIS_NO_EXPORT -DBUILD_SHARED_LIBS=$SHARED_BUILD -DASSIMP_COVERALLS=$ENABLE_COVERALLS
-}
+#---------------------------------------------------------------------------
+#Open Asset Import Library (assimp)
+#---------------------------------------------------------------------------
+# Copyright (c) 2006-2017, assimp team
+#
+# License see LICENSE file
+#
+function generate() {
+    OPTIONS="-DASSIMP_WERROR=ON"
+
+    if [ "$DISABLE_EXPORTERS" = "YES" ] ; then
+        OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=YES"
+    else
+        OPTIONS="$OPTIONS -DASSIMP_NO_EXPORT=NO"
+    fi
+
+    if [ "$SHARED_BUILD" = "ON" ] ; then
+        OPTIONS="$OPTIONS -DBUILD_SHARED_LIBS=ON"
+    else
+        OPTIONS="$OPTIONS -DBUILD_SHARED_LIBS=OFF"
+    fi
+
+    if [ "$ENABLE_COVERALLS" = "ON" ] ; then
+        OPTIONS="$OPTIONS -DASSIMP_COVERALLS=ON"
+    else
+        OPTIONS="$OPTIONS -DASSIMP_COVERALLS=OFF"
+    fi
 
+    if [ "$ASAN" = "ON" ] ; then
+        OPTIONS="$OPTIONS -DASSIMP_ASAN=ON"
+    else
+        OPTIONS="$OPTIONS -DASSIMP_ASAN=OFF"
+    fi
+
+    if [ "$UBSAN" = "ON" ] ; then
+        OPTIONS="$OPTIONS -DASSIMP_UBSAN=ON"
+    fi
+
+    cmake -G "Unix Makefiles" $OPTIONS
+}
+# build and run unittests, if not android
 if [ $ANDROID ]; then
     ant -v -Dmy.dir=${TRAVIS_BUILD_DIR} -f ${TRAVIS_BUILD_DIR}/port/jassimp/build.xml ndk-jni
-else
+fi
+if [ "$TRAVIS_OS_NAME" = "linux" ]; then
+  if [ $ANALYZE = "ON" ] ; then
+    if [ "$CC" = "clang" ]; then
+        scan-build cmake -G "Unix Makefiles" -DBUILD_SHARED_LIBS=OFF -DASSIMP_BUILD_TESTS=OFF
+        scan-build --status-bugs make -j2
+    else
+        cppcheck --version
+        generate \
+        && cppcheck --error-exitcode=1 -j2 -Iinclude -Icode code 2> cppcheck.txt
+        if [ -s cppcheck.txt ]; then
+            cat cppcheck.txt
+            exit 1
+        fi
+    fi
+  else
     generate \
     && make -j4 \
     && sudo make install \
     && sudo ldconfig \
-    && (cd test/unit; ../../bin/unit) \
-    #&& (cd test/regression; chmod 755 run.py; ./run.py ../../bin/assimp; \
-	#   chmod 755 result_checker.py; ./result_checker.py)
+    && (cd test/unit; ../../bin/unit)
+  fi
 fi

+ 49 - 33
.travis.yml

@@ -1,58 +1,74 @@
+sudo: required
+language: cpp
+
+cache: ccache
+
 before_install:
-  - sudo apt-get update -qq
-  - sudo apt-get install cmake
-  - sudo apt-get install cmake python3
-  - if [ $LINUX ]; then sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; fi
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then sudo apt-get update -qq && sudo apt-get install cmake cppcheck && sudo apt-get install cmake python3 && sudo apt-get install -qq freeglut3-dev libxmu-dev libxi-dev ; echo -n | openssl s_client -connect scan.coverity.com:443 | sed -ne '/-BEGIN CERTIFICATE-/,/-END CERTIFICATE-/p' | sudo tee -a /etc/ssl/certs/ca- ; fi
+  - 'if [ "$TRAVIS_OS_NAME" = "osx" ];  then
+       if brew ls --versions cmake > /dev/null; then
+         echo cmake already installed.;
+       else
+         brew install cmake;
+       fi;
+       brew install python3;
+       brew install homebrew/x11/freeglut; 
+    fi'
   - echo -e "#ifndef A_R_H_INC\n#define A_R_H_INC\n#define GitVersion ${TRAVIS_JOB_ID}\n#define GitBranch \"${TRAVIS_BRANCH}\"\n#endif // A_R_H_INC" > revision.h
   # install latest LCOV (1.9 was failing)
-  - cd ${TRAVIS_BUILD_DIR}
-  - wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz
-  - tar xf lcov_1.11.orig.tar.gz
-  - sudo make -C lcov-1.11/ install
-  - gem install coveralls-lcov
-  - lcov --version
-  - g++ --version
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && wget http://ftp.de.debian.org/debian/pool/main/l/lcov/lcov_1.11.orig.tar.gz && tar xf lcov_1.11.orig.tar.gz && sudo make -C lcov-1.11/ install && gem install coveralls-lcov && lcov --version && g++ --version ; fi
 
-branches:
-  only:
-    - master
+os:
+  - linux
+
+compiler:
+  - gcc
+  - clang
 
 env:
   global:
+  # COVERITY_SCAN_TOKEN
     - secure: "lZ7pHQvl5dpZWzBQAaIMf0wqrvtcZ4wiZKeIZjf83TEsflW8+z0uTpIuN30ZV6Glth/Sq1OhLnTP5+N57fZU/1ebA5twHdvP4bS5CIUUg71/CXQZNl36xeaqvxsG/xRrdpKOsPdjAOsQ9KPTQulsX43XDLS7CasMiLvYOpqKcPc="
     - PV=r8e PLATF=linux-x86_64 NDK_HOME=${TRAVIS_BUILD_DIR}/android-ndk-${PV} PATH=${PATH}:${NDK_HOME}
-  matrix:
-    - LINUX=1 TRAVIS_NO_EXPORT=YES ENABLE_COVERALLS=ON
-    - LINUX=1 TRAVIS_NO_EXPORT=NO  ENABLE_COVERALLS=OFF
-    - LINUX=1 SHARED_BUILD=ON      ENABLE_COVERALLS=OFF
-    - LINUX=1 SHARED_BUILD=OFF     ENABLE_COVERALLS=OFF
-    - ANDROID=1
 
-language: cpp
-  
-compiler:
-  - gcc
-  - clang
+matrix:
+  include:
+    - os: linux
+      compiler: clang
+      env: ANALYZE=ON
+    - os: linux
+      compiler: clang
+      env: ASAN=ON
+    - os: linux
+      compiler: clang
+      env: UBSAN=ON
+    - os: linux
+      compiler: clang
+      env: SHARED_BUILD=ON
+    - os: linux
+      compiler: gcc
+      env: ANALYZE=ON
+    - os: linux
+      compiler: gcc
+      env: DISABLE_EXPORTERS=YES ENABLE_COVERALLS=ON
+    - os: linux
+      compiler: gcc
+      env: SHARED_BUILD=ON
 
 install:
   - if [ $ANDROID ]; then wget -c http://dl.google.com/android/ndk/android-ndk-${PV}-${PLATF}.tar.bz2 && tar xf android-ndk-${PV}-${PLATF}.tar.bz2 ; fi
 
 before_script:
-  - cd ${TRAVIS_BUILD_DIR}
   # init coverage to 0 (optional)
-  - lcov --directory . --zerocounters
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --zerocounters ; fi
 
 script:
   - export COVERALLS_SERVICE_NAME=travis-ci
   - export COVERALLS_REPO_TOKEN=abc12345
   - . ./.travis.sh
-
+ 
 after_success:
-  - cd ${TRAVIS_BUILD_DIR}
-  - lcov --directory . --capture --output-file coverage.info
-  - lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info
-  - lcov --list coverage.info
-  - coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info
+  - if [ "$TRAVIS_OS_NAME" = "linux" ]; then cd ${TRAVIS_BUILD_DIR} && lcov --directory . --capture --output-file coverage.info && lcov --remove coverage.info '/usr/*' 'contrib/*' 'test/*' --output-file coverage.info && lcov --list coverage.info && coveralls-lcov --source-encoding=ISO-8859-1 --repo-token=${COVERALLS_TOKEN} coverage.info ; fi
 
 addons:
   coverity_scan:

+ 349 - 173
CHANGES

@@ -1,173 +1,349 @@
-----------------------------------------------------------------------
-CHANGELOG
-----------------------------------------------------------------------
-
-3.2.1 (2016-10-01)
-
-FEATURES:
-  - Updated glTF exporter to meet 1.0 specification.
-
-FIXES/HOUSEKEEPING:
-  - Fixed glTF Validator errors for exported glTF format.
-
-ISSUES:
-  - Hard coded sampler setting for
-    - magFilter
-    - minFilter
-  - void* in ExportData for accessor max and min.
-
-
-
-3.2.0 (2015-11-03)
-
-FEATURES:
-  - OpenDDL-Parser is part of contrib-source.
-  - Experimental OpenGEX-support
-  - CI-check for linux and windows
-  - Coverity check added
-  - New regression testsuite.
-
-FIXES/HOUSEKEEPING:
-  - Hundreds of bugfixes  in all parts of the library
-  - Unified line endings
-
-
-API COMPATIBILITY:
-  - Removed precompiled header to increase build speed for linux
-
-
-3.1.1 (2014-06-15)
-
-FEATURES:
-   - Support for FBX 2013 and newer, binary and ASCII (this is partly
-     work from Google Summer of Code 2012)
-   - Support for OGRE binary mesh and skeleton format
-   - Updated BLEND support for newer Blender versions
-   - Support for arbitrary meta data, used to hold FBX and DAE metadata
-   - OBJ Export now produces smaller files
-   - Meshes can now have names, this is supported by the major importers
-   - Improved IFC geometry generation
-   - M3 support has been removed
-
-FIXES/HOUSEKEEPING:
-    - Hundreds of bugfixes in all parts of the library
-    - CMake is now the primary build system
-
-API COMPATIBILITY:
-    - 3.1.1 is not binary compatible to 3.0 due to aiNode::mMetaData
-      and aiMesh::mName
-    - Export interface has been cleaned up and unified
-    - Other than that no relevant changes
-
-
-3.0 (2012-07-07)
-
-FEATURES:
-   - new export interface similar to the import API.
-   - Supported export formats: Collada, OBJ, PLY and STL
-   - added new import formats: XGL/ZGL, M3 (experimental)
-   - new postprocessing steps: Debone
-   - vastly improved IFC (Industry Foundation Classes) support
-   - introduced API to query importer meta information (such as supported
-       format versions, full name, maintainer info).
-   - reworked Ogre XML import
-   - C-API now supports per-import properties
-
-FIXES/HOUSEKEEPING:
-
-   - hundreds of bugfixes in all parts of the library
-   - unified naming and cleanup of public headers
-   - improved CMake build system
-   - templatized math library
-   - reduce dependency on boost.thread, only remaining spot
-     is synchronization for the C logging API
-
-API COMPATIBILITY:
-   - renamed headers, export interface, C API properties and meta data
-     prevent compatibility with code written for 2.0, but in
-     most cases these can be easily resolved
-   - Note: 3.0 is not binary compatible with 2.0
-
-
-
-
-2.0 (2010-11-21)
-
-FEATURES:
-   - Add support for static Blender (*.blend) scenes
-   - Add support for Q3BSP scenes
-   - Add a windows-based OpenGL sample featuring texturing & basic materials
-   - Add an experimental progress feedback interface.
-   - Vastly improved performance (up to 500%, depending on mesh size and
-     spatial structure) in some expensive postprocessing steps
-   - AssimpView now uses a reworked layout which leaves more space
-     to the scene hierarchy window
-
-   - Add C# bindings ('Assimp.NET')
-   - Keep BSD-licensed and otherwise free test files in separate
-     folders (./test/models and ./test/models-nonbsd).
-
-FIXES:
-   - Many Collada bugfixes, improve fault tolerance
-   - Fix possible crashes in the Obj loader
-   - Improve the Ogre XML loader
-   - OpenGL-sample now works with MinGW
-   - Fix Importer::FindLoader failing on uppercase file extensions
-   - Fix flawed path handling when locating external files
-   - Limit the maximum number of vertices, faces, face indices and
-     weights that Assimp is able to handle. This is to avoid
-     crashes due to overflowing counters.
-
-   - Updated XCode project files
-   - Further CMAKE build improvements
-
-
-API CHANGES:
-   - Add data structures for vertex-based animations (These are not
-     currently used, however ...)
-   - Some Assimp::Importer methods are const now.
-
-
-
-
-
-1.1 (2010-04-17)
-This is the list of relevant changes from the 1.0 (r412) release to 1.1 (r700).
-
-FEATURES:
-  - Vastly improved Collada support
-  - Add MS3D (Milkshape 3D) support
-  - Add support for Ogre XML static meshes
-  - Add experimental COB (TrueSpace) support
-  - Automatic test suite to quickly locate regressions
-  - D bindings (`dAssimp`)
-  - Python 2.n bindings (`PyAssimp`)
-  - Add basic support for Unicode input files (utf8, utf16 and utf32)
-  - Add further utilities to the `assimp` tool (xml/binary dumps, quick file stats)
-  - Switch to a CMAKE-based build system including an install target for unix'es
-  - Automatic evaluation of subdivision surfaces for some formats.
-  - Add `Importer::ReadFileFromMemory` and the corresponding C-API `aiReadFileFromMemory`
-  - Expose further math utilities via the C-API (i.e. `aiMultiplyMatrix4`)
-
-  - Move noboost files away from the public include directory
-  - Many, many bugfixes and improvements in existing loaders and postprocessing steps
-  - Documentation improved and clarified in many places.
-  - Add a sample on using Assimp in conjunction with OpenGL
-
-  - Distribution/packaging: comfortable SDK installer for Windows
-  - Distribution/packaging: improved release packages for other architectures
-
-CRITICAL FIXES:
-  - Resolve problems with clashing heap managers, STL ABIs and runtime libraries (win32)
-  - Fix automatic detection of file type if no file extension is given
-  - Improved exception safety and robustness, prevent leaking of exceptions through the C interface
-  - Fix possible heap corruption due to material properties pulled in incorrectly
-  - Avoid leaking in certain error scenarios
-  - Fix 64 bit compatibility problems in some loaders (i.e. MDL)
-
-BREAKING API CHANGES:
-  - None -
-
-MINOR API BEHAVIOUR CHANGES:
- - Change quaternion orientation to suit to the more common convention (-w).
- - aiString is utf8 now. Not yet consistent, however.
+----------------------------------------------------------------------
+CHANGELOG
+----------------------------------------------------------------------
+4.0.1 (2017-07-28)
+    - FIXES/HOUSEKEEPING:
+    - fix version test.
+    - Not compiling when using ASSIMP_DOUBLE_PRECISION
+    - Added support for python3
+    - Check if cmake is installed with brew
+    - Low performance in OptimizeMeshesProcess::ProcessNode with huge numbers of meshes
+    - Elapsed seconds not shown correctly
+    - StreamReader: fix out-of-range exception
+    - PPdPmdParser: fix compilation for clang
+
+
+4.0.0 (2017-07-18)
+
+FEATURES:
+    - Double precision support provided ( available via cmake option )
+	- QT-Widget based assimp-viewer ( works for windows, linux, osx )
+	- Open3DGC codec supported by glFT-importer
+	- glTF: Read and write transparency values
+	- Add Triangulate post-processing step to glTF exporters
+	- Update rapidjson to v1.0.2
+	- Added method to append new metadata to structure
+	- Unittests: intoduce a prototype model differ
+	- X3D support
+	- AMF support
+	- Lugdunum3D support
+	- Obj-Importer: obj-homogeneous_coords support
+	- Obj-Importer: new streaming handling
+	- Added support for 64 bit version header introduced in FbxSdk2016
+	- Travis: enable coverall support.
+	- PyAssimp: New version of the pyASSIMP 3D viewer, with much improved 3D controls
+    - Morph animation support for collada	
+	- Added support for parameters Ni and Tf in OBJ/MTL file format
+	- aiScene: add method to add children
+	- Added new option to IFC importer to control tessellation angle + removed unused IFC option
+	- aiMetaData: introduce aiMetaData::Dealloc
+	- Samples: add a DX11 example
+	- travis ci: test on OXS ( XCode 6.3 ) as well
+	- travis ci: enable sudo support.
+	- openddlparser: integrate release v0.4.0
+	- aiMetaData: Added support for metadata in assbin format
+	
+FIXES/HOUSEKEEPING:
+    - Introduce usage of #pragma statement
+	- Put cmake-scripts into their own folder
+	- Fix install pathes ( issue 938 )
+	- Fix object_compare in blender importer( issue 946 )
+	- Fix OSX compilation error
+	- Fix unzip path when no other version was found ( issue 967 )
+	- Set _FILE_OFFSET_BITS=64 for 32-bit linux ( issue 975 )
+	- Fix constructor for radjson on OSX
+	- Use Assimp namespace to fix build for big-endian architectures
+	- Add -fPIC to C Flags for 64bit linux Shared Object builds
+	- MDLLoader: fix resource leak.
+	- MakeVerboseFormat: fix invalid delete statement
+	- IFC: fix possible use after free access bug
+	- ComputeUVMappingprocess: add missing initialization for scalar value
+    - Fix invalid release of mat + mesh
+	- IrrImporter: Fix release functions
+	- Split mesh before exporting gltf ( issue 995 )
+	- 3MFImporter: add source group for visual studio
+	- IFC: Switch generated file to 2 files to fix issue related to <mingw4.9 ( Thanks Qt! )
+	- ObjImporter: fix test for vertices import
+    - export scene combiner ( issues177 )
+	- FBX: make lookup test less strict ( issues 994 )
+	- OpenGEX-Importer: add import of vertex colors ( issue 954 )
+	- fix bug when exporting mRotationKeys data
+	- fix mingw build (mingw supports stat64 nowadays)
+	- cfileio: fix leaks by not closing files in the destructor
+	- Fix OBJ parser mtllib statement parsing bug.
+	- Q3BSP-Importer: remove dead code
+	- Fix BlenderDNA for clang cross compiler.
+	- ScenePreprocessor: fix invalid index counter.
+	- Fix compiler warnings ( issue 957 )
+	- Fix obj .mtl file loading
+	- Fixed a compile error on MSVC14 x64 caused by the /bigobj flag failing to be set for the 1 and 2-suffixed versions introduced in commit 0a25b076b8968b7ea2aa96d7d1b4381be2d72ce6
+	- Fixed build warnings on MSVC14 x64
+	- Remove scaling of specular exponent in OBJFileImporter.cpp
+	- use ai_assert instead of assert ( issue 1076 )
+	- Added a preprocessor definition for MSVC to silence safety warnings regarding C library functions. This addresses all warnings for MSVC x86 and x64 when building zlib, tools and viewer as a static lib
+	- fix parsing of texture name ( issue 899 )
+	- add warning when detecting invalid mat definition ( issue 1111 )
+	- copy aiTexture type declaration instead of using decltype for declaration to fix iOS build( issue 1101 )
+	- FBX: Add additional material properties
+	- FBX: Correct camera position and clip planes
+    - FBX: Add correct light locations and falloff values
+	- fix typo ( issue 1141 )
+	- Fix collada export. Don't duplicate TEXCOORD/NORMALS/COLORS in <vertices> and <polylist> ( issue 1084 )
+	- OBJParser: set material index when changing current material
+	- OBJ: check for null mesh before updating material index
+	- add vertex color export support ( issue 809 )
+	- Fix memory leak in Collada importer ( issue 1169 )
+	- add stp to the list of supported extensions for step-files ( issue 1183 )
+	- fix clang build ( Issue-1169 ) 
+	- fix for FreeBSD
+	- Import FindPkgMacros to main CMake Configuration
+	- Extended support for tessellation parameter to more IFC shapes
+	- defensice handling of utf-8 decode issues ( issue 1211 )
+	- Fixed compiler error on clang 4.0 running on OSX
+	- use test extension for exported test files ( issue 1228 )
+	- Set UVW index material properties for OBJ files
+	- Fixed no member named 'atop' in global namespace issue for Android NDK compilation
+	- Apply mechanism to decide use for IrrXML external or internal
+	- Fix static init ordering bug in OpenGEX importer
+	- GLTF exporter: ensure animation accessors have same count
+	- GLTF exporter: convert animation time from ticks to seconds
+	- Add support for reading texture coordinates from PLY meshes with properties named 'texture_u' and 'texture_v'
+	- Added TokensForSearch in BlenderLoader to allow CanRead return true for in-memory files.
+	- fix wrong delete ( issue 1266 )
+	- OpenGEX: fix invalid handling with color4 token ( issue 1262 )
+	- LWOLoader: fix link in loader description
+	- Fix error when custom CMAKE_C_FLAGS is specified
+	- Fast-atof: log overflow errors
+	- Obj-Importer: do not break when detecting an overflow ( issue 1244 )
+	- Obj-Importer: fix parsing of multible line data definitions
+	- Fixed bug where IFC models with multiple IFCSite only loaded 1 site instead of the complete model
+	- PLYImporter: - optimize memory and speed on ply importer / change parser to use a file stream - manage texture path in ply 
+	  import - manage texture coords on faces in ply import - correction on point cloud faces generation
+	- Utf8: integrate new lib ( issue 1158 )
+	- fixed CMAKE_MODULE_PATH overwriting previous values
+	- OpenGEX: Fixed bug in material color processing ( issue 1271 )
+	- SceneCombiner: move header for scenecombiner to public folder.
+	- GLTF exporter: ensure buffer view byte offsets are correctly aligned
+	- X3D importer: Added EXPORT and IMPORT to the list of ignored XML tags
+    - X3D Exporter: fixed missing attributes
+    - X3D importer: Fixed import of normals for the single index / normal per vertex case
+    - X3D importer: Fixed handling of inlined files
+    - X3D importer: fixed whitespace handling (issue 1202)
+	- X3D importer: Fixed iterator on MSVC 2015
+    - X3D importer: Fixed problems with auto, override and regex on older compilers
+    - X3D importer: Fixed missing header file
+    - X3D importer: Fixed path handling
+	- X3D importer: Implemented support for binary X3D files
+    - fix build without 3DS ( issue 1319 )
+	- pyassimp: Fixed indices for IndexedTriangleFanSet, IndexedTriangleSet and IndexedTriangleStripSet
+	- Fixes parameters to pyassimp.load
+	- Obj-Importe: Fixed texture bug due simultaneously using 'usemtl' and 'usemap' attributes
+	- check if all exporters are disabled ( issue 1320 )
+	- Remove std functions deprecated by C++11.
+	- X-Importer: make it deal with lines
+	- use correct path for compilers ( issue 1335 )
+	- Collada: add workaround to deal with polygon with holes 
+	- update python readme
+	- Use unique node names when loading Collada files
+	- Fixed many FBX bugs
+
+API COMPATIBILITY:
+    - Changed ABI-compatibility to v3.3.1, please rebuild your precompiled libraries ( see issue 1182 )
+	- VS2010 outdated
+
+3.3.1 (2016-07-08)
+
+FIXES/HOUSEKEEPING:
+    - Setup of default precision for 17 exporters
+    - Fix xcode project files
+    - Fix BlenderTesselator: offsetof operator
+    - Invalid version in cmake file
+    - Update pstdint.h to latest greatest
+
+
+3.3.0 (2016-07-05)
+
+FEATURES:
+    - C++11 support enabled
+    - New regression-test-UI
+    - Experimental glTF-importer support
+    - OpenGEX: add support for cameras and lights
+    - C4D: update to latest Melange-SDK
+    - Add a gitter channel
+    - Coverity check enabled
+    - Switch to <...> include brackets for public headers 
+    - Enable export by pyAssimp
+    - CI: check windows build
+    - Add functionality to perform a singlepost-processing step
+    - many more, just check the history
+
+FIXES/HOUSEKEEPING:
+    - Fix of many resource leaks in unittests and main lib
+    - Fix iOS-buildfor X64
+    - Choosing zlib manually for cmake
+    - many more, just check the history
+
+
+3.2.1 (2016-010-10)
+
+FEATURES:
+  - Updated glTF exporter to meet 1.0 specification.
+
+FIXES/HOUSEKEEPING:
+  - Fixed glTF Validator errors for exported glTF format.
+
+ISSUES:
+  - Hard coded sampler setting for
+    - magFilter
+    - minFilter
+  - void* in ExportData for accessor max and min.
+
+
+3.2.0 (2015-11-03)
+
+FEATURES:
+  - OpenDDL-Parser is part of contrib-source.
+  - Experimental OpenGEX-support
+  - CI-check for linux and windows
+  - Coverity check added
+  - New regression testsuite.
+
+FIXES/HOUSEKEEPING:
+  - Hundreds of bugfixes  in all parts of the library
+  - Unified line endings
+
+
+API COMPATIBILITY:
+  - Removed precompiled header to increase build speed for linux
+
+
+3.1.1 (2014-06-15)
+
+FEATURES:
+   - Support for FBX 2013 and newer, binary and ASCII (this is partly
+     work from Google Summer of Code 2012)
+   - Support for OGRE binary mesh and skeleton format
+   - Updated BLEND support for newer Blender versions
+   - Support for arbitrary meta data, used to hold FBX and DAE metadata
+   - OBJ Export now produces smaller files
+   - Meshes can now have names, this is supported by the major importers
+   - Improved IFC geometry generation
+   - M3 support has been removed
+
+FIXES/HOUSEKEEPING:
+    - Hundreds of bugfixes in all parts of the library
+    - CMake is now the primary build system
+
+API COMPATIBILITY:
+    - 3.1.1 is not binary compatible to 3.0 due to aiNode::mMetaData
+      and aiMesh::mName
+    - Export interface has been cleaned up and unified
+    - Other than that no relevant changes
+
+
+3.0 (2012-07-07)
+
+FEATURES:
+   - new export interface similar to the import API.
+   - Supported export formats: Collada, OBJ, PLY and STL
+   - added new import formats: XGL/ZGL, M3 (experimental)
+   - new postprocessing steps: Debone
+   - vastly improved IFC (Industry Foundation Classes) support
+   - introduced API to query importer meta information (such as supported
+       format versions, full name, maintainer info).
+   - reworked Ogre XML import
+   - C-API now supports per-import properties
+
+FIXES/HOUSEKEEPING:
+
+   - hundreds of bugfixes in all parts of the library
+   - unified naming and cleanup of public headers
+   - improved CMake build system
+   - templatized math library
+   - reduce dependency on boost.thread, only remaining spot
+     is synchronization for the C logging API
+
+API COMPATIBILITY:
+   - renamed headers, export interface, C API properties and meta data
+     prevent compatibility with code written for 2.0, but in
+     most cases these can be easily resolved
+   - Note: 3.0 is not binary compatible with 2.0
+
+
+2.0 (2010-11-21)
+
+FEATURES:
+   - Add support for static Blender (*.blend) scenes
+   - Add support for Q3BSP scenes
+   - Add a windows-based OpenGL sample featuring texturing & basic materials
+   - Add an experimental progress feedback interface.
+   - Vastly improved performance (up to 500%, depending on mesh size and
+     spatial structure) in some expensive postprocessing steps
+   - AssimpView now uses a reworked layout which leaves more space
+     to the scene hierarchy window
+
+   - Add C# bindings ('Assimp.NET')
+   - Keep BSD-licensed and otherwise free test files in separate
+     folders (./test/models and ./test/models-nonbsd).
+
+FIXES:
+   - Many Collada bugfixes, improve fault tolerance
+   - Fix possible crashes in the Obj loader
+   - Improve the Ogre XML loader
+   - OpenGL-sample now works with MinGW
+   - Fix Importer::FindLoader failing on uppercase file extensions
+   - Fix flawed path handling when locating external files
+   - Limit the maximum number of vertices, faces, face indices and
+     weights that Assimp is able to handle. This is to avoid
+     crashes due to overflowing counters.
+
+   - Updated XCode project files
+   - Further CMAKE build improvements
+
+
+API CHANGES:
+   - Add data structures for vertex-based animations (These are not
+     currently used, however ...)
+   - Some Assimp::Importer methods are const now.
+
+   
+1.1 (2010-04-17)
+This is the list of relevant changes from the 1.0 (r412) release to 1.1 (r700).
+
+FEATURES:
+  - Vastly improved Collada support
+  - Add MS3D (Milkshape 3D) support
+  - Add support for Ogre XML static meshes
+  - Add experimental COB (TrueSpace) support
+  - Automatic test suite to quickly locate regressions
+  - D bindings (`dAssimp`)
+  - Python 2.n bindings (`PyAssimp`)
+  - Add basic support for Unicode input files (utf8, utf16 and utf32)
+  - Add further utilities to the `assimp` tool (xml/binary dumps, quick file stats)
+  - Switch to a CMAKE-based build system including an install target for unix'es
+  - Automatic evaluation of subdivision surfaces for some formats.
+  - Add `Importer::ReadFileFromMemory` and the corresponding C-API `aiReadFileFromMemory`
+  - Expose further math utilities via the C-API (i.e. `aiMultiplyMatrix4`)
+
+  - Move noboost files away from the public include directory
+  - Many, many bugfixes and improvements in existing loaders and postprocessing steps
+  - Documentation improved and clarified in many places.
+  - Add a sample on using Assimp in conjunction with OpenGL
+
+  - Distribution/packaging: comfortable SDK installer for Windows
+  - Distribution/packaging: improved release packages for other architectures
+
+CRITICAL FIXES:
+  - Resolve problems with clashing heap managers, STL ABIs and runtime libraries (win32)
+  - Fix automatic detection of file type if no file extension is given
+  - Improved exception safety and robustness, prevent leaking of exceptions through the C interface
+  - Fix possible heap corruption due to material properties pulled in incorrectly
+  - Avoid leaking in certain error scenarios
+  - Fix 64 bit compatibility problems in some loaders (i.e. MDL)
+
+BREAKING API CHANGES:
+  - None -
+
+MINOR API BEHAVIOUR CHANGES:
+ - Change quaternion orientation to suit to the more common convention (-w).
+ - aiString is utf8 now. Not yet consistent, however.

+ 165 - 79
CMakeLists.txt

@@ -1,7 +1,6 @@
 # Open Asset Import Library (assimp)
 # ----------------------------------------------------------------------
-#
-# Copyright (c) 2006-2016, assimp team
+# Copyright (c) 2006-2017, assimp team
 # All rights reserved.
 #
 # Redistribution and use of this software in source and binary forms,
@@ -33,10 +32,9 @@
 # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-#
 #----------------------------------------------------------------------
 SET(CMAKE_LEGACY_CYGWIN_WIN32 0) # Remove when CMake >= 2.8.4 is required
-cmake_minimum_required( VERSION 2.8 )
+CMAKE_MINIMUM_REQUIRED( VERSION 2.8 )
 PROJECT( Assimp )
 
 # All supported options ###############################################
@@ -44,6 +42,10 @@ OPTION( BUILD_SHARED_LIBS
   "Build package with shared libraries."
   ON
 )
+OPTION( BUILD_FRAMEWORK
+  "Build package as Mac OS X Framework bundle."
+  OFF
+)
 OPTION( ASSIMP_DOUBLE_PRECISION
   "Set to ON to enable double precision processing"
   OFF
@@ -64,11 +66,11 @@ OPTION( ASSIMP_BUILD_ZLIB
   "Build your own zlib"
   OFF
 )
-option( ASSIMP_BUILD_ASSIMP_TOOLS
+OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
   "If the supplementary tools for Assimp are built in addition to the library."
   ON
 )
-option ( ASSIMP_BUILD_SAMPLES
+OPTION ( ASSIMP_BUILD_SAMPLES
   "If the official samples are built as well (needs Glut)."
   OFF
 )
@@ -77,34 +79,66 @@ OPTION ( ASSIMP_BUILD_TESTS
   ON
 )
 OPTION ( ASSIMP_COVERALLS
-   "Eańable this to measure test coverage."
-   OFF
+  "Enable this to measure test coverage."
+  OFF
+)
+OPTION ( ASSIMP_WERROR
+  "Treat warnings as errors."
+  OFF
+)
+OPTION ( ASSIMP_ASAN
+  "Enable AddressSanitizer."
+  OFF
+)
+OPTION ( ASSIMP_UBSAN
+  "Enable Undefined Behavior sanitizer."
+  OFF
 )
+OPTION ( SYSTEM_IRRXML
+  "Use system installed Irrlicht/IrrXML library."
+  OFF
+)
+OPTION ( BUILD_DOCS
+  "Build documentation using Doxygen."
+  OFF
+)
+
+if (WIN32)
+  ADD_DEFINITIONS( -DWIN32_LEAN_AND_MEAN )
+endif()
 
 IF(MSVC)
-  set (CMAKE_PREFIX_PATH "D:\\libs\\devil")
+  SET (CMAKE_PREFIX_PATH "D:\\libs\\devil")
   OPTION( ASSIMP_INSTALL_PDB
     "Install MSVC debug files."
     ON
   )
 ENDIF(MSVC)
 
+IF (BUILD_FRAMEWORK)
+  SET (BUILD_SHARED_LIBS ON)
+  MESSAGE(STATUS "Framework bundle building enabled")
+ENDIF(BUILD_FRAMEWORK)
+
 IF(NOT BUILD_SHARED_LIBS)
+  MESSAGE(STATUS "Shared libraries disabled")
   SET(LINK_SEARCH_START_STATIC TRUE)
+ELSE()
+  MESSAGE(STATUS "Shared libraries enabled")
 ENDIF(NOT BUILD_SHARED_LIBS)
 
 # Define here the needed parameters
-SET (ASSIMP_VERSION_MAJOR 3)
-SET (ASSIMP_VERSION_MINOR 3)
-SET (ASSIMP_VERSION_PATCH 1) # subversion revision?
+SET (ASSIMP_VERSION_MAJOR 4)
+SET (ASSIMP_VERSION_MINOR 1)
+SET (ASSIMP_VERSION_PATCH 0)
 SET (ASSIMP_VERSION ${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH})
-SET (ASSIMP_SOVERSION 3)
+SET (ASSIMP_SOVERSION 4)
 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 )
+ADD_DEFINITIONS( -DOPENDDL_NO_USE_CPP11 )
 set_property( GLOBAL PROPERTY CXX_STANDARD 11 )
 
 # Get the current working branch
@@ -126,68 +160,103 @@ EXECUTE_PROCESS(
 )
 
 IF(NOT GIT_COMMIT_HASH)
-  SET(GIT_COMMIT_HASH 0)
+    SET(GIT_COMMIT_HASH 0)
 ENDIF(NOT GIT_COMMIT_HASH)
 
 IF(ASSIMP_DOUBLE_PRECISION)
-  ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
+    ADD_DEFINITIONS(-DASSIMP_DOUBLE_PRECISION)
 ENDIF(ASSIMP_DOUBLE_PRECISION)
 
-configure_file(
+CONFIGURE_FILE(
   ${CMAKE_CURRENT_LIST_DIR}/revision.h.in
   ${CMAKE_CURRENT_BINARY_DIR}/revision.h
 )
 
-configure_file(
+CONFIGURE_FILE(
   ${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h.in
-  ${CMAKE_CURRENT_LIST_DIR}/include/assimp/config.h
+  ${CMAKE_CURRENT_BINARY_DIR}/include/assimp/config.h
 )
 
-include_directories(
+INCLUDE_DIRECTORIES(
     ./
+	include
     ${CMAKE_CURRENT_BINARY_DIR}
     ${CMAKE_CURRENT_BINARY_DIR}/include
 )
 
-SET(CMAKE_MODULE_PATH       "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
+LIST(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake-modules" )
 SET(LIBASSIMP_COMPONENT     "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}" )
 SET(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_MINOR}.${ASSIMP_VERSION_PATCH}-dev" )
 SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev)
 SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
 
-# Ensure that we do not run into issues like http://www.tcm.phy.cam.ac.uk/sw/inodes64.html on 32 bit linux
 IF( UNIX )
-  IF ( CMAKE_SIZEOF_VOID_P EQUAL 4) # only necessary for 32-bit linux
-    ADD_DEFINITIONS(-D_FILE_OFFSET_BITS=64 )
+  # 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()
-ENDIF()
 
-IF((CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX) AND NOT CMAKE_COMPILER_IS_MINGW)
-  IF (BUILD_SHARED_LIBS AND CMAKE_SIZEOF_VOID_P EQUAL 8) # -fPIC is only required for shared libs on 64 bit
-     SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fPIC")
-     SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
-  ENDIF()
+  # Use GNUInstallDirs for Unix predefined directories
+  INCLUDE(GNUInstallDirs)
+ENDIF( UNIX )
+
+
+# Grouped compiler settings
+IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
   # hide all not-exported symbols
-  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -Wall -std=c++0x" )
+  SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -fPIC -Wall -std=c++0x")
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+  SET(LIBSTDC++_LIBRARIES -lstdc++)
 ELSEIF(MSVC)
   # enable multi-core compilation with MSVC
   add_compile_options(/MP)
-ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" )
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -g -fvisibility=hidden -Wall -Wno-long-long -pedantic -std=c++11" )
+
+  # disable "elements of array '' will be default initialized" warning on MSVC2013
+  IF(MSVC12)
+    add_compile_options(/wd4351)
+  ENDIF()
+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_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
 ELSEIF( CMAKE_COMPILER_IS_MINGW )
-  SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wno-long-long -pedantic -std=c++11" )
-  add_definitions( -U__STRICT_ANSI__ )
+  SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fvisibility=hidden -Wall -Wno-long-long -std=c++11" )
+  SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+  ADD_DEFINITIONS( -U__STRICT_ANSI__ )
 ENDIF()
 
 if (ASSIMP_COVERALLS)
-    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")
+    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()
 
-INCLUDE (FindPkgConfig)
-INCLUDE_DIRECTORIES( include )
+if (ASSIMP_WERROR)
+  MESSAGE(STATUS "Treating warnings as errors")
+  IF (MSVC)
+    add_compile_options(/WX)
+  ELSE()
+    SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
+    SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
+  ENDIF()
+endif()
+
+if (ASSIMP_ASAN)
+    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()
+
+INCLUDE (FindPkgMacros)
 INCLUDE (PrecompiledHeader)
 
 # If this is an in-source build (CMAKE_SOURCE_DIR == CMAKE_BINARY_DIR),
@@ -217,20 +286,25 @@ ENDIF()
 # Only generate this target if no higher-level project already has
 IF (NOT TARGET uninstall)
   # 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")
 ENDIF()
 
 # 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-version.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/assimp-config-version.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)
 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 )
 
-IF( CMAKE_COMPILER_IS_GNUCXX )
-  SET(LIBSTDC++_LIBRARIES -lstdc++)
-ENDIF( CMAKE_COMPILER_IS_GNUCXX )
+IF( BUILD_DOCS )
+    add_subdirectory(doc)
+ENDIF( BUILD_DOCS )
+
+# Look for system installed irrXML
+IF ( SYSTEM_IRRXML )
+    find_package( IrrXML REQUIRED )
+ENDIF( SYSTEM_IRRXML )
 
 # Search for external dependencies, and build them from source if not found
 # Search for zlib
@@ -240,9 +314,9 @@ ENDIF( NOT ASSIMP_BUILD_ZLIB )
 
 IF( NOT ZLIB_FOUND )
   message(STATUS "compiling zlib from souces")
-  include(CheckIncludeFile)
-  include(CheckTypeSize)
-  include(CheckFunctionExists)
+  INCLUDE(CheckIncludeFile)
+  INCLUDE(CheckTypeSize)
+  INCLUDE(CheckFunctionExists)
   # compile from sources
   add_subdirectory(contrib/zlib)
   SET(ZLIB_FOUND 1)
@@ -255,9 +329,7 @@ ENDIF(NOT ZLIB_FOUND)
 INCLUDE_DIRECTORIES(${ZLIB_INCLUDE_DIR})
 
 # Search for unzip
-IF (PKG_CONFIG_FOUND)
-  PKG_CHECK_MODULES(UNZIP minizip)
-ENDIF (PKG_CONFIG_FOUND)
+use_pkgconfig(UNZIP minizip)
 
 IF ( ASSIMP_NO_EXPORT )
   ADD_DEFINITIONS( -DASSIMP_BUILD_NO_EXPORT)
@@ -328,6 +400,8 @@ ELSE (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
   ADD_DEFINITIONS( -DASSIMP_BUILD_NO_C4D_IMPORTER )
 ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 
+ADD_SUBDIRECTORY(contrib)
+
 ADD_SUBDIRECTORY( code/ )
 IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
   IF ( WIN32 AND DirectX_D3DX9_LIBRARY )
@@ -335,7 +409,7 @@ IF ( ASSIMP_BUILD_ASSIMP_TOOLS )
     IF ( ASSIMP_BUILD_ASSIMP_VIEW )
       ADD_SUBDIRECTORY( tools/assimp_view/ )
     ENDIF ( ASSIMP_BUILD_ASSIMP_VIEW )
-  ENDIF ( WIN32 )
+  ENDIF ( WIN32 AND DirectX_D3DX9_LIBRARY )
 
   ADD_SUBDIRECTORY( tools/assimp_cmd/ )
 
@@ -431,29 +505,41 @@ IF(CMAKE_CPACK_COMMAND AND UNIX AND ASSIMP_OPT_BUILD_PACKAGES)
 ENDIF()
 
 if(WIN32)
-	if (CMAKE_SIZEOF_VOID_P EQUAL 8)
-		SET(BIN_DIR "${PROJECT_SOURCE_DIR}/bin64/")
-		SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib64/")
-	elseif()
-		SET(BIN_DIR "${PROJECT_SOURCE_DIR}/bin32/")
-		SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/")
-	ENDIF()
-
-	if(MSVC12)
-		SET(ASSIMP_MSVC_VERSION "vc120")
-	elseif(MSVC14)
-		SET(ASSIMP_MSVC_VERSION "vc140")
-	ENDIF(MSVC12)
-
-	if(MSVC12 OR MSVC14)
-		add_custom_target(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." 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.lib	${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM)
-		add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll		${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll  VERBATIM)
-		add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM)
-		add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM)
-		add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM)
-		add_custom_command(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
-	ENDIF(MSVC12 OR MSVC14)
+  if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+    SET(BIN_DIR "${PROJECT_SOURCE_DIR}/bin64/")
+    SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib64/")
+  elseif()
+    SET(BIN_DIR "${PROJECT_SOURCE_DIR}/bin32/")
+    SET(LIB_DIR "${PROJECT_SOURCE_DIR}/lib32/")
+  ENDIF()
+
+  if(MSVC12)
+    SET(ASSIMP_MSVC_VERSION "vc120")
+  elseif(MSVC14)
+    SET(ASSIMP_MSVC_VERSION "vc140")
+  ENDIF(MSVC12)
+
+  if(MSVC12 OR MSVC14)
+    add_custom_target(UpdateAssimpLibsDebugSymbolsAndDLLs COMMENT "Copying Assimp Libraries ..." VERBATIM)
+    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.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.lib	${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM)
+      ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll		${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll  VERBATIM)
+      ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM)
+      ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM)
+      ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib VERBATIM)
+      ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/Debug/assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.pdb VERBATIM)
+    ELSE()
+      ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/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/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/assimp-${ASSIMP_MSVC_VERSION}-mt.lib	${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mt.lib VERBATIM)
+      ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.dll		${BIN_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.dll  VERBATIM)
+      ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.exp		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.exp VERBATIM)
+      ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.ilk VERBATIM)
+      ADD_CUSTOM_COMMAND(TARGET UpdateAssimpLibsDebugSymbolsAndDLLs COMMAND ${CMAKE_COMMAND} -E copy ${CMAKE_BINARY_DIR}/code/assimp-${ASSIMP_MSVC_VERSION}-mtd.lib		${LIB_DIR}assimp-${ASSIMP_MSVC_VERSION}-mtd.lib 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(MSVC12 OR MSVC14)
 ENDIF (WIN32)

+ 168 - 160
CREDITS

@@ -1,160 +1,168 @@
-===============================================================
-Open Asset Import Library (Assimp)
-Developers and Contributors
-===============================================================
-
-The following is a non-exhaustive list of all constributors over the years.
-If you think your name should be listed here, drop us a line and we'll add you.
-
-- Alexander Gessler,
-3DS-, BLEND-, ASE-, DXF-, HMP-, MDL-, MD2-, MD3-, MD5-, MDC-, NFF-, PLY-, STL-, RAW-, OFF-, MS3D-, Q3D- and LWO-Loader, Assimp-Viewer, assimp-cmd, -noboost, Website (Design).
-
-- Thomas Schulze,
-X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation.
-
-- Kim Kulling,
-Obj-, Q3BSD-, OpenGEX-Loader, Logging system, CMake-build-environment, Linux-build, Website ( Admin ), Coverity ( Admin ), Glitter ( Admin ).
-
-- R.Schmidt,
-Linux build, eclipse support.
-
-- Matthias Gubisch,
-Assimp.net
-Visual Studio 9 support, bugfixes.
-
-- Mark Sibly
-B3D-Loader, Assimp testing
-
-- Jonathan Klein
-Ogre Loader, VC2010 fixes and CMake fixes.
-
-- Sebastian Hempel,
-PyAssimp (first version)
-Compile-Bugfixes for mingw, add environment for static library support in make.
-
-- Jonathan Pokrass
-Supplied a bugfix concerning the scaling in the md3 loader.
-
-- Andrew Galante,
-Submitted patches to make Assimp compile with GCC-4, a makefile and the xcode3 workspace.
-
-- Andreas Nagel
-First Assimp testing & verification under Windows Vista 64 Bit.
-
-- Marius Schr�der
-Allowed us to use many of his models for screenshots and testing.
-
-- Christian Schubert
-Supplied various XFiles for testing purposes.
-
-- Tizian Wieland
-Searched the web for hundreds of test models for internal use
-
-- John Connors
-Supplied patches for linux and SCons.
-
-- T. R.
-The GUY who performed some of the CSM mocaps.
-
-- Andy Maloney
-Contributed fixes for the documentation and the doxygen markup
-
-- Zhao Lei
-Contributed several bugfixes fixing memory leaks and improving float parsing 
-
-- sueastside
-Updated PyAssimp to the latest Assimp data structures and provided a script to keep the Python binding up-to-date.
-
-- Tobias Rittig
-Collada testing with Cinema 4D
-
-- Brad Grantham
-Improvements in OpenGL-Sample.
-
-- Robert Ramirez
-Add group loading feature to Obj-Loader.
-
-- Chris Maiwald
-Many bugreports, improving Assimp's portability, regular testing & feedback.
-
-- Stepan Hrbek
-Bugreport and fix for a obj-materialloader crash.
-
-- David Nadlinger
-D bindings, CMake install support. 
-
-- Dario Accornero
-Contributed several patches regarding Mac OS/XCode targets, bug reports.
-
-- Martin Walser (Samhayne)
-Contributed the 'SimpleTexturedOpenGl' sample.
-
-- Matthias Fauconneau
-Contributed a fix for the Q3-BSP loader.
-
-- J�rgen P. Tjern�
-Contributed updated and improved xcode workspaces
-
-- drparallax
-Contributed the /samples/SimpleAssimpViewX sample
-
-- Carsten Fuchs
-Contributed a fix for the Normalize method in aiQuaternion.
-
-- dbburgess
-Contributes a Android-specific build issue: log the hardware architecture for ARM.
-
-- alfiereinre7
-Contributes a obj-fileparser fix: missing tokens in the obj-token list.
-
-- Roman Kharitonov
-Contributes a fix for the configure script environment.
-
-- Ed Diana
-Contributed AssimpDelphi (/port/AssimpDelphi).
-
-- rdb 
-Contributes a bundle of fixes and improvements for the bsp-importer.
-
-- Mick P
-For contributing the De-bone postprocessing step and filing various bug reports.
-
-- Rosen Diankov
-Contributed patches to build assimp debian packages using cmake.
-
-- Mark Page
-Contributed a patch to fix the VertexTriangleAdjacency postprocessing step.
-
-- IOhannes
-Contributed the Debian build fixes ( architecture macro ).
-
-- gellule
-Several LWO and LWS fixes (pivoting). 
-
-- Marcel Metz
-GCC/Linux fixes for the SimpleOpenGL sample.
-
-- Brian Miller
-Bugfix for a compiler fix for iOS on arm.
-
-- S�verin Lemaignan
-Rewrite of PyAssimp, distutils and Python3 support
-
-- albert-wang
-Bugfixes for the collada parser
-
-- Ya ping Jin
-Bugfixes for uv-tanget calculation.
-
-- Jonne Nauha
-Ogre Binary format support
-
-- Filip Wasil, Tieto Poland Sp. z o.o.
-Android JNI asset extraction support
-
-- Richard Steffen
-Contributed ExportProperties interface
-Contributed X File exporter
-Contributed Step (stp) exporter
-
-
+===============================================================
+Open Asset Import Library (Assimp)
+Developers and Contributors
+===============================================================
+
+The following is a non-exhaustive list of all constributors over the years.
+If you think your name should be listed here, drop us a line and we'll add you.
+
+- Alexander Gessler,
+3DS-, BLEND-, ASE-, DXF-, HMP-, MDL-, MD2-, MD3-, MD5-, MDC-, NFF-, PLY-, STL-, RAW-, OFF-, MS3D-, Q3D- and LWO-Loader, Assimp-Viewer, assimp-cmd, -noboost, Website (Design).
+
+- Thomas Schulze,
+X-, Collada-, BVH-Loader, Postprocessing framework. Data structure & Interface design, documentation.
+
+- Kim Kulling,
+Obj-, Q3BSD-, OpenGEX-Loader, Logging system, CMake-build-environment, Linux-build, Website ( Admin ), Coverity ( Admin ), Glitter ( Admin ).
+
+- R.Schmidt,
+Linux build, eclipse support.
+
+- Matthias Gubisch,
+Assimp.net
+Visual Studio 9 support, bugfixes.
+
+- Mark Sibly
+B3D-Loader, Assimp testing
+
+- Jonathan Klein
+Ogre Loader, VC2010 fixes and CMake fixes.
+
+- Sebastian Hempel,
+PyAssimp (first version)
+Compile-Bugfixes for mingw, add environment for static library support in make.
+
+- Jonathan Pokrass
+Supplied a bugfix concerning the scaling in the md3 loader.
+
+- Andrew Galante,
+Submitted patches to make Assimp compile with GCC-4, a makefile and the xcode3 workspace.
+
+- Andreas Nagel
+First Assimp testing & verification under Windows Vista 64 Bit.
+
+- Marius Schr�der
+Allowed us to use many of his models for screenshots and testing.
+
+- Christian Schubert
+Supplied various XFiles for testing purposes.
+
+- Tizian Wieland
+Searched the web for hundreds of test models for internal use
+
+- John Connors
+Supplied patches for linux and SCons.
+
+- T. R.
+The GUY who performed some of the CSM mocaps.
+
+- Andy Maloney
+Contributed fixes for the documentation and the doxygen markup
+
+- Zhao Lei
+Contributed several bugfixes fixing memory leaks and improving float parsing 
+
+- sueastside
+Updated PyAssimp to the latest Assimp data structures and provided a script to keep the Python binding up-to-date.
+
+- Tobias Rittig
+Collada testing with Cinema 4D
+
+- Brad Grantham
+Improvements in OpenGL-Sample.
+
+- Robert Ramirez
+Add group loading feature to Obj-Loader.
+
+- Chris Maiwald
+Many bugreports, improving Assimp's portability, regular testing & feedback.
+
+- Stepan Hrbek
+Bugreport and fix for a obj-materialloader crash.
+
+- David Nadlinger
+D bindings, CMake install support.
+
+- Dario Accornero
+Contributed several patches regarding Mac OS/XCode targets, bug reports.
+
+- Martin Walser (Samhayne)
+Contributed the 'SimpleTexturedOpenGl' sample.
+
+- Matthias Fauconneau
+Contributed a fix for the Q3-BSP loader.
+
+- Jørgen P. Tjernø
+Contributed updated and improved xcode workspaces
+
+- drparallax
+Contributed the /samples/SimpleAssimpViewX sample
+
+- Carsten Fuchs
+Contributed a fix for the Normalize method in aiQuaternion.
+
+- dbburgess
+Contributes a Android-specific build issue: log the hardware architecture for ARM.
+
+- alfiereinre7
+Contributes a obj-fileparser fix: missing tokens in the obj-token list.
+
+- Roman Kharitonov
+Contributes a fix for the configure script environment.
+
+- Ed Diana
+Contributed AssimpDelphi (/port/AssimpDelphi).
+
+- rdb
+Contributes a bundle of fixes and improvements for the bsp-importer.
+
+- Mick P
+For contributing the De-bone postprocessing step and filing various bug reports.
+
+- Rosen Diankov
+Contributed patches to build assimp debian packages using cmake.
+
+- Mark Page
+Contributed a patch to fix the VertexTriangleAdjacency postprocessing step.
+
+- IOhannes
+Contributed the Debian build fixes ( architecture macro ).
+
+- gellule
+Several LWO and LWS fixes (pivoting). 
+
+- Marcel Metz
+GCC/Linux fixes for the SimpleOpenGL sample.
+
+- Brian Miller
+Bugfix for a compiler fix for iOS on arm.
+
+- Séverin Lemaignan
+Rewrite of PyAssimp, distutils and Python3 support
+
+- albert-wang
+Bugfixes for the collada parser
+
+- Ya ping Jin
+Bugfixes for uv-tanget calculation.
+
+- Jonne Nauha
+Ogre Binary format support
+
+- Filip Wasil, Tieto Poland Sp. z o.o.
+Android JNI asset extraction support
+
+- Richard Steffen
+Contributed ExportProperties interface
+Contributed X File exporter
+Contributed Step (stp) exporter
+
+For a more detailed list just check: https://github.com/assimp/assimp/network/members
+
+Patreons:
+- migenius
+- Marcus
+- Cort
+- elect
+- Steffen
+

+ 78 - 78
LICENSE

@@ -1,78 +1,78 @@
-Open Asset Import Library (assimp)
-
-Copyright (c) 2006-2016, assimp team
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the
-following conditions are met:
-
-* Redistributions of source code must retain the above
-  copyright notice, this list of conditions and the
-  following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-  copyright notice, this list of conditions and the
-  following disclaimer in the documentation and/or other
-  materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-  contributors may be used to endorse or promote products
-  derived from this software without specific prior
-  written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-
-******************************************************************************
-
-AN EXCEPTION applies to all files in the ./test/models-nonbsd folder.
-These are 3d models for testing purposes, from various free sources
-on the internet. They are - unless otherwise stated - copyright of
-their respective creators, which may impose additional requirements
-on the use of their work. For any of these models, see
-<model-name>.source.txt for more legal information. Contact us if you
-are a copyright holder and believe that we credited you inproperly or
-if you don't want your files to appear in the repository.
-
-
-******************************************************************************
-
-Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
-http://code.google.com/p/poly2tri/
-
-All rights reserved.
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-* Redistributions of source code must retain the above copyright notice,
-  this list of conditions and the following disclaimer.
-* Redistributions in binary form must reproduce the above copyright notice,
-  this list of conditions and the following disclaimer in the documentation
-  and/or other materials provided with the distribution.
-* Neither the name of Poly2Tri nor the names of its contributors may be
-  used to endorse or promote products derived from this software without specific
-  prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+Open Asset Import Library (assimp)
+
+Copyright (c) 2006-2016, assimp team
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+  copyright notice, this list of conditions and the
+  following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+  copyright notice, this list of conditions and the
+  following disclaimer in the documentation and/or other
+  materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+  contributors may be used to endorse or promote products
+  derived from this software without specific prior
+  written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+
+
+******************************************************************************
+
+AN EXCEPTION applies to all files in the ./test/models-nonbsd folder.
+These are 3d models for testing purposes, from various free sources
+on the internet. They are - unless otherwise stated - copyright of
+their respective creators, which may impose additional requirements
+on the use of their work. For any of these models, see
+<model-name>.source.txt for more legal information. Contact us if you
+are a copyright holder and believe that we credited you inproperly or
+if you don't want your files to appear in the repository.
+
+
+******************************************************************************
+
+Poly2Tri Copyright (c) 2009-2010, Poly2Tri Contributors
+http://code.google.com/p/poly2tri/
+
+All rights reserved.
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice,
+  this list of conditions and the following disclaimer.
+* Redistributions in binary form must reproduce the above copyright notice,
+  this list of conditions and the following disclaimer in the documentation
+  and/or other materials provided with the distribution.
+* Neither the name of Poly2Tri nor the names of its contributors may be
+  used to endorse or promote products derived from this software without specific
+  prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

+ 170 - 140
Readme.md

@@ -1,140 +1,170 @@
-Open Asset Import Library (assimp)
-==================================
-
-[![Linux Build Status](https://travis-ci.org/assimp/assimp.png)](https://travis-ci.org/assimp/assimp)
-[![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
-<a href="https://scan.coverity.com/projects/5607">
-  <img alt="Coverity Scan Build Status"
-       src="https://scan.coverity.com/projects/5607/badge.svg"/>
-</a>
-[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
-<br>
-
-APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
-
-Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
-
-This is the development trunk containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [assimp.sf.net](http://assimp.sf.net) or from *nix package repositories.
-The current build status is:
-
-Gitter chat: [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
-__[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.__
-
-#### Supported file formats ####
-
-A full list [is here](http://assimp.sourceforge.net/main_features_formats.html).
-__Importers__:
-
-- 3DS
-- BLEND (Blender)
-- DAE/Collada
-- FBX
-- IFC-STEP
-- ASE
-- DXF
-- HMP
-- MD2
-- MD3
-- MD5
-- MDC
-- MDL
-- NFF
-- PLY
-- STL
-- X
-- OBJ
-- OpenGEX
-- SMD
-- LWO
-- LXO
-- LWS  
-- TER
-- AC3D
-- MS3D
-- COB
-- Q3BSP
-- XGL
-- CSM
-- BVH
-- B3D
-- NDO
-- Ogre Binary
-- Ogre XML
-- Q3D
-- ASSBIN (Assimp custom format)
-- glTF (partial)
-- 3MF
-
-Additionally, some formats are supported by dependency on non-free code or external SDKs (not built by default):
-
-- C4D (https://github.com/acgessler/assimp-cinema4d)
-
-__Exporters__:
-
-- DAE (Collada)
-- STL
-- OBJ
-- PLY
-- X
-- 3DS
-- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
-- ASSBIN
-- STEP
-- glTF (partial)
-
-### 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.
-
-### Ports ###
-* [Android](port/AndroidJNI/README.md)
-* [Python](port/PyAssimp/README.md)
-* [.NET](port/AssimpNET/Readme.md)
-* [Pascal](port/AssimpPascal/Readme.md)
-
-#### Repository structure ####
-Open Asset Import Library is implemented in C++. The directory structure is:
-
-	/code		Source code
-	/contrib	Third-party libraries
-	/doc		Documentation (doxysource and pre-compiled docs)
-	/include	Public header C and C++ header files
-	/scripts 	Scripts used to generate the loading code for some formats
-	/port		Ports to other languages and scripts to maintain those.
-	/test		Unit- and regression tests, test suite of models
-	/tools		Tools (old assimp viewer, command line `assimp`)
-	/samples	A small number of samples to illustrate possible
-                        use cases for Assimp
-	/workspaces	Build environments for vc,xcode,... (deprecated,
-			CMake has superseeded all legacy build options!)
-
-
-### Where to get help ###
-For more information, visit [our website](http://assimp.sourceforge.net/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
-(CHMs for Windows are included in some release packages and should be located right here in the root folder).
-
-If the docs don't solve your problem, ask on [StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
-
-For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_
-  [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions)
-
-Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
-
-And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
-
-### Contributing ###
-Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
-a pull request with your changes against the main repository's `master` branch.
-
-### Donate ###
-If you like assimp, consider buying us a beer (or two):
-[Donate](http://sourceforge.net/donate/index.php?group_id=226462)
-
-### License ###
-Our license is based on the modified, __3-clause BSD__-License.
-
-An _informal_ summary is: do whatever you want, but include Assimp's license text with your product -
-and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp.
-For the legal details, see the `LICENSE` file.
-
-### Why this name ###
-Sorry, we're germans :-), no english native speakers ...
+Open Asset Import Library (assimp)
+==================================
+A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
+### Current build status ###
+[![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp)
+[![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
+<a href="https://scan.coverity.com/projects/5607">
+  <img alt="Coverity Scan Build Status"
+       src="https://scan.coverity.com/projects/5607/badge.svg"/>
+</a>
+[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
+[![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+<br>
+
+APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
+
+Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
+
+This is the development repo containing the latest features and bugfixes. For productive use though, we recommend one of the stable releases available from [Github Assimp Releases](https://github.com/assimp/assimp/releases).
+
+Monthly donations via Patreon:
+<br>[![Patreon](https://cloud.githubusercontent.com/assets/8225057/5990484/70413560-a9ab-11e4-8942-1a63607c0b00.png)](http://www.patreon.com/assimp)
+
+<br>
+
+One-off donations via PayPal:
+<br>[![PayPal](https://www.paypalobjects.com/en_US/i/btn/btn_donate_LG.gif)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4)
+
+<br>
+
+Please check our Wiki as well: https://github.com/assimp/assimp/wiki
+
+#### Supported file formats ####
+
+A full list [is here](http://assimp.org/main_features_formats.html).
+__Importers__:
+- 3D
+- 3DS
+- 3MF
+- AC
+- AC3D
+- ACC
+- AMJ
+- ASE
+- ASK
+- B3D;
+- BLEND (Blender)
+- BVH
+- COB
+- CMS
+- DAE/Collada
+- DXF
+- ENFF
+- FBX
+- glTF 1.0 + GLB
+- glTF 2.0
+- HMB
+- IFC-STEP
+- IRR / IRRMESH
+- LWO
+- LWS
+- LXO
+- MD2
+- MD3
+- MD5
+- MDC
+- MDL
+- MESH / MESH.XML
+- MOT
+- MS3D
+- NDO
+- NFF
+- OBJ
+- OFF
+- OGEX
+- PLY
+- PMX
+- PRJ
+- Q3O
+- Q3S
+- RAW
+- SCN
+- SIB
+- SMD
+- STL
+- STP
+- TER
+- UC
+- VTA
+- X
+- X3D
+- XGL
+- ZGL
+
+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)
+
+__Exporters__:
+
+- DAE (Collada)
+- STL
+- OBJ
+- PLY
+- X
+- 3DS
+- JSON (for WebGl, via https://github.com/acgessler/assimp2json)
+- ASSBIN
+- STEP
+- glTF 1.0 (partial)
+- glTF 2.0 (partial)
+
+### 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.
+
+### Ports ###
+* [Android](port/AndroidJNI/README.md)
+* [Python](port/PyAssimp/README.md)
+* [.NET](port/AssimpNET/Readme.md)
+* [Pascal](port/AssimpPascal/Readme.md)
+* [Javascript (Alpha)](https://github.com/makc/assimp2json)
+* [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)
+
+### Other tools ###
+[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
+
+#### Repository structure ####
+Open Asset Import Library is implemented in C++. The directory structure is:
+
+	/code		Source code
+	/contrib	Third-party libraries
+	/doc		Documentation (doxysource and pre-compiled docs)
+	/include	Public header C and C++ header files
+	/scripts 	Scripts used to generate the loading code for some formats
+	/port		Ports to other languages and scripts to maintain those.
+	/test		Unit- and regression tests, test suite of models
+	/tools		Tools (old assimp viewer, command line `assimp`)
+	/samples	A small number of samples to illustrate possible
+                        use cases for Assimp
+	/workspaces	Build environments for vc,xcode,... (deprecated,
+			CMake has superseeded all legacy build options!)
+
+
+### Where to get help ###
+For more information, visit [our website](http://assimp.org/). Or check out the `./doc`- folder, which contains the official documentation in HTML format.
+(CHMs for Windows are included in some release packages and should be located right here in the root folder).
+
+If the docs don't solve your problem, ask on [StackOverflow](http://stackoverflow.com/questions/tagged/assimp?sort=newest). If you think you found a bug, please open an issue on Github.
+
+For development discussions, there is also a (very low-volume) mailing list, _assimp-discussions_
+  [(subscribe here)]( https://lists.sourceforge.net/lists/listinfo/assimp-discussions)
+
+Open Asset Import Library is a library to load various 3d file formats into a shared, in-memory format. It supports more than __40 file formats__ for import and a growing selection of file formats for export.
+
+And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)<br>
+
+### Contributing ###
+Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
+a pull request with your changes against the main repository's `master` branch.
+
+### License ###
+Our license is based on the modified, __3-clause BSD__-License.
+
+An _informal_ summary is: do whatever you want, but include Assimp's license text with your product -
+and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you may link statically to Assimp.
+For the legal details, see the `LICENSE` file.
+
+### Why this name ###
+Sorry, we're germans :-), no english native speakers ...

+ 43 - 22
appveyor.yml

@@ -10,33 +10,54 @@ branches:
   only:
     - master
 
+matrix:
+  fast_finish: true
+    
+image:
+  - Visual Studio 2013
+  - Visual Studio 2015
+  - Visual Studio 2017
+    
 platform:
-    - x86
-    - x64
-
-configuration:
-  - 14 2015
-  - 12 2013
-  #- MinGW
-  #- 10 2010 # only works for x86
-
-init:
-- if "%platform%" EQU "x64" ( for %%a in (2008 2010 MinGW) do ( if "%Configuration%"=="%%a" (echo "Skipping unsupported configuration" && exit /b 1 ) ) )
+  - Win32
+  - x64
+  
+configuration: Release
 
 install:
-# Make compiler command line tools available
-- call c:\projects\assimp\scripts\appveyor\compiler_setup.bat
-
-build_script:
-- cd c:\projects\assimp
-- if "%platform%" equ "x64" (cmake CMakeLists.txt -G "Visual Studio %Configuration% Win64")
-- if "%platform%" equ "x86" (cmake CMakeLists.txt -G "Visual Studio %Configuration%")
-- if "%platform%" equ "x64" (msbuild /m /p:Configuration=Release /p:Platform="x64" Assimp.sln)
-- if "%platform%" equ "x86" (msbuild /m /p:Configuration=Release /p:Platform="Win32" Assimp.sln)
-
+  - set PATH=C:\Ruby24-x64\bin;%PATH%
+  - set CMAKE_DEFINES -DASSIMP_WERROR=ON
+  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2013" set CMAKE_GENERATOR_NAME=Visual Studio 12 2013
+  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2015" set CMAKE_GENERATOR_NAME=Visual Studio 14 2015
+  - if "%APPVEYOR_BUILD_WORKER_IMAGE%"=="Visual Studio 2017" set CMAKE_GENERATOR_NAME=Visual Studio 15 2017
+  - if "%platform%"=="x64" set CMAKE_GENERATOR_NAME=%CMAKE_GENERATOR_NAME% Win64
+  - cmake %CMAKE_DEFINES% -G "%CMAKE_GENERATOR_NAME%"
+  
+cache:
+  - code\assimp.dir\%CONFIGURATION%
+  - contrib\zlib\zlibstatic.dir\%CONFIGURATION%
+  - contrib\zlib\zlib.dir\%CONFIGURATION%
+  - tools\assimp_cmd\assimp_cmd.dir\%CONFIGURATION%
+  - tools\assimp_view\assimp_viewer.dir\%CONFIGURATION%
+  - test\unit.dir\%CONFIGURATION%
+  - bin\.mtime_cache
+  
+before_build:
+  - ruby scripts\AppVeyor\mtime_cache -g scripts\AppVeyor\cacheglobs.txt -c bin\.mtime_cache\cache.json
+  
+build:
+  parallel: true
+  project: Assimp.sln
+  
 after_build:
-  - 7z a assimp.7z c:\projects\assimp\bin\release\* c:\projects\assimp\lib\release\*
+  - 7z a assimp.7z bin\%CONFIGURATION%\* lib\%CONFIGURATION%\*
+
+test_script:
+  - cmd: bin\%CONFIGURATION%\unit.exe --gtest_output=xml:testout.xml
 
+on_finish:
+  - ps: (new-object net.webclient).UploadFile("https://ci.appveyor.com/api/testresults/junit/$($env:APPVEYOR_JOB_ID)", (Resolve-Path .\testout.xml))
+  
 artifacts:
   - path: assimp.7z
     name: assimp_lib

+ 36 - 1
assimp-config-version.cmake.in

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

+ 1 - 1
assimp.pc.in

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

+ 2 - 2
cmake-modules/CoverallsGenerateGcov.cmake

@@ -310,7 +310,7 @@ foreach (GCOV_FILE ${GCOV_FILES})
 	message("MD5: ${GCOV_SRC_PATH} = ${GCOV_CONTENTS_MD5}")
 
 	# Loads the gcov file as a list of lines.
-	# (We first open the file and replace all occurences of [] with _
+	# (We first open the file and replace all occurrences of [] with _
 	#  because CMake will fail to parse a line containing unmatched brackets...
 	#  also the \ to escaped \n in macros screws up things.)
 	# https://public.kitware.com/Bug/view.php?id=15369
@@ -329,7 +329,7 @@ foreach (GCOV_FILE ${GCOV_FILES})
 	# Instead of trying to parse the source from the
 	# gcov file, simply read the file contents from the source file.
 	# (Parsing it from the gcov is hard because C-code uses ; in many places
-	#  which also happens to be the same as the CMake list delimeter).
+	#  which also happens to be the same as the CMake list delimiter).
 	file(READ ${GCOV_SRC_PATH} GCOV_FILE_SOURCE)
 
 	string(REPLACE "\\" "\\\\" GCOV_FILE_SOURCE "${GCOV_FILE_SOURCE}")

+ 72 - 0
cmake-modules/FindDevIL.cmake

@@ -0,0 +1,72 @@
+# Distributed under the OSI-approved BSD 3-Clause License.  See accompanying
+# file Copyright.txt or https://cmake.org/licensing for details.
+
+#.rst:
+# FindDevIL
+# ---------
+#
+#
+#
+# This module locates the developer's image library.
+# http://openil.sourceforge.net/
+#
+# This module sets:
+#
+# ::
+#
+#    IL_LIBRARIES -   the name of the IL library. These include the full path to
+#                     the core DevIL library. This one has to be linked into the
+#                     application.
+#    ILU_LIBRARIES -  the name of the ILU library. Again, the full path. This
+#                     library is for filters and effects, not actual loading. It
+#                     doesn't have to be linked if the functionality it provides
+#                     is not used.
+#    ILUT_LIBRARIES - the name of the ILUT library. Full path. This part of the
+#                     library interfaces with OpenGL. It is not strictly needed
+#                     in applications.
+#    IL_INCLUDE_DIR - where to find the il.h, ilu.h and ilut.h files.
+#    IL_FOUND -       this is set to TRUE if all the above variables were set.
+#                     This will be set to false if ILU or ILUT are not found,
+#                     even if they are not needed. In most systems, if one
+#                     library is found all the others are as well. That's the
+#                     way the DevIL developers release it.
+
+# TODO: Add version support.
+# Tested under Linux and Windows (MSVC)
+
+#include(${CMAKE_CURRENT_LIST_DIR}/FindPackageHandleStandardArgs.cmake)
+include(FindPackageHandleStandardArgs)
+
+find_path(IL_INCLUDE_DIR il.h
+  PATH_SUFFIXES include IL
+  DOC "The path to the directory that contains il.h"
+)
+
+#message("IL_INCLUDE_DIR is ${IL_INCLUDE_DIR}")
+
+find_library(IL_LIBRARIES
+  NAMES IL DEVIL
+  PATH_SUFFIXES lib64 lib lib32
+  DOC "The file that corresponds to the base il library."
+)
+
+#message("IL_LIBRARIES is ${IL_LIBRARIES}")
+
+find_library(ILUT_LIBRARIES
+  NAMES ILUT
+  PATH_SUFFIXES lib64 lib lib32
+  DOC "The file that corresponds to the il (system?) utility library."
+)
+
+#message("ILUT_LIBRARIES is ${ILUT_LIBRARIES}")
+
+find_library(ILU_LIBRARIES
+  NAMES ILU
+  PATH_SUFFIXES lib64 lib lib32
+  DOC "The file that corresponds to the il utility library."
+)
+
+#message("ILU_LIBRARIES is ${ILU_LIBRARIES}")
+
+FIND_PACKAGE_HANDLE_STANDARD_ARGS(IL DEFAULT_MSG
+                                  IL_LIBRARIES IL_INCLUDE_DIR)

+ 17 - 0
cmake-modules/FindIrrXML.cmake

@@ -0,0 +1,17 @@
+# Find IrrXMl from irrlicht project
+#
+# Find LibIrrXML headers and library
+#
+#   IRRXML_FOUND          - IrrXML found
+#   IRRXML_INCLUDE_DIR    - Headers location
+#   IRRXML_LIBRARY        - IrrXML main library
+
+find_path(IRRXML_INCLUDE_DIR irrXML.h
+    PATH_SUFFIXES include/irrlicht include/irrxml)
+find_library(IRRXML_LIBRARY IrrXML)
+
+include(FindPackageHandleStandardArgs)
+find_package_handle_standard_args(IrrXML REQUIRED_VARS IRRXML_INCLUDE_DIR IRRXML_LIBRARY)
+
+
+mark_as_advanced(IRRXML_INCLUDE_DIR IRRXML_LIBRARY)

+ 7 - 4
cmake-modules/FindPkgMacros.cmake

@@ -59,10 +59,13 @@ endmacro(clear_if_changed)
 
 # Try to get some hints from pkg-config, if available
 macro(use_pkgconfig PREFIX PKGNAME)
-  find_package(PkgConfig)
-  if (PKG_CONFIG_FOUND)
-    pkg_check_modules(${PREFIX} ${PKGNAME})
-  endif ()
+  # Android does not support PKG_CONFIG so we disable it
+  IF ( NOT ANDROID )
+    find_package(PkgConfig)
+    if (PKG_CONFIG_FOUND)
+      pkg_check_modules(${PREFIX} ${PKGNAME})
+    endif ()
+  ENDIF ( NOT ANDROID )
 endmacro (use_pkgconfig)
 
 # Couple a set of release AND debug libraries (or frameworks)

+ 1 - 1
cmake-modules/FindZLIB.cmake

@@ -11,7 +11,7 @@
 # Once done, this will define
 #
 #  ZLIB_FOUND - system has ZLIB
-#  ZLIB_INCLUDE_DIRS - the ZLIB include directories 
+#  ZLIB_INCLUDE_DIRS - the ZLIB include directories
 #  ZLIB_LIBRARIES - link these to use ZLIB
 
 include(FindPkgMacros)

+ 8 - 4
code/3DSConverter.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -55,18 +56,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 using namespace Assimp;
 
+static const unsigned int NotSet = 0xcdcdcdcd;
+
 // ------------------------------------------------------------------------------------------------
 // Setup final material indices, generae a default material if necessary
 void Discreet3DSImporter::ReplaceDefaultMaterial()
 {
-
     // Try to find an existing material that matches the
     // typical default material setting:
     // - no textures
     // - diffuse color (in grey!)
     // NOTE: This is here to workaround the fact that some
     // exporters are writing a default material, too.
-    unsigned int idx = 0xcdcdcdcd;
+    unsigned int idx( NotSet );
     for (unsigned int i = 0; i < mScene->mMaterials.size();++i)
     {
         std::string s = mScene->mMaterials[i].mName;
@@ -92,7 +94,9 @@ void Discreet3DSImporter::ReplaceDefaultMaterial()
         }
         idx = i;
     }
-    if (0xcdcdcdcd == idx)idx = (unsigned int)mScene->mMaterials.size();
+    if ( NotSet == idx ) {
+        idx = ( unsigned int )mScene->mMaterials.size();
+    }
 
     // now iterate through all meshes and through all faces and
     // find all faces that are using the default material

+ 10 - 4
code/3DSExporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -38,14 +39,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
-
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_3DS_EXPORTER
 
 #include "3DSExporter.h"
 #include "3DSLoader.h"
 #include "3DSHelper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "SplitLargeMeshes.h"
 #include "StringComparison.h"
 #include <assimp/IOSystem.hpp>
@@ -150,7 +150,7 @@ namespace {
 
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to 3DS. Prototyped and registered in Exporter.cpp
-void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+void ExportScene3DS(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
 {
     std::shared_ptr<IOStream> outfile (pIOSystem->Open(pFile, "wb"));
     if(!outfile) {
@@ -209,6 +209,12 @@ Discreet3DSExporter:: Discreet3DSExporter(std::shared_ptr<IOStream> outfile, con
     }
 }
 
+// ------------------------------------------------------------------------------------------------
+Discreet3DSExporter::~Discreet3DSExporter() {
+    // empty
+}
+
+
 // ------------------------------------------------------------------------------------------------
 int Discreet3DSExporter::WriteHierarchy(const aiNode& node, int seq, int sibling_level)
 {

+ 10 - 12
code/3DSExporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -48,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <memory>
 
 #include "StreamWriter.h"
-#include "./../include/assimp/material.h"
+#include <assimp/material.h>
 
 struct aiScene;
 struct aiNode;
@@ -59,23 +60,21 @@ namespace Assimp
 {
 
 // ------------------------------------------------------------------------------------------------
-/** Helper class to export a given scene to a 3DS file. */
+/**
+ *  @brief  Helper class to export a given scene to a 3DS file.
+ */
 // ------------------------------------------------------------------------------------------------
-class Discreet3DSExporter
-{
+class Discreet3DSExporter {
 public:
     Discreet3DSExporter(std::shared_ptr<IOStream> outfile, const aiScene* pScene);
+    ~Discreet3DSExporter();
 
 private:
-
     void WriteMeshes();
     void WriteMaterials();
     void WriteTexture(const aiMaterial& mat, aiTextureType type, uint16_t chunk_flags);
-
     void WriteFaceMaterialChunk(const aiMesh& mesh);
-
     int WriteHierarchy(const aiNode& node, int level, int sibling_level);
-
     void WriteString(const std::string& s);
     void WriteString(const aiString& s);
     void WriteColor(const aiColor3D& color);
@@ -83,7 +82,6 @@ private:
     void WritePercentChunk(double f);
 
 private:
-
     const aiScene* const scene;
     StreamWriterLE writer;
 
@@ -94,6 +92,6 @@ private:
 
 };
 
-}
+} // Namespace Assimp
 
-#endif
+#endif // AI_3DSEXPORTER_H_INC

+ 15 - 12
code/3DSHelper.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,15 +44,14 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_3DSFILEHELPER_H_INC
 #define AI_3DSFILEHELPER_H_INC
 
-
 #include "SpatialSort.h"
 #include "SmoothingGroups.h"
 #include "StringUtils.h"
 #include "qnan.h"
-#include "./../include/assimp/material.h"
-#include "./../include/assimp/camera.h"
-#include "./../include/assimp/light.h"
-#include "./../include/assimp/anim.h"
+#include <assimp/material.h>
+#include <assimp/camera.h>
+#include <assimp/light.h>
+#include <assimp/anim.h>
 #include <stdio.h> //sprintf
 
 namespace Assimp    {
@@ -63,16 +63,19 @@ namespace D3DS  {
 /** Discreet3DS class: Helper class for loading 3ds files. Defines chunks
 *  and data structures.
 */
-class Discreet3DS
-{
+class Discreet3DS {
 private:
-    inline Discreet3DS() {}
+    Discreet3DS() {
+        // empty
+    }
 
-public:
+    ~Discreet3DS() {
+        // empty
+    }
 
+public:
     //! data structure for a single chunk in a .3ds file
-    struct Chunk
-    {
+    struct Chunk {
         uint16_t    Flag;
         uint32_t    Size;
     } PACK_STRUCT;

+ 4 - 2
code/3DSLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
 #include "StringComparison.h"
 
 using namespace Assimp;
@@ -1379,7 +1381,7 @@ void Discreet3DSImporter::ParseColorChunk( aiColor3D* out, bool acceptPercent )
         bGamma = true;
 
     case Discreet3DS::CHUNK_RGBF:
-        if (sizeof(ai_real) * 3 > diff)   {
+        if (sizeof(float) * 3 > diff)   {
             *out = clrError;
             return;
         }

+ 2 - 1
code/3DSLoader.h

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 89 - 0
code/3MFXmlTags.h

@@ -0,0 +1,89 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+namespace Assimp {
+namespace D3MF {
+
+namespace XmlTag {
+    static const std::string model = "model";
+    static const std::string model_unit = "unit";
+    static const std::string metadata = "metadata";
+    static const std::string resources = "resources";
+    static const std::string object = "object";
+    static const std::string mesh = "mesh";
+    static const std::string vertices = "vertices";
+    static const std::string vertex = "vertex";
+    static const std::string triangles = "triangles";
+    static const std::string triangle = "triangle";
+    static const std::string x = "x";
+    static const std::string y = "y";
+    static const std::string z = "z";
+    static const std::string v1 = "v1";
+    static const std::string v2 = "v2";
+    static const std::string v3 = "v3";
+    static const std::string id = "id";
+    static const std::string name = "name";
+    static const std::string type = "type";
+    static const std::string build = "build";
+    static const std::string item = "item";
+    static const std::string objectid = "objectid";
+    static const std::string transform = "transform";
+
+    static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
+    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_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
+    static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships";
+    static const std::string RELS_RELATIONSHIP_NODE = "Relationship";
+    static const std::string RELS_ATTRIB_TARGET = "Target";
+    static const std::string RELS_ATTRIB_TYPE = "Type";
+    static const std::string RELS_ATTRIB_ID = "Id";
+    static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
+    static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
+    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_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
+
+}
+
+} // Namespace D3MF
+} // Namespace Assimp

+ 3 - 1
code/ACLoader.cpp

@@ -4,7 +4,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -60,6 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/scene.h>
 #include <assimp/config.h>
 #include <assimp/IOSystem.hpp>
+#include <assimp/importerdesc.h>
 #include <memory>
 
 using namespace Assimp;

+ 2 - 1
code/ACLoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 4 - 4
code/AMFImporter.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -51,11 +52,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AMFImporter_Macro.hpp"
 
 #include "fast_atof.h"
-#include "DefaultIOSystem.h"
+#include <assimp/DefaultIOSystem.h>
 
 // Header files, stdlib.
 #include <memory>
-#include <string>
 
 namespace Assimp
 {
@@ -353,7 +353,7 @@ static bool ParseHelper_Decode_Base64_IsBase64(const char pChar)
 void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector<uint8_t>& pOutputData) const
 {
     // With help from
-    // RenИ Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html
+    // René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html
     const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 
     uint8_t tidx = 0;

+ 12 - 12
code/AMFImporter.hpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -52,9 +53,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AMFImporter_Node.hpp"
 
 // Header files, Assimp.
-#include "assimp/DefaultLogger.hpp"
-#include "assimp/importerdesc.h"
-#include "assimp/ProgressHandler.hpp"
+#include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
 #include "assimp/types.h"
 #include "BaseImporter.h"
 #include "irrXMLWrapper.h"
@@ -135,18 +135,18 @@ private:
 	};
 
 	/// \struct SPP_Texture
-	/// Data type for postprocessing step. More suitable container for texture.
+	/// Data type for post-processing step. More suitable container for texture.
 	struct SPP_Texture
 	{
 		std::string ID;
-		size_t Width, Height, Depth;
-		bool Tiled;
-		decltype(aiTexture::achFormatHint) FormatHint;
-		uint8_t* Data;
+		size_t      Width, Height, Depth;
+		bool        Tiled;
+        char        FormatHint[ 9 ];// 8 for string + 1 for terminator.
+		uint8_t    *Data;
 	};
 
 	///	\struct SComplexFace
-	/// Data type for postprocessing step. Contain face data.
+	/// Data type for post-processing step. Contain face data.
 	struct SComplexFace
 	{
 		aiFace Face;///< Face vertices.
@@ -249,7 +249,7 @@ private:
 
 	/// \fn size_t PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B, const std::string& pID_A)
 	/// Return converted texture ID which related to specified source textures ID's. If converted texture does not exist then it will be created and ID on new
-	/// converted texture will be returned. Convertion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it
+	/// converted texture will be returned. Conversion: set of textures from \ref CAMFImporter_NodeElement_Texture to one \ref SPP_Texture and place it
 	/// to converted textures list.
 	/// Any of source ID's can be absent(empty string) or even one ID only specified. But at least one ID must be specified.
 	/// \param [in] pID_R - ID of source "red" texture.
@@ -378,7 +378,7 @@ private:
 	void XML_CheckNode_MustHaveChildren();
 
 	/// \fn bool XML_CheckNode_NameEqual(const std::string& pNodeName)
-	/// Chek if current node name is equal to pNodeName.
+	/// Check if current node name is equal to pNodeName.
 	/// \param [in] pNodeName - name for checking.
 	/// return true if current node name is equal to pNodeName, else - false.
 	bool XML_CheckNode_NameEqual(const std::string& pNodeName) { return mReader->getNodeName() == pNodeName; }

+ 2 - 1
code/AMFImporter_Geometry.cpp

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

+ 2 - 1
code/AMFImporter_Macro.hpp

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

+ 2 - 1
code/AMFImporter_Material.cpp

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

+ 25 - 48
code/AMFImporter_Node.hpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -59,18 +60,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 /// \class CAMFImporter_NodeElement
 /// Base class for elements of nodes.
-class CAMFImporter_NodeElement
-{
-	/***********************************************/
-	/******************** Types ********************/
-	/***********************************************/
+class CAMFImporter_NodeElement {
 
 public:
-
-	/// \enum EType
 	/// Define what data type contain node element.
-	enum EType
-	{
+	enum EType {
 		ENET_Color,        ///< Color element: <color>.
 		ENET_Constellation,///< Grouping element: <constellation>.
 		ENET_Coordinates,  ///< Coordinates element: <coordinates>.
@@ -91,52 +85,37 @@ public:
 		ENET_Invalid       ///< Element has invalid type and possible contain invalid data.
 	};
 
-	/***********************************************/
-	/****************** Constants ******************/
-	/***********************************************/
-
-public:
-
 	const EType Type;///< Type of element.
-
-	/***********************************************/
-	/****************** Variables ******************/
-	/***********************************************/
-
-public:
-
 	std::string ID;///< ID of element.
-	CAMFImporter_NodeElement* Parent;///< Parrent element. If nullptr then this node is root.
+	CAMFImporter_NodeElement* Parent;///< Parent element. If nullptr then this node is root.
 	std::list<CAMFImporter_NodeElement*> Child;///< Child elements.
 
-	/***********************************************/
-	/****************** Functions ******************/
-	/***********************************************/
+public:                                               /// Destructor, virtual..
+    virtual ~CAMFImporter_NodeElement() {
+        // empty
+    }
 
 private:
-
-	/// \fn CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement)
 	/// Disabled copy constructor.
 	CAMFImporter_NodeElement(const CAMFImporter_NodeElement& pNodeElement);
 
-	/// \fn CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement)
 	/// Disabled assign operator.
 	CAMFImporter_NodeElement& operator=(const CAMFImporter_NodeElement& pNodeElement);
 
-	/// \fn CAMFImporter_NodeElement()
 	/// Disabled default constructor.
 	CAMFImporter_NodeElement();
 
 protected:
-
-	/// \fn CAMFImporter_NodeElement(const EType pType, CAMFImporter_NodeElement* pParent)
 	/// In constructor inheritor must set element type.
 	/// \param [in] pType - element type.
 	/// \param [in] pParent - parent element.
 	CAMFImporter_NodeElement(const EType pType, CAMFImporter_NodeElement* pParent)
-		: Type(pType), Parent(pParent)
-	{}
-
+	: Type(pType)
+    , ID()
+    , Parent(pParent)
+    , Child() {
+        // empty
+    }
 };// class IAMFImporter_NodeElement
 
 /// \struct CAMFImporter_NodeElement_Constellation
@@ -158,7 +137,7 @@ struct CAMFImporter_NodeElement_Instance : public CAMFImporter_NodeElement
 {
 	/****************** Variables ******************/
 
-	std::string ObjectID;///< ID of object for instanciation.
+	std::string ObjectID;///< ID of object for instantiation.
 	/// \var Delta - The distance of translation in the x, y, or z direction, respectively, in the referenced object's coordinate system, to
 	/// create an instance of the object in the current constellation.
 	aiVector3D Delta;
@@ -399,25 +378,23 @@ struct CAMFImporter_NodeElement_Triangle : public CAMFImporter_NodeElement
 
 };// struct CAMFImporter_NodeElement_Triangle
 
-/// \struct CAMFImporter_NodeElement_Texture
 /// Structure that define texture node.
-struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement
-{
-	/****************** Variables ******************/
-
+struct CAMFImporter_NodeElement_Texture : public CAMFImporter_NodeElement {
 	size_t Width, Height, Depth;///< Size of the texture.
 	std::vector<uint8_t> Data;///< Data of the texture.
 	bool Tiled;
 
-	/****************** Functions ******************/
-
-	/// \fn CAMFImporter_NodeElement_Texture(CAMFImporter_NodeElement* pParent)
 	/// Constructor.
 	/// \param [in] pParent - pointer to parent node.
 	CAMFImporter_NodeElement_Texture(CAMFImporter_NodeElement* pParent)
-		: CAMFImporter_NodeElement(ENET_Texture, pParent)
-	{}
-
+	: CAMFImporter_NodeElement(ENET_Texture, pParent)
+    , Width( 0 )
+    , Height( 0 )
+    , Depth( 0 )
+    , Data()
+    , Tiled( false ){
+        // empty
+    }
 };// struct CAMFImporter_NodeElement_Texture
 
 #endif // INCLUDED_AI_AMF_IMPORTER_NODE_H

+ 39 - 29
code/AMFImporter_Postprocess.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -49,20 +50,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "AMFImporter.hpp"
 
 // Header files, Assimp.
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "StandardShapes.h"
 #include "StringUtils.h"
 
 // Header files, stdlib.
-#include <algorithm>
 #include <iterator>
 
 namespace Assimp
 {
 
-aiColor4D AMFImporter::SPP_Material::GetColor(const float pX, const float pY, const float pZ) const
+aiColor4D AMFImporter::SPP_Material::GetColor(const float /*pX*/, const float /*pY*/, const float /*pZ*/) const
 {
-aiColor4D tcol;
+    aiColor4D tcol;
 
 	// Check if stored data are supported.
 	if(Composition.size() != 0)
@@ -93,8 +93,8 @@ aiColor4D tcol;
 void AMFImporter::PostprocessHelper_CreateMeshDataArray(const CAMFImporter_NodeElement_Mesh& pNodeElement, std::vector<aiVector3D>& pVertexCoordinateArray,
 														std::vector<CAMFImporter_NodeElement_Color*>& pVertexColorArray) const
 {
-CAMFImporter_NodeElement_Vertices* vn = nullptr;
-size_t col_idx;
+    CAMFImporter_NodeElement_Vertices* vn = nullptr;
+    size_t col_idx;
 
 	// All data stored in "vertices", search for it.
 	for(CAMFImporter_NodeElement* ne_child: pNodeElement.Child)
@@ -142,8 +142,8 @@ size_t col_idx;
 size_t AMFImporter::PostprocessHelper_GetTextureID_Or_Create(const std::string& pID_R, const std::string& pID_G, const std::string& pID_B,
 																const std::string& pID_A)
 {
-size_t TextureConverted_Index;
-std::string TextureConverted_ID;
+    size_t TextureConverted_Index;
+    std::string TextureConverted_ID;
 
 	// check input data
 	if(pID_R.empty() && pID_G.empty() && pID_B.empty() && pID_A.empty())
@@ -261,20 +261,31 @@ std::string TextureConverted_ID;
 	size_t off_b = 0;
 
 	// Calculate size of the target array and rule how data will be copied.
-	if(!pID_R.empty()) { tex_size += src_texture[0]->Data.size(); step++, off_g++, off_b++; }
-	if(!pID_G.empty()) { tex_size += src_texture[1]->Data.size(); step++, off_b++; }
-	if(!pID_B.empty()) { tex_size += src_texture[2]->Data.size(); step++; }
-	if(!pID_A.empty()) { tex_size += src_texture[3]->Data.size(); step++; }
-
-	// Create target array.
+    if(!pID_R.empty() && nullptr != src_texture[ 0 ] ) {
+        tex_size += src_texture[0]->Data.size(); step++, off_g++, off_b++;
+    }
+    if(!pID_G.empty() && nullptr != src_texture[ 1 ] ) {
+        tex_size += src_texture[1]->Data.size(); step++, off_b++;
+    }
+    if(!pID_B.empty() && nullptr != src_texture[ 2 ] ) {
+        tex_size += src_texture[2]->Data.size(); step++;
+    }
+    if(!pID_A.empty() && nullptr != src_texture[ 3 ] ) {
+        tex_size += src_texture[3]->Data.size(); step++;
+    }
+
+    // Create target array.
 	converted_texture.Data = new uint8_t[tex_size];
 	// And copy data
 	auto CopyTextureData = [&](const std::string& pID, const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void
 	{
 		if(!pID.empty())
 		{
-			for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++)
-				converted_texture.Data[idx_target] = src_texture[pSrcTexNum]->Data.at(idx_src);
+			for(size_t idx_target = pOffset, idx_src = 0; idx_target < tex_size; idx_target += pStep, idx_src++) {
+				CAMFImporter_NodeElement_Texture* tex = src_texture[pSrcTexNum];
+				ai_assert(tex);
+				converted_texture.Data[idx_target] = tex->Data.at(idx_src);
+			}
 		}
 	};// auto CopyTextureData = [&](const size_t pOffset, const size_t pStep, const uint8_t pSrcTexNum) -> void
 
@@ -293,19 +304,19 @@ std::string TextureConverted_ID;
 
 void AMFImporter::PostprocessHelper_SplitFacesByTextureID(std::list<SComplexFace>& pInputList, std::list<std::list<SComplexFace> >& pOutputList_Separated)
 {
-auto texmap_is_equal = [](const CAMFImporter_NodeElement_TexMap* pTexMap1, const CAMFImporter_NodeElement_TexMap* pTexMap2) -> bool
-{
-	if((pTexMap1 == nullptr) && (pTexMap2 == nullptr)) return true;
-	if(pTexMap1 == nullptr) return false;
-	if(pTexMap2 == nullptr) return false;
+    auto texmap_is_equal = [](const CAMFImporter_NodeElement_TexMap* pTexMap1, const CAMFImporter_NodeElement_TexMap* pTexMap2) -> bool
+    {
+	    if((pTexMap1 == nullptr) && (pTexMap2 == nullptr)) return true;
+	    if(pTexMap1 == nullptr) return false;
+	    if(pTexMap2 == nullptr) return false;
 
-	if(pTexMap1->TextureID_R != pTexMap2->TextureID_R) return false;
-	if(pTexMap1->TextureID_G != pTexMap2->TextureID_G) return false;
-	if(pTexMap1->TextureID_B != pTexMap2->TextureID_B) return false;
-	if(pTexMap1->TextureID_A != pTexMap2->TextureID_A) return false;
+	    if(pTexMap1->TextureID_R != pTexMap2->TextureID_R) return false;
+	    if(pTexMap1->TextureID_G != pTexMap2->TextureID_G) return false;
+	    if(pTexMap1->TextureID_B != pTexMap2->TextureID_B) return false;
+	    if(pTexMap1->TextureID_A != pTexMap2->TextureID_A) return false;
 
-	return true;
-};
+	    return true;
+    };
 
 	pOutputList_Separated.clear();
 	if(pInputList.size() == 0) return;
@@ -678,7 +689,6 @@ std::list<unsigned int> mesh_idx;
 				tmesh->mNumVertices = static_cast<unsigned int>(vert_arr.size());
 				tmesh->mVertices = new aiVector3D[tmesh->mNumVertices];
 				tmesh->mColors[0] = new aiColor4D[tmesh->mNumVertices];
-				tmesh->mFaces = new aiFace[face_list_cur.size()];
 
 				memcpy(tmesh->mVertices, vert_arr.data(), tmesh->mNumVertices * sizeof(aiVector3D));
 				memcpy(tmesh->mColors[0], col_arr.data(), tmesh->mNumVertices * sizeof(aiColor4D));

+ 8 - 1
code/ASELoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -45,6 +46,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
 
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
+
 // internal headers
 #include "ASELoader.h"
 #include "StringComparison.h"
@@ -54,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/scene.h>
+#include <assimp/importerdesc.h>
 
 #include <memory>
 
@@ -1017,6 +1021,7 @@ void ASEImporter::ConvertMeshes(ASE::Mesh& mesh, std::vector<aiMesh*>& avOutMesh
 
                             // convert bones, if existing
                             if (!mesh.mBones.empty()) {
+                                ai_assert(avOutputBones);
                                 // check whether there is a vertex weight for this vertex index
                                 if (iIndex2 < mesh.mBoneVertices.size())    {
 
@@ -1318,4 +1323,6 @@ bool ASEImporter::GenerateNormals(ASE::Mesh& mesh)  {
     return false;
 }
 
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

+ 7 - 5
code/ASELoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -46,12 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "BaseImporter.h"
 #include <assimp/types.h>
+#include "ASEParser.h"
 
 struct aiNode;
-#include "ASEParser.h"
 
 namespace Assimp {
 
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 // --------------------------------------------------------------------------------
 /** Importer class for the 3DS ASE ASCII format.
@@ -62,9 +64,6 @@ public:
     ASEImporter();
     ~ASEImporter();
 
-
-public:
-
     // -------------------------------------------------------------------
     /** Returns whether the class can handle the format of the given file.
      * See BaseImporter::CanRead() for details.
@@ -200,6 +199,9 @@ protected:
     bool noSkeletonMesh;
 };
 
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
 } // end of namespace Assimp
 
+
 #endif // AI_3DSIMPORTER_H_INC

+ 9 - 6
code/ASEParser.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -45,11 +46,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 
 #ifndef ASSIMP_BUILD_NO_ASE_IMPORTER
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
 
 // internal headers
 #include "TextureTransform.h"
 #include "ASELoader.h"
-#include "MaterialSystem.h"
 #include "fast_atof.h"
 #include <assimp/DefaultLogger.hpp>
 
@@ -1135,7 +1136,7 @@ void Parser::ParseLV3ScaleAnimationBlock(ASE::Animation& anim)
             bool b = false;
 
             // For the moment we're just reading the three floats -
-            // we ignore the dditional information for bezier's and TCBs
+            // we ignore the additional information for bezier's and TCBs
 
             // simple scaling keyframe
             if (TokenMatch(filePtr,"CONTROL_SCALE_SAMPLE" ,20))
@@ -1181,7 +1182,7 @@ void Parser::ParseLV3PosAnimationBlock(ASE::Animation& anim)
             bool b = false;
 
             // For the moment we're just reading the three floats -
-            // we ignore the dditional information for bezier's and TCBs
+            // we ignore the additional information for bezier's and TCBs
 
             // simple scaling keyframe
             if (TokenMatch(filePtr,"CONTROL_POS_SAMPLE" ,18))
@@ -1227,7 +1228,7 @@ void Parser::ParseLV3RotAnimationBlock(ASE::Animation& anim)
             bool b = false;
 
             // For the moment we're just reading the  floats -
-            // we ignore the dditional information for bezier's and TCBs
+            // we ignore the additional information for bezier's and TCBs
 
             // simple scaling keyframe
             if (TokenMatch(filePtr,"CONTROL_ROT_SAMPLE" ,18))
@@ -1858,7 +1859,7 @@ void Parser::ParseLV3MeshCFaceListBlock(unsigned int iNumFaces, ASE::Mesh& mesh)
             ++filePtr;
 
             // Face entry
-            if (TokenMatch(filePtr,"MESH_CFACE" ,11))
+            if (TokenMatch(filePtr,"MESH_CFACE" ,10))
             {
                 unsigned int aiValues[3];
                 unsigned int iIndex = 0;
@@ -2151,4 +2152,6 @@ void Parser::ParseLV4MeshLong(unsigned int& iOut)
     iOut = strtoul10(filePtr,&filePtr);
 }
 
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
 #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

+ 6 - 1
code/ASEParser.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -48,6 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/mesh.h>
 #include <assimp/anim.h>
 
+#ifndef ASSIMP_BUILD_NO_3DS_IMPORTER
+
 // for some helper routines like IsSpace()
 #include "ParsingUtils.h"
 #include "qnan.h"
@@ -661,4 +664,6 @@ public:
 } // Namespace ASE
 } // Namespace ASSIMP
 
+#endif // ASSIMP_BUILD_NO_3DS_IMPORTER
+
 #endif // !! include guard

+ 59 - 5
code/AssbinExporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -138,6 +139,17 @@ inline size_t Write<aiVector3D>(IOStream * stream, const aiVector3D& v)
     return t;
 }
 
+// -----------------------------------------------------------------------------------
+// Serialize a color value
+template <>
+inline size_t Write<aiColor3D>(IOStream * stream, const aiColor3D& v)
+{
+    size_t t = Write<float>(stream,v.r);
+    t += Write<float>(stream,v.g);
+    t += Write<float>(stream,v.b);
+    return t;
+}
+
 // -----------------------------------------------------------------------------------
 // Serialize a color value
 template <>
@@ -159,6 +171,7 @@ inline size_t Write<aiQuaternion>(IOStream * stream, const aiQuaternion& v)
     t += Write<float>(stream,v.x);
     t += Write<float>(stream,v.y);
     t += Write<float>(stream,v.z);
+    ai_assert(t == 16);
     return 16;
 }
 
@@ -324,10 +337,13 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
         {
             AssbinChunkWriter chunk( container, ASSBIN_CHUNK_AINODE );
 
+			unsigned int nb_metadata = (node->mMetaData != NULL ? node->mMetaData->mNumProperties : 0);
+
             Write<aiString>(&chunk,node->mName);
             Write<aiMatrix4x4>(&chunk,node->mTransformation);
             Write<unsigned int>(&chunk,node->mNumChildren);
             Write<unsigned int>(&chunk,node->mNumMeshes);
+			Write<unsigned int>(&chunk,nb_metadata);
 
             for (unsigned int i = 0; i < node->mNumMeshes;++i) {
                 Write<unsigned int>(&chunk,node->mMeshes[i]);
@@ -336,6 +352,44 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
             for (unsigned int i = 0; i < node->mNumChildren;++i) {
                 WriteBinaryNode( &chunk, node->mChildren[i] );
             }
+
+			for (unsigned int i = 0; i < nb_metadata; ++i) {
+				const aiString& key = node->mMetaData->mKeys[i];
+				aiMetadataType type = node->mMetaData->mValues[i].mType;
+				void* value = node->mMetaData->mValues[i].mData;
+
+				Write<aiString>(&chunk, key);
+				Write<uint16_t>(&chunk, type);
+				
+				switch (type) {
+                    case AI_BOOL:
+                        Write<bool>(&chunk, *((bool*) value));
+                        break;
+                    case AI_INT32:
+                        Write<int32_t>(&chunk, *((int32_t*) value));
+                        break;
+                    case AI_UINT64:
+                        Write<uint64_t>(&chunk, *((uint64_t*) value));
+                        break;
+                    case AI_FLOAT:
+                        Write<float>(&chunk, *((float*) value));
+                        break;
+                    case AI_DOUBLE:
+                        Write<double>(&chunk, *((double*) value));
+                        break;
+                    case AI_AISTRING:
+                        Write<aiString>(&chunk, *((aiString*) value));
+                        break;
+                    case AI_AIVECTOR3D:
+                        Write<aiVector3D>(&chunk, *((aiVector3D*) value));
+                        break;
+#ifdef SWIG
+                    case FORCE_32BIT:
+#endif // SWIG
+                    default:
+                        break;
+				}
+			}
         }
 
         // -----------------------------------------------------------------------------------
@@ -597,9 +651,9 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
                 Write<float>(&chunk,l->mAttenuationQuadratic);
             }
 
-            Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorDiffuse);
-            Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorSpecular);
-            Write<aiVector3D>(&chunk,(const aiVector3D&)l->mColorAmbient);
+            Write<aiColor3D>(&chunk,l->mColorDiffuse);
+            Write<aiColor3D>(&chunk,l->mColorSpecular);
+            Write<aiColor3D>(&chunk,l->mColorAmbient);
 
             if (l->mType == aiLightSource_SPOT) {
                 Write<float>(&chunk,l->mAngleInnerCone);
@@ -757,7 +811,7 @@ inline size_t WriteArray(IOStream * stream, const T* in, unsigned int size)
         }
     };
 
-void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+void ExportSceneAssbin(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
 {
     AssbinExport exporter;
     exporter.WriteBinaryDump( pFile, pIOSystem, pScene );

+ 2 - 1
code/AssbinExporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 63 - 9
code/AssbinLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -54,6 +55,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/mesh.h>
 #include <assimp/anim.h>
 #include <assimp/scene.h>
+#include <assimp/importerdesc.h>
 
 #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
 #   include <zlib.h>
@@ -196,9 +198,9 @@ template <typename T> void ReadBounds( IOStream * stream, T* /*p*/, unsigned int
     stream->Seek( sizeof(T) * n, aiOrigin_CUR );
 }
 
-void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
-{
+void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node, aiNode* parent ) {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AINODE);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -208,29 +210,72 @@ void AssbinImporter::ReadBinaryNode( IOStream * stream, aiNode** node )
     (*node)->mTransformation = Read<aiMatrix4x4>(stream);
     (*node)->mNumChildren = Read<unsigned int>(stream);
     (*node)->mNumMeshes = Read<unsigned int>(stream);
+	unsigned int nb_metadata = Read<unsigned int>(stream);
 
-    if ((*node)->mNumMeshes)
-    {
+    if(parent) {
+        (*node)->mParent = parent;
+    }
+
+    if ((*node)->mNumMeshes) {
         (*node)->mMeshes = new unsigned int[(*node)->mNumMeshes];
         for (unsigned int i = 0; i < (*node)->mNumMeshes; ++i) {
             (*node)->mMeshes[i] = Read<unsigned int>(stream);
         }
     }
 
-    if ((*node)->mNumChildren)
-    {
+    if ((*node)->mNumChildren) {
         (*node)->mChildren = new aiNode*[(*node)->mNumChildren];
         for (unsigned int i = 0; i < (*node)->mNumChildren; ++i) {
-            ReadBinaryNode( stream, &(*node)->mChildren[i] );
+            ReadBinaryNode( stream, &(*node)->mChildren[i], *node );
         }
     }
 
+    if ( nb_metadata > 0 ) {
+        (*node)->mMetaData = aiMetadata::Alloc(nb_metadata);
+        for (unsigned int i = 0; i < nb_metadata; ++i) {
+            (*node)->mMetaData->mKeys[i] = Read<aiString>(stream);
+            (*node)->mMetaData->mValues[i].mType = (aiMetadataType) Read<uint16_t>(stream);
+            void* data( nullptr );
+
+            switch ((*node)->mMetaData->mValues[i].mType) {
+                case AI_BOOL:
+                    data = new bool(Read<bool>(stream));
+                    break;
+                case AI_INT32:
+                    data = new int32_t(Read<int32_t>(stream));
+                    break;
+                case AI_UINT64:
+                    data = new uint64_t(Read<uint64_t>(stream));
+                    break;
+                case AI_FLOAT:
+                    data = new float(Read<float>(stream));
+                    break;
+                case AI_DOUBLE:
+                    data = new double(Read<double>(stream));
+                    break;
+                case AI_AISTRING:
+                    data = new aiString(Read<aiString>(stream));
+                    break;
+                case AI_AIVECTOR3D:
+                    data = new aiVector3D(Read<aiVector3D>(stream));
+                    break;
+#ifndef SWIG
+                case FORCE_32BIT:
+#endif // SWIG
+                default:
+                    break;
+            }
+
+			(*node)->mMetaData->mValues[i].mData = data;
+		}
+	}
 }
 
 // -----------------------------------------------------------------------------------
 void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
 {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AIBONE);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -255,6 +300,7 @@ void AssbinImporter::ReadBinaryBone( IOStream * stream, aiBone* b )
 void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
 {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AIMESH);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -380,6 +426,7 @@ void AssbinImporter::ReadBinaryMesh( IOStream * stream, aiMesh* mesh )
 void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialProperty* prop)
 {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIALPROPERTY);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -397,6 +444,7 @@ void AssbinImporter::ReadBinaryMaterialProperty(IOStream * stream, aiMaterialPro
 void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
 {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AIMATERIAL);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -419,6 +467,7 @@ void AssbinImporter::ReadBinaryMaterial(IOStream * stream, aiMaterial* mat)
 void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
 {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AINODEANIM);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -468,6 +517,7 @@ void AssbinImporter::ReadBinaryNodeAnim(IOStream * stream, aiNodeAnim* nd)
 void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
 {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AIANIMATION);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -489,6 +539,7 @@ void AssbinImporter::ReadBinaryAnim( IOStream * stream, aiAnimation* anim )
 void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
 {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AITEXTURE);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -513,6 +564,7 @@ void AssbinImporter::ReadBinaryTexture(IOStream * stream, aiTexture* tex)
 void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
 {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AILIGHT);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -540,6 +592,7 @@ void AssbinImporter::ReadBinaryLight( IOStream * stream, aiLight* l )
 void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
 {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AICAMERA);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -556,6 +609,7 @@ void AssbinImporter::ReadBinaryCamera( IOStream * stream, aiCamera* cam )
 void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
 {
     uint32_t chunkID = Read<uint32_t>(stream);
+    (void)(chunkID);
     ai_assert(chunkID == ASSBIN_CHUNK_AISCENE);
     /*uint32_t size =*/ Read<uint32_t>(stream);
 
@@ -569,7 +623,7 @@ void AssbinImporter::ReadBinaryScene( IOStream * stream, aiScene* scene )
 
     // Read node graph
     scene->mRootNode = new aiNode[1];
-    ReadBinaryNode( stream, &scene->mRootNode );
+    ReadBinaryNode( stream, &scene->mRootNode, (aiNode*)NULL );
 
     // Read all meshes
     if (scene->mNumMeshes)

+ 3 - 4
code/AssbinLoader.h

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -46,7 +47,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define AI_ASSBINIMPORTER_H_INC
 
 #include "BaseImporter.h"
-#include <assimp/types.h>
 
 struct aiMesh;
 struct aiNode;
@@ -71,7 +71,6 @@ class AssbinImporter : public BaseImporter
 private:
   bool shortened;
   bool compressed;
-protected:
 
 public:
   virtual bool CanRead(
@@ -86,7 +85,7 @@ public:
     IOSystem* pIOHandler
     );
   void ReadBinaryScene( IOStream * stream, aiScene* pScene );
-  void ReadBinaryNode( IOStream * stream, aiNode** mRootNode );
+  void ReadBinaryNode( IOStream * stream, aiNode** mRootNode, aiNode* parent );
   void ReadBinaryMesh( IOStream * stream, aiMesh* mesh );
   void ReadBinaryBone( IOStream * stream, aiBone* bone );
   void ReadBinaryMaterial(IOStream * stream, aiMaterial* mat);

+ 14 - 20
code/Assimp.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -65,8 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 // ------------------------------------------------------------------------------------------------
 using namespace Assimp;
 
-namespace Assimp
-{
+namespace Assimp {
     // underlying structure for aiPropertyStore
     typedef BatchLoader::PropertyMap PropertyMap;
 
@@ -109,12 +109,11 @@ static std::mutex gLogStreamMutex;
 
 // ------------------------------------------------------------------------------------------------
 // Custom LogStream implementation for the C-API
-class LogToCallbackRedirector : public LogStream
-{
+class LogToCallbackRedirector : public LogStream {
 public:
     explicit LogToCallbackRedirector(const aiLogStream& s)
-        : stream (s)    {
-            ai_assert(NULL != s.callback);
+    : stream (s)    {
+        ai_assert(NULL != s.callback);
     }
 
     ~LogToCallbackRedirector()  {
@@ -145,8 +144,7 @@ private:
 };
 
 // ------------------------------------------------------------------------------------------------
-void ReportSceneNotFoundError()
-{
+void ReportSceneNotFoundError() {
     DefaultLogger::get()->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");
 
@@ -155,22 +153,18 @@ void ReportSceneNotFoundError()
 
 // ------------------------------------------------------------------------------------------------
 // Reads the given file and returns its content.
-const aiScene* aiImportFile( const char* pFile, unsigned int pFlags)
-{
+const aiScene* aiImportFile( const char* pFile, unsigned int pFlags) {
     return aiImportFileEx(pFile,pFlags,NULL);
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags,  aiFileIO* pFS)
-{
+const aiScene* aiImportFileEx( const char* pFile, unsigned int pFlags,  aiFileIO* pFS) {
     return aiImportFileExWithProperties(pFile, pFlags, pFS, NULL);
 }
 
 // ------------------------------------------------------------------------------------------------
-const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags,
-    aiFileIO* pFS,
-    const aiPropertyStore* props)
-{
+const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFlags, 
+        aiFileIO* pFS, const aiPropertyStore* props) {
     ai_assert(NULL != pFile);
 
     const aiScene* scene = NULL;
@@ -189,7 +183,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
         pimpl->mMatrixProperties = pp->matrices;
     }
     // setup a custom IO system if necessary
-    if (pFS)    {
+    if (pFS) {
         imp->SetIOHandler( new CIOSystemWrapper (pFS) );
     }
 
@@ -200,8 +194,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
     if( scene)  {
         ScenePrivateData* priv = const_cast<ScenePrivateData*>( ScenePriv(scene) );
         priv->mOrigImporter = imp;
-    }
-    else    {
+    } else {
         // if failed, extract error code and destroy the import
         gLastErrorString = imp->GetErrorString();
         delete imp;
@@ -209,6 +202,7 @@ const aiScene* aiImportFileExWithProperties( const char* pFile, unsigned int pFl
 
     // return imported data. If the import failed the pointer is NULL anyways
     ASSIMP_END_EXCEPTION_REGION(const aiScene*);
+    
     return scene;
 }
 

+ 4 - 2
code/AssimpCExport.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -44,8 +45,9 @@ Assimp C export interface. See Exporter.cpp for some notes.
 */
 
 #ifndef ASSIMP_BUILD_NO_EXPORT
+
 #include "CInterfaceIOWrapper.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "ScenePrivate.h"
 #include <assimp/Exporter.hpp>
 

+ 4 - 3
code/AssxmlExporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -41,7 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  ASSXML exporter main code
  */
 #include <stdarg.h>
-#include "./../include/assimp/version.h"
+#include <assimp/version.h>
 #include "ProcessHelper.h"
 #include <assimp/IOStream.hpp>
 #include <assimp/IOSystem.hpp>
@@ -630,7 +631,7 @@ void WriteDump(const aiScene* scene, IOStream* io, bool shortened) {
 
 } // end of namespace AssxmlExport
 
-void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+void ExportSceneAssxml(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
 {
     IOStream * out = pIOSystem->Open( pFile, "wt" );
     if (!out) return;

+ 2 - 1
code/AssxmlExporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 27 - 4
code/B3DImporter.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -56,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/anim.h>
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
-
+#include <assimp/importerdesc.h>
 
 using namespace Assimp;
 using namespace std;
@@ -81,6 +82,20 @@ static const aiImporterDesc desc = {
 
 //#define DEBUG_B3D
 
+template<typename T>
+void DeleteAllBarePointers(std::vector<T>& x)
+{
+    for(auto p : x)
+    {
+        delete p;
+    }
+}
+
+B3DImporter::~B3DImporter()
+{
+    DeleteAllBarePointers(_animations);
+}
+
 // ------------------------------------------------------------------------------------------------
 bool B3DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const{
 
@@ -156,7 +171,8 @@ int B3DImporter::ReadByte(){
 // ------------------------------------------------------------------------------------------------
 int B3DImporter::ReadInt(){
     if( _pos+4<=_buf.size() ){
-        int n=*(int*)&_buf[_pos];
+        int n;
+        memcpy(&n, &_buf[_pos], 4);
         _pos+=4;
         return n;
     }
@@ -167,7 +183,8 @@ int B3DImporter::ReadInt(){
 // ------------------------------------------------------------------------------------------------
 float B3DImporter::ReadFloat(){
     if( _pos+4<=_buf.size() ){
-        float n=*(float*)&_buf[_pos];
+        float n;
+        memcpy(&n, &_buf[_pos], 4);
         _pos+=4;
         return n;
     }
@@ -557,13 +574,19 @@ aiNode *B3DImporter::ReadNODE( aiNode *parent ){
 void B3DImporter::ReadBB3D( aiScene *scene ){
 
     _textures.clear();
+
     _materials.clear();
 
     _vertices.clear();
+
     _meshes.clear();
 
+    DeleteAllBarePointers(_nodes);
     _nodes.clear();
+
     _nodeAnims.clear();
+
+    DeleteAllBarePointers(_animations);
     _animations.clear();
 
     string t=ReadChunk();

+ 4 - 2
code/B3DImporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -48,7 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/material.h>
 #include "BaseImporter.h"
 
-#include <string>
 #include <vector>
 
 struct aiNodeAnim;
@@ -59,6 +59,8 @@ namespace Assimp{
 
 class B3DImporter : public BaseImporter{
 public:
+    B3DImporter() = default;
+    virtual ~B3DImporter();
 
     virtual bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const;
 

+ 3 - 1
code/BVHLoader.cpp

@@ -4,7 +4,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -51,6 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "TinyFormatter.h"
 #include <assimp/IOSystem.hpp>
 #include <assimp/scene.h>
+#include <assimp/importerdesc.h>
 
 using namespace Assimp;
 using namespace Assimp::Formatter;

+ 2 - 1
code/BVHLoader.h

@@ -4,7 +4,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 15 - 48
code/BaseImporter.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -50,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/scene.h>
 #include <assimp/Importer.hpp>
 #include <assimp/postprocess.h>
+#include <assimp/importerdesc.h>
 #include <ios>
 #include <list>
 #include <memory>
@@ -87,12 +89,12 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile,
     FileSystemFilter filter(pFile,pIOHandler);
 
     // create a scene object to hold the data
-    ScopeGuard<aiScene> sc(new aiScene());
+    std::unique_ptr<aiScene> sc(new aiScene());
 
     // dispatch importing
     try
     {
-        InternReadFile( pFile, sc, &filter);
+        InternReadFile( pFile, sc.get(), &filter);
 
     } catch( const std::exception& err )    {
         // extract error description
@@ -102,8 +104,7 @@ aiScene* BaseImporter::ReadFile(const Importer* pImp, const std::string& pFile,
     }
 
     // return what we gathered from the import.
-    sc.dismiss();
-    return sc;
+    return sc.release();
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -301,24 +302,13 @@ void BaseImporter::GetExtensionList(std::set<std::string>& extensions)
     return false;
 }
 
-#include "../contrib/ConvertUTF/ConvertUTF.h"
-
-// ------------------------------------------------------------------------------------------------
-void ReportResult(ConversionResult res)
-{
-    if(res == sourceExhausted) {
-        DefaultLogger::get()->error("Source ends with incomplete character sequence, transformation to UTF-8 fails");
-    }
-    else if(res == sourceIllegal) {
-        DefaultLogger::get()->error("Source contains illegal character sequence, transformation to UTF-8 fails");
-    }
-}
+#include "../contrib/utf8cpp/source/utf8.h"
 
 // ------------------------------------------------------------------------------------------------
 // Convert to UTF8 data
 void BaseImporter::ConvertToUTF8(std::vector<char>& data)
 {
-    ConversionResult result;
+    //ConversionResult result;
     if(data.size() < 8) {
         throw DeadlyImportError("File is too small");
     }
@@ -331,7 +321,8 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
         data.resize(data.size()-3);
         return;
     }
-
+    
+    
     // UTF 32 BE with BOM
     if(*((uint32_t*)&data.front()) == 0xFFFE0000) {
 
@@ -345,21 +336,10 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
     if(*((uint32_t*)&data.front()) == 0x0000FFFE) {
         DefaultLogger::get()->debug("Found UTF-32 BOM ...");
 
-        const uint32_t* sstart = (uint32_t*)&data.front()+1, *send = (uint32_t*)&data.back()+1;
-        char* dstart,*dend;
         std::vector<char> output;
-        do {
-            output.resize(output.size()?output.size()*3/2:data.size()/2);
-            dstart = &output.front(),dend = &output.back()+1;
-
-            result = ConvertUTF32toUTF8((const UTF32**)&sstart,(const UTF32*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion);
-        } while(result == targetExhausted);
-
-        ReportResult(result);
-
-        // copy to output buffer.
-        const size_t outlen = (size_t)(dstart-&output.front());
-        data.assign(output.begin(),output.begin()+outlen);
+        int *ptr = (int*)&data[ 0 ];
+        int *end = ptr + ( data.size() / sizeof(int) ) +1;
+        utf8::utf32to8( ptr, end, back_inserter(output));
         return;
     }
 
@@ -376,21 +356,8 @@ void BaseImporter::ConvertToUTF8(std::vector<char>& data)
     if(*((uint16_t*)&data.front()) == 0xFEFF) {
         DefaultLogger::get()->debug("Found UTF-16 BOM ...");
 
-        const uint16_t* sstart = (uint16_t*)&data.front()+1, *send = (uint16_t*)(&data.back()+1);
-        char* dstart,*dend;
-        std::vector<char> output;
-        do {
-            output.resize(output.size()?output.size()*3/2:data.size()*3/4);
-            dstart = &output.front(),dend = &output.back()+1;
-
-            result = ConvertUTF16toUTF8((const UTF16**)&sstart,(const UTF16*)send,(UTF8**)&dstart,(UTF8*)dend,lenientConversion);
-        } while(result == targetExhausted);
-
-        ReportResult(result);
-
-        // copy to output buffer.
-        const size_t outlen = (size_t)(dstart-&output.front());
-        data.assign(output.begin(),output.begin()+outlen);
+        std::vector<unsigned char> output;
+        utf8::utf16to8(data.begin(), data.end(), back_inserter(output));
         return;
     }
 }

+ 4 - 44
code/BaseImporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -44,14 +45,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include "Exceptional.h"
 
-#include <string>
-#include <map>
 #include <vector>
 #include <set>
 #include <assimp/types.h>
 #include <assimp/ProgressHandler.hpp>
 
 struct aiScene;
+struct aiImporterDesc;
 
 namespace Assimp    {
 
@@ -61,47 +61,10 @@ class BaseProcess;
 class SharedPostProcessInfo;
 class IOStream;
 
-
 // utility to do char4 to uint32 in a portable manner
 #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
     (string[1] << 16) + (string[2] << 8) + string[3]))
 
-// ---------------------------------------------------------------------------
-template <typename T>
-struct ScopeGuard
-{
-    explicit ScopeGuard(T* obj) : obj(obj), mdismiss() {}
-    ~ScopeGuard () throw() {
-        if (!mdismiss) {
-            delete obj;
-        }
-        obj = NULL;
-    }
-
-    T* dismiss() {
-        mdismiss=true;
-        return obj;
-    }
-
-    operator T*() {
-        return obj;
-    }
-
-    T* operator -> () {
-        return obj;
-    }
-
-private:
-    // no copying allowed.
-    ScopeGuard();
-    ScopeGuard( const ScopeGuard & );
-    ScopeGuard &operator = ( const ScopeGuard & );
-
-    T* obj;
-    bool mdismiss;
-};
-
-
 
 // ---------------------------------------------------------------------------
 /** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface
@@ -194,14 +157,11 @@ public:
         const Importer* pImp
         );
 
-
     // -------------------------------------------------------------------
     /** Called by #Importer::GetImporterInfo to get a description of
      *  some loader features. Importers must provide this information. */
     virtual const aiImporterDesc* GetInfo() const = 0;
 
-
-
     // -------------------------------------------------------------------
     /** Called by #Importer::GetExtensionList for each loaded importer.
      *  Take the extension list contained in the structure returned by
@@ -317,7 +277,7 @@ public: // static utilities
      *  @param Size of one token, in bytes. Maximally 16 bytes.
      *  @return true if one of the given tokens was found
      *
-     *  @note For convinence, the check is also performed for the
+     *  @note For convenience, the check is also performed for the
      *  byte-swapped variant of all tokens (big endian). Only for
      *  tokens of size 2,4.
      */

+ 2 - 1
code/BaseProcess.cpp

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

+ 2 - 3
code/BaseProcess.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,8 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_BASEPROCESS_H
 
 #include <map>
-
-#include <assimp/types.h>
 #include "GenericProperty.h"
 
 struct aiScene;

+ 4 - 3
code/Bitmap.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -101,7 +102,7 @@ namespace Assimp {
         offset += Copy(&data[offset], header.size);
         offset += Copy(&data[offset], header.reserved1);
         offset += Copy(&data[offset], header.reserved2);
-        offset += Copy(&data[offset], header.offset);
+                  Copy(&data[offset], header.offset);
 
         file->Write(data, Header::header_size, 1);
     }
@@ -121,7 +122,7 @@ namespace Assimp {
         offset += Copy(&data[offset], dib.x_resolution);
         offset += Copy(&data[offset], dib.y_resolution);
         offset += Copy(&data[offset], dib.nb_colors);
-        offset += Copy(&data[offset], dib.nb_important_colors);
+                  Copy(&data[offset], dib.nb_important_colors);
 
         file->Write(data, DIB::dib_size, 1);
     }

+ 61 - 82
code/Bitmap.h

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -50,93 +51,71 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <stdint.h>
 #include <cstddef>
+
 struct aiTexture;
 
 namespace Assimp {
 
 class IOStream;
-class Bitmap {
-
-    protected:
-
-        struct Header {
-
-            uint16_t type;
-
-            uint32_t size;
-
-            uint16_t reserved1;
-
-            uint16_t reserved2;
-
-            uint32_t offset;
-
-            // We define the struct size because sizeof(Header) might return a wrong result because of structure padding.
-            // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
-            static const std::size_t header_size =
-                sizeof(uint16_t) + // type
-                sizeof(uint32_t) + // size
-                sizeof(uint16_t) + // reserved1
-                sizeof(uint16_t) + // reserved2
-                sizeof(uint32_t);  // offset
-
-        };
-
-        struct DIB {
-
-            uint32_t size;
-
-            int32_t width;
-
-            int32_t height;
-
-            uint16_t planes;
-
-            uint16_t bits_per_pixel;
-
-            uint32_t compression;
-
-            uint32_t image_size;
-
-            int32_t x_resolution;
-
-            int32_t y_resolution;
-
-            uint32_t nb_colors;
-
-            uint32_t nb_important_colors;
-
-            // We define the struct size because sizeof(DIB) might return a wrong result because of structure padding.
-            // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
-            static const std::size_t dib_size =
-                sizeof(uint32_t) + // size
-                sizeof(int32_t) +  // width
-                sizeof(int32_t) +  // height
-                sizeof(uint16_t) + // planes
-                sizeof(uint16_t) + // bits_per_pixel
-                sizeof(uint32_t) + // compression
-                sizeof(uint32_t) + // image_size
-                sizeof(int32_t) +  // x_resolution
-                sizeof(int32_t) +  // y_resolution
-                sizeof(uint32_t) + // nb_colors
-                sizeof(uint32_t);  // nb_important_colors
-
-        };
-
-        static const std::size_t mBytesPerPixel = 4;
-
-    public:
-
-        static void Save(aiTexture* texture, IOStream* file);
-
-    protected:
-
-        static void WriteHeader(Header& header, IOStream* file);
-
-        static void WriteDIB(DIB& dib, IOStream* file);
-
-        static void WriteData(aiTexture* texture, IOStream* file);
 
+class Bitmap {
+protected:
+
+    struct Header {
+        uint16_t type;
+        uint32_t size;
+        uint16_t reserved1;
+        uint16_t reserved2;
+        uint32_t offset;
+
+        // We define the struct size because sizeof(Header) might return a wrong result because of structure padding.
+        // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
+        static const std::size_t header_size =
+            sizeof(uint16_t) + // type
+            sizeof(uint32_t) + // size
+            sizeof(uint16_t) + // reserved1
+            sizeof(uint16_t) + // reserved2
+            sizeof(uint32_t);  // offset
+    };
+
+    struct DIB {
+        uint32_t size;
+        int32_t width;
+        int32_t height;
+        uint16_t planes;
+        uint16_t bits_per_pixel;
+        uint32_t compression;
+        uint32_t image_size;
+        int32_t x_resolution;
+        int32_t y_resolution;
+        uint32_t nb_colors;
+        uint32_t nb_important_colors;
+
+        // We define the struct size because sizeof(DIB) might return a wrong result because of structure padding.
+        // Moreover, we must use this ugly and error prone syntax because Visual Studio neither support constexpr or sizeof(name_of_field).
+        static const std::size_t dib_size =
+            sizeof(uint32_t) + // size
+            sizeof(int32_t) +  // width
+            sizeof(int32_t) +  // height
+            sizeof(uint16_t) + // planes
+            sizeof(uint16_t) + // bits_per_pixel
+            sizeof(uint32_t) + // compression
+            sizeof(uint32_t) + // image_size
+            sizeof(int32_t) +  // x_resolution
+            sizeof(int32_t) +  // y_resolution
+            sizeof(uint32_t) + // nb_colors
+            sizeof(uint32_t);  // nb_important_colors
+    };
+
+    static const std::size_t mBytesPerPixel = 4;
+
+public:
+    static void Save(aiTexture* texture, IOStream* file);
+
+protected:
+    static void WriteHeader(Header& header, IOStream* file);
+    static void WriteDIB(DIB& dib, IOStream* file);
+    static void WriteData(aiTexture* texture, IOStream* file);
 };
 
 }

+ 5 - 1
code/BlenderBMesh.cpp

@@ -52,7 +52,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 namespace Assimp
 {
-    template< > const std::string LogFunctions< BlenderBMeshConverter >::log_prefix = "BLEND_BMESH: ";
+    template< > const char* LogFunctions< BlenderBMeshConverter >::Prefix()
+    {
+        static auto prefix = "BLEND_BMESH: ";
+        return prefix;
+    }
 }
 
 using namespace Assimp;

+ 3 - 1
code/BlenderDNA.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -48,6 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BlenderDNA.h"
 #include "StreamReader.h"
 #include "fast_atof.h"
+#include "TinyFormatter.h"
 
 using namespace Assimp;
 using namespace Assimp::Blender;

+ 10 - 7
code/BlenderDNA.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -46,12 +47,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_BLEND_DNA_H
 
 #include "BaseImporter.h"
-#include "TinyFormatter.h"
 #include "StreamReader.h"
 #include <assimp/DefaultLogger.hpp>
 #include <stdint.h>
 #include <memory>
-
+#include <map>
 
 // enable verbose log output. really verbose, so be careful.
 #ifdef ASSIMP_BUILD_DEBUG
@@ -92,6 +92,12 @@ struct Error : DeadlyImportError {
  *  descendents. It serves as base class for all data structure fields. */
 // -------------------------------------------------------------------------------
 struct ElemBase {
+    ElemBase()
+    : dna_type(nullptr)
+    {
+        // empty
+    }
+
     virtual ~ElemBase() {
         // empty
     }
@@ -253,10 +259,7 @@ public:
      *  a compiler complain is the result.
      *  @param dest Destination value to be written
      *  @param db File database, including input stream. */
-    template <typename T> inline void Convert (T& dest,
-        const FileDatabase& db) const;
-
-
+    template <typename T> void Convert (T& dest, const FileDatabase& db) const;
 
     // --------------------------------------------------------
     // generic converter

+ 9 - 4
code/BlenderDNA.inl

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -46,9 +47,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #define INCLUDED_AI_BLEND_DNA_INL
 
 #include <memory>
+#include "TinyFormatter.h"
 
 namespace Assimp {
-    namespace Blender {
+namespace Blender {
 
 //--------------------------------------------------------------------------------
 const Field& Structure :: operator [] (const std::string& ss) const
@@ -583,11 +585,14 @@ template <> inline void Structure :: Convert<int>    (int& dest,const FileDataba
 }
 
 // ------------------------------------------------------------------------------------------------
-template <> inline void Structure :: Convert<short>  (short& dest,const FileDatabase& db) const
+template<> inline void Structure :: Convert<short>  (short& dest,const FileDatabase& db) const
 {
     // automatic rescaling from short to float and vice versa (seems to be used by normals)
     if (name == "float") {
-        dest = static_cast<short>(db.reader->GetF4() * 32767.f);
+        float f = db.reader->GetF4();
+        if ( f > 1.0f )
+            f = 1.0f;
+        dest = static_cast<short>( f * 32767.f);
         //db.reader->IncPtr(-4);
         return;
     }

+ 4 - 4
code/BlenderIntermediate.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -48,9 +49,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BlenderLoader.h"
 #include "BlenderDNA.h"
 #include "BlenderScene.h"
-#include "BlenderSceneGen.h"
 #include <deque>
-#include "./../include/assimp/material.h"
+#include <assimp/material.h>
 
 struct aiTexture;
 
@@ -110,7 +110,7 @@ namespace Blender {
         void operator= (const TempArray&)  {
         }
 
-        TempArray(const TempArray& arr) {
+        TempArray(const TempArray& /*arr*/) {
         }
 
     private:

+ 24 - 16
code/BlenderLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -54,12 +55,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BlenderBMesh.h"
 #include "StringUtils.h"
 #include <assimp/scene.h>
-#include "StringComparison.h"
+#include <assimp/importerdesc.h>
 
+#include "StringComparison.h"
 #include "StreamReader.h"
 #include "MemoryIOWrapper.h"
+
 #include <cctype>
-#include <cstdint>
 
 
 // zlib is needed for compressed blend files
@@ -72,7 +74,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endif
 
 namespace Assimp {
-    template<> const std::string LogFunctions<BlenderImporter>::log_prefix = "BLEND: ";
+    template<> const char* LogFunctions<BlenderImporter>::Prefix()
+    {
+        static auto prefix = "BLEND: ";
+        return prefix;
+    }
 }
 
 using namespace Assimp;
@@ -96,8 +102,9 @@ static const aiImporterDesc blenderDesc = {
 // ------------------------------------------------------------------------------------------------
 // Constructor to be privately used by Importer
 BlenderImporter::BlenderImporter()
-: modifier_cache(new BlenderModifierShowcase())
-{}
+: modifier_cache(new BlenderModifierShowcase()) {
+    // empty
+}
 
 // ------------------------------------------------------------------------------------------------
 // Destructor, private as well
@@ -107,6 +114,7 @@ BlenderImporter::~BlenderImporter()
 }
 
 static const char* Tokens[] = { "BLENDER" };
+static const char* TokensForSearch[] = { "blender" };
 
 // ------------------------------------------------------------------------------------------------
 // Returns whether the class can handle the format of the given file.
@@ -119,7 +127,7 @@ bool BlenderImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, b
 
     else if ((!extension.length() || checkSig) && pIOHandler)   {
         // note: this won't catch compressed files
-        return SearchFileHeaderForToken(pIOHandler,pFile, Tokens,1);
+        return SearchFileHeaderForToken(pIOHandler,pFile, TokensForSearch,1);
     }
     return false;
 }
@@ -145,8 +153,7 @@ void BlenderImporter::SetupProperties(const Importer* /*pImp*/)
     // nothing to be done for the moment
 }
 
-struct free_it
-{
+struct free_it {
     free_it(void* free) : free(free) {}
     ~free_it() {
         ::free(this->free);
@@ -165,6 +172,7 @@ void BlenderImporter::InternReadFile( const std::string& pFile,
     free_it free_it_really(dest);
 #endif
 
+
     FileDatabase file;
     std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile,"rb"));
     if (!stream) {
@@ -1140,7 +1148,7 @@ void BlenderImporter::ConvertMesh(const Scene& /*in*/, const Object* /*obj*/, co
 // ------------------------------------------------------------------------------------------------
 aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj, const Camera* cam, ConversionData& /*conv_data*/)
 {
-    ScopeGuard<aiCamera> out(new aiCamera());
+    std::unique_ptr<aiCamera> out(new aiCamera());
     out->mName = obj->id.name+2;
     out->mPosition = aiVector3D(0.f, 0.f, 0.f);
     out->mUp = aiVector3D(0.f, 1.f, 0.f);
@@ -1151,13 +1159,13 @@ aiCamera* BlenderImporter::ConvertCamera(const Scene& /*in*/, const Object* obj,
     out->mClipPlaneNear = cam->clipsta;
     out->mClipPlaneFar = cam->clipend;
 
-    return out.dismiss();
+    return out.release();
 }
 
 // ------------------------------------------------------------------------------------------------
 aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, const Lamp* lamp, ConversionData& /*conv_data*/)
 {
-    ScopeGuard<aiLight> out(new aiLight());
+    std::unique_ptr<aiLight> out(new aiLight());
     out->mName = obj->id.name+2;
 
     switch (lamp->type)
@@ -1195,7 +1203,7 @@ aiLight* BlenderImporter::ConvertLight(const Scene& /*in*/, const Object* obj, c
     out->mColorAmbient = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
     out->mColorSpecular = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
     out->mColorDiffuse = aiColor3D(lamp->r, lamp->g, lamp->b) * lamp->energy;
-    return out.dismiss();
+    return out.release();
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -1213,7 +1221,7 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
         ++it;
     }
 
-    ScopeGuard<aiNode> node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB'
+    std::unique_ptr<aiNode> node(new aiNode(obj->id.name+2)); // skip over the name prefix 'OB'
     if (obj->data) {
         switch (obj->type)
         {
@@ -1297,14 +1305,14 @@ aiNode* BlenderImporter::ConvertNode(const Scene& in, const Object* obj, Convers
         aiNode** nd = node->mChildren = new aiNode*[node->mNumChildren]();
         for (const Object* nobj :children) {
             *nd = ConvertNode(in,nobj,conv_data,node->mTransformation * parentTransform);
-            (*nd++)->mParent = node;
+            (*nd++)->mParent = node.get();
         }
     }
 
     // apply modifiers
     modifier_cache->ApplyModifiers(*node,conv_data,in,*obj);
 
-    return node.dismiss();
+    return node.release();
 }
 
 #endif // ASSIMP_BUILD_NO_BLEND_IMPORTER

+ 2 - 1
code/BlenderLoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 8 - 5
code/BlenderModifier.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -42,10 +43,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of some blender modifiers (i.e subdivision, mirror).
  */
 
-
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
+
 #include "BlenderModifier.h"
-#include "SceneCombiner.h"
+#include <assimp/SceneCombiner.h>
 #include "Subdivision.h"
 #include <assimp/scene.h>
 #include <memory>
@@ -265,7 +266,7 @@ void  BlenderModifier_Mirror :: DoIt(aiNode& out, ConversionData& conv_data,  co
 
     std::copy(out.mMeshes,out.mMeshes+out.mNumMeshes,nind);
     std::transform(out.mMeshes,out.mMeshes+out.mNumMeshes,nind+out.mNumMeshes,
-        std::bind1st(std::plus< unsigned int >(),out.mNumMeshes));
+        [&out](unsigned int n) { return out.mNumMeshes + n; });
 
     delete[] out.mMeshes;
     out.mMeshes = nind;
@@ -309,7 +310,9 @@ void  BlenderModifier_Subdivision :: DoIt(aiNode& out, ConversionData& conv_data
 
     std::unique_ptr<Subdivider> subd(Subdivider::Create(algo));
     ai_assert(subd);
-
+    if ( conv_data.meshes->empty() ) {
+        return;
+    }
     aiMesh** const meshes = &conv_data.meshes[conv_data.meshes->size() - out.mNumMeshes];
     std::unique_ptr<aiMesh*[]> tempmeshes(new aiMesh*[out.mNumMeshes]());
 

+ 2 - 1
code/BlenderModifier.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 33 - 14
code/BlenderScene.cpp

@@ -44,9 +44,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #ifndef ASSIMP_BUILD_NO_BLEND_IMPORTER
 
-#include "BlenderDNA.h"
 #include "BlenderScene.h"
 #include "BlenderSceneGen.h"
+#include "BlenderDNA.h"
 
 using namespace Assimp;
 using namespace Assimp::Blender;
@@ -59,7 +59,9 @@ template <> void Structure :: Convert<Object> (
 {
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
+    int temp = 0;
+    ReadField<ErrorPolicy_Fail>(temp,"type",db);
+    dest.type = static_cast<Assimp::Blender::Object::Type>(temp);
     ReadFieldArray2<ErrorPolicy_Warn>(dest.obmat,"obmat",db);
     ReadFieldArray2<ErrorPolicy_Warn>(dest.parentinv,"parentinv",db);
     ReadFieldArray<ErrorPolicy_Warn>(dest.parsubstr,"parsubstr",db);
@@ -100,14 +102,21 @@ template <> void Structure :: Convert<MTex> (
     ) const
 {
 
-    ReadField<ErrorPolicy_Igno>((short&)dest.mapto,"mapto",db);
-    ReadField<ErrorPolicy_Igno>((int&)dest.blendtype,"blendtype",db);
+    int temp_short = 0;
+    ReadField<ErrorPolicy_Igno>(temp_short,"mapto",db);
+    dest.mapto = static_cast<Assimp::Blender::MTex::MapType>(temp_short);
+    int temp = 0;
+    ReadField<ErrorPolicy_Igno>(temp,"blendtype",db);
+    dest.blendtype = static_cast<Assimp::Blender::MTex::BlendType>(temp);
     ReadFieldPtr<ErrorPolicy_Igno>(dest.object,"*object",db);
     ReadFieldPtr<ErrorPolicy_Igno>(dest.tex,"*tex",db);
     ReadFieldArray<ErrorPolicy_Igno>(dest.uvname,"uvname",db);
-    ReadField<ErrorPolicy_Igno>((int&)dest.projx,"projx",db);
-    ReadField<ErrorPolicy_Igno>((int&)dest.projy,"projy",db);
-    ReadField<ErrorPolicy_Igno>((int&)dest.projz,"projz",db);
+    ReadField<ErrorPolicy_Igno>(temp,"projx",db);
+    dest.projx = static_cast<Assimp::Blender::MTex::Projection>(temp);
+    ReadField<ErrorPolicy_Igno>(temp,"projy",db);
+    dest.projy = static_cast<Assimp::Blender::MTex::Projection>(temp);
+    ReadField<ErrorPolicy_Igno>(temp,"projz",db);
+    dest.projx = static_cast<Assimp::Blender::MTex::Projection>(temp);
     ReadField<ErrorPolicy_Igno>(dest.mapping,"mapping",db);
     ReadFieldArray<ErrorPolicy_Igno>(dest.ofs,"ofs",db);
     ReadFieldArray<ErrorPolicy_Igno>(dest.size,"size",db);
@@ -190,7 +199,9 @@ template <> void Structure :: Convert<Lamp> (
 {
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
+    int temp = 0;
+    ReadField<ErrorPolicy_Fail>(temp,"type",db);
+    dest.type = static_cast<Assimp::Blender::Lamp::Type>(temp);
     ReadField<ErrorPolicy_Igno>(dest.flags,"flags",db);
     ReadField<ErrorPolicy_Igno>(dest.colormodel,"colormodel",db);
     ReadField<ErrorPolicy_Igno>(dest.totex,"totex",db);
@@ -204,7 +215,8 @@ template <> void Structure :: Convert<Lamp> (
     ReadField<ErrorPolicy_Igno>(dest.spotblend,"spotblend",db);
     ReadField<ErrorPolicy_Igno>(dest.att1,"att1",db);
     ReadField<ErrorPolicy_Igno>(dest.att2,"att2",db);
-    ReadField<ErrorPolicy_Igno>((int&)dest.falloff_type,"falloff_type",db);
+    ReadField<ErrorPolicy_Igno>(temp,"falloff_type",db);
+    dest.falloff_type = static_cast<Assimp::Blender::Lamp::FalloffType>(temp);
     ReadField<ErrorPolicy_Igno>(dest.sun_brightness,"sun_brightness",db);
     ReadField<ErrorPolicy_Igno>(dest.area_size,"area_size",db);
     ReadField<ErrorPolicy_Igno>(dest.area_sizey,"area_sizey",db);
@@ -522,7 +534,7 @@ template <> void Structure :: Convert<MVert> (
     ReadFieldArray<ErrorPolicy_Fail>(dest.co,"co",db);
     ReadFieldArray<ErrorPolicy_Fail>(dest.no,"no",db);
     ReadField<ErrorPolicy_Igno>(dest.flag,"flag",db);
-    ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
+    //ReadField<ErrorPolicy_Warn>(dest.mat_nr,"mat_nr",db);
     ReadField<ErrorPolicy_Igno>(dest.bweight,"bweight",db);
 
     db.reader->IncPtr(size);
@@ -693,8 +705,12 @@ template <> void Structure :: Convert<Tex> (
     const FileDatabase& db
     ) const
 {
-    ReadField<ErrorPolicy_Igno>((short&)dest.imaflag,"imaflag",db);
-    ReadField<ErrorPolicy_Fail>((int&)dest.type,"type",db);
+    short temp_short = 0;
+    ReadField<ErrorPolicy_Igno>(temp_short,"imaflag",db);
+    dest.imaflag = static_cast<Assimp::Blender::Tex::ImageFlags>(temp_short);
+    int temp = 0;
+    ReadField<ErrorPolicy_Fail>(temp,"type",db);
+    dest.type = static_cast<Assimp::Blender::Tex::Type>(temp);
     ReadFieldPtr<ErrorPolicy_Warn>(dest.ima,"*ima",db);
 
     db.reader->IncPtr(size);
@@ -708,8 +724,11 @@ template <> void Structure :: Convert<Camera> (
 {
 
     ReadField<ErrorPolicy_Fail>(dest.id,"id",db);
-    ReadField<ErrorPolicy_Warn>((int&)dest.type,"type",db);
-    ReadField<ErrorPolicy_Warn>((int&)dest.flag,"flag",db);
+    int temp = 0;
+    ReadField<ErrorPolicy_Warn>(temp,"type",db);
+    dest.type = static_cast<Assimp::Blender::Camera::Type>(temp);
+    ReadField<ErrorPolicy_Warn>(temp,"flag",db);
+    dest.flag = static_cast<Assimp::Blender::Camera::Type>(temp);
     ReadField<ErrorPolicy_Warn>(dest.lens,"lens",db);
     ReadField<ErrorPolicy_Warn>(dest.sensor_x,"sensor_x",db);
     ReadField<ErrorPolicy_Igno>(dest.clipsta,"clipsta",db);

+ 57 - 4
code/BlenderScene.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -224,6 +225,14 @@ struct TFace : ElemBase {
 
 // -------------------------------------------------------------------------------
 struct MTFace : ElemBase {
+	MTFace()
+	: flag(0)
+	, mode(0)
+	, tile(0)
+	, unwrap(0)
+	{
+	}
+
     float uv[4][2] FAIL;
     char flag;
     short mode;
@@ -616,6 +625,17 @@ struct Object : ElemBase  {
     std::shared_ptr<ElemBase> data FAIL;
 
     ListBase modifiers;
+
+    Object()
+    : ElemBase()
+    , type( Type_EMPTY )
+    , parent( nullptr )
+    , track()
+    , proxy()
+    , proxy_from()
+    , data() {
+        // empty
+    }
 };
 
 
@@ -624,6 +644,15 @@ struct Base : ElemBase {
     Base* prev WARN;
     std::shared_ptr<Base> next WARN;
     std::shared_ptr<Object> object WARN;
+
+    Base() 
+    : ElemBase()
+    , prev( nullptr )
+    , next()
+    , object() {
+        // empty
+        // empty
+    }
 };
 
 // -------------------------------------------------------------------------------
@@ -635,8 +664,15 @@ struct Scene : ElemBase {
     std::shared_ptr<Base> basact WARN;
 
     ListBase base;
-};
 
+    Scene()
+    : ElemBase()
+    , camera()
+    , world()
+    , basact() {
+        // empty
+    }
+};
 
 // -------------------------------------------------------------------------------
 struct Image : ElemBase {
@@ -664,6 +700,11 @@ struct Image : ElemBase {
     short animspeed;
 
     short gen_x, gen_y, gen_type;
+    
+    Image()
+    : ElemBase() {
+        // empty
+    }
 };
 
 // -------------------------------------------------------------------------------
@@ -751,6 +792,14 @@ struct Tex : ElemBase {
     //VoxelData *vd;
 
     //char use_nodes;
+
+    Tex()
+    : ElemBase()
+    , imaflag( ImageFlags_INTERPOL )
+    , type( Type_CLOUDS )
+    , ima() {
+        // empty
+    }
 };
 
 // -------------------------------------------------------------------------------
@@ -839,9 +888,13 @@ struct MTex : ElemBase {
     //float lifefac, sizefac, ivelfac, pvelfac;
     //float shadowfac;
     //float zenupfac, zendownfac, blendfac;
-};
-
 
+    MTex()
+    : ElemBase() {
+        // empty
     }
+};
+
+}
 }
 #endif

+ 12 - 3
code/BlenderTessellator.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -58,7 +59,11 @@ static const unsigned int BLEND_TESS_MAGIC = 0x83ed9ac3;
 
 namspace Assimp
 {
-    template< > const std::string LogFunctions< BlenderTessellatorGL >::log_prefix = "BLEND_TESS_GL: ";
+    template< > const char* LogFunctions< BlenderTessellatorGL >::Prefix()
+    {
+        static auto prefix = "BLEND_TESS_GL: ";
+        return prefix;
+    }
 }
 
 using namespace Assimp;
@@ -251,7 +256,11 @@ void BlenderTessellatorGL::TessellateError( GLenum errorCode, void* )
 
 namespace Assimp
 {
-    template< > const std::string LogFunctions< BlenderTessellatorP2T >::log_prefix = "BLEND_TESS_P2T: ";
+    template< > const char* LogFunctions< BlenderTessellatorP2T >::Prefix()
+    {
+        static auto prefix = "BLEND_TESS_P2T: ";
+        return prefix;
+    }
 }
 
 using namespace Assimp;

+ 2 - 1
code/BlenderTessellator.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 6 - 5
code/BlobIOSystem.h

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -45,10 +46,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_BLOBIOSYSTEM_H_INCLUDED
 #define AI_BLOBIOSYSTEM_H_INCLUDED
 
-#include "./../include/assimp/IOStream.hpp"
-#include "./../include/assimp/cexport.h"
-#include "./../include/assimp/IOSystem.hpp"
-#include "./../include/assimp/DefaultLogger.hpp"
+#include <assimp/IOStream.hpp>
+#include <assimp/cexport.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/DefaultLogger.hpp>
 #include <stdint.h>
 #include <set>
 #include <vector>

+ 2 - 1
code/ByteSwapper.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 6 - 6
code/C4DImporter.cpp

@@ -185,11 +185,11 @@ void C4DImporter::InternReadFile( const std::string& pFile,
         if(mesh->mMaterialIndex >= mat_count) {
             ++mat_count;
 
-            ScopeGuard<aiMaterial> def_material(new aiMaterial());
+            std::unique_ptr<aiMaterial> def_material(new aiMaterial());
             const aiString name(AI_DEFAULT_MATERIAL_NAME);
             def_material->AddProperty(&name, AI_MATKEY_NAME);
 
-            materials.push_back(def_material.dismiss());
+            materials.push_back(def_material.release());
             break;
         }
     }
@@ -393,7 +393,7 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent)
 // ------------------------------------------------------------------------------------------------
 aiMesh* C4DImporter::ReadMesh(BaseObject* object)
 {
-    assert(object != NULL && object->GetType() == Opolygon);
+    ai_assert(object != NULL && object->GetType() == Opolygon);
 
     // based on Melange sample code
     PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
@@ -412,7 +412,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
     const CPolygon* polys = polyObject->GetPolygonR();
     ai_assert(polys != NULL);
 
-    ScopeGuard<aiMesh> mesh(new aiMesh());
+    std::unique_ptr<aiMesh> mesh(new aiMesh());
     mesh->mNumFaces = static_cast<unsigned int>(polyCount);
     aiFace* face = mesh->mFaces = new aiFace[mesh->mNumFaces]();
 
@@ -616,7 +616,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object)
     }
 
     mesh->mMaterialIndex = ResolveMaterial(polyObject);
-    return mesh.dismiss();
+    return mesh.release();
 }
 
 
@@ -635,7 +635,7 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj)
     TextureTag& ttag = dynamic_cast<TextureTag&>(*tag);
 
     BaseMaterial* const mat = ttag.GetMaterial();
-    assert(mat != NULL);
+    ai_assert(mat != NULL);
 
     const MaterialMap::const_iterator it = material_mapping.find(mat);
     if(it == material_mapping.end()) {

+ 1 - 1
code/C4DImporter.h

@@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include "BaseImporter.h"
 #include "LogAux.h"
 
-#include <set>
+#include <map>
 struct aiNode;
 struct aiMesh;
 struct aiMaterial;

+ 2 - 1
code/CInterfaceIOWrapper.cpp

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

+ 2 - 1
code/CInterfaceIOWrapper.h

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

+ 102 - 36
code/CMakeLists.txt

@@ -1,7 +1,8 @@
 # Open Asset Import Library (assimp)
 # ----------------------------------------------------------------------
 #
-# Copyright (c) 2006-2016, assimp team
+# Copyright (c) 2006-2017, assimp team
+
 # All rights reserved.
 #
 # Redistribution and use of this software in source and binary forms,
@@ -58,8 +59,9 @@ SET( PUBLIC_HEADERS
   ${HEADER_PATH}/camera.h
   ${HEADER_PATH}/color4.h
   ${HEADER_PATH}/color4.inl
-  ${HEADER_PATH}/config.h
+  ${CMAKE_CURRENT_BINARY_DIR}/../include/assimp/config.h
   ${HEADER_PATH}/defs.h
+  ${HEADER_PATH}/Defines.h
   ${HEADER_PATH}/cfileio.h
   ${HEADER_PATH}/light.h
   ${HEADER_PATH}/material.h
@@ -93,6 +95,9 @@ SET( PUBLIC_HEADERS
   ${HEADER_PATH}/NullLogger.hpp
   ${HEADER_PATH}/cexport.h
   ${HEADER_PATH}/Exporter.hpp
+  ${HEADER_PATH}/DefaultIOStream.h
+  ${HEADER_PATH}/DefaultIOSystem.h
+  ${HEADER_PATH}/SceneCombiner.h
 )
 
 SET( Core_SRCS
@@ -125,9 +130,7 @@ SET( Common_SRCS
   ByteSwapper.h
   DefaultProgressHandler.h
   DefaultIOStream.cpp
-  DefaultIOStream.h
   DefaultIOSystem.cpp
-  DefaultIOSystem.h
   CInterfaceIOWrapper.cpp
   CInterfaceIOWrapper.h
   Hash.h
@@ -147,13 +150,14 @@ SET( Common_SRCS
   SpatialSort.cpp
   SpatialSort.h
   SceneCombiner.cpp
-  SceneCombiner.h
   ScenePreprocessor.cpp
   ScenePreprocessor.h
   SkeletonMeshBuilder.cpp
   SkeletonMeshBuilder.h
   SplitByBoneCountProcess.cpp
   SplitByBoneCountProcess.h
+  ScaleProcess.cpp
+  ScaleProcess.h
   SmoothingGroups.h
   StandardShapes.cpp
   StandardShapes.h
@@ -163,6 +167,7 @@ SET( Common_SRCS
   RemoveComments.h
   Subdivision.cpp
   Subdivision.h
+  scene.cpp
   Vertex.h
   LineSplitter.h
   TinyFormatter.h
@@ -173,6 +178,8 @@ SET( Common_SRCS
   XMLTools.h
   Version.cpp
   IOStreamBuffer.h
+  CreateAnimMesh.h
+  CreateAnimMesh.cpp
 )
 SOURCE_GROUP(Common FILES ${Common_SRCS})
 
@@ -184,10 +191,16 @@ IF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
   SOURCE_GROUP( C4D FILES ${C4D_SRCS})
 ENDIF ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER )
 
+# if this variable is set to TRUE, the user can manually disable importers by setting
+# ASSIMP_BUILD_XXX_IMPORTER to FALSE for each importer
+# if this variable is set to FALSE, the user can manually enable importers by setting
+# ASSIMP_BUILD_XXX_IMPORTER to TRUE for each importer
+OPTION(ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT "default value of all ASSIMP_BUILD_XXX_IMPORTER value" TRUE)
+
 # macro to add the CMake Option ADD_ASSIMP_IMPORTER_<name> which enables compile of loader
 # this way selective loaders can be compiled (reduces filesize + compile time)
 MACRO(ADD_ASSIMP_IMPORTER name)
-  OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" TRUE)
+  OPTION(ASSIMP_BUILD_${name}_IMPORTER "build the ${name} importer" ${ASSIMP_BUILD_ALL_IMPORTERS_BY_DEFAULT})
   IF(ASSIMP_BUILD_${name}_IMPORTER)
     LIST(APPEND ASSIMP_LOADER_SRCS ${ARGN})
     SET(ASSIMP_IMPORTERS_ENABLED "${ASSIMP_IMPORTERS_ENABLED} ${name}")
@@ -560,6 +573,9 @@ SET( PostProcessing_SRCS
 )
 SOURCE_GROUP( PostProcessing FILES ${PostProcessing_SRCS})
 
+SET( IrrXML_SRCS irrXMLWrapper.h )
+SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS})
+
 ADD_ASSIMP_IMPORTER( Q3D
   Q3DLoader.cpp
   Q3DLoader.h
@@ -634,6 +650,9 @@ ADD_ASSIMP_IMPORTER(X3D
   X3DImporter_Rendering.cpp
   X3DImporter_Shape.cpp
   X3DImporter_Texturing.cpp
+  FIReader.hpp
+  FIReader.cpp
+  X3DVocabulary.cpp
 )
 
 ADD_ASSIMP_IMPORTER( GLTF
@@ -645,13 +664,34 @@ ADD_ASSIMP_IMPORTER( GLTF
   glTFImporter.h
   glTFExporter.h
   glTFExporter.cpp
+  glTF2Asset.h
+  glTF2Asset.inl
+  glTF2AssetWriter.h
+  glTF2AssetWriter.inl
+  glTF2Importer.cpp
+  glTF2Importer.h
+  glTF2Exporter.h
+  glTF2Exporter.cpp
 )
 
 ADD_ASSIMP_IMPORTER( 3MF
     D3MFImporter.h
     D3MFImporter.cpp
+    D3MFExporter.h
+    D3MFExporter.cpp
     D3MFOpcPackage.h
     D3MFOpcPackage.cpp
+    3MFXmlTags.h
+)
+
+ADD_ASSIMP_IMPORTER( MMD
+  MMDCpp14.h
+  MMDImporter.cpp
+  MMDImporter.h
+  MMDPmdParser.h
+  MMDPmxParser.h
+  MMDPmxParser.cpp
+  MMDVmdParser.h
 )
 
 SET( Step_SRCS
@@ -672,23 +712,6 @@ SET( Extra_SRCS
 )
 SOURCE_GROUP( Extra FILES ${Extra_SRCS})
 
-SET( IrrXML_SRCS
-  irrXMLWrapper.h
-  ../contrib/irrXML/CXMLReaderImpl.h
-  ../contrib/irrXML/heapsort.h
-  ../contrib/irrXML/irrArray.h
-  ../contrib/irrXML/irrString.h
-  ../contrib/irrXML/irrTypes.h
-  ../contrib/irrXML/irrXML.cpp
-  ../contrib/irrXML/irrXML.h
-)
-SOURCE_GROUP( IrrXML FILES ${IrrXML_SRCS})
-
-SET( ConvertUTF_SRCS
-  ../contrib/ConvertUTF/ConvertUTF.h
-  ../contrib/ConvertUTF/ConvertUTF.c
-)
-SOURCE_GROUP( ConvertUTF FILES ${ConvertUTF_SRCS})
 
 SET( Clipper_SRCS
   ../contrib/clipper/clipper.hpp
@@ -720,16 +743,26 @@ SET( unzip_SRCS
 )
 SOURCE_GROUP( unzip FILES ${unzip_SRCS})
 
+SET( ziplib_SRCS
+  ../contrib/zip/src/miniz.h
+  ../contrib/zip/src/zip.c
+  ../contrib/zip/src/zip.h
+)
+
+SOURCE_GROUP( ziplib FILES ${ziplib_SRCS} )
+
 SET ( openddl_parser_SRCS
   ../contrib/openddlparser/code/OpenDDLParser.cpp
   ../contrib/openddlparser/code/DDLNode.cpp
   ../contrib/openddlparser/code/OpenDDLCommon.cpp
   ../contrib/openddlparser/code/OpenDDLExport.cpp
   ../contrib/openddlparser/code/Value.cpp
+  ../contrib/openddlparser/code/OpenDDLStream.cpp
   ../contrib/openddlparser/include/openddlparser/OpenDDLParser.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLParserUtils.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLCommon.h
   ../contrib/openddlparser/include/openddlparser/OpenDDLExport.h
+  ../contrib/openddlparser/include/openddlparser/OpenDDLStream.h
   ../contrib/openddlparser/include/openddlparser/DDLNode.h
   ../contrib/openddlparser/include/openddlparser/Value.h
 )
@@ -824,12 +857,12 @@ SET( assimp_src
 
   # Third-party libraries
   ${IrrXML_SRCS}
-  ${ConvertUTF_SRCS}
   ${unzip_compile_SRCS}
   ${Poly2Tri_SRCS}
   ${Clipper_SRCS}
   ${openddl_parser_SRCS}
   ${open3dgc_SRCS}
+  ${ziplib_SRCS}
   # Necessary to show the headers in the project when using the VC++ generator:
 
   ${PUBLIC_HEADERS}
@@ -839,7 +872,8 @@ SET( assimp_src
 ADD_DEFINITIONS( -DOPENDDLPARSER_BUILD )
 
 INCLUDE_DIRECTORIES(
-  ../contrib/openddlparser/include
+    ${IRRXML_INCLUDE_DIR}
+    ../contrib/openddlparser/include
 )
 
 IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
@@ -849,7 +883,7 @@ ENDIF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
 
 ADD_LIBRARY( assimp ${assimp_src} )
 
-TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} )
+TARGET_LINK_LIBRARIES(assimp ${ZLIB_LIBRARIES} ${OPENDDL_PARSER_LIBRARIES} ${IRRXML_LIBRARY} )
 
 if(ANDROID AND ASSIMP_ANDROID_JNIIOSYSTEM)
   set(ASSIMP_ANDROID_JNIIOSYSTEM_PATH port/AndroidJNI)
@@ -892,8 +926,27 @@ SET_TARGET_PROPERTIES( assimp PROPERTIES
 )
 
 if (APPLE)
-  SET_TARGET_PROPERTIES( assimp PROPERTIES INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${ASSIMP_LIB_INSTALL_DIR}")
-endif()
+  SET_TARGET_PROPERTIES( assimp PROPERTIES
+    INSTALL_NAME_DIR "${CMAKE_INSTALL_PREFIX}/${ASSIMP_LIB_INSTALL_DIR}"
+  )
+
+  if (BUILD_FRAMEWORK)
+    SET_TARGET_PROPERTIES( assimp PROPERTIES
+      FRAMEWORK TRUE
+      FRAMEWORK_VERSION C
+      MACOSX_FRAMEWORK_IDENTIFIER net.sf.assimp
+      PUBLIC_HEADER "${PUBLIC_HEADERS}"
+    )
+
+    # PUBLIC_HEADER option does not support directory structure creation
+    # add ./Compiler/*.h to assimp.framework via copy command
+    ADD_CUSTOM_COMMAND(TARGET assimp POST_BUILD 
+      COMMAND "${CMAKE_COMMAND}" -E copy_directory 
+         "../${HEADER_PATH}/Compiler"
+         assimp.framework/Headers/Compiler
+      COMMENT "Copying public ./Compiler/ header files to framework bundle's Headers/Compiler/")
+  endif(BUILD_FRAMEWORK)
+endif(APPLE)
 
 # Build against external unzip, or add ../contrib/unzip so
 # assimp can #include "unzip.h"
@@ -913,9 +966,11 @@ INSTALL( TARGETS assimp
   LIBRARY DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
   ARCHIVE DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
   RUNTIME DESTINATION ${ASSIMP_BIN_INSTALL_DIR}
+  FRAMEWORK DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
   COMPONENT ${LIBASSIMP_COMPONENT})
 INSTALL( FILES ${PUBLIC_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp COMPONENT assimp-dev)
 INSTALL( FILES ${COMPILER_HEADERS} DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}/assimp/Compiler COMPONENT assimp-dev)
+
 if (ASSIMP_ANDROID_JNIIOSYSTEM)
   INSTALL(FILES ${HEADER_PATH}/${ASSIMP_ANDROID_JNIIOSYSTEM_PATH}/AndroidJNIIOSystem.h
     DESTINATION ${ASSIMP_INCLUDE_INSTALL_DIR}
@@ -923,14 +978,25 @@ if (ASSIMP_ANDROID_JNIIOSYSTEM)
 endif(ASSIMP_ANDROID_JNIIOSYSTEM)
 
 if(MSVC AND ASSIMP_INSTALL_PDB)
-  install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb
-    DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
-    CONFIGURATIONS Debug
-  )
-  install(FILES ${Assimp_BINARY_DIR}/code/RelWithDebInfo/assimp.pdb
-    DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
-    CONFIGURATIONS RelWithDebInfo
-  )
+  IF(CMAKE_GENERATOR MATCHES "^Visual Studio")
+    install(FILES ${Assimp_BINARY_DIR}/code/Debug/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb
+      DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+      CONFIGURATIONS Debug
+    )
+    install(FILES ${Assimp_BINARY_DIR}/code/RelWithDebInfo/assimp${LIBRARY_SUFFIX}.pdb
+      DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+      CONFIGURATIONS RelWithDebInfo
+    )
+  ELSE()
+    install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}${CMAKE_DEBUG_POSTFIX}.pdb
+      DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+      CONFIGURATIONS Debug
+    )
+    install(FILES ${Assimp_BINARY_DIR}/code/assimp${LIBRARY_SUFFIX}.pdb
+      DESTINATION ${ASSIMP_LIB_INSTALL_DIR}
+      CONFIGURATIONS RelWithDebInfo
+    )
+  ENDIF()
 endif ()
 
 if (ASSIMP_COVERALLS)

+ 11 - 9
code/COBLoader.cpp

@@ -2,7 +2,7 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/IOSystem.hpp>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/scene.h>
-
+#include <assimp/importerdesc.h>
 
 using namespace Assimp;
 using namespace Assimp::COB;
@@ -941,20 +941,22 @@ void COBImporter::UnsupportedChunk_Binary( StreamReaderLE& reader, const ChunkIn
 // ------------------------------------------------------------------------------------------------
 // tiny utility guard to aid me at staying within chunk boundaries.
 class chunk_guard {
-
 public:
-
     chunk_guard(const COB::ChunkInfo& nfo, StreamReaderLE& reader)
-        : nfo(nfo)
-        , reader(reader)
-        , cur(reader.GetCurrentPos())
-    {
+    : nfo(nfo)
+    , reader(reader)
+    , cur(reader.GetCurrentPos()) {
     }
 
     ~chunk_guard() {
         // don't do anything if the size is not given
         if(nfo.size != static_cast<unsigned int>(-1)) {
-            reader.IncPtr(static_cast<int>(nfo.size)-reader.GetCurrentPos()+cur);
+            try {
+                reader.IncPtr( static_cast< int >( nfo.size ) - reader.GetCurrentPos() + cur );
+            } catch ( DeadlyImportError e ) {
+                // out of limit so correct the value
+                reader.IncPtr( reader.GetReadLimit() );
+            }
         }
     }
 

+ 2 - 1
code/COBLoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 6 - 4
code/COBScene.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -46,12 +47,13 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <memory>
 #include <deque>
+#include <map>
 
 #include "BaseImporter.h"
-#include "./../include/assimp/material.h"
+#include <assimp/material.h>
 
-namespace Assimp    {
-    namespace COB {
+namespace Assimp {
+namespace COB {
 
 // ------------------
 /** Represents a single vertex index in a face */

+ 3 - 2
code/CSMLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -57,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/anim.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/scene.h>
-
+#include <assimp/importerdesc.h>
 
 using namespace Assimp;
 

+ 2 - 1
code/CSMLoader.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 2 - 1
code/CalcTangentsProcess.cpp

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

+ 2 - 1
code/CalcTangentsProcess.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 527 - 60
code/ColladaExporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -38,18 +39,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
-
-
 #ifndef ASSIMP_BUILD_NO_EXPORT
 #ifndef ASSIMP_BUILD_NO_COLLADA_EXPORTER
-#include "ColladaExporter.h"
 
+#include "ColladaExporter.h"
 #include "Bitmap.h"
 #include "fast_atof.h"
-#include "SceneCombiner.h"
-#include "DefaultIOSystem.h"
+#include <assimp/SceneCombiner.h>
 #include "StringUtils.h"
 #include "XMLTools.h"
+#include <assimp/DefaultIOSystem.h>
 #include <assimp/IOSystem.hpp>
 #include <assimp/Exporter.hpp>
 #include <assimp/scene.h>
@@ -59,6 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <memory>
 #include <ctime>
 #include <set>
+#include <vector>
+#include <iostream>
 
 using namespace Assimp;
 
@@ -67,13 +68,17 @@ namespace Assimp
 
 // ------------------------------------------------------------------------------------------------
 // Worker function for exporting a scene to Collada. Prototyped and registered in Exporter.cpp
-void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* pProperties)
+void ExportSceneCollada(const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/)
 {
     std::string path = DefaultIOSystem::absolutePath(std::string(pFile));
     std::string file = DefaultIOSystem::completeBaseName(std::string(pFile));
 
     // invoke the exporter
     ColladaExporter iDoTheExportThing( pScene, pIOSystem, path, file);
+    
+    if (iDoTheExportThing.mOutput.fail()) {
+        throw DeadlyExportError("output data creation failed. Most likely the file became too large: " + std::string(pFile));
+    }
 
     // we're still here - export successfully completed. Write result to the given IOSYstem
     std::unique_ptr<IOStream> outfile (pIOSystem->Open(pFile,"wt"));
@@ -103,7 +108,7 @@ ColladaExporter::ColladaExporter( const aiScene* pScene, IOSystem* pIOSystem, co
     // set up strings
     endstr = "\n";
 
-    // start writing
+    // start writing the file
     WriteFile();
 }
 
@@ -133,8 +138,12 @@ void ColladaExporter::WriteFile()
     WriteLightsLibrary();
     WriteMaterials();
     WriteGeometryLibrary();
+    WriteControllerLibrary();
 
     WriteSceneLibrary();
+	
+	// customized, Writes the animation library
+	WriteAnimationsLibrary();
 
     // useless Collada fu at the end, just in case we haven't had enough indirections, yet.
     mOutput << startstr << "<scene>" << endstr;
@@ -550,7 +559,7 @@ void ColladaExporter::WriteImageEntry( const Surface& pSurface, const std::strin
     std::stringstream imageUrlEncoded;
     for( std::string::const_iterator it = pSurface.texture.begin(); it != pSurface.texture.end(); ++it )
     {
-      if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '.' || *it == '/' || *it == '\\' )
+      if( isalnum_C( (unsigned char) *it) || *it == ':' || *it == '_' || *it == '-' || *it == '.' || *it == '/' || *it == '\\' )
         imageUrlEncoded << *it;
       else
         imageUrlEncoded << '%' << std::hex << size_t( (unsigned char) *it) << std::dec;
@@ -652,7 +661,7 @@ void ColladaExporter::WriteMaterials()
       if( materialCountWithThisName == 0 ) {
         materials[a].name = name.C_Str();
       } else {
-        materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName);  
+        materials[a].name = std::string(name.C_Str()) + to_string(materialCountWithThisName);
       }
     }
     for( std::string::iterator it = materials[a].name.begin(); it != materials[a].name.end(); ++it ) {
@@ -692,7 +701,6 @@ void ColladaExporter::WriteMaterials()
 
     materials[a].shininess.exist = mat->Get( AI_MATKEY_SHININESS, materials[a].shininess.value) == aiReturn_SUCCESS;
     materials[a].transparency.exist = mat->Get( AI_MATKEY_OPACITY, materials[a].transparency.value) == aiReturn_SUCCESS;
-    materials[a].transparency.value = materials[a].transparency.value;
     materials[a].index_refraction.exist = mat->Get( AI_MATKEY_REFRACTI, materials[a].index_refraction.value) == aiReturn_SUCCESS;
   }
 
@@ -787,6 +795,177 @@ void ColladaExporter::WriteMaterials()
   }
 }
 
+// ------------------------------------------------------------------------------------------------
+// Writes the controller library
+void ColladaExporter::WriteControllerLibrary()
+{
+    mOutput << startstr << "<library_controllers>" << endstr;
+    PushTag();
+    
+    for( size_t a = 0; a < mScene->mNumMeshes; ++a)
+        WriteController( a);
+
+    PopTag();
+    mOutput << startstr << "</library_controllers>" << endstr;
+}
+
+// ------------------------------------------------------------------------------------------------
+// Writes a skin controller of the given mesh
+void ColladaExporter::WriteController( size_t pIndex)
+{
+    const aiMesh* mesh = mScene->mMeshes[pIndex];
+    const std::string idstr = GetMeshId( pIndex);
+    const std::string idstrEscaped = XMLEscape(idstr);
+
+    if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
+        return;
+
+    if ( mesh->mNumBones == 0 )
+        return;
+
+    mOutput << startstr << "<controller id=\"" << idstrEscaped << "-skin\" ";
+    mOutput << "name=\"skinCluster" << pIndex << "\">"<< endstr;
+    PushTag();
+
+    mOutput << startstr << "<skin source=\"#" << idstrEscaped << "\">" << endstr;
+    PushTag();
+
+    // bind pose matrix
+    mOutput << startstr << "<bind_shape_matrix>" << endstr;
+    PushTag();
+
+    // I think it is identity in general cases.
+    aiMatrix4x4 mat;
+    mOutput << startstr << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << endstr;
+    mOutput << startstr << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << endstr;
+    mOutput << startstr << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << endstr;
+    mOutput << startstr << mat.d1 << " " << mat.d2 << " " << mat.d3 << " " << mat.d4 << endstr;
+
+    PopTag();
+    mOutput << startstr << "</bind_shape_matrix>" << endstr;
+
+    mOutput << startstr << "<source id=\"" << idstrEscaped << "-skin-joints\" name=\"" << idstrEscaped << "-skin-joints\">" << endstr;
+    PushTag();
+
+    mOutput << startstr << "<Name_array id=\"" << idstrEscaped << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\">";
+
+    for( size_t i = 0; i < mesh->mNumBones; ++i )
+        mOutput << XMLEscape(mesh->mBones[i]->mName.C_Str()) << " ";
+
+    mOutput << "</Name_array>" << endstr;
+
+    mOutput << startstr << "<technique_common>" << endstr;
+    PushTag();
+    
+    mOutput << startstr << "<accessor source=\"#" << idstrEscaped << "-skin-joints-array\" count=\"" << mesh->mNumBones << "\" stride=\"" << 1 << "\">" << endstr;
+    PushTag();
+
+    mOutput << startstr << "<param name=\"JOINT\" type=\"Name\"></param>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</accessor>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</technique_common>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</source>" << endstr;
+
+    std::vector<ai_real> bind_poses;
+    bind_poses.reserve(mesh->mNumBones * 16);
+    for(unsigned int i = 0; i < mesh->mNumBones; ++i)
+        for( unsigned int j = 0; j < 4; ++j)
+            bind_poses.insert(bind_poses.end(), mesh->mBones[i]->mOffsetMatrix[j], mesh->mBones[i]->mOffsetMatrix[j] + 4);
+
+    WriteFloatArray( idstr + "-skin-bind_poses", FloatType_Mat4x4, (const ai_real*) bind_poses.data(), bind_poses.size() / 16);
+
+    bind_poses.clear();
+    
+    std::vector<ai_real> skin_weights;
+    skin_weights.reserve(mesh->mNumVertices * mesh->mNumBones);
+    for( size_t i = 0; i < mesh->mNumBones; ++i)
+        for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
+            skin_weights.push_back(mesh->mBones[i]->mWeights[j].mWeight);
+
+    WriteFloatArray( idstr + "-skin-weights", FloatType_Weight, (const ai_real*) skin_weights.data(), skin_weights.size());
+
+    skin_weights.clear();
+
+    mOutput << startstr << "<joints>" << endstr;
+    PushTag();
+
+    mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstrEscaped << "-skin-joints\"></input>" << endstr;
+    mOutput << startstr << "<input semantic=\"INV_BIND_MATRIX\" source=\"#" << idstrEscaped << "-skin-bind_poses\"></input>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</joints>" << endstr;
+
+    mOutput << startstr << "<vertex_weights count=\"" << mesh->mNumVertices << "\">" << endstr;
+    PushTag();
+
+    mOutput << startstr << "<input semantic=\"JOINT\" source=\"#" << idstrEscaped << "-skin-joints\" offset=\"0\"></input>" << endstr;
+    mOutput << startstr << "<input semantic=\"WEIGHT\" source=\"#" << idstrEscaped << "-skin-weights\" offset=\"1\"></input>" << endstr;
+
+    mOutput << startstr << "<vcount>";
+
+    std::vector<ai_uint> num_influences(mesh->mNumVertices, (ai_uint)0);
+    for( size_t i = 0; i < mesh->mNumBones; ++i)
+        for( size_t j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
+            ++num_influences[mesh->mBones[i]->mWeights[j].mVertexId];
+
+    for( size_t i = 0; i < mesh->mNumVertices; ++i)
+        mOutput << num_influences[i] << " ";
+
+    mOutput << "</vcount>" << endstr;
+
+    mOutput << startstr << "<v>";
+
+    ai_uint joint_weight_indices_length = 0;
+    std::vector<ai_uint> accum_influences;
+    accum_influences.reserve(num_influences.size());
+    for( size_t i = 0; i < num_influences.size(); ++i)
+    {
+        accum_influences.push_back(joint_weight_indices_length);
+        joint_weight_indices_length += num_influences[i];
+    }
+
+    ai_uint weight_index = 0;
+    std::vector<ai_int> joint_weight_indices(2 * joint_weight_indices_length, (ai_int)-1);
+    for( unsigned int i = 0; i < mesh->mNumBones; ++i)
+        for( unsigned j = 0; j < mesh->mBones[i]->mNumWeights; ++j)
+        {
+            unsigned int vId = mesh->mBones[i]->mWeights[j].mVertexId;
+            for( ai_uint k = 0; k < num_influences[vId]; ++k)
+            {
+                if (joint_weight_indices[2 * (accum_influences[vId] + k)] == -1)
+                {
+                    joint_weight_indices[2 * (accum_influences[vId] + k)] = i;
+                    joint_weight_indices[2 * (accum_influences[vId] + k) + 1] = weight_index;
+                    break;
+                }
+            }
+            ++weight_index;
+        }
+
+    for( size_t i = 0; i < joint_weight_indices.size(); ++i)
+        mOutput << joint_weight_indices[i] << " ";
+
+    num_influences.clear();
+    accum_influences.clear();
+    joint_weight_indices.clear();
+
+    mOutput << "</v>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</vertex_weights>" << endstr;
+
+    PopTag();
+    mOutput << startstr << "</skin>" << endstr;
+    
+    PopTag();
+    mOutput << startstr << "</controller>" << endstr;
+}
+
 // ------------------------------------------------------------------------------------------------
 // Writes the geometry library
 void ColladaExporter::WriteGeometryLibrary()
@@ -809,8 +988,8 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
     const std::string idstr = GetMeshId( pIndex);
     const std::string idstrEscaped = XMLEscape(idstr);
 
-  if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
-    return;
+    if ( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
+        return;
 
     // opening tag
     mOutput << startstr << "<geometry id=\"" << idstrEscaped << "\" name=\"" << idstrEscaped << "_name\" >" << endstr;
@@ -843,22 +1022,10 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
     }
 
     // assemble vertex structure
+    // Only write input for POSITION since we will write other as shared inputs in polygon definition
     mOutput << startstr << "<vertices id=\"" << idstrEscaped << "-vertices" << "\">" << endstr;
     PushTag();
     mOutput << startstr << "<input semantic=\"POSITION\" source=\"#" << idstrEscaped << "-positions\" />" << endstr;
-    if( mesh->HasNormals() )
-        mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstrEscaped << "-normals\" />" << endstr;
-    for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
-    {
-        if( mesh->HasTextureCoords(static_cast<unsigned int>(a)) )
-            mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstrEscaped << "-tex" << a << "\" " /*<< "set=\"" << a << "\"" */ << " />" << endstr;
-    }
-    for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
-    {
-        if( mesh->HasVertexColors(static_cast<unsigned int>(a) ) )
-            mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstrEscaped << "-color" << a << "\" " /*<< set=\"" << a << "\"" */ << " />" << endstr;
-    }
-
     PopTag();
     mOutput << startstr << "</vertices>" << endstr;
 
@@ -877,6 +1044,19 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
         mOutput << startstr << "<lines count=\"" << countLines << "\" material=\"defaultMaterial\">" << endstr;
         PushTag();
         mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
+        if( mesh->HasNormals() )
+            mOutput << startstr << "<input semantic=\"NORMAL\" source=\"#" << idstrEscaped << "-normals\" />" << endstr;
+        for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
+        {
+            if( mesh->HasTextureCoords(static_cast<unsigned int>(a)) )
+                mOutput << startstr << "<input semantic=\"TEXCOORD\" source=\"#" << idstrEscaped << "-tex" << a << "\" " << "set=\"" << a << "\""  << " />" << endstr;
+        }
+        for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
+        {
+            if( mesh->HasVertexColors(static_cast<unsigned int>(a) ) )
+                mOutput << startstr << "<input semantic=\"COLOR\" source=\"#" << idstrEscaped << "-color" << a << "\" " << "set=\"" << a << "\""  << " />" << endstr;
+        }
+
         mOutput << startstr << "<p>";
         for( size_t a = 0; a < mesh->mNumFaces; ++a )
         {
@@ -898,10 +1078,17 @@ void ColladaExporter::WriteGeometry( size_t pIndex)
         mOutput << startstr << "<polylist count=\"" << countPoly << "\" material=\"defaultMaterial\">" << endstr;
         PushTag();
         mOutput << startstr << "<input offset=\"0\" semantic=\"VERTEX\" source=\"#" << idstrEscaped << "-vertices\" />" << endstr;
+        if( mesh->HasNormals() )
+            mOutput << startstr << "<input offset=\"0\" semantic=\"NORMAL\" source=\"#" << idstrEscaped << "-normals\" />" << endstr;
         for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
         {
-            if( mesh->HasTextureCoords(static_cast<unsigned int>(a) ) )
-                mOutput << startstr << "<input offset=\"0\" semantic=\"TEXCOORD\" source=\"#" << idstrEscaped << "-tex" << a << "\" set=\"" << a << "\" />" << endstr;
+            if( mesh->HasTextureCoords(static_cast<unsigned int>(a)) )
+                mOutput << startstr << "<input offset=\"0\" semantic=\"TEXCOORD\" source=\"#" << idstrEscaped << "-tex" << a << "\" " << "set=\"" << a << "\""  << " />" << endstr;
+        }
+        for( size_t a = 0; a < AI_MAX_NUMBER_OF_COLOR_SETS; ++a )
+        {
+            if( mesh->HasVertexColors(static_cast<unsigned int>(a) ) )
+                mOutput << startstr << "<input offset=\"0\" semantic=\"COLOR\" source=\"#" << idstrEscaped << "-color" << a << "\" " << "set=\"" << a << "\""  << " />" << endstr;
         }
 
         mOutput << startstr << "<vcount>";
@@ -943,6 +1130,9 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
         case FloatType_TexCoord2: floatsPerElement = 2; break;
         case FloatType_TexCoord3: floatsPerElement = 3; break;
         case FloatType_Color: floatsPerElement = 3; break;
+        case FloatType_Mat4x4: floatsPerElement = 16; break;
+        case FloatType_Weight: floatsPerElement = 1; break;
+		case FloatType_Time: floatsPerElement = 1; break;
         default:
             return;
     }
@@ -1011,7 +1201,21 @@ void ColladaExporter::WriteFloatArray( const std::string& pIdString, FloatDataTy
             mOutput << startstr << "<param name=\"G\" type=\"float\" />" << endstr;
             mOutput << startstr << "<param name=\"B\" type=\"float\" />" << endstr;
             break;
-    }
+
+        case FloatType_Mat4x4:
+            mOutput << startstr << "<param name=\"TRANSFORM\" type=\"float4x4\" />" << endstr;
+            break;
+
+        case FloatType_Weight:
+            mOutput << startstr << "<param name=\"WEIGHT\" type=\"float\" />" << endstr;
+            break;
+
+		// customized, add animation related
+		case FloatType_Time:
+			mOutput << startstr << "<param name=\"TIME\" type=\"float\" />" << endstr;
+			break;
+
+	}
 
     PopTag();
     mOutput << startstr << "</accessor>" << endstr;
@@ -1041,7 +1245,172 @@ void ColladaExporter::WriteSceneLibrary()
     PopTag();
     mOutput << startstr << "</library_visual_scenes>" << endstr;
 }
-
+// ------------------------------------------------------------------------------------------------
+void ColladaExporter::WriteAnimationLibrary(size_t pIndex)
+{
+	const aiAnimation * anim = mScene->mAnimations[pIndex];
+	
+	if ( anim->mNumChannels == 0 && anim->mNumMeshChannels == 0 && anim->mNumMorphMeshChannels ==0 )
+		return;
+	
+	const std::string animation_name_escaped = XMLEscape( anim->mName.C_Str() );
+	std::string idstr = anim->mName.C_Str();
+	std::string ending = std::string( "AnimId" ) + to_string(pIndex);
+	if (idstr.length() >= ending.length()) {
+		if (0 != idstr.compare (idstr.length() - ending.length(), ending.length(), ending)) {
+			idstr = idstr + ending;
+		}
+	} else {
+		idstr = idstr + ending;
+	}
+
+	const std::string idstrEscaped = XMLEscape(idstr);
+	
+	mOutput << startstr << "<animation id=\"" + idstrEscaped + "\" name=\"" + animation_name_escaped + "\">" << endstr;
+	PushTag();
+	
+	for (size_t a = 0; a < anim->mNumChannels; ++a) {
+		const aiNodeAnim * nodeAnim = anim->mChannels[a];
+		
+		// sanity check
+		if ( nodeAnim->mNumPositionKeys != nodeAnim->mNumScalingKeys ||  nodeAnim->mNumPositionKeys != nodeAnim->mNumRotationKeys ) continue;
+		
+		{
+			const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-input");
+
+			std::vector<ai_real> frames;
+			for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
+				frames.push_back(static_cast<ai_real>(nodeAnim->mPositionKeys[i].mTime));
+			}
+			
+			WriteFloatArray( node_idstr , FloatType_Time, (const ai_real*) frames.data(), frames.size());
+			frames.clear();
+		}
+		
+		{
+			const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-output");
+			
+			std::vector<ai_real> keyframes;
+			keyframes.reserve(nodeAnim->mNumPositionKeys * 16);
+			for( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
+				
+				aiVector3D Scaling = nodeAnim->mScalingKeys[i].mValue;
+				aiMatrix4x4 ScalingM;  // identity
+				ScalingM[0][0] = Scaling.x; ScalingM[1][1] = Scaling.y; ScalingM[2][2] = Scaling.z;
+				
+				aiQuaternion RotationQ = nodeAnim->mRotationKeys[i].mValue;
+				aiMatrix4x4 s = aiMatrix4x4( RotationQ.GetMatrix() );
+				aiMatrix4x4 RotationM(s.a1, s.a2, s.a3, 0, s.b1, s.b2, s.b3, 0, s.c1, s.c2, s.c3, 0, 0, 0, 0, 1);
+				
+				aiVector3D Translation = nodeAnim->mPositionKeys[i].mValue;
+				aiMatrix4x4 TranslationM;	// identity
+				TranslationM[0][3] = Translation.x; TranslationM[1][3] = Translation.y; TranslationM[2][3] = Translation.z;
+				
+				// Combine the above transformations
+				aiMatrix4x4 mat = TranslationM * RotationM * ScalingM;
+				
+				for( unsigned int j = 0; j < 4; ++j) {
+					keyframes.insert(keyframes.end(), mat[j], mat[j] + 4);
+                }
+			}
+			
+			WriteFloatArray( node_idstr, FloatType_Mat4x4, (const ai_real*) keyframes.data(), keyframes.size() / 16);
+		}
+		
+		{
+			std::vector<std::string> names;
+			for ( size_t i = 0; i < nodeAnim->mNumPositionKeys; ++i) {
+				if ( nodeAnim->mPreState == aiAnimBehaviour_DEFAULT
+					|| nodeAnim->mPreState == aiAnimBehaviour_LINEAR
+					|| nodeAnim->mPreState == aiAnimBehaviour_REPEAT
+					) {
+					names.push_back( "LINEAR" );
+				} else if (nodeAnim->mPostState == aiAnimBehaviour_CONSTANT) {
+					names.push_back( "STEP" );
+				}
+			}
+			
+			const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-interpolation");
+			std::string arrayId = node_idstr + "-array";
+			
+			mOutput << startstr << "<source id=\"" << XMLEscape(node_idstr) << "\">" << endstr;
+			PushTag();
+			
+			// source array
+			mOutput << startstr << "<Name_array id=\"" << XMLEscape(arrayId) << "\" count=\"" << names.size() << "\"> ";
+			for( size_t a = 0; a < names.size(); ++a ) {
+				mOutput << names[a] << " ";
+            }
+			mOutput << "</Name_array>" << endstr;
+			
+			mOutput << startstr << "<technique_common>" << endstr;
+			PushTag();
+
+			mOutput << startstr << "<accessor source=\"#" << XMLEscape(arrayId) << "\" count=\"" << names.size() << "\" stride=\"" << 1 << "\">" << endstr;
+			PushTag();
+			
+			mOutput << startstr << "<param name=\"INTERPOLATION\" type=\"name\"></param>" << endstr;
+			
+			PopTag();
+			mOutput << startstr << "</accessor>" << endstr;
+			
+			PopTag();
+			mOutput << startstr << "</technique_common>" << endstr;
+
+			PopTag();
+			mOutput << startstr << "</source>" << endstr;
+		}
+		
+	}
+	
+	for (size_t a = 0; a < anim->mNumChannels; ++a) {
+		const aiNodeAnim * nodeAnim = anim->mChannels[a];
+		
+		{
+		// samplers
+			const std::string node_idstr = nodeAnim->mNodeName.data + std::string("_matrix-sampler");
+			mOutput << startstr << "<sampler id=\"" << XMLEscape(node_idstr) << "\">" << endstr;
+			PushTag();
+			
+			mOutput << startstr << "<input semantic=\"INPUT\" source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-input") ) << "\"/>" << endstr;
+			mOutput << startstr << "<input semantic=\"OUTPUT\" source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-output") ) << "\"/>" << endstr;
+			mOutput << startstr << "<input semantic=\"INTERPOLATION\" source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-interpolation") ) << "\"/>" << endstr;
+			
+			PopTag();
+			mOutput << startstr << "</sampler>" << endstr;
+		}
+	}
+	
+	for (size_t a = 0; a < anim->mNumChannels; ++a) {
+		const aiNodeAnim * nodeAnim = anim->mChannels[a];
+		
+		{
+		// channels
+			mOutput << startstr << "<channel source=\"#" << XMLEscape( nodeAnim->mNodeName.data + std::string("_matrix-sampler") ) << "\" target=\"" << XMLEscape(nodeAnim->mNodeName.data) << "/matrix\"/>" << endstr;
+		}
+	}
+	
+	PopTag();
+	mOutput << startstr << "</animation>" << endstr;
+	
+}
+// ------------------------------------------------------------------------------------------------
+void ColladaExporter::WriteAnimationsLibrary()
+{
+	const std::string scene_name_escaped = XMLEscape(mScene->mRootNode->mName.C_Str());
+	
+	if ( mScene->mNumAnimations > 0 ) {
+		mOutput << startstr << "<library_animations>" << endstr;
+		PushTag();
+		
+		// start recursive write at the root node
+		for( size_t a = 0; a < mScene->mNumAnimations; ++a)
+			WriteAnimationLibrary( a );
+
+		PopTag();
+		mOutput << startstr << "</library_animations>" << endstr;
+	}
+}
 // ------------------------------------------------------------------------------------------------
 // Helper to find a bone by name in the scene
 aiBone* findBone( const aiScene* scene, const char * name) {
@@ -1057,6 +1426,59 @@ aiBone* findBone( const aiScene* scene, const char * name) {
     return NULL;
 }
 
+// ------------------------------------------------------------------------------------------------
+const aiNode * findBoneNode( const aiNode* aNode, const aiBone* bone)
+{
+	if ( aNode && bone && aNode->mName == bone->mName ) {
+		return aNode;
+	}
+	
+	if ( aNode && bone ) {
+		for (unsigned int i=0; i < aNode->mNumChildren; ++i) {
+			aiNode * aChild = aNode->mChildren[i];
+			const aiNode * foundFromChild = 0;
+			if ( aChild ) {
+				foundFromChild = findBoneNode( aChild, bone );
+				if ( foundFromChild ) return foundFromChild;
+			}
+		}
+	}
+	
+	return NULL;
+}
+
+const aiNode * findSkeletonRootNode( const aiScene* scene, const aiMesh * mesh)
+{
+	std::set<const aiNode*> topParentBoneNodes;
+	if ( mesh && mesh->mNumBones > 0 ) {
+		for (unsigned int i=0; i < mesh->mNumBones; ++i) {
+			aiBone * bone = mesh->mBones[i];
+
+			const aiNode * node = findBoneNode( scene->mRootNode, bone);
+			if ( node ) {
+				while ( node->mParent && findBone(scene, node->mParent->mName.C_Str() ) != 0 ) {
+					node = node->mParent;
+				}
+				topParentBoneNodes.insert( node );
+			}
+		}
+	}
+	
+	if ( !topParentBoneNodes.empty() ) {
+		const aiNode * parentBoneNode = *topParentBoneNodes.begin();
+		if ( topParentBoneNodes.size() == 1 ) {
+			return parentBoneNode;
+		} else {
+			for (auto it : topParentBoneNodes) {
+				if ( it->mParent ) return it->mParent;
+			}
+			return parentBoneNode;
+		}
+	}
+	
+	return NULL;
+}
+
 // ------------------------------------------------------------------------------------------------
 // Recursively writes the given node
 void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
@@ -1072,16 +1494,34 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
     // If the node is associated with a bone, it is a joint node (JOINT)
     // otherwise it is a normal node (NODE)
     const char * node_type;
+    bool is_joint, is_skeleton_root = false;
     if (NULL == findBone(pScene, pNode->mName.C_Str())) {
         node_type = "NODE";
+        is_joint = false;
     } else {
         node_type = "JOINT";
+        is_joint = true;
+        if(!pNode->mParent || NULL == findBone(pScene, pNode->mParent->mName.C_Str()))
+            is_skeleton_root = true;
     }
 
     const std::string node_name_escaped = XMLEscape(pNode->mName.data);
+	/* // customized, Note! the id field is crucial for inter-xml look up, it cannot be replaced with sid ?!
     mOutput << startstr
-            << "<node id=\"" << node_name_escaped
-            << "\" name=\"" << node_name_escaped
+            << "<node ";
+    if(is_skeleton_root)
+        mOutput << "id=\"" << "skeleton_root" << "\" "; // For now, only support one skeleton in a scene.
+    mOutput << (is_joint ? "s" : "") << "id=\"" << node_name_escaped;
+	 */
+	mOutput << startstr << "<node ";
+	if(is_skeleton_root) {
+		mOutput << "id=\"" << node_name_escaped << "\" " << (is_joint ? "sid=\"" + node_name_escaped +"\"" : "") ; // For now, only support one skeleton in a scene.
+		mFoundSkeletonRootNodeID = node_name_escaped;
+	} else {
+		mOutput << "id=\"" << node_name_escaped << "\" " << (is_joint ? "sid=\"" + node_name_escaped +"\"": "") ;
+	}
+	
+    mOutput << " name=\"" << node_name_escaped
             << "\" type=\"" << node_type
             << "\">" << endstr;
     PushTag();
@@ -1089,7 +1529,11 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
     // write transformation - we can directly put the matrix there
     // TODO: (thom) decompose into scale - rot - quad to allow addressing it by animations afterwards
     const aiMatrix4x4& mat = pNode->mTransformation;
-    mOutput << startstr << "<matrix>";
+	
+	// customized, sid should be 'matrix' to match with loader code.
+    //mOutput << startstr << "<matrix sid=\"transform\">";
+	mOutput << startstr << "<matrix sid=\"matrix\">";
+	
     mOutput << mat.a1 << " " << mat.a2 << " " << mat.a3 << " " << mat.a4 << " ";
     mOutput << mat.b1 << " " << mat.b2 << " " << mat.b3 << " " << mat.b4 << " ";
     mOutput << mat.c1 << " " << mat.c2 << " " << mat.c3 << " " << mat.c4 << " ";
@@ -1117,33 +1561,56 @@ void ColladaExporter::WriteNode( const aiScene* pScene, aiNode* pNode)
     for( size_t a = 0; a < pNode->mNumMeshes; ++a )
     {
         const aiMesh* mesh = mScene->mMeshes[pNode->mMeshes[a]];
-    // do not instanciate mesh if empty. I wonder how this could happen
-    if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
-        continue;
-    mOutput << startstr << "<instance_geometry url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "\">" << endstr;
-    PushTag();
-    mOutput << startstr << "<bind_material>" << endstr;
-    PushTag();
-    mOutput << startstr << "<technique_common>" << endstr;
-    PushTag();
-    mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << XMLEscape(materials[mesh->mMaterialIndex].name) << "\">" << endstr;
-    PushTag();
-    for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
-    {
-        if( mesh->HasTextureCoords( static_cast<unsigned int>(a) ) )
-            // semantic       as in <texture texcoord=...>
-            // input_semantic as in <input semantic=...>
-            // input_set      as in <input set=...>
-            mOutput << startstr << "<bind_vertex_input semantic=\"CHANNEL" << a << "\" input_semantic=\"TEXCOORD\" input_set=\"" << a << "\"/>" << endstr;
-    }
-    PopTag();
-    mOutput << startstr << "</instance_material>" << endstr;
-    PopTag();
-    mOutput << startstr << "</technique_common>" << endstr;
-    PopTag();
-    mOutput << startstr << "</bind_material>" << endstr;
-    PopTag();
-        mOutput << startstr << "</instance_geometry>" << endstr;
+        // do not instantiate mesh if empty. I wonder how this could happen
+        if( mesh->mNumFaces == 0 || mesh->mNumVertices == 0 )
+            continue;
+
+        if( mesh->mNumBones == 0 )
+        {
+            mOutput << startstr << "<instance_geometry url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "\">" << endstr;
+            PushTag();
+        }
+        else
+        {
+            mOutput << startstr
+                    << "<instance_controller url=\"#" << XMLEscape(GetMeshId( pNode->mMeshes[a])) << "-skin\">"
+                    << endstr;
+            PushTag();
+
+			// note! this mFoundSkeletonRootNodeID some how affects animation, it makes the mesh attaches to armature skeleton root node.
+			// use the first bone to find skeleton root
+			const aiNode * skeletonRootBoneNode = findSkeletonRootNode( pScene, mesh );
+			if ( skeletonRootBoneNode ) {
+				mFoundSkeletonRootNodeID = XMLEscape( skeletonRootBoneNode->mName.C_Str() );
+			}
+            mOutput << startstr << "<skeleton>#" << mFoundSkeletonRootNodeID << "</skeleton>" << endstr;
+        }
+        mOutput << startstr << "<bind_material>" << endstr;
+        PushTag();
+        mOutput << startstr << "<technique_common>" << endstr;
+        PushTag();
+        mOutput << startstr << "<instance_material symbol=\"defaultMaterial\" target=\"#" << XMLEscape(materials[mesh->mMaterialIndex].name) << "\">" << endstr;
+        PushTag();
+        for( size_t a = 0; a < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++a )
+        {
+            if( mesh->HasTextureCoords( static_cast<unsigned int>(a) ) )
+                // semantic       as in <texture texcoord=...>
+                // input_semantic as in <input semantic=...>
+                // input_set      as in <input set=...>
+                mOutput << startstr << "<bind_vertex_input semantic=\"CHANNEL" << a << "\" input_semantic=\"TEXCOORD\" input_set=\"" << a << "\"/>" << endstr;
+        }
+        PopTag();
+        mOutput << startstr << "</instance_material>" << endstr;
+        PopTag();
+        mOutput << startstr << "</technique_common>" << endstr;
+        PopTag();
+        mOutput << startstr << "</bind_material>" << endstr;
+        
+        PopTag();
+        if( mesh->mNumBones == 0)
+            mOutput << startstr << "</instance_geometry>" << endstr;
+        else
+            mOutput << startstr << "</instance_controller>" << endstr;
     }
 
     // recurse into subnodes

+ 20 - 3
code/ColladaExporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -101,13 +102,21 @@ protected:
     void WriteSpotLight(const aiLight *const light);
     void WriteAmbienttLight(const aiLight *const light);
 
+    /// Writes the controller library
+    void WriteControllerLibrary();
+
+    /// Writes a skin controller of the given mesh
+    void WriteController( size_t pIndex);
+
     /// Writes the geometry library
     void WriteGeometryLibrary();
 
     /// Writes the given mesh
     void WriteGeometry( size_t pIndex);
 
-    enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color };
+    //enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight };
+    // customized to add animation related type
+	enum FloatDataType { FloatType_Vector, FloatType_TexCoord2, FloatType_TexCoord3, FloatType_Color, FloatType_Mat4x4, FloatType_Weight, FloatType_Time };
 
     /// Writes a float array of the given type
     void WriteFloatArray( const std::string& pIdString, FloatDataType pType, const ai_real* pData, size_t pElementCount);
@@ -115,13 +124,21 @@ protected:
     /// Writes the scene library
     void WriteSceneLibrary();
 
+	// customized, Writes the animation library
+	void WriteAnimationsLibrary();
+	void WriteAnimationLibrary( size_t pIndex);
+	std::string mFoundSkeletonRootNodeID = "skeleton_root";	 	// will be replaced by found node id in the WriteNode call.
+	
     /// Recursively writes the given node
     void WriteNode( const aiScene* scene, aiNode* pNode);
 
     /// Enters a new xml element, which increases the indentation
     void PushTag() { startstr.append( "  "); }
     /// Leaves an element, decreasing the indentation
-    void PopTag() { ai_assert( startstr.length() > 1); startstr.erase( startstr.length() - 2); }
+    void PopTag() { 
+        ai_assert( startstr.length() > 1); 
+        startstr.erase( startstr.length() - 2); 
+    }
 
     /// Creates a mesh ID for the given mesh
     std::string GetMeshId( size_t pIndex) const {

+ 34 - 3
code/ColladaHelper.h

@@ -4,7 +4,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -43,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_COLLADAHELPER_H_INC
 #define AI_COLLADAHELPER_H_INC
 
-#include <string>
 #include <map>
 #include <vector>
 #include <stdint.h>
@@ -89,6 +89,21 @@ enum InputType
     IT_Bitangent
 };
 
+/** Supported controller types */
+enum ControllerType
+{
+    Skin,
+    Morph
+};
+
+/** Supported morph methods */
+enum MorphMethod
+{
+    Normalized,
+    Relative
+};
+
+
 /** Contains all data for one of the different transformation types */
 struct Transform
 {
@@ -287,7 +302,7 @@ struct Accessor
     size_t mOffset;  // in number of values
     size_t mStride;  // Stride in number of values
     std::vector<std::string> mParams; // names of the data streams in the accessors. Empty string tells to ignore.
-    size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, thats XYZ, for a color RGBA and so on.
+    size_t mSubOffset[4]; // Suboffset inside the object for the common 4 elements. For a vector, that's XYZ, for a color RGBA and so on.
                           // For example, SubOffset[0] denotes which of the values inside the object is the vector X component.
     std::string mSource;   // URL of the source array
     mutable const Data* mData; // Pointer to the source array, if resolved. NULL else
@@ -380,6 +395,12 @@ enum PrimitiveType
 /** A skeleton controller to deform a mesh with the use of joints */
 struct Controller
 {
+    // controller type
+    ControllerType mType;
+
+    // Morphing method if type is Morph
+    MorphMethod mMethod;
+
     // the URL of the mesh deformed by the controller.
     std::string mMeshId;
 
@@ -402,6 +423,9 @@ struct Controller
 
     // JointIndex-WeightIndex pairs for all vertices
     std::vector< std::pair<size_t, size_t> > mWeights;
+
+    std::string mMorphTarget;
+    std::string mMorphWeight;
 };
 
 /** A collada material. Pretty much the only member is a reference to an effect. */
@@ -577,6 +601,12 @@ struct AnimationChannel
     std::string mSourceTimes;
     /** Source URL of the value values. Collada calls them "output". */
     std::string mSourceValues;
+    /** Source URL of the IN_TANGENT semantic values. */
+    std::string mInTanValues;
+    /** Source URL of the OUT_TANGENT semantic values. */
+    std::string mOutTanValues;
+    /** Source URL of the INTERPOLATION semantic values. */
+    std::string mInterpolationValues;
 };
 
 /** An animation. Container for 0-x animation channels or 0-x animations */
@@ -645,6 +675,7 @@ struct Animation
 struct ChannelEntry
 {
     const Collada::AnimationChannel* mChannel; ///> the source channel
+    std::string mTargetId;
     std::string mTransformId;   // the ID of the transformation step of the node which is influenced
     size_t mTransformIndex; // Index into the node's transform chain to apply the channel to
     size_t mSubElement; // starting index inside the transform data

+ 298 - 55
code/ColladaLoader.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -49,20 +50,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/scene.h>
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/Importer.hpp>
-#include "ColladaParser.h"
+#include <assimp/importerdesc.h>
 
+#include "ColladaParser.h"
 #include "fast_atof.h"
 #include "ParsingUtils.h"
 #include "SkeletonMeshBuilder.h"
-#include "Defines.h"
+#include "CreateAnimMesh.h"
 
 #include "time.h"
 #include "math.h"
 #include <algorithm>
-#include <cstdint>
 #include <numeric>
-#include "Defines.h"
-
+#include <assimp/Defines.h>
 
 using namespace Assimp;
 using namespace Assimp::Formatter;
@@ -119,7 +119,7 @@ bool ColladaLoader::CanRead( const std::string& pFile, IOSystem* pIOHandler, boo
          *  might be NULL and it's our duty to return true here.
          */
         if (!pIOHandler)return true;
-        const char* tokens[] = {"collada"};
+        const char* tokens[] = {"<collada"};
         return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
     }
     return false;
@@ -132,7 +132,6 @@ void ColladaLoader::SetupProperties(const Importer* pImp)
     ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION,0) != 0;
 }
 
-
 // ------------------------------------------------------------------------------------------------
 // Get file extension list
 const aiImporterDesc* ColladaLoader::GetInfo () const
@@ -150,6 +149,7 @@ void ColladaLoader::InternReadFile( const std::string& pFile, aiScene* pScene, I
     mMeshIndexByID.clear();
     mMaterialIndexByName.clear();
     mMeshes.clear();
+    mTargetMeshes.clear();
     newMats.clear();
     mLights.clear();
     mCameras.clear();
@@ -571,6 +571,21 @@ void ColladaLoader::BuildMeshesForNode( const ColladaParser& pParser, const Coll
     }
 }
 
+// ------------------------------------------------------------------------------------------------
+// Find mesh from either meshes or morph target meshes
+aiMesh *ColladaLoader::findMesh(std::string meshid)
+{
+    for (unsigned int i = 0; i < mMeshes.size(); i++)
+        if (std::string(mMeshes[i]->mName.data) == meshid)
+            return mMeshes[i];
+
+    for (unsigned int i = 0; i < mTargetMeshes.size(); i++)
+        if (std::string(mTargetMeshes[i]->mName.data) == meshid)
+            return mTargetMeshes[i];
+
+    return NULL;
+}
+
 // ------------------------------------------------------------------------------------------------
 // Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh
 aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
@@ -656,8 +671,70 @@ aiMesh* ColladaLoader::CreateMesh( const ColladaParser& pParser, const Collada::
             face.mIndices[b] = static_cast<unsigned int>(vertex++);
     }
 
+    // create morph target meshes if any
+    std::vector<aiMesh*> targetMeshes;
+    std::vector<float> targetWeights;
+    Collada::MorphMethod method = Collada::Normalized;
+
+    for(std::map<std::string, Collada::Controller>::const_iterator it = pParser.mControllerLibrary.begin();
+        it != pParser.mControllerLibrary.end(); it++)
+    {
+        const Collada::Controller &c = it->second;
+        const Collada::Mesh* baseMesh = pParser.ResolveLibraryReference( pParser.mMeshLibrary, c.mMeshId);
+
+        if (c.mType == Collada::Morph && baseMesh->mName == pSrcMesh->mName)
+        {
+            const Collada::Accessor& targetAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphTarget);
+            const Collada::Accessor& weightAccessor = pParser.ResolveLibraryReference( pParser.mAccessorLibrary, c.mMorphWeight);
+            const Collada::Data& targetData = pParser.ResolveLibraryReference( pParser.mDataLibrary, targetAccessor.mSource);
+            const Collada::Data& weightData = pParser.ResolveLibraryReference( pParser.mDataLibrary, weightAccessor.mSource);
+
+            // take method
+            method = c.mMethod;
+
+            if (!targetData.mIsStringArray)
+                throw DeadlyImportError( "target data must contain id. ");
+            if (weightData.mIsStringArray)
+                throw DeadlyImportError( "target weight data must not be textual ");
+
+            for (unsigned int i = 0; i < targetData.mStrings.size(); ++i)
+            {
+                const Collada::Mesh* targetMesh = pParser.ResolveLibraryReference(pParser.mMeshLibrary, targetData.mStrings.at(i));
+
+                aiMesh *aimesh = findMesh(targetMesh->mName);
+                if (!aimesh)
+                {
+                    if (targetMesh->mSubMeshes.size() > 1)
+                        throw DeadlyImportError( "Morhing target mesh must be a single");
+                    aimesh = CreateMesh(pParser, targetMesh, targetMesh->mSubMeshes.at(0), NULL, 0, 0);
+                    mTargetMeshes.push_back(aimesh);
+                }
+                targetMeshes.push_back(aimesh);
+            }
+            for (unsigned int i = 0; i < weightData.mValues.size(); ++i)
+                targetWeights.push_back(weightData.mValues.at(i));
+        }
+    }
+    if (targetMeshes.size() > 0 && targetWeights.size() == targetMeshes.size())
+    {
+        std::vector<aiAnimMesh*> animMeshes;
+        for (unsigned int i = 0; i < targetMeshes.size(); i++)
+        {
+            aiAnimMesh *animMesh = aiCreateAnimMesh(targetMeshes.at(i));
+            animMesh->mWeight = targetWeights[i];
+            animMeshes.push_back(animMesh);
+        }
+        dstMesh->mMethod = (method == Collada::Relative)
+                                ? aiMorphingMethod_MORPH_RELATIVE
+                                : aiMorphingMethod_MORPH_NORMALIZED;
+        dstMesh->mAnimMeshes = new aiAnimMesh*[animMeshes.size()];
+        dstMesh->mNumAnimMeshes = static_cast<unsigned int>(animMeshes.size());
+        for (unsigned int i = 0; i < animMeshes.size(); i++)
+            dstMesh->mAnimMeshes[i] = animMeshes.at(i);
+    }
+
     // create bones if given
-    if( pSrcController)
+    if( pSrcController && pSrcController->mType == Collada::Skin)
     {
         // refuse if the vertex count does not match
 //      if( pSrcController->mWeightCounts.size() != dstMesh->mNumVertices)
@@ -956,6 +1033,68 @@ void ColladaLoader::StoreAnimations( aiScene* pScene, const ColladaParser& pPars
         CreateAnimation( pScene, pParser, pSrcAnim, animName);
 }
 
+struct MorphTimeValues
+{
+    float mTime;
+    struct key
+    {
+        float mWeight;
+        unsigned int mValue;
+    };
+    std::vector<key> mKeys;
+};
+
+void insertMorphTimeValue(std::vector<MorphTimeValues> &values, float time, float weight, unsigned int value)
+{
+    MorphTimeValues::key k;
+    k.mValue = value;
+    k.mWeight = weight;
+    if (values.size() == 0 || time < values[0].mTime)
+    {
+        MorphTimeValues val;
+        val.mTime = time;
+        val.mKeys.push_back(k);
+        values.insert(values.begin(), val);
+        return;
+    }
+    if (time > values.back().mTime)
+    {
+        MorphTimeValues val;
+        val.mTime = time;
+        val.mKeys.push_back(k);
+        values.insert(values.end(), val);
+        return;
+    }
+    for (unsigned int i = 0; i < values.size(); i++)
+    {
+        if (std::abs(time - values[i].mTime) < 1e-6f)
+        {
+            values[i].mKeys.push_back(k);
+            return;
+        } else if (time > values[i].mTime && time < values[i+1].mTime)
+        {
+            MorphTimeValues val;
+            val.mTime = time;
+            val.mKeys.push_back(k);
+            values.insert(values.begin() + i, val);
+            return;
+        }
+    }
+    // should not get here
+}
+
+float getWeightAtKey(const std::vector<MorphTimeValues> &values, int key, unsigned int value)
+{
+    for (unsigned int i = 0; i < values[key].mKeys.size(); i++)
+    {
+        if (values[key].mKeys[i].mValue == value)
+            return values[key].mKeys[i].mWeight;
+    }
+    // no value at key found, try to interpolate if present at other keys. if not, return zero
+    // TODO: interpolation
+    return 0.0f;
+}
+
 // ------------------------------------------------------------------------------------------------
 // Constructs the animation for the given source anim
 void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pParser, const Collada::Animation* pSrcAnim, const std::string& pName)
@@ -965,6 +1104,8 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
     CollectNodes( pScene->mRootNode, nodes);
 
     std::vector<aiNodeAnim*> anims;
+    std::vector<aiMeshMorphAnim*> morphAnims;
+
     for( std::vector<const aiNode*>::const_iterator nit = nodes.begin(); nit != nodes.end(); ++nit)
     {
         // find all the collada anim channels which refer to the current node
@@ -988,7 +1129,20 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
             // find the slash that separates the node name - there should be only one
             std::string::size_type slashPos = srcChannel.mTarget.find( '/');
             if( slashPos == std::string::npos)
+            {
+                std::string::size_type targetPos = srcChannel.mTarget.find(srcNode->mID);
+                if (targetPos == std::string::npos)
+                    continue;
+
+                // not node transform, but something else. store as unknown animation channel for now
+                entry.mChannel = &(*cit);
+                entry.mTargetId = srcChannel.mTarget.substr(targetPos + pSrcAnim->mName.length(),
+                                        srcChannel.mTarget.length() - targetPos - pSrcAnim->mName.length());
+                if (entry.mTargetId.front() == '-')
+                    entry.mTargetId = entry.mTargetId.substr(1);
+                entries.push_back(entry);
                 continue;
+            }
             if( srcChannel.mTarget.find( '/', slashPos+1) != std::string::npos)
                 continue;
             std::string targetID = srcChannel.mTarget.substr( 0, slashPos);
@@ -1068,8 +1222,14 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
                 if( srcNode->mTransforms[a].mID == entry.mTransformId)
                     entry.mTransformIndex = a;
 
-            if( entry.mTransformIndex == SIZE_MAX) {
-                continue;
+            if( entry.mTransformIndex == SIZE_MAX)
+            {
+                if (entry.mTransformId.find("morph-weights") != std::string::npos)
+                {
+                    entry.mTargetId = entry.mTransformId;
+                    entry.mTransformId = "";
+                } else
+                    continue;
             }
 
             entry.mChannel = &(*cit);
@@ -1213,49 +1373,125 @@ void ColladaLoader::CreateAnimation( aiScene* pScene, const ColladaParser& pPars
 //      ai_assert( resultTrafos.size() > 0);
 
         // build an animation channel for the given node out of these trafo keys
-    if( !resultTrafos.empty() )
-    {
-          aiNodeAnim* dstAnim = new aiNodeAnim;
-          dstAnim->mNodeName = nodeName;
-          dstAnim->mNumPositionKeys = static_cast<unsigned int>(resultTrafos.size());
-          dstAnim->mNumRotationKeys= static_cast<unsigned int>(resultTrafos.size());
-          dstAnim->mNumScalingKeys = static_cast<unsigned int>(resultTrafos.size());
-          dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()];
-          dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()];
-          dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()];
-
-          for( size_t a = 0; a < resultTrafos.size(); ++a)
-          {
-              aiMatrix4x4 mat = resultTrafos[a];
-              double time = double( mat.d4); // remember? time is stored in mat.d4
-        mat.d4 = 1.0f;
-
-              dstAnim->mPositionKeys[a].mTime = time;
-              dstAnim->mRotationKeys[a].mTime = time;
-              dstAnim->mScalingKeys[a].mTime = time;
-              mat.Decompose( dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue);
-          }
+        if( !resultTrafos.empty() )
+        {
+              aiNodeAnim* dstAnim = new aiNodeAnim;
+              dstAnim->mNodeName = nodeName;
+              dstAnim->mNumPositionKeys = static_cast<unsigned int>(resultTrafos.size());
+              dstAnim->mNumRotationKeys = static_cast<unsigned int>(resultTrafos.size());
+              dstAnim->mNumScalingKeys = static_cast<unsigned int>(resultTrafos.size());
+              dstAnim->mPositionKeys = new aiVectorKey[resultTrafos.size()];
+              dstAnim->mRotationKeys = new aiQuatKey[resultTrafos.size()];
+              dstAnim->mScalingKeys = new aiVectorKey[resultTrafos.size()];
+
+              for( size_t a = 0; a < resultTrafos.size(); ++a)
+              {
+                  aiMatrix4x4 mat = resultTrafos[a];
+                  double time = double( mat.d4); // remember? time is stored in mat.d4
+                    mat.d4 = 1.0f;
+
+                  dstAnim->mPositionKeys[a].mTime = time;
+                  dstAnim->mRotationKeys[a].mTime = time;
+                  dstAnim->mScalingKeys[a].mTime = time;
+                  mat.Decompose( dstAnim->mScalingKeys[a].mValue, dstAnim->mRotationKeys[a].mValue, dstAnim->mPositionKeys[a].mValue);
+              }
 
-          anims.push_back( dstAnim);
-    } else
-    {
-      DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
-    }
+              anims.push_back( dstAnim);
+        } else
+        {
+          DefaultLogger::get()->warn( "Collada loader: found empty animation channel, ignored. Please check your exporter.");
+        }
+
+        if( !entries.empty() && entries.front().mTimeAccessor->mCount > 0 )
+        {
+            std::vector<Collada::ChannelEntry> morphChannels;
+            for( std::vector<Collada::ChannelEntry>::iterator it = entries.begin(); it != entries.end(); ++it)
+            {
+                Collada::ChannelEntry& e = *it;
+
+                // skip non-transform types
+                if (e.mTargetId.empty())
+                    continue;
+
+                if (e.mTargetId.find("morph-weights") != std::string::npos)
+                    morphChannels.push_back(e);
+            }
+            if (morphChannels.size() > 0)
+            {
+                // either 1) morph weight animation count should contain morph target count channels
+                // or     2) one channel with morph target count arrays
+                // assume first
+
+                aiMeshMorphAnim *morphAnim = new aiMeshMorphAnim;
+                morphAnim->mName.Set(nodeName);
+
+                std::vector<MorphTimeValues> morphTimeValues;
+
+                int morphAnimChannelIndex = 0;
+                for( std::vector<Collada::ChannelEntry>::iterator it = morphChannels.begin(); it != morphChannels.end(); ++it)
+                {
+                    Collada::ChannelEntry& e = *it;
+                    std::string::size_type apos = e.mTargetId.find('(');
+                    std::string::size_type bpos = e.mTargetId.find(')');
+                    if (apos == std::string::npos || bpos == std::string::npos)
+                        // unknown way to specify weight -> ignore this animation
+                        continue;
+
+                    // weight target can be in format Weight_M_N, Weight_N, WeightN, or some other way
+                    // we ignore the name and just assume the channels are in the right order
+                    for (unsigned int i = 0; i < e.mTimeData->mValues.size(); i++)
+                        insertMorphTimeValue(morphTimeValues, e.mTimeData->mValues.at(i), e.mValueData->mValues.at(i), morphAnimChannelIndex);
+
+                    ++morphAnimChannelIndex;
+                }
+
+                morphAnim->mNumKeys = static_cast<unsigned int>(morphTimeValues.size());
+                morphAnim->mKeys = new aiMeshMorphKey[morphAnim->mNumKeys];
+                for (unsigned int key = 0; key < morphAnim->mNumKeys; key++)
+                {
+                    morphAnim->mKeys[key].mNumValuesAndWeights = static_cast<unsigned int>(morphChannels.size());
+                    morphAnim->mKeys[key].mValues = new unsigned int [morphChannels.size()];
+                    morphAnim->mKeys[key].mWeights = new double [morphChannels.size()];
+
+                    morphAnim->mKeys[key].mTime = morphTimeValues[key].mTime;
+                    for (unsigned int valueIndex = 0; valueIndex < morphChannels.size(); valueIndex++)
+                    {
+                        morphAnim->mKeys[key].mValues[valueIndex] = valueIndex;
+                        morphAnim->mKeys[key].mWeights[valueIndex] = getWeightAtKey(morphTimeValues, key, valueIndex);
+                    }
+                }
+
+                morphAnims.push_back(morphAnim);
+            }
+        }
     }
 
-    if( !anims.empty())
+    if( !anims.empty() || !morphAnims.empty())
     {
         aiAnimation* anim = new aiAnimation;
         anim->mName.Set( pName);
         anim->mNumChannels = static_cast<unsigned int>(anims.size());
-        anim->mChannels = new aiNodeAnim*[anims.size()];
-        std::copy( anims.begin(), anims.end(), anim->mChannels);
+        if (anim->mNumChannels > 0)
+        {
+            anim->mChannels = new aiNodeAnim*[anims.size()];
+            std::copy( anims.begin(), anims.end(), anim->mChannels);
+        }
+        anim->mNumMorphMeshChannels = static_cast<unsigned int>(morphAnims.size());
+        if (anim->mNumMorphMeshChannels > 0)
+        {
+            anim->mMorphMeshChannels = new aiMeshMorphAnim*[anim->mNumMorphMeshChannels];
+            std::copy( morphAnims.begin(), morphAnims.end(), anim->mMorphMeshChannels);
+        }
         anim->mDuration = 0.0f;
         for( size_t a = 0; a < anims.size(); ++a)
         {
-            anim->mDuration = std::max( anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys-1].mTime);
-            anim->mDuration = std::max( anim->mDuration, anims[a]->mRotationKeys[anims[a]->mNumRotationKeys-1].mTime);
-            anim->mDuration = std::max( anim->mDuration, anims[a]->mScalingKeys[anims[a]->mNumScalingKeys-1].mTime);
+                anim->mDuration = std::max( anim->mDuration, anims[a]->mPositionKeys[anims[a]->mNumPositionKeys-1].mTime);
+                anim->mDuration = std::max( anim->mDuration, anims[a]->mRotationKeys[anims[a]->mNumRotationKeys-1].mTime);
+                anim->mDuration = std::max( anim->mDuration, anims[a]->mScalingKeys[anims[a]->mNumScalingKeys-1].mTime);
+        }
+        for (size_t a = 0; a < morphAnims.size(); ++a)
+        {
+            anim->mDuration = std::max(anim->mDuration, morphAnims[a]->mKeys[morphAnims[a]->mNumKeys-1].mTime);
         }
         anim->mTicksPerSecond = 1;
         mAnims.push_back( anim);
@@ -1383,7 +1619,7 @@ void ColladaLoader::FillMaterials( const ColladaParser& pParser, aiScene* /*pSce
         mat.AddProperty( &effect.mRefractIndex, 1, AI_MATKEY_REFRACTI);
 
         // transparency, a very hard one. seemingly not all files are following the
-        // specification here (1.0 transparency => completly opaque)...
+        // specification here (1.0 transparency => completely opaque)...
         // therefore, we let the opportunity for the user to manually invert
         // the transparency if necessary and we add preliminary support for RGB_ZERO mode
         if(effect.mTransparency >= 0.f && effect.mTransparency <= 1.f) {
@@ -1489,6 +1725,8 @@ void ColladaLoader::BuildMaterials( ColladaParser& pParser, aiScene* /*pScene*/)
 aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pParser,
     const Collada::Effect& pEffect, const std::string& pName)
 {
+    aiString result;
+
     // recurse through the param references until we end up at an image
     std::string name = pName;
     while( 1)
@@ -1507,11 +1745,17 @@ aiString ColladaLoader::FindFilenameForEffectTexture( const ColladaParser& pPars
     ColladaParser::ImageLibrary::const_iterator imIt = pParser.mImageLibrary.find( name);
     if( imIt == pParser.mImageLibrary.end())
     {
-        throw DeadlyImportError( format() <<
-            "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
-    }
+        //missing texture should not stop the conversion
+        //throw DeadlyImportError( format() <<
+        //    "Collada: Unable to resolve effect texture entry \"" << pName << "\", ended up at ID \"" << name << "\"." );
 
-    aiString result;
+        DefaultLogger::get()->warn("Collada: Unable to resolve effect texture entry \"" + pName + "\", ended up at ID \"" + name + "\".");
+
+        //set default texture file name
+        result.Set(name + ".jpg");
+        ConvertPath(result);
+        return result;
+    }
 
     // if this is an embedded texture image setup an aiTexture for it
     if (imIt->second.mFileName.empty())
@@ -1659,14 +1903,13 @@ const Collada::Node* ColladaLoader::FindNodeBySID( const Collada::Node* pNode, c
 }
 
 // ------------------------------------------------------------------------------------------------
-// Finds a proper name for a node derived from the collada-node's properties
+// Finds a proper unique name for a node derived from the collada-node's properties.
+// The name must be unique for proper node-bone association.
 std::string ColladaLoader::FindNameForNode( const Collada::Node* pNode)
 {
-    // now setup the name of the node. We take the name if not empty, otherwise the collada ID
-    // FIX: Workaround for XSI calling the instanced visual scene 'untitled' by default.
-    if (!pNode->mName.empty() && pNode->mName != "untitled")
-        return pNode->mName;
-    else if (!pNode->mID.empty())
+    // Now setup the name of the assimp node. The collada name might not be
+    // unique, so we use the collada ID.
+    if (!pNode->mID.empty())
         return pNode->mID;
     else if (!pNode->mSID.empty())
     return pNode->mSID;

+ 7 - 1
code/ColladaLoader.h

@@ -4,7 +4,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -117,6 +118,8 @@ protected:
     /** Builds meshes for the given node and references them */
     void BuildMeshesForNode( const ColladaParser& pParser, const Collada::Node* pNode,
         aiNode* pTarget);
+		
+    aiMesh *findMesh(std::string meshid);
 
     /** Creates a mesh for the given ColladaMesh face subset and returns the newly created mesh */
     aiMesh* CreateMesh( const ColladaParser& pParser, const Collada::Mesh* pSrcMesh, const Collada::SubMesh& pSubMesh,
@@ -223,6 +226,9 @@ protected:
 
     /** Accumulated meshes for the target scene */
     std::vector<aiMesh*> mMeshes;
+	
+    /** Accumulated morph target meshes */
+    std::vector<aiMesh*> mTargetMeshes;
 
     /** Temporary material list */
     std::vector<std::pair<Collada::Effect*, aiMaterial*> > newMats;

+ 82 - 28
code/ColladaParser.cpp

@@ -3,7 +3,8 @@
 Open Asset Import Library (assimp)
 ---------------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 
 All rights reserved.
 
@@ -43,7 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *  @brief Implementation of the Collada parser helper
  */
 
-
 #ifndef ASSIMP_BUILD_NO_COLLADA_IMPORTER
 
 #include <sstream>
@@ -224,7 +224,7 @@ void ColladaParser::ReadStructure()
 }
 
 // ------------------------------------------------------------------------------------------------
-// Reads asset informations such as coordinate system informations and legal blah
+// Reads asset information such as coordinate system information and legal blah
 void ColladaParser::ReadAssetInfo()
 {
     if( mReader->isEmptyElement())
@@ -585,6 +585,12 @@ void ColladaParser::ReadAnimationSampler( Collada::AnimationChannel& pChannel)
                     pChannel.mSourceTimes = source;
                 else if( strcmp( semantic, "OUTPUT") == 0)
                     pChannel.mSourceValues = source;
+                else if( strcmp( semantic, "IN_TANGENT") == 0)
+                    pChannel.mInTanValues = source;
+                else if( strcmp( semantic, "OUT_TANGENT") == 0)
+                    pChannel.mOutTanValues = source;
+                else if( strcmp( semantic, "INTERPOLATION") == 0)
+                    pChannel.mInterpolationValues = source;
 
                 if( !mReader->isEmptyElement())
                     SkipElement();
@@ -647,6 +653,9 @@ void ColladaParser::ReadControllerLibrary()
 // Reads a controller into the given mesh structure
 void ColladaParser::ReadController( Collada::Controller& pController)
 {
+    // initial values
+    pController.mType = Skin;
+    pController.mMethod = Normalized;
     while( mReader->read())
     {
         if( mReader->getNodeType() == irr::io::EXN_ELEMENT)
@@ -654,8 +663,15 @@ void ColladaParser::ReadController( Collada::Controller& pController)
             // two types of controllers: "skin" and "morph". Only the first one is relevant, we skip the other
             if( IsElement( "morph"))
             {
-                // should skip everything inside, so there's no danger of catching elements in between
-                SkipElement();
+                pController.mType = Morph;
+                int baseIndex = GetAttribute("source");
+                pController.mMeshId = mReader->getAttributeValue(baseIndex) + 1;
+                int methodIndex = GetAttribute("method");
+                if (methodIndex > 0) {
+                    const char *method = mReader->getAttributeValue(methodIndex);
+                    if (strcmp(method, "RELATIVE") == 0)
+                        pController.mMethod = Relative;
+                }
             }
             else if( IsElement( "skin"))
             {
@@ -667,18 +683,18 @@ void ColladaParser::ReadController( Collada::Controller& pController)
             else if( IsElement( "bind_shape_matrix"))
             {
                 // content is 16 floats to define a matrix... it seems to be important for some models
-          const char* content = GetTextContent();
+                const char* content = GetTextContent();
 
-          // read the 16 floats
-          for( unsigned int a = 0; a < 16; a++)
-          {
-              // read a number
-          content = fast_atoreal_move<ai_real>( content, pController.mBindShapeMatrix[a]);
-              // skip whitespace after it
-              SkipSpacesAndLineEnd( &content);
-          }
+                // read the 16 floats
+                for( unsigned int a = 0; a < 16; a++)
+                {
+                    // read a number
+                    content = fast_atoreal_move<ai_real>( content, pController.mBindShapeMatrix[a]);
+                    // skip whitespace after it
+                    SkipSpacesAndLineEnd( &content);
+                }
 
-        TestClosing( "bind_shape_matrix");
+                TestClosing( "bind_shape_matrix");
             }
             else if( IsElement( "source"))
             {
@@ -693,6 +709,32 @@ void ColladaParser::ReadController( Collada::Controller& pController)
             {
                 ReadControllerWeights( pController);
             }
+            else if ( IsElement( "targets" ))
+            {
+                while (mReader->read()) {
+                    if( mReader->getNodeType() == irr::io::EXN_ELEMENT) {
+                        if ( IsElement( "input")) {
+                            int semanticsIndex = GetAttribute("semantic");
+                            int sourceIndex = GetAttribute("source");
+
+                            const char *semantics = mReader->getAttributeValue(semanticsIndex);
+                            const char *source = mReader->getAttributeValue(sourceIndex);
+                            if (strcmp(semantics, "MORPH_TARGET") == 0) {
+                                pController.mMorphTarget = source + 1;
+                            }
+                            else if (strcmp(semantics, "MORPH_WEIGHT") == 0)
+                            {
+                                pController.mMorphWeight = source + 1;
+                            }
+                        }
+                    } else if( mReader->getNodeType() == irr::io::EXN_ELEMENT_END) {
+                        if( strcmp( mReader->getNodeName(), "targets") == 0)
+                            break;
+                        else
+                            ThrowException( "Expected end of <targets> element.");
+                    }
+                }
+            }
             else
             {
                 // ignore the rest
@@ -703,7 +745,7 @@ void ColladaParser::ReadController( Collada::Controller& pController)
         {
             if( strcmp( mReader->getNodeName(), "controller") == 0)
                 break;
-            else if( strcmp( mReader->getNodeName(), "skin") != 0)
+            else if( strcmp( mReader->getNodeName(), "skin") != 0 && strcmp( mReader->getNodeName(), "morph") != 0)
                 ThrowException( "Expected end of <controller> element.");
         }
     }
@@ -1592,7 +1634,7 @@ void ColladaParser::ReadEffectColor( aiColor4D& pColor, Sampler& pSampler)
             }
             else if( IsElement( "texture"))
             {
-                // get name of source textur/sampler
+                // get name of source texture/sampler
                 int attrTex = GetAttribute( "texture");
                 pSampler.mName = mReader->getAttributeValue( attrTex);
 
@@ -1823,7 +1865,7 @@ void ColladaParser::ReadMesh( Mesh* pMesh)
                 ReadIndexData( pMesh);
             } else
             {
-                // ignore the rest
+                // ignore the restf
                 SkipElement();
             }
         }
@@ -2173,8 +2215,9 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
             else if (IsElement("extra"))
             {
                 SkipElement("extra");
-            } else
-            {
+            } else if ( IsElement("ph")) {                
+                SkipElement("ph");
+            } else {
                 ThrowException( format() << "Unexpected sub element <" << mReader->getNodeName() << "> in tag <" << elementName << ">" );
             }
         }
@@ -2188,7 +2231,7 @@ void ColladaParser::ReadIndexData( Mesh* pMesh)
     }
 
 #ifdef ASSIMP_BUILD_DEBUG
-	if (primType != Prim_TriFans && primType != Prim_TriStrips &&
+	if (primType != Prim_TriFans && primType != Prim_TriStrips && primType != Prim_LineStrip &&
         primType != Prim_Lines) { // this is ONLY to workaround a bug in SketchUp 15.3.331 where it writes the wrong 'count' when it writes out the 'lines'.
         ai_assert(actualPrimitives == numPrimitives);
     }
@@ -2311,9 +2354,9 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
 		ThrowException( "Expected different index count in <p> element.");
 
 	// find the data for all sources
-  for( std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
+    for( std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)
     {
-    InputChannel& input = *it;
+        InputChannel& input = *it;
         if( input.mResolved)
             continue;
 
@@ -2325,9 +2368,9 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
             acc->mData = &ResolveLibraryReference( mDataLibrary, acc->mSource);
     }
     // and the same for the per-index channels
-  for( std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
-  {
-    InputChannel& input = *it;
+    for( std::vector<InputChannel>::iterator it = pPerIndexChannels.begin(); it != pPerIndexChannels.end(); ++it)
+    {
+        InputChannel& input = *it;
         if( input.mResolved)
             continue;
 
@@ -2357,6 +2400,10 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
         size_t numberOfVertices = indices.size() / numOffsets;
         numPrimitives = numberOfVertices - 2;
     }
+    if (pPrimType == Prim_LineStrip) {
+        size_t numberOfVertices = indices.size() / numOffsets;
+        numPrimitives = numberOfVertices - 1;
+    }
 
     pMesh->mFaceSize.reserve( numPrimitives);
     pMesh->mFacePosIndices.reserve( indices.size() / numOffsets);
@@ -2373,6 +2420,11 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
                 for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
                     CopyVertex(currentVertex, numOffsets, numPoints, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
                 break;
+            case Prim_LineStrip:
+                numPoints = 2;
+                for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
+                    CopyVertex(currentVertex, numOffsets, 1, perVertexOffset, pMesh, pPerIndexChannels, currentPrimitive, indices);
+                break;
             case Prim_Triangles:
                 numPoints = 3;
                 for (size_t currentVertex = 0; currentVertex < numPoints; currentVertex++)
@@ -2409,13 +2461,15 @@ size_t ColladaParser::ReadPrimitives( Mesh* pMesh, std::vector<InputChannel>& pP
     return numPrimitives;
 }
 
+///@note This function willn't work correctly if both PerIndex and PerVertex channels have same channels.
+///For example if TEXCOORD present in both <vertices> and <polylist> tags this function will create wrong uv coordinates.
+///It's not clear from COLLADA documentation is this allowed or not. For now only exporter fixed to avoid such behavior
 void ColladaParser::CopyVertex(size_t currentVertex, size_t numOffsets, size_t numPoints, size_t perVertexOffset, Mesh* pMesh, std::vector<InputChannel>& pPerIndexChannels, size_t currentPrimitive, const std::vector<size_t>& indices){
     // calculate the base offset of the vertex whose attributes we ant to copy
     size_t baseOffset = currentPrimitive * numOffsets * numPoints + currentVertex * numOffsets;
 
     // don't overrun the boundaries of the index list
-    size_t maxIndexRequested = baseOffset + numOffsets - 1;
-    ai_assert(maxIndexRequested < indices.size());
+    ai_assert((baseOffset + numOffsets - 1) < indices.size());
 
     // extract per-vertex channels using the global per-vertex offset
     for (std::vector<InputChannel>::iterator it = pMesh->mPerVertexData.begin(); it != pMesh->mPerVertexData.end(); ++it)

+ 3 - 3
code/ColladaParser.h

@@ -2,7 +2,8 @@
  Open Asset Import Library (assimp)
  ----------------------------------------------------------------------
 
- Copyright (c) 2006-2016, assimp team
+ Copyright (c) 2006-2017, assimp team
+
  All rights reserved.
 
  Redistribution and use of this software in source and binary forms,
@@ -49,7 +50,6 @@
 #include "ColladaHelper.h"
 #include <assimp/ai_assert.h>
 #include "TinyFormatter.h"
-#include <memory>
 
 namespace Assimp
 {
@@ -77,7 +77,7 @@ namespace Assimp
         /** Reads the structure of the file */
         void ReadStructure();
 
-        /** Reads asset informations such as coordinate system informations and legal blah */
+        /** Reads asset information such as coordinate system information and legal blah */
         void ReadAssetInfo();
 
         /** Reads the animation library */

+ 2 - 1
code/ComputeUVMappingProcess.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 2 - 1
code/ComputeUVMappingProcess.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 2 - 1
code/ConvertToLHProcess.cpp

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

+ 2 - 1
code/ConvertToLHProcess.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,

+ 92 - 0
code/CreateAnimMesh.cpp

@@ -0,0 +1,92 @@
+/*
+---------------------------------------------------------------------------
+Open Asset Import Library (assimp)
+---------------------------------------------------------------------------
+
+Copyright (C) 2016 The Qt Company Ltd.
+Copyright (c) 2006-2012, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the following
+conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+---------------------------------------------------------------------------
+*/
+
+#include "CreateAnimMesh.h"
+
+namespace Assimp    {
+
+aiAnimMesh *aiCreateAnimMesh(const aiMesh *mesh)
+{
+    aiAnimMesh *animesh = new aiAnimMesh;
+    animesh->mVertices = NULL;
+    animesh->mNormals = NULL;
+    animesh->mTangents = NULL;
+    animesh->mBitangents = NULL;
+    animesh->mNumVertices = mesh->mNumVertices;
+    if (mesh->mVertices) {
+        animesh->mVertices = new aiVector3D[animesh->mNumVertices];
+        std::memcpy(animesh->mVertices, mesh->mVertices, mesh->mNumVertices * sizeof(aiVector3D));
+    }
+    if (mesh->mNormals) {
+        animesh->mNormals = new aiVector3D[animesh->mNumVertices];
+        std::memcpy(animesh->mNormals, mesh->mNormals, mesh->mNumVertices * sizeof(aiVector3D));
+    }
+    if (mesh->mTangents) {
+        animesh->mTangents = new aiVector3D[animesh->mNumVertices];
+        std::memcpy(animesh->mTangents, mesh->mTangents, mesh->mNumVertices * sizeof(aiVector3D));
+    }
+    if (mesh->mBitangents) {
+        animesh->mBitangents = new aiVector3D[animesh->mNumVertices];
+        std::memcpy(animesh->mBitangents, mesh->mBitangents, mesh->mNumVertices * sizeof(aiVector3D));
+    }
+
+    for (int i = 0; i < AI_MAX_NUMBER_OF_COLOR_SETS; ++i) {
+        if (mesh->mColors[i]) {
+            animesh->mColors[i] = new aiColor4D[animesh->mNumVertices];
+            std::memcpy(animesh->mColors[i], mesh->mColors[i], mesh->mNumVertices * sizeof(aiColor4D));
+        } else {
+            animesh->mColors[i] = NULL;
+        }
+    }
+
+    for (int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+        if (mesh->mTextureCoords[i]) {
+            animesh->mTextureCoords[i] = new aiVector3D[animesh->mNumVertices];
+            std::memcpy(animesh->mTextureCoords[i], mesh->mTextureCoords[i], mesh->mNumVertices * sizeof(aiVector3D));
+        } else {
+            animesh->mTextureCoords[i] = NULL;
+        }
+    }
+    return animesh;
+}
+
+} // end of namespace Assimp

+ 57 - 0
code/CreateAnimMesh.h

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

+ 328 - 0
code/D3MFExporter.cpp

@@ -0,0 +1,328 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
+
+#include "D3MFExporter.h"
+
+#include <assimp/scene.h>
+#include <assimp/IOSystem.hpp>
+#include <assimp/IOStream.hpp>
+#include <assimp/Exporter.hpp>
+#include <assimp/DefaultLogger.hpp>
+
+#include "Exceptional.h"
+#include "3MFXmlTags.h"
+#include "D3MFOpcPackage.h"
+
+#include <contrib/zip/src/zip.h>
+
+namespace Assimp {
+
+void ExportScene3MF( const char* pFile, IOSystem* pIOSystem, const aiScene* pScene, const ExportProperties* /*pProperties*/ ) {
+    if ( nullptr == pIOSystem ) {
+        throw DeadlyExportError( "Could not export 3MP archive: " + std::string( pFile ) );
+    }
+    D3MF::D3MFExporter myExporter( pFile, pScene );
+    if ( myExporter.validate() ) {
+        if ( pIOSystem->Exists( pFile ) ) {
+            if ( !pIOSystem->DeleteFile( pFile ) ) {
+                throw DeadlyExportError( "File exists, cannot override : " + std::string( pFile ) );
+            }
+        }
+        bool ok = myExporter.exportArchive(pFile);
+        if ( !ok ) {
+            throw DeadlyExportError( "Could not export 3MP archive: " + std::string( pFile ) );
+        }
+    }
+}
+
+namespace D3MF {
+
+D3MFExporter::D3MFExporter( const char* pFile, const aiScene* pScene )
+: mArchiveName( pFile )
+, m_zipArchive( nullptr )
+, mScene( pScene )
+, mModelOutput()
+, mRelOutput()
+, mContentOutput()
+, mBuildItems()
+, mRelations() {
+    // empty
+}
+
+D3MFExporter::~D3MFExporter() {
+    for ( size_t i = 0; i < mRelations.size(); ++i ) {
+        delete mRelations[ i ];
+    }
+    mRelations.clear();
+}
+
+bool D3MFExporter::validate() {
+    if ( mArchiveName.empty() ) {
+        return false;
+    }
+
+    if ( nullptr == mScene ) {
+        return false;
+    }
+
+    return true;
+}
+
+bool D3MFExporter::exportArchive( const char *file ) {
+    bool ok( true );
+
+    m_zipArchive = zip_open( file, ZIP_DEFAULT_COMPRESSION_LEVEL, 'w' );
+    if ( nullptr == m_zipArchive ) {
+        return false;
+    }
+    ok |= exportContentTypes();
+    ok |= export3DModel();
+    ok |= exportRelations();
+
+    zip_close( m_zipArchive );
+    m_zipArchive = nullptr;
+
+    return ok;
+}
+
+
+bool D3MFExporter::exportContentTypes() {
+    mContentOutput.clear();
+
+    mContentOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+    mContentOutput << std::endl;
+    mContentOutput << "<Types xmlns = \"http://schemas.openxmlformats.org/package/2006/content-types\">";
+    mContentOutput << std::endl;
+    mContentOutput << "<Default Extension = \"rels\" ContentType = \"application/vnd.openxmlformats-package.relationships+xml\" />";
+    mContentOutput << std::endl;
+    mContentOutput << "<Default Extension = \"model\" ContentType = \"application/vnd.ms-package.3dmanufacturing-3dmodel+xml\" />";
+    mContentOutput << std::endl;
+    mContentOutput << "</Types>";
+    mContentOutput << std::endl;
+    exportContentTyp( XmlTag::CONTENT_TYPES_ARCHIVE );
+
+    return true;
+}
+
+bool D3MFExporter::exportRelations() {
+    mRelOutput.clear();
+
+    mRelOutput << "<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
+    mRelOutput << std::endl;
+    mRelOutput << "<Relationships xmlns=\"http://schemas.openxmlformats.org/package/2006/relationships\">";
+
+    for ( size_t i = 0; i < mRelations.size(); ++i ) {
+        mRelOutput << "<Relationship Target=\"/" << mRelations[ i ]->target << "\" ";
+        mRelOutput << "Id=\"" << mRelations[i]->id << "\" ";
+        mRelOutput << "Type=\"" << mRelations[ i ]->type << "\" />";
+        mRelOutput << std::endl;
+    }
+    mRelOutput << "</Relationships>";
+    mRelOutput << std::endl;
+
+    writeRelInfoToFile( "_rels", ".rels" );
+    mRelOutput.flush();
+
+    return true;
+}
+
+bool D3MFExporter::export3DModel() {
+    mModelOutput.clear();
+
+    writeHeader();
+    mModelOutput << "<" << XmlTag::model << " " << XmlTag::model_unit << "=\"millimeter\""
+            << "xmlns=\"http://schemas.microsoft.com/3dmanufacturing/core/2015/02\">"
+            << std::endl;
+    mModelOutput << "<" << XmlTag::resources << ">";
+    mModelOutput << std::endl;
+
+    writeObjects();
+
+
+    mModelOutput << "</" << XmlTag::resources << ">";
+    mModelOutput << std::endl;
+    writeBuild();
+
+    mModelOutput << "</" << XmlTag::model << ">\n";
+
+    OpcPackageRelationship *info = new OpcPackageRelationship;
+    info->id = "rel0";
+    info->target = "/3D/3DModel.model";
+    info->type = XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
+    mRelations.push_back( info );
+
+    writeModelToArchive( "3D", "3DModel.model" );
+    mModelOutput.flush();
+
+    return true;
+}
+
+void D3MFExporter::writeHeader() {
+    mModelOutput << "<?xml version=\"1.0\" encoding=\"UTF - 8\"?>";
+    mModelOutput << std::endl;
+}
+
+void D3MFExporter::writeObjects() {
+    if ( nullptr == mScene->mRootNode ) {
+        return;
+    }
+
+    aiNode *root = mScene->mRootNode;
+    for ( unsigned int i = 0; i < root->mNumChildren; ++i ) {
+        aiNode *currentNode( root->mChildren[ i ] );
+        if ( nullptr == currentNode ) {
+            continue;
+        }
+        mModelOutput << "<" << XmlTag::object << " id=\"" << currentNode->mName.C_Str() << "\" type=\"model\">";
+        mModelOutput << std::endl;
+        for ( unsigned int j = 0; j < currentNode->mNumMeshes; ++j ) {
+            aiMesh *currentMesh = mScene->mMeshes[ currentNode->mMeshes[ j ] ];
+            if ( nullptr == currentMesh ) {
+                continue;
+            }
+            writeMesh( currentMesh );
+        }
+        mBuildItems.push_back( i );
+
+        mModelOutput << "</" << XmlTag::object << ">";
+        mModelOutput << std::endl;
+    }
+}
+
+void D3MFExporter::writeMesh( aiMesh *mesh ) {
+    if ( nullptr == mesh ) {
+        return;
+    }
+
+    mModelOutput << "<" << XmlTag::mesh << ">" << std::endl;
+    mModelOutput << "<" << XmlTag::vertices << ">" << std::endl;
+    for ( unsigned int i = 0; i < mesh->mNumVertices; ++i ) {
+        writeVertex( mesh->mVertices[ i ] );
+    }
+    mModelOutput << "</" << XmlTag::vertices << ">" << std::endl;
+
+    writeFaces( mesh );
+
+    mModelOutput << "</" << XmlTag::mesh << ">" << std::endl;
+}
+
+void D3MFExporter::writeVertex( const aiVector3D &pos ) {
+    mModelOutput << "<" << XmlTag::vertex << " x=\"" << pos.x << "\" y=\"" << pos.y << "\" z=\"" << pos.z << "\" />";
+    mModelOutput << std::endl;
+}
+
+void D3MFExporter::writeFaces( aiMesh *mesh ) {
+    if ( nullptr == mesh ) {
+        return;
+    }
+
+    if ( !mesh->HasFaces() ) {
+        return;
+    }
+    mModelOutput << "<" << XmlTag::triangles << ">" << std::endl;
+    for ( unsigned int i = 0; i < mesh->mNumFaces; ++i ) {
+        aiFace &currentFace = mesh->mFaces[ i ];
+        mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[ 0 ] << "\" v2=\""
+                << currentFace.mIndices[ 1 ] << "\" v3=\"" << currentFace.mIndices[ 2 ] << "\"/>";
+        mModelOutput << std::endl;
+    }
+    mModelOutput << "</" << XmlTag::triangles << ">";
+    mModelOutput << std::endl;
+}
+
+void D3MFExporter::writeBuild() {
+    mModelOutput << "<" << XmlTag::build << ">" << std::endl;
+
+    for ( size_t i = 0; i < mBuildItems.size(); ++i ) {
+        mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 1 << "\"/>";
+        mModelOutput << std::endl;
+    }
+    mModelOutput << "</" << XmlTag::build << ">";
+    mModelOutput << std::endl;
+}
+
+void D3MFExporter::exportContentTyp( const std::string &filename ) {
+    if ( nullptr == m_zipArchive ) {
+        throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." );
+    }
+    const std::string entry = filename;
+    zip_entry_open( m_zipArchive, entry.c_str() );
+
+    const std::string &exportTxt( mContentOutput.str() );
+    zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() );
+
+    zip_entry_close( m_zipArchive );
+}
+
+void D3MFExporter::writeModelToArchive( const std::string &folder, const std::string &modelName ) {
+    if ( nullptr == m_zipArchive ) {
+        throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." );
+    }
+    const std::string entry = folder + "/" + modelName;
+    zip_entry_open( m_zipArchive, entry.c_str() );
+
+    const std::string &exportTxt( mModelOutput.str() );
+    zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() );
+
+    zip_entry_close( m_zipArchive );
+}
+
+void D3MFExporter::writeRelInfoToFile( const std::string &folder, const std::string &relName ) {
+    if ( nullptr == m_zipArchive ) {
+        throw DeadlyExportError( "3MF-Export: Zip archive not valid, nullptr." );
+    }
+    const std::string entry = folder + "/" + relName;
+    zip_entry_open( m_zipArchive, entry.c_str() );
+
+    const std::string &exportTxt( mRelOutput.str() );
+    zip_entry_write( m_zipArchive, exportTxt.c_str(), exportTxt.size() );
+
+    zip_entry_close( m_zipArchive );
+}
+
+
+} // Namespace D3MF
+} // Namespace Assimp
+
+#endif // ASSIMP_BUILD_NO_3MF_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT

+ 103 - 0
code/D3MFExporter.h

@@ -0,0 +1,103 @@
+/*
+Open Asset Import Library (assimp)
+----------------------------------------------------------------------
+
+Copyright (c) 2006-2017, assimp team
+
+All rights reserved.
+
+Redistribution and use of this software in source and binary forms,
+with or without modification, are permitted provided that the
+following conditions are met:
+
+* Redistributions of source code must retain the above
+copyright notice, this list of conditions and the
+following disclaimer.
+
+* Redistributions in binary form must reproduce the above
+copyright notice, this list of conditions and the
+following disclaimer in the documentation and/or other
+materials provided with the distribution.
+
+* Neither the name of the assimp team, nor the names of its
+contributors may be used to endorse or promote products
+derived from this software without specific prior
+written permission of the assimp team.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------
+*/
+#pragma once
+
+#include <memory>
+#include <sstream>
+#include <vector>
+#include <assimp/vector3.h>
+
+struct aiScene;
+struct aiNode;
+struct aiMaterial;
+struct aiMesh;
+
+struct zip_t;
+
+namespace Assimp {
+
+class IOStream;
+
+namespace D3MF {
+
+#ifndef ASSIMP_BUILD_NO_EXPORT
+#ifndef ASSIMP_BUILD_NO_3MF_EXPORTER
+
+struct OpcPackageRelationship;
+
+class D3MFExporter {
+public:
+    D3MFExporter( const char* pFile, const aiScene* pScene );
+    ~D3MFExporter();
+    bool validate();
+    bool exportArchive( const char *file );
+    bool exportContentTypes();
+    bool exportRelations();
+    bool export3DModel();
+
+protected:
+    void writeHeader();
+    void writeObjects();
+    void writeMesh( aiMesh *mesh );
+    void writeVertex( const aiVector3D &pos );
+    void writeFaces( aiMesh *mesh );
+    void writeBuild();
+    void exportContentTyp( const std::string &filename );
+    void writeModelToArchive( const std::string &folder, const std::string &modelName );
+    void writeRelInfoToFile( const std::string &folder, const std::string &relName );
+
+private:
+    std::string mArchiveName;
+    zip_t *m_zipArchive;
+    const aiScene *mScene;
+    std::ostringstream mModelOutput;
+    std::ostringstream mRelOutput;
+    std::ostringstream mContentOutput;
+    std::vector<unsigned int> mBuildItems;
+    std::vector<OpcPackageRelationship*> mRelations;
+};
+
+#endif // ASSIMP_BUILD_NO_3MF_EXPORTER
+#endif // ASSIMP_BUILD_NO_EXPORT
+
+} // Namespace D3MF
+} // Namespace Assimp
+

+ 37 - 87
code/D3MFImporter.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -38,96 +39,57 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
+#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
+
 #include "D3MFImporter.h"
 
 #include <assimp/scene.h>
-#include <assimp/IOStream.hpp>
 #include <assimp/IOSystem.hpp>
 #include <assimp/DefaultLogger.hpp>
+#include <assimp/importerdesc.h>
 #include "StringComparison.h"
 #include "StringUtils.h"
 
-
 #include <string>
-#include <sstream>
 #include <vector>
 #include <map>
-#include <algorithm>
 #include <cassert>
-#include <cstdlib>
 #include <memory>
 
-#include <assimp/ai_assert.h>
-
-#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
-
 #include "D3MFOpcPackage.h"
 #include <contrib/unzip/unzip.h>
 #include "irrXMLWrapper.h"
+#include "3MFXmlTags.h"
 
 namespace Assimp {
 namespace D3MF {
 
-
-namespace XmlTag {
-    static const std::string model     = "model";
-    static const std::string metadata  = "metadata";
-    static const std::string resources = "resources";
-    static const std::string object    = "object";
-    static const std::string mesh      = "mesh";
-    static const std::string vertices  = "vertices";
-    static const std::string vertex    = "vertex";
-    static const std::string triangles = "triangles";
-    static const std::string triangle  = "triangle";
-    static const std::string x         = "x";
-    static const std::string y         = "y";
-    static const std::string z         = "z";
-    static const std::string v1        = "v1";
-    static const std::string v2        = "v2";
-    static const std::string v3        = "v3";
-    static const std::string id        = "id";
-    static const std::string name      = "name";
-    static const std::string type      = "type";
-    static const std::string build     = "build";
-    static const std::string item      = "item";
-    static const std::string objectid  = "objectid";
-    static const std::string transform = "transform";
-}
-
-
-class XmlSerializer
-{
+class XmlSerializer {
 public:
     XmlSerializer(XmlReader* xmlReader)
-        : xmlReader(xmlReader)
-    {
-
+    : xmlReader(xmlReader) {
+		// empty
     }
 
-    void ImportXml(aiScene* scene)
-    {
-
-        scene->mFlags |= AI_SCENE_FLAGS_NON_VERBOSE_FORMAT;
+    ~XmlSerializer() {
+        // empty
+    }
 
+    void ImportXml(aiScene* scene) {
         scene->mRootNode = new aiNode();
         std::vector<aiNode*> children;
 
-        while(ReadToEndElement(D3MF::XmlTag::model))
-        {
-
-            if(xmlReader->getNodeName() == D3MF::XmlTag::object)
-            {
+        while(ReadToEndElement(D3MF::XmlTag::model)) {
+            if(xmlReader->getNodeName() == D3MF::XmlTag::object) {
                 children.push_back(ReadObject(scene));
-            }
-            else if(xmlReader->getNodeName() == D3MF::XmlTag::build)
-            {
+            } else if(xmlReader->getNodeName() == D3MF::XmlTag::build) {
 
             }
         }
 
-        if(scene->mRootNode->mName.length == 0)
-            scene->mRootNode->mName.Set("3MF");
-
+        if ( scene->mRootNode->mName.length == 0 ) {
+            scene->mRootNode->mName.Set( "3MF" );
+        }
 
         scene->mNumMeshes = static_cast<unsigned int>(meshes.size());
         scene->mMeshes = new aiMesh*[scene->mNumMeshes]();
@@ -138,13 +100,12 @@ public:
         scene->mRootNode->mChildren = new aiNode*[scene->mRootNode->mNumChildren]();
 
         std::copy(children.begin(), children.end(), scene->mRootNode->mChildren);
-
     }
 
 private:
     aiNode* ReadObject(aiScene* scene)
     {
-        ScopeGuard<aiNode> node(new aiNode());
+        std::unique_ptr<aiNode> node(new aiNode());
 
         std::vector<unsigned long> meshIds;
 
@@ -184,14 +145,12 @@ private:
 
         std::copy(meshIds.begin(), meshIds.end(), node->mMeshes);
 
-        return node.dismiss();
+        return node.release();
 
     }
 
-    aiMesh* ReadMesh()
-    {
+    aiMesh* ReadMesh() {
         aiMesh* mesh = new aiMesh();
-
         while(ReadToEndElement(D3MF::XmlTag::mesh))
         {
             if(xmlReader->getNodeName() == D3MF::XmlTag::vertices)
@@ -202,10 +161,8 @@ private:
             {
                 ImportTriangles(mesh);
             }
-
         }
 
-
         return mesh;
     }
 
@@ -226,12 +183,14 @@ private:
         std::copy(vertices.begin(), vertices.end(), mesh->mVertices);
 
     }
+
     aiVector3D ReadVertex()
     {
         aiVector3D vertex;
+
         vertex.x = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::x.c_str()), nullptr);
         vertex.y = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::y.c_str()), nullptr);
-        vertex.z = ai_strtof>(xmlReader->getAttributeValue(D3MF::XmlTag::z.c_str()), nullptr);
+        vertex.z = ai_strtof(xmlReader->getAttributeValue(D3MF::XmlTag::z.c_str()), nullptr);
 
         return vertex;
     }
@@ -253,9 +212,7 @@ private:
         mesh->mFaces = new aiFace[mesh->mNumFaces];
         mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
 
-
         std::copy(faces.begin(), faces.end(), mesh->mFaces);
-
     }
 
     aiFace ReadTriangle()
@@ -272,7 +229,6 @@ private:
     }
 
 private:
-
     bool ReadToStartElement(const std::string& startTag)
     {
         while(xmlReader->read())
@@ -312,12 +268,11 @@ private:
 private:
     std::vector<aiMesh*> meshes;
     XmlReader* xmlReader;
-
-
 };
 
 } //namespace D3MF
 
+static const std::string Extension = "3mf";
 
 static const aiImporterDesc desc = {
     "3mf Importer",
@@ -329,24 +284,22 @@ static const aiImporterDesc desc = {
     0,
     0,
     0,
-    "3mf"
+    Extension.c_str()
 };
 
 
 D3MFImporter::D3MFImporter()
-{
-
+: BaseImporter() {
+    // empty
 }
 
-D3MFImporter::~D3MFImporter()
-{
-
+D3MFImporter::~D3MFImporter() {
+    // empty
 }
 
-bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const
-{
+bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
     const std::string extension = GetExtension(pFile);
-    if(extension == "3mf") {
+    if(extension == Extension ) {
         return true;
     } else if ( !extension.length() || checkSig ) {
         if (nullptr == pIOHandler ) {
@@ -357,18 +310,15 @@ bool D3MFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
     return false;
 }
 
-void D3MFImporter::SetupProperties(const Importer *pImp)
-{
-
+void D3MFImporter::SetupProperties(const Importer * /*pImp*/) {
+    // empty
 }
 
-const aiImporterDesc *D3MFImporter::GetInfo() const
-{
+const aiImporterDesc *D3MFImporter::GetInfo() const {
     return &desc;
 }
 
-void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler)
-{
+void D3MFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
     D3MF::D3MFOpcPackage opcPackage(pIOHandler, pFile);
 
     std::unique_ptr<CIrrXML_IOStreamReader> xmlStream(new CIrrXML_IOStreamReader(opcPackage.RootStream()));

+ 7 - 11
code/D3MFImporter.h

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -41,28 +42,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #ifndef AI_D3MFLOADER_H_INCLUDED
 #define AI_D3MFLOADER_H_INCLUDED
 
-#include <vector>
-#include <cstdint>
-
 #include "BaseImporter.h"
 
 namespace Assimp {
 
-class D3MFImporter : public BaseImporter
-{
+class D3MFImporter : public BaseImporter {
 public:
+    // BaseImporter interface
     D3MFImporter();
     ~D3MFImporter();
-
-    // BaseImporter interface
-public:
     bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;
     void SetupProperties(const Importer *pImp);
     const aiImporterDesc *GetInfo() const;
 
 protected:
     void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
-
 };
-}
+
+} // Namespace Assimp
+
 #endif // AI_D3MFLOADER_H_INCLUDED

+ 83 - 146
code/D3MFOpcPackage.cpp

@@ -2,7 +2,8 @@
 Open Asset Import Library (assimp)
 ----------------------------------------------------------------------
 
-Copyright (c) 2006-2016, assimp team
+Copyright (c) 2006-2017, assimp team
+
 All rights reserved.
 
 Redistribution and use of this software in source and binary forms,
@@ -38,6 +39,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ----------------------------------------------------------------------
 */
 
+#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
 
 #include "D3MFOpcPackage.h"
 #include "Exceptional.h"
@@ -47,57 +49,29 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #include <assimp/DefaultLogger.hpp>
 #include <assimp/ai_assert.h>
 
+#include <cstdlib>
 #include <memory>
 #include <vector>
 #include <map>
 #include <algorithm>
 #include <cassert>
-#include <cstdlib>
-
-#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
-
 #include <contrib/unzip/unzip.h>
+#include "3MFXmlTags.h"
 
 namespace Assimp {
 
 namespace D3MF {
 
-namespace XmlTag {
-    static const std::string CONTENT_TYPES_ARCHIVE  = "[Content_Types].xml";
-    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_RELATIONSHIPS        = "http://schemas.openxmlformats.org/package/2006/relationships";
-    static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships";
-    static const std::string RELS_RELATIONSHIP_NODE      = "Relationship";
-    static const std::string RELS_ATTRIB_TARGET         = "Target";
-    static const std::string RELS_ATTRIB_TYPE            = "Type";
-    static const std::string RELS_ATTRIB_ID              = "Id";
-    static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
-    static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
-    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_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
-}
-
 class IOSystem2Unzip {
-
-    public:
-
-        static voidpf open(voidpf opaque, const char* filename, int mode);
-
-        static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
-
-        static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
-
-        static long tell(voidpf opaque, voidpf stream);
-
-        static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
-
-        static int close(voidpf opaque, voidpf stream);
-
-        static int testerror(voidpf opaque, voidpf stream);
-
-        static zlib_filefunc_def get(IOSystem* pIOHandler);
+public:
+    static voidpf open(voidpf opaque, const char* filename, int mode);
+    static uLong read(voidpf opaque, voidpf stream, void* buf, uLong size);
+    static uLong write(voidpf opaque, voidpf stream, const void* buf, uLong size);
+    static long tell(voidpf opaque, voidpf stream);
+    static long seek(voidpf opaque, voidpf stream, uLong offset, int origin);
+    static int close(voidpf opaque, voidpf stream);
+    static int testerror(voidpf opaque, voidpf stream);
+    static zlib_filefunc_def get(IOSystem* pIOHandler);
 };
 
 voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
@@ -116,7 +90,6 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char* filename, int mode) {
         }
     }
 
-
     return (voidpf) io_system->Open(filename, mode_fopen);
 }
 
@@ -186,58 +159,51 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem* pIOHandler) {
     return mapping;
 }
 
-
-class ZipFile : public IOStream
-{
+class ZipFile : public IOStream {
     friend class D3MFZipArchive;
 
 public:
     explicit ZipFile(size_t size);
-
-    ~ZipFile();
-
+    virtual ~ZipFile();
     size_t Read(void* pvBuffer, size_t pSize, size_t pCount );
-
     size_t Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/);
-
     size_t FileSize() const;
-
     aiReturn Seek(size_t /*pOffset*/, aiOrigin /*pOrigin*/);
-
     size_t Tell() const;
-
     void Flush();
 
 private:
-
-    void* m_Buffer;
-
+    void *m_Buffer;
     size_t m_Size;
-
 };
 
-ZipFile::ZipFile(size_t size) : m_Size(size) {
+ZipFile::ZipFile(size_t size)
+: m_Buffer( nullptr )
+, m_Size(size) {
     ai_assert(m_Size != 0);
-
-    m_Buffer = malloc(m_Size);
+    m_Buffer = ::malloc(m_Size);
 }
 
 ZipFile::~ZipFile() {
-    free(m_Buffer);
+    ::free(m_Buffer);
     m_Buffer = NULL;
 }
 
 size_t ZipFile::Read(void* pvBuffer, size_t pSize, size_t pCount) {
     const size_t size = pSize * pCount;
-    assert(size <= m_Size);
+    ai_assert(size <= m_Size);
 
     std::memcpy(pvBuffer, m_Buffer, size);
 
     return size;
 }
 
-size_t ZipFile::Write(const void* /*pvBuffer*/, size_t /*pSize*/, size_t /*pCount*/) {
-    return 0;
+size_t ZipFile::Write(const void* pvBuffer, size_t size, size_t pCount ) {
+    const size_t size_to_write( size * pCount );
+    if ( 0 == size_to_write ) {
+        return 0U;
+    }
+    return 0U;
 }
 
 size_t ZipFile::FileSize() const {
@@ -256,55 +222,36 @@ void ZipFile::Flush() {
     // empty
 }
 
-
-class D3MFZipArchive : public IOSystem
-{
+class D3MFZipArchive : public IOSystem {
 public:
-
     static const unsigned int FileNameSize = 256;
 
-public:
-
     D3MFZipArchive(IOSystem* pIOHandler, const std::string & rFile);
-
     ~D3MFZipArchive();
-
     bool Exists(const char* pFile) const;
-
     char getOsSeparator() const;
-
     IOStream* Open(const char* pFile, const char* pMode = "rb");
-
     void Close(IOStream* pFile);
-
     bool isOpen() const;
-
     void getFileList(std::vector<std::string> &rFileList);
 
 private:
-
     bool mapArchive();
 
 private:
-
     unzFile m_ZipFileHandle;
-
     std::map<std::string, ZipFile*> m_ArchiveMap;
-
 };
 
-
 // ------------------------------------------------------------------------------------------------
 //  Constructor.
 D3MFZipArchive::D3MFZipArchive(IOSystem* pIOHandler, const std::string& rFile)
-    : m_ZipFileHandle(NULL), m_ArchiveMap()
-{
-    if (! rFile.empty())
-    {                
+: m_ZipFileHandle(NULL)
+, m_ArchiveMap() {
+    if (! rFile.empty()) {                
         zlib_filefunc_def mapping = IOSystem2Unzip::get(pIOHandler);            
 
         m_ZipFileHandle = unzOpen2(rFile.c_str(), &mapping);
-
         if(m_ZipFileHandle != NULL) {            
             mapArchive();
         }
@@ -379,6 +326,7 @@ IOStream *D3MFZipArchive::Open(const char* pFile, const char* /*pMode*/) {
 // ------------------------------------------------------------------------------------------------
 //  Close a filestream.
 void D3MFZipArchive::Close(IOStream *pFile) {
+    (void)(pFile);
     ai_assert(pFile != NULL);
 
     // We don't do anything in case the file would be opened again in the future
@@ -433,24 +381,12 @@ bool D3MFZipArchive::mapArchive() {
 
 // ------------------------------------------------------------------------------------------------
 
-struct OpcPackageRelationship
-{
-    std::string id;
-    std::string type;
-    std::string target;
-};
-
 typedef std::shared_ptr<OpcPackageRelationship> OpcPackageRelationshipPtr;
 
-class OpcPackageRelationshipReader
-{
+class OpcPackageRelationshipReader {
 public:
-
-    OpcPackageRelationshipReader(XmlReader* xmlReader)
-    {        
-
-        while(xmlReader->read())
-        {
+    OpcPackageRelationshipReader(XmlReader* xmlReader) {        
+        while(xmlReader->read()) {
             if(xmlReader->getNodeType() == irr::io::EXN_ELEMENT &&
                xmlReader->getNodeName() == XmlTag::RELS_RELATIONSHIP_CONTAINER)
             {
@@ -473,57 +409,68 @@ public:
         }
     }
 
-    void ParseAttributes(XmlReader*)
-    {
+    void ParseAttributes(XmlReader*) {
+        // empty
+    }
 
+    bool validateRels( OpcPackageRelationshipPtr &relPtr ) {
+        if ( relPtr->id.empty() || relPtr->type.empty() || relPtr->target.empty() ) {
+            return false;
+        }
+        return true;
     }
 
-    void ParseChildNode(XmlReader* xmlReader)
-    {        
+    void ParseChildNode(XmlReader* xmlReader) {        
         OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
 
-        relPtr->id = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_ID.c_str());
-        relPtr->type = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_TYPE.c_str());
-        relPtr->target = xmlReader->getAttributeValue(XmlTag::RELS_ATTRIB_TARGET.c_str());
-
-        m_relationShips.push_back(relPtr);
+        relPtr->id = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_ID.c_str());
+        relPtr->type = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TYPE.c_str());
+        relPtr->target = xmlReader->getAttributeValueSafe(XmlTag::RELS_ATTRIB_TARGET.c_str());
+        if ( validateRels( relPtr ) ) {
+            m_relationShips.push_back( relPtr );
+        }
     }
+
     std::vector<OpcPackageRelationshipPtr> m_relationShips;
 };
 // ------------------------------------------------------------------------------------------------
 
 D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
-    : m_RootStream(nullptr)
-{    
-    zipArchive.reset(new D3MF::D3MFZipArchive( pIOHandler, rFile ));    
-    if(!zipArchive->isOpen()) {
+: mRootStream(nullptr)
+, mZipArchive() {    
+    mZipArchive.reset( new D3MF::D3MFZipArchive( pIOHandler, rFile ) );    
+    if(!mZipArchive->isOpen()) {
         throw DeadlyImportError("Failed to open file " + rFile+ ".");
     }
 
     std::vector<std::string> fileList;
-    zipArchive->getFileList(fileList);
+    mZipArchive->getFileList(fileList);
 
-    for(auto& file: fileList){
+    for (auto& file: fileList) {
         if(file == D3MF::XmlTag::ROOT_RELATIONSHIPS_ARCHIVE) {
             //PkgRelationshipReader pkgRelReader(file, archive);
-            ai_assert(zipArchive->Exists(file.c_str()));
+            ai_assert(mZipArchive->Exists(file.c_str()));
 
-            IOStream *fileStream = zipArchive->Open(file.c_str());
+            IOStream *fileStream = mZipArchive->Open(file.c_str());
 
             ai_assert(fileStream != nullptr);
 
             std::string rootFile = ReadPackageRootRelationship(fileStream);
-            if(rootFile.size() > 0 && rootFile[0] == '/')
-                rootFile = rootFile.substr(1);
+            if ( rootFile.size() > 0 && rootFile[ 0 ] == '/' ) {
+                rootFile = rootFile.substr( 1 );
+                if ( rootFile[ 0 ] == '/' ) {
+                    // deal with zipbug
+                    rootFile = rootFile.substr( 1 );
+                }
+            }
 
             DefaultLogger::get()->debug(rootFile);
 
-            m_RootStream = zipArchive->Open(rootFile.c_str());
-
-            ai_assert(m_RootStream != nullptr);
-
-
-
+            mRootStream = mZipArchive->Open(rootFile.c_str());
+            ai_assert( mRootStream != nullptr );
+            if ( nullptr == mRootStream ) {
+                throw DeadlyExportError( "Cannot open rootfile in archive : " + rootFile );
+            }
 
         //    const size_t size = zipArchive->FileSize();
         //    m_Data.resize( size );
@@ -534,50 +481,40 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem* pIOHandler, const std::string& rFile)
         //        m_Data.clear();
         //        return false;
         //    }
-            zipArchive->Close( fileStream );
+            mZipArchive->Close( fileStream );
 
-        }
-        else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE)
-        {
+        } else if( file == D3MF::XmlTag::CONTENT_TYPES_ARCHIVE) {
 
         }
     }
 }
 
-D3MFOpcPackage::~D3MFOpcPackage()
-{
-
+D3MFOpcPackage::~D3MFOpcPackage() {
+    // empty
 }
 
-IOStream* D3MFOpcPackage::RootStream() const
-{
-    return m_RootStream;
+IOStream* D3MFOpcPackage::RootStream() const {
+    return mRootStream;
 }
 
-
-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<XmlReader> xml(irr::io::createIrrXMLReader(xmlStream.get()));
 
     OpcPackageRelationshipReader reader(xml.get());
 
-
     auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr& rel){
         return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
     });
 
-
-
     if(itr == reader.m_relationShips.end())
-        throw DeadlyImportError("Cannot find" + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
+        throw DeadlyImportError("Cannot find " + XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
 
     return (*itr)->target;
 }
 
-} //namespace D3MF
+} // Namespace D3MF
 
-}
+} // Namespace Assimp
 
 #endif //ASSIMP_BUILD_NO_3MF_IMPORTER

Some files were not shown because too many files changed in this diff